diff options
Diffstat (limited to 'doc')
338 files changed, 36790 insertions, 16895 deletions
diff --git a/doc/KNOWN_BUGS b/doc/KNOWN_BUGS index b30f5a52a5..44dd8812b7 100644 --- a/doc/KNOWN_BUGS +++ b/doc/KNOWN_BUGS @@ -1,4 +1,3 @@ PostgreSQL has a single combined bugs, missing features, and todo list simply called TODO, in this directory. A current copy is always available on our web site. - diff --git a/doc/MISSING_FEATURES b/doc/MISSING_FEATURES index b30f5a52a5..44dd8812b7 100644 --- a/doc/MISSING_FEATURES +++ b/doc/MISSING_FEATURES @@ -1,4 +1,3 @@ PostgreSQL has a single combined bugs, missing features, and todo list simply called TODO, in this directory. A current copy is always available on our web site. - diff --git a/doc/Makefile b/doc/Makefile index 32ef320b4d..2e5e09ef88 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -4,7 +4,7 @@ # # Copyright (c) 1994, Regents of the University of California # -# $PostgreSQL: pgsql/doc/Makefile,v 1.39 2009/08/09 22:47:59 petere Exp $ +# doc/Makefile # #---------------------------------------------------------------------------- @@ -12,5 +12,5 @@ subdir = doc top_builddir = .. include $(top_builddir)/src/Makefile.global -all distprep html man install installdirs uninstall clean distclean maintainer-clean: +all distprep html man install installdirs uninstall clean distclean maintainer-clean maintainer-check: $(MAKE) -C src $@ diff --git a/doc/bug.template b/doc/bug.template index d666433bef..f921883ecb 100644 --- a/doc/bug.template +++ b/doc/bug.template @@ -27,7 +27,7 @@ System Configuration: Operating System (example: Linux 2.4.18) : - PostgreSQL version (example: PostgreSQL 9.0beta3): PostgreSQL 9.0beta3 + PostgreSQL version (example: PostgreSQL 9.1beta2): PostgreSQL 9.1beta2 Compiler used (example: gcc 3.3.5) : @@ -40,7 +40,7 @@ Please enter a FULL description of your problem: Please describe a way to repeat the problem. Please try to provide a -concise reproducible example, if at all possible: +concise reproducible example, if at all possible: ---------------------------------------------------------------------- diff --git a/doc/src/Makefile b/doc/src/Makefile index 57da994476..b0d4f1f506 100644 --- a/doc/src/Makefile +++ b/doc/src/Makefile @@ -1,8 +1,8 @@ -# $PostgreSQL: pgsql/doc/src/Makefile,v 1.37 2009/08/09 22:47:59 petere Exp $ +# doc/src/Makefile subdir = doc/src top_builddir = ../.. include $(top_builddir)/src/Makefile.global -all distprep html man install installdirs uninstall clean distclean maintainer-clean: +all distprep html man install installdirs uninstall clean distclean maintainer-clean maintainer-check: $(MAKE) -C sgml $@ diff --git a/doc/src/sgml/.cvsignore b/doc/src/sgml/.cvsignore deleted file mode 100644 index ed986e3a76..0000000000 --- a/doc/src/sgml/.cvsignore +++ /dev/null @@ -1,6 +0,0 @@ -html -html-stamp -man1 -man3 -man7 -man-stamp diff --git a/doc/src/sgml/.gitignore b/doc/src/sgml/.gitignore new file mode 100644 index 0000000000..e1b84b490f --- /dev/null +++ b/doc/src/sgml/.gitignore @@ -0,0 +1,33 @@ +# Stuff shipped in tarballs +/html/ +/html-stamp +/man1/ +/man3/ +/man7/ +/man-stamp +# Other popular build targets +/HISTORY +/INSTALL +/regress_README +/postgres-US.pdf +/postgres-A4.pdf +/postgres.html +/postgres.txt +# GENERATED_SGML +/features-supported.sgml +/features-unsupported.sgml +/errcodes-table.sgml +/version.sgml +/bookindex.sgml +/HTML.index +# Assorted byproducts from building the above +/postgres.xml +/HISTORY.html +/INSTALL.html +/regress_README.html +/postgres-US.aux +/postgres-US.log +/postgres-US.out +/postgres-A4.aux +/postgres-A4.log +/postgres-A4.out diff --git a/doc/src/sgml/Makefile b/doc/src/sgml/Makefile index 5745362214..c5078a8080 100644 --- a/doc/src/sgml/Makefile +++ b/doc/src/sgml/Makefile @@ -2,13 +2,13 @@ # # PostgreSQL documentation makefile # -# $PostgreSQL: pgsql/doc/src/sgml/Makefile,v 1.148 2010/06/12 21:40:31 tgl Exp $ +# doc/src/sgml/Makefile # #---------------------------------------------------------------------------- # This makefile is for building and installing the documentation. # When a release tarball is created, the documentation files are -# prepared using the distprep target. In CVS-based trees these files +# prepared using the distprep target. In Git-based trees these files # don't exist, unless explicitly built, so we skip the installation in # that case. @@ -52,7 +52,7 @@ override XSLTPROCFLAGS += --stringparam pg.version '$(VERSION)' GENERATED_SGML = bookindex.sgml version.sgml \ - features-supported.sgml features-unsupported.sgml + features-supported.sgml features-unsupported.sgml errcodes-table.sgml ALLSGML := $(wildcard $(srcdir)/*.sgml $(srcdir)/ref/*.sgml) $(GENERATED_SGML) @@ -64,7 +64,7 @@ CATALOG = -c $(DOCBOOKSTYLE)/catalog endif # Enable some extra warnings -# -wfully-tagged needed to throw a warning on missing tags +# -wfully-tagged needed to throw a warning on missing tags # for older tool chains, 2007-08-31 # Note: try "make SPFLAGS=-wxml" to catch a lot of other dubious constructs, # in particular < and & that haven't been made into entities. It's far too @@ -126,8 +126,8 @@ bookindex.sgml: HTML.index # changes. version.sgml: $(top_srcdir)/configure { \ - echo "<!entity version \"$(VERSION)\">"; \ - echo "<!entity majorversion \"$(MAJORVERSION)\">"; \ + echo "<!ENTITY version \"$(VERSION)\">"; \ + echo "<!ENTITY majorversion \"$(MAJORVERSION)\">"; \ } > $@ features-supported.sgml: $(top_srcdir)/src/backend/catalog/sql_feature_packages.txt $(top_srcdir)/src/backend/catalog/sql_features.txt @@ -136,6 +136,8 @@ features-supported.sgml: $(top_srcdir)/src/backend/catalog/sql_feature_packages. features-unsupported.sgml: $(top_srcdir)/src/backend/catalog/sql_feature_packages.txt $(top_srcdir)/src/backend/catalog/sql_features.txt $(PERL) $(srcdir)/mk_feature_tables.pl NO $^ > $@ +errcodes-table.sgml: $(top_srcdir)/src/backend/utils/errcodes.txt generate-errcodes-table.pl + $(PERL) $(srcdir)/generate-errcodes-table.pl $< > $@ ## ## Print @@ -218,9 +220,9 @@ HISTORY.html: generate_history.pl $(wildcard $(srcdir)/release*.sgml) rm tempfile_HISTORY.sgml regress_README.html: regress.sgml - ( echo '<!doctype chapter PUBLIC "-//OASIS//DTD DocBook V4.2//EN" ['; \ - echo '<!entity % standalone-ignore "IGNORE">'; \ - echo '<!entity % standalone-include "INCLUDE"> ]>'; \ + ( echo '<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook V4.2//EN" ['; \ + echo '<!ENTITY % standalone-ignore "IGNORE">'; \ + echo '<!ENTITY % standalone-include "INCLUDE"> ]>'; \ cat $< ) >tempfile_regress_README.sgml $(JADE.text) -V nochunks tempfile_regress_README.sgml > $@ rm tempfile_regress_README.sgml @@ -277,7 +279,7 @@ MAKEINFO = makeinfo ## # Quick syntax check without style processing -check: postgres.sgml $(ALMOSTALLSGML) check-tabs +check maintainer-check: postgres.sgml $(ALMOSTALLSGML) check-tabs $(NSGMLS) $(SPFLAGS) $(SGMLINCLUDE) -s $< diff --git a/doc/src/sgml/README.links b/doc/src/sgml/README.links index 1991c20b23..2668b00d7f 100644 --- a/doc/src/sgml/README.links +++ b/doc/src/sgml/README.links @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/README.links,v 1.3 2009/01/10 16:58:39 momjian Exp $ --> +<!-- doc/src/sgml/README.links --> Linking within SGML documents can be confusing, so here is a summary: @@ -7,8 +7,8 @@ Intra-document Linking ---------------------- <xref> - use to get link text from the title of the target link; has no - close tag + use to get chapter/section # from the title of the target + link, or xreflabel if defined at the target; has no close tag http://www.oasis-open.org/docbook/documentation/reference/html/xref.html <link> @@ -28,7 +28,8 @@ External Linking <ulink> like <link>, but uses a URL (not a document target); requires - </ulink>; if no text is specified, the URL appears as the link text + </ulink>; if no text is specified, the URL appears as the link + text http://www.oasis-open.org/docbook/documentation/reference/html/ulink.html url= @@ -40,4 +41,5 @@ Guidelines o If you want to supply text, use <link>, else <xref> o Do not use text with <ulink> so the URL appears in printed output -o You can supply text at the target location with 'xreflabel' +o Specific nouns like GUC variables, SQL commands, and contrib modules + usually have xreflabels diff --git a/doc/src/sgml/acronyms.sgml b/doc/src/sgml/acronyms.sgml index 8bcad311d2..8f6752f05d 100644 --- a/doc/src/sgml/acronyms.sgml +++ b/doc/src/sgml/acronyms.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/acronyms.sgml,v 1.8 2010/03/17 17:12:31 petere Exp $ --> +<!-- doc/src/sgml/acronyms.sgml --> <appendix id="acronyms"> <title>Acronyms</title> @@ -99,21 +99,19 @@ </varlistentry> <varlistentry> - <term><acronym>CVE</acronym></term> + <term><acronym>CTE</acronym></term> <listitem> <para> - <ulink url="http://cve.mitre.org/">Common Vulnerabilities and Exposures</ulink> + <link linkend="queries-with">Common Table Expression</link> </para> </listitem> </varlistentry> <varlistentry> - <term><acronym>CVS</acronym></term> + <term><acronym>CVE</acronym></term> <listitem> <para> - <ulink - url="http://en.wikipedia.org/wiki/Concurrent_Versions_System">Concurrent - Versions System</ulink> + <ulink url="http://cve.mitre.org/">Common Vulnerabilities and Exposures</ulink> </para> </listitem> </varlistentry> @@ -249,6 +247,16 @@ </varlistentry> <varlistentry> + <term><acronym>Git</acronym></term> + <listitem> + <para> + <ulink + url="http://en.wikipedia.org/wiki/Git_(software)">Git</ulink> + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><acronym>GMT</acronym></term> <listitem> <para> @@ -292,7 +300,7 @@ <listitem> <para> <ulink - url="http://anoncvs.postgresql.org/cvsweb.cgi/pgsql/src/backend/access/heap/README.HOT">Heap-Only + url="http://git.postgresql.org/gitweb?p=postgresql.git;a=blob;f=src/backend/access/heap/README.HOT;hb=HEAD">Heap-Only Tuples</ulink> </para> </listitem> @@ -477,7 +485,7 @@ <term><acronym>PGXS</acronym></term> <listitem> <para> - <link linkend="xfunc-c-pgxs"><productname>PostgreSQL</> Extension System</link> + <link linkend="extend-pgxs"><productname>PostgreSQL</> Extension System</link> </para> </listitem> </varlistentry> @@ -505,7 +513,7 @@ <term><acronym>PL</acronym></term> <listitem> <para> - <link linkend="server-programming">Programming Languages (server-side)</link> + <link linkend="server-programming">Procedural Languages (server-side)</link> </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/adminpack.sgml b/doc/src/sgml/adminpack.sgml index b097000281..9b72f34ead 100644 --- a/doc/src/sgml/adminpack.sgml +++ b/doc/src/sgml/adminpack.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/adminpack.sgml,v 1.3 2007/12/06 04:12:09 tgl Exp $ --> +<!-- doc/src/sgml/adminpack.sgml --> -<sect1 id="adminpack"> +<sect1 id="adminpack" xreflabel="adminpack"> <title>adminpack</title> <indexterm zone="adminpack"> @@ -15,7 +15,7 @@ </para> <sect2> - <title>Functions implemented</title> + <title>Functions Implemented</title> <para> The functions implemented by <filename>adminpack</> can only be run by a diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml index 38045b51fd..218988e0af 100644 --- a/doc/src/sgml/advanced.sgml +++ b/doc/src/sgml/advanced.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/advanced.sgml,v 1.61 2010/07/03 02:57:46 rhaas Exp $ --> +<!-- doc/src/sgml/advanced.sgml --> <chapter id="tutorial-advanced"> <title>Advanced Features</title> @@ -371,7 +371,7 @@ SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) FROM emps <para> A window function call always contains an <literal>OVER</> clause - following the window function's name and argument(s). This is what + directly following the window function's name and argument(s). This is what syntactically distinguishes it from a regular function or aggregate function. The <literal>OVER</> clause determines exactly how the rows of the query are split up for processing by the window function. @@ -383,10 +383,10 @@ SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) FROM emps </para> <para> - Although <function>avg</> will produce the same result no matter - what order it processes the partition's rows in, this is not true of all - window functions. When needed, you can control that order using - <literal>ORDER BY</> within <literal>OVER</>. Here is an example: + You can also control the order in which rows are processed by + window functions using <literal>ORDER BY</> within <literal>OVER</>. + (The window <literal>ORDER BY</> does not even have to match the + order in which the rows are output.) Here is an example: <programlisting> SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY salary DESC) FROM empsalary; @@ -533,7 +533,7 @@ WHERE pos < 3; </programlisting> The above query only shows the rows from the inner query having - <literal>rank</> less than <literal>3</>. + <literal>rank</> less than 3. </para> <para> diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml index 888f6c2a50..c1d9043f7d 100644 --- a/doc/src/sgml/arch-dev.sgml +++ b/doc/src/sgml/arch-dev.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/arch-dev.sgml,v 2.34 2010/04/03 07:22:52 petere Exp $ --> +<!-- doc/src/sgml/arch-dev.sgml --> <chapter id="overview"> <title>Overview of PostgreSQL Internals</title> @@ -463,7 +463,7 @@ needed, plus any auxiliary steps needed, such as sort nodes or aggregate-function calculation nodes. Most of these plan node types have the additional ability to do <firstterm>selection</> - (discarding rows that do not meet a specified boolean condition) + (discarding rows that do not meet a specified Boolean condition) and <firstterm>projection</> (computation of a derived column set based on given column values, that is, evaluation of scalar expressions where needed). One of the responsibilities of the diff --git a/doc/src/sgml/array.sgml b/doc/src/sgml/array.sgml index bfc373ac05..3508ba3e3c 100644 --- a/doc/src/sgml/array.sgml +++ b/doc/src/sgml/array.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/array.sgml,v 1.70 2009/06/17 21:58:48 tgl Exp $ --> +<!-- doc/src/sgml/array.sgml --> <sect1 id="arrays"> <title>Arrays</title> @@ -259,7 +259,7 @@ SELECT schedule[1:2][1:1] FROM sal_emp WHERE name = 'Bill'; If any dimension is written as a slice, i.e., contains a colon, then all dimensions are treated as slices. Any dimension that has only a single - number (no colon) is treated as being from <literal>1</> + number (no colon) is treated as being from 1 to the number specified. For example, <literal>[2]</> is treated as <literal>[1:2]</>, as in this example: @@ -369,7 +369,7 @@ UPDATE sal_emp SET pay_by_quarter = ARRAY[25000,25000,27000,27000] <programlisting> UPDATE sal_emp SET pay_by_quarter[4] = 15000 WHERE name = 'Bill'; -</programListing> +</programlisting> or updated in a slice: @@ -646,7 +646,7 @@ SELECT f1[1][-2][3] AS e1, f1[1][-1][5] AS e2 If the value written for an element is <literal>NULL</> (in any case variant), the element is taken to be NULL. The presence of any quotes or backslashes disables this and allows the literal string value - <quote>NULL</> to be entered. Also, for backwards compatibility with + <quote>NULL</> to be entered. Also, for backward compatibility with pre-8.2 versions of <productname>PostgreSQL</>, the <xref linkend="guc-array-nulls"> configuration parameter can be turned <literal>off</> to suppress recognition of <literal>NULL</> as a NULL. diff --git a/doc/src/sgml/auth-delay.sgml b/doc/src/sgml/auth-delay.sgml new file mode 100644 index 0000000000..b91a7ecda7 --- /dev/null +++ b/doc/src/sgml/auth-delay.sgml @@ -0,0 +1,67 @@ +<!-- doc/src/sgml/auth-delay.sgml --> + +<sect1 id="auth-delay" xreflabel="auth_delay"> + <title>auth_delay</title> + + <indexterm zone="auth-delay"> + <primary>auth_delay</primary> + </indexterm> + + <para> + <filename>auth_delay</filename> causes the server to pause briefly before + reporting authentication failure, to make brute-force attacks on database + passwords more difficult. Note that it does nothing to prevent + denial-of-service attacks, and may even exacerbate them, since processes + that are waiting before reporting authentication failure will still consume + connection slots. + </para> + + <para> + In order to function, this module must be loaded via + <xref linkend="guc-shared-preload-libraries"> in <filename>postgresql.conf</>. + </para> + + <sect2> + <title>Configuration Parameters</title> + + <variablelist> + <varlistentry> + <term> + <varname>auth_delay.milliseconds</varname> (<type>int</type>) + </term> + <indexterm> + <primary><varname>auth_delay.milliseconds</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + The number of milliseconds to wait before reporting an authentication + failure. The default is 0. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + In order to set these parameters in your <filename>postgresql.conf</> file, + you will need to add <literal>auth_delay</> to + <xref linkend="guc-custom-variable-classes">. Typical usage might be: + </para> + +<programlisting> +# postgresql.conf +shared_preload_libraries = 'auth_delay' + +custom_variable_classes = 'auth_delay' +auth_delay.milliseconds = '500' +</programlisting> + </sect2> + + <sect2> + <title>Author</title> + + <para> + KaiGai Kohei <email>kaigai@ak.jp.nec.com</email> + </para> + </sect2> + +</sect1> diff --git a/doc/src/sgml/auto-explain.sgml b/doc/src/sgml/auto-explain.sgml index 56340b11de..b16f9064ff 100644 --- a/doc/src/sgml/auto-explain.sgml +++ b/doc/src/sgml/auto-explain.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/auto-explain.sgml,v 1.8 2010/04/03 07:22:52 petere Exp $ --> +<!-- doc/src/sgml/auto-explain.sgml --> -<sect1 id="auto-explain"> +<sect1 id="auto-explain" xreflabel="auto_explain"> <title>auto_explain</title> <indexterm zone="auto-explain"> @@ -19,9 +19,9 @@ The module provides no SQL-accessible functions. To use it, simply load it into the server. You can load it into an individual session: - <programlisting> +<programlisting> LOAD 'auto_explain'; - </programlisting> +</programlisting> (You must be superuser to do that.) More typical usage is to preload it into all sessions by including <literal>auto_explain</> in @@ -32,7 +32,7 @@ LOAD 'auto_explain'; </para> <sect2> - <title>Configuration parameters</title> + <title>Configuration Parameters</title> <para> There are several configuration parameters that control the behavior of @@ -112,8 +112,8 @@ LOAD 'auto_explain'; <listitem> <para> <varname>auto_explain.log_buffers</varname> causes <command>EXPLAIN - (ANALYZE, BUFFERS)</> output, rather than just <command>EXPLAIN</> - output, to be printed when an execution plan is logged. This parameter is + (ANALYZE, BUFFERS)</> output, rather than just <command>EXPLAIN</> + output, to be printed when an execution plan is logged. This parameter is off by default. Only superusers can change this setting. This parameter has no effect unless <varname>auto_explain.log_analyze</> parameter is set. @@ -163,45 +163,44 @@ LOAD 'auto_explain'; <xref linkend="guc-custom-variable-classes">. Typical usage might be: </para> - <programlisting> +<programlisting> # postgresql.conf shared_preload_libraries = 'auto_explain' custom_variable_classes = 'auto_explain' auto_explain.log_min_duration = '3s' - </programlisting> +</programlisting> </sect2> <sect2> <title>Example</title> - <programlisting> - postgres=# LOAD 'auto_explain'; - postgres=# SET auto_explain.log_min_duration = 0; - postgres=# SELECT count(*) - FROM pg_class, pg_index - WHERE oid = indrelid AND indisunique; - </programlisting> +<programlisting> +postgres=# LOAD 'auto_explain'; +postgres=# SET auto_explain.log_min_duration = 0; +postgres=# SELECT count(*) + FROM pg_class, pg_index + WHERE oid = indrelid AND indisunique; +</programlisting> <para> This might produce log output such as: </para> - <programlisting><![CDATA[ - LOG: duration: 3.651 ms plan: - Query Text: SELECT count(*) - FROM pg_class, pg_index - WHERE oid = indrelid AND indisunique; - Aggregate (cost=16.79..16.80 rows=1 width=0) (actual time=3.626..3.627 rows=1 loops=1) - -> Hash Join (cost=4.17..16.55 rows=92 width=0) (actual time=3.349..3.594 rows=92 loops=1) - Hash Cond: (pg_class.oid = pg_index.indrelid) - -> Seq Scan on pg_class (cost=0.00..9.55 rows=255 width=4) (actual time=0.016..0.140 rows=255 loops=1) - -> Hash (cost=3.02..3.02 rows=92 width=4) (actual time=3.238..3.238 rows=92 loops=1) - Buckets: 1024 Batches: 1 Memory Usage: 4kB - -> Seq Scan on pg_index (cost=0.00..3.02 rows=92 width=4) (actual time=0.008..3.187 rows=92 loops=1) - Filter: indisunique -]]> - </programlisting> +<screen><![CDATA[ +LOG: duration: 3.651 ms plan: + Query Text: SELECT count(*) + FROM pg_class, pg_index + WHERE oid = indrelid AND indisunique; + Aggregate (cost=16.79..16.80 rows=1 width=0) (actual time=3.626..3.627 rows=1 loops=1) + -> Hash Join (cost=4.17..16.55 rows=92 width=0) (actual time=3.349..3.594 rows=92 loops=1) + Hash Cond: (pg_class.oid = pg_index.indrelid) + -> Seq Scan on pg_class (cost=0.00..9.55 rows=255 width=4) (actual time=0.016..0.140 rows=255 loops=1) + -> Hash (cost=3.02..3.02 rows=92 width=4) (actual time=3.238..3.238 rows=92 loops=1) + Buckets: 1024 Batches: 1 Memory Usage: 4kB + -> Seq Scan on pg_index (cost=0.00..3.02 rows=92 width=4) (actual time=0.008..3.187 rows=92 loops=1) + Filter: indisunique +]]></screen> </sect2> <sect2> diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml index 2f271efc4c..03180cf108 100644 --- a/doc/src/sgml/backup.sgml +++ b/doc/src/sgml/backup.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.156 2010/06/07 02:01:08 itagaki Exp $ --> +<!-- doc/src/sgml/backup.sgml --> <chapter id="backup"> <title>Backup and Restore</title> @@ -20,7 +20,8 @@ <listitem><para>File system level backup</para></listitem> <listitem><para>Continuous archiving</para></listitem> </itemizedlist> - Each has its own strengths and weaknesses; each is discussed in turn below. + Each has its own strengths and weaknesses; each is discussed in turn + in the following sections. </para> <sect1 id="backup-dump"> @@ -74,6 +75,16 @@ pg_dump <replaceable class="parameter">dbname</replaceable> > <replaceable cl </para> <para> + An important advantage of <application>pg_dump</> over the other backup + methods described later is that <application>pg_dump</>'s output can + generally be re-loaded into newer versions of <productname>PostgreSQL</>, + whereas file-level backups and continuous archiving are both extremely + server-version-specific. <application>pg_dump</> is also the only method + that will work when transferring a database to a different machine + architecture, such as going from a 32-bit to a 64-bit server. + </para> + + <para> Dumps created by <application>pg_dump</> are internally consistent, meaning, the dump represents a snapshot of the database at the time <application>pg_dump</> began running. <application>pg_dump</> does not @@ -92,7 +103,7 @@ pg_dump <replaceable class="parameter">dbname</replaceable> > <replaceable cl </important> <sect2 id="backup-dump-restore"> - <title>Restoring the dump</title> + <title>Restoring the Dump</title> <para> The text files created by <application>pg_dump</> are intended to @@ -214,7 +225,7 @@ psql -f <replaceable class="parameter">infile</replaceable> postgres </sect2> <sect2 id="backup-dump-large"> - <title>Handling large databases</title> + <title>Handling Large Databases</title> <para> Some operating systems have maximum file size limits that cause @@ -372,6 +383,8 @@ tar -cf backup.tar /usr/local/pgsql/data on the backed-up data, it will think the previous server instance crashed and will replay the WAL log. This is not a problem; just be aware of it (and be sure to include the WAL files in your backup). + You can perform a <command>CHECKPOINT</command> before taking the + snapshot to reduce recovery time. </para> <para> @@ -388,7 +401,7 @@ tar -cf backup.tar /usr/local/pgsql/data <para> If simultaneous snapshots are not possible, one option is to shut down the database server long enough to establish all the frozen snapshots. - Another option is perform a continuous archiving base backup (<xref + Another option is to perform a continuous archiving base backup (<xref linkend="backup-base-backup">) because such backups are immune to file system changes during the backup. This requires enabling continuous archiving just during the backup process; restore is done using @@ -415,7 +428,7 @@ tar -cf backup.tar /usr/local/pgsql/data </sect1> <sect1 id="continuous-archiving"> - <title>Continuous Archiving and Point-In-Time Recovery (PITR)</title> + <title>Continuous Archiving and Point-in-Time Recovery (PITR)</title> <indexterm zone="backup"> <primary>continuous archiving</primary> @@ -490,7 +503,7 @@ tar -cf backup.tar /usr/local/pgsql/data <application>pg_dumpall</application> do not produce file-system-level backups and cannot be used as part of a continuous-archiving solution. Such dumps are <emphasis>logical</> and do not contain enough - information to used by WAL reply. + information to be used by WAL replay. </para> </note> @@ -514,7 +527,7 @@ tar -cf backup.tar /usr/local/pgsql/data </para> <sect2 id="backup-archiving-wal"> - <title>Setting up WAL archiving</title> + <title>Setting Up WAL Archiving</title> <para> In an abstract sense, a running <productname>PostgreSQL</> system @@ -566,7 +579,8 @@ tar -cf backup.tar /usr/local/pgsql/data character in the command. The simplest useful command is something like: <programlisting> -archive_command = 'cp -i %p /mnt/server/archivedir/%f </dev/null' +archive_command = 'cp -i %p /mnt/server/archivedir/%f </dev/null' # Unix +archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"' # Windows </programlisting> which will copy archivable WAL segments to the directory <filename>/mnt/server/archivedir</>. (This is an example, not a @@ -799,6 +813,17 @@ SELECT pg_stop_backup(); </para> <para> + You can also use the <xref linkend="app-pgbasebackup"> tool to take + the backup, instead of manually copying the files. This tool will do + the equivalent of <function>pg_start_backup()</>, copy and + <function>pg_stop_backup()</> steps automatically, and transfers the + backup over a regular <productname>PostgreSQL</productname> connection + using the replication protocol, instead of requiring file system level + access. <command>pg_basebackup</command> does not interfere with file system level backups + taken using <function>pg_start_backup()</>/<function>pg_stop_backup()</>. + </para> + + <para> Some file system backup tools emit warnings or errors if the files they are trying to copy change while the copy proceeds. When taking a base backup of an active database, this situation is normal @@ -810,8 +835,8 @@ SELECT pg_stop_backup(); GNU <application>tar</> return an error code indistinguishable from a fatal error if a file was truncated while <application>tar</> was copying it. Fortunately, GNU <application>tar</> versions 1.16 and - later exit with <literal>1</> if a file was changed during the backup, - and <literal>2</> for other errors. + later exit with 1 if a file was changed during the backup, + and 2 for other errors. </para> <para> @@ -910,7 +935,7 @@ SELECT pg_stop_backup(); </sect2> <sect2 id="backup-pitr-recovery"> - <title>Recovering using a Continuous Archive Backup</title> + <title>Recovering Using a Continuous Archive Backup</title> <para> Okay, the worst has happened and you need to recover from your backup. @@ -1061,9 +1086,10 @@ restore_command = 'cp /mnt/server/archivedir/%f %p' the junior DBA dropped your main transaction table), just specify the required stopping point in <filename>recovery.conf</>. You can specify the stop point, known as the <quote>recovery target</>, either by - date/time or by completion of a specific transaction ID. As of this - writing only the date/time option is very usable, since there are no tools - to help you identify with any accuracy which transaction ID to use. + date/time, named restore point or by completion of a specific transaction + ID. As of this writing only the date/time and named restore point options + are very usable, since there are no tools to help you identify with any + accuracy which transaction ID to use. </para> <note> @@ -1169,7 +1195,7 @@ restore_command = 'cp /mnt/server/archivedir/%f %p' </para> <sect3 id="backup-standalone"> - <title>Standalone hot backups</title> + <title>Standalone Hot Backups</title> <para> It is possible to use <productname>PostgreSQL</>'s backup facilities to @@ -1232,7 +1258,7 @@ restore_command = 'gunzip < /mnt/server/archivedir/%f | pg_decompresslog - %p </sect3> <sect3 id="backup-scripts"> - <title><varname>archive_command</varname> scripts</title> + <title><varname>archive_command</varname> Scripts</title> <para> Many people choose to use scripts to define their @@ -1352,190 +1378,4 @@ archive_command = 'local_backup_script.sh' </sect2> </sect1> - <sect1 id="migration"> - <title>Migration Between Releases</title> - - <indexterm zone="migration"> - <primary>upgrading</primary> - </indexterm> - - <indexterm zone="migration"> - <primary>version</primary> - <secondary>compatibility</secondary> - </indexterm> - - <para> - This section discusses how to migrate your database data from one - <productname>PostgreSQL</> release to a newer one. - The software installation procedure <foreignphrase>per se</> is not the - subject of this section; those details are in <xref linkend="installation">. - </para> - - <para> - <productname>PostgreSQL</> major versions are represented by the - first two digit groups of the version number, e.g. 8.4. - <productname>PostgreSQL</> minor versions are represented by the - the third group of version digits, i.e., 8.4.2 is the second minor - release of 8.4. Minor releases never change the internal storage - format and are always compatible with earlier and later minor - releases of the same major version number, i.e. 8.4.2 is compatible - with 8.4, 8.4.1 and 8.4.6. To update between compatible versions, - you simply replace the executables while the server is down and - restart the server. The data directory remains unchanged — - minor upgrades are that simple. - </para> - - <para> - For <emphasis>major</> releases of <productname>PostgreSQL</>, the - internal data storage format is subject to change. When migrating - data from one major version of <productname>PostgreSQL</> to another, - you need to back up your data and restore it on the new server. - This must be done using <application>pg_dump</>; file system level - backup methods will not work. There are checks in place that prevent - you from using a data directory with an incompatible version of - <productname>PostgreSQL</productname>, so no great harm can be done - by trying to start the wrong server version on a data directory. - </para> - - <para> - It is recommended that you use the <application>pg_dump</> and - <application>pg_dumpall</> programs from the newer version of - <productname>PostgreSQL</>, to take advantage of enhancements - that might have been made in these programs. Current releases of the - dump programs can read data from any server version back to 7.0. - </para> - - <para> - The least downtime can be achieved by installing the new server in - a different directory and running both the old and the new servers - in parallel, on different ports. Then you can use something like: - -<programlisting> -pg_dumpall -p 5432 | psql -d postgres -p 6543 -</programlisting> - - to transfer your data. Or use an intermediate file if you wish. - Then you can shut down the old server and start the new server using - the port the old one was running on. You should make sure that the - old database is not updated after you begin to run - <application>pg_dumpall</>, otherwise you will lose that data. See <xref - linkend="client-authentication"> for information on how to prohibit - access. - </para> - - <para> - It is also possible to use replication methods, such as - <productname>Slony</>, to create a standby server with the updated version of - <productname>PostgreSQL</>. The standby can be on the same computer or - a different computer. Once it has synced up with the master server - (running the older version of <productname>PostgreSQL</>), you can - switch masters and make the standby the master and shut down the older - database instance. Such a switch-over results in only several seconds - of downtime for an upgrade. - </para> - - <para> - If you cannot or do not want to run two servers in parallel, you can - do the backup step before installing the new version, bring down - the old server, move the old version out of the way, install the new - version, start the new server, and restore the data. For example: - -<programlisting> -pg_dumpall > backup -pg_ctl stop -mv /usr/local/pgsql /usr/local/pgsql.old -# Rename any tablespace directories as well -cd ~/postgresql-&version; -gmake install -initdb -D /usr/local/pgsql/data -postgres -D /usr/local/pgsql/data -psql -f backup postgres -</programlisting> - - See <xref linkend="runtime"> about ways to start and stop the - server and other details. The installation instructions will advise - you of strategic places to perform these steps. - </para> - - <note> - <para> - When you <quote>move the old installation out of the way</quote> - it might no longer be perfectly usable. Some of the executable programs - contain absolute paths to various installed programs and data files. - This is usually not a big problem, but if you plan on using two - installations in parallel for a while you should assign them - different installation directories at build time. (This problem - is rectified in <productname>PostgreSQL</> version 8.0 and later, so long - as you move all subdirectories containing installed files together; - for example if <filename>/usr/local/postgres/bin/</> goes to - <filename>/usr/local/postgres.old/bin/</>, then - <filename>/usr/local/postgres/share/</> must go to - <filename>/usr/local/postgres.old/share/</>. In pre-8.0 releases - moving an installation like this will not work.) - </para> - </note> - - <para> - In practice you probably want to test your client applications on the - new version before switching over completely. This is another reason - for setting up concurrent installations of old and new versions. When - testing a <productname>PostgreSQL</> major upgrade, consider the - following categories of possible changes: - </para> - - <variablelist> - - <varlistentry> - <term>Administration</term> - <listitem> - <para> - The capabilities available for administrators to monitor and control - the server often change and improve in each major release. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>SQL</term> - <listitem> - <para> - Typically this includes new SQL command capabilities and not changes - in behavior, unless specifically mentioned in the release notes. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Library API</term> - <listitem> - <para> - Typically libraries like <application>libpq</> only add new - functionality, again unless mentioned in the release notes. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>System Catalogs</term> - <listitem> - <para> - System catalog changes usually only affect database management tools. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Server C-language API</term> - <listitem> - <para> - This involved changes in the backend function API, which is written - in the C programming language. Such changes effect code that - references backend functions deep inside the server. - </para> - </listitem> - </varlistentry> - - </variablelist> - - </sect1> </chapter> diff --git a/doc/src/sgml/biblio.sgml b/doc/src/sgml/biblio.sgml index 859b888a5c..e2cd69d278 100644 --- a/doc/src/sgml/biblio.sgml +++ b/doc/src/sgml/biblio.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/biblio.sgml,v 1.28 2010/03/17 17:12:31 petere Exp $ --> +<!-- doc/src/sgml/biblio.sgml --> <bibliography id="biblio"> <title>Bibliography</title> @@ -164,7 +164,7 @@ </bibliodiv> <bibliodiv> - <title>PostgreSQL-Specific Documentation</title> + <title>PostgreSQL-specific Documentation</title> <para>This section is for related documentation.</para> <biblioentry id="SIM98"> @@ -257,7 +257,7 @@ ssimkovi@ag.or.at <bibliodiv> <title>Proceedings and Articles</title> <para>This section is for articles and newsletters.</para> - + <biblioentry id="OLSON93"> <title>Partial indexing in POSTGRES: research project</title> <titleabbrev>Olson, 1993</titleabbrev> @@ -328,7 +328,7 @@ ssimkovi@ag.or.at <biblioset relation="article"> <title>Generalized Partial Indexes <ulink url="http://citeseer.ist.psu.edu/seshadri95generalized.html">(cached version) -<!-- +<!-- Original URL: http://citeseer.ist.psu.edu/seshadri95generalized.html --> </ulink> diff --git a/doc/src/sgml/bki.sgml b/doc/src/sgml/bki.sgml index d747f9244e..aaf500ad08 100644 --- a/doc/src/sgml/bki.sgml +++ b/doc/src/sgml/bki.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/bki.sgml,v 1.23 2010/01/05 01:06:55 tgl Exp $ --> +<!-- doc/src/sgml/bki.sgml --> <chapter id="bki"> <title><acronym>BKI</acronym> Backend Interface</title> @@ -122,7 +122,7 @@ The table is created as shared if <literal>shared_relation</> is specified. It will have OIDs unless <literal>without_oids</> is specified. - The table's rowtype OID (<structname>pg_type</> OID) can optionally + The table's row type OID (<structname>pg_type</> OID) can optionally be specified via the <literal>rowtype_oid</> clause; if not specified, an OID is automatically generated for it. (The <literal>rowtype_oid</> clause is useless if <literal>bootstrap</> is specified, but it can be diff --git a/doc/src/sgml/btree-gin.sgml b/doc/src/sgml/btree-gin.sgml index d2142028eb..42b9e97b72 100644 --- a/doc/src/sgml/btree-gin.sgml +++ b/doc/src/sgml/btree-gin.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/btree-gin.sgml,v 1.1 2009/03/25 23:20:01 tgl Exp $ --> +<!-- doc/src/sgml/btree-gin.sgml --> -<sect1 id="btree-gin"> +<sect1 id="btree-gin" xreflabel="btree_gin"> <title>btree_gin</title> <indexterm zone="btree-gin"> @@ -9,7 +9,7 @@ <para> <filename>btree_gin</> provides sample GIN operator classes that - implement B-Tree equivalent behavior for the data types + implement B-tree equivalent behavior for the data types <type>int2</>, <type>int4</>, <type>int8</>, <type>float4</>, <type>float8</>, <type>timestamp with time zone</>, <type>timestamp without time zone</>, <type>time with time zone</>, @@ -21,17 +21,17 @@ <para> In general, these operator classes will not outperform the equivalent - standard btree index methods, and they lack one major feature of the - standard btree code: the ability to enforce uniqueness. However, + standard B-tree index methods, and they lack one major feature of the + standard B-tree code: the ability to enforce uniqueness. However, they are useful for GIN testing and as a base for developing other GIN operator classes. Also, for queries that test both a GIN-indexable - column and a btree-indexable column, it might be more efficient to create - a multi-column GIN index that uses one of these opclasses than to create + column and a B-tree-indexable column, it might be more efficient to create + a multicolumn GIN index that uses one of these operator classes than to create two separate indexes that would have to be combined via bitmap ANDing. </para> <sect2> - <title>Example usage</title> + <title>Example Usage</title> <programlisting> CREATE TABLE test (a int4); diff --git a/doc/src/sgml/btree-gist.sgml b/doc/src/sgml/btree-gist.sgml index 8264d5a219..2275a997ba 100644 --- a/doc/src/sgml/btree-gist.sgml +++ b/doc/src/sgml/btree-gist.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/btree-gist.sgml,v 1.5 2010/03/17 17:12:31 petere Exp $ --> +<!-- doc/src/sgml/btree-gist.sgml --> -<sect1 id="btree-gist"> +<sect1 id="btree-gist" xreflabel="btree_gist"> <title>btree_gist</title> <indexterm zone="btree-gist"> @@ -8,8 +8,8 @@ </indexterm> <para> - <filename>btree_gist</> provides sample GiST operator classes that - implement B-Tree equivalent behavior for the data types + <filename>btree_gist</> provides GiST index operator classes that + implement B-tree equivalent behavior for the data types <type>int2</>, <type>int4</>, <type>int8</>, <type>float4</>, <type>float8</>, <type>numeric</>, <type>timestamp with time zone</>, <type>timestamp without time zone</>, <type>time with time zone</>, @@ -21,14 +21,42 @@ <para> In general, these operator classes will not outperform the equivalent - standard btree index methods, and they lack one major feature of the - standard btree code: the ability to enforce uniqueness. However, - they are useful for GiST testing and as a base for developing other - GiST operator classes. + standard B-tree index methods, and they lack one major feature of the + standard B-tree code: the ability to enforce uniqueness. However, + they provide some other features that are not available with a B-tree + index, as described below. Also, these operator classes are useful + when a multicolumn GiST index is needed, wherein some of the columns + are of data types that are only indexable with GiST but other columns + are just simple data types. Lastly, these operator classes are useful for + GiST testing and as a base for developing other GiST operator classes. + </para> + + <para> + In addition to the typical B-tree search operators, <filename>btree_gist</> + also provides index support for <literal><></literal> (<quote>not + equals</quote>). This may be useful in combination with an + <link linkend="SQL-CREATETABLE-EXCLUDE">exclusion constraint</link>, + as described below. + </para> + + <para> + Also, for data types for which there is a natural distance metric, + <filename>btree_gist</> defines a distance operator <literal><-></>, + and provides GiST index support for nearest-neighbor searches using + this operator. Distance operators are provided for + <type>int2</>, <type>int4</>, <type>int8</>, <type>float4</>, + <type>float8</>, <type>timestamp with time zone</>, + <type>timestamp without time zone</>, + <type>time without time zone</>, <type>date</>, <type>interval</>, + <type>oid</>, and <type>money</>. </para> <sect2> - <title>Example usage</title> + <title>Example Usage</title> + + <para> + Simple example using <literal>btree_gist</literal> instead of <literal>btree</literal>: + </para> <programlisting> CREATE TABLE test (a int4); @@ -36,6 +64,32 @@ CREATE TABLE test (a int4); CREATE INDEX testidx ON test USING gist (a); -- query SELECT * FROM test WHERE a < 10; +-- nearest-neighbor search: find the ten entries closest to "42" +SELECT *, a <-> 42 AS dist FROM test ORDER BY a <-> 42 LIMIT 10; +</programlisting> + + <para> + Use an <link linkend="SQL-CREATETABLE-EXCLUDE">exclusion + constraint</link> to enforce the rule that a cage at a zoo + can contain only one kind of animal: + </para> + +<programlisting> +=> CREATE TABLE zoo ( + cage INTEGER, + animal TEXT, + EXCLUDE USING gist (cage WITH =, animal WITH <>) +); + +=> INSERT INTO zoo VALUES(123, 'zebra'); +INSERT 0 1 +=> INSERT INTO zoo VALUES(123, 'zebra'); +INSERT 0 1 +=> INSERT INTO zoo VALUES(123, 'lion'); +ERROR: conflicting key value violates exclusion constraint "zoo_cage_animal_excl" +DETAIL: Key (cage, animal)=(123, lion) conflicts with existing key (cage, animal)=(123, zebra). +=> INSERT INTO zoo VALUES(124, 'lion'); +INSERT 0 1 </programlisting> </sect2> diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 4ab833133c..8504555bac 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.225 2010/04/03 07:22:52 petere Exp $ --> +<!-- doc/src/sgml/catalogs.sgml --> <!-- Documentation of the system catalogs, directed toward PostgreSQL developers --> @@ -104,6 +104,11 @@ </row> <row> + <entry><link linkend="catalog-pg-collation"><structname>pg_collation</structname></link></entry> + <entry>collations (locale information)</entry> + </row> + + <row> <entry><link linkend="catalog-pg-conversion"><structname>pg_conversion</structname></link></entry> <entry>encoding conversion information</entry> </row> @@ -114,6 +119,11 @@ </row> <row> + <entry><link linkend="catalog-pg-db-role-setting"><structname>pg_db_role_setting</structname></link></entry> + <entry>per-role and per-database settings</entry> + </row> + + <row> <entry><link linkend="catalog-pg-default-acl"><structname>pg_default_acl</structname></link></entry> <entry>default privileges for object types</entry> </row> @@ -134,6 +144,11 @@ </row> <row> + <entry><link linkend="catalog-pg-extension"><structname>pg_extension</structname></link></entry> + <entry>installed extensions</entry> + </row> + + <row> <entry><link linkend="catalog-pg-foreign-data-wrapper"><structname>pg_foreign_data_wrapper</structname></link></entry> <entry>foreign-data wrapper definitions</entry> </row> @@ -144,6 +159,11 @@ </row> <row> + <entry><link linkend="catalog-pg-foreign-table"><structname>pg_foreign_table</structname></link></entry> + <entry>additional foreign table information</entry> + </row> + + <row> <entry><link linkend="catalog-pg-index"><structname>pg_index</structname></link></entry> <entry>additional index information</entry> </row> @@ -204,8 +224,8 @@ </row> <row> - <entry><link linkend="catalog-pg-db-role-setting"><structname>pg_db_role_setting</structname></link></entry> - <entry>per-role and per-database settings</entry> + <entry><link linkend="catalog-pg-seclabel"><structname>pg_seclabel</structname></link></entry> + <entry>security labels on database objects</entry> </row> <row> @@ -344,8 +364,8 @@ <entry> The initial value of the transition state. This is a text field containing the initial value in its external string - representation. If this field is NULL, the transition state - value starts out NULL + representation. If this field is null, the transition state + value starts out null. </entry> </row> </tbody> @@ -418,7 +438,16 @@ <entry><structfield>amcanorder</structfield></entry> <entry><type>bool</type></entry> <entry></entry> - <entry>Does the access method support ordered scans?</entry> + <entry>Does the access method support ordered scans sorted by the + indexed column's value?</entry> + </row> + + <row> + <entry><structfield>amcanorderbyop</structfield></entry> + <entry><type>bool</type></entry> + <entry></entry> + <entry>Does the access method support ordered scans sorted by the result + of an operator on the indexed column?</entry> </row> <row> @@ -451,17 +480,10 @@ </row> <row> - <entry><structfield>amindexnulls</structfield></entry> - <entry><type>bool</type></entry> - <entry></entry> - <entry>Does the access method support null index entries?</entry> - </row> - - <row> <entry><structfield>amsearchnulls</structfield></entry> <entry><type>bool</type></entry> <entry></entry> - <entry>Does the access method support IS NULL/NOT NULL searches?</entry> + <entry>Does the access method support <literal>IS NULL</>/<literal>NOT NULL</> searches?</entry> </row> <row> @@ -479,6 +501,13 @@ </row> <row> + <entry><structfield>ampredlocks</structfield></entry> + <entry><type>bool</type></entry> + <entry></entry> + <entry>Does an index of this type manage fine-grained predicate locks?</entry> + </row> + + <row> <entry><structfield>amkeytype</structfield></entry> <entry><type>oid</type></entry> <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry> @@ -496,7 +525,7 @@ <entry><structfield>ambeginscan</structfield></entry> <entry><type>regproc</type></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> - <entry><quote>Start new scan</quote> function</entry> + <entry><quote>Prepare for index scan</quote> function</entry> </row> <row> @@ -517,14 +546,14 @@ <entry><structfield>amrescan</structfield></entry> <entry><type>regproc</type></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> - <entry><quote>Restart this scan</quote> function</entry> + <entry><quote>(Re)start index scan</quote> function</entry> </row> <row> <entry><structfield>amendscan</structfield></entry> <entry><type>regproc</type></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> - <entry><quote>End this scan</quote> function</entry> + <entry><quote>Clean up after index scan</quote> function</entry> </row> <row> @@ -549,6 +578,13 @@ </row> <row> + <entry><structfield>ambuildempty</structfield></entry> + <entry><type>regproc</type></entry> + <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> + <entry><quote>Build empty index</quote> function</entry> + </row> + + <row> <entry><structfield>ambulkdelete</structfield></entry> <entry><type>regproc</type></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> @@ -593,9 +629,13 @@ <para> The catalog <structname>pg_amop</structname> stores information about operators associated with access method operator families. There is one - row for each operator that is a member of an operator family. An operator + row for each operator that is a member of an operator family. A family + member can be either a <firstterm>search</> operator or an + <firstterm>ordering</> operator. An operator can appear in more than one family, but cannot appear in more than one - position within a family. + search position nor more than one ordering position within a family. + (It is allowed, though unlikely, for an operator to be used for both + search and ordering purposes.) </para> <table> @@ -641,6 +681,14 @@ </row> <row> + <entry><structfield>amoppurpose</structfield></entry> + <entry><type>char</type></entry> + <entry></entry> + <entry>Operator purpose, either <literal>s</> for search or + <literal>o</> for ordering</entry> + </row> + + <row> <entry><structfield>amopopr</structfield></entry> <entry><type>oid</type></entry> <entry><literal><link linkend="catalog-pg-operator"><structname>pg_operator</structname></link>.oid</literal></entry> @@ -654,11 +702,53 @@ <entry>Index access method operator family is for</entry> </row> + <row> + <entry><structfield>amopsortfamily</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-opfamily"><structname>pg_opfamily</structname></link>.oid</literal></entry> + <entry>The btree operator family this entry sorts according to, if an + ordering operator; zero if a search operator</entry> + </row> + </tbody> </tgroup> </table> <para> + A <quote>search</> operator entry indicates that an index of this operator + family can be searched to find all rows satisfying + <literal>WHERE</> + <replaceable>indexed_column</> + <replaceable>operator</> + <replaceable>constant</>. + Obviously, such an operator must return boolean, and its left-hand input + type must match the index's column data type. + </para> + + <para> + An <quote>ordering</> operator entry indicates that an index of this + operator family can be scanned to return rows in the order represented by + <literal>ORDER BY</> + <replaceable>indexed_column</> + <replaceable>operator</> + <replaceable>constant</>. + Such an operator could return any sortable data type, though again + its left-hand input type must match the index's column data type. + The exact semantics of the <literal>ORDER BY</> are specified by the + <structfield>amopsortfamily</structfield> column, which must reference + a btree operator family for the operator's result type. + </para> + + <note> + <para> + At present, it's assumed that the sort order for an ordering operator + is the default for the referenced opfamily, i.e., <literal>ASC NULLS + LAST</>. This might someday be relaxed by adding additional columns + to specify sort options explicitly. + </para> + </note> + + <para> An entry's <structfield>amopmethod</> must match the <structname>opfmethod</> of its containing operator family (including <structfield>amopmethod</> here is an intentional denormalization of the @@ -797,7 +887,7 @@ <row> <entry><structfield>adbin</structfield></entry> - <entry><type>text</type></entry> + <entry><type>pg_node_tree</type></entry> <entry></entry> <entry>The internal representation of the column default value</entry> </row> @@ -892,7 +982,7 @@ The exact meaning of positive values is data type-dependent. For scalar data types, <structfield>attstattarget</structfield> is both the target number of <quote>most common values</quote> - to collect, and the target number of histogram bins to create + to collect, and the target number of histogram bins to create. </entry> </row> @@ -913,7 +1003,7 @@ <entry> The number of the column. Ordinary columns are numbered from 1 up. System columns, such as <structfield>oid</structfield>, - have (arbitrary) negative numbers + have (arbitrary) negative numbers. </entry> </row> @@ -924,7 +1014,7 @@ <entry> Number of dimensions, if the column is an array type; otherwise 0. (Presently, the number of dimensions of an array is not enforced, - so any nonzero value effectively means <quote>it's an array</>) + so any nonzero value effectively means <quote>it's an array</>.) </entry> </row> @@ -948,7 +1038,7 @@ supplied at table creation time (for example, the maximum length of a <type>varchar</type> column). It is passed to type-specific input functions and length coercion functions. - The value will generally be -1 for types that do not need <structfield>atttypmod</> + The value will generally be -1 for types that do not need <structfield>atttypmod</>. </entry> </row> @@ -968,7 +1058,7 @@ <entry> Normally a copy of <literal>pg_type.typstorage</> of this column's type. For TOAST-able data types, this can be altered - after column creation to control storage policy + after column creation to control storage policy. </entry> </row> @@ -987,7 +1077,7 @@ <entry></entry> <entry> This represents a not-null constraint. It is possible to - change this column to enable or disable the constraint + change this column to enable or disable the constraint. </entry> </row> @@ -998,7 +1088,7 @@ <entry> This column has a default value, in which case there will be a corresponding entry in the <structname>pg_attrdef</structname> - catalog that actually defines the value + catalog that actually defines the value. </entry> </row> @@ -1009,7 +1099,7 @@ <entry> This column has been dropped and is no longer valid. A dropped column is still physically present in the table, but is - ignored by the parser and so cannot be accessed via SQL + ignored by the parser and so cannot be accessed via SQL. </entry> </row> @@ -1019,7 +1109,7 @@ <entry></entry> <entry> This column is defined locally in the relation. Note that a column can - be locally defined and inherited simultaneously + be locally defined and inherited simultaneously. </entry> </row> @@ -1029,7 +1119,17 @@ <entry></entry> <entry> The number of direct ancestors this column has. A column with a - nonzero number of ancestors cannot be dropped nor renamed + nonzero number of ancestors cannot be dropped nor renamed. + </entry> + </row> + + <row> + <entry><structfield>attcollation</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-collation"><structname>pg_collation</structname></link>.oid</literal></entry> + <entry> + The defined collation of the column, or zero if the column is + not of a collatable data type. </entry> </row> @@ -1163,7 +1263,18 @@ <entry><type>bool</type></entry> <entry> Role can log in. That is, this role can be given as the initial - session authorization identifier + session authorization identifier. + </entry> + </row> + + <row> + <entry><structfield>rolreplication</structfield></entry> + <entry><type>bool</type></entry> + <entry> + Role is a replication role. That is, this role can initiate streaming + replication (see <xref linkend="streaming-replication">) and set/unset + the system backup mode using <function>pg_start_backup</> and + <function>pg_stop_backup</>. </entry> </row> @@ -1172,21 +1283,30 @@ <entry><type>int4</type></entry> <entry> For roles that can log in, this sets maximum number of concurrent - connections this role can make. -1 means no limit + connections this role can make. -1 means no limit. </entry> </row> <row> <entry><structfield>rolpassword</structfield></entry> <entry><type>text</type></entry> - <entry>Password (possibly encrypted); NULL if none</entry> + <entry> + Password (possibly encrypted); null if none. If the password + is encrypted, this column will begin with the string <literal>md5</> + followed by a 32-character hexadecimal MD5 hash. The MD5 hash + will be of the user's password concatenated to their user name. + For example, if user <literal>joe</> has password <literal>xyzzy</>, + <productname>PostgreSQL</> will store the md5 hash of + <literal>xyzzyjoe</>. A password that does not follow that + format is assumed to be unencrypted. + </entry> </row> <row> <entry><structfield>rolvaliduntil</structfield></entry> <entry><type>timestamptz</type></entry> <entry>Password expiry time (only used for password authentication); - NULL if no expiration</entry> + null if no expiration</entry> </row> </tbody> </tgroup> @@ -1338,7 +1458,7 @@ <literal>a</> means implicitly in assignment to a target column, as well as explicitly. <literal>i</> means implicitly in expressions, as well as the - other cases + other cases. </entry> </row> <row> @@ -1349,7 +1469,7 @@ Indicates how the cast is performed. <literal>f</> means that the function specified in the <structfield>castfunc</> field is used. <literal>i</> means that the input/output functions are used. - <literal>b</> means that the types are binary-coercible, thus no conversion is required + <literal>b</> means that the types are binary-coercible, thus no conversion is required. </entry> </row> </tbody> @@ -1362,7 +1482,7 @@ return the cast destination type as their result type. A cast function can have up to three arguments. The second argument, if present, must be type <type>integer</>; it receives the type - modifier associated with the destination type, or <literal>-1</> + modifier associated with the destination type, or -1 if there is none. The third argument, if present, must be type <type>boolean</>; it receives <literal>true</> if the cast is an explicit cast, <literal>false</> otherwise. @@ -1445,6 +1565,16 @@ </row> <row> + <entry><structfield>reloftype</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry> + <entry> + For typed tables, the OID of the underlying composite type, + zero for all other relations + </entry> + </row> + + <row> <entry><structfield>relowner</structfield></entry> <entry><type>oid</type></entry> <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry> @@ -1487,7 +1617,7 @@ <symbol>BLCKSZ</symbol>). This is only an estimate used by the planner. It is updated by <command>VACUUM</command>, <command>ANALYZE</command>, and a few DDL commands such as - <command>CREATE INDEX</command> + <command>CREATE INDEX</command>. </entry> </row> @@ -1499,7 +1629,7 @@ Number of rows in the table. This is only an estimate used by the planner. It is updated by <command>VACUUM</command>, <command>ANALYZE</command>, and a few DDL commands such as - <command>CREATE INDEX</command> + <command>CREATE INDEX</command>. </entry> </row> @@ -1510,7 +1640,7 @@ <entry> OID of the TOAST table associated with this table, 0 if none. The TOAST table stores large attributes <quote>out of line</quote> in a - secondary table + secondary table. </entry> </row> @@ -1519,7 +1649,7 @@ <entry><type>oid</type></entry> <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry> <entry> - For a TOAST table, the OID of its index. 0 if not a TOAST table + For a TOAST table, the OID of its index. 0 if not a TOAST table. </entry> </row> @@ -1539,17 +1669,17 @@ <entry> True if this table is shared across all databases in the cluster. Only certain system catalogs (such as <structname>pg_database</structname>) - are shared + are shared. </entry> </row> <row> - <entry><structfield>relistemp</structfield></entry> - <entry><type>bool</type></entry> + <entry><structfield>relpersistence</structfield></entry> + <entry><type>char</type></entry> <entry></entry> <entry> - True if this table is a temporary relation. If so, only the creating - session can safely access its contents + <literal>p</> = permanent table, <literal>u</> = unlogged table, + <literal>t</> = temporary table </entry> </row> @@ -1560,8 +1690,8 @@ <entry> <literal>r</> = ordinary table, <literal>i</> = index, <literal>S</> = sequence, <literal>v</> = view, <literal>c</> = - composite type, <literal>t</> = TOAST - table + composite type, <literal>t</> = TOAST table, + <literal>f</> = foreign table </entry> </row> @@ -1573,7 +1703,7 @@ Number of user columns in the relation (system columns not counted). There must be this many corresponding entries in <structname>pg_attribute</structname>. See also - <literal>pg_attribute.attnum</literal> + <literal>pg_attribute.attnum</literal>. </entry> </row> @@ -1606,17 +1736,6 @@ </row> <row> - <entry><structfield>relhasexclusion</structfield></entry> - <entry><type>bool</type></entry> - <entry></entry> - <entry> - For a table, true if the table has (or once had) any exclusion - constraints; for an index, true if the index supports an exclusion - constraint - </entry> - </row> - - <row> <entry><structfield>relhasrules</structfield></entry> <entry><type>bool</type></entry> <entry></entry> @@ -1652,7 +1771,7 @@ (<quote>frozen</>) transaction ID in this table. This is used to track whether the table needs to be vacuumed in order to prevent transaction ID wraparound or to allow <literal>pg_clog</> to be shrunk. Zero - (<symbol>InvalidTransactionId</symbol>) if the relation is not a table + (<symbol>InvalidTransactionId</symbol>) if the relation is not a table. </entry> </row> @@ -1681,7 +1800,7 @@ </table> <para> - Several of the boolean flags in <structname>pg_class</> are maintained + Several of the Boolean flags in <structname>pg_class</> are maintained lazily: they are guaranteed to be true if that's the correct state, but may not be reset to false immediately when the condition is no longer true. For example, <structfield>relhasindex</> is set by @@ -1776,6 +1895,13 @@ </row> <row> + <entry><structfield>convalidated</structfield></entry> + <entry><type>bool</type></entry> + <entry></entry> + <entry>Has the constraint been validated? Can only be false for foreign keys</entry> + </row> + + <row> <entry><structfield>conrelid</structfield></entry> <entry><type>oid</type></entry> <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry> @@ -1847,7 +1973,7 @@ <entry></entry> <entry> This constraint is defined locally for the relation. Note that a - constraint can be locally defined and inherited simultaneously + constraint can be locally defined and inherited simultaneously. </entry> </row> @@ -1858,7 +1984,7 @@ <entry> The number of direct inheritance ancestors this constraint has. A constraint with - a nonzero number of ancestors cannot be dropped nor renamed + a nonzero number of ancestors cannot be dropped nor renamed. </entry> </row> @@ -1907,7 +2033,7 @@ <row> <entry><structfield>conbin</structfield></entry> - <entry><type>text</type></entry> + <entry><type>pg_node_tree</type></entry> <entry></entry> <entry>If a check constraint, an internal representation of the expression</entry> </row> @@ -1945,13 +2071,113 @@ <para> <literal>pg_class.relchecks</literal> needs to agree with the number of check-constraint entries found in this table for each - relation. Also, <literal>pg_class.relhasexclusion</literal> must - be true if there are any exclusion-constraint entries for the relation. + relation. </para> </note> </sect1> + <sect1 id="catalog-pg-collation"> + <title><structname>pg_collation</structname></title> + + <indexterm zone="catalog-pg-collation"> + <primary>pg_collation</primary> + </indexterm> + + <para> + The catalog <structname>pg_collation</structname> describes the + available collations, which are essentially mappings from an SQL + name to operating system locale categories. + See <xref linkend="collation"> for more information. + </para> + + <table> + <title><structname>pg_collation</> Columns</title> + + <tgroup cols="4"> + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>References</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><structfield>collname</structfield></entry> + <entry><type>name</type></entry> + <entry></entry> + <entry>Collation name (unique per namespace and encoding)</entry> + </row> + + <row> + <entry><structfield>collnamespace</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-namespace"><structname>pg_namespace</structname></link>.oid</literal></entry> + <entry> + The OID of the namespace that contains this collation + </entry> + </row> + + <row> + <entry><structfield>collowner</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry> + <entry>Owner of the collation</entry> + </row> + + <row> + <entry><structfield>collencoding</structfield></entry> + <entry><type>int4</type></entry> + <entry></entry> + <entry>Encoding in which the collation is applicable, or -1 if it + works for any encoding</entry> + </row> + + <row> + <entry><structfield>collcollate</structfield></entry> + <entry><type>name</type></entry> + <entry></entry> + <entry><symbol>LC_COLLATE</> for this collation object</entry> + </row> + + <row> + <entry><structfield>collctype</structfield></entry> + <entry><type>name</type></entry> + <entry></entry> + <entry><symbol>LC_CTYPE</> for this collation object</entry> + </row> + </tbody> + </tgroup> + </table> + + <para> + Note that the unique key on this catalog is (<structfield>collname</>, + <structfield>collencoding</>, <structfield>collnamespace</>) not just + (<structfield>collname</>, <structfield>collnamespace</>). + <productname>PostgreSQL</productname> generally ignores all + collations that do not have <structfield>collencoding</> equal to + either the current database's encoding or -1, and creation of new entries + with the same name as an entry with <structfield>collencoding</> = -1 + is forbidden. Therefore it is sufficient to use a qualified SQL name + (<replaceable>schema</>.<replaceable>name</>) to identify a collation, + even though this is not unique according to the catalog definition. + The reason for defining the catalog this way is that + <application>initdb</> fills it in at cluster initialization time with + entries for all locales available on the system, so it must be able to + hold entries for all encodings that might ever be used in the cluster. + </para> + + <para> + In the <literal>template0</> database, it could be useful to create + collations whose encoding does not match the database encoding, + since they could match the encodings of databases later cloned from + <literal>template0</>. This would currently have to be done manually. + </para> + </sect1> + <sect1 id="catalog-pg-conversion"> <title><structname>pg_conversion</structname></title> @@ -1960,9 +2186,8 @@ </indexterm> <para> - The catalog <structname>pg_conversion</structname> describes the - available encoding conversion procedures. See - <xref linkend="sql-createconversion"> + The catalog <structname>pg_conversion</structname> describes + encoding conversion procedures. See <xref linkend="sql-createconversion"> for more information. </para> @@ -2128,7 +2353,7 @@ <entry></entry> <entry> If false then no one can connect to this database. This is - used to protect the <literal>template0</> database from being altered + used to protect the <literal>template0</> database from being altered. </entry> </row> @@ -2138,7 +2363,7 @@ <entry></entry> <entry> Sets maximum number of concurrent connections that can be made - to this database. -1 means no limit + to this database. -1 means no limit. </entry> </row> @@ -2162,7 +2387,7 @@ track whether the database needs to be vacuumed in order to prevent transaction ID wraparound or to allow <literal>pg_clog</> to be shrunk. It is the minimum of the per-table - <structname>pg_class</>.<structfield>relfrozenxid</> values + <structname>pg_class</>.<structfield>relfrozenxid</> values. </entry> </row> @@ -2175,7 +2400,7 @@ Within this database, all tables for which <structname>pg_class</>.<structfield>reltablespace</> is zero will be stored in this tablespace; in particular, all the non-shared - system catalogs will be there + system catalogs will be there. </entry> </row> @@ -2196,6 +2421,66 @@ </sect1> + <sect1 id="catalog-pg-db-role-setting"> + <title><structname>pg_db_role_setting</structname></title> + + <indexterm zone="catalog-pg-db-role-setting"> + <primary>pg_db_role_setting</primary> + </indexterm> + + <para> + The catalog <structname>pg_db_role_setting</structname> records the default + values that have been set for run-time configuration variables, + for each role and database combination. + </para> + + <para> + Unlike most system catalogs, <structname>pg_db_role_setting</structname> + is shared across all databases of a cluster: there is only one + copy of <structname>pg_db_role_setting</structname> per cluster, not + one per database. + </para> + + <table> + <title><structname>pg_db_role_setting</> Columns</title> + + <tgroup cols="4"> + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>References</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><structfield>setdatabase</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-database"><structname>pg_database</structname></link>.oid</literal></entry> + <entry>The OID of the database the setting is applicable to, or zero if not database-specific</entry> + </row> + + <row> + <entry><structfield>setrole</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry> + <entry>The OID of the role the setting is applicable to, or zero if not role-specific</entry> + </row> + + <row> + <entry><structfield>setconfig</structfield></entry> + <entry><type>text[]</type></entry> + <entry></entry> + <entry>Defaults for run-time configuration variables</entry> + </row> + </tbody> + </tgroup> + </table> + </sect1> + + <sect1 id="catalog-pg-default-acl"> <title><structname>pg_default_acl</structname></title> @@ -2273,7 +2558,7 @@ </para> <para> - Note that when an ACL entry in another catalog is NULL, it is taken + Note that when an ACL entry in another catalog is null, it is taken to represent the hard-wired default privileges for its object, <emphasis>not</> whatever might be in <structname>pg_default_acl</> at the moment. <structname>pg_default_acl</> is only consulted during @@ -2340,7 +2625,7 @@ For a table column, this is the column number (the <structfield>objid</> and <structfield>classid</> refer to the table itself). For all other object types, this column is - zero + zero. </entry> </row> @@ -2366,7 +2651,7 @@ For a table column, this is the column number (the <structfield>refobjid</> and <structfield>refclassid</> refer to the table itself). For all other object types, this column - is zero + is zero. </entry> </row> @@ -2438,6 +2723,21 @@ </varlistentry> <varlistentry> + <term><symbol>DEPENDENCY_EXTENSION</> (<literal>e</>)</term> + <listitem> + <para> + The dependent object is a member of the <firstterm>extension</> that is + the referenced object (see + <link linkend="catalog-pg-extension"><structname>pg_extension</structname></link>). + The dependent object can be dropped only via + <command>DROP EXTENSION</> on the referenced object. Functionally + this dependency type acts the same as an internal dependency, but + it's kept separate for clarity and to simplify <application>pg_dump</>. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><symbol>DEPENDENCY_PIN</> (<literal>p</>)</term> <listitem> <para> @@ -2515,7 +2815,7 @@ For a comment on a table column, this is the column number (the <structfield>objoid</> and <structfield>classoid</> refer to the table itself). For all other object types, this column is - zero + zero. </entry> </row> @@ -2541,12 +2841,9 @@ <para> The <structname>pg_enum</structname> catalog contains entries - matching enum types to their associated values and labels. The + showing the values and labels for each enum type. The internal representation of a given enum value is actually the OID - of its associated row in <structname>pg_enum</structname>. The - OIDs for a particular enum type are guaranteed to be ordered in - the way the type should sort, but there is no guarantee about the - ordering of OIDs of unrelated enum types. + of its associated row in <structname>pg_enum</structname>. </para> <table> @@ -2571,6 +2868,13 @@ </row> <row> + <entry><structfield>enumsortorder</structfield></entry> + <entry><type>float4</type></entry> + <entry></entry> + <entry>The sort position of this enum value within its enum type</entry> + </row> + + <row> <entry><structfield>enumlabel</structfield></entry> <entry><type>name</type></entry> <entry></entry> @@ -2579,6 +2883,121 @@ </tbody> </tgroup> </table> + + <para> + The OIDs for <structname>pg_enum</structname> rows follow a special + rule: even-numbered OIDs are guaranteed to be ordered in the same way + as the sort ordering of their enum type. That is, if two even OIDs + belong to the same enum type, the smaller OID must have the smaller + <structfield>enumsortorder</structfield> value. Odd-numbered OID values + need bear no relationship to the sort order. This rule allows the + enum comparison routines to avoid catalog lookups in many common cases. + The routines that create and alter enum types attempt to assign even + OIDs to enum values whenever possible. + </para> + + <para> + When an enum type is created, its members are assigned sort-order + positions 1..<replaceable>n</>. But members added later might be given + negative or fractional values of <structfield>enumsortorder</structfield>. + The only requirement on these values is that they be correctly + ordered and unique within each enum type. + </para> + </sect1> + + + <sect1 id="catalog-pg-extension"> + <title><structname>pg_extension</structname></title> + + <indexterm zone="catalog-pg-extension"> + <primary>pg_extension</primary> + </indexterm> + + <para> + The catalog <structname>pg_extension</structname> stores information + about the installed extensions. See <xref linkend="extend-extensions"> + for details about extensions. + </para> + + <table> + <title><structname>pg_extension</> Columns</title> + + <tgroup cols="4"> + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>References</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><structfield>extname</structfield></entry> + <entry><type>name</type></entry> + <entry></entry> + <entry>Name of the extension</entry> + </row> + + <row> + <entry><structfield>extowner</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry> + <entry>Owner of the extension</entry> + </row> + + <row> + <entry><structfield>extnamespace</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-namespace"><structname>pg_namespace</structname></link>.oid</literal></entry> + <entry>Schema containing the extension's exported objects</entry> + </row> + + <row> + <entry><structfield>extrelocatable</structfield></entry> + <entry><type>bool</type></entry> + <entry></entry> + <entry>True if extension can be relocated to another schema</entry> + </row> + + <row> + <entry><structfield>extversion</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry>Version name for the extension</entry> + </row> + + <row> + <entry><structfield>extconfig</structfield></entry> + <entry><type>oid[]</type></entry> + <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry> + <entry>Array of <type>regclass</> OIDs for the extension's configuration + table(s), or <literal>NULL</> if none</entry> + </row> + + <row> + <entry><structfield>extcondition</structfield></entry> + <entry><type>text[]</type></entry> + <entry></entry> + <entry>Array of <literal>WHERE</>-clause filter conditions for the + extension's configuration table(s), or <literal>NULL</> if none</entry> + </row> + + </tbody> + </tgroup> + </table> + + <para> + Note that unlike most catalogs with a <quote>namespace</> column, + <structfield>extnamespace</structfield> is not meant to imply + that the extension belongs to that schema. Extension names are never + schema-qualified. Rather, <structfield>extnamespace</structfield> + indicates the schema that contains most or all of the extension's + objects. If <structfield>extrelocatable</structfield> is true, then + this schema must in fact contain all schema-qualifiable objects + belonging to the extension. + </para> </sect1> @@ -2625,15 +3044,26 @@ </row> <row> + <entry><structfield>fdwhandler</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> + <entry> + References a handler function that is responsible for + supplying execution routines for the foreign-data wrapper. + Zero if no handler is provided + </entry> + </row> + + <row> <entry><structfield>fdwvalidator</structfield></entry> <entry><type>oid</type></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> <entry> References a validator function that is responsible for - checking the validity of the generic options given to the - foreign-data wrapper, as well as to foreign servers and user + checking the validity of the options given to the + foreign-data wrapper, as well as options for foreign servers and user mappings using the foreign-data wrapper. Zero if no validator - is provided. + is provided </entry> </row> @@ -2672,8 +3102,8 @@ <para> The catalog <structname>pg_foreign_server</structname> stores - foreign server definitions. A foreign server describes the - connection to a remote server, managing external data. Foreign + foreign server definitions. A foreign server describes a source + of external data, such as a remote server. Foreign servers are accessed via foreign-data wrappers. </para> @@ -2709,7 +3139,7 @@ <entry><structfield>srvfdw</structfield></entry> <entry><type>oid</type></entry> <entry><literal><link linkend="catalog-pg-foreign-data-wrapper"><structname>pg_foreign_data_wrapper</structname></link>.oid</literal></entry> - <entry>The OID of the foreign-data wrapper of this foreign server</entry> + <entry>OID of the foreign-data wrapper of this foreign server</entry> </row> <row> @@ -2743,7 +3173,65 @@ <entry><type>text[]</type></entry> <entry></entry> <entry> - Foreign server specific options, as <quote>keyword=value</> strings. + Foreign server specific options, as <quote>keyword=value</> strings + </entry> + </row> + </tbody> + </tgroup> + </table> + </sect1> + + + <sect1 id="catalog-pg-foreign-table"> + <title><structname>pg_foreign_table</structname></title> + + <indexterm zone="catalog-pg-foreign-table"> + <primary>pg_foreign_table</primary> + </indexterm> + + <para> + The catalog <structname>pg_foreign_table</structname> contains + auxiliary information about foreign tables. A foreign table is + primarily represented by a <structname>pg_class</structname> entry, + just like a regular table. Its <structname>pg_foreign_table</structname> + entry contains the information that is pertinent only to foreign tables + and not any other kind of relation. + </para> + + <table> + <title><structname>pg_foreign_table</> Columns</title> + + <tgroup cols="4"> + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>References</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><structfield>ftrelid</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry> + <entry>OID of the <structname>pg_class</> entry for this foreign table</entry> + </row> + + <row> + <entry><structfield>ftserver</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-foreign-server"><structname>pg_foreign_server</structname></link>.oid</literal></entry> + <entry>OID of the foreign server for this foreign table</entry> + </row> + + <row> + <entry><structfield>ftoptions</structfield></entry> + <entry><type>text[]</type></entry> + <entry></entry> + <entry> + Foreign table options, as <quote>keyword=value</> strings </entry> </row> </tbody> @@ -2817,11 +3305,19 @@ </row> <row> + <entry><structfield>indisexclusion</structfield></entry> + <entry><type>bool</type></entry> + <entry></entry> + <entry>If true, this index supports an exclusion constraint</entry> + </row> + + <row> <entry><structfield>indimmediate</structfield></entry> <entry><type>bool</type></entry> <entry></entry> - <entry>If true, the uniqueness check is enforced immediately on insertion - (<structfield>indisunique</> should always be true when this is true)</entry> + <entry>If true, the uniqueness check is enforced immediately on + insertion + (irrelevant if <structfield>indisunique</> is not true)</entry> </row> <row> @@ -2840,7 +3336,7 @@ index is possibly incomplete: it must still be modified by <command>INSERT</>/<command>UPDATE</> operations, but it cannot safely be used for queries. If it is unique, the uniqueness property is not - true either + true either. </entry> </row> @@ -2850,7 +3346,7 @@ <entry></entry> <entry> If true, queries must not use the index until the <structfield>xmin</> - of this <structname>pg_index</> row is below their TransactionXmin + of this <structname>pg_index</> row is below their <symbol>TransactionXmin</symbol> event horizon, because the table may contain broken HOT chains with incompatible rows that they can see </entry> @@ -2863,7 +3359,7 @@ <entry> If true, the index is currently ready for inserts. False means the index must be ignored by <command>INSERT</>/<command>UPDATE</> - operations + operations. </entry> </row> @@ -2877,7 +3373,17 @@ of <literal>1 3</literal> would mean that the first and the third table columns make up the index key. A zero in this array indicates that the corresponding index attribute is an expression over the table columns, - rather than a simple column reference + rather than a simple column reference. + </entry> + </row> + + <row> + <entry><structfield>indcollation</structfield></entry> + <entry><type>oidvector</type></entry> + <entry><literal><link linkend="catalog-pg-collation"><structname>pg_collation</structname></link>.oid</literal></entry> + <entry> + For each column in the index key, this contains the OID of the + collation to use for the index. </entry> </row> @@ -2888,7 +3394,7 @@ <entry> For each column in the index key, this contains the OID of the operator class to use. See - <link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link> for details + <link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link> for details. </entry> </row> @@ -2899,26 +3405,32 @@ <entry> This is an array of <structfield>indnatts</structfield> values that store per-column flag bits. The meaning of the bits is defined by - the index's access method + the index's access method. </entry> </row> <row> <entry><structfield>indexprs</structfield></entry> - <entry><type>text</type></entry> + <entry><type>pg_node_tree</type></entry> <entry></entry> - <entry>Expression trees (in <function>nodeToString()</function> representation) - for index attributes that are not simple column references. This is a - list with one element for each zero entry in <structfield>indkey</>. - NULL if all index attributes are simple references</entry> + <entry> + Expression trees (in <function>nodeToString()</function> + representation) for index attributes that are not simple column + references. This is a list with one element for each zero + entry in <structfield>indkey</>. Null if all index attributes + are simple references. + </entry> </row> <row> <entry><structfield>indpred</structfield></entry> - <entry><type>text</type></entry> + <entry><type>pg_node_tree</type></entry> <entry></entry> - <entry>Expression tree (in <function>nodeToString()</function> representation) - for partial index predicate. NULL if not a partial index</entry> + <entry> + Expression tree (in <function>nodeToString()</function> + representation) for partial index predicate. Null if not a + partial index. + </entry> </row> </tbody> </tgroup> @@ -2980,7 +3492,7 @@ <entry> If there is more than one direct parent for a child table (multiple inheritance), this number tells the order in which the - inherited columns are to be arranged. The count starts at 1 + inherited columns are to be arranged. The count starts at 1. </entry> </row> </tbody> @@ -3041,7 +3553,7 @@ <acronym>SQL</acronym>) and true for user-defined languages. Currently, <application>pg_dump</application> still uses this to determine which languages need to be dumped, but this might be - replaced by a different mechanism in the future + replaced by a different mechanism in the future. </entry> </row> @@ -3053,7 +3565,7 @@ True if this is a trusted language, which means that it is believed not to grant access to anything outside the normal SQL execution environment. Only superusers can create functions in untrusted - languages + languages. </entry> </row> @@ -3077,7 +3589,7 @@ This references a function that is responsible for executing <quote>inline</> anonymous code blocks (<xref linkend="sql-do"> blocks). - Zero if inline blocks are not supported + Zero if inline blocks are not supported. </entry> </row> @@ -3088,7 +3600,7 @@ <entry> This references a language validator function that is responsible for checking the syntax and validity of new functions when they - are created. Zero if no validator is provided + are created. Zero if no validator is provided. </entry> </row> @@ -3133,7 +3645,7 @@ <structname>pg_largeobject</structname> was publicly readable and could be used to obtain the OIDs (and contents) of all large objects in the system. This is no longer the case; use - <link linkend="catalog-pg-largeobject-metadata">pg_largeobject_metadata</link> + <link linkend="catalog-pg-largeobject-metadata"><structname>pg_largeobject_metadata</></link> to obtain a list of large object OIDs. </para> @@ -3172,7 +3684,7 @@ <entry></entry> <entry> Actual data stored in the large object. - This will never be more than <symbol>LOBLKSIZE</> bytes and might be less + This will never be more than <symbol>LOBLKSIZE</> bytes and might be less. </entry> </row> </tbody> @@ -3201,7 +3713,7 @@ The catalog <structname>pg_largeobject_metadata</structname> holds metadata associated with large objects. The actual large object data is stored in - <link linkend="catalog-pg-largeobject">pg_largeobject</link>. + <link linkend="catalog-pg-largeobject"><structname>pg_largeobject</></link>. </para> <table> @@ -3222,7 +3734,7 @@ <entry><structfield>lomowner</structfield></entry> <entry><type>oid</type></entry> <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry> - <entry>Owner of the largeobject</entry> + <entry>Owner of the large object</entry> </row> <row> @@ -3693,13 +4205,13 @@ <row> <entry><structfield>tmplinline</structfield></entry> <entry><type>text</type></entry> - <entry>Name of anonymous-block handler function, or NULL if none</entry> + <entry>Name of anonymous-block handler function, or null if none</entry> </row> <row> <entry><structfield>tmplvalidator</structfield></entry> <entry><type>text</type></entry> - <entry>Name of validator function, or NULL if none</entry> + <entry>Name of validator function, or null if none</entry> </row> <row> @@ -3711,7 +4223,7 @@ <row> <entry><structfield>tmplacl</structfield></entry> <entry><type>aclitem[]</type></entry> - <entry>Access privileges for template (not yet used)</entry> + <entry>Access privileges for template (not actually used)</entry> </row> </tbody> @@ -3722,16 +4234,17 @@ There are not currently any commands that manipulate procedural language templates; to change the built-in information, a superuser must modify the table using ordinary <command>INSERT</command>, <command>DELETE</command>, - or <command>UPDATE</command> commands. It is likely that a future - release of <productname>PostgreSQL</productname> will offer - commands to change the entries in a cleaner fashion. + or <command>UPDATE</command> commands. </para> - <para> - When implemented, the <structfield>tmplacl</structfield> field will provide - access control for the template itself (i.e., the right to create a - language using it), not for the languages created from the template. - </para> + <note> + <para> + It is likely that <structname>pg_pltemplate</> will be removed in some + future release of <productname>PostgreSQL</productname>, in favor of + keeping this knowledge about procedural languages in their respective + extension installation scripts. + </para> + </note> </sect1> @@ -3853,7 +4366,7 @@ Function returns null if any call argument is null. In that case the function won't actually be called at all. Functions that are not <quote>strict</quote> must be prepared to handle - null inputs + null inputs. </entry> </row> @@ -3913,7 +4426,7 @@ An array with the data types of the function arguments. This includes only input arguments (including <literal>INOUT</literal> and <literal>VARIADIC</> arguments), and thus represents - the call signature of the function + the call signature of the function. </entry> </row> @@ -3927,7 +4440,7 @@ <literal>INOUT</literal> arguments); however, if all the arguments are <literal>IN</literal> arguments, this field will be null. Note that subscripting is 1-based, whereas for historical reasons - <structfield>proargtypes</> is subscripted from 0 + <structfield>proargtypes</> is subscripted from 0. </entry> </row> @@ -3945,7 +4458,7 @@ If all the arguments are <literal>IN</literal> arguments, this field will be null. Note that subscripts correspond to positions of - <structfield>proallargtypes</> not <structfield>proargtypes</> + <structfield>proallargtypes</> not <structfield>proargtypes</>. </entry> </row> @@ -3958,13 +4471,13 @@ Arguments without a name are set to empty strings in the array. If none of the arguments have a name, this field will be null. Note that subscripts correspond to positions of - <structfield>proallargtypes</> not <structfield>proargtypes</> + <structfield>proallargtypes</> not <structfield>proargtypes</>. </entry> </row> <row> <entry><structfield>proargdefaults</structfield></entry> - <entry><type>text</type></entry> + <entry><type>pg_node_tree</type></entry> <entry></entry> <entry> Expression trees (in <function>nodeToString()</function> representation) @@ -3972,7 +4485,7 @@ <structfield>pronargdefaults</> elements, corresponding to the last <replaceable>N</> <emphasis>input</> arguments (i.e., the last <replaceable>N</> <structfield>proargtypes</> positions). - If none of the arguments have defaults, this field will be null + If none of the arguments have defaults, this field will be null. </entry> </row> @@ -3984,7 +4497,7 @@ This tells the function handler how to invoke the function. It might be the actual source code of the function for interpreted languages, a link symbol, a file name, or just about anything - else, depending on the implementation language/call convention + else, depending on the implementation language/call convention. </entry> </row> @@ -3994,7 +4507,7 @@ <entry></entry> <entry> Additional information about how to invoke the function. - Again, the interpretation is language-specific + Again, the interpretation is language-specific. </entry> </row> @@ -4113,7 +4626,7 @@ <row> <entry><structfield>ev_qual</structfield></entry> - <entry><type>text</type></entry> + <entry><type>pg_node_tree</type></entry> <entry></entry> <entry> Expression tree (in the form of a @@ -4124,7 +4637,7 @@ <row> <entry><structfield>ev_action</structfield></entry> - <entry><type>text</type></entry> + <entry><type>pg_node_tree</type></entry> <entry></entry> <entry> Query tree (in the form of a @@ -4145,28 +4658,22 @@ </sect1> - <sect1 id="catalog-pg-db-role-setting"> - <title><structname>pg_db_role_setting</structname></title> - <indexterm zone="catalog-pg-db-role-setting"> - <primary>pg_db_role_setting</primary> - </indexterm> + <sect1 id="catalog-pg-seclabel"> + <title><structname>pg_seclabel</structname></title> - <para> - The catalog <structname>pg_db_role_setting</structname> records the default - values that have been set for run-time configuration variables, - for each role and database combination. - </para> + <indexterm zone="catalog-pg-seclabel"> + <primary>pg_seclabel</primary> + </indexterm> <para> - Unlike most system catalogs, <structname>pg_db_role_setting</structname> - is shared across all databases of a cluster: there is only one - copy of <structname>pg_db_role_setting</structname> per cluster, not - one per database. + The catalog <structname>pg_seclabel</structname> stores security + labels on database objects. See the + <xref linkend="sql-security-label"> statement. </para> <table> - <title><structname>pg_db_role_setting</> Columns</title> + <title><structname>pg_seclabel</structname> Columns</title> <tgroup cols="4"> <thead> @@ -4180,31 +4687,49 @@ <tbody> <row> - <entry><structfield>setdatabase</structfield></entry> + <entry><structfield>objoid</structfield></entry> <entry><type>oid</type></entry> - <entry><literal><link linkend="catalog-pg-database"><structname>pg_database</structname></link>.oid</literal></entry> - <entry>The OID of the database the setting is applicable to, or zero if not database-specific</entry> + <entry>any OID column</entry> + <entry>The OID of the object this security label pertains to</entry> </row> <row> - <entry><structfield>setrole</structfield></entry> + <entry><structfield>classoid</structfield></entry> <entry><type>oid</type></entry> - <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry> - <entry>The OID of the role the setting is applicable to, or zero if not role-specific</entry> + <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry> + <entry>The OID of the system catalog this object appears in</entry> </row> <row> - <entry><structfield>setconfig</structfield></entry> - <entry><type>text[]</type></entry> + <entry><structfield>objsubid</structfield></entry> + <entry><type>int4</type></entry> <entry></entry> - <entry>Defaults for run-time configuration variables</entry> + <entry> + For a security label on a table column, this is the column number (the + <structfield>objoid</> and <structfield>classoid</> refer to + the table itself). For all other object types, this column is + zero. + </entry> + </row> + + <row> + <entry><structfield>provider</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry>The label provider associated with this label.</entry> + </row> + + <row> + <entry><structfield>label</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry>The security label applied to this object.</entry> </row> </tbody> </tgroup> </table> </sect1> - <sect1 id="catalog-pg-shdepend"> <title><structname>pg_shdepend</structname></title> @@ -4276,7 +4801,7 @@ <entry> For a table column, this is the column number (the <structfield>objid</> and <structfield>classid</> refer to the - table itself). For all other object types, this column is zero + table itself). For all other object types, this column is zero. </entry> </row> @@ -4548,7 +5073,7 @@ of rows in the table; for example, a column in which values appear about twice on the average could be represented by <structfield>stadistinct</> = -0.5. - A zero value means the number of distinct values is unknown + A zero value means the number of distinct values is unknown. </entry> </row> @@ -4559,7 +5084,7 @@ <entry> A code number indicating the kind of statistics stored in the <replaceable>N</>th <quote>slot</quote> of the - <structname>pg_statistic</structname> row + <structname>pg_statistic</structname> row. </entry> </row> @@ -4571,7 +5096,7 @@ An operator used to derive the statistics stored in the <replaceable>N</>th <quote>slot</quote>. For example, a histogram slot would show the <literal><</literal> operator - that defines the sort order of the data + that defines the sort order of the data. </entry> </row> @@ -4581,7 +5106,7 @@ <entry></entry> <entry> Numerical statistics of the appropriate kind for the - <replaceable>N</>th <quote>slot</quote>, or NULL if the slot + <replaceable>N</>th <quote>slot</quote>, or null if the slot kind does not involve numerical values </entry> </row> @@ -4592,11 +5117,11 @@ <entry></entry> <entry> Column data values of the appropriate kind for the - <replaceable>N</>th <quote>slot</quote>, or NULL if the slot + <replaceable>N</>th <quote>slot</quote>, or null if the slot kind does not store any data values. Each array's element values are actually of the specific column's data type, so there is no way to define these columns' type more specifically than - <type>anyarray</> + <type>anyarray</>. </entry> </row> </tbody> @@ -4695,7 +5220,8 @@ </indexterm> <para> - The catalog <structname>pg_trigger</structname> stores triggers on tables. + The catalog <structname>pg_trigger</structname> stores triggers on tables + and views. See <xref linkend="sql-createtrigger"> for more information. </para> @@ -4739,7 +5265,7 @@ <entry><structfield>tgtype</structfield></entry> <entry><type>int2</type></entry> <entry></entry> - <entry>Bit mask identifying trigger conditions</entry> + <entry>Bit mask identifying trigger firing conditions</entry> </row> <row> @@ -4810,7 +5336,7 @@ <entry><structfield>tgattr</structfield></entry> <entry><type>int2vector</type></entry> <entry><literal><link linkend="catalog-pg-attribute"><structname>pg_attribute</structname></link>.attnum</literal></entry> - <entry>column numbers, if trigger is column-specific; otherwise an + <entry>Column numbers, if trigger is column-specific; otherwise an empty array</entry> </row> @@ -4823,10 +5349,10 @@ <row> <entry><structfield>tgqual</structfield></entry> - <entry><type>text</type></entry> + <entry><type>pg_node_tree</type></entry> <entry></entry> <entry>Expression tree (in <function>nodeToString()</function> - representation) for the trigger's <literal>WHEN</> condition, or NULL + representation) for the trigger's <literal>WHEN</> condition, or null if none</entry> </row> </tbody> @@ -4856,7 +5382,7 @@ <note> <para> <literal>pg_class.relhastriggers</literal> - must be true if a table has any triggers in this catalog. + must be true if a relation has any triggers in this catalog. </para> </note> @@ -5319,7 +5845,7 @@ where Datum is 8 bytes). Variable-length types are always passed by reference. Note that <structfield>typbyval</structfield> can be false even if the - length would allow pass-by-value + length would allow pass-by-value. </entry> </row> @@ -5335,7 +5861,7 @@ <literal>e</literal> for an enum type, or <literal>p</literal> for a pseudo-type. See also <structfield>typrelid</structfield> and - <structfield>typbasetype</structfield> + <structfield>typbasetype</structfield>. </entry> </row> @@ -5347,7 +5873,7 @@ <structfield>typcategory</structfield> is an arbitrary classification of data types that is used by the parser to determine which implicit casts should be <quote>preferred</>. - See <xref linkend="catalog-typcategory-table"> + See <xref linkend="catalog-typcategory-table">. </entry> </row> @@ -5369,7 +5895,7 @@ True if the type is defined, false if this is a placeholder entry for a not-yet-defined type. When <structfield>typisdefined</structfield> is false, nothing - except the type name, namespace, and OID can be relied on + except the type name, namespace, and OID can be relied on. </entry> </row> @@ -5380,7 +5906,7 @@ <entry> Character that separates two values of this type when parsing array input. Note that the delimiter is associated with the array - element data type, not the array data type + element data type, not the array data type. </entry> </row> @@ -5396,7 +5922,7 @@ <structname>pg_class</structname> entry doesn't really represent a table, but it is needed anyway for the type's <structname>pg_attribute</structname> entries to link to.) - Zero for non-composite types + Zero for non-composite types. </entry> </row> @@ -5418,7 +5944,7 @@ its internal representation must be some number of values of the <structfield>typelem</structfield> data type with no other data. Variable-length array types have a header defined by the array - subroutines + subroutines. </entry> </row> @@ -5479,7 +6005,7 @@ <entry><structfield>typanalyze</structfield></entry> <entry><type>regproc</type></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> - <entry>Custom ANALYZE function, or 0 to use the standard function</entry> + <entry>Custom <command>ANALYZE</command> function, or 0 to use the standard function</entry> </row> <row> @@ -5565,7 +6091,7 @@ <entry></entry> <entry><para> <structfield>typnotnull</structfield> represents a not-null - constraint on a type. Used for domains only + constraint on a type. Used for domains only. </para></entry> </row> @@ -5576,7 +6102,7 @@ <entry><para> If this is a domain (see <structfield>typtype</structfield>), then <structfield>typbasetype</structfield> identifies the type that this - one is based on. Zero if this type is not a domain + one is based on. Zero if this type is not a domain. </para></entry> </row> @@ -5587,7 +6113,7 @@ <entry><para> Domains use <structfield>typtypmod</structfield> to record the <literal>typmod</> to be applied to their base type (-1 if base type does not use a - <literal>typmod</>). -1 if this type is not a domain + <literal>typmod</>). -1 if this type is not a domain. </para></entry> </row> @@ -5597,21 +6123,35 @@ <entry></entry> <entry><para> <structfield>typndims</structfield> is the number of array dimensions - for a domain that is an array (that is, <structfield>typbasetype</> is - an array type; the domain's <structfield>typelem</> will match the base - type's <structfield>typelem</structfield>). - Zero for types other than domains over array types + for a domain over an array (that is, <structfield>typbasetype</> is + an array type). + Zero for types other than domains over array types. </para></entry> </row> <row> + <entry><structfield>typcollation</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-collation"><structname>pg_collation</structname></link>.oid</literal></entry> + <entry><para> + <structfield>typcollation</structfield> specifies the collation + of the type. If the type does not support collations, this will + be zero. A base type that supports collations will have + <symbol>DEFAULT_COLLATION_OID</symbol> here. A domain over a + collatable type can have some other collation OID, if one was + specified for the domain. + </para></entry> + </row> + + <row> <entry><structfield>typdefaultbin</structfield></entry> - <entry><type>text</type></entry> + <entry><type>pg_node_tree</type></entry> <entry></entry> <entry><para> - If <structfield>typdefaultbin</> is not null, it is the <function>nodeToString()</function> + If <structfield>typdefaultbin</> is not null, it is the + <function>nodeToString()</function> representation of a default expression for the type. This is - only used for domains + only used for domains. </para></entry> </row> @@ -5626,8 +6166,8 @@ default expression represented by <structfield>typdefaultbin</>. If <structfield>typdefaultbin</> is null and <structfield>typdefault</> is not, then <structfield>typdefault</> is the external representation of - the type's default value, which might be fed to the type's input - converter to produce a constant + the type's default value, which can be fed to the type's input + converter to produce a constant. </para></entry> </row> </tbody> @@ -5766,7 +6306,7 @@ <entry><type>text[]</type></entry> <entry></entry> <entry> - User mapping specific options, as <quote>keyword=value</> strings. + User mapping specific options, as <quote>keyword=value</> strings </entry> </row> </tbody> @@ -5819,6 +6359,16 @@ <tbody> <row> + <entry><link linkend="view-pg-available-extensions"><structname>pg_available_extensions</structname></link></entry> + <entry>available extensions</entry> + </row> + + <row> + <entry><link linkend="view-pg-available-extension-versions"><structname>pg_available_extension_versions</structname></link></entry> + <entry>available versions of extensions</entry> + </row> + + <row> <entry><link linkend="view-pg-cursors"><structname>pg_cursors</structname></link></entry> <entry>open cursors</entry> </row> @@ -5859,6 +6409,11 @@ </row> <row> + <entry><link linkend="view-pg-seclabels"><structname>pg_seclabels</structname></link></entry> + <entry>security labels</entry> + </row> + + <row> <entry><link linkend="view-pg-settings"><structname>pg_settings</structname></link></entry> <entry>parameter settings</entry> </row> @@ -5894,6 +6449,11 @@ </row> <row> + <entry><link linkend="view-pg-user-mappings"><structname>pg_user_mappings</structname></link></entry> + <entry>user mappings</entry> + </row> + + <row> <entry><link linkend="view-pg-views"><structname>pg_views</structname></link></entry> <entry>views</entry> </row> @@ -5903,6 +6463,156 @@ </table> </sect1> + <sect1 id="view-pg-available-extensions"> + <title><structname>pg_available_extensions</structname></title> + + <indexterm zone="view-pg-available-extensions"> + <primary>pg_available_extensions</primary> + </indexterm> + + <para> + The <structname>pg_available_extensions</structname> view lists the + extensions that are available for installation. + See also the + <link linkend="catalog-pg-extension"><structname>pg_extension</structname></link> + catalog, which shows the extensions currently installed. + </para> + + <table> + <title><structname>pg_available_extensions</> Columns</title> + + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><structfield>name</structfield></entry> + <entry><type>name</type></entry> + <entry>Extension name</entry> + </row> + + <row> + <entry><structfield>default_version</structfield></entry> + <entry><type>text</type></entry> + <entry>Name of default version, or <literal>NULL</literal> if none is + specified</entry> + </row> + + <row> + <entry><structfield>installed_version</structfield></entry> + <entry><type>text</type></entry> + <entry>Currently installed version of the extension, + or <literal>NULL</literal> if not installed</entry> + </row> + + <row> + <entry><structfield>comment</structfield></entry> + <entry><type>text</type></entry> + <entry>Comment string from the extension's control file</entry> + </row> + </tbody> + </tgroup> + </table> + + <para> + The <structname>pg_available_extensions</structname> view is read only. + </para> + </sect1> + + <sect1 id="view-pg-available-extension-versions"> + <title><structname>pg_available_extension_versions</structname></title> + + <indexterm zone="view-pg-available-extension-versions"> + <primary>pg_available_extension_versions</primary> + </indexterm> + + <para> + The <structname>pg_available_extension_versions</structname> view lists the + specific extension versions that are available for installation. + See also the <link + linkend="catalog-pg-extension"><structname>pg_extension</structname></link> + catalog, which shows the extensions currently installed. + </para> + + <table> + <title><structname>pg_available_extension_versions</> Columns</title> + + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><structfield>name</structfield></entry> + <entry><type>name</type></entry> + <entry>Extension name</entry> + </row> + + <row> + <entry><structfield>version</structfield></entry> + <entry><type>text</type></entry> + <entry>Version name</entry> + </row> + + <row> + <entry><structfield>installed</structfield></entry> + <entry><type>bool</type></entry> + <entry>True if this version of this extension is currently + installed</entry> + </row> + + <row> + <entry><structfield>superuser</structfield></entry> + <entry><type>bool</type></entry> + <entry>True if only superusers are allowed to install this extension</entry> + </row> + + <row> + <entry><structfield>relocatable</structfield></entry> + <entry><type>bool</type></entry> + <entry>True if extension can be relocated to another schema</entry> + </row> + + <row> + <entry><structfield>schema</structfield></entry> + <entry><type>name</type></entry> + <entry>Name of the schema that the extension must be installed into, + or <literal>NULL</literal> if partially or fully relocatable</entry> + </row> + + <row> + <entry><structfield>requires</structfield></entry> + <entry><type>name[]</type></entry> + <entry>Names of prerequisite extensions, + or <literal>NULL</literal> if none</entry> + </row> + + <row> + <entry><structfield>comment</structfield></entry> + <entry><type>text</type></entry> + <entry>Comment string from the extension's control file</entry> + </row> + </tbody> + </tgroup> + </table> + + <para> + The <structname>pg_available_extension_versions</structname> view is read + only. + </para> + </sect1> + <sect1 id="view-pg-cursors"> <title><structname>pg_cursors</structname></title> @@ -6126,7 +6836,7 @@ <entry><structfield>tablespace</structfield></entry> <entry><type>name</type></entry> <entry><literal><link linkend="catalog-pg-tablespace"><structname>pg_tablespace</structname></link>.spcname</literal></entry> - <entry>Name of tablespace containing index (NULL if default for database)</entry> + <entry>Name of tablespace containing index (null if default for database)</entry> </row> <row> <entry><structfield>indexdef</structfield></entry> @@ -6193,7 +6903,7 @@ <entry><type>text</type></entry> <entry></entry> <entry> - type of the lockable object: + Type of the lockable object: <literal>relation</>, <literal>extend</>, <literal>page</>, @@ -6212,7 +6922,7 @@ <entry> OID of the database in which the object exists, or zero if the object is a shared object, or - NULL if the object is a transaction ID + null if the object is a transaction ID </entry> </row> <row> @@ -6220,7 +6930,7 @@ <entry><type>oid</type></entry> <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry> <entry> - OID of the relation, or NULL if the object is not + OID of the relation, or null if the object is not a relation or part of a relation </entry> </row> @@ -6229,7 +6939,7 @@ <entry><type>integer</type></entry> <entry></entry> <entry> - Page number within the relation, or NULL if the object + Page number within the relation, or null if the object is not a tuple or relation page </entry> </row> @@ -6238,7 +6948,7 @@ <entry><type>smallint</type></entry> <entry></entry> <entry> - Tuple number within the page, or NULL if the object is not a tuple + Tuple number within the page, or null if the object is not a tuple </entry> </row> <row> @@ -6246,7 +6956,7 @@ <entry><type>text</type></entry> <entry></entry> <entry> - Virtual ID of a transaction, or NULL if the object is not a + Virtual ID of a transaction, or null if the object is not a virtual transaction ID </entry> </row> @@ -6255,7 +6965,7 @@ <entry><type>xid</type></entry> <entry></entry> <entry> - ID of a transaction, or NULL if the object is not a transaction ID + ID of a transaction, or null if the object is not a transaction ID </entry> </row> <row> @@ -6263,7 +6973,7 @@ <entry><type>oid</type></entry> <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry> <entry> - OID of the system catalog containing the object, or NULL if the + OID of the system catalog containing the object, or null if the object is not a general database object </entry> </row> @@ -6272,11 +6982,10 @@ <entry><type>oid</type></entry> <entry>any OID column</entry> <entry> - OID of the object within its system catalog, or NULL if the + OID of the object within its system catalog, or null if the object is not a general database object. For advisory locks it is used to distinguish the two key - spaces (<literal>1</> for an int8 key, <literal>2</> for two - int4 keys). + spaces (1 for an int8 key, 2 for two int4 keys). </entry> </row> <row> @@ -6287,7 +6996,7 @@ For a table column, this is the column number (the <structfield>classid</> and <structfield>objid</> refer to the table itself). For all other object types, this column is - zero. NULL if the object is not a general database object + zero. Null if the object is not a general database object </entry> </row> <row> @@ -6304,7 +7013,7 @@ <entry></entry> <entry> Process ID of the server process holding or awaiting this - lock. NULL if the lock is held by a prepared transaction + lock. Null if the lock is held by a prepared transaction. </entry> </row> <row> @@ -6312,7 +7021,7 @@ <entry><type>text</type></entry> <entry></entry> <entry>Name of the lock mode held or desired by this process (see <xref - linkend="locking-tables">)</entry> + linkend="locking-tables"> and <xref linkend="xact-serializable">)</entry> </row> <row> <entry><structfield>granted</structfield></entry> @@ -6452,7 +7161,7 @@ this is the <command>PREPARE</command> statement submitted by the client. For prepared statements created via the frontend/backend protocol, this is the text of the prepared - statement itself + statement itself. </entry> </row> <row> @@ -6469,7 +7178,7 @@ The expected parameter types for the prepared statement in the form of an array of <type>regtype</type>. The OID corresponding to an element of this array can be obtained by casting the - <type>regtype</type> value to <type>oid</type> + <type>regtype</type> value to <type>oid</type>. </entry> </row> <row> @@ -6675,7 +7384,7 @@ <entry></entry> <entry> For roles that can log in, this sets maximum number of concurrent - connections this role can make. -1 means no limit + connections this role can make. -1 means no limit. </entry> </row> @@ -6691,7 +7400,7 @@ <entry><type>timestamptz</type></entry> <entry></entry> <entry>Password expiry time (only used for password authentication); - NULL if no expiration</entry> + null if no expiration</entry> </row> <row> @@ -6766,6 +7475,97 @@ </sect1> + <sect1 id="view-pg-seclabels"> + <title><structname>pg_seclabels</structname></title> + + <indexterm zone="view-pg-seclabels"> + <primary>pg_seclabels</primary> + </indexterm> + + <para> + The view <structname>pg_seclabels</structname> provides information about + security labels. It as an easier-to-query version of the + <link linkend="catalog-pg-seclabel"><structname>pg_seclabel</></> catalog. + </para> + + <table> + <title><structname>pg_seclabels</> Columns</title> + + <tgroup cols="4"> + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>References</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><structfield>objoid</structfield></entry> + <entry><type>oid</type></entry> + <entry>any OID column</entry> + <entry>The OID of the object this security label pertains to</entry> + </row> + <row> + <entry><structfield>classoid</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry> + <entry>The OID of the system catalog this object appears in</entry> + </row> + <row> + <entry><structfield>objsubid</structfield></entry> + <entry><type>int4</type></entry> + <entry></entry> + <entry> + For a security label on a table column, this is the column number (the + <structfield>objoid</> and <structfield>classoid</> refer to + the table itself). For all other object types, this column is + zero. + </entry> + </row> + <row> + <entry><structfield>objtype</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry> + The type of object to which this label applies, as text. + </entry> + </row> + <row> + <entry><structfield>objnamespace</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-namespace"><structname>pg_namespace</structname></link>.oid</literal></entry> + <entry> + The OID of the namespace for this object, if applicable; + otherwise NULL. + </entry> + </row> + <row> + <entry><structfield>objname</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry> + The name of the object to which this label applies, as text. + </entry> + </row> + <row> + <entry><structfield>provider</structfield></entry> + <entry><type>text</type></entry> + <entry><literal><link linkend="catalog-pg-seclabel"><structname>pg_seclabel</structname></link>.provider</literal></entry> + <entry>The label provider associated with this label.</entry> + </row> + <row> + <entry><structfield>label</structfield></entry> + <entry><type>text</type></entry> + <entry><literal><link linkend="catalog-pg-seclabel"><structname>pg_seclabel</structname></link>.label</literal></entry> + <entry>The security label applied to this object.</entry> + </row> + </tbody> + </tgroup> + </table> + </sect1> + <sect1 id="view-pg-settings"> <title><structname>pg_settings</structname></title> @@ -6828,7 +7628,7 @@ <row> <entry><structfield>context</structfield></entry> <entry><type>text</type></entry> - <entry>Context required to set the parameter's value</entry> + <entry>Context required to set the parameter's value (see below)</entry> </row> <row> <entry><structfield>vartype</structfield></entry> @@ -6845,19 +7645,19 @@ <row> <entry><structfield>min_val</structfield></entry> <entry><type>text</type></entry> - <entry>Minimum allowed value of the parameter (NULL for non-numeric + <entry>Minimum allowed value of the parameter (null for non-numeric values)</entry> </row> <row> <entry><structfield>max_val</structfield></entry> <entry><type>text</type></entry> - <entry>Maximum allowed value of the parameter (NULL for non-numeric + <entry>Maximum allowed value of the parameter (null for non-numeric values)</entry> </row> <row> <entry><structfield>enumvals</structfield></entry> <entry><type>text[]</type></entry> - <entry>Allowed values of an enum parameter (NULL for non-enum + <entry>Allowed values of an enum parameter (null for non-enum values)</entry> </row> <row> @@ -6875,16 +7675,16 @@ <row> <entry><structfield>sourcefile</structfield></entry> <entry><type>text</type></entry> - <entry>Configuration file the current value was set in (NULL for + <entry>Configuration file the current value was set in (null for values set from sources other than configuration files, or when - examined by a non-superuser). - Helpful when using configuration include directives</entry> + examined by a non-superuser); + helpful when using <literal>include</> directives in configuration files</entry> </row> <row> <entry><structfield>sourceline</structfield></entry> <entry><type>integer</type></entry> <entry>Line number within the configuration file the current value was - set at (NULL for values set from sources other than configuration files, + set at (null for values set from sources other than configuration files, or when examined by a non-superuser) </entry> </row> @@ -6893,6 +7693,98 @@ </table> <para> + There are several possible values of <structfield>context</structfield>. + In order of decreasing difficulty of changing the setting, they are: + </para> + + <variablelist> + <varlistentry> + <term><literal>internal</literal></term> + <listitem> + <para> + These settings cannot be changed directly; they reflect internally + determined values. Some of them may be adjustable by rebuilding the + server with different configuration options, or by changing options + supplied to <command>initdb</command>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>postmaster</literal></term> + <listitem> + <para> + These settings can only be applied when the server starts, so any change + requires restarting the server. Values for these settings are typically + stored in the <filename>postgresql.conf</filename> file, or passed on + the command line when starting the server. Of course, settings with any + of the lower <structfield>context</structfield> types can also be + set at server start time. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>sighup</literal></term> + <listitem> + <para> + Changes to these settings can be made in + <filename>postgresql.conf</filename> without restarting the server. + Send a <systemitem>SIGHUP</systemitem> signal to the postmaster to + cause it to re-read <filename>postgresql.conf</filename> and apply + the changes. The postmaster will also forward the + <systemitem>SIGHUP</systemitem> signal to its child processes so that + they all pick up the new value. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>backend</literal></term> + <listitem> + <para> + Changes to these settings can be made in + <filename>postgresql.conf</filename> without restarting the server; + they can also be set for a particular session in the connection request + packet (for example, via <application>libpq</>'s <literal>PGOPTIONS</> + environment variable). However, these settings never change in a + session after it is started. If you change them in + <filename>postgresql.conf</filename>, send a + <systemitem>SIGHUP</systemitem> signal to the postmaster to cause it to + re-read <filename>postgresql.conf</filename>. The new values will only + affect subsequently-launched sessions. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>superuser</literal></term> + <listitem> + <para> + These settings can be set from <filename>postgresql.conf</filename>, + or within a session via the <command>SET</> command; but only superusers + can change them via <command>SET</>. Changes in + <filename>postgresql.conf</filename> will affect existing sessions + only if no session-local value has been established with <command>SET</>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>user</literal></term> + <listitem> + <para> + These settings can be set from <filename>postgresql.conf</filename>, + or within a session via the <command>SET</> command. Any user is + allowed to change his session-local value. Changes in + <filename>postgresql.conf</filename> will affect existing sessions + only if no session-local value has been established with <command>SET</>. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + See <xref linkend="config-setting"> for more information about the various + ways to change these parameters. + </para> + + <para> The <structname>pg_settings</structname> view cannot be inserted into or deleted from, but it can be updated. An <command>UPDATE</command> applied to a row of <structname>pg_settings</structname> is equivalent to executing @@ -6920,7 +7812,8 @@ compatibility: it emulates a catalog that existed in <productname>PostgreSQL</productname> before version 8.1. It shows properties of all roles that are marked as - <structfield>rolcanlogin</>. + <structfield>rolcanlogin</> in + <link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>. </para> <para> @@ -6987,7 +7880,9 @@ <entry><structfield>passwd</structfield></entry> <entry><type>text</type></entry> <entry></entry> - <entry>Password (possibly encrypted)</entry> + <entry>Password (possibly encrypted); null if none. See + <link linkend="catalog-pg-authid"><structname>pg_authid</structname></link> + for details of how encrypted passwords are stored.</entry> </row> <row> @@ -7101,7 +7996,7 @@ likely to increase as the table grows; the positive form is used when the column seems to have a fixed number of possible values.) For example, -1 indicates a unique column in which the number of distinct - values is the same as the number of rows + values is the same as the number of rows. </entry> </row> @@ -7110,9 +8005,9 @@ <entry><type>anyarray</type></entry> <entry></entry> <entry> - A list of the most common values in the column. (NULL if + A list of the most common values in the column. (Null if no values seem to be more common than any others.) - For some datatypes such as <type>tsvector</>, this is a list of + For some data types such as <type>tsvector</>, this is a list of the most common element values rather than values of the type itself. </entry> </row> @@ -7124,8 +8019,8 @@ <entry> A list of the frequencies of the most common values or elements, i.e., number of occurrences of each divided by total number of rows. - (NULL when <structfield>most_common_vals</structfield> is.) - For some datatypes such as <type>tsvector</>, it can also store some + (Null when <structfield>most_common_vals</structfield> is.) + For some data types such as <type>tsvector</>, it can also store some additional information, making it longer than the <structfield>most_common_vals</> array. </entry> @@ -7139,7 +8034,7 @@ A list of values that divide the column's values into groups of approximately equal population. The values in <structfield>most_common_vals</>, if present, are omitted from this - histogram calculation. (This column is NULL if the column data type + histogram calculation. (This column is null if the column data type does not have a <literal><</> operator or if the <structfield>most_common_vals</> list accounts for the entire population.) @@ -7155,7 +8050,7 @@ logical ordering of the column values. This ranges from -1 to +1. When the value is near -1 or +1, an index scan on the column will be estimated to be cheaper than when it is near zero, due to reduction - of random access to the disk. (This column is NULL if the column data + of random access to the disk. (This column is null if the column data type does not have a <literal><</> operator.) </entry> </row> @@ -7220,25 +8115,25 @@ <entry><structfield>tablespace</structfield></entry> <entry><type>name</type></entry> <entry><literal><link linkend="catalog-pg-tablespace"><structname>pg_tablespace</structname></link>.spcname</literal></entry> - <entry>Name of tablespace containing table (NULL if default for database)</entry> + <entry>Name of tablespace containing table (null if default for database)</entry> </row> <row> <entry><structfield>hasindexes</structfield></entry> <entry><type>boolean</type></entry> <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.relhasindex</literal></entry> - <entry>true if table has (or recently had) any indexes</entry> + <entry>True if table has (or recently had) any indexes</entry> </row> <row> <entry><structfield>hasrules</structfield></entry> <entry><type>boolean</type></entry> <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.relhasrules</literal></entry> - <entry>true if table has (or once had) rules</entry> + <entry>True if table has (or once had) rules</entry> </row> <row> <entry><structfield>hastriggers</structfield></entry> <entry><type>boolean</type></entry> <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.relhastriggers</literal></entry> - <entry>true if table has (or once had) triggers</entry> + <entry>True if table has (or once had) triggers</entry> </row> </tbody> </tgroup> @@ -7509,7 +8404,7 @@ <entry> User mapping specific options, as <quote>keyword=value</> strings, if the current user is the owner of the foreign - server, else null. + server, else null </entry> </row> </tbody> diff --git a/doc/src/sgml/charset.sgml b/doc/src/sgml/charset.sgml index f7b9c5dd24..6b0793e219 100644 --- a/doc/src/sgml/charset.sgml +++ b/doc/src/sgml/charset.sgml @@ -1,7 +1,7 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/charset.sgml,v 2.99 2010/03/17 17:12:31 petere Exp $ --> +<!-- doc/src/sgml/charset.sgml --> <chapter id="charset"> - <title>Localization</> + <title>Localization</title> <para> This chapter describes the available localization features from the @@ -15,6 +15,8 @@ Using the locale features of the operating system to provide locale-specific collation order, number formatting, translated messages, and other aspects. + This is covered in <xref linkend="locale"> and + <xref linkend="collation">. </para> </listitem> @@ -23,6 +25,7 @@ Providing a number of different character sets to support storing text in all kinds of languages, and providing character set translation between client and server. + This is covered in <xref linkend="multibyte">. </para> </listitem> </itemizedlist> @@ -44,7 +47,7 @@ </para> <sect2> - <title>Overview</> + <title>Overview</title> <para> Locale support is automatically initialized when a database @@ -65,13 +68,13 @@ initdb --locale=sv_SE <para> This example for Unix systems sets the locale to Swedish (<literal>sv</>) as spoken - in Sweden (<literal>SE</>). Other possibilities might be + in Sweden (<literal>SE</>). Other possibilities might include <literal>en_US</> (U.S. English) and <literal>fr_CA</> (French Canadian). If more than one character set can be used for a locale then the specifications can take the form <replaceable>language_territory.codeset</>. For example, <literal>fr_BE.UTF-8</> represents the French language (fr) as - spoken in Belgium (BE), with a <acronym>UTF-8</> character set + spoken in Belgium (BE), with a <acronym>UTF-8</> character set encoding. </para> @@ -130,7 +133,8 @@ initdb --locale=sv_SE <para> If you want the system to behave as if it had no locale support, - use the special locale <literal>C</> or <literal>POSIX</>. + use the special locale name <literal>C</>, or equivalently + <literal>POSIX</>. </para> <para> @@ -138,9 +142,12 @@ initdb --locale=sv_SE fixed when the database is created. You can use different settings for different databases, but once a database is created, you cannot change them for that database anymore. <literal>LC_COLLATE</literal> - and <literal>LC_CTYPE</literal> are these type of categories. They affect + and <literal>LC_CTYPE</literal> are these categories. They affect the sort order of indexes, so they must be kept fixed, or indexes on - text columns would become corrupt. The default values for these + text columns would become corrupt. + (But you can alleviate this restriction using collations, as discussed + in <xref linkend="collation">.) + The default values for these categories are determined when <command>initdb</command> is run, and those values are used when new databases are created, unless specified otherwise in the <command>CREATE DATABASE</command> command. @@ -153,7 +160,7 @@ initdb --locale=sv_SE linkend="runtime-config-client-format"> for details). The values that are chosen by <command>initdb</command> are actually only written into the configuration file <filename>postgresql.conf</filename> to - serve as defaults when the server is started. If you disable these + serve as defaults when the server is started. If you remove these assignments from <filename>postgresql.conf</filename> then the server will inherit the settings from its execution environment. </para> @@ -198,7 +205,7 @@ initdb --locale=sv_SE </sect2> <sect2> - <title>Behavior</> + <title>Behavior</title> <para> The locale settings influence the following SQL features: @@ -214,17 +221,21 @@ initdb --locale=sv_SE <listitem> <para> - The ability to use indexes with <literal>LIKE</> clauses - <indexterm><primary>LIKE</><secondary>and locales</></indexterm> + The <function>upper</>, <function>lower</>, and <function>initcap</> + functions + <indexterm><primary>upper</><secondary>and locales</></indexterm> + <indexterm><primary>lower</><secondary>and locales</></indexterm> </para> </listitem> <listitem> <para> - The <function>upper</>, <function>lower</>, and <function>initcap</> - functions - <indexterm><primary>upper</><secondary>and locales</></indexterm> - <indexterm><primary>lower</><secondary>and locales</></indexterm> + Pattern matching operators (<literal>LIKE</>, <literal>SIMILAR TO</>, + and POSIX-style regular expressions); locales affect both case + insensitive matching and the classification of characters by + character-class regular expressions + <indexterm><primary>LIKE</><secondary>and locales</></indexterm> + <indexterm><primary>regular expressions</><secondary>and locales</></indexterm> </para> </listitem> @@ -234,6 +245,12 @@ initdb --locale=sv_SE <indexterm><primary>to_char</><secondary>and locales</></indexterm> </para> </listitem> + + <listitem> + <para> + The ability to use indexes with <literal>LIKE</> clauses + </para> + </listitem> </itemizedlist> </para> @@ -251,12 +268,14 @@ initdb --locale=sv_SE operator classes exist. These allow the creation of an index that performs a strict character-by-character comparison, ignoring locale comparison rules. Refer to <xref linkend="indexes-opclass"> - for more information. + for more information. Another approach is to create indexes using + the <literal>C</> collation, as discussed in + <xref linkend="collation">. </para> </sect2> <sect2> - <title>Problems</> + <title>Problems</title> <para> If locale support doesn't work according to the explanation above, @@ -304,6 +323,267 @@ initdb --locale=sv_SE </sect1> + <sect1 id="collation"> + <title>Collation Support</title> + + <indexterm zone="collation"><primary>collation</></> + + <para> + The collation feature allows specifying the sort order and character + classification behavior of data per-column, or even per-operation. + This alleviates the restriction that the + <symbol>LC_COLLATE</symbol> and <symbol>LC_CTYPE</symbol> settings + of a database cannot be changed after its creation. + </para> + + <sect2> + <title>Concepts</title> + + <para> + Conceptually, every expression of a collatable data type has a + collation. (The built-in collatable data types are + <type>text</type>, <type>varchar</type>, and <type>char</type>. + User-defined base types can also be marked collatable, and of course + a domain over a collatable data type is collatable.) If the + expression is a column reference, the collation of the expression is the + defined collation of the column. If the expression is a constant, the + collation is the default collation of the data type of the + constant. The collation of a more complex expression is derived + from the collations of its inputs, as described below. + </para> + + <para> + The collation of an expression can be the <quote>default</quote> + collation, which means the locale settings defined for the + database. It is also possible for an expression's collation to be + indeterminate. In such cases, ordering operations and other + operations that need to know the collation will fail. + </para> + + <para> + When the database system has to perform an ordering or a character + classification, it uses the collation of the input expression. This + happens, for example, with <literal>ORDER BY</literal> clauses + and function or operator calls such as <literal><</literal>. + The collation to apply for an <literal>ORDER BY</literal> clause + is simply the collation of the sort key. The collation to apply for a + function or operator call is derived from the arguments, as described + below. In addition to comparison operators, collations are taken into + account by functions that convert between lower and upper case + letters, such as <function>lower</>, <function>upper</>, and + <function>initcap</>; by pattern matching operators; and by + <function>to_char</> and related functions. + </para> + + <para> + For a function or operator call, the collation that is derived by + examining the argument collations is used at run time for performing + the specified operation. If the result of the function or operator + call is of a collatable data type, the collation is also used at parse + time as the defined collation of the function or operator expression, + in case there is a surrounding expression that requires knowledge of + its collation. + </para> + + <para> + The <firstterm>collation derivation</firstterm> of an expression can be + implicit or explicit. This distinction affects how collations are + combined when multiple different collations appear in an + expression. An explicit collation derivation occurs when a + <literal>COLLATE</literal> clause is used; all other collation + derivations are implicit. When multiple collations need to be + combined, for example in a function call, the following rules are + used: + + <orderedlist> + <listitem> + <para> + If any input expression has an explicit collation derivation, then + all explicitly derived collations among the input expressions must be + the same, otherwise an error is raised. If any explicitly + derived collation is present, that is the result of the + collation combination. + </para> + </listitem> + + <listitem> + <para> + Otherwise, all input expressions must have the same implicit + collation derivation or the default collation. If any non-default + collation is present, that is the result of the collation combination. + Otherwise, the result is the default collation. + </para> + </listitem> + + <listitem> + <para> + If there are conflicting non-default implicit collations among the + input expressions, then the combination is deemed to have indeterminate + collation. This is not an error condition unless the particular + function being invoked requires knowledge of the collation it should + apply. If it does, an error will be raised at run-time. + </para> + </listitem> + </orderedlist> + + For example, consider this table definition: +<programlisting> +CREATE TABLE test1 ( + a text COLLATE "de_DE", + b text COLLATE "es_ES", + ... +); +</programlisting> + + Then in +<programlisting> +SELECT a < 'foo' FROM test1; +</programlisting> + the <literal><</literal> comparison is performed according to + <literal>de_DE</literal> rules, because the expression combines an + implicitly derived collation with the default collation. But in +<programlisting> +SELECT a < ('foo' COLLATE "fr_FR") FROM test1; +</programlisting> + the comparison is performed using <literal>fr_FR</literal> rules, + because the explicit collation derivation overrides the implicit one. + Furthermore, given +<programlisting> +SELECT a < b FROM test1; +</programlisting> + the parser cannot determine which collation to apply, since the + <structfield>a</> and <structfield>b</> columns have conflicting + implicit collations. Since the <literal><</literal> operator + does need to know which collation to use, this will result in an + error. The error can be resolved by attaching an explicit collation + specifier to either input expression, thus: +<programlisting> +SELECT a < b COLLATE "de_DE" FROM test1; +</programlisting> + or equivalently +<programlisting> +SELECT a COLLATE "de_DE" < b FROM test1; +</programlisting> + On the other hand, the structurally similar case +<programlisting> +SELECT a || b FROM test1; +</programlisting> + does not result in an error, because the <literal>||</> operator + does not care about collations: its result is the same regardless + of the collation. + </para> + + <para> + The collation assigned to a function or operator's combined input + expressions is also considered to apply to the function or operator's + result, if the function or operator delivers a result of a collatable + data type. So, in +<programlisting> +SELECT * FROM test1 ORDER BY a || 'foo'; +</programlisting> + the ordering will be done according to <literal>de_DE</literal> rules. + But this query: +<programlisting> +SELECT * FROM test1 ORDER BY a || b; +</programlisting> + results in an error, because even though the <literal>||</> operator + doesn't need to know a collation, the <literal>ORDER BY</> clause does. + As before, the conflict can be resolved with an explicit collation + specifier: +<programlisting> +SELECT * FROM test1 ORDER BY a || b COLLATE "fr_FR"; +</programlisting> + </para> + </sect2> + + <sect2> + <title>Managing Collations</title> + + <para> + A collation is an SQL schema object that maps an SQL name to + operating system locales. In particular, it maps to a combination + of <symbol>LC_COLLATE</symbol> and <symbol>LC_CTYPE</symbol>. (As + the name would suggest, the main purpose of a collation is to set + <symbol>LC_COLLATE</symbol>, which controls the sort order. But + it is rarely necessary in practice to have an + <symbol>LC_CTYPE</symbol> setting that is different from + <symbol>LC_COLLATE</symbol>, so it is more convenient to collect + these under one concept than to create another infrastructure for + setting <symbol>LC_CTYPE</symbol> per expression.) Also, a collation + is tied to a character set encoding (see <xref linkend="multibyte">). + The same collation name may exist for different encodings. + </para> + + <para> + On all platforms, the collations named <literal>default</>, + <literal>C</>, and <literal>POSIX</> are available. Additional + collations may be available depending on operating system support. + The <literal>default</> collation selects the <symbol>LC_COLLATE</symbol> + and <symbol>LC_CTYPE</symbol> values specified at database creation time. + The <literal>C</> and <literal>POSIX</> collations both specify + <quote>traditional C</> behavior, in which only the ASCII letters + <quote><literal>A</></quote> through <quote><literal>Z</></quote> + are treated as letters, and sorting is done strictly by character + code byte values. + </para> + + <para> + If the operating system provides support for using multiple locales + within a single program (<function>newlocale</> and related functions), + then when a database cluster is initialized, <command>initdb</command> + populates the system catalog <literal>pg_collation</literal> with + collations based on all the locales it finds on the operating + system at the time. For example, the operating system might + provide a locale named <literal>de_DE.utf8</literal>. + <command>initdb</command> would then create a collation named + <literal>de_DE.utf8</literal> for encoding <literal>UTF8</literal> + that has both <symbol>LC_COLLATE</symbol> and + <symbol>LC_CTYPE</symbol> set to <literal>de_DE.utf8</literal>. + It will also create a collation with the <literal>.utf8</literal> + tag stripped off the name. So you could also use the collation + under the name <literal>de_DE</literal>, which is less cumbersome + to write and makes the name less encoding-dependent. Note that, + nevertheless, the initial set of collation names is + platform-dependent. + </para> + + <para> + In case a collation is needed that has different values for + <symbol>LC_COLLATE</symbol> and <symbol>LC_CTYPE</symbol>, a new + collation may be created using + the <xref linkend="sql-createcollation"> command. That command + can also be used to create a new collation from an existing + collation, which can be useful to be able to use + operating-system-independent collation names in applications. + </para> + + <para> + Within any particular database, only collations that use that + database's encoding are of interest. Other entries in + <literal>pg_collation</literal> are ignored. Thus, a stripped collation + name such as <literal>de_DE</literal> can be considered unique + within a given database even though it would not be unique globally. + Use of the stripped collation names is recommendable, since it will + make one less thing you need to change if you decide to change to + another database encoding. Note however that the <literal>default</>, + <literal>C</>, and <literal>POSIX</> collations can be used + regardless of the database encoding. + </para> + + <para> + <productname>PostgreSQL</productname> considers distinct collation + objects to be incompatible even when they have identical properties. + Thus for example, +<programlisting> +SELECT a COLLATE "C" < b COLLATE "POSIX" FROM test1; +</programlisting> + will draw an error even though the <literal>C</> and <literal>POSIX</> + collations have identical behaviors. Mixing stripped and non-stripped + collation names is therefore not recommended. + </para> + </sect2> + </sect1> + <sect1 id="multibyte"> <title>Character Set Support</title> diff --git a/doc/src/sgml/chkpass.sgml b/doc/src/sgml/chkpass.sgml index 016ba92f86..9f682d8981 100644 --- a/doc/src/sgml/chkpass.sgml +++ b/doc/src/sgml/chkpass.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/chkpass.sgml,v 1.2 2007/12/06 04:12:09 tgl Exp $ --> +<!-- doc/src/sgml/chkpass.sgml --> -<sect1 id="chkpass"> +<sect1 id="chkpass" xreflabel="chkpass"> <title>chkpass</title> <indexterm zone="chkpass"> @@ -32,7 +32,7 @@ passwords without re-encrypting them. If you want the encrypted password without the colon then use the <function>raw()</> function. This allows you to use the - type with things like Apache's Auth_PostgreSQL module. + type with things like Apache's <literal>Auth_PostgreSQL</> module. </para> <para> @@ -43,7 +43,7 @@ </para> <para> - Note that the chkpass data type is not indexable. + Note that the <type>chkpass</type> data type is not indexable. <!-- I haven't worried about making this type indexable. I doubt that anyone would ever need to sort a file in order of encrypted password. diff --git a/doc/src/sgml/citext.sgml b/doc/src/sgml/citext.sgml index 49b0989815..0c6855fea6 100644 --- a/doc/src/sgml/citext.sgml +++ b/doc/src/sgml/citext.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/citext.sgml,v 1.4 2010/06/29 22:29:13 momjian Exp $ --> +<!-- doc/src/sgml/citext.sgml --> -<sect1 id="citext"> +<sect1 id="citext" xreflabel="citext"> <title>citext</title> <indexterm zone="citext"> @@ -22,9 +22,9 @@ in <productname>PostgreSQL</> has been to use the <function>lower</> function when comparing values, for example - <programlisting> - SELECT * FROM tab WHERE lower(col) = LOWER(?); - </programlisting> +<programlisting> +SELECT * FROM tab WHERE lower(col) = LOWER(?); +</programlisting> </para> <para> @@ -58,11 +58,11 @@ The <type>citext</> data type allows you to eliminate calls to <function>lower</> in SQL queries, and allows a primary key to be case-insensitive. <type>citext</> is locale-aware, just - like <type>text</>, which means that the comparison of upper case and + like <type>text</>, which means that the matching of upper case and lower case characters is dependent on the rules of - the <literal>LC_CTYPE</> locale setting. Again, this behavior is + the database's <literal>LC_CTYPE</> setting. Again, this behavior is identical to the use of <function>lower</> in queries. But because it's - done transparently by the datatype, you don't have to remember to do + done transparently by the data type, you don't have to remember to do anything special in your queries. </para> @@ -74,40 +74,48 @@ <para> Here's a simple example of usage: - <programlisting> - CREATE TABLE users ( - nick CITEXT PRIMARY KEY, - pass TEXT NOT NULL - ); +<programlisting> +CREATE TABLE users ( + nick CITEXT PRIMARY KEY, + pass TEXT NOT NULL +); - INSERT INTO users VALUES ( 'larry', md5(random()::text) ); - INSERT INTO users VALUES ( 'Tom', md5(random()::text) ); - INSERT INTO users VALUES ( 'Damian', md5(random()::text) ); - INSERT INTO users VALUES ( 'NEAL', md5(random()::text) ); - INSERT INTO users VALUES ( 'Bjørn', md5(random()::text) ); +INSERT INTO users VALUES ( 'larry', md5(random()::text) ); +INSERT INTO users VALUES ( 'Tom', md5(random()::text) ); +INSERT INTO users VALUES ( 'Damian', md5(random()::text) ); +INSERT INTO users VALUES ( 'NEAL', md5(random()::text) ); +INSERT INTO users VALUES ( 'Bjørn', md5(random()::text) ); - SELECT * FROM users WHERE nick = 'Larry'; - </programlisting> +SELECT * FROM users WHERE nick = 'Larry'; +</programlisting> The <command>SELECT</> statement will return one tuple, even though - the <structfield>nick</> column was set to <quote>larry</> and the query - was for <quote>Larry</>. + the <structfield>nick</> column was set to <literal>larry</> and the query + was for <literal>Larry</>. </para> </sect2> <sect2> <title>String Comparison Behavior</title> + + <para> + <type>citext</> performs comparisons by converting each string to lower + case (as though <function>lower</> were called) and then comparing the + results normally. Thus, for example, two strings are considered equal + if <function>lower</> would produce identical results for them. + </para> + <para> In order to emulate a case-insensitive collation as closely as possible, - there are <type>citext</>-specific versions of a number of the comparison + there are <type>citext</>-specific versions of a number of string-processing operators and functions. So, for example, the regular expression operators <literal>~</> and <literal>~*</> exhibit the same behavior when - applied to <type>citext</>: they both compare case-insensitively. + applied to <type>citext</>: they both match case-insensitively. The same is true for <literal>!~</> and <literal>!~*</>, as well as for the <literal>LIKE</> operators <literal>~~</> and <literal>~~*</>, and <literal>!~~</> and <literal>!~~*</>. If you'd like to match - case-sensitively, you can always cast to <type>text</> before comparing. + case-sensitively, you can cast the operator's arguments to <type>text</>. </para> <para> @@ -168,10 +176,10 @@ <itemizedlist> <listitem> <para> - <type>citext</>'s behavior depends on + <type>citext</>'s case-folding behavior depends on the <literal>LC_CTYPE</> setting of your database. How it compares - values is therefore determined when - <application>initdb</> is run to create the cluster. It is not truly + values is therefore determined when the database is created. + It is not truly case-insensitive in the terms defined by the Unicode standard. Effectively, what this means is that, as long as you're happy with your collation, you should be happy with <type>citext</>'s comparisons. But @@ -183,8 +191,22 @@ <listitem> <para> + As of <productname>PostgreSQL</> 9.1, you can attach a + <literal>COLLATE</> specification to <type>citext</> columns or data + values. Currently, <type>citext</> operators will honor a non-default + <literal>COLLATE</> specification while comparing case-folded strings, + but the initial folding to lower case is always done according to the + database's <literal>LC_CTYPE</> setting (that is, as though + <literal>COLLATE "default"</> were given). This may be changed in a + future release so that both steps follow the input <literal>COLLATE</> + specification. + </para> + </listitem> + + <listitem> + <para> <type>citext</> is not as efficient as <type>text</> because the - operator functions and the btree comparison functions must make copies + operator functions and the B-tree comparison functions must make copies of the data and convert it to lower case for comparisons. It is, however, slightly more efficient than using <function>lower</> to get case-insensitive matching. @@ -198,11 +220,11 @@ contexts. The standard answer is to use the <type>text</> type and manually use the <function>lower</> function when you need to compare case-insensitively; this works all right if case-insensitive comparison - is needed only infrequently. If you need case-insensitive most of - the time and case-sensitive infrequently, consider storing the data + is needed only infrequently. If you need case-insensitive behavior most + of the time and case-sensitive infrequently, consider storing the data as <type>citext</> and explicitly casting the column to <type>text</> - when you want case-sensitive comparison. In either situation, you - will need two indexes if you want both types of searches to be fast. + when you want case-sensitive comparison. In either situation, you will + need two indexes if you want both types of searches to be fast. </para> </listitem> @@ -210,8 +232,8 @@ <para> The schema containing the <type>citext</> operators must be in the current <varname>search_path</> (typically <literal>public</>); - if it is not, a normal case-sensitive <type>text</> comparison - is performed. + if it is not, the normal case-sensitive <type>text</> operators + will be invoked instead. </para> </listitem> </itemizedlist> diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 0afaa820e9..77c541b6cb 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.139 2010/06/29 22:29:13 momjian Exp $ --> +<!-- doc/src/sgml/client-auth.sgml --> <chapter id="client-authentication"> <title>Client Authentication</title> @@ -48,13 +48,14 @@ runs. If all the users of a particular server also have accounts on the server's machine, it makes sense to assign database user names that match their operating system user names. However, a server that - accepts remote connections might have many database users who have no local operating system + accepts remote connections might have many database users who have no local + operating system account, and in such cases there need be no connection between database user names and OS user names. </para> <sect1 id="auth-pg-hba-conf"> - <title>The <filename>pg_hba.conf</filename> file</title> + <title>The <filename>pg_hba.conf</filename> File</title> <indexterm zone="auth-pg-hba-conf"> <primary>pg_hba.conf</primary> @@ -80,9 +81,9 @@ A record is made up of a number of fields which are separated by spaces and/or tabs. Fields can contain white space if the field value is quoted. - Quoting one of the keywords in a database or username field (e.g., + Quoting one of the keywords in a database, user, or address field (e.g., <literal>all</> or <literal>replication</>) makes the word lose its special - character, and just match a database or user with that name. + character, and just match a database, user, or host with that name. </para> <para> @@ -101,9 +102,9 @@ A record can have one of the seven formats <synopsis> local <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional> -host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>CIDR-address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional> -hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>CIDR-address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional> -hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>CIDR-address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional> +host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional> +hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional> +hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional> host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional> hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional> hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional> @@ -218,13 +219,17 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> </varlistentry> <varlistentry> - <term><replaceable>CIDR-address</replaceable></term> + <term><replaceable>address</replaceable></term> <listitem> <para> - Specifies the client machine IP address range that this record - matches. This field contains an IP address in standard dotted decimal - notation and a <acronym>CIDR</> mask length. (IP addresses can only be - specified numerically, not as domain or host names.) The mask + Specifies the client machine addresses that this record + matches. This field can contain either a host name, an IP + address range, or one of the special key words mentioned below. + </para> + + <para> + An IP address is specified in standard dotted decimal + notation with a <acronym>CIDR</> mask length. The mask length indicates the number of high-order bits of the client IP address that must match. Bits to the right of this must be zero in the given IP address. @@ -233,18 +238,13 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> </para> <para> - Instead of a <replaceable>CIDR-address</replaceable>, you can write - <literal>samehost</literal> to match any of the server's own IP - addresses, or <literal>samenet</literal> to match any address in any - subnet that the server is directly connected to. - </para> - - <para> - Typical examples of a <replaceable>CIDR-address</replaceable> are + Typical examples of an IP address range specified this way are <literal>172.20.143.89/32</literal> for a single host, or <literal>172.20.143.0/24</literal> for a small network, or <literal>10.6.0.0/16</literal> for a larger one. - <literal>0.0.0.0/0</literal> (<quote>all balls</>) represents all addresses. + <literal>0.0.0.0/0</literal> represents all + IPv4 addresses, and <literal>::/0</literal> represents + all IPv6 addresses. To specify a single host, use a CIDR mask of 32 for IPv4 or 128 for IPv6. In a network address, do not omit trailing zeroes. </para> @@ -260,6 +260,81 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> </para> <para> + You can also write <literal>all</literal> to match any IP address, + <literal>samehost</literal> to match any of the server's own IP + addresses, or <literal>samenet</literal> to match any address in any + subnet that the server is directly connected to. + </para> + + <para> + If a host name is specified (anything that is not an IP address + or a special key word is processed as a potential host name), + that name is compared with the result of a reverse name + resolution of the client's IP address (e.g., reverse DNS + lookup, if DNS is used). Host name comparisons are case + insensitive. If there is a match, then a forward name + resolution (e.g., forward DNS lookup) is performed on the host + name to check whether any of the addresses it resolves to are + equal to the client's IP address. If both directions match, + then the entry is considered to match. (The host name that is + used in <filename>pg_hba.conf</filename> should be the one that + address-to-name resolution of the client's IP address returns, + otherwise the line won't be matched. Some host name databases + allow associating an IP address with multiple host names, but + the operating system will only return one host name when asked + to resolve an IP address.) + </para> + + <para> + A host name specification that starts with a dot + (<literal>.</literal>) matches a suffix of the actual host + name. So <literal>.example.com</literal> would match + <literal>foo.example.com</literal> (but not just + <literal>example.com</literal>). + </para> + + <para> + When host names are specified + in <filename>pg_hba.conf</filename>, you should make sure that + name resolution is reasonably fast. It can be of advantage to + set up a local name resolution cache such + as <command>nscd</command>. Also, you may wish to enable the + configuration parameter <varname>log_hostname</varname> to see + the client's host name instead of the IP address in the log. + </para> + + <sidebar> + <para> + Occasionally, users have wondered why host names are handled + in this seemingly complicated way with two name resolutions + and requiring reverse lookup of IP addresses, which is + sometimes not set up or points to some undesirable host name. + It is primarily for efficiency: A connection attempt requires + two resolver lookups of the current client's address. If + there is resolver problem with that address, it becomes only + that client's problem. A hypothetical alternative + implementation which only does forward lookups would have to + resolve every host name mentioned in + <filename>pg_hba.conf</filename> at every connection attempt. + That would already be slow by itself. And if there is a + resolver problem with one of the host names, it becomes + everyone's problem. + </para> + + <para> + Also, a reverse lookup is necessary to implement the suffix + matching feature, because the actual client host name needs to + be known in order to match it against the pattern. + </para> + + <para> + Note that this behavior is consistent with other popular + implementations of host name-based access control, such as the + Apache HTTP Server and TCP Wrappers. + </para> + </sidebar> + + <para> This field only applies to <literal>host</literal>, <literal>hostssl</literal>, and <literal>hostnossl</> records. </para> @@ -383,17 +458,30 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <term><literal>ident</></term> <listitem> <para> - Obtain the operating system user name of the client (for - TCP/IP connections by contacting the ident server on the - client, for local connections by getting it from the - operating system) and check if it matches the requested - database user name. + Obtain the operating system user name of the client + by contacting the ident server on the client + and check if it matches the requested database user name. + Ident authentication can only be used on TCP/IP + connections. When specified for local connections, peer + authentication will be used instead. See <xref linkend="auth-ident"> for details. </para> </listitem> </varlistentry> <varlistentry> + <term><literal>peer</></term> + <listitem> + <para> + Obtain the client's operating system user name from the operating + system and check if it matches the requested database user name. + This is only available for local connections. + See <xref linkend="auth-peer"> for details. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><literal>ldap</></term> <listitem> <para> @@ -505,18 +593,18 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> </para> <example id="example-pg-hba.conf"> - <title>Example <filename>pg_hba.conf</filename> entries</title> + <title>Example <filename>pg_hba.conf</filename> Entries</title> <programlisting> # Allow any user on the local system to connect to any database with # any database user name using Unix-domain sockets (the default for local # connections). # -# TYPE DATABASE USER CIDR-ADDRESS METHOD +# TYPE DATABASE USER ADDRESS METHOD local all all trust # The same using local loopback TCP/IP connections. # -# TYPE DATABASE USER CIDR-ADDRESS METHOD +# TYPE DATABASE USER ADDRESS METHOD host all all 127.0.0.1/32 trust # The same as the previous line, but using a separate netmask column @@ -524,26 +612,42 @@ host all all 127.0.0.1/32 trust # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD host all all 127.0.0.1 255.255.255.255 trust +# The same over IPv6. +# +# TYPE DATABASE USER ADDRESS METHOD +host all all ::1/128 trust + +# The same using a host name (would typically cover both IPv4 and IPv6). +# +# TYPE DATABASE USER ADDRESS METHOD +host all all localhost trust + # Allow any user from any host with IP address 192.168.93.x to connect # to database "postgres" as the same user name that ident reports for # the connection (typically the operating system user name). # -# TYPE DATABASE USER CIDR-ADDRESS METHOD +# TYPE DATABASE USER ADDRESS METHOD host postgres all 192.168.93.0/24 ident # Allow any user from host 192.168.12.10 to connect to database # "postgres" if the user's password is correctly supplied. # -# TYPE DATABASE USER CIDR-ADDRESS METHOD +# TYPE DATABASE USER ADDRESS METHOD host postgres all 192.168.12.10/32 md5 +# Allow any user from hosts in the example.com domain to connect to +# any database if the user's password is correctly supplied. +# +# TYPE DATABASE USER ADDRESS METHOD +host all all .example.com md5 + # In the absence of preceding "host" lines, these two lines will # reject all connections from 192.168.54.1 (since that entry will be # matched first), but allow Kerberos 5 connections from anywhere else # on the Internet. The zero mask causes no bits of the host IP # address to be considered, so it matches any host. # -# TYPE DATABASE USER CIDR-ADDRESS METHOD +# TYPE DATABASE USER ADDRESS METHOD host all all 192.168.54.1/32 reject host all all 0.0.0.0/0 krb5 @@ -553,7 +657,7 @@ host all all 0.0.0.0/0 krb5 # connection is allowed if there is an entry in pg_ident.conf for map # "omicron" that says "bryanh" is allowed to connect as "guest1". # -# TYPE DATABASE USER CIDR-ADDRESS METHOD +# TYPE DATABASE USER ADDRESS METHOD host all all 192.168.0.0/16 ident map=omicron # If these are the only three lines for local connections, they will @@ -563,7 +667,7 @@ host all all 192.168.0.0/16 ident map=omicro # $PGDATA/admins contains a list of names of administrators. Passwords # are required in all cases. # -# TYPE DATABASE USER CIDR-ADDRESS METHOD +# TYPE DATABASE USER ADDRESS METHOD local sameuser all md5 local all @admins md5 local all +support md5 @@ -578,10 +682,10 @@ local db1,db2,@demodbs all md5 </sect1> <sect1 id="auth-username-maps"> - <title>Username maps</title> + <title>User Name Maps</title> <indexterm zone="auth-username-maps"> - <primary>Username maps</primary> + <primary>User name maps</primary> </indexterm> <para> @@ -589,10 +693,10 @@ local db1,db2,@demodbs all md5 the name of the operating system user that initiated the connection might not be the same as the database user he needs to connect as. In this case, a user name map can be applied to map the operating system - username to a database user. To use username mapping, specify + user name to a database user. To use user name mapping, specify <literal>map</literal>=<replaceable>map-name</replaceable> in the options field in <filename>pg_hba.conf</filename>. This option is - supported for all authentication methods that receive external usernames. + supported for all authentication methods that receive external user names. Since different mappings might be needed for different connections, the name of the map to be used is specified in the <replaceable>map-name</replaceable> parameter in <filename>pg_hba.conf</filename> @@ -600,7 +704,7 @@ local db1,db2,@demodbs all md5 </para> <para> - Username maps are defined in the ident map file, which by default is named + User name maps are defined in the ident map file, which by default is named <filename>pg_ident.conf</><indexterm><primary>pg_ident.conf</primary></indexterm> and is stored in the cluster's data directory. (It is possible to place the map file @@ -636,13 +740,13 @@ local db1,db2,@demodbs all md5 expression can include a single capture, or parenthesized subexpression, which can then be referenced in the <replaceable>database-username</> field as <literal>\1</> (backslash-one). This allows the mapping of - multiple usernames in a single line, which is particularly useful for + multiple user names in a single line, which is particularly useful for simple syntax substitutions. For example, these entries <programlisting> mymap /^(.*)@mydomain\.com$ \1 mymap /^(.*)@otherdomain\.com$ guest </programlisting> - will remove the domain part for users with system usernames that end with + will remove the domain part for users with system user names that end with <literal>@mydomain.com</>, and allow any user whose system name ends with <literal>@otherdomain.com</> to log in as <literal>guest</>. </para> @@ -652,7 +756,7 @@ mymap /^(.*)@otherdomain\.com$ guest Keep in mind that by default, a regular expression can match just part of a string. It's usually wise to use <literal>^</> and <literal>$</>, as shown in the above example, to force the match to be to the entire - system username. + system user name. </para> </tip> @@ -683,7 +787,7 @@ mymap /^(.*)@otherdomain\.com$ guest </para> <example id="example-pg-ident.conf"> - <title>An example <filename>pg_ident.conf</> file</title> + <title>An Example <filename>pg_ident.conf</> File</title> <programlisting> # MAPNAME SYSTEM-USERNAME PG-USERNAME @@ -698,13 +802,13 @@ omicron bryanh guest1 </sect1> <sect1 id="auth-methods"> - <title>Authentication methods</title> + <title>Authentication Methods</title> <para> The following subsections describe the authentication methods in more detail. </para> <sect2 id="auth-trust"> - <title>Trust authentication</title> + <title>Trust Authentication</title> <para> When <literal>trust</> authentication is specified, @@ -752,7 +856,7 @@ omicron bryanh guest1 </sect2> <sect2 id="auth-password"> - <title>Password authentication</title> + <title>Password Authentication</title> <indexterm> <primary>MD5</> @@ -786,7 +890,7 @@ omicron bryanh guest1 each database user is stored in the <literal>pg_authid</> system catalog. Passwords can be managed with the SQL commands <xref linkend="sql-createuser"> and - <xref linkend="sql-alteruser">, + <xref linkend="sql-alterrole">, e.g., <userinput>CREATE USER foo WITH PASSWORD 'secret'</userinput>. If no password has been set up for a user, the stored password is null and password authentication will always fail for that user. @@ -795,7 +899,7 @@ omicron bryanh guest1 </sect2> <sect2 id="gssapi-auth"> - <title>GSSAPI authentication</title> + <title>GSSAPI Authentication</title> <indexterm zone="gssapi-auth"> <primary>GSSAPI</primary> @@ -833,9 +937,9 @@ omicron bryanh guest1 <term><literal>include_realm</literal></term> <listitem> <para> - If set to <literal>1</>, the realm name from the authenticated user + If set to 1, the realm name from the authenticated user principal is included in the system user name that's passed through - username mapping (<xref linkend="auth-username-maps">). This is + user name mapping (<xref linkend="auth-username-maps">). This is useful for handling users from multiple realms. </para> </listitem> @@ -845,10 +949,10 @@ omicron bryanh guest1 <term><literal>map</literal></term> <listitem> <para> - Allows for mapping between system and database usernames. See + Allows for mapping between system and database user names. See <xref linkend="auth-username-maps"> for details. For a Kerberos principal <literal>username/hostbased@EXAMPLE.COM</literal>, the - username used for mapping is <literal>username/hostbased</literal> + user name used for mapping is <literal>username/hostbased</literal> if <literal>include_realm</literal> is disabled, and <literal>username/hostbased@EXAMPLE.COM</literal> if <literal>include_realm</literal> is enabled. @@ -862,7 +966,7 @@ omicron bryanh guest1 <para> Sets the realm to match user principal names against. If this parameter is set, only users of that realm will be accepted. If it is not set, - users of any realm can connect, subject to whatever username mapping + users of any realm can connect, subject to whatever user name mapping is done. </para> </listitem> @@ -872,7 +976,7 @@ omicron bryanh guest1 </sect2> <sect2 id="sspi-auth"> - <title>SSPI authentication</title> + <title>SSPI Authentication</title> <indexterm zone="sspi-auth"> <primary>SSPI</primary> @@ -904,9 +1008,9 @@ omicron bryanh guest1 <term><literal>include_realm</literal></term> <listitem> <para> - If set to <literal>1</>, the realm name from the authenticated user + If set to 1, the realm name from the authenticated user principal is included in the system user name that's passed through - username mapping (<xref linkend="auth-username-maps">). This is + user name mapping (<xref linkend="auth-username-maps">). This is useful for handling users from multiple realms. </para> </listitem> @@ -916,7 +1020,7 @@ omicron bryanh guest1 <term><literal>map</literal></term> <listitem> <para> - Allows for mapping between system and database usernames. See + Allows for mapping between system and database user names. See <xref linkend="auth-username-maps"> for details. </para> </listitem> @@ -928,7 +1032,7 @@ omicron bryanh guest1 <para> Sets the realm to match user principal names against. If this parameter is set, only users of that realm will be accepted. If it is not set, - users of any realm can connect, subject to whatever username mapping + users of any realm can connect, subject to whatever user name mapping is done. </para> </listitem> @@ -938,7 +1042,7 @@ omicron bryanh guest1 </sect2> <sect2 id="kerberos-auth"> - <title>Kerberos authentication</title> + <title>Kerberos Authentication</title> <indexterm zone="kerberos-auth"> <primary>Kerberos</primary> @@ -1006,13 +1110,13 @@ omicron bryanh guest1 <para> Client principals must have their <productname>PostgreSQL</> database user name as their first component, for example - <literal>pgusername@realm</>. Alternatively, you can use a username + <literal>pgusername@realm</>. Alternatively, you can use a user name mapping to map from the first component of the principal name to the database user name. By default, the realm of the client is not checked by <productname>PostgreSQL</>. If you have cross-realm authentication enabled and need to verify the realm, use the <literal>krb_realm</> parameter, or enable <literal>include_realm</> - and use username mapping to check the realm. + and use user name mapping to check the realm. </para> <para> @@ -1041,7 +1145,7 @@ omicron bryanh guest1 principal matching the requested database user name. For example, for database user name <literal>fred</>, principal <literal>fred@EXAMPLE.COM</> would be able to connect. To also allow - principal <literal>fred/users.example.com@EXAMPLE.COM</>, use a username + principal <literal>fred/users.example.com@EXAMPLE.COM</>, use a user name map, as described in <xref linkend="auth-username-maps">. </para> @@ -1063,7 +1167,7 @@ omicron bryanh guest1 <term><literal>map</literal></term> <listitem> <para> - Allows for mapping between system and database usernames. See + Allows for mapping between system and database user names. See <xref linkend="auth-username-maps"> for details. </para> </listitem> @@ -1073,9 +1177,9 @@ omicron bryanh guest1 <term><literal>include_realm</literal></term> <listitem> <para> - If set to <literal>1</>, the realm name from the authenticated user + If set to 1, the realm name from the authenticated user principal is included in the system user name that's passed through - username mapping (<xref linkend="auth-username-maps">). This is + user name mapping (<xref linkend="auth-username-maps">). This is useful for handling users from multiple realms. </para> </listitem> @@ -1087,7 +1191,7 @@ omicron bryanh guest1 <para> Sets the realm to match user principal names against. If this parameter is set, only users of that realm will be accepted. If it is not set, - users of any realm can connect, subject to whatever username mapping + users of any realm can connect, subject to whatever user name mapping is done. </para> </listitem> @@ -1110,7 +1214,7 @@ omicron bryanh guest1 </sect2> <sect2 id="auth-ident"> - <title>Ident-based authentication</title> + <title>Ident Authentication</title> <indexterm> <primary>ident</primary> @@ -1118,13 +1222,19 @@ omicron bryanh guest1 <para> The ident authentication method works by obtaining the client's - operating system user name and using it as the allowed database user - name (with an optional username mapping). - The determination of the client's - user name is the security-critical point, and it works differently - depending on the connection type, as described below. + operating system user name from an ident server and using it as + the allowed database user name (with an optional user name mapping). + This is only supported on TCP/IP connections. </para> + <note> + <para> + When ident is specified for a local (non-TCP/IP) connection, + peer authentication (see <xref linkend="auth-peer">) will be + used instead. + </para> + </note> + <para> The following configuration options are supported for <productname>ident</productname>: <variablelist> @@ -1132,7 +1242,7 @@ omicron bryanh guest1 <term><literal>map</literal></term> <listitem> <para> - Allows for mapping between system and database usernames. See + Allows for mapping between system and database user names. See <xref linkend="auth-username-maps"> for details. </para> </listitem> @@ -1140,9 +1250,6 @@ omicron bryanh guest1 </variablelist> </para> - <sect3> - <title>Ident Authentication over TCP/IP</title> - <para> The <quote>Identification Protocol</quote> is described in RFC 1413. Virtually every Unix-like @@ -1185,40 +1292,51 @@ omicron bryanh guest1 since <productname>PostgreSQL</> does not have any way to decrypt the returned string to determine the actual user name. </para> - </sect3> + </sect2> - <sect3> - <title>Ident Authentication over Local Sockets</title> + <sect2 id="auth-peer"> + <title>Peer Authentication</title> + + <indexterm> + <primary>peer</primary> + </indexterm> <para> - On systems supporting <symbol>SO_PEERCRED</symbol> requests for - Unix-domain sockets (currently <systemitem - class="osname">Linux</>, <systemitem class="osname">FreeBSD</>, - <systemitem class="osname">NetBSD</>, <systemitem class="osname">OpenBSD</>, - <systemitem class="osname">BSD/OS</>, and <systemitem class="osname">Solaris</systemitem>), ident authentication can also - be applied to local connections. - <productname>PostgreSQL</> uses <symbol>SO_PEERCRED</symbol> to find out - the operating system name of the connected client process. - In this case, no security risk is added by - using ident authentication; indeed it is a preferable choice for - local connections on such systems. + The peer authentication method works by obtaining the client's + operating system user name from the kernel and using it as the + allowed database user name (with optional user name mapping). This + method is only supported on local connections. </para> - <para> - On systems without <symbol>SO_PEERCRED</> requests, ident - authentication is only available for TCP/IP connections. As a - work-around, it is possible to specify the <systemitem - class="systemname">localhost</> address <systemitem - class="systemname">127.0.0.1</> and make connections to this - address. This method is trustworthy to the extent that you trust - the local ident server. - </para> - </sect3> + <para> + The following configuration options are supported for <productname>peer</productname>: + <variablelist> + <varlistentry> + <term><literal>map</literal></term> + <listitem> + <para> + Allows for mapping between system and database user names. See + <xref linkend="auth-username-maps"> for details. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <para> + Peer authentication is only available on operating systems providing + the <function>getpeereid()</> function, the <symbol>SO_PEERCRED</symbol> + socket parameter, or similar mechanisms. Currently that includes + <systemitem class="osname">Linux</>, + most flavors of <systemitem class="osname">BSD</> including + <systemitem class="osname">Mac OS X</>, + and <systemitem class="osname">Solaris</systemitem>. + </para> </sect2> <sect2 id="auth-ldap"> - <title>LDAP authentication</title> + <title>LDAP Authentication</title> <indexterm zone="auth-ldap"> <primary>LDAP</primary> @@ -1245,7 +1363,7 @@ omicron bryanh guest1 <para> In the second mode, the server first binds to the LDAP directory with - a fixed username and password, specified with <replaceable>ldapbinduser</> + a fixed user name and password, specified with <replaceable>ldapbinduser</> and <replaceable>ldapbinddn</>, and performs a search for the user trying to log in to the database. If no user and password is configured, an anonymous bind will be attempted to the directory. The search will be @@ -1284,7 +1402,7 @@ omicron bryanh guest1 <term><literal>ldaptls</literal></term> <listitem> <para> - Set to <literal>1</> to make the connection between PostgreSQL and the + Set to 1 to make the connection between PostgreSQL and the LDAP server use TLS encryption. Note that this only encrypts the traffic to the LDAP server — the connection to the client will still be unencrypted unless SSL is used. @@ -1295,7 +1413,7 @@ omicron bryanh guest1 <term><literal>ldapprefix</literal></term> <listitem> <para> - String to prepend to the username when forming the DN to bind as, + String to prepend to the user name when forming the DN to bind as, when doing simple bind authentication. </para> </listitem> @@ -1304,7 +1422,7 @@ omicron bryanh guest1 <term><literal>ldapsuffix</literal></term> <listitem> <para> - String to append to the username when forming the DN to bind as, + String to append to the user name when forming the DN to bind as, when doing simple bind authentication. </para> </listitem> @@ -1340,7 +1458,7 @@ omicron bryanh guest1 <term><literal>ldapsearchattribute</literal></term> <listitem> <para> - Attribute to match against the username in the search when doing + Attribute to match against the user name in the search when doing search+bind authentication. </para> </listitem> @@ -1353,16 +1471,16 @@ omicron bryanh guest1 Since LDAP often uses commas and spaces to separate the different parts of a DN, it is often necessary to use double-quoted parameter values when configuring LDAP options, for example: +<programlisting> +ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net" +</programlisting> </para> </note> - <synopsis> -ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net" - </synopsis> </sect2> <sect2 id="auth-radius"> - <title>RADIUS authentication</title> + <title>RADIUS Authentication</title> <indexterm zone="auth-radius"> <primary>RADIUS</primary> @@ -1451,7 +1569,7 @@ ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net" </sect2> <sect2 id="auth-cert"> - <title>Certificate authentication</title> + <title>Certificate Authentication</title> <indexterm zone="auth-cert"> <primary>Certificate</primary> @@ -1464,9 +1582,9 @@ ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net" the client provide a valid certificate. No password prompt will be sent to the client. The <literal>cn</literal> (Common Name) attribute of the certificate - will be compared to the requested database username, and if they match - the login will be allowed. Username mapping can be used to allow - <literal>cn</literal> to be different from the database username. + will be compared to the requested database user name, and if they match + the login will be allowed. User name mapping can be used to allow + <literal>cn</literal> to be different from the database user name. </para> <para> @@ -1477,7 +1595,7 @@ ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net" <term><literal>map</literal></term> <listitem> <para> - Allows for mapping between system and database usernames. See + Allows for mapping between system and database user names. See <xref linkend="auth-username-maps"> for details. </para> </listitem> @@ -1487,7 +1605,7 @@ ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net" </sect2> <sect2 id="auth-pam"> - <title>PAM authentication</title> + <title>PAM Authentication</title> <indexterm zone="auth-pam"> <primary>PAM</primary> @@ -1533,7 +1651,7 @@ ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net" </sect1> <sect1 id="client-authentication-problems"> - <title>Authentication problems</title> + <title>Authentication Problems</title> <para> Authentication failures and related problems generally diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 2fbe6a8c24..39819695d1 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.294 2010/07/08 10:20:13 mha Exp $ --> +<!-- doc/src/sgml/config.sgml --> -<chapter Id="runtime-config"> +<chapter id="runtime-config"> <title>Server Configuration</title> <indexterm> @@ -135,7 +135,7 @@ env PGOPTIONS='-c geqo=off' psql Furthermore, it is possible to assign a set of parameter settings to a user or a database. Whenever a session is started, the default settings for the user and database involved are loaded. The - commands <xref linkend="sql-alteruser"> + commands <xref linkend="sql-alterrole"> and <xref linkend="sql-alterdatabase">, respectively, are used to configure these settings. Per-database settings override anything received from the @@ -166,10 +166,12 @@ SET ENABLE_SEQSCAN TO OFF; </para> <para> - The virtual table <structname>pg_settings</structname> - (described in <xref linkend="view-pg-settings">) also allows - displaying and updating session run-time parameters. It is equivalent - to <command>SHOW</> and <command>SET</>, but can be more convenient + The virtual table <structname>pg_settings</structname> also allows + displaying and updating session run-time parameters; see <xref + linkend="view-pg-settings"> for details and a description of the + different variable types and when they can be changed. + <structname>pg_settings</structname> is equivalent to <command>SHOW</> + and <command>SET</>, but can be more convenient to use because it can be joined with other tables, or selected from using any desired selection condition. It also contains more information about what values are allowed for the parameters. @@ -243,7 +245,7 @@ SET ENABLE_SEQSCAN TO OFF; <listitem> <para> Specifies the configuration file for - <xref linkend="auth-username-maps"> username mapping + <xref linkend="auth-username-maps"> user name mapping (customarily called <filename>pg_ident.conf</>). This parameter can only be set at server start. </para> @@ -324,7 +326,9 @@ SET ENABLE_SEQSCAN TO OFF; to listen for connections from client applications. The value takes the form of a comma-separated list of host names and/or numeric IP addresses. The special entry <literal>*</> - corresponds to all available IP interfaces. + corresponds to all available IP interfaces. The entry + <literal>0.0.0.0</> allows listening for all IPv4 addresses and + <literal>::</> allows listening for all IPv6 addresses. If the list is empty, the server does not listen on any IP interface at all, in which case only Unix-domain sockets can be used to connect to it. @@ -426,6 +430,20 @@ SET ENABLE_SEQSCAN TO OFF; <filename>/tmp</filename>, but can be changed at build time. This parameter can only be set at server start. </para> + + <para> + In addition to the socket file itself, which is named + <literal>.s.PGSQL.<replaceable>nnnn</></literal> where + <replaceable>nnnn</> is the server's port number, an ordinary file + named <literal>.s.PGSQL.<replaceable>nnnn</>.lock</literal> will be + created in the <varname>unix_socket_directory</> directory. Neither + file should ever be removed manually. + </para> + + <para> + This parameter is irrelevant on Windows, which does not have + Unix-domain sockets. + </para> </listitem> </varlistentry> @@ -445,6 +463,11 @@ SET ENABLE_SEQSCAN TO OFF; group of the server user. This parameter can only be set at server start. </para> + + <para> + This parameter is irrelevant on Windows, which does not have + Unix-domain sockets. + </para> </listitem> </varlistentry> @@ -482,6 +505,11 @@ SET ENABLE_SEQSCAN TO OFF; <para> This parameter can only be set at server start. </para> + + <para> + This parameter is irrelevant on Windows, which does not have + Unix-domain sockets. + </para> </listitem> </varlistentry> @@ -523,18 +551,19 @@ SET ENABLE_SEQSCAN TO OFF; </indexterm> <listitem> <para> - Specifies the number of seconds before sending a keepalive packet on an otherwise idle - connection. A value of 0 uses the system default. This parameter is supported - only on systems that support the <symbol>TCP_KEEPIDLE</> or <symbol>TCP_KEEPALIVE</> - symbols, and on Windows; on other systems, it must be zero. This parameter is - ignored for connections made via a Unix-domain socket. - <note> - <para> - On Windows, a value of 0 will set this parameter to 2 hours, - since Windows does not provide a way to read the default value. - </para> - </note> + Specifies the number of seconds before sending a keepalive packet on + an otherwise idle connection. A value of 0 uses the system default. + This parameter is supported only on systems that support the + <symbol>TCP_KEEPIDLE</> or <symbol>TCP_KEEPALIVE</> symbols, and on + Windows; on other systems, it must be zero. This parameter is ignored + for connections made via a Unix-domain socket. </para> + <note> + <para> + On Windows, a value of 0 will set this parameter to 2 hours, + since Windows does not provide a way to read the system default value. + </para> + </note> </listitem> </varlistentry> @@ -545,18 +574,19 @@ SET ENABLE_SEQSCAN TO OFF; </indexterm> <listitem> <para> - Specifies the number of seconds between sending keepalives on an otherwise idle - connection. A value of 0 uses the system default. This parameter is supported - only on systems that support the <symbol>TCP_KEEPINTVL</> - symbol, and on Windows; on other systems, it must be zero. This parameter is - ignored for connections made via a Unix-domain socket. - <note> - <para> - On Windows, a value of 0 will set this parameter to 1 second, - since Windows does not provide a way to read the default value. - </para> - </note> + Specifies the number of seconds between sending keepalives on an + otherwise idle connection. A value of 0 uses the system default. + This parameter is supported only on systems that support the + <symbol>TCP_KEEPINTVL</> symbol, and on Windows; on other systems, it + must be zero. This parameter is ignored for connections made via a + Unix-domain socket. </para> + <note> + <para> + On Windows, a value of 0 will set this parameter to 1 second, + since Windows does not provide a way to read the system default value. + </para> + </note> </listitem> </varlistentry> @@ -568,16 +598,16 @@ SET ENABLE_SEQSCAN TO OFF; <listitem> <para> Specifies the number of keepalive packets to send on an otherwise idle - connection. A value of 0 uses the system default. This parameter is supported - only on systems that support the <symbol>TCP_KEEPCNT</> - symbol; on other systems, it must be zero. This parameter is - ignored for connections made via a Unix-domain socket. - <note> - <para> - This parameter is not supported on Windows, and must be zero. - </para> - </note> + connection. A value of 0 uses the system default. This parameter is + supported only on systems that support the <symbol>TCP_KEEPCNT</> + symbol; on other systems, it must be zero. This parameter is ignored + for connections made via a Unix-domain socket. </para> + <note> + <para> + This parameter is not supported on Windows, and must be zero. + </para> + </note> </listitem> </varlistentry> @@ -675,7 +705,7 @@ SET ENABLE_SEQSCAN TO OFF; <para> When a password is specified in <xref linkend="sql-createuser"> or - <xref linkend="sql-alteruser"> + <xref linkend="sql-alterrole"> without writing either <literal>ENCRYPTED</> or <literal>UNENCRYPTED</>, this parameter determines whether the password is to be encrypted. The default is <literal>on</> @@ -692,7 +722,7 @@ SET ENABLE_SEQSCAN TO OFF; <listitem> <para> Sets the location of the Kerberos server key file. See - <xref linkend="kerberos-auth"> or <xref linkend="gssapi-auth"> + <xref linkend="kerberos-auth"> or <xref linkend="gssapi-auth"> for details. This parameter can only be set in the <filename>postgresql.conf</> file or on the server command line. </para> @@ -722,7 +752,7 @@ SET ENABLE_SEQSCAN TO OFF; <para> Sets whether Kerberos and GSSAPI user names should be treated case-insensitively. - The default is <literal>off</> (case sensitive). This parameter can only be + The default is <literal>off</> (case sensitive). This parameter can only be set in the <filename>postgresql.conf</> file or on the server command line. </para> </listitem> @@ -1018,7 +1048,7 @@ SET ENABLE_SEQSCAN TO OFF; </para> </listitem> </varlistentry> - + <varlistentry id="guc-shared-preload-libraries" xreflabel="shared_preload_libraries"> <term><varname>shared_preload_libraries</varname> (<type>string</type>)</term> <indexterm> @@ -1050,7 +1080,7 @@ SET ENABLE_SEQSCAN TO OFF; when the library is first used. However, the time to start each new server process might increase slightly, even if that process never uses the library. So this parameter is recommended only for - libraries that will be used in most sessions. + libraries that will be used in most sessions. </para> <note> @@ -1058,7 +1088,7 @@ SET ENABLE_SEQSCAN TO OFF; On Windows hosts, preloading a library at server start will not reduce the time required to start each new server process; each server process will re-load all preload libraries. However, <varname>shared_preload_libraries - </varname> is still useful on Windows hosts because some shared libraries may + </varname> is still useful on Windows hosts because some shared libraries may need to perform certain operations that only take place at postmaster start (for example, a shared library may need to reserve lightweight locks or shared memory and you can't do that after the postmaster has started). @@ -1071,8 +1101,8 @@ SET ENABLE_SEQSCAN TO OFF; <para> Every PostgreSQL-supported library has a <quote>magic - block</> that is checked to guarantee compatibility. - For this reason, non-PostgreSQL libraries cannot be + block</> that is checked to guarantee compatibility. + For this reason, non-PostgreSQL libraries cannot be loaded in this way. </para> </listitem> @@ -1082,7 +1112,7 @@ SET ENABLE_SEQSCAN TO OFF; </sect2> <sect2 id="runtime-config-resource-vacuum-cost"> - <title>Cost-Based Vacuum Delay</title> + <title>Cost-based Vacuum Delay</title> <para> During the execution of <xref linkend="sql-vacuum"> @@ -1328,7 +1358,8 @@ SET ENABLE_SEQSCAN TO OFF; simultaneously. Raising this value will increase the number of I/O operations that any individual <productname>PostgreSQL</> session attempts to initiate in parallel. The allowed range is 1 to 1000, - or zero to disable issuance of asynchronous I/O requests. + or zero to disable issuance of asynchronous I/O requests. Currently, + this setting only affects bitmap heap scans. </para> <para> @@ -1433,18 +1464,19 @@ SET ENABLE_SEQSCAN TO OFF; <para> While turning off <varname>fsync</varname> is often a performance benefit, this can result in unrecoverable data corruption in - the event of an unexpected system shutdown or crash. Thus it - is only advisable to turn off <varname>fsync</varname> if + the event of a power failure or system crash. Thus it + is only advisable to turn off <varname>fsync</varname> if you can easily recreate your entire database from external data. </para> <para> Examples of safe circumstances for turning off - <varname>fsync</varname> include the initial loading a new + <varname>fsync</varname> include the initial loading of a new database cluster from a backup file, using a database cluster - for processing statistics on an hourly basis which is then - recreated, or for a reporting read-only database clone which + for processing a batch of data after which the database + will be thrown away and recreated, + or for a read-only database clone which gets recreated frequently and is not used for failover. High quality hardware alone is not a sufficient justification for turning off <varname>fsync</varname>. @@ -1460,7 +1492,7 @@ SET ENABLE_SEQSCAN TO OFF; <para> <varname>fsync</varname> can only be set in the <filename>postgresql.conf</> file or on the server command line. - If you turn this parameter off, also consider turning off + If you turn this parameter off, also consider turning off <xref linkend="guc-full-page-writes">. </para> </listitem> @@ -1475,8 +1507,9 @@ SET ENABLE_SEQSCAN TO OFF; <para> Specifies whether transaction commit will wait for WAL records to be written to disk before the command returns a <quote>success</> - indication to the client. The default, and safe, setting is - <literal>on</>. When <literal>off</>, there can be a delay between + indication to the client. Valid values are <literal>on</>, + <literal>local</>, and <literal>off</>. The default, and safe, value + is <literal>on</>. When <literal>off</>, there can be a delay between when success is reported to the client and when the transaction is really guaranteed to be safe against a server crash. (The maximum delay is three times <xref linkend="guc-wal-writer-delay">.) Unlike @@ -1491,17 +1524,30 @@ SET ENABLE_SEQSCAN TO OFF; discussion see <xref linkend="wal-async-commit">. </para> <para> + If <xref linkend="guc-synchronous-standby-names"> is set, this + parameter also controls whether or not transaction commit will wait + for the transaction's WAL records to be flushed to disk and replicated + to the standby server. The commit wait will last until a reply from + the current synchronous standby indicates it has written the commit + record of the transaction to durable storage. If synchronous + replication is in use, it will normally be sensible either to wait + both for WAL records to reach both the local and remote disks, or + to allow the transaction to commit asynchronously. However, the + special value <literal>local</> is available for transactions that + wish to wait for local flush to disk, but not synchronous replication. + </para> + <para> This parameter can be changed at any time; the behavior for any one transaction is determined by the setting in effect when it commits. It is therefore possible, and useful, to have some transactions commit synchronously and others asynchronously. - For example, to make a single multi-statement transaction commit + For example, to make a single multistatement transaction commit asynchronously when the default is the opposite, issue <command>SET LOCAL synchronous_commit TO OFF</> within the transaction. </para> </listitem> </varlistentry> - + <varlistentry id="guc-wal-sync-method" xreflabel="wal_sync_method"> <term><varname>wal_sync_method</varname> (<type>enum</type>)</term> <indexterm> @@ -1527,12 +1573,12 @@ SET ENABLE_SEQSCAN TO OFF; </listitem> <listitem> <para> - <literal>fsync_writethrough</> (call <function>fsync()</> at each commit, forcing write-through of any disk write cache) + <literal>fsync</> (call <function>fsync()</> at each commit) </para> </listitem> <listitem> <para> - <literal>fsync</> (call <function>fsync()</> at each commit) + <literal>fsync_writethrough</> (call <function>fsync()</> at each commit, forcing write-through of any disk write cache) </para> </listitem> <listitem> @@ -1542,18 +1588,21 @@ SET ENABLE_SEQSCAN TO OFF; </listitem> </itemizedlist> <para> + The <literal>open_</>* options also use <literal>O_DIRECT</> if available. Not all of these choices are available on all platforms. The default is the first method in the above list that is supported - by the platform. - The <literal>open_</>* options also use <literal>O_DIRECT</> if available. - The utility <filename>src/tools/fsync</> in the PostgreSQL source tree - can do performance testing of various fsync methods. + by the platform, except that <literal>fdatasync</> is the default on + Linux. The default is not necessarily ideal; it might be + necessary to change this setting or other aspects of your system + configuration in order to create a crash-safe configuration or + achieve optimal performance. + These aspects are discussed in <xref linkend="wal-reliability">. This parameter can only be set in the <filename>postgresql.conf</> file or on the server command line. </para> </listitem> </varlistentry> - + <varlistentry id="guc-full-page-writes" xreflabel="full_page_writes"> <indexterm> <primary><varname>full_page_writes</> configuration parameter</primary> @@ -1607,12 +1656,25 @@ SET ENABLE_SEQSCAN TO OFF; </indexterm> <listitem> <para> - The amount of memory used in shared memory for WAL data. The - default is 64 kilobytes (<literal>64kB</>). The setting need only - be large enough to hold the amount of WAL data generated by one - typical transaction, since the data is written out to disk at - every transaction commit. This parameter can only be set at server - start. + The amount of shared memory used for WAL data that has not yet been + written to disk. The default setting of -1 selects a size equal to + 1/32nd (about 3%) of <xref linkend="guc-shared-buffers">, but not less + than <literal>64kB</literal> nor more than the size of one WAL + segment, typically <literal>16MB</literal>. This value can be set + manually if the automatic choice is too large or too small, + but any positive value less than <literal>32kB</literal> will be + treated as <literal>32kB</literal>. + This parameter can only be set at server start. + </para> + + <para> + The contents of the WAL buffers are written out to disk at every + transaction commit, so extremely large values are unlikely to + provide a significant benefit. However, setting this value to at + least a few megabytes can improve write performance on a busy + server where many clients are committing at once. The auto-tuning + selected by the default setting of -1 should give reasonable + results in most cases. </para> <para> @@ -1652,17 +1714,23 @@ SET ENABLE_SEQSCAN TO OFF; </indexterm> <listitem> <para> - Time delay between writing a commit record to the WAL buffer - and flushing the buffer out to disk, in microseconds. A - nonzero delay can allow multiple transactions to be committed - with only one <function>fsync()</function> system call, if + When the commit data for a transaction is flushed to disk, any + additional commits ready at that time are also flushed out. + <varname>commit_delay</varname> adds a time delay, set in + microseconds, before a transaction attempts to + flush the WAL buffer out to disk. A nonzero delay can allow more + transactions to be committed with only one flush operation, if system load is high enough that additional transactions become ready to commit within the given interval. But the delay is just wasted if no other transactions become ready to commit. Therefore, the delay is only performed if at least <varname>commit_siblings</varname> other transactions are active at the instant that a server process has written its - commit record. The default is zero (no delay). + commit record. + The default <varname>commit_delay</> is zero (no delay). + Since all pending commit data will be written at every flush + regardless of this setting, it is rare that adding delay + by increasing this parameter will actually improve performance. </para> </listitem> </varlistentry> @@ -1817,7 +1885,7 @@ SET ENABLE_SEQSCAN TO OFF; </para> </listitem> </varlistentry> - + <varlistentry id="guc-archive-timeout" xreflabel="archive_timeout"> <term><varname>archive_timeout</varname> (<type>integer</type>)</term> <indexterm> @@ -1871,7 +1939,8 @@ SET ENABLE_SEQSCAN TO OFF; <listitem> <para> Specifies the maximum number of concurrent connections from standby - servers (i.e., the maximum number of simultaneously running WAL sender + servers or streaming base backup clients (i.e., the maximum number of + simultaneously running WAL sender processes). The default is zero. This parameter can only be set at server start. <varname>wal_level</> must be set to <literal>archive</> or <literal>hot_standby</> to allow connections from standby servers. @@ -1888,8 +1957,11 @@ SET ENABLE_SEQSCAN TO OFF; Specifies the delay between activity rounds for WAL sender processes. In each round the WAL sender sends any WAL accumulated since the last round to the standby server. It then sleeps for - <varname>wal_sender_delay</> milliseconds, and repeats. The default - value is 200 milliseconds (<literal>200ms</>). + <varname>wal_sender_delay</> milliseconds, and repeats. The sleep + is interrupted by transaction commit, so the effects of a committed + transaction are sent to standby servers as soon as the commit + happens, regardless of this setting. The default value is one second + (<literal>1s</>). Note that on many systems, the effective resolution of sleep delays is 10 milliseconds; setting <varname>wal_sender_delay</> to a value that is not a multiple of 10 might have the same results as setting it to @@ -1926,7 +1998,8 @@ SET ENABLE_SEQSCAN TO OFF; doesn't keep any extra segments for standby purposes, and the number of old WAL segments available to standby servers is a function of the location of the previous checkpoint and status of WAL - archiving. This parameter can only be set in the + archiving. This parameter has no effect on restartpoints. + This parameter can only be set in the <filename>postgresql.conf</> file or on the server command line. </para> </listitem> @@ -1954,11 +2027,92 @@ SET ENABLE_SEQSCAN TO OFF; This parameter can only be set in the <filename>postgresql.conf</> file or on the server command line. </para> + <para> + You should also consider setting <varname>hot_standby_feedback</> + as an alternative to using this parameter. + </para> + </listitem> + </varlistentry> + + <varlistentry id="guc-replication-timeout" xreflabel="replication_timeout"> + <term><varname>replication_timeout</varname> (<type>integer</type>)</term> + <indexterm> + <primary><varname>replication_timeout</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + Terminate replication connections that are inactive longer + than the specified number of milliseconds. This is useful for + the primary server to detect a standby crash or network outage. + A value of zero disables the timeout mechanism. This parameter + can only be set in + the <filename>postgresql.conf</> file or on the server command line. + The default value is 60 seconds. + </para> + <para> + To prevent connections from being terminated prematurely, + <xref linkend="guc-wal-receiver-status-interval"> + must be enabled on the standby, and its value must be less than the + value of <varname>replication_timeout</>. + </para> </listitem> </varlistentry> </variablelist> </sect2> + <sect2 id="runtime-config-sync-rep"> + <title>Synchronous Replication</title> + + <para> + These settings control the behavior of the built-in + <firstterm>synchronous replication</> feature. + These parameters would be set on the primary server that is + to send replication data to one or more standby servers. + </para> + + <variablelist> + <varlistentry id="guc-synchronous-standby-names" xreflabel="synchronous_standby_names"> + <term><varname>synchronous_standby_names</varname> (<type>string</type>)</term> + <indexterm> + <primary><varname>synchronous_standby_names</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + Specifies a priority ordered list of standby names that can offer + synchronous replication. At any one time there will be at most one + synchronous standby that will wake sleeping users following commit. + The synchronous standby will be the first named standby that is + both currently connected and streaming in real-time to the standby + (as shown by a state of "STREAMING"). Other standby servers + with listed later will become potential synchronous standbys. + If the current synchronous standby disconnects for whatever reason + it will be replaced immediately with the next highest priority standby. + Specifying more than one standby name can allow very high availability. + </para> + <para> + The standby name is currently taken as the application_name of the + standby, as set in the primary_conninfo on the standby. Names are + not enforced for uniqueness. In case of duplicates one of the standbys + will be chosen to be the synchronous standby, though exactly which + one is indeterminate. + The special entry <literal>*</> matches any application_name, including + the default application name of <literal>walreceiver</>. + </para> + <para> + If no synchronous standby names are specified, then synchronous + replication is not enabled and transaction commit will never wait for + replication. This is the default configuration. Even when + synchronous replication is enabled, individual transactions can be + configured not to wait for replication by setting the + <xref linkend="guc-synchronous-commit"> parameter to + <literal>local</> or <literal>off</>. + </para> + </listitem> + </varlistentry> + + </variablelist> + </sect2> + <sect2 id="runtime-config-standby"> <title>Standby Servers</title> @@ -2046,6 +2200,51 @@ SET ENABLE_SEQSCAN TO OFF; </listitem> </varlistentry> + <varlistentry id="guc-wal-receiver-status-interval" xreflabel="wal_receiver_status_interval"> + <term><varname>wal_receiver_status_interval</varname> (<type>integer</type>)</term> + <indexterm> + <primary><varname>wal_receiver_status_interval</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + Specifies the minimum frequency, in seconds, for the WAL receiver + process on the standby to send information about replication progress + to the primary, where they can be seen using the + <literal>pg_stat_replication</literal> view. The standby will report + the last transaction log position it has written, the last position it + has flushed to disk, and the last position it has applied. Updates are + sent each time the write or flush positions changed, or at least as + often as specified by this parameter. Thus, the apply position may + lag slightly behind the true position. Setting this parameter to zero + disables status updates completely. This parameter can only be set in + the <filename>postgresql.conf</> file or on the server command line. + The default value is 10 seconds. + </para> + <para> + When <xref linkend="guc-replication-timeout"> is enabled on the primary, + <varname>wal_receiver_status_interval</> must be enabled, and its value + must be less than the value of <varname>replication_timeout</>. + </para> + </listitem> + </varlistentry> + + <varlistentry id="guc-hot-standby-feedback" xreflabel="hot_standby"> + <term><varname>hot_standby_feedback</varname> (<type>boolean</type>)</term> + <indexterm> + <primary><varname>hot_standby_feedback</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + Specifies whether or not a hot standby will send feedback to the primary + about queries currently executing on the standby. This parameter can + be used to eliminate query cancels caused by cleanup records, but + can cause database bloat on the primary for some workloads. + The default value is <literal>off</literal>. Feedback messages will not + be sent more frequently than once per <varname>wal_receiver_status_interval</>. + </para> + </listitem> + </varlistentry> + </variablelist> </sect2> </sect1> @@ -2225,7 +2424,7 @@ SET ENABLE_SEQSCAN TO OFF; </para> </listitem> </varlistentry> - + </variablelist> </sect2> <sect2 id="runtime-config-query-constants"> @@ -2264,7 +2463,7 @@ SET ENABLE_SEQSCAN TO OFF; <para> Sets the planner's estimate of the cost of a disk page fetch that is part of a series of sequential fetches. The default is 1.0. - This value can be overriden for a particular tablespace by setting + This value can be overridden for a particular tablespace by setting the tablespace parameter of the same name (see <xref linkend="sql-altertablespace">). </para> @@ -2280,7 +2479,7 @@ SET ENABLE_SEQSCAN TO OFF; <para> Sets the planner's estimate of the cost of a non-sequentially-fetched disk page. The default is 4.0. - This value can be overriden for a particular tablespace by setting + This value can be overridden for a particular tablespace by setting the tablespace parameter of the same name (see <xref linkend="sql-altertablespace">). </para> @@ -2336,7 +2535,7 @@ SET ENABLE_SEQSCAN TO OFF; </para> </listitem> </varlistentry> - + <varlistentry id="guc-cpu-operator-cost" xreflabel="cpu_operator_cost"> <term><varname>cpu_operator_cost</varname> (<type>floating point</type>)</term> <indexterm> @@ -2350,7 +2549,7 @@ SET ENABLE_SEQSCAN TO OFF; </para> </listitem> </varlistentry> - + <varlistentry id="guc-effective-cache-size" xreflabel="effective_cache_size"> <term><varname>effective_cache_size</varname> (<type>integer</type>)</term> <indexterm> @@ -2372,7 +2571,9 @@ SET ENABLE_SEQSCAN TO OFF; space. This parameter has no effect on the size of shared memory allocated by <productname>PostgreSQL</productname>, nor does it reserve kernel disk cache; it is used only for estimation - purposes. The default is 128 megabytes (<literal>128MB</>). + purposes. The system also does not assume data remains in + the disk cache between queries. The default is 128 megabytes + (<literal>128MB</>). </para> </listitem> </varlistentry> @@ -2713,10 +2914,10 @@ SELECT * FROM parent WHERE key = 2400; <productname>PostgreSQL</productname> supports several methods for logging server messages, including <systemitem>stderr</systemitem>, <systemitem>csvlog</systemitem> and - <systemitem>syslog</systemitem>. On Windows, + <systemitem>syslog</systemitem>. On Windows, <systemitem>eventlog</systemitem> is also supported. Set this parameter to a list of desired log destinations separated by - commas. The default is to log to <systemitem>stderr</systemitem> + commas. The default is to log to <systemitem>stderr</systemitem> only. This parameter can only be set in the <filename>postgresql.conf</> file or on the server command line. @@ -2727,7 +2928,7 @@ SELECT * FROM parent WHERE key = 2400; value</> (<acronym>CSV</>) format, which is convenient for loading logs into programs. See <xref linkend="runtime-config-logging-csvlog"> for details. - <varname>logging_collector</varname> must be enabled to generate + <varname>logging_collector</varname> must be enabled to generate CSV-format log output. </para> @@ -2790,7 +2991,7 @@ local0.* /var/log/postgresql </indexterm> <listitem> <para> - When <varname>logging_collector</> is enabled, + When <varname>logging_collector</> is enabled, this parameter determines the directory in which log files will be created. It can be specified as an absolute path, or relative to the cluster data directory. @@ -2829,7 +3030,7 @@ local0.* /var/log/postgresql </para> <para> If CSV-format output is enabled in <varname>log_destination</>, - <literal>.csv</> will be appended to the timestamped + <literal>.csv</> will be appended to the timestamped log file name to create the file name for CSV-format output. (If <varname>log_filename</> ends in <literal>.log</>, the suffix is replaced instead.) @@ -2843,6 +3044,39 @@ local0.* /var/log/postgresql </listitem> </varlistentry> + <varlistentry id="guc-log-file-mode" xreflabel="log_file_mode"> + <term><varname>log_file_mode</varname> (<type>integer</type>)</term> + <indexterm> + <primary><varname>log_file_mode</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + On Unix systems this parameter sets the permissions for log files + when <varname>logging_collector</varname> is enabled. (On Microsoft + Windows this parameter is ignored.) + The parameter value is expected to be a numeric mode + specified in the format accepted by the + <function>chmod</function> and <function>umask</function> + system calls. (To use the customary octal format the number + must start with a <literal>0</literal> (zero).) + </para> + <para> + The default permissions are <literal>0600</>, meaning only the + server owner can read or write the log files. The other commonly + useful setting is <literal>0640</>, allowing members of the owner's + group to read the files. Note however that to make use of such a + setting, you'll need to alter <xref linkend="guc-log-directory"> to + store the files somewhere outside the cluster data directory. In + any case, it's unwise to make the log files world-readable, since + they might contain sensitive data. + </para> + <para> + This parameter can only be set in the <filename>postgresql.conf</> + file or on the server command line. + </para> + </listitem> + </varlistentry> + <varlistentry id="guc-log-rotation-age" xreflabel="log_rotation_age"> <term><varname>log_rotation_age</varname> (<type>integer</type>)</term> <indexterm> @@ -2901,18 +3135,18 @@ local0.* /var/log/postgresql </para> <para> Example: To keep 7 days of logs, one log file per day named - <literal>server_log.Mon</literal>, <literal>server_log.Tue</literal>, + <literal>server_log.Mon</literal>, <literal>server_log.Tue</literal>, etc, and automatically overwrite last week's log with this week's log, - set <varname>log_filename</varname> to <literal>server_log.%a</literal>, - <varname>log_truncate_on_rotation</varname> to <literal>on</literal>, and + set <varname>log_filename</varname> to <literal>server_log.%a</literal>, + <varname>log_truncate_on_rotation</varname> to <literal>on</literal>, and <varname>log_rotation_age</varname> to <literal>1440</literal>. </para> <para> - Example: To keep 24 hours of logs, one log file per hour, but - also rotate sooner if the log file size exceeds 1GB, set - <varname>log_filename</varname> to <literal>server_log.%H%M</literal>, - <varname>log_truncate_on_rotation</varname> to <literal>on</literal>, - <varname>log_rotation_age</varname> to <literal>60</literal>, and + Example: To keep 24 hours of logs, one log file per hour, but + also rotate sooner if the log file size exceeds 1GB, set + <varname>log_filename</varname> to <literal>server_log.%H%M</literal>, + <varname>log_truncate_on_rotation</varname> to <literal>on</literal>, + <varname>log_rotation_age</varname> to <literal>60</literal>, and <varname>log_rotation_size</varname> to <literal>1000000</literal>. Including <literal>%M</> in <varname>log_filename</varname> allows any size-driven rotations that might occur to select a file name @@ -2942,7 +3176,7 @@ local0.* /var/log/postgresql </para> </listitem> </varlistentry> - + <varlistentry id="guc-syslog-ident" xreflabel="syslog_ident"> <term><varname>syslog_ident</varname> (<type>string</type>)</term> <indexterm> @@ -3067,7 +3301,7 @@ local0.* /var/log/postgresql </para> </listitem> </varlistentry> - + <varlistentry id="guc-log-min-duration-statement" xreflabel="log_min_duration_statement"> <term><varname>log_min_duration_statement</varname> (<type>integer</type>)</term> <indexterm> @@ -3098,7 +3332,7 @@ local0.* /var/log/postgresql the text of statements that are logged because of <varname>log_statement</> will not be repeated in the duration log message. - If you are not using <application>syslog</>, it is recommended + If you are not using <application>syslog</>, it is recommended that you log the PID or session ID using <xref linkend="guc-log-line-prefix"> so that you can link the statement message to the later @@ -3119,7 +3353,7 @@ local0.* /var/log/postgresql </para> <table id="runtime-config-severity-levels"> - <title>Message severity levels</title> + <title>Message Severity Levels</title> <tgroup cols="4"> <thead> <row> @@ -3275,10 +3509,9 @@ local0.* /var/log/postgresql </indexterm> <listitem> <para> - Causes checkpoints to be logged in the server log. Some - statistics about each checkpoint are included in the log messages, - including the number of buffers written and the time spent writing - them. + Causes checkpoints and restartpoints to be logged in the server log. + Some statistics are included in the log messages, including the number + of buffers written and the time spent writing them. This parameter can only be set in the <filename>postgresql.conf</> file or on the server command line. The default is off. </para> @@ -3294,14 +3527,14 @@ local0.* /var/log/postgresql <para> Causes each attempted connection to the server to be logged, as well as successful completion of client authentication. - This parameter can only be set in the <filename>postgresql.conf</> - file or on the server command line. The default is off. + This parameter cannot be changed after session start. + The default is off. </para> <note> <para> - Some client programs, like <application>psql</>, attempt - to connect twice while determining if a password is required, so + Some client programs, like <application>psql</>, attempt + to connect twice while determining if a password is required, so duplicate <quote>connection received</> messages do not necessarily indicate a problem. </para> @@ -3320,8 +3553,7 @@ local0.* /var/log/postgresql <varname>log_connections</varname> but at session termination, and includes the duration of the session. This is off by default. - This parameter can only be set in the <filename>postgresql.conf</> - file or on the server command line. + This parameter cannot be changed after session start. </para> </listitem> </varlistentry> @@ -3373,9 +3605,8 @@ local0.* /var/log/postgresql fields to displayed messages. <literal>TERSE</> excludes the logging of <literal>DETAIL</>, <literal>HINT</>, <literal>QUERY</>, and <literal>CONTEXT</> error information. - <literal>VERBOSE</> output includes the <link - linkend="errcodes-appendix">SQLSTATE</> error - code and the source code file name, function name, + <literal>VERBOSE</> output includes the <symbol>SQLSTATE</> error + code (see also <xref linkend="errcodes-appendix">) and the source code file name, function name, and line number that generated the error. Only superusers can change this setting. </para> @@ -3398,7 +3629,7 @@ local0.* /var/log/postgresql </para> </listitem> </varlistentry> - + <varlistentry id="guc-log-line-prefix" xreflabel="log_line_prefix"> <term><varname>log_line_prefix</varname> (<type>string</type>)</term> <indexterm> @@ -3474,7 +3705,7 @@ local0.* /var/log/postgresql </row> <row> <entry><literal>%e</literal></entry> - <entry>SQL state</entry> + <entry>SQLSTATE error code</entry> <entry>no</entry> </row> <row> @@ -3543,9 +3774,9 @@ FROM pg_stat_activity; <tip> <para> - <application>Syslog</> produces its own + <application>Syslog</> produces its own time stamp and process ID information, so you probably do not want to - use those escapes if you are logging to <application>syslog</>. + include those escapes if you are logging to <application>syslog</>. </para> </tip> </listitem> @@ -3624,7 +3855,7 @@ FROM pg_stat_activity; A value of zero logs all temporary file information, while positive values log only files whose size is greater than or equal to the specified number of kilobytes. The - default setting is <literal>-1</>, which disables such logging. + default setting is -1, which disables such logging. Only superusers can change this setting. </para> </listitem> @@ -3637,11 +3868,11 @@ FROM pg_stat_activity; </indexterm> <listitem> <para> - Sets the time zone used for timestamps written in the log. + Sets the time zone used for timestamps written in the server log. Unlike <xref linkend="guc-timezone">, this value is cluster-wide, so that all sessions will report timestamps consistently. - The default is <literal>unknown</>, which means use whatever - the system environment specifies as the time zone. See <xref + If not explicitly set, the server initializes this variable to the + time zone specified by its system environment. See <xref linkend="datatype-timezones"> for more information. This parameter can only be set in the <filename>postgresql.conf</> file or on the server command line. @@ -3660,7 +3891,7 @@ FROM pg_stat_activity; This option emits log lines in comma-separated-values (<acronym>CSV</>) format, with these columns: - timestamp with milliseconds, + time stamp with milliseconds, user name, database name, process ID, @@ -3672,7 +3903,7 @@ FROM pg_stat_activity; virtual transaction ID, regular transaction ID, error severity, - SQL state code, + SQLSTATE code, error message, error message detail, hint, @@ -3744,9 +3975,9 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; <listitem> <para> - Set <varname>log_rotation_size</varname> to 0 to disable - size-based log rotation, as it makes the log file name difficult - to predict. + Set <varname>log_rotation_size</varname> to 0 to disable + size-based log rotation, as it makes the log file name difficult + to predict. </para> </listitem> @@ -3778,7 +4009,7 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; </sect1> <sect1 id="runtime-config-statistics"> - <title>Run-Time Statistics</title> + <title>Run-time Statistics</title> <sect2 id="runtime-config-statistics-collector"> <title>Query and Index Statistics Collector</title> @@ -3995,7 +4226,10 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; all autovacuum actions. Minus-one (the default) disables logging autovacuum actions. For example, if you set this to <literal>250ms</literal> then all automatic vacuums and analyzes that run - 250ms or longer will be logged. Enabling this parameter can be helpful + 250ms or longer will be logged. In addition, when this parameter is + set to any value other than <literal>-1</literal>, a message will be + logged if an autovacuum action is skipped due to the existence of a + conflicting lock. Enabling this parameter can be helpful in tracking autovacuum activity. This setting can only be set in the <filename>postgresql.conf</> file or on the server command line. </para> @@ -4117,11 +4351,16 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; <para> Specifies the maximum age (in transactions) that a table's <structname>pg_class</>.<structfield>relfrozenxid</> field can - attain before a <command>VACUUM</> operation is forced to prevent - transaction ID wraparound within the table. Note that the system - will launch autovacuum processes to prevent wraparound even when - autovacuum is otherwise disabled. - The default is 200 million transactions. + attain before a <command>VACUUM</> operation is forced + to prevent transaction ID wraparound within the table. + Note that the system will launch autovacuum processes to + prevent wraparound even when autovacuum is otherwise disabled. + </para> + + <para> + Vacuum also allows removal of old files from the + <filename>pg_clog</> subdirectory, which is why the default + is a relatively low 200 million transactions. This parameter can only be set at server start, but the setting can be reduced for individual tables by changing storage parameters. @@ -4138,8 +4377,7 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; <listitem> <para> Specifies the cost delay value that will be used in automatic - <command>VACUUM</> operations. If <literal>-1</> is - specified, the regular + <command>VACUUM</> operations. If -1 is specified, the regular <xref linkend="guc-vacuum-cost-delay"> value will be used. The default value is 20 milliseconds. This parameter can only be set in the <filename>postgresql.conf</> @@ -4158,7 +4396,7 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; <listitem> <para> Specifies the cost limit value that will be used in automatic - <command>VACUUM</> operations. If <literal>-1</> is specified (which is the + <command>VACUUM</> operations. If -1 is specified (which is the default), the regular <xref linkend="guc-vacuum-cost-limit"> value will be used. Note that the value is distributed proportionally among the running autovacuum @@ -4288,6 +4526,12 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; </para> <para> + This variable is also not used when creating databases. + By default, a new database inherits its tablespace setting from + the template database it is copied from. + </para> + + <para> For more information on tablespaces, see <xref linkend="manage-ag-tablespaces">. </para> @@ -4361,6 +4605,7 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; <varlistentry id="guc-default-transaction-isolation" xreflabel="default_transaction_isolation"> <indexterm> <primary>transaction isolation level</primary> + <secondary>setting default</secondary> </indexterm> <indexterm> <primary><varname>default_transaction_isolation</> configuration parameter</primary> @@ -4386,6 +4631,7 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; <varlistentry id="guc-default-transaction-read-only" xreflabel="default_transaction_read_only"> <indexterm> <primary>read-only transaction</primary> + <secondary>setting default</secondary> </indexterm> <indexterm> <primary><varname>default_transaction_read_only</> configuration parameter</primary> @@ -4405,6 +4651,41 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; </listitem> </varlistentry> + <varlistentry id="guc-default-transaction-deferrable" xreflabel="default_transaction_deferrable"> + <indexterm> + <primary>deferrable transaction</primary> + <secondary>setting default</secondary> + </indexterm> + <indexterm> + <primary><varname>default_transaction_deferrable</> configuration parameter</primary> + </indexterm> + + <term><varname>default_transaction_deferrable</varname> (<type>boolean</type>)</term> + <listitem> + <para> + When running at the <literal>serializable</> isolation level, + a deferrable read-only SQL transaction may be delayed before + it is allowed to proceed. However, once it begins executing + it does not incur any of the overhead required to ensure + serializability; so serialization code will have no reason to + force it to abort because of concurrent updates, making this + option suitable for long-running read-only transactions. + </para> + + <para> + This parameter controls the default deferrable status of each + new transaction. It currently has no effect on read-write + transactions or those operating at isolation levels lower + than <literal>serializable</>. The default is <literal>off</>. + </para> + + <para> + Consult <xref linkend="sql-set-transaction"> for more information. + </para> + </listitem> + </varlistentry> + + <varlistentry id="guc-session-replication-role" xreflabel="session_replication_role"> <term><varname>session_replication_role</varname> (<type>enum</type>)</term> <indexterm> @@ -4636,10 +4917,9 @@ SET XML OPTION { DOCUMENT | CONTENT }; <listitem> <para> Sets the time zone for displaying and interpreting time stamps. - The default is <literal>unknown</>, which means to use whatever - the system environment specifies as the time zone. See <xref - linkend="datatype-timezones"> for more - information. + If not explicitly set, the server initializes this variable to the + time zone specified by its system environment. See <xref + linkend="datatype-timezones"> for more information. </para> </listitem> </varlistentry> @@ -4655,7 +4935,7 @@ SET XML OPTION { DOCUMENT | CONTENT }; Sets the collection of time zone abbreviations that will be accepted by the server for datetime input. The default is <literal>'Default'</>, which is a collection that works in most of the world; there are - also 'Australia' and 'India', and other collections can be defined + also <literal>'Australia'</literal> and <literal>'India'</literal>, and other collections can be defined for a particular installation. See <xref linkend="datetime-appendix"> for more information. </para> @@ -4699,6 +4979,8 @@ SET XML OPTION { DOCUMENT | CONTENT }; <para> Sets the client-side encoding (character set). The default is to use the database encoding. + The character sets supported by the <productname>PostgreSQL</productname> + server are described in <xref linkend="multibyte-charset-supported">. </para> </listitem> </varlistentry> @@ -4921,7 +5203,7 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' libraries to be loaded into specific sessions without an explicit <command>LOAD</> command being given. For example, debugging could be enabled for all sessions under a given user name by setting - this parameter with <command>ALTER USER SET</>. + this parameter with <command>ALTER ROLE SET</>. </para> <para> @@ -4931,7 +5213,7 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' <para> Every PostgreSQL-supported library has a <quote>magic - block</> that is checked to guarantee compatibility. + block</> that is checked to guarantee compatibility. For this reason, non-PostgreSQL libraries cannot be loaded in this way. </para> @@ -5028,6 +5310,39 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' </listitem> </varlistentry> + <varlistentry id="guc-max-pred-locks-per-transaction" xreflabel="max_pred_locks_per_transaction"> + <term><varname>max_pred_locks_per_transaction</varname> (<type>integer</type>)</term> + <indexterm> + <primary><varname>max_pred_locks_per_transaction</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + The shared predicate lock table tracks locks on + <varname>max_pred_locks_per_transaction</varname> * (<xref + linkend="guc-max-connections"> + <xref + linkend="guc-max-prepared-transactions">) objects (e.g., tables); + hence, no more than this many distinct objects can be locked at + any one time. This parameter controls the average number of object + locks allocated for each transaction; individual transactions + can lock more objects as long as the locks of all transactions + fit in the lock table. This is <emphasis>not</> the number of + rows that can be locked; that value is unlimited. The default, + 64, has generally been sufficient in testing, but you might need to + raise this value if you have clients that touch many different + tables in a single serializable transaction. This parameter can + only be set at server start. + </para> + + <para> + Increasing this parameter might cause <productname>PostgreSQL</> + to request more <systemitem class="osname">System V</> shared + memory than your operating system's default configuration + allows. See <xref linkend="sysvipc"> for information on how to + adjust those parameters, if necessary. + </para> + </listitem> + </varlistentry> + </variablelist> </sect1> @@ -5052,7 +5367,7 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' null values to be entered. However, <productname>PostgreSQL</> versions before 8.2 did not support null values in arrays, and therefore would treat <literal>NULL</> as specifying a normal array element with - the string value <quote>NULL</>. For backwards compatibility with + the string value <quote>NULL</>. For backward compatibility with applications that require the old behavior, this variable can be turned <literal>off</>. </para> @@ -5144,9 +5459,9 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' <para> Applications that wish to use backslash as escape should be modified to use escape string syntax (<literal>E'...'</>), - because the default behavior of ordinary strings will change - in a future release for SQL compatibility. This variable can - be enabled to help detect applications that will break. + because the default behavior of ordinary strings is now to treat + backslash as an ordinary character, per SQL standard. This variable + can be enabled to help locate code that needs to be changed. </para> </listitem> </varlistentry> @@ -5175,6 +5490,23 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' </listitem> </varlistentry> + <varlistentry id="guc-quote-all-identifiers" xreflabel="quote-all-identifiers"> + <term><varname>quote_all_identifiers</varname> (<type>boolean</type>)</term> + <indexterm> + <primary><varname>quote_all_identifiers</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + When the database generates SQL, force all identifiers to be quoted, + even if they are not (currently) keywords. This will affect the + output of <command>EXPLAIN</> as well as the results of functions + like <function>pg_get_viewdef</>. See also the + <option>--quote-all-identifiers</option> option of + <xref linkend="app-pgdump"> and <xref linkend="app-pg-dumpall">. + </para> + </listitem> + </varlistentry> + <varlistentry id="guc-sql-inheritance" xreflabel="sql_inheritance"> <term><varname>sql_inheritance</varname> (<type>boolean</type>)</term> <indexterm> @@ -5185,7 +5517,7 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' <para> This controls the inheritance semantics. If turned <literal>off</>, subtables are not accessed by various commands by default; basically - an implied <literal>ONLY</literal> key word. This was added for + an implied <literal>ONLY</literal> key word. This was added for compatibility with releases prior to 7.1. See <xref linkend="ddl-inherit"> for more information. </para> @@ -5203,11 +5535,8 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' This controls whether ordinary string literals (<literal>'...'</>) treat backslashes literally, as specified in the SQL standard. - The default is currently <literal>off</>, causing - <productname>PostgreSQL</productname> to have its historical - behavior of treating backslashes as escape characters. - The default will change to <literal>on</> in a future release - to improve compatibility with the SQL standard. + Beginning in <productname>PostgreSQL</productname> 9.1, the default is + <literal>on</> (prior releases defaulted to <literal>off</>). Applications can check this parameter to determine how string literals will be processed. The presence of this parameter can also be taken as an indication @@ -5299,6 +5628,47 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' </sect2> </sect1> + <sect1 id="runtime-config-error-handling"> + <title>Error Handling</title> + + <variablelist> + + <varlistentry id="guc-exit-on-error" xreflabel="exit_on_error"> + <term><varname>exit_on_error</varname> (<type>boolean</type>)</term> + <indexterm> + <primary><varname>exit_on_error</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + If true, any error will terminate the current session. By default, + this is set to false, so that only FATAL errors will terminate the + session. + </para> + </listitem> + </varlistentry> + + <varlistentry id="guc-restart-after-crash" xreflabel="restart_after_crash"> + <term><varname>restart_after_crash</varname> (<type>boolean</type>)</term> + <indexterm> + <primary><varname>restart_after_crash</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + When set to true, which is the default, <productname>PostgreSQL</> + will automatically reinitialize after a backend crash. Leaving this + value set to true is normally the best way to maximize the availability + of the database. However, in some circumstances, such as when + <productname>PostgreSQL</> is being invoked by clusterware, it may be + useful to disable the restart so that the clusterware can gain + control and take any actions it deems appropriate. + </para> + </listitem> + </varlistentry> + + </variablelist> + + </sect1> + <sect1 id="runtime-config-preset"> <title>Preset Options</title> @@ -5403,7 +5773,7 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' the server. The default value of <literal>NAMEDATALEN</> is 64; therefore the default <varname>max_identifier_length</varname> is 63 bytes, which - can be less than 63 characters when using multi-byte encodings. + can be less than 63 characters when using multibyte encodings. </para> </listitem> </varlistentry> @@ -5689,6 +6059,31 @@ plruby.use_strict = true # generates error: unknown class name </listitem> </varlistentry> + <varlistentry id="guc-trace-recovery-messages" xreflabel="trace_recovery_messages"> + <term><varname>trace_recovery_messages</varname> (<type>enum</type>)</term> + <indexterm> + <primary><varname>trace_recovery_messages</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + Enables logging of recovery-related debugging output that otherwise + would not be logged. This parameter allows the user to override the + normal setting of <xref linkend="guc-log-min-messages">, but only for + specific messages. This is intended for use in debugging Hot Standby. + Valid values are <literal>DEBUG5</>, <literal>DEBUG4</>, + <literal>DEBUG3</>, <literal>DEBUG2</>, <literal>DEBUG1</>, and + <literal>LOG</>. The default, <literal>LOG</>, does not affect + logging decisions at all. The other values cause recovery-related + debug messages of that priority or higher to be logged as though they + had <literal>LOG</> priority; for common settings of + <varname>log_min_messages</> this results in unconditionally sending + them to the server log. + This parameter can only be set in the <filename>postgresql.conf</> + file or on the server command line. + </para> + </listitem> + </varlistentry> + <varlistentry id="guc-trace-sort" xreflabel="trace_sort"> <term><varname>trace_sort</varname> (<type>boolean</type>)</term> <indexterm> @@ -5714,36 +6109,27 @@ plruby.use_strict = true # generates error: unknown class name If on, emit information about lock usage. Information dumped includes the type of lock operation, the type of lock and the unique identifier of the object being locked or unlocked. Also included - are bitmasks for the lock types already granted on this object as + are bit masks for the lock types already granted on this object as well as for the lock types awaited on this object. For each lock type a count of the number of granted locks and waiting locks is also dumped as well as the totals. An example of the log file output is shown here: - </para> - <para> - LOG: LockAcquire: new: lock(0xb7acd844) id(24688,24696,0,0,0,1) - grantMask(0) req(0,0,0,0,0,0,0)=0 grant(0,0,0,0,0,0,0)=0 - wait(0) type(AccessShareLock) - </para> - <para> - LOG: GrantLock: lock(0xb7acd844) id(24688,24696,0,0,0,1) - grantMask(2) req(1,0,0,0,0,0,0)=1 grant(1,0,0,0,0,0,0)=1 - wait(0) type(AccessShareLock) - - </para> - <para> - LOG: UnGrantLock: updated: lock(0xb7acd844) id(24688,24696,0,0,0,1) - grantMask(0) req(0,0,0,0,0,0,0)=0 grant(0,0,0,0,0,0,0)=0 - wait(0) type(AccessShareLock) - </para> - <para> - LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1) - grantMask(0) req(0,0,0,0,0,0,0)=0 grant(0,0,0,0,0,0,0)=0 - wait(0) type(INVALID) - </para> - <para> +<screen> +LOG: LockAcquire: new: lock(0xb7acd844) id(24688,24696,0,0,0,1) + grantMask(0) req(0,0,0,0,0,0,0)=0 grant(0,0,0,0,0,0,0)=0 + wait(0) type(AccessShareLock) +LOG: GrantLock: lock(0xb7acd844) id(24688,24696,0,0,0,1) + grantMask(2) req(1,0,0,0,0,0,0)=1 grant(1,0,0,0,0,0,0)=1 + wait(0) type(AccessShareLock) +LOG: UnGrantLock: updated: lock(0xb7acd844) id(24688,24696,0,0,0,1) + grantMask(0) req(0,0,0,0,0,0,0)=0 grant(0,0,0,0,0,0,0)=0 + wait(0) type(AccessShareLock) +LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1) + grantMask(0) req(0,0,0,0,0,0,0)=0 grant(0,0,0,0,0,0,0)=0 + wait(0) type(INVALID) +</screen> Details of the structure being dumped may be found in - src/include/storage/lock.h + <filename>src/include/storage/lock.h</filename>. </para> <para> This parameter is only available if the <symbol>LOCK_DEBUG</symbol> @@ -5837,7 +6223,7 @@ plruby.use_strict = true # generates error: unknown class name <listitem> <para> If set, dumps information about all current locks when a - DeadLockTimeout occurs. + deadlock timeout occurs. </para> <para> This parameter is only available if the <symbol>LOCK_DEBUG</symbol> @@ -5855,7 +6241,7 @@ plruby.use_strict = true # generates error: unknown class name <listitem> <para> If set, logs system resource usage statistics (memory and CPU) on - various btree operations. + various B-tree operations. </para> <para> This parameter is only available if the <symbol>BTREE_BUILD_STATS</symbol> @@ -5880,32 +6266,6 @@ plruby.use_strict = true # generates error: unknown class name </listitem> </varlistentry> - <varlistentry id="guc-trace-recovery-messages" xreflabel="trace_recovery_messages"> - <term><varname>trace_recovery_messages</varname> (<type>enum</type>)</term> - <indexterm> - <primary><varname>trace_recovery_messages</> configuration parameter</primary> - </indexterm> - <listitem> - <para> - Controls which message levels are written to the server log - for system modules needed for recovery processing. This allows - the user to override the normal setting of log_min_messages, - but only for specific messages. This is intended for use in - debugging Hot Standby. - Valid values are <literal>DEBUG5</>, <literal>DEBUG4</>, - <literal>DEBUG3</>, <literal>DEBUG2</>, <literal>DEBUG1</>, - <literal>INFO</>, <literal>NOTICE</>, <literal>WARNING</>, - <literal>ERROR</>, <literal>LOG</>, <literal>FATAL</>, and - <literal>PANIC</>. Each level includes all the levels that - follow it. The later the level, the fewer messages are sent - to the log. The default is <literal>WARNING</>. Note that - <literal>LOG</> has a different rank here than in - <varname>client_min_messages</>. - Parameter should be set in the postgresql.conf only. - </para> - </listitem> - </varlistentry> - <varlistentry id="guc-zero-damaged-pages" xreflabel="zero_damaged_pages"> <term><varname>zero_damaged_pages</varname> (<type>boolean</type>)</term> <indexterm> @@ -5915,15 +6275,17 @@ plruby.use_strict = true # generates error: unknown class name <para> Detection of a damaged page header normally causes <productname>PostgreSQL</> to report an error, aborting the current - command. Setting <varname>zero_damaged_pages</> to on causes - the system to instead report a warning, zero out the damaged page, - and continue processing. This behavior <emphasis>will destroy data</>, - namely all the rows on the damaged page. But it allows you to get + transaction. Setting <varname>zero_damaged_pages</> to on causes + the system to instead report a warning, zero out the damaged + page in memory, and continue processing. This behavior <emphasis>will destroy data</>, + namely all the rows on the damaged page. However, it does allow you to get past the error and retrieve rows from any undamaged pages that might - be present in the table. So it is useful for recovering data if + be present in the table. It is useful for recovering data if corruption has occurred due to a hardware or software error. You should generally not set this on until you have given up hope of recovering - data from the damaged pages of a table. The + data from the damaged pages of a table. Zeroed-out pages are not + forced to disk so it is recommended to recreate the table or + the index before turning this parameter off again. The default setting is <literal>off</>, and it can only be changed by a superuser. </para> @@ -5944,11 +6306,11 @@ plruby.use_strict = true # generates error: unknown class name </para> <table id="runtime-config-short-table"> - <title>Short option key</title> + <title>Short Option Key</title> <tgroup cols="2"> <thead> <row> - <entry>Short option</entry> + <entry>Short Option</entry> <entry>Equivalent</entry> </row> </thead> @@ -6033,7 +6395,7 @@ plruby.use_strict = true # generates error: unknown class name <row> <entry><option>-tpa</option>, <option>-tpl</option>, <option>-te</option></entry> <entry><literal>log_parser_stats = on</>, - <literal>log_planner_stats = on</>, + <literal>log_planner_stats = on</>, <literal>log_executor_stats = on</></entry> </row> <row> diff --git a/doc/src/sgml/contacts.sgml b/doc/src/sgml/contacts.sgml index 6b15de3968..a981625027 100644 --- a/doc/src/sgml/contacts.sgml +++ b/doc/src/sgml/contacts.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/contacts.sgml,v 1.9 2006/03/10 19:10:47 momjian Exp $ --> +<!-- doc/src/sgml/contacts.sgml --> <appendix label="B" id="contacts"> <title>Contacts</title> @@ -15,7 +15,7 @@ and the mailing lists themselves. <para> Refer to the introduction in this manual or to the -<productname>PostgreSQL</productname> +<productname>PostgreSQL</productname> <ulink url="http://www.postgresql.org">web page</ulink> for subscription information to the no-cost mailing lists. </para> diff --git a/doc/src/sgml/contrib-spi.sgml b/doc/src/sgml/contrib-spi.sgml index 62ef9ef2a2..3287c18d27 100644 --- a/doc/src/sgml/contrib-spi.sgml +++ b/doc/src/sgml/contrib-spi.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/contrib-spi.sgml,v 1.2 2007/12/06 04:12:09 tgl Exp $ --> +<!-- doc/src/sgml/contrib-spi.sgml --> -<sect1 id="contrib-spi"> +<sect1 id="contrib-spi" xreflabel="spi"> <title>spi</title> <indexterm zone="contrib-spi"> @@ -9,7 +9,7 @@ </indexterm> <para> - The <filename>contrib/spi</> module provides several workable examples + The <application>spi</> module provides several workable examples of using SPI and triggers. While these functions are of some value in their own right, they are even more useful as examples to modify for your own purposes. The functions are general enough to be used @@ -17,8 +17,13 @@ below) while creating a trigger. </para> + <para> + Each of the groups of functions described below is provided as a + separately-installable extension. + </para> + <sect2> - <title>refint.c — functions for implementing referential integrity</title> + <title>refint — Functions for Implementing Referential Integrity</title> <para> <function>check_primary_key()</> and @@ -59,7 +64,7 @@ </sect2> <sect2> - <title>timetravel.c — functions for implementing time travel</title> + <title>timetravel — Functions for Implementing Time Travel</title> <para> Long ago, <productname>PostgreSQL</> had a built-in time travel feature @@ -133,8 +138,8 @@ CREATE TABLE mytab ( <para> <function>set_timetravel()</> allows you to turn time-travel on or off for a table. - <literal>set_timetravel('mytab', 1)</> will turn TT ON for table mytab. - <literal>set_timetravel('mytab', 0)</> will turn TT OFF for table mytab. + <literal>set_timetravel('mytab', 1)</> will turn TT ON for table <literal>mytab</>. + <literal>set_timetravel('mytab', 0)</> will turn TT OFF for table <literal>mytab</>. In both cases the old status is reported. While TT is off, you can modify the start_date and stop_date columns freely. Note that the on/off status is local to the current database session — fresh sessions will @@ -152,7 +157,7 @@ CREATE TABLE mytab ( </sect2> <sect2> - <title>autoinc.c — functions for autoincrementing fields</title> + <title>autoinc — Functions for Autoincrementing Fields</title> <para> <function>autoinc()</> is a trigger that stores the next value of @@ -179,7 +184,7 @@ CREATE TABLE mytab ( </sect2> <sect2> - <title>insert_username.c — functions for tracking who changed a table</title> + <title>insert_username — Functions for Tracking Who Changed a Table</title> <para> <function>insert_username()</> is a trigger that stores the current @@ -200,7 +205,7 @@ CREATE TABLE mytab ( </sect2> <sect2> - <title>moddatetime.c — functions for tracking last modification time</title> + <title>moddatetime — Functions for Tracking Last Modification Time</title> <para> <function>moddatetime()</> is a trigger that stores the current @@ -211,7 +216,9 @@ CREATE TABLE mytab ( <para> To use, create a <literal>BEFORE UPDATE</> trigger using this function. Specify a single trigger - argument: the name of the <type>timestamp</> column to be modified. + argument: the name of the column to be modified. + The column must be of type <type>timestamp</> or <type>timestamp with + time zone</>. </para> <para> diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml index b801c40443..adf09ca872 100644 --- a/doc/src/sgml/contrib.sgml +++ b/doc/src/sgml/contrib.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/contrib.sgml,v 1.18 2010/06/14 17:25:24 sriggs Exp $ --> +<!-- doc/src/sgml/contrib.sgml --> <appendix id="contrib"> <title>Additional Supplied Modules</title> @@ -16,7 +16,7 @@ <para> When building from the source distribution, these modules are not built - automatically, unless you build the "world" target + automatically, unless you build the "world" target (see <xref linkend="build">). You can build and install all of them by running: <screen> @@ -46,41 +46,49 @@ <para> Many modules supply new user-defined functions, operators, or types. To make use of one of these modules, after you have installed the code - you need to register the new objects in the database - system by running the SQL commands in the <literal>.sql</> file - supplied by the module. For example, + you need to register the new SQL objects in the database system. + In <productname>PostgreSQL</> 9.1 and later, this is done by executing + a <xref linkend="sql-createextension"> command. In a fresh database, + you can simply do <programlisting> -psql -d dbname -f <replaceable>SHAREDIR</>/contrib/<replaceable>module</>.sql +CREATE EXTENSION <replaceable>module_name</>; </programlisting> - Here, <replaceable>SHAREDIR</> means the installation's <quote>share</> - directory (<literal>pg_config --sharedir</> will tell you what this is). - In most cases the script must be run by a database superuser. - </para> - - <para> - You need to run the <literal>.sql</> file in each database that you want + This command must be run by a database superuser. This registers the + new SQL objects in the current database only, so you need to run this + command in each database that you want the module's facilities to be available in. Alternatively, run it in - database <literal>template1</> so that the module will be copied into + database <literal>template1</> so that the extension will be copied into subsequently-created databases by default. </para> <para> - You can modify the first command in the <literal>.sql</> file to determine - which schema within the database the module's objects will be created in. - By default, they will be placed in <literal>public</>. + Many modules allow you to install their objects in a schema of your + choice. To do that, add <literal>SCHEMA + <replaceable>schema_name</></literal> to the <command>CREATE EXTENSION</> + command. By default, the objects will be placed in your current creation + target schema, typically <literal>public</>. </para> <para> - After a major-version upgrade of <productname>PostgreSQL</>, run the - installation script again, even though the module's objects might have - been brought forward from the old installation by dump and restore. - This ensures that any new functions will be available and any needed - corrections will be applied. + If your database was brought forward by dump and reload from a pre-9.1 + version of <productname>PostgreSQL</>, and you had been using the pre-9.1 + version of the module in it, you should instead do + +<programlisting> +CREATE EXTENSION <replaceable>module_name</> FROM unpackaged; +</programlisting> + + This will update the pre-9.1 objects of the module into a proper + <firstterm>extension</> object. Future updates to the module will be + managed by <xref linkend="sql-alterextension">. + For more information about extension updates, see + <xref linkend="extend-extensions">. </para> &adminpack; + &auth-delay; &auto-explain; &btree-gin; &btree-gist; @@ -90,7 +98,9 @@ psql -d dbname -f <replaceable>SHAREDIR</>/contrib/<replaceable>module</>.sql &dblink; &dict-int; &dict-xsyn; + &dummy-seclabel; &earthdistance; + &file-fdw; &fuzzystrmatch; &hstore; &intagg; @@ -110,9 +120,11 @@ psql -d dbname -f <replaceable>SHAREDIR</>/contrib/<replaceable>module</>.sql &pgstandby; &pgstatstatements; &pgstattuple; + &pgtestfsync; &pgtrgm; &pgupgrade; &seg; + &sepgsql; &contrib-spi; &sslinfo; &tablefunc; diff --git a/doc/src/sgml/cube.sgml b/doc/src/sgml/cube.sgml index 7c28a81f5c..e2da68556d 100644 --- a/doc/src/sgml/cube.sgml +++ b/doc/src/sgml/cube.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/cube.sgml,v 1.7 2009/12/08 20:08:30 mha Exp $ --> +<!-- doc/src/sgml/cube.sgml --> -<sect1 id="cube"> +<sect1 id="cube" xreflabel="cube"> <title>cube</title> <indexterm zone="cube"> @@ -9,7 +9,7 @@ <para> This module implements a data type <type>cube</> for - representing multi-dimensional cubes. + representing multidimensional cubes. </para> <sect2> @@ -23,7 +23,7 @@ </para> <table id="cube-repr-table"> - <title>Cube external representations</title> + <title>Cube External Representations</title> <tgroup cols="2"> <tbody> <row> @@ -98,59 +98,76 @@ <para> The <filename>cube</> module includes a GiST index operator class for <type>cube</> values. - The operators supported by the GiST opclass include: + The operators supported by the GiST operator class are shown in <xref linkend="cube-gist-operators">. </para> - <itemizedlist> - <listitem> - <programlisting> -a = b Same as - </programlisting> - <para> - The cubes a and b are identical. - </para> - </listitem> - <listitem> - <programlisting> -a && b Overlaps - </programlisting> - <para> - The cubes a and b overlap. - </para> - </listitem> - <listitem> - <programlisting> -a @> b Contains - </programlisting> - <para> - The cube a contains the cube b. - </para> - </listitem> - <listitem> - <programlisting> -a <@ b Contained in - </programlisting> - <para> - The cube a is contained in the cube b. - </para> - </listitem> - </itemizedlist> + <table id="cube-gist-operators"> + <title>Cube GiST Operators</title> + <tgroup cols="2"> + <thead> + <row> + <entry>Operator</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><literal>a = b</></entry> + <entry>The cubes a and b are identical.</entry> + </row> + + <row> + <entry><literal>a && b</></entry> + <entry>The cubes a and b overlap.</entry> + </row> + + <row> + <entry><literal>a @> b</></entry> + <entry>The cube a contains the cube b.</entry> + </row> + + <row> + <entry><literal>a <@ b</></entry> + <entry>The cube a is contained in the cube b.</entry> + </row> + </tbody> + </tgroup> + </table> <para> - (Before PostgreSQL 8.2, the containment operators @> and <@ were - respectively called @ and ~. These names are still available, but are + (Before PostgreSQL 8.2, the containment operators <literal>@></> and <literal><@</> were + respectively called <literal>@</> and <literal>~</>. These names are still available, but are deprecated and will eventually be retired. Notice that the old names are reversed from the convention formerly followed by the core geometric - datatypes!) + data types!) </para> <para> The standard B-tree operators are also provided, for example - <programlisting> -[a, b] < [c, d] Less than -[a, b] > [c, d] Greater than - </programlisting> + <informaltable> + <tgroup cols="2"> + <thead> + <row> + <entry>Operator</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><literal>[a, b] < [c, d]</literal></entry> + <entry>Less than</entry> + </row> + + <row> + <entry><literal>[a, b] > [c, d]</literal></entry> + <entry>Greater than</entry> + </row> + </tbody> + </tgroup> + </informaltable> These operators do not make a lot of sense for any practical purpose but sorting. These operators first compare (a) to (c), @@ -164,7 +181,7 @@ a <@ b Contained in </para> <table id="cube-functions-table"> - <title>Cube functions</title> + <title>Cube Functions</title> <tgroup cols="2"> <tbody> <row> @@ -322,7 +339,7 @@ cube_inter <para> In all binary operations on differently-dimensioned cubes, I assume the - lower-dimensional one to be a cartesian projection, i. e., having zeroes + lower-dimensional one to be a Cartesian projection, i. e., having zeroes in place of coordinates omitted in the string representation. The above examples are equivalent to: </para> diff --git a/doc/src/sgml/cvs.sgml b/doc/src/sgml/cvs.sgml deleted file mode 100644 index 58061405e2..0000000000 --- a/doc/src/sgml/cvs.sgml +++ /dev/null @@ -1,271 +0,0 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/cvs.sgml,v 1.52 2009/12/07 19:19:56 mha Exp $ --> - -<appendix id="cvs"> - <appendixinfo> - <authorgroup> - <author> - <firstname>Marc</firstname> - <surname>Fournier</surname> - </author> - <author> - <firstname>Tom</firstname> - <surname>Lane</surname> - </author> - <author> - <firstname>Thomas</firstname> - <surname>Lockhart</surname> - </author> - <author> - <firstname>David</firstname> - <surname>Fetter</surname> - </author> - </authorgroup> - <date>1999-05-20</date> - </appendixinfo> - - <title>The Source Code Repository</title> - - <para> - The <productname>PostgreSQL</productname> source code is stored and managed using the - <productname>CVS</productname> version control system. An official mirror using - <productname>Git</productname> is also available, for those who wish to use a - distributed version control system. This mirror is automatically - updated whenever the main repository changes, so it always contains the latest - versions of all branches. - </para> - - <para> - Using <productname>git</> is the most flexible way to work with the source, and it - allows you to work offline without having constant access to the project servers. - <productname>rsync</> based <productname>cvs</> also lets you work offline, but - lacks many of the other advantages of <productname>git</>. - </para> - - <para> - Our Wiki, <ulink - url="http://wiki.postgresql.org/wiki/Working_with_CVS"></ulink> and - <ulink url="http://wiki.postgresql.org/wiki/Working_with_Git"></ulink>, - has additional details on working with CVS and Git. - </para> - - <sect1 id="git"> - <title>Getting The Source Via <productname>Git</></title> - - <para> - With <productname>git</> you will make a copy of the entire code repository - to your local machine, so you will have access to all history and branches - offline. This is the fastest and most flexible way to develop or test - patches. - </para> - - <procedure> - <title>Git</title> - - <step> - <para> - You will need an installed version of <productname>git</>, which you can get - from <ulink url="http://git-scm.com"></ulink>. Many systems also have a recent - version of <application>git</> installed by default, or available in their - package repository system. - </para> - </step> - - <step> - <para> - To being using the git repository, make a clone of the official mirror: - -<programlisting> -git clone git://git.postgresql.org/git/postgresql.git -</programlisting> - - This will copy the full repository to your local machine, so it may take - a while to complete, especially if you have a slow internet connection. - </para> - - <para> - The git mirror can also be reached via the http protocol in case for example - a firewall is blocking access to the git protocol. Just replace the URL - like: - -<programlisting> -git clone http://git.postgresql.org/git/postgresql.git -</programlisting> - - The http protocol is less efficient than the git protocol, so it will be - slightly slower to use. - </para> - </step> - - <step> - <para> - Whenever you want to get the latest updates in the system, <command>cd</> - into the repository, and run: - -<programlisting> -git fetch -</programlisting> - </para> - </step> - </procedure> - <para> - <productname>git</> can do a lot more things than just fetch the source. For - more information, consult the man pages for the product, or the website at - <ulink url="http://git-scm.com"></>. - </para> - </sect1> - - <sect1 id="anoncvs"> - <title>Getting The Source Via Anonymous <productname>CVS</productname></title> - - <para> - If you would like to keep up with the current sources on a regular - basis, you can fetch them from our <productname>CVS</productname> server - and then use <productname>CVS</productname> to - retrieve updates from time to time. - </para> - - <procedure> - <title>Anonymous CVS</title> - - <step> - <para> - You will need a local copy of <productname>CVS</productname> - (Concurrent Version Control System), which you can get from - <ulink url="http://www.nongnu.org/cvs/"></ulink> (the official - site with the latest version) or any GNU software archive site - (often somewhat outdated). Many systems have a recent version of - <application>cvs</application> installed by default. - </para> - </step> - - <step> - <para> - Do an initial login to the <productname>CVS</productname> server: - -<programlisting> -cvs -d :pserver:anoncvs@anoncvs.postgresql.org:/projects/cvsroot login -</programlisting> - - You will be prompted for a password; you can enter anything except - an empty string. - </para> - - <para> - You should only need to do this once, since the password will be - saved in <filename>.cvspass</filename> in your home directory. - </para> - </step> - - <step> - <para> - Fetch the <productname>PostgreSQL</productname> sources: -<programlisting> -cvs -z3 -d :pserver:anoncvs@anoncvs.postgresql.org:/projects/cvsroot co -P pgsql -</programlisting> - - This installs the <productname>PostgreSQL</productname> sources into a - subdirectory <filename>pgsql</filename> - of the directory you are currently in. - </para> - - <para> - This initial checkout is a little slower than simply downloading - a <filename>tar.gz</filename> file. The advantage of <productname>CVS</> - doesn't show up until you want to update the file set later on. - </para> - </step> - - <step> - <para> - Whenever you want to update to the latest <productname>CVS</productname> sources, - <command>cd</command> into - the <filename>pgsql</filename> subdirectory, and issue: -<programlisting> -cvs -z3 update -d -P -</programlisting> - - This will fetch only the changes since the last time you updated. - You can update in just a couple of minutes, typically, even over - a modem-speed line. - </para> - </step> - - <step> - <para> - You can save yourself some typing by making a file <filename>.cvsrc</filename> - in your home directory that contains: - -<programlisting> -cvs -z3 -update -d -P -</programlisting> - - This supplies the <option>-z3</option> option to all <command>cvs</> commands, and the - <option>-d</option> and <option>-P</option> options to <command>cvs update</>. Then you just have - to say: -<programlisting> -cvs update -</programlisting> - - to update your files. - </para> - </step> - </procedure> - - <para> - <productname>CVS</productname> can do a lot of other things, such - as fetching prior revisions of the - <productname>PostgreSQL</productname> sources rather than the - latest development version. For more info consult the manual that - comes with <productname>CVS</productname>, or see the online - documentation at <ulink url="http://www.nongnu.org/cvs/"></ulink>. - </para> - <para> - <productname>CVS</productname> has deficiencies. For example, - generating diffs that add or remove files requires write access to the - CVS repository. To work around that deficiency, use - <productname>cvsutils</productname>, which is packaged in several - operating systems, and is available in source form at <ulink - url="http://www.red-bean.com/cvsutils/"></ulink>, or use <productname>git</> - or another system designed to work offline. - </para> - - <para> - Note that building <productname>PostgreSQL</productname> from a CVS - pull requires reasonably up-to-date versions of <application>bison</> - and <application>flex</>, which are not needed to build from a distribution - tarball because the files made with them are pre-built in a tarball. - You will need Perl as well. - Otherwise the tool requirements are the same as building from source. - </para> - </sect1> - - <sect1 id="rsync"> - <title>Getting The Source Via <productname>rsync</productname></title> - - <para> - An alternative to using anonymous CVS for retrieving the - <productname>PostgreSQL</productname> source tree is - <productname>rsync</productname>, an incremental file transfer tool. - A major advantage to using <productname>rsync</productname> instead of - plain <productname>cvs</> is that it - can reliably replicate the <emphasis>entire</emphasis> CVS repository - on your local system, allowing fast local access to <command>cvs</> - operations such as <option>log</option> and <option>diff</option>. - Other advantages include fast synchronization to the - <productname>PostgreSQL</productname> server due to an efficient - streaming transfer protocol which only sends the changes since the last - update. - </para> - - <para> - You can download the CVS repository using this command: -<programlisting> -rsync -avzH --delete anoncvs.postgresql.org::pgsql-cvs cvsroot/ -</programlisting> - For full instructions, see the "rsync" section in the - <ulink url="http://pgfoundry.org/docman/view.php/1000040/4/PGBuildFarm-HOWTO.txt"> - pgbuildfarm instructions</ulink>. - </para> - </sect1> -</appendix> diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 20bf2ea9fa..ab8eb2d30b 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.250 2010/07/03 04:03:06 tgl Exp $ --> +<!-- doc/src/sgml/datatype.sgml --> <chapter id="datatype"> <title>Data Types</title> @@ -21,7 +21,7 @@ <para> <xref linkend="datatype-table"> shows all the built-in general-purpose data - types. Most of the alternative names listed in the + types. Most of the alternative names listed in the <quote>Aliases</quote> column are the names used internally by <productname>PostgreSQL</productname> for historical reasons. In addition, some internally used or deprecated types are available, @@ -346,13 +346,13 @@ <entry><type>decimal</></entry> <entry>variable</entry> <entry>user-specified precision, exact</entry> - <entry>no limit</entry> + <entry>up to 131072 digits before the decimal point; up to 16383 digits after the decimal point</entry> </row> <row> <entry><type>numeric</></entry> <entry>variable</entry> <entry>user-specified precision, exact</entry> - <entry>no limit</entry> + <entry>up to 131072 digits before the decimal point; up to 16383 digits after the decimal point</entry> </row> <row> @@ -435,7 +435,7 @@ the best balance between range, storage size, and performance. The <type>smallint</type> type is generally only used if disk space is at a premium. The <type>bigint</type> type should only - be used if the <type>integer</type> range is insufficient, + be used if the range of the <type>integer</type> type is insufficient, because the latter is definitely faster. </para> @@ -476,8 +476,8 @@ </indexterm> <para> - The type <type>numeric</type> can store numbers with up to 1000 - digits of precision and perform calculations exactly. It is + The type <type>numeric</type> can store numbers with a + very large number of digits and perform calculations exactly. It is especially recommended for storing monetary amounts and other quantities where exactness is required. However, arithmetic on <type>numeric</type> values is very slow compared to the integer @@ -525,6 +525,15 @@ NUMERIC explicitly.) </para> + <note> + <para> + The maximum allowed precision when explicitly specified in the + type declaration is 1000; <type>NUMERIC</type> without a specified + precision is subject to the limits described in <xref + linkend="datatype-numeric-table">. + </para> + </note> + <para> If the scale of a value to be stored is greater than the declared scale of the column, the system will round the value to the specified @@ -555,7 +564,7 @@ NUMERIC <para> In addition to ordinary numeric values, the <type>numeric</type> - type allows the special value <literal>NaN</>, meaning + type allows the special value <literal>NaN</>, meaning <quote>not-a-number</quote>. Any operation on <literal>NaN</> yields another <literal>NaN</>. When writing this value as a constant in an SQL command, you must put quotes around it, @@ -703,9 +712,9 @@ NUMERIC <type>float(<replaceable>p</replaceable>)</type> for specifying inexact numeric types. Here, <replaceable>p</replaceable> specifies the minimum acceptable precision in <emphasis>binary</> digits. - <productname>PostgreSQL</productname> accepts + <productname>PostgreSQL</productname> accepts <type>float(1)</type> to <type>float(24)</type> as selecting the - <type>real</type> type, while + <type>real</type> type, while <type>float(25)</type> to <type>float(53)</type> select <type>double precision</type>. Values of <replaceable>p</replaceable> outside the allowed range draw an error. @@ -839,32 +848,11 @@ ALTER SEQUENCE <replaceable class="parameter">tablename</replaceable>_<replaceab fractional precision; see <xref linkend="datatype-money-table">. The fractional precision is determined by the database's <xref linkend="guc-lc-monetary"> setting. + The range shown in the table assumes there are two fractional digits. Input is accepted in a variety of formats, including integer and floating-point literals, as well as typical currency formatting, such as <literal>'$1,000.00'</literal>. Output is generally in the latter form but depends on the locale. - Non-quoted numeric values can be converted to <type>money</type> by - casting the numeric value to <type>text</type> and then - <type>money</type>, for example: -<programlisting> -SELECT 1234::text::money; -</programlisting> - There is no simple way of doing the reverse in a locale-independent - manner, namely casting a <type>money</type> value to a numeric type. - If you know the currency symbol and thousands separator you can use - <function>regexp_replace()</>: -<programlisting> -SELECT regexp_replace('52093.89'::money::text, '[$,]', '', 'g')::numeric; -</programlisting> - - </para> - - <para> - Since the output of this data type is locale-sensitive, it might not - work to load <type>money</> data into a database that has a different - setting of <varname>lc_monetary</>. To avoid problems, before - restoring a dump into a new database make sure <varname>lc_monetary</> has the same or - equivalent value as in the database that was dumped. </para> <table id="datatype-money-table"> @@ -888,6 +876,42 @@ SELECT regexp_replace('52093.89'::money::text, '[$,]', '', 'g')::numeric; </tbody> </tgroup> </table> + + <para> + Since the output of this data type is locale-sensitive, it might not + work to load <type>money</> data into a database that has a different + setting of <varname>lc_monetary</>. To avoid problems, before + restoring a dump into a new database make sure <varname>lc_monetary</> has + the same or equivalent value as in the database that was dumped. + </para> + + <para> + Values of the <type>numeric</type>, <type>int</type>, and + <type>bigint</type> data types can be cast to <type>money</type>. + Conversion from the <type>real</type> and <type>double precision</type> + data types can be done by casting to <type>numeric</type> first, for + example: +<programlisting> +SELECT '12.34'::float8::numeric::money; +</programlisting> + However, this is not recommended. Floating point numbers should not be + used to handle money due to the potential for rounding errors. + </para> + + <para> + A <type>money</type> value can be cast to <type>numeric</type> without + loss of precision. Conversion to other types could potentially lose + precision, and must also be done in two stages: +<programlisting> +SELECT '52093.89'::money::numeric::float8; +</programlisting> + </para> + + <para> + When a <type>money</type> value is divided by another <type>money</type> + value, the result is <type>double precision</type> (i.e., a pure number, + not money); the currency units cancel each other out in the division. + </para> </sect1> @@ -1010,7 +1034,9 @@ SELECT regexp_replace('52093.89'::money::text, '[$,]', '', 'g')::numeric; and they will be removed when converting a <type>character</type> value to one of the other string types. Note that trailing spaces <emphasis>are</> semantically significant in - <type>character varying</type> and <type>text</type> values. + <type>character varying</type> and <type>text</type> values, and + when using pattern matching, e.g. <literal>LIKE</>, + regular expressions. </para> <para> @@ -1057,7 +1083,7 @@ SELECT regexp_replace('52093.89'::money::text, '[$,]', '', 'g')::numeric; </para> <example> - <title>Using the character types</title> + <title>Using the Character Types</title> <programlisting> CREATE TABLE test1 (a character(4)); @@ -1210,7 +1236,7 @@ SELECT b, char_length(b) FROM test2; </para> <sect2> - <title><type>bytea</> hex format</title> + <title><type>bytea</> Hex Format</title> <para> The <quote>hex</> format encodes binary data as 2 hexadecimal digits @@ -1237,7 +1263,7 @@ SELECT E'\\xDEADBEEF'; </sect2> <sect2> - <title><type>bytea</> escape format</title> + <title><type>bytea</> Escape Format</title> <para> The <quote>escape</quote> format is the traditional @@ -1248,7 +1274,7 @@ SELECT E'\\xDEADBEEF'; represented as an ASCII character into special escape sequences. If, from the point of view of the application, representing bytes as characters makes sense, then this representation can be - convenient. But in practice it is usually confusing becauses it + convenient. But in practice it is usually confusing because it fuzzes up the distinction between binary strings and character strings, and also the particular escape mechanism that was chosen is somewhat unwieldy. So this format should probably be avoided @@ -1435,6 +1461,9 @@ SELECT E'\\xDEADBEEF'; <primary>timestamp</primary> </indexterm> <indexterm zone="datatype-datetime"> + <primary>timestamptz</primary> + </indexterm> + <indexterm zone="datatype-datetime"> <primary>timestamp with time zone</primary> </indexterm> <indexterm zone="datatype-datetime"> @@ -1527,7 +1556,9 @@ SELECT E'\\xDEADBEEF'; be equivalent to <type>timestamp without time zone</type>, and <productname>PostgreSQL</productname> honors that behavior. (Releases prior to 7.3 treated it as <type>timestamp - with time zone</type>.) + with time zone</type>.) <type>timestamptz</type> is accepted as an + abbreviation for <type>timestamp with time zone</type>; this is a + <productname>PostgreSQL</productname> extension. </para> </note> @@ -1576,21 +1607,21 @@ SELECT E'\\xDEADBEEF'; <para> The <type>interval</type> type has an additional option, which is to restrict the set of stored fields by writing one of these phrases: -<programlisting> - YEAR - MONTH - DAY - HOUR - MINUTE - SECOND - YEAR TO MONTH - DAY TO HOUR - DAY TO MINUTE - DAY TO SECOND - HOUR TO MINUTE - HOUR TO SECOND - MINUTE TO SECOND -</programlisting> +<literallayout class="monospaced"> +YEAR +MONTH +DAY +HOUR +MINUTE +SECOND +YEAR TO MONTH +DAY TO HOUR +DAY TO MINUTE +DAY TO SECOND +HOUR TO MINUTE +HOUR TO SECOND +MINUTE TO SECOND +</literallayout> Note that if both <replaceable>fields</replaceable> and <replaceable>p</replaceable> are specified, the <replaceable>fields</replaceable> must include <literal>SECOND</>, @@ -1620,7 +1651,7 @@ SELECT E'\\xDEADBEEF'; <para> Date and time input is accepted in almost any reasonable format, including - ISO 8601, <acronym>SQL</acronym>-compatible, + ISO 8601, <acronym>SQL</acronym>-compatible, traditional <productname>POSTGRES</productname>, and others. For some formats, ordering of day, month, and year in date input is ambiguous and there is support for specifying the expected @@ -1637,12 +1668,12 @@ SELECT E'\\xDEADBEEF'; See <xref linkend="datetime-appendix"> for the exact parsing rules of date/time input and for the recognized text fields including months, days of the week, and - time zones. + time zones. </para> <para> Remember that any date or time literal input needs to be enclosed - in single quotes, like text strings. Refer to + in single quotes, like text strings. Refer to <xref linkend="sql-syntax-constants-generic"> for more information. <acronym>SQL</acronym> requires the following syntax @@ -1664,7 +1695,7 @@ SELECT E'\\xDEADBEEF'; <indexterm> <primary>date</primary> </indexterm> - + <para> <xref linkend="datatype-datetime-date-table"> shows some possible inputs for the <type>date</type> type. @@ -1779,7 +1810,7 @@ SELECT E'\\xDEADBEEF'; <para> Valid input for these types consists of a time of day followed by an optional time zone. (See <xref - linkend="datatype-datetime-time-table"> + linkend="datatype-datetime-time-table"> and <xref linkend="datatype-timezone-table">.) If a time zone is specified in the input for <type>time without time zone</type>, it is silently ignored. You can also specify a date but it will @@ -1946,8 +1977,8 @@ January 8 04:05:06 1999 PST <para> The <acronym>SQL</acronym> standard differentiates - <type>timestamp without time zone</type> - and <type>timestamp with time zone</type> literals by the presence of a + <type>timestamp without time zone</type> + and <type>timestamp with time zone</type> literals by the presence of a <quote>+</quote> or <quote>-</quote> symbol and time zone offset after the time. Hence, according to the standard, @@ -2089,10 +2120,10 @@ January 8 04:05:06 1999 PST The following <acronym>SQL</acronym>-compatible functions can also be used to obtain the current time value for the corresponding data type: - <literal>CURRENT_DATE</literal>, <literal>CURRENT_TIME</literal>, - <literal>CURRENT_TIMESTAMP</literal>, <literal>LOCALTIME</literal>, - <literal>LOCALTIMESTAMP</literal>. The latter four accept an - optional subsecond precision specification. (See <xref + <literal>CURRENT_DATE</literal>, <literal>CURRENT_TIME</literal>, + <literal>CURRENT_TIMESTAMP</literal>, <literal>LOCALTIME</literal>, + <literal>LOCALTIMESTAMP</literal>. The latter four accept an + optional subsecond precision specification. (See <xref linkend="functions-datetime-current">.) Note that these are SQL functions and are <emphasis>not</> recognized in data input strings. </para> @@ -2247,10 +2278,10 @@ January 8 04:05:06 1999 PST <itemizedlist> <listitem> <para> - Although the <type>date</type> type + Although the <type>date</type> type cannot have an associated time zone, the <type>time</type> type can. - Time zones in the real world have little meaning unless + Time zones in the real world have little meaning unless associated with a date as well as a time, since the offset can vary through the year with daylight-saving time boundaries. @@ -2259,7 +2290,7 @@ January 8 04:05:06 1999 PST <listitem> <para> - The default time zone is specified as a constant numeric offset + The default time zone is specified as a constant numeric offset from <acronym>UTC</>. It is therefore impossible to adapt to daylight-saving time when doing date/time arithmetic across <acronym>DST</acronym> boundaries. @@ -2479,7 +2510,7 @@ P <replaceable>quantity</> <replaceable>unit</> <optional> <replaceable>quantity </para> <table id="datatype-interval-iso8601-units"> - <title>ISO 8601 interval unit abbreviations</title> + <title>ISO 8601 Interval Unit Abbreviations</title> <tgroup cols="2"> <thead> <row> @@ -2751,13 +2782,34 @@ P <optional> <replaceable>years</>-<replaceable>months</>-<replaceable>days</> < <para> <productname>PostgreSQL</productname> provides the - standard <acronym>SQL</acronym> type <type>boolean</type>. - <type>boolean</type> can have one of only two states: - <quote>true</quote> or <quote>false</quote>. A third state, - <quote>unknown</quote>, is represented by the + standard <acronym>SQL</acronym> type <type>boolean</type>; + see <xref linkend="datatype-boolean-table">. + The <type>boolean</type> type can have several states: + <quote>true</quote>, <quote>false</quote>, and a third state, + <quote>unknown</quote>, which is represented by the <acronym>SQL</acronym> null value. </para> + <table id="datatype-boolean-table"> + <title>Boolean Data Type</title> + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Storage Size</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><type>boolean</type></entry> + <entry>1 byte</entry> + <entry>state of true or false</entry> + </row> + </tbody> + </tgroup> + </table> + <para> Valid literal values for the <quote>true</quote> state are: <simplelist> @@ -2786,8 +2838,14 @@ P <optional> <replaceable>years</>-<replaceable>months</>-<replaceable>days</> < (<acronym>SQL</acronym>-compliant) usage. </para> + <para> + <xref linkend="datatype-boolean-example"> shows that + <type>boolean</type> values are output using the letters + <literal>t</literal> and <literal>f</literal>. + </para> + <example id="datatype-boolean-example"> - <title>Using the <type>boolean</type> type</title> + <title>Using the <type>boolean</type> Type</title> <programlisting> CREATE TABLE test1 (a boolean, b text); @@ -2805,16 +2863,6 @@ SELECT * FROM test1 WHERE a; t | sic est </programlisting> </example> - - <para> - <xref linkend="datatype-boolean-example"> shows that - <type>boolean</type> values are output using the letters - <literal>t</literal> and <literal>f</literal>. - </para> - - <para> - <type>boolean</type> uses 1 byte of storage. - </para> </sect1> <sect1 id="datatype-enum"> @@ -2852,10 +2900,6 @@ CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy'); Once created, the enum type can be used in table and function definitions much like any other type: - </para> - - <example> - <title>Basic Enum Usage</title> <programlisting> CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy'); CREATE TABLE person ( @@ -2869,7 +2913,7 @@ SELECT * FROM person WHERE current_mood = 'happy'; Moe | happy (1 row) </programlisting> - </example> + </para> </sect2> <sect2> @@ -2880,10 +2924,7 @@ SELECT * FROM person WHERE current_mood = 'happy'; order in which the values were listed when the type was created. All standard comparison operators and related aggregate functions are supported for enums. For example: - </para> - <example> - <title>Enum Ordering</title> <programlisting> INSERT INTO person VALUES ('Larry', 'sad'); INSERT INTO person VALUES ('Curly', 'ok'); @@ -2901,7 +2942,7 @@ SELECT * FROM person WHERE current_mood > 'sad' ORDER BY current_mood; Moe | happy (2 rows) -SELECT name +SELECT name FROM person WHERE current_mood = (SELECT MIN(current_mood) FROM person); name @@ -2909,7 +2950,7 @@ WHERE current_mood = (SELECT MIN(current_mood) FROM person); Larry (1 row) </programlisting> - </example> + </para> </sect2> <sect2> @@ -2917,11 +2958,8 @@ WHERE current_mood = (SELECT MIN(current_mood) FROM person); <para> Each enumerated data type is separate and cannot - be compared with other enumerated types. - </para> + be compared with other enumerated types. See this example: - <example> - <title>Lack of Casting</title> <programlisting> CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic'); CREATE TABLE holidays ( @@ -2937,15 +2975,12 @@ SELECT person.name, holidays.num_weeks FROM person, holidays WHERE person.current_mood = holidays.happiness; ERROR: operator does not exist: mood = happiness </programlisting> - </example> + </para> <para> If you really need to do something like that, you can either write a custom operator or add explicit casts to your query: - </para> - <example> - <title>Comparing Different Enums by Casting to Text</title> <programlisting> SELECT person.name, holidays.num_weeks FROM person, holidays WHERE person.current_mood::text = holidays.happiness::text; @@ -2955,12 +2990,12 @@ SELECT person.name, holidays.num_weeks FROM person, holidays (1 row) </programlisting> - </example> + </para> </sect2> <sect2> <title>Implementation Details</title> - + <para> An enum value occupies four bytes on disk. The length of an enum value's textual label is limited by the <symbol>NAMEDATALEN</symbol> @@ -3397,11 +3432,11 @@ SELECT person.name, holidays.num_weeks FROM person, holidays <table id="datatype-net-cidr-table"> <title><type>cidr</> Type Input Examples</title> <tgroup cols="3"> - <thead> - <row> + <thead> + <row> <entry><type>cidr</type> Input</entry> <entry><type>cidr</type> Output</entry> - <entry><literal><function>abbrev</function>(<type>cidr</type>)</literal></entry> + <entry><literal><function>abbrev(<type>cidr</type>)</function></literal></entry> </row> </thead> <tbody> @@ -3509,7 +3544,7 @@ SELECT person.name, holidays.num_weeks FROM person, holidays </sect2> <sect2 id="datatype-macaddr"> - <title><type>macaddr</></> + <title><type>macaddr</type></title> <indexterm> <primary>macaddr (data type)</primary> @@ -3607,7 +3642,7 @@ SELECT person.name, holidays.num_weeks FROM person, holidays </para> <example> - <title>Using the bit string types</title> + <title>Using the Bit String Types</title> <programlisting> CREATE TABLE test (a BIT(3), b BIT VARYING(5)); @@ -3760,7 +3795,7 @@ select 'The Fat Rats'::tsvector; for searching: <programlisting> -SELECT to_tsvector('english', 'The Fat Rats'); +SELECT to_tsvector('english', 'The Fat Rats'); to_tsvector ----------------- 'fat':2 'rat':3 @@ -3780,13 +3815,13 @@ SELECT to_tsvector('english', 'The Fat Rats'); <para> A <type>tsquery</type> value stores lexemes that are to be - searched for, and combines them honoring the boolean operators + searched for, and combines them honoring the Boolean operators <literal>&</literal> (AND), <literal>|</literal> (OR), and <literal>!</> (NOT). Parentheses can be used to enforce grouping of the operators: <programlisting> - SELECT 'fat & rat'::tsquery; +SELECT 'fat & rat'::tsquery; tsquery --------------- 'fat' & 'rat' @@ -3830,7 +3865,25 @@ SELECT 'super:*'::tsquery; 'super':* </programlisting> This query will match any word in a <type>tsvector</> that begins - with <quote>super</>. + with <quote>super</>. Note that prefixes are first processed by + text search configurations, which means this comparison returns + true: +<programlisting> +SELECT to_tsvector( 'postgraduate' ) @@ to_tsquery( 'postgres:*' ); + ?column? +---------- + t +(1 row) +</programlisting> + because <literal>postgres</> gets stemmed to <literal>postgr</>: +<programlisting> +SELECT to_tsquery('postgres:*'); + to_tsquery +------------ + 'postgr':* +(1 row) +</programlisting> + which then matches <literal>postgraduate</>. </para> <para> @@ -3900,9 +3953,9 @@ a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11 <productname>PostgreSQL</productname> provides storage and comparison functions for UUIDs, but the core database does not include any function for generating UUIDs, because no single algorithm is well - suited for every application. The contrib module - <filename>contrib/uuid-ossp</filename> provides functions that implement - several standard algorithms. + suited for every application. The <xref + linkend="uuid-ossp"> module + provides functions that implement several standard algorithms. Alternatively, UUIDs could be generated by client applications or other libraries invoked through a server-side function. </para> @@ -3921,7 +3974,7 @@ a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11 checks the input values for well-formedness, and there are support functions to perform type-safe operations on it; see <xref linkend="functions-xml">. Use of this data type requires the - installation to have been built with <command>configure + installation to have been built with <command>configure --with-libxml</>. </para> @@ -4397,6 +4450,10 @@ SELECT * FROM pg_attribute </indexterm> <indexterm zone="datatype-pseudo"> + <primary>fdw_handler</primary> + </indexterm> + + <indexterm zone="datatype-pseudo"> <primary>cstring</primary> </indexterm> @@ -4479,6 +4536,11 @@ SELECT * FROM pg_attribute </row> <row> + <entry><type>fdw_handler</></entry> + <entry>A foreign-data wrapper handler is declared to return <type>fdw_handler</>.</entry> + </row> + + <row> <entry><type>record</></entry> <entry>Identifies a function returning an unspecified row type.</entry> </row> diff --git a/doc/src/sgml/datetime.sgml b/doc/src/sgml/datetime.sgml index d072118869..707bd5abb6 100644 --- a/doc/src/sgml/datetime.sgml +++ b/doc/src/sgml/datetime.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/datetime.sgml,v 2.60 2009/03/22 01:12:31 tgl Exp $ --> +<!-- doc/src/sgml/datetime.sgml --> <appendix id="datetime-appendix"> <title>Date/Time Support</title> @@ -75,7 +75,7 @@ <para> If the token is a text string, match up with possible strings: </para> - + <substeps> <step> <para> @@ -83,7 +83,7 @@ abbreviation. </para> </step> - + <step> <para> If not found, do a similar binary-search table lookup to match @@ -101,7 +101,7 @@ </step> </substeps> </step> - + <step> <para> When the token is a number or number field: @@ -111,7 +111,7 @@ <step> <para> If there are eight or six digits, - and if no other date fields have been previously read, then interpret + and if no other date fields have been previously read, then interpret as a <quote>concatenated date</quote> (e.g., <literal>19990118</literal> or <literal>990118</literal>). The interpretation is <literal>YYYYMMDD</> or <literal>YYMMDD</>. @@ -124,7 +124,7 @@ and a year has already been read, then interpret as day of year. </para> </step> - + <step> <para> If four or six digits and a year has already been read, then @@ -360,10 +360,10 @@ </para> <para> - <literal>timezone_abbreviations</> can be set to any file name + <varname>timezone_abbreviations</> can be set to any file name found in <filename>.../share/timezonesets/</>, if the file's name is entirely alphabetic. (The prohibition against non-alphabetic - characters in <literal>timezone_abbreviations</> prevents reading + characters in <varname>timezone_abbreviations</> prevents reading files outside the intended directory, as well as reading editor backup files and other extraneous files.) </para> @@ -420,7 +420,7 @@ according to the <literal>zoneinfo</> timezone database. The zone name definitions found in these files can be copied and pasted into a custom configuration file as needed. Note that these files cannot be directly - referenced as <literal>timezone_abbreviations</> settings, because of + referenced as <varname>timezone_abbreviations</> settings, because of the dot embedded in their names. </para> @@ -465,7 +465,7 @@ about 1 day in 128 years. </para> - <para> + <para> The accumulating calendar error prompted Pope Gregory XIII to reform the calendar in accordance with instructions from the Council of Trent. @@ -544,7 +544,7 @@ $ <userinput>cal 9 1752</userinput> the beginnings of the Chinese calendar can be traced back to the 14th century BC. Legend has it that the Emperor Huangdi invented that calendar in 2637 BC. - + The People's Republic of China uses the Gregorian calendar for civil purposes. The Chinese calendar is used for determining festivals. @@ -552,7 +552,7 @@ $ <userinput>cal 9 1752</userinput> <para> The <quote>Julian Date</quote> is unrelated to the <quote>Julian - calendar</quote>. + calendar</quote>. The Julian Date system was invented by the French scholar Joseph Justus Scaliger (1540-1609) and probably takes its name from Scaliger's father, diff --git a/doc/src/sgml/dblink.sgml b/doc/src/sgml/dblink.sgml index e894a8cfc7..22551402e3 100644 --- a/doc/src/sgml/dblink.sgml +++ b/doc/src/sgml/dblink.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/dblink.sgml,v 1.13 2010/06/15 20:29:01 tgl Exp $ --> +<!-- doc/src/sgml/dblink.sgml --> -<sect1 id="dblink"> +<sect1 id="dblink" xreflabel="dblink"> <title>dblink</title> <indexterm zone="dblink"> @@ -25,10 +25,10 @@ </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_connect(text connstr) returns text - dblink_connect(text connname, text connstr) returns text - </synopsis> +<synopsis> +dblink_connect(text connstr) returns text +dblink_connect(text connname, text connstr) returns text +</synopsis> </refsynopsisdiv> <refsect1> @@ -116,66 +116,66 @@ <refsect1> <title>Example</title> - <programlisting> - select dblink_connect('dbname=postgres'); - dblink_connect - ---------------- - OK - (1 row) - - select dblink_connect('myconn', 'dbname=postgres'); - dblink_connect - ---------------- - OK - (1 row) - - -- FOREIGN DATA WRAPPER functionality - -- Note: local connection must require password authentication for this to work properly - -- Otherwise, you will receive the following error from dblink_connect(): - -- ---------------------------------------------------------------------- - -- ERROR: password is required - -- DETAIL: Non-superuser cannot connect if the server does not request a password. - -- HINT: Target server's authentication method must be changed. - CREATE USER dblink_regression_test WITH PASSWORD 'secret'; - CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator; - CREATE SERVER fdtest FOREIGN DATA WRAPPER postgresql OPTIONS (hostaddr '127.0.0.1', dbname 'contrib_regression'); - - CREATE USER MAPPING FOR dblink_regression_test SERVER fdtest OPTIONS (user 'dblink_regression_test', password 'secret'); - GRANT USAGE ON FOREIGN SERVER fdtest TO dblink_regression_test; - GRANT SELECT ON TABLE foo TO dblink_regression_test; - - \set ORIGINAL_USER :USER - \c - dblink_regression_test - SELECT dblink_connect('myconn', 'fdtest'); - dblink_connect - ---------------- - OK - (1 row) - - SELECT * FROM dblink('myconn','SELECT * FROM foo') AS t(a int, b text, c text[]); - a | b | c - ----+---+--------------- - 0 | a | {a0,b0,c0} - 1 | b | {a1,b1,c1} - 2 | c | {a2,b2,c2} - 3 | d | {a3,b3,c3} - 4 | e | {a4,b4,c4} - 5 | f | {a5,b5,c5} - 6 | g | {a6,b6,c6} - 7 | h | {a7,b7,c7} - 8 | i | {a8,b8,c8} - 9 | j | {a9,b9,c9} - 10 | k | {a10,b10,c10} - (11 rows) - - \c - :ORIGINAL_USER - REVOKE USAGE ON FOREIGN SERVER fdtest FROM dblink_regression_test; - REVOKE SELECT ON TABLE foo FROM dblink_regression_test; - DROP USER MAPPING FOR dblink_regression_test SERVER fdtest; - DROP USER dblink_regression_test; - DROP SERVER fdtest; - DROP FOREIGN DATA WRAPPER postgresql; - </programlisting> +<screen> +SELECT dblink_connect('dbname=postgres'); + dblink_connect +---------------- + OK +(1 row) + +SELECT dblink_connect('myconn', 'dbname=postgres'); + dblink_connect +---------------- + OK +(1 row) + +-- FOREIGN DATA WRAPPER functionality +-- Note: local connection must require password authentication for this to work properly +-- Otherwise, you will receive the following error from dblink_connect(): +-- ---------------------------------------------------------------------- +-- ERROR: password is required +-- DETAIL: Non-superuser cannot connect if the server does not request a password. +-- HINT: Target server's authentication method must be changed. +CREATE USER dblink_regression_test WITH PASSWORD 'secret'; +CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator; +CREATE SERVER fdtest FOREIGN DATA WRAPPER postgresql OPTIONS (hostaddr '127.0.0.1', dbname 'contrib_regression'); + +CREATE USER MAPPING FOR dblink_regression_test SERVER fdtest OPTIONS (user 'dblink_regression_test', password 'secret'); +GRANT USAGE ON FOREIGN SERVER fdtest TO dblink_regression_test; +GRANT SELECT ON TABLE foo TO dblink_regression_test; + +\set ORIGINAL_USER :USER +\c - dblink_regression_test +SELECT dblink_connect('myconn', 'fdtest'); + dblink_connect +---------------- + OK +(1 row) + +SELECT * FROM dblink('myconn','SELECT * FROM foo') AS t(a int, b text, c text[]); + a | b | c +----+---+--------------- + 0 | a | {a0,b0,c0} + 1 | b | {a1,b1,c1} + 2 | c | {a2,b2,c2} + 3 | d | {a3,b3,c3} + 4 | e | {a4,b4,c4} + 5 | f | {a5,b5,c5} + 6 | g | {a6,b6,c6} + 7 | h | {a7,b7,c7} + 8 | i | {a8,b8,c8} + 9 | j | {a9,b9,c9} + 10 | k | {a10,b10,c10} +(11 rows) + +\c - :ORIGINAL_USER +REVOKE USAGE ON FOREIGN SERVER fdtest FROM dblink_regression_test; +REVOKE SELECT ON TABLE foo FROM dblink_regression_test; +DROP USER MAPPING FOR dblink_regression_test SERVER fdtest; +DROP USER dblink_regression_test; +DROP SERVER fdtest; +DROP FOREIGN DATA WRAPPER postgresql; +</screen> </refsect1> </refentry> @@ -191,10 +191,10 @@ </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_connect_u(text connstr) returns text - dblink_connect_u(text connname, text connstr) returns text - </synopsis> +<synopsis> +dblink_connect_u(text connstr) returns text +dblink_connect_u(text connname, text connstr) returns text +</synopsis> </refsynopsisdiv> <refsect1> @@ -244,10 +244,10 @@ </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_disconnect() returns text - dblink_disconnect(text connname) returns text - </synopsis> +<synopsis> +dblink_disconnect() returns text +dblink_disconnect(text connname) returns text +</synopsis> </refsynopsisdiv> <refsect1> @@ -287,23 +287,23 @@ <refsect1> <title>Example</title> - <programlisting> - test=# select dblink_disconnect(); - dblink_disconnect - ------------------- - OK - (1 row) +<screen> +SELECT dblink_disconnect(); + dblink_disconnect +------------------- + OK +(1 row) - select dblink_disconnect('myconn'); - dblink_disconnect - ------------------- - OK - (1 row) - </programlisting> +SELECT dblink_disconnect('myconn'); + dblink_disconnect +------------------- + OK +(1 row) +</screen> </refsect1> </refentry> - <refentry id="CONTRIB-DBLINK"> + <refentry id="CONTRIB-DBLINK-FUNCTION"> <refmeta> <refentrytitle>dblink</refentrytitle> <manvolnum>3</manvolnum> @@ -315,11 +315,11 @@ </refnamediv> <refsynopsisdiv> - <synopsis> - dblink(text connname, text sql [, bool fail_on_error]) returns setof record - dblink(text connstr, text sql [, bool fail_on_error]) returns setof record - dblink(text sql [, bool fail_on_error]) returns setof record - </synopsis> +<synopsis> +dblink(text connname, text sql [, bool fail_on_error]) returns setof record +dblink(text connstr, text sql [, bool fail_on_error]) returns setof record +dblink(text sql [, bool fail_on_error]) returns setof record +</synopsis> </refsynopsisdiv> <refsect1> @@ -413,7 +413,7 @@ SELECT * extension.) This allows the system to understand what <literal>*</> should expand to, and what <structname>proname</> in the <literal>WHERE</> clause refers to, in advance of trying - to execute the function. At runtime, an error will be thrown + to execute the function. At run time, an error will be thrown if the actual query result from the remote database does not have the same number of columns shown in the <literal>FROM</> clause. The column names need not match, however, and <function>dblink</> @@ -440,89 +440,89 @@ SELECT * This allows the column type information to be buried in the view, instead of having to spell it out in every query. For example, - <programlisting> - create view myremote_pg_proc as - select * - from dblink('dbname=postgres', 'select proname, prosrc from pg_proc') - as t1(proname name, prosrc text); +<programlisting> +CREATE VIEW myremote_pg_proc AS + SELECT * + FROM dblink('dbname=postgres', 'select proname, prosrc from pg_proc') + AS t1(proname name, prosrc text); - select * from myremote_pg_proc where proname like 'bytea%'; - </programlisting> +SELECT * FROM myremote_pg_proc WHERE proname LIKE 'bytea%'; +</programlisting> </para> </refsect1> <refsect1> <title>Example</title> - <programlisting> - select * from dblink('dbname=postgres', 'select proname, prosrc from pg_proc') - as t1(proname name, prosrc text) where proname like 'bytea%'; - proname | prosrc - ------------+------------ - byteacat | byteacat - byteaeq | byteaeq - bytealt | bytealt - byteale | byteale - byteagt | byteagt - byteage | byteage - byteane | byteane - byteacmp | byteacmp - bytealike | bytealike - byteanlike | byteanlike - byteain | byteain - byteaout | byteaout - (12 rows) - - select dblink_connect('dbname=postgres'); - dblink_connect - ---------------- - OK - (1 row) - - select * from dblink('select proname, prosrc from pg_proc') - as t1(proname name, prosrc text) where proname like 'bytea%'; - proname | prosrc - ------------+------------ - byteacat | byteacat - byteaeq | byteaeq - bytealt | bytealt - byteale | byteale - byteagt | byteagt - byteage | byteage - byteane | byteane - byteacmp | byteacmp - bytealike | bytealike - byteanlike | byteanlike - byteain | byteain - byteaout | byteaout - (12 rows) - - select dblink_connect('myconn', 'dbname=regression'); - dblink_connect - ---------------- - OK - (1 row) - - select * from dblink('myconn', 'select proname, prosrc from pg_proc') - as t1(proname name, prosrc text) where proname like 'bytea%'; - proname | prosrc - ------------+------------ - bytearecv | bytearecv - byteasend | byteasend - byteale | byteale - byteagt | byteagt - byteage | byteage - byteane | byteane - byteacmp | byteacmp - bytealike | bytealike - byteanlike | byteanlike - byteacat | byteacat - byteaeq | byteaeq - bytealt | bytealt - byteain | byteain - byteaout | byteaout - (14 rows) - </programlisting> +<screen> +SELECT * FROM dblink('dbname=postgres', 'select proname, prosrc from pg_proc') + AS t1(proname name, prosrc text) WHERE proname LIKE 'bytea%'; + proname | prosrc +------------+------------ + byteacat | byteacat + byteaeq | byteaeq + bytealt | bytealt + byteale | byteale + byteagt | byteagt + byteage | byteage + byteane | byteane + byteacmp | byteacmp + bytealike | bytealike + byteanlike | byteanlike + byteain | byteain + byteaout | byteaout +(12 rows) + +SELECT dblink_connect('dbname=postgres'); + dblink_connect +---------------- + OK +(1 row) + +SELECT * FROM dblink('select proname, prosrc from pg_proc') + AS t1(proname name, prosrc text) WHERE proname LIKE 'bytea%'; + proname | prosrc +------------+------------ + byteacat | byteacat + byteaeq | byteaeq + bytealt | bytealt + byteale | byteale + byteagt | byteagt + byteage | byteage + byteane | byteane + byteacmp | byteacmp + bytealike | bytealike + byteanlike | byteanlike + byteain | byteain + byteaout | byteaout +(12 rows) + +SELECT dblink_connect('myconn', 'dbname=regression'); + dblink_connect +---------------- + OK +(1 row) + +SELECT * FROM dblink('myconn', 'select proname, prosrc from pg_proc') + AS t1(proname name, prosrc text) WHERE proname LIKE 'bytea%'; + proname | prosrc +------------+------------ + bytearecv | bytearecv + byteasend | byteasend + byteale | byteale + byteagt | byteagt + byteage | byteage + byteane | byteane + byteacmp | byteacmp + bytealike | bytealike + byteanlike | byteanlike + byteacat | byteacat + byteaeq | byteaeq + bytealt | bytealt + byteain | byteain + byteaout | byteaout +(14 rows) +</screen> </refsect1> </refentry> @@ -538,11 +538,11 @@ SELECT * </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_exec(text connname, text sql [, bool fail_on_error]) returns text - dblink_exec(text connstr, text sql [, bool fail_on_error]) returns text - dblink_exec(text sql [, bool fail_on_error]) returns text - </synopsis> +<synopsis> +dblink_exec(text connname, text sql [, bool fail_on_error]) returns text +dblink_exec(text connstr, text sql [, bool fail_on_error]) returns text +dblink_exec(text sql [, bool fail_on_error]) returns text +</synopsis> </refsynopsisdiv> <refsect1> @@ -622,40 +622,40 @@ SELECT * <refsect1> <title>Example</title> - <programlisting> - select dblink_connect('dbname=dblink_test_standby'); - dblink_connect - ---------------- - OK - (1 row) - - select dblink_exec('insert into foo values(21,''z'',''{"a0","b0","c0"}'');'); - dblink_exec - ----------------- - INSERT 943366 1 - (1 row) - - select dblink_connect('myconn', 'dbname=regression'); - dblink_connect - ---------------- - OK - (1 row) - - select dblink_exec('myconn', 'insert into foo values(21,''z'',''{"a0","b0","c0"}'');'); - dblink_exec - ------------------ - INSERT 6432584 1 - (1 row) - - select dblink_exec('myconn', 'insert into pg_class values (''foo'')',false); - NOTICE: sql error - DETAIL: ERROR: null value in column "relnamespace" violates not-null constraint - - dblink_exec - ------------- - ERROR - (1 row) - </programlisting> +<screen> +SELECT dblink_connect('dbname=dblink_test_standby'); + dblink_connect +---------------- + OK +(1 row) + +SELECT dblink_exec('insert into foo values(21,''z'',''{"a0","b0","c0"}'');'); + dblink_exec +----------------- + INSERT 943366 1 +(1 row) + +SELECT dblink_connect('myconn', 'dbname=regression'); + dblink_connect +---------------- + OK +(1 row) + +SELECT dblink_exec('myconn', 'insert into foo values(21,''z'',''{"a0","b0","c0"}'');'); + dblink_exec +------------------ + INSERT 6432584 1 +(1 row) + +SELECT dblink_exec('myconn', 'insert into pg_class values (''foo'')',false); +NOTICE: sql error +DETAIL: ERROR: null value in column "relnamespace" violates not-null constraint + + dblink_exec +------------- + ERROR +(1 row) +</screen> </refsect1> </refentry> @@ -671,10 +671,10 @@ SELECT * </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_open(text cursorname, text sql [, bool fail_on_error]) returns text - dblink_open(text connname, text cursorname, text sql [, bool fail_on_error]) returns text - </synopsis> +<synopsis> +dblink_open(text cursorname, text sql [, bool fail_on_error]) returns text +dblink_open(text connname, text cursorname, text sql [, bool fail_on_error]) returns text +</synopsis> </refsynopsisdiv> <refsect1> @@ -763,19 +763,19 @@ SELECT * <refsect1> <title>Example</title> - <programlisting> - test=# select dblink_connect('dbname=postgres'); - dblink_connect - ---------------- - OK - (1 row) +<screen> +SELECT dblink_connect('dbname=postgres'); + dblink_connect +---------------- + OK +(1 row) - test=# select dblink_open('foo', 'select proname, prosrc from pg_proc'); - dblink_open - ------------- - OK - (1 row) - </programlisting> +SELECT dblink_open('foo', 'select proname, prosrc from pg_proc'); + dblink_open +------------- + OK +(1 row) +</screen> </refsect1> </refentry> @@ -791,10 +791,10 @@ SELECT * </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_fetch(text cursorname, int howmany [, bool fail_on_error]) returns setof record - dblink_fetch(text connname, text cursorname, int howmany [, bool fail_on_error]) returns setof record - </synopsis> +<synopsis> +dblink_fetch(text cursorname, int howmany [, bool fail_on_error]) returns setof record +dblink_fetch(text connname, text cursorname, int howmany [, bool fail_on_error]) returns setof record +</synopsis> </refsynopsisdiv> <refsect1> @@ -880,51 +880,51 @@ SELECT * <refsect1> <title>Example</title> - <programlisting> - test=# select dblink_connect('dbname=postgres'); - dblink_connect - ---------------- - OK - (1 row) - - test=# select dblink_open('foo', 'select proname, prosrc from pg_proc where proname like ''bytea%'''); - dblink_open - ------------- - OK - (1 row) - - test=# select * from dblink_fetch('foo', 5) as (funcname name, source text); - funcname | source - ----------+---------- - byteacat | byteacat - byteacmp | byteacmp - byteaeq | byteaeq - byteage | byteage - byteagt | byteagt - (5 rows) - - test=# select * from dblink_fetch('foo', 5) as (funcname name, source text); - funcname | source - -----------+----------- - byteain | byteain - byteale | byteale - bytealike | bytealike - bytealt | bytealt - byteane | byteane - (5 rows) - - test=# select * from dblink_fetch('foo', 5) as (funcname name, source text); - funcname | source - ------------+------------ - byteanlike | byteanlike - byteaout | byteaout - (2 rows) - - test=# select * from dblink_fetch('foo', 5) as (funcname name, source text); - funcname | source - ----------+-------- - (0 rows) - </programlisting> +<screen> +SELECT dblink_connect('dbname=postgres'); + dblink_connect +---------------- + OK +(1 row) + +SELECT dblink_open('foo', 'select proname, prosrc from pg_proc where proname like ''bytea%'''); + dblink_open +------------- + OK +(1 row) + +SELECT * FROM dblink_fetch('foo', 5) AS (funcname name, source text); + funcname | source +----------+---------- + byteacat | byteacat + byteacmp | byteacmp + byteaeq | byteaeq + byteage | byteage + byteagt | byteagt +(5 rows) + +SELECT * FROM dblink_fetch('foo', 5) AS (funcname name, source text); + funcname | source +-----------+----------- + byteain | byteain + byteale | byteale + bytealike | bytealike + bytealt | bytealt + byteane | byteane +(5 rows) + +SELECT * FROM dblink_fetch('foo', 5) AS (funcname name, source text); + funcname | source +------------+------------ + byteanlike | byteanlike + byteaout | byteaout +(2 rows) + +SELECT * FROM dblink_fetch('foo', 5) AS (funcname name, source text); + funcname | source +----------+-------- +(0 rows) +</screen> </refsect1> </refentry> @@ -940,10 +940,10 @@ SELECT * </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_close(text cursorname [, bool fail_on_error]) returns text - dblink_close(text connname, text cursorname [, bool fail_on_error]) returns text - </synopsis> +<synopsis> +dblink_close(text cursorname [, bool fail_on_error]) returns text +dblink_close(text connname, text cursorname [, bool fail_on_error]) returns text +</synopsis> </refsynopsisdiv> <refsect1> @@ -1013,25 +1013,25 @@ SELECT * <refsect1> <title>Example</title> - <programlisting> - test=# select dblink_connect('dbname=postgres'); - dblink_connect - ---------------- - OK - (1 row) - - test=# select dblink_open('foo', 'select proname, prosrc from pg_proc'); - dblink_open - ------------- - OK - (1 row) - - test=# select dblink_close('foo'); - dblink_close - -------------- - OK - (1 row) - </programlisting> +<screen> +SELECT dblink_connect('dbname=postgres'); + dblink_connect +---------------- + OK +(1 row) + +SELECT dblink_open('foo', 'select proname, prosrc from pg_proc'); + dblink_open +------------- + OK +(1 row) + +SELECT dblink_close('foo'); + dblink_close +-------------- + OK +(1 row) +</screen> </refsect1> </refentry> @@ -1047,9 +1047,9 @@ SELECT * </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_get_connections() returns text[] - </synopsis> +<synopsis> +dblink_get_connections() returns text[] +</synopsis> </refsynopsisdiv> <refsect1> @@ -1070,9 +1070,9 @@ SELECT * <refsect1> <title>Example</title> - <programlisting> - SELECT dblink_get_connections(); - </programlisting> +<programlisting> +SELECT dblink_get_connections(); +</programlisting> </refsect1> </refentry> @@ -1088,9 +1088,9 @@ SELECT * </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_error_message(text connname) returns text - </synopsis> +<synopsis> +dblink_error_message(text connname) returns text +</synopsis> </refsynopsisdiv> <refsect1> @@ -1129,9 +1129,9 @@ SELECT * <refsect1> <title>Example</title> - <programlisting> - SELECT dblink_error_message('dtest1'); - </programlisting> +<programlisting> +SELECT dblink_error_message('dtest1'); +</programlisting> </refsect1> </refentry> @@ -1147,9 +1147,9 @@ SELECT * </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_send_query(text connname, text sql) returns int - </synopsis> +<synopsis> +dblink_send_query(text connname, text sql) returns int +</synopsis> </refsynopsisdiv> <refsect1> @@ -1207,9 +1207,9 @@ SELECT * <refsect1> <title>Example</title> - <programlisting> - SELECT dblink_send_query('dtest1', 'SELECT * FROM foo WHERE f1 < 3'); - </programlisting> +<programlisting> +SELECT dblink_send_query('dtest1', 'SELECT * FROM foo WHERE f1 < 3'); +</programlisting> </refsect1> </refentry> @@ -1225,9 +1225,9 @@ SELECT * </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_is_busy(text connname) returns int - </synopsis> +<synopsis> +dblink_is_busy(text connname) returns int +</synopsis> </refsynopsisdiv> <refsect1> @@ -1266,9 +1266,9 @@ SELECT * <refsect1> <title>Example</title> - <programlisting> - SELECT dblink_is_busy('dtest1'); - </programlisting> +<programlisting> +SELECT dblink_is_busy('dtest1'); +</programlisting> </refsect1> </refentry> @@ -1284,10 +1284,10 @@ SELECT * </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_get_notify() returns setof (notify_name text, be_pid int, extra text) - dblink_get_notify(text connname) returns setof (notify_name text, be_pid int, extra text) - </synopsis> +<synopsis> +dblink_get_notify() returns setof (notify_name text, be_pid int, extra text) +dblink_get_notify(text connname) returns setof (notify_name text, be_pid int, extra text) +</synopsis> </refsynopsisdiv> <refsect1> @@ -1320,25 +1320,25 @@ SELECT * <refsect1> <title>Return Value</title> - <para>Returns setof (notify_name text, be_pid int, extra text), or an empty set if none.</para> + <para>Returns <type>setof (notify_name text, be_pid int, extra text)</type>, or an empty set if none.</para> </refsect1> <refsect1> <title>Example</title> - <programlisting> -test=# SELECT dblink_exec('LISTEN virtual'); +<screen> +SELECT dblink_exec('LISTEN virtual'); dblink_exec ------------- LISTEN (1 row) -test=# SELECT * FROM dblink_get_notify(); +SELECT * FROM dblink_get_notify(); notify_name | be_pid | extra -------------+--------+------- (0 rows) -test=# NOTIFY virtual; +NOTIFY virtual; NOTIFY SELECT * FROM dblink_get_notify(); @@ -1346,7 +1346,7 @@ SELECT * FROM dblink_get_notify(); -------------+--------+------- virtual | 1229 | (1 row) - </programlisting> +</screen> </refsect1> </refentry> @@ -1362,9 +1362,9 @@ SELECT * FROM dblink_get_notify(); </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_get_result(text connname [, bool fail_on_error]) returns setof record - </synopsis> +<synopsis> +dblink_get_result(text connname [, bool fail_on_error]) returns setof record +</synopsis> </refsynopsisdiv> <refsect1> @@ -1439,62 +1439,62 @@ SELECT * FROM dblink_get_notify(); <refsect1> <title>Example</title> - <programlisting> - contrib_regression=# SELECT dblink_connect('dtest1', 'dbname=contrib_regression'); - dblink_connect - ---------------- - OK - (1 row) - - contrib_regression=# SELECT * from - contrib_regression-# dblink_send_query('dtest1', 'select * from foo where f1 < 3') as t1; - t1 - ---- - 1 - (1 row) - - contrib_regression=# SELECT * from dblink_get_result('dtest1') as t1(f1 int, f2 text, f3 text[]); - f1 | f2 | f3 - ----+----+------------ - 0 | a | {a0,b0,c0} - 1 | b | {a1,b1,c1} - 2 | c | {a2,b2,c2} - (3 rows) - - contrib_regression=# SELECT * from dblink_get_result('dtest1') as t1(f1 int, f2 text, f3 text[]); - f1 | f2 | f3 - ----+----+---- - (0 rows) - - contrib_regression=# SELECT * from - dblink_send_query('dtest1', 'select * from foo where f1 < 3; select * from foo where f1 > 6') as t1; - t1 - ---- - 1 - (1 row) - - contrib_regression=# SELECT * from dblink_get_result('dtest1') as t1(f1 int, f2 text, f3 text[]); - f1 | f2 | f3 - ----+----+------------ - 0 | a | {a0,b0,c0} - 1 | b | {a1,b1,c1} - 2 | c | {a2,b2,c2} - (3 rows) - - contrib_regression=# SELECT * from dblink_get_result('dtest1') as t1(f1 int, f2 text, f3 text[]); - f1 | f2 | f3 - ----+----+--------------- - 7 | h | {a7,b7,c7} - 8 | i | {a8,b8,c8} - 9 | j | {a9,b9,c9} - 10 | k | {a10,b10,c10} - (4 rows) - - contrib_regression=# SELECT * from dblink_get_result('dtest1') as t1(f1 int, f2 text, f3 text[]); - f1 | f2 | f3 - ----+----+---- - (0 rows) - </programlisting> +<screen> +contrib_regression=# SELECT dblink_connect('dtest1', 'dbname=contrib_regression'); + dblink_connect +---------------- + OK +(1 row) + +contrib_regression=# SELECT * FROM +contrib_regression-# dblink_send_query('dtest1', 'select * from foo where f1 < 3') AS t1; + t1 +---- + 1 +(1 row) + +contrib_regression=# SELECT * FROM dblink_get_result('dtest1') AS t1(f1 int, f2 text, f3 text[]); + f1 | f2 | f3 +----+----+------------ + 0 | a | {a0,b0,c0} + 1 | b | {a1,b1,c1} + 2 | c | {a2,b2,c2} +(3 rows) + +contrib_regression=# SELECT * FROM dblink_get_result('dtest1') AS t1(f1 int, f2 text, f3 text[]); + f1 | f2 | f3 +----+----+---- +(0 rows) + +contrib_regression=# SELECT * FROM +contrib_regression-# dblink_send_query('dtest1', 'select * from foo where f1 < 3; select * from foo where f1 > 6') AS t1; + t1 +---- + 1 +(1 row) + +contrib_regression=# SELECT * FROM dblink_get_result('dtest1') AS t1(f1 int, f2 text, f3 text[]); + f1 | f2 | f3 +----+----+------------ + 0 | a | {a0,b0,c0} + 1 | b | {a1,b1,c1} + 2 | c | {a2,b2,c2} +(3 rows) + +contrib_regression=# SELECT * FROM dblink_get_result('dtest1') AS t1(f1 int, f2 text, f3 text[]); + f1 | f2 | f3 +----+----+--------------- + 7 | h | {a7,b7,c7} + 8 | i | {a8,b8,c8} + 9 | j | {a9,b9,c9} + 10 | k | {a10,b10,c10} +(4 rows) + +contrib_regression=# SELECT * FROM dblink_get_result('dtest1') AS t1(f1 int, f2 text, f3 text[]); + f1 | f2 | f3 +----+----+---- +(0 rows) +</screen> </refsect1> </refentry> @@ -1510,9 +1510,9 @@ SELECT * FROM dblink_get_notify(); </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_cancel_query(text connname) returns text - </synopsis> +<synopsis> +dblink_cancel_query(text connname) returns text +</synopsis> </refsynopsisdiv> <refsect1> @@ -1556,9 +1556,9 @@ SELECT * FROM dblink_get_notify(); <refsect1> <title>Example</title> - <programlisting> - SELECT dblink_cancel_query('dtest1'); - </programlisting> +<programlisting> +SELECT dblink_cancel_query('dtest1'); +</programlisting> </refsect1> </refentry> @@ -1576,9 +1576,9 @@ SELECT * FROM dblink_get_notify(); </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_get_pkey(text relname) returns setof dblink_pkey_results - </synopsis> +<synopsis> +dblink_get_pkey(text relname) returns setof dblink_pkey_results +</synopsis> </refsynopsisdiv> <refsect1> @@ -1615,11 +1615,11 @@ SELECT * FROM dblink_get_notify(); <para> Returns one row for each primary key field, or no rows if the relation - has no primary key. The result rowtype is defined as + has no primary key. The result row type is defined as - <programlisting> +<programlisting> CREATE TYPE dblink_pkey_results AS (position int, colname text); - </programlisting> +</programlisting> The <literal>position</> column simply runs from 1 to <replaceable>N</>; it is the number of the field within the primary key, not the number @@ -1630,18 +1630,23 @@ CREATE TYPE dblink_pkey_results AS (position int, colname text); <refsect1> <title>Example</title> - <programlisting> -test=# create table foobar(f1 int, f2 int, f3 int, -test(# primary key(f1,f2,f3)); +<screen> +CREATE TABLE foobar ( + f1 int, + f2 int, + f3 int, + PRIMARY KEY (f1, f2, f3) +); CREATE TABLE -test=# select * from dblink_get_pkey('foobar'); + +SELECT * FROM dblink_get_pkey('foobar'); position | colname ----------+--------- 1 | f1 2 | f2 3 | f3 (3 rows) - </programlisting> +</screen> </refsect1> </refentry> @@ -1660,13 +1665,13 @@ test=# select * from dblink_get_pkey('foobar'); </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_build_sql_insert(text relname, - int2vector primary_key_attnums, - integer num_primary_key_atts, - text[] src_pk_att_vals_array, - text[] tgt_pk_att_vals_array) returns text - </synopsis> +<synopsis> +dblink_build_sql_insert(text relname, + int2vector primary_key_attnums, + integer num_primary_key_atts, + text[] src_pk_att_vals_array, + text[] tgt_pk_att_vals_array) returns text +</synopsis> </refsynopsisdiv> <refsect1> @@ -1766,13 +1771,13 @@ test=# select * from dblink_get_pkey('foobar'); <refsect1> <title>Example</title> - <programlisting> - test=# select dblink_build_sql_insert('foo', '1 2', 2, '{"1", "a"}', '{"1", "b''a"}'); - dblink_build_sql_insert - -------------------------------------------------- - INSERT INTO foo(f1,f2,f3) VALUES('1','b''a','1') - (1 row) - </programlisting> +<screen> +SELECT dblink_build_sql_insert('foo', '1 2', 2, '{"1", "a"}', '{"1", "b''a"}'); + dblink_build_sql_insert +-------------------------------------------------- + INSERT INTO foo(f1,f2,f3) VALUES('1','b''a','1') +(1 row) +</screen> </refsect1> </refentry> @@ -1790,12 +1795,12 @@ test=# select * from dblink_get_pkey('foobar'); </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_build_sql_delete(text relname, - int2vector primary_key_attnums, - integer num_primary_key_atts, - text[] tgt_pk_att_vals_array) returns text - </synopsis> +<synopsis> +dblink_build_sql_delete(text relname, + int2vector primary_key_attnums, + integer num_primary_key_atts, + text[] tgt_pk_att_vals_array) returns text +</synopsis> </refsynopsisdiv> <refsect1> @@ -1880,13 +1885,13 @@ test=# select * from dblink_get_pkey('foobar'); <refsect1> <title>Example</title> - <programlisting> - test=# select dblink_build_sql_delete('"MyFoo"', '1 2', 2, '{"1", "b"}'); - dblink_build_sql_delete - --------------------------------------------- - DELETE FROM "MyFoo" WHERE f1='1' AND f2='b' - (1 row) - </programlisting> +<screen> +SELECT dblink_build_sql_delete('"MyFoo"', '1 2', 2, '{"1", "b"}'); + dblink_build_sql_delete +--------------------------------------------- + DELETE FROM "MyFoo" WHERE f1='1' AND f2='b' +(1 row) +</screen> </refsect1> </refentry> @@ -1904,13 +1909,13 @@ test=# select * from dblink_get_pkey('foobar'); </refnamediv> <refsynopsisdiv> - <synopsis> - dblink_build_sql_update(text relname, - int2vector primary_key_attnums, - integer num_primary_key_atts, - text[] src_pk_att_vals_array, - text[] tgt_pk_att_vals_array) returns text - </synopsis> +<synopsis> +dblink_build_sql_update(text relname, + int2vector primary_key_attnums, + integer num_primary_key_atts, + text[] src_pk_att_vals_array, + text[] tgt_pk_att_vals_array) returns text +</synopsis> </refsynopsisdiv> <refsect1> @@ -2013,13 +2018,13 @@ test=# select * from dblink_get_pkey('foobar'); <refsect1> <title>Example</title> - <programlisting> - test=# select dblink_build_sql_update('foo', '1 2', 2, '{"1", "a"}', '{"1", "b"}'); - dblink_build_sql_update - ------------------------------------------------------------- - UPDATE foo SET f1='1',f2='b',f3='1' WHERE f1='1' AND f2='b' - (1 row) - </programlisting> +<screen> +SELECT dblink_build_sql_update('foo', '1 2', 2, '{"1", "a"}', '{"1", "b"}'); + dblink_build_sql_update +------------------------------------------------------------- + UPDATE foo SET f1='1',f2='b',f3='1' WHERE f1='1' AND f2='b' +(1 row) +</screen> </refsect1> </refentry> diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index ab4021ad3c..9709dd613f 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.93 2010/04/06 02:18:04 momjian Exp $ --> +<!-- doc/src/sgml/ddl.sgml --> <chapter id="ddl"> <title>Data Definition</title> @@ -36,7 +36,7 @@ is fixed, and each column has a name. The number of rows is variable — it reflects how much data is stored at a given moment. SQL does not make any guarantees about the order of the rows in a - table. When a table is read, the rows will appear in random order, + table. When a table is read, the rows will appear in an unspecified order, unless sorting is explicitly requested. This is covered in <xref linkend="queries">. Furthermore, SQL does not assign unique identifiers to rows, so it is possible to have several completely @@ -544,6 +544,11 @@ CREATE TABLE products ( </programlisting> </para> + <para> + Adding a unique constraint will automatically create a unique btree + index on the column or group of columns used in the constraint. + </para> + <indexterm> <primary>null value</primary> <secondary sortas="unique constraints">with unique constraints</secondary> @@ -623,6 +628,11 @@ CREATE TABLE example ( </para> <para> + Adding a primary key will automatically create a unique btree index + on the column or group of columns used in the primary key. + </para> + + <para> A table can have at most one primary key. (There can be any number of unique and not-null constraints, which are functionally the same thing, but only one can be identified as the primary key.) @@ -832,6 +842,16 @@ CREATE TABLE order_items ( </para> <para> + Since a <command>DELETE</command> of a row from the referenced table + or an <command>UPDATE</command> of a referenced column will require + a scan of the referencing table for rows matching the old value, it + is often a good idea to index the referencing columns. Because this + is not always needed, and there are many choices available on how + to index, declaration of a foreign key constraint does not + automatically create an index on the referencing columns. + </para> + + <para> More information about updating and deleting data is in <xref linkend="dml">. </para> @@ -846,8 +866,8 @@ CREATE TABLE order_items ( </para> </sect2> - <sect2> - <title>Exclusion constraints</title> + <sect2 id="ddl-constraints-exclusion"> + <title>Exclusion Constraints</title> <indexterm> <primary>exclusion constraint</primary> @@ -875,6 +895,11 @@ CREATE TABLE circles ( See also <link linkend="SQL-CREATETABLE-EXCLUDE"><command>CREATE TABLE ... CONSTRAINT ... EXCLUDE</></link> for details. </para> + + <para> + Adding an exclusion constraint will automatically create an index + of the type specified in the constraint declaration. + </para> </sect2> </sect1> @@ -1375,17 +1400,29 @@ ALTER TABLE products RENAME TO items; <see>privilege</see> </indexterm> + <indexterm zone="ddl-priv"> + <primary>owner</primary> + </indexterm> + + <indexterm zone="ddl-priv"> + <primary>GRANT</primary> + </indexterm> + + <indexterm zone="ddl-priv"> + <primary>REVOKE</primary> + </indexterm> + <para> - When you create a database object, you become its owner. By - default, only the owner of an object can do anything with the - object. In order to allow other users to use it, - <firstterm>privileges</firstterm> must be granted. (However, - users that have the superuser attribute can always - access any object.) + When an object is created, it is assigned an owner. The + owner is normally the role that executed the creation statement. + For most kinds of objects, the initial state is that only the owner + (or a superuser) can do anything with the object. To allow + other roles to use it, <firstterm>privileges</firstterm> must be + granted. </para> <para> - There are several different privileges: <literal>SELECT</>, + There are different kinds of privileges: <literal>SELECT</>, <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>, <literal>TRUNCATE</>, <literal>REFERENCES</>, <literal>TRIGGER</>, <literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>, @@ -1404,14 +1441,14 @@ ALTER TABLE products RENAME TO items; the owner only. </para> - <note> - <para> - To change the owner of a table, index, sequence, or view, use the - <xref linkend="sql-altertable"> - command. There are corresponding <literal>ALTER</> commands for - other object types. - </para> - </note> + <para> + An object can be assigned to a new owner with an <command>ALTER</command> + command of the appropriate kind for the object, e.g. <xref + linkend="sql-altertable">. Superusers can always do + this; ordinary roles can only do it if they are both the current owner + of the object (or a member of the owning role) and a member of the new + owning role. + </para> <para> To assign privileges, the <command>GRANT</command> command is @@ -2520,7 +2557,7 @@ CREATE TABLE measurement_y2008m01 ( ) INHERITS (measurement); just creating the partition tables as above, the table creation script should really be: - <programlisting> +<programlisting> CREATE TABLE measurement_y2006m02 ( CHECK ( logdate >= DATE '2006-02-01' AND logdate < DATE '2006-03-01' ) ) INHERITS (measurement); @@ -2545,7 +2582,7 @@ CREATE TABLE measurement_y2008m01 ( <para> We probably need indexes on the key columns too: - <programlisting> +<programlisting> CREATE INDEX measurement_y2006m02_logdate ON measurement_y2006m02 (logdate); CREATE INDEX measurement_y2006m03_logdate ON measurement_y2006m03 (logdate); ... @@ -2961,6 +2998,53 @@ ANALYZE measurement; </sect2> </sect1> + <sect1 id="ddl-foreign-data"> + <title>Foreign Data</title> + + <indexterm> + <primary>foreign data</primary> + </indexterm> + <indexterm> + <primary>foreign table</primary> + </indexterm> + + <para> + <productname>PostgreSQL</productname> implements portions of the SQL/MED + specification, allowing you to access data that resides outside + PostgreSQL using regular SQL queries. Such data is referred to as + <firstterm>foreign data</>. (Note that this usage is not to be confused + with foreign keys, which are a type of constraint within the database.) + </para> + + <para> + Foreign data is accessed with help from a + <firstterm>foreign data wrapper</firstterm>. A foreign data wrapper is a + library that can communicate with an external data source, hiding the + details of connecting to the data source and fetching data from it. There + are several foreign data wrappers available, which can for example read + plain data files residing on the server, or connect to another PostgreSQL + instance. If none of the existing foreign data wrappers suit your needs, + you can write your own; see <xref linkend="fdwhandler">. + </para> + + <para> + To access foreign data, you need to create a <firstterm>foreign server</> + object, which defines how to connect to a particular external data source, + according to the set of options used by a particular foreign data + wrapper. Then you need to create one or more <firstterm>foreign + tables</firstterm>, which define the structure of the remote data. A + foreign table can be used in queries just like a normal table, but a + foreign table has no storage in the PostgreSQL server. Whenever it is + used, PostgreSQL asks the foreign data wrapper to fetch the data from the + external source. + </para> + + <para> + Currently, foreign tables are read-only. This limitation may be fixed + in a future release. + </para> + </sect1> + <sect1 id="ddl-others"> <title>Other Database Objects</title> diff --git a/doc/src/sgml/dfunc.sgml b/doc/src/sgml/dfunc.sgml index 310787aa12..bc29fb18cb 100644 --- a/doc/src/sgml/dfunc.sgml +++ b/doc/src/sgml/dfunc.sgml @@ -1,7 +1,7 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/dfunc.sgml,v 1.36 2010/04/03 07:22:53 petere Exp $ --> +<!-- doc/src/sgml/dfunc.sgml --> <sect2 id="dfunc"> - <title>Compiling and Linking Dynamically-Loaded Functions</title> + <title>Compiling and Linking Dynamically-loaded Functions</title> <para> Before you are able to use your @@ -160,7 +160,7 @@ cc -shared -o foo.so foo.o <para> Here is an example. It assumes the developer tools are installed. <programlisting> -cc -c foo.c +cc -c foo.c cc -bundle -flat_namespace -undefined suppress -o foo.so foo.o </programlisting> </para> @@ -226,7 +226,7 @@ gcc -G -o foo.so foo.o </varlistentry> <varlistentry> - <term><systemitem class="osname">Tru64 UNIX</></term> + <term><systemitem class="osname">Tru64 UNIX</></term> <indexterm><primary>Tru64 UNIX</><secondary>shared library</></> <indexterm><primary>Digital UNIX</><see>Tru64 UNIX</></> <listitem> @@ -272,7 +272,7 @@ gcc -shared -o foo.so foo.o <tip> <para> - If this is too complicated for you, you should consider using + If this is too complicated for you, you should consider using <ulink url="http://www.gnu.org/software/libtool/"> <productname>GNU Libtool</productname></ulink>, which hides the platform differences behind a uniform interface. diff --git a/doc/src/sgml/dict-int.sgml b/doc/src/sgml/dict-int.sgml index d19487f789..d49f3e2a3a 100644 --- a/doc/src/sgml/dict-int.sgml +++ b/doc/src/sgml/dict-int.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/dict-int.sgml,v 1.2 2007/12/06 04:12:10 tgl Exp $ --> +<!-- doc/src/sgml/dict-int.sgml --> -<sect1 id="dict-int"> +<sect1 id="dict-int" xreflabel="dict_int"> <title>dict_int</title> <indexterm zone="dict-int"> @@ -47,8 +47,8 @@ <title>Usage</title> <para> - Running the installation script creates a text search template - <literal>intdict_template</> and a dictionary <literal>intdict</> + Installing the <literal>dict_int</> extension creates a text search + template <literal>intdict_template</> and a dictionary <literal>intdict</> based on it, with the default parameters. You can alter the parameters, for example diff --git a/doc/src/sgml/dict-xsyn.sgml b/doc/src/sgml/dict-xsyn.sgml index 7df6959d3d..42362ffbc8 100644 --- a/doc/src/sgml/dict-xsyn.sgml +++ b/doc/src/sgml/dict-xsyn.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/dict-xsyn.sgml,v 1.3 2009/08/05 18:06:49 tgl Exp $ --> +<!-- doc/src/sgml/dict-xsyn.sgml --> -<sect1 id="dict-xsyn"> +<sect1 id="dict-xsyn" xreflabel="dict_xsyn"> <title>dict_xsyn</title> <indexterm zone="dict-xsyn"> @@ -64,9 +64,9 @@ <para> Each line represents a group of synonyms for a single word, which is given first on the line. Synonyms are separated by whitespace, thus: - <programlisting> +<programlisting> word syn1 syn2 syn3 - </programlisting> +</programlisting> </para> </listitem> <listitem> @@ -87,8 +87,8 @@ word syn1 syn2 syn3 <title>Usage</title> <para> - Running the installation script creates a text search template - <literal>xsyn_template</> and a dictionary <literal>xsyn</> + Installing the <literal>dict_xsyn</> extension creates a text search + template <literal>xsyn_template</> and a dictionary <literal>xsyn</> based on it, with default parameters. You can alter the parameters, for example diff --git a/doc/src/sgml/diskusage.sgml b/doc/src/sgml/diskusage.sgml index aa64e4228e..de1d0b4b00 100644 --- a/doc/src/sgml/diskusage.sgml +++ b/doc/src/sgml/diskusage.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/diskusage.sgml,v 1.20 2010/02/07 20:48:09 tgl Exp $ --> +<!-- doc/src/sgml/diskusage.sgml --> <chapter id="diskusage"> <title>Monitoring Disk Usage</title> @@ -9,7 +9,7 @@ </para> <sect1 id="disk-usage"> - <title>Determining Disk Usage</Title> + <title>Determining Disk Usage</title> <indexterm zone="disk-usage"> <primary>disk usage</primary> @@ -31,10 +31,9 @@ <para> You can monitor disk space in three ways: using the SQL functions listed in <xref linkend="functions-admin-dbsize">, - using the tools in <filename>contrib/oid2name</>, or + 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. - <filename>contrib/oid2name</> is described in <xref linkend="oid2name">. The remainder of this section shows how to do it by inspection of the system catalogs. </para> @@ -52,7 +51,7 @@ SELECT pg_relation_filepath(oid), relpages FROM pg_class WHERE relname = 'custom </programlisting> Each page is typically 8 kilobytes. (Remember, <structfield>relpages</> is only updated by <command>VACUUM</>, <command>ANALYZE</>, and - a few DDL commands such as <command>CREATE INDEX</>.) The file pathname + a few DDL commands such as <command>CREATE INDEX</>.) The file path name is of interest if you want to examine the table's disk file directly. </para> diff --git a/doc/src/sgml/dml.sgml b/doc/src/sgml/dml.sgml index 69d162efe7..cd36a73811 100644 --- a/doc/src/sgml/dml.sgml +++ b/doc/src/sgml/dml.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/dml.sgml,v 1.22 2010/04/03 07:22:53 petere Exp $ --> +<!-- doc/src/sgml/dml.sgml --> <chapter id="dml"> <title>Data Manipulation</title> diff --git a/doc/src/sgml/docguide.sgml b/doc/src/sgml/docguide.sgml index 41dfc2abc8..7bbe3246e7 100644 --- a/doc/src/sgml/docguide.sgml +++ b/doc/src/sgml/docguide.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/docguide.sgml,v 1.85 2010/06/12 09:55:12 petere Exp $ --> +<!-- doc/src/sgml/docguide.sgml --> <appendix id="docguide"> <title>Documentation</title> @@ -240,8 +240,8 @@ <para> It's possible that the ports do not update the main catalog file - in <filename>/usr/local/share/sgml/catalog.ports</filename> or order - isn't proper . Be sure to have the following lines in begining of file: + in <filename>/usr/local/share/sgml/catalog.ports</filename> or order + isn't proper . Be sure to have the following lines in beginning of file: <programlisting> CATALOG "openjade/catalog" CATALOG "iso8879/catalog" @@ -268,7 +268,7 @@ CATALOG "docbook/4.2/catalog" available for <productname>Debian GNU/Linux</productname>. To install, simply use: <programlisting> -apt-get install docbook docbook-dsssl docbook-xsl openjade xsltproc +apt-get install docbook docbook-dsssl docbook-xsl openjade1.3 xsltproc </programlisting> </para> </sect2> @@ -306,9 +306,22 @@ make install <envar>SGML_CATALOG_FILES</envar> to point to the file whenever you use <application>jade</application> later on. (This method is also an option if OpenJade is already - installed and you want to install the rest of the tool chain + installed and you want to install the rest of the toolchain locally.) </para> + + <note> + <para> + Some users have reported encountering a segmentation fault using + openjade 1.4devel to build the PDFs, with a message like: +<screen> +openjade:./stylesheet.dsl:664:2:E: flow object not accepted by port; only display flow objects accepted +make: *** [postgres-A4.tex-pdf] Segmentation fault +</screen> + Downgrading to openjade 1.3 should get rid of this error. + </para> + </note> + </step> <step id="doc-openjade-install"> @@ -613,7 +626,7 @@ gmake man </screen> </para> </listitem> - + <listitem> <para> To make a <acronym>PDF</acronym>: @@ -1005,10 +1018,8 @@ save_size.pdfjadetex = 15000 (setq sgml-indent-step 1) (setq sgml-indent-data t) (setq sgml-parent-document nil) -(setq sgml-default-dtd-file "./reference.ced") (setq sgml-exposed-tags nil) (setq sgml-catalog-files '("/usr/local/share/sgml/catalog")) -(setq sgml-ecat-files nil) (autoload 'sgml-mode "psgml" "Major mode to edit SGML files." t ) </programlisting> @@ -1025,8 +1036,6 @@ save_size.pdfjadetex = 15000 </para> <para> - The <productname>PostgreSQL</productname> distribution includes a - parsed DTD definitions file <filename>reference.ced</filename>. You might find that when using <productname>PSGML</productname>, a comfortable way of working with these separate files of book parts is to insert a proper <literal>DOCTYPE</literal> @@ -1048,7 +1057,7 @@ save_size.pdfjadetex = 15000 </sect2> <sect2> - <title>Other Emacs modes</title> + <title>Other Emacs Modes</title> <para> <productname>GNU Emacs</productname> ships with a different @@ -1056,12 +1065,14 @@ save_size.pdfjadetex = 15000 <productname>PSGML</productname>, but it's less confusing and lighter weight. Also, it offers syntax highlighting (font lock), which can be very helpful. + <filename>src/tools/editors/emacs.samples</filename> contains + sample settings for this mode. </para> <para> Norm Walsh offers a <ulink url="http://nwalsh.com/emacs/docbookide/index.html">major mode</ulink> - specifically for DocBook which also has font-lock and a number of features to + specifically for DocBook which also has font-lock and a number of features to reduce typing. </para> </sect2> @@ -1116,7 +1127,7 @@ save_size.pdfjadetex = 15000 </para> </listitem> </varlistentry> - + <varlistentry> <term>Description</term> <listitem> @@ -1125,7 +1136,7 @@ save_size.pdfjadetex = 15000 </para> </listitem> </varlistentry> - + <varlistentry> <term>Options</term> <listitem> @@ -1135,7 +1146,7 @@ save_size.pdfjadetex = 15000 </para> </listitem> </varlistentry> - + <varlistentry> <term>Exit Status</term> <listitem> @@ -1146,7 +1157,7 @@ save_size.pdfjadetex = 15000 </para> </listitem> </varlistentry> - + <varlistentry> <term>Usage</term> <listitem> @@ -1158,7 +1169,7 @@ save_size.pdfjadetex = 15000 </para> </listitem> </varlistentry> - + <varlistentry> <term>Environment</term> <listitem> @@ -1169,7 +1180,7 @@ save_size.pdfjadetex = 15000 </para> </listitem> </varlistentry> - + <varlistentry> <term>Files</term> <listitem> @@ -1180,7 +1191,7 @@ save_size.pdfjadetex = 15000 </para> </listitem> </varlistentry> - + <varlistentry> <term>Diagnostics</term> <listitem> @@ -1193,7 +1204,7 @@ save_size.pdfjadetex = 15000 </para> </listitem> </varlistentry> - + <varlistentry> <term>Notes</term> <listitem> @@ -1204,7 +1215,7 @@ save_size.pdfjadetex = 15000 </para> </listitem> </varlistentry> - + <varlistentry> <term>Examples</term> <listitem> @@ -1213,7 +1224,7 @@ save_size.pdfjadetex = 15000 </para> </listitem> </varlistentry> - + <varlistentry> <term>History</term> <listitem> @@ -1224,7 +1235,7 @@ save_size.pdfjadetex = 15000 </para> </listitem> </varlistentry> - + <varlistentry> <term>See Also</term> <listitem> diff --git a/doc/src/sgml/dummy-seclabel.sgml b/doc/src/sgml/dummy-seclabel.sgml new file mode 100644 index 0000000000..28d19d2409 --- /dev/null +++ b/doc/src/sgml/dummy-seclabel.sgml @@ -0,0 +1,74 @@ +<!-- doc/src/sgml/dummy_seclabel.sgml --> + +<sect1 id="dummy-seclabel" xreflabel="dummy_seclabel"> + <title>dummy_seclabel</title> + + <indexterm zone="dummy-seclabel"> + <primary>dummy_seclabel</primary> + </indexterm> + + <para> + The <filename>dummy_seclabel</> module exists only to support regression + testing of the <command>SECURITY LABEL</> statement. It is not intended + to be used in production. + </para> + + <sect2> + <title>Rationale</title> + + <para> + The <command>SECURITY LABEL</> statement allows the user to assign security + labels to database objects; however, security labels can only be assigned + when specifically allowed by a loadable module, so this module is provided + to allow proper regression testing. + </para> + + <para> + Security label providers intended to be used in production will typically be + dependent on a platform-specific feature such as + <productname>SE-Linux</productname>. This module is platform-independent, + and therefore better-suited to regression testing. + </para> + </sect2> + + <sect2> + <title>Usage</title> + + <para> + Here's a simple example of usage: + </para> + +<programlisting> +# postgresql.conf +shared_preload_libraries = 'dummy_label' +</programlisting> + +<programlisting> +postgres=# CREATE TABLE t (a int, b text); +CREATE TABLE +postgres=# SECURITY LABEL ON TABLE t IS 'classified'; +SECURITY LABEL +</programlisting> + + <para> + The <filename>dummy_seclabel</> module provides only four hardcoded + labels: <literal>unclassified</>, <literal>classified</>, + <literal>secret</>, and <literal>top secret</>. + It does not allow any other strings as security labels. + </para> + <para> + These labels are not used to enforce access controls. They are only used + to check whether the <command>SECURITY LABEL</> statement works as expected, + or not. + </para> + </sect2> + + <sect2> + <title>Author</title> + + <para> + KaiGai Kohei <email>kaigai@ak.jp.nec.com</email> + </para> + </sect2> + +</sect1> diff --git a/doc/src/sgml/earthdistance.sgml b/doc/src/sgml/earthdistance.sgml index a732b1d54a..f9002b235b 100644 --- a/doc/src/sgml/earthdistance.sgml +++ b/doc/src/sgml/earthdistance.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/earthdistance.sgml,v 1.3 2007/12/06 04:12:10 tgl Exp $ --> +<!-- doc/src/sgml/earthdistance.sgml --> -<sect1 id="earthdistance"> +<sect1 id="earthdistance" xreflabel="earthdistance"> <title>earthdistance</title> <indexterm zone="earthdistance"> @@ -10,9 +10,9 @@ <para> The <filename>earthdistance</> module provides two different approaches to calculating great circle distances on the surface of the Earth. The one - described first depends on the <filename>cube</> package (which + described first depends on the <filename>cube</> module (which <emphasis>must</> be installed before <filename>earthdistance</> can be - installed). The second one is based on the built-in <type>point</> datatype, + installed). The second one is based on the built-in <type>point</> data type, using longitude and latitude for the coordinates. </para> @@ -24,7 +24,7 @@ </para> <sect2> - <title>Cube-based earth distances</title> + <title>Cube-based Earth Distances</title> <para> Data is stored in cubes that are points (both corners are the same) using 3 @@ -38,7 +38,7 @@ The radius of the Earth is obtained from the <function>earth()</> function. It is given in meters. But by changing this one function you can change the module to use some other units, or to use a different value of - the radius that you feel is more appropiate. + the radius that you feel is more appropriate. </para> <para> @@ -55,11 +55,12 @@ </para> <para> - The following functions are provided: + The provided functions are shown + in <xref linkend="earthdistance-cube-functions">. </para> <table id="earthdistance-cube-functions"> - <title>Cube-based earthdistance functions</title> + <title>Cube-based Earthdistance Functions</title> <tgroup cols="3"> <thead> <row> @@ -136,7 +137,7 @@ </sect2> <sect2> - <title>Point-based earth distances</title> + <title>Point-based Earth Distances</title> <para> The second part of the module relies on representing Earth locations as @@ -148,11 +149,12 @@ </para> <para> - A single operator is provided: + A single operator is provided, shown + in <xref linkend="earthdistance-point-operators">. </para> <table id="earthdistance-point-operators"> - <title>Point-based earthdistance operators</title> + <title>Point-based Earthdistance Operators</title> <tgroup cols="3"> <thead> <row> diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml index 7c8b02802d..def250c156 100644 --- a/doc/src/sgml/ecpg.sgml +++ b/doc/src/sgml/ecpg.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/ecpg.sgml,v 1.100 2010/05/13 14:16:41 mha Exp $ --> +<!-- doc/src/sgml/ecpg.sgml --> <chapter id="ecpg"> <title><application>ECPG</application> - Embedded <acronym>SQL</acronym> in C</title> @@ -13,7 +13,7 @@ Linus Tolke (<email>linus@epact.se</email>) and Michael Meskes (<email>meskes@postgresql.org</email>). Originally it was written to work with <acronym>C</acronym>. It also works with <acronym>C++</acronym>, but - it does not recognize all <acronym>C++</acronym> constructs yet. + it does not recognize all <acronym>C++</acronym> constructs yet. </para> <para> @@ -28,10 +28,13 @@ <para> An embedded SQL program consists of code written in an ordinary programming language, in this case C, mixed with SQL commands in - specially marked sections. To build the program, the source code + specially marked sections. To build the program, the source code (<filename>*.pgc</filename>) is first passed through the embedded SQL preprocessor, which converts it - to an ordinary C program, and afterwards it can be processed by a C - compiler. + to an ordinary C program (<filename>*.c</filename>), and afterwards it can be processed by a C + compiler. (For details about the compiling and linking see <xref linkend="ecpg-process">). + Converted ECPG applications call functions in the libpq library + through the embedded SQL library (ecpglib), and communicate with + the PostgreSQL server using the normal frontend-backend protocol. </para> <para> @@ -71,7 +74,15 @@ EXEC SQL ...; </sect1> <sect1 id="ecpg-connect"> - <title>Connecting to the Database Server</title> + <title>Managing Database Connections</title> + + <para> + This section describes how to open, close, and switch database + connections. + </para> + + <sect2 id="ecpg-connecting"> + <title>Connecting to the Database Server</title> <para> One connects to a database using the following statement: @@ -99,7 +110,7 @@ EXEC SQL CONNECT TO <replaceable>target</replaceable> <optional>AS <replaceable> <literal>unix:postgresql://<replaceable>hostname</><optional>:<replaceable>port</></optional><optional>/<replaceable>dbname</></optional><optional>?<replaceable>options</></optional></literal> </simpara> </listitem> - + <listitem> <simpara> an SQL string literal containing one of the above forms @@ -111,7 +122,7 @@ EXEC SQL CONNECT TO <replaceable>target</replaceable> <optional>AS <replaceable> a reference to a character variable containing one of the above forms (see examples) </simpara> </listitem> - + <listitem> <simpara> <literal>DEFAULT</literal> @@ -200,10 +211,91 @@ EXEC SQL CONNECT TO :target USER :user; example above to encapsulate the connection target string somewhere. </para> - </sect1> + </sect2> + + <sect2 id="ecpg-set-connection"> + <title>Choosing a Connection</title> + + <para> + SQL statements in embedded SQL programs are by default executed on + the current connection, that is, the most recently opened one. If + an application needs to manage multiple connections, then there are + two ways to handle this. + </para> + + <para> + The first option is to explicitly choose a connection for each SQL + statement, for example: +<programlisting> +EXEC SQL AT <replaceable>connection-name</replaceable> SELECT ...; +</programlisting> + This option is particularly suitable if the application needs to + use several connections in mixed order. + </para> + + <para> + If your application uses multiple threads of execution, they cannot share a + connection concurrently. You must either explicitly control access to the connection + (using mutexes) or use a connection for each thread. If each thread uses its own connection, + you will need to use the AT clause to specify which connection the thread will use. + </para> + + <para> + The second option is to execute a statement to switch the current + connection. That statement is: +<programlisting> +EXEC SQL SET CONNECTION <replaceable>connection-name</replaceable>; +</programlisting> + This option is particularly convenient if many statements are to be + executed on the same connection. It is not thread-aware. + </para> + + <para> + Here is an example program managing multiple database connections: +<programlisting><![CDATA[ +#include <stdio.h> - <sect1 id="ecpg-disconnect"> - <title>Closing a Connection</title> +EXEC SQL BEGIN DECLARE SECTION; + char dbname[1024]; +EXEC SQL END DECLARE SECTION; + +int +main() +{ + EXEC SQL CONNECT TO testdb1 AS con1 USER testuser; + EXEC SQL CONNECT TO testdb2 AS con2 USER testuser; + EXEC SQL CONNECT TO testdb3 AS con3 USER testuser; + + /* This query would be executed in the last opened database "testdb3". */ + EXEC SQL SELECT current_database() INTO :dbname; + printf("current=%s (should be testdb3)\n", dbname); + + /* Using "AT" to run a query in "testdb2" */ + EXEC SQL AT con2 SELECT current_database() INTO :dbname; + printf("current=%s (should be testdb2)\n", dbname); + + /* Switch the current connection to "testdb1". */ + EXEC SQL SET CONNECTION con1; + + EXEC SQL SELECT current_database() INTO :dbname; + printf("current=%s (should be testdb1)\n", dbname); + + EXEC SQL DISCONNECT ALL; + return 0; +} +]]></programlisting> + + This example would produce this output: +<screen> +current=testdb3 (should be testdb3) +current=testdb2 (should be testdb2) +current=testdb1 (should be testdb1) +</screen> + </para> + </sect2> + + <sect2 id="ecpg-disconnect"> + <title>Closing a Connection</title> <para> To close a connection, use the following statement: @@ -247,6 +339,8 @@ EXEC SQL DISCONNECT <optional><replaceable>connection</replaceable></optional>; It is good style that an application always explicitly disconnect from every connection it opened. </para> + </sect2> + </sect1> <sect1 id="ecpg-commands"> @@ -257,6 +351,9 @@ EXEC SQL DISCONNECT <optional><replaceable>connection</replaceable></optional>; Below are some examples of how to do that. </para> + <sect2 id="ecpg-executing"> + <title>Executing SQL Statements</title> + <para> Creating a table: <programlisting> @@ -283,6 +380,26 @@ EXEC SQL COMMIT; </para> <para> + Updates: +<programlisting> +EXEC SQL UPDATE foo + SET ascii = 'foobar' + WHERE number = 9999; +EXEC SQL COMMIT; +</programlisting> + </para> + + <para> + <literal>SELECT</literal> statements that return a single result + row can also be executed using + <literal>EXEC SQL</literal> directly. To handle result sets with + multiple rows, an application has to use a cursor; + see <xref linkend="ecpg-cursors"> below. (As a special case, an + application can fetch multiple rows at once into an array host + variable; see <xref linkend="ecpg-variables-arrays">.) + </para> + + <para> Single-row select: <programlisting> EXEC SQL SELECT foo INTO :FooBar FROM table1 WHERE ascii = 'doodad'; @@ -290,6 +407,33 @@ EXEC SQL SELECT foo INTO :FooBar FROM table1 WHERE ascii = 'doodad'; </para> <para> + Also, a configuration parameter can be retrieved with the + <literal>SHOW</literal> command: +<programlisting> +EXEC SQL SHOW search_path INTO :var; +</programlisting> + </para> + + <para> + The tokens of the form + <literal>:<replaceable>something</replaceable></literal> are + <firstterm>host variables</firstterm>, that is, they refer to + variables in the C program. They are explained in <xref + linkend="ecpg-variables">. + </para> + </sect2> + + <sect2 id="ecpg-cursors"> + <title>Using Cursors</title> + + <para> + To retrieve a result set holding multiple rows, an application has + to declare a cursor and fetch each row from the cursor. The steps + to use a cursor are the following: declare a cursor, open it, fetch + a row from the cursor, repeat, and finally close it. + </para> + + <para> Select using cursors: <programlisting> EXEC SQL DECLARE foo_bar CURSOR FOR @@ -304,72 +448,150 @@ EXEC SQL COMMIT; </para> <para> - Updates: -<programlisting> -EXEC SQL UPDATE foo - SET ascii = 'foobar' - WHERE number = 9999; -EXEC SQL COMMIT; -</programlisting> + For more details about declaration of the cursor, + see <xref linkend="ecpg-sql-declare">, and + see <xref linkend="sql-fetch"> for <literal>FETCH</literal> command + details. </para> - <para> - The tokens of the form - <literal>:<replaceable>something</replaceable></literal> are - <firstterm>host variables</firstterm>, that is, they refer to - variables in the C program. They are explained in <xref - linkend="ecpg-variables">. - </para> + <note> + <para> + The ECPG <command>DECLARE</command> command does not actually + cause a statement to be sent to the PostgreSQL backend. The + cursor is opened in the backend (using the + backend's <command>DECLARE</command> command) at the point when + the <command>OPEN</command> command is executed. + </para> + </note> + </sect2> + + <sect2 id="ecpg-transactions"> + <title>Managing Transactions</title> <para> In the default mode, statements are committed only when <command>EXEC SQL COMMIT</command> is issued. The embedded SQL interface also supports autocommit of transactions (similar to - <application>libpq</> behavior) via the <option>-t</option> command-line - option to <command>ecpg</command> (see below) or via the <literal>EXEC SQL - SET AUTOCOMMIT TO ON</literal> statement. In autocommit mode, each - command is automatically committed unless it is inside an explicit - transaction block. This mode can be explicitly turned off using - <literal>EXEC SQL SET AUTOCOMMIT TO OFF</literal>. + <application>libpq</> behavior) via the <option>-t</option> + command-line option to <command>ecpg</command> (see <xref + linkend="app-ecpg">) or via the <literal>EXEC SQL SET AUTOCOMMIT TO + ON</literal> statement. In autocommit mode, each command is + automatically committed unless it is inside an explicit transaction + block. This mode can be explicitly turned off using <literal>EXEC + SQL SET AUTOCOMMIT TO OFF</literal>. </para> - </sect1> - <sect1 id="ecpg-set-connection"> - <title>Choosing a Connection</title> + <para> + The following transaction management commands are available: - <para> - The SQL statements shown in the previous section are executed on - the current connection, that is, the most recently opened one. If - an application needs to manage multiple connections, then there are - two ways to handle this. - </para> + <variablelist> + <varlistentry> + <term><literal>EXEC SQL COMMIT</literal></term> + <listitem> + <para> + Commit an in-progress transaction. + </para> + </listitem> + </varlistentry> - <para> - The first option is to explicitly choose a connection for each SQL - statement, for example: + <varlistentry> + <term><literal>EXEC SQL ROLLBACK</literal></term> + <listitem> + <para> + Roll back an in-progress transaction. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>EXEC SQL SET AUTOCOMMIT TO ON</literal></term> + <listitem> + <para> + Enable autocommit mode. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>SET AUTOCOMMIT TO OFF</literal></term> + <listitem> + <para> + Disable autocommit mode. This is the default. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </sect2> + + <sect2 id="ecpg-prepared"> + <title>Prepared Statements</title> + + <para> + When the values to be passed to an SQL statement are not known at + compile time, or the same statement is going to be used many + times, then prepared statements can be useful. + </para> + + <para> + The statement is prepared using the + command <literal>PREPARE</literal>. For the values that are not + known yet, use the + placeholder <quote><literal>?</literal></quote>: <programlisting> -EXEC SQL AT <replaceable>connection-name</replaceable> SELECT ...; +EXEC SQL PREPARE stmt1 FROM "SELECT oid, datname FROM pg_database WHERE oid = ?"; </programlisting> - This option is particularly suitable if the application needs to - use several connections in mixed order. - </para> + </para> - <para> - If your application uses multiple threads of execution, they cannot share a - connection concurrently. You must either explicitly control access to the connection - (using mutexes) or use a connection for each thread. If each thread uses its own connection, - you will need to use the AT clause to specify which connection the thread will use. - </para> + <para> + If a statement returns a single row, the application can + call <literal>EXECUTE</literal> after + <literal>PREPARE</literal> to execute the statement, supplying the + actual values for the placeholders with a <literal>USING</literal> + clause: +<programlisting> +EXEC SQL EXECUTE stmt1 INTO :dboid, :dbname USING 1; +</programlisting> + </para> - <para> - The second option is to execute a statement to switch the current - connection. That statement is: + <para> + If a statement returns multiple rows, the application can use a + cursor declared based on the prepared statement. To bind input + parameters, the cursor must be opened with + a <literal>USING</literal> clause: <programlisting> -EXEC SQL SET CONNECTION <replaceable>connection-name</replaceable>; +EXEC SQL PREPARE stmt1 FROM "SELECT oid,datname FROM pg_database WHERE oid > ?"; +EXEC SQL DECLARE foo_bar CURSOR FOR stmt1; + +/* when end of result set reached, break out of while loop */ +EXEC SQL WHENEVER NOT FOUND DO BREAK; + +EXEC SQL OPEN foo_bar USING 100; +... +while (1) +{ + EXEC SQL FETCH NEXT FROM foo_bar INTO :dboid, :dbname; + ... +} +EXEC SQL CLOSE foo_bar; </programlisting> - This option is particularly convenient if many statements are to be - executed on the same connection. It is not thread-aware. - </para> + </para> + + <para> + When you don't need the prepared statement anymore, you should + deallocate it: +<programlisting> +EXEC SQL DEALLOCATE PREPARE <replaceable>name</replaceable>; +</programlisting> + </para> + + <para> + For more details about <literal>PREPARE</literal>, + see <xref linkend="ecpg-sql-prepare">. Also + see <xref linkend="ecpg-dynamic"> for more details about using + placeholders and input parameters. + </para> + </sect2> </sect1> <sect1 id="ecpg-variables"> @@ -391,7 +613,13 @@ EXEC SQL SET CONNECTION <replaceable>connection-name</replaceable>; variables</firstterm>. </para> - <sect2> + <para> + Another way to exchange values between PostgreSQL backends and ECPG + applications is the use of SQL descriptors, described + in <xref linkend="ecpg-descriptors">. + </para> + + <sect2 id="ecpg-variables-overview"> <title>Overview</title> <para> @@ -416,7 +644,7 @@ EXEC SQL INSERT INTO sometable VALUES (:v1, 'foo', :v2); </para> </sect2> - <sect2> + <sect2 id="ecpg-declare-sections"> <title>Declare Sections</title> <para> @@ -467,107 +695,8 @@ EXEC SQL int i = 4; </para> </sect2> - <sect2> - <title>Different types of host variables</title> - <para> - As a host variable you can also use arrays, typedefs, structs and - pointers. Moreover there are special types of host variables that exist - only in ECPG. - </para> - - <para> - A few examples on host variables: - <variablelist> - <varlistentry> - <term>Arrays</term> - <listitem> - <para> - One of the most common uses of an array declaration is probably the - allocation of a char array as in: -<programlisting> -EXEC SQL BEGIN DECLARE SECTION; - char str[50]; -EXEC SQL END DECLARE SECTION; -</programlisting> - Note that you have to take care of the length for yourself. If you use - this host variable as the target variable of a query which returns a - string with more than 49 characters, a buffer overflow occurs. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Typedefs</term> - <listitem> - <para> - Use the <literal>typedef</literal> keyword to map new types to already - existing types. -<programlisting> -EXEC SQL BEGIN DECLARE SECTION; - typedef char mychartype[40]; - typedef long serial_t; -EXEC SQL END DECLARE SECTION; -</programlisting> - Note that you could also use: -<programlisting> -EXEC SQL TYPE serial_t IS long; -</programlisting> - This declaration does not need to be part of a declare section. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Pointers</term> - <listitem> - <para> - You can declare pointers to the most common types. Note however that - you cannot use pointers as target variables of queries without - auto-allocation. See <xref linkend="ecpg-descriptors"> for more - information on auto-allocation. - </para> -<programlisting> -EXEC SQL BEGIN DECLARE SECTION; - int *intp; - char **charp; -EXEC SQL END DECLARE SECTION; -</programlisting> - </listitem> - </varlistentry> - - <varlistentry> - <term>Special types of variables</term> - <listitem> - <para> - ECPG contains some special types that help you to interact easily with - data from the SQL server. For example it has implemented support for - the <type>varchar</>, <type>numeric</>, <type>date</>, <type>timestamp</>, and <type>interval</> types. - <xref linkend="ecpg-pgtypes"> contains basic functions to deal with - those types, such that you do not need to send a query to the SQL - server just for adding an interval to a timestamp for example. - </para> - <para> - The special type <type>VARCHAR</type> - is converted into a named <type>struct</> for every variable. A - declaration like: -<programlisting> -VARCHAR var[180]; -</programlisting> - is converted into: -<programlisting> -struct varchar_var { int len; char arr[180]; } var; -</programlisting> - This structure is suitable for interfacing with SQL datums of type - <type>varchar</type>. - </para> - </listitem> - </varlistentry> - </variablelist> - </para> - </sect2> - - <sect2> - <title><command>SELECT INTO</command> and <command>FETCH INTO</command></title> + <sect2 id="ecpg-retrieving"> + <title>Retrieving Query Results</title> <para> Now you should be able to pass data generated by your program into @@ -577,6 +706,9 @@ struct varchar_var { int len; char arr[180]; } var; <command>FETCH</command>. These commands have a special <literal>INTO</literal> clause that specifies which host variables the retrieved values are to be stored in. + <command>SELECT</command> is used for a query that returns only + single row, and <command>FETCH</command> is used for a query that + returns multiple rows, using a cursor. </para> <para> @@ -617,7 +749,8 @@ EXEC SQL DECLARE foo CURSOR FOR SELECT a, b FROM test; ... -do { +do +{ ... EXEC SQL FETCH NEXT FROM foo INTO :v1, :v2; ... @@ -634,7 +767,951 @@ do { </para> </sect2> - <sect2> + <sect2 id="ecpg-variables-type-mapping"> + <title>Type Mapping</title> + + <para> + When ECPG applications exchange values between the PostgreSQL + server and the C application, such as when retrieving query + results from the server or executing SQL statements with input + parameters, the values need to be converted between PostgreSQL + data types and host language variable types (C language data + types, concretely). One of the main points of ECPG is that it + takes care of this automatically in most cases. + </para> + + <para> + In this respect, there are two kinds of data types: Some simple + PostgreSQL data types, such as <type>integer</type> + and <type>text</type>, can be read and written by the application + directly. Other PostgreSQL data types, such + as <type>timestamp</type> and <type>numeric</type> can only be + accessed through special library functions; see + <xref linkend="ecpg-special-types">. + </para> + + <para> + <xref linkend="ecpg-datatype-hostvars-table"> shows which PostgreSQL + data types correspond to which C data types. When you wish to + send or receive a value of a given PostgreSQL data type, you + should declare a C variable of the corresponding C data type in + the declare section. + </para> + + <table id="ecpg-datatype-hostvars-table"> + <title>Mapping Between PostgreSQL Data Types and C Variable Types</title> + <tgroup cols="2"> + <thead> + <row> + <entry>PostgreSQL data type</entry> + <entry>Host variable type</entry> + </row> + </thead> + + <tbody> + <row> + <entry><type>smallint</type></entry> + <entry><type>short</type></entry> + </row> + + <row> + <entry><type>integer</type></entry> + <entry><type>int</type></entry> + </row> + + <row> + <entry><type>bigint</type></entry> + <entry><type>long long int</type></entry> + </row> + + <row> + <entry><type>decimal</type></entry> + <entry><type>decimal</type><footnote id="ecpg-datatype-table-fn"><para>This type can only be accessed through special library functions; see <xref linkend="ecpg-special-types">.</para></footnote></entry> + </row> + + <row> + <entry><type>numeric</type></entry> + <entry><type>numeric</type><footnoteref linkend="ecpg-datatype-table-fn"></entry> + </row> + + <row> + <entry><type>real</type></entry> + <entry><type>float</type></entry> + </row> + + <row> + <entry><type>double precision</type></entry> + <entry><type>double</type></entry> + </row> + + <row> + <entry><type>serial</type></entry> + <entry><type>int</type></entry> + </row> + + <row> + <entry><type>bigserial</type></entry> + <entry><type>long long int</type></entry> + </row> + + <row> + <entry><type>oid</type></entry> + <entry><type>unsigned int</type></entry> + </row> + + <row> + <entry><type>character(<replaceable>n</>)</type>, <type>varchar(<replaceable>n</>)</type>, <type>text</type></entry> + <entry><type>char[<replaceable>n</>+1]</type>, <type>VARCHAR[<replaceable>n</>+1]</type><footnote><para>declared in <filename>ecpglib.h</filename></para></footnote></entry> + </row> + + <row> + <entry><type>name</type></entry> + <entry><type>char[NAMEDATALEN]</type></entry> + </row> + + <row> + <entry><type>timestamp</type></entry> + <entry><type>timestamp</type><footnoteref linkend="ecpg-datatype-table-fn"></entry> + </row> + + <row> + <entry><type>interval</type></entry> + <entry><type>interval</type><footnoteref linkend="ecpg-datatype-table-fn"></entry> + </row> + + <row> + <entry><type>date</type></entry> + <entry><type>date</type><footnoteref linkend="ecpg-datatype-table-fn"></entry> + </row> + + <row> + <entry><type>boolean</type></entry> + <entry><type>bool</type><footnote><para>declared in <filename>ecpglib.h</filename> if not native</para></footnote></entry> + </row> + </tbody> + </tgroup> + </table> + + <sect3 id="ecpg-char"> + <title>Handling Character Strings</title> + + <para> + To handle SQL character string data types, such + as <type>varchar</type> and <type>text</type>, there are two + possible ways to declare the host variables. + </para> + + <para> + One way is using <type>char[]</type>, an array + of <type>char</type>, which is the most common way to handle + character data in C. +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; + char str[50]; +EXEC SQL END DECLARE SECTION; +</programlisting> + Note that you have to take care of the length yourself. If you + use this host variable as the target variable of a query which + returns a string with more than 49 characters, a buffer overflow + occurs. + </para> + + <para> + The other way is using the <type>VARCHAR</type> type, which is a + special type provided by ECPG. The definition on an array of + type <type>VARCHAR</type> is converted into a + named <type>struct</> for every variable. A declaration like: +<programlisting> +VARCHAR var[180]; +</programlisting> + is converted into: +<programlisting> +struct varchar_var { int len; char arr[180]; } var; +</programlisting> + The member <structfield>arr</structfield> hosts the string + including a terminating zero byte. Thus, to store a string in + a <type>VARCHAR</type> host variable, the host variable has to be + declared with the length including the zero byte terminator. The + member <structfield>len</structfield> holds the length of the + string stored in the <structfield>arr</structfield> without the + terminating zero byte. When a host variable is used as input for + a query, if <literal>strlen(arr)</literal> + and <structfield>len</structfield> are different, the shorter one + is used. + </para> + + <para> + Two or more <type>VARCHAR</type> host variables cannot be defined + in single line statement. The following code will confuse + the <command>ecpg</command> preprocessor: +<programlisting> +VARCHAR v1[128], v2[128]; /* WRONG */ +</programlisting> + Two variables should be defined in separate statements like this: +<programlisting> +VARCHAR v1[128]; +VARCHAR v2[128]; +</programlisting> + </para> + + <para> + <type>VARCHAR</type> can be written in upper or lower case, but + not in mixed case. + </para> + + <para> + <type>char</type> and <type>VARCHAR</type> host variables can + also hold values of other SQL types, which will be stored in + their string forms. + </para> + </sect3> + + <sect3 id="ecpg-special-types"> + <title>Accessing Special Data Types</title> + + <para> + ECPG contains some special types that help you to interact easily + with some special data types from the PostgreSQL server. In + particular, it has implemented support for the + <type>numeric</>, <type>decimal</type>, <type>date</>, <type>timestamp</>, + and <type>interval</> types. These data types cannot usefully be + mapped to primitive host variable types (such + as <type>int</>, <type>long long int</type>, + or <type>char[]</type>), because they have a complex internal + structure. Applications deal with these types by declaring host + variables in special types and accessing them using functions in + the pgtypes library. The pgtypes library, described in detail + in <xref linkend="ecpg-pgtypes"> contains basic functions to deal + with those types, such that you do not need to send a query to + the SQL server just for adding an interval to a time stamp for + example. + </para> + + <para> + The follow subsections describe these special data types. For + more details about pgtypes library functions, + see <xref linkend="ecpg-pgtypes">. + </para> + + <sect4> + <title id="ecpg-type-timestamp-date">timestamp, date</title> + + <para> + Here is a pattern for handling <type>timestamp</type> variables + in the ECPG host application. + </para> + + <para> + First, the program has to include the header file for the + <type>timestamp</type> type: +<programlisting> +#include <pgtypes_timestamp.h> +</programlisting> + </para> + + <para> + Next, declare a host variable as type <type>timestamp</type> in + the declare section: +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; +timestamp ts; +EXEC SQL END DECLARE SECTION; +</programlisting> + </para> + + <para> + And after reading a value into the host variable, process it + using pgtypes library functions. In following example, the + <type>timestamp</type> value is converted into text (ASCII) form + with the <function>PGTYPEStimestamp_to_asc()</function> + function: +<programlisting> +EXEC SQL SELECT now()::timestamp INTO :ts; + +printf("ts = %s\n", PGTYPEStimestamp_to_asc(ts)); +</programlisting> + This example will show some result like following: +<screen> +ts = 2010-06-27 18:03:56.949343 +</screen> + </para> + + <para> + In addition, the DATE type can be handled in the same way. The + program has to include <filename>pg_types_date.h</filename>, declare a host variable + as the date type and convert a DATE value into a text form using + <function>PGTYPESdate_to_asc()</function> function. For more details about the + pgtypes library functions, see <xref linkend="ecpg-pgtypes">. + </para> + </sect4> + + <sect4 id="ecpg-type-interval"> + <title>interval</title> + + <para> + The handling of the <type>interval</type> type is also similar + to the <type>timestamp</type> and <type>date</type> types. It + is required, however, to allocate memory for + an <type>interval</type> type value explicitly. In other words, + the memory space for the variable has to be allocated in the + heap memory, not in the stack memory. + </para> + + <para> + Here is an example program: +<programlisting> +#include <stdio.h> +#include <stdlib.h> +#include <pgtypes_interval.h> + +int +main(void) +{ +EXEC SQL BEGIN DECLARE SECTION; + interval *in; +EXEC SQL END DECLARE SECTION; + + EXEC SQL CONNECT TO testdb; + + in = PGTYPESinterval_new(); + EXEC SQL SELECT '1 min'::interval INTO :in; + printf("interval = %s\n", PGTYPESinterval_to_asc(in)); + PGTYPESinterval_free(in); + + EXEC SQL COMMIT; + EXEC SQL DISCONNECT ALL; + return 0; +} +</programlisting> + </para> + </sect4> + + <sect4 id="ecpg-type-numeric-decimal"> + <title>numeric, decimal</title> + + <para> + The handling of the <type>numeric</type> + and <type>decimal</type> types is similar to the + <type>interval</type> type: It requires defining a pointer, + allocating some memory space on the heap, and accessing the + variable using the pgtypes library functions. For more details + about the pgtypes library functions, + see <xref linkend="ecpg-pgtypes">. + </para> + + <para> + No functions are provided specifically for + the <type>decimal</type> type. An application has to convert it + to a <type>numeric</type> variable using a pgtypes library + function to do further processing. + </para> + + <para> + Here is an example program handling <type>numeric</type> + and <type>decimal</type> type variables. +<programlisting> +#include <stdio.h> +#include <stdlib.h> +#include <pgtypes_numeric.h> + +EXEC SQL WHENEVER SQLERROR STOP; + +int +main(void) +{ +EXEC SQL BEGIN DECLARE SECTION; + numeric *num; + numeric *num2; + decimal *dec; +EXEC SQL END DECLARE SECTION; + + EXEC SQL CONNECT TO testdb; + + num = PGTYPESnumeric_new(); + dec = PGTYPESdecimal_new(); + + EXEC SQL SELECT 12.345::numeric(4,2), 23.456::decimal(4,2) INTO :num, :dec; + + printf("numeric = %s\n", PGTYPESnumeric_to_asc(num, 0)); + printf("numeric = %s\n", PGTYPESnumeric_to_asc(num, 1)); + printf("numeric = %s\n", PGTYPESnumeric_to_asc(num, 2)); + + /* Convert decimal to numeric to show a decimal value. */ + num2 = PGTYPESnumeric_new(); + PGTYPESnumeric_from_decimal(dec, num2); + + printf("decimal = %s\n", PGTYPESnumeric_to_asc(num2, 0)); + printf("decimal = %s\n", PGTYPESnumeric_to_asc(num2, 1)); + printf("decimal = %s\n", PGTYPESnumeric_to_asc(num2, 2)); + + PGTYPESnumeric_free(num2); + PGTYPESdecimal_free(dec); + PGTYPESnumeric_free(num); + + EXEC SQL COMMIT; + EXEC SQL DISCONNECT ALL; + return 0; +} +</programlisting> + </para> + </sect4> + </sect3> + + <sect3 id="ecpg-variables-nonprimitive-c"> + <title>Host Variables with Nonprimitive Types</title> + + <para> + As a host variable you can also use arrays, typedefs, structs, and + pointers. + </para> + + <sect4 id="ecpg-variables-arrays"> + <title>Arrays</title> + + <para> + There are two use cases for arrays as host variables. The first + is a way to store some text string in <type>char[]</type> + or <type>VARCHAR[]</type>, as + explained <xref linkend="ecpg-char">. The second use case is to + retrieve multiple rows from a query result without using a + cursor. Without an array, to process a query result consisting + of multiple rows, it is required to use a cursor and + the <command>FETCH</command> command. But with array host + variables, multiple rows can be received at once. The length of + the array has to be defined to be able to accommodate all rows, + otherwise a buffer overflow will likely occur. + </para> + + <para> + Following example scans the <literal>pg_database</literal> + system table and shows all OIDs and names of the available + databases: +<programlisting> +int +main(void) +{ +EXEC SQL BEGIN DECLARE SECTION; + int dbid[8]; + char dbname[8][16]; + int i; +EXEC SQL END DECLARE SECTION; + + memset(dbname, 0, sizeof(char)* 16 * 8); + memset(dbid, 0, sizeof(int) * 8); + + EXEC SQL CONNECT TO testdb; + + /* Retrieve multiple rows into arrays at once. */ + EXEC SQL SELECT oid,datname INTO :dbid, :dbname FROM pg_database; + + for (i = 0; i < 8; i++) + printf("oid=%d, dbname=%s\n", dbid[i], dbname[i]); + + EXEC SQL COMMIT; + EXEC SQL DISCONNECT ALL; + return 0; +} +</programlisting> + + This example shows following result. (The exact values depend on + local circumstances.) +<screen> +oid=1, dbname=template1 +oid=11510, dbname=template0 +oid=11511, dbname=postgres +oid=313780, dbname=testdb +oid=0, dbname= +oid=0, dbname= +oid=0, dbname= +</screen> + </para> + </sect4> + + <sect4 id="ecpg-variables-struct"> + <title>Structures</title> + + <para> + A structure whose member names match the column names of a query + result, can be used to retrieve multiple columns at once. The + structure enables handling multiple column values in a single + host variable. + </para> + + <para> + The following example retrieves OIDs, names, and sizes of the + available databases from the <literal>pg_database</literal> + system table and using + the <function>pg_database_size()</function> function. In this + example, a structure variable <varname>dbinfo_t</varname> with + members whose names match each column in + the <literal>SELECT</literal> result is used to retrieve one + result row without putting multiple host variables in + the <literal>FETCH</literal> statement. +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; + typedef struct + { + int oid; + char datname[65]; + long long int size; + } dbinfo_t; + + dbinfo_t dbval; +EXEC SQL END DECLARE SECTION; + + memset(&dbval, 0, sizeof(dbinfo_t)); + + EXEC SQL DECLARE cur1 CURSOR FOR SELECT oid, datname, pg_database_size(oid) AS size FROM pg_database; + EXEC SQL OPEN cur1; + + /* when end of result set reached, break out of while loop */ + EXEC SQL WHENEVER NOT FOUND DO BREAK; + + while (1) + { + /* Fetch multiple columns into one structure. */ + EXEC SQL FETCH FROM cur1 INTO :dbval; + + /* Print members of the structure. */ + printf("oid=%d, datname=%s, size=%lld\n", dbval.oid, dbval.datname, dbval.size); + } + + EXEC SQL CLOSE cur1; +</programlisting> + </para> + + <para> + This example shows following result. (The exact values depend on + local circumstances.) +<screen> +oid=1, datname=template1, size=4324580 +oid=11510, datname=template0, size=4243460 +oid=11511, datname=postgres, size=4324580 +oid=313780, datname=testdb, size=8183012 +</screen> + </para> + + <para> + Structure host variables <quote>absorb</quote> as many columns + as the structure as fields. Additional columns can be assigned + to other host variables. For example, the above program could + also be restructured like this, with the <varname>size</varname> + variable outside the structure: +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; + typedef struct + { + int oid; + char datname[65]; + } dbinfo_t; + + dbinfo_t dbval; + long long int size; +EXEC SQL END DECLARE SECTION; + + memset(&dbval, 0, sizeof(dbinfo_t)); + + EXEC SQL DECLARE cur1 CURSOR FOR SELECT oid, datname, pg_database_size(oid) AS size FROM pg_database; + EXEC SQL OPEN cur1; + + /* when end of result set reached, break out of while loop */ + EXEC SQL WHENEVER NOT FOUND DO BREAK; + + while (1) + { + /* Fetch multiple columns into one structure. */ + EXEC SQL FETCH FROM cur1 INTO :dbval, :size; + + /* Print members of the structure. */ + printf("oid=%d, datname=%s, size=%lld\n", dbval.oid, dbval.datname, size); + } + + EXEC SQL CLOSE cur1; +</programlisting> + </para> + </sect4> + + <sect4> + <title>Typedefs</title> + + <para> + Use the <literal>typedef</literal> keyword to map new types to already + existing types. +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; + typedef char mychartype[40]; + typedef long serial_t; +EXEC SQL END DECLARE SECTION; +</programlisting> + Note that you could also use: +<programlisting> +EXEC SQL TYPE serial_t IS long; +</programlisting> + This declaration does not need to be part of a declare section. + </para> + </sect4> + + <sect4> + <title>Pointers</title> + + <para> + You can declare pointers to the most common types. Note however + that you cannot use pointers as target variables of queries + without auto-allocation. See <xref linkend="ecpg-descriptors"> + for more information on auto-allocation. + </para> + + <para> +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; + int *intp; + char **charp; +EXEC SQL END DECLARE SECTION; +</programlisting> + </para> + </sect4> + </sect3> + </sect2> + + <sect2 id="ecpg-variables-nonprimitive-sql"> + <title>Handling Nonprimitive SQL Data Types</title> + + <para> + This section contains information on how to handle nonscalar and + user-defined SQL-level data types in ECPG applications. Note that + this is distinct from the handling of host variables of + nonprimitive types, described in the previous section. + </para> + + <sect3> + <title>Arrays</title> + + <para> + SQL-level arrays are not directly supported in ECPG. It is not + possible to simply map an SQL array into a C array host variable. + This will result in undefined behavior. Some workarounds exist, + however. + </para> + + <para> + If a query accesses <emphasis>elements</emphasis> of an array + separately, then this avoids the use of arrays in ECPG. Then, a + host variable with a type that can be mapped to the element type + should be used. For example, if a column type is array of + <type>integer</type>, a host variable of type <type>int</type> + can be used. Also if the element type is <type>varchar</type> + or <type>text</type>, a host variable of type <type>char[]</type> + or <type>VARCHAR[]</type> can be used. + </para> + + <para> + Here is an example. Assume the following table: +<programlisting> +CREATE TABLE t3 ( + ii integer[] +); + +testdb=> SELECT * FROM t3; + ii +------------- + {1,2,3,4,5} +(1 row) +</programlisting> + + The following example program retrieves the 4th element of the + array and stores it into a host variable of + type <type>int</type>: +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; +int ii; +EXEC SQL END DECLARE SECTION; + +EXEC SQL DECLARE cur1 CURSOR FOR SELECT ii[4] FROM t3; +EXEC SQL OPEN cur1; + +EXEC SQL WHENEVER NOT FOUND DO BREAK; + +while (1) +{ + EXEC SQL FETCH FROM cur1 INTO :ii ; + printf("ii=%d\n", ii); +} + +EXEC SQL CLOSE cur1; +</programlisting> + + This example shows the following result: +<screen> +ii=4 +</screen> + </para> + + <para> + To map multiple array elements to the multiple elements in an + array type host variables each element of array column and each + element of the host variable array have to be managed separately, + for example: +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; +int ii_a[8]; +EXEC SQL END DECLARE SECTION; + +EXEC SQL DECLARE cur1 CURSOR FOR SELECT ii[1], ii[2], ii[3], ii[4] FROM t3; +EXEC SQL OPEN cur1; + +EXEC SQL WHENEVER NOT FOUND DO BREAK; + +while (1) +{ + EXEC SQL FETCH FROM cur1 INTO :ii_a[0], :ii_a[1], :ii_a[2], :ii_a[3]; + ... +} +</programlisting> + </para> + + <para> + Note again that +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; +int ii_a[8]; +EXEC SQL END DECLARE SECTION; + +EXEC SQL DECLARE cur1 CURSOR FOR SELECT ii FROM t3; +EXEC SQL OPEN cur1; + +EXEC SQL WHENEVER NOT FOUND DO BREAK; + +while (1) +{ + /* WRONG */ + EXEC SQL FETCH FROM cur1 INTO :ii_a; + ... +} +</programlisting> + would not work correctly in this case, because you cannot map an + array type column to an array host variable directly. + </para> + + <para> + Another workaround is to store arrays in their external string + representation in host variables of type <type>char[]</type> + or <type>VARCHAR[]</type>. For more details about this + representation, see <xref linkend="arrays-input">. Note that + this means that the array cannot be accessed naturally as an + array in the host program (without further processing that parses + the text representation). + </para> + </sect3> + + <sect3> + <title>Composite Types</title> + + <para> + Composite types are not directly supported in ECPG, but an easy workaround is possible. + The + available workarounds are similar to the ones described for + arrays above: Either access each attribute separately or use the + external string representation. + </para> + + <para> + For the following examples, assume the following type and table: +<programlisting> +CREATE TYPE comp_t AS (intval integer, textval varchar(32)); +CREATE TABLE t4 (compval comp_t); +INSERT INTO t4 VALUES ( (256, 'PostgreSQL') ); +</programlisting> + + The most obvious solution is to access each attribute separately. + The following program retrieves data from the example table by + selecting each attribute of the type <type>comp_t</type> + separately: +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; +int intval; +varchar textval[33]; +EXEC SQL END DECLARE SECTION; + +/* Put each element of the composite type column in the SELECT list. */ +EXEC SQL DECLARE cur1 CURSOR FOR SELECT (compval).intval, (compval).textval FROM t4; +EXEC SQL OPEN cur1; + +EXEC SQL WHENEVER NOT FOUND DO BREAK; + +while (1) +{ + /* Fetch each element of the composite type column into host variables. */ + EXEC SQL FETCH FROM cur1 INTO :intval, :textval; + + printf("intval=%d, textval=%s\n", intval, textval.arr); +} + +EXEC SQL CLOSE cur1; +</programlisting> + </para> + + <para> + To enhance this example, the host variables to store values in + the <command>FETCH</command> command can be gathered into one + structure. For more details about the host variable in the + structure form, see <xref linkend="ecpg-variables-struct">. + To switch to the structure, the example can be modified as below. + The two host variables, <varname>intval</varname> + and <varname>textval</varname>, become members of + the <structname>comp_t</structname> structure, and the structure + is specified on the <command>FETCH</command> command. +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; +typedef struct +{ + int intval; + varchar textval[33]; +} comp_t; + +comp_t compval; +EXEC SQL END DECLARE SECTION; + +/* Put each element of the composite type column in the SELECT list. */ +EXEC SQL DECLARE cur1 CURSOR FOR SELECT (compval).intval, (compval).textval FROM t4; +EXEC SQL OPEN cur1; + +EXEC SQL WHENEVER NOT FOUND DO BREAK; + +while (1) +{ + /* Put all values in the SELECT list into one structure. */ + EXEC SQL FETCH FROM cur1 INTO :compval; + + printf("intval=%d, textval=%s\n", compval.intval, compval.textval.arr); +} + +EXEC SQL CLOSE cur1; +</programlisting> + + Although a structure is used in the <command>FETCH</command> + command, the attribute names in the <command>SELECT</command> + clause are specified one by one. This can be enhanced by using + a <literal>*</literal> to ask for all attributes of the composite + type value. +<programlisting> +... +EXEC SQL DECLARE cur1 CURSOR FOR SELECT (compval).* FROM t4; +EXEC SQL OPEN cur1; + +EXEC SQL WHENEVER NOT FOUND DO BREAK; + +while (1) +{ + /* Put all values in the SELECT list into one structure. */ + EXEC SQL FETCH FROM cur1 INTO :compval; + + printf("intval=%d, textval=%s\n", compval.intval, compval.textval.arr); +} +... +</programlisting> + This way, composite types can be mapped into structures almost + seamlessly, even though ECPG does not understand the composite + type itself. + </para> + + <para> + Finally, it is also possible to store composite type values in + their external string representation in host variables of + type <type>char[]</type> or <type>VARCHAR[]</type>. But that + way, it is not easily possible to access the fields of the value + from the host program. + </para> + </sect3> + + <sect3> + <title>User-defined Base Types</title> + + <para> + New user-defined base types are not directly supported by ECPG. + You can use the external string representation and host variables + of type <type>char[]</type> or <type>VARCHAR[]</type>, and this + solution is indeed appropriate and sufficient for many types. + </para> + + <para> + Here is an example using the data type <type>complex</type> from + the example in <xref linkend="xtypes">. The external string + representation of that type is <literal>(%lf,%lf)</literal>, + which is defined in the + functions <function>complex_in()</function> + and <function>complex_out()</function> functions + in <xref linkend="xtypes">. The following example inserts the + complex type values <literal>(1,1)</literal> + and <literal>(3,3)</literal> into the + columns <literal>a</literal> and <literal>b</literal>, and select + them from the table after that. + +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; + varchar a[64]; + varchar b[64]; +EXEC SQL END DECLARE SECTION; + + EXEC SQL INSERT INTO test_complex VALUES ('(1,1)', '(3,3)'); + + EXEC SQL DECLARE cur1 CURSOR FOR SELECT a, b FROM test_complex; + EXEC SQL OPEN cur1; + + EXEC SQL WHENEVER NOT FOUND DO BREAK; + + while (1) + { + EXEC SQL FETCH FROM cur1 INTO :a, :b; + printf("a=%s, b=%s\n", a.arr, b.arr); + } + + EXEC SQL CLOSE cur1; +</programlisting> + + This example shows following result: +<screen> +a=(1,1), b=(3,3) +</screen> + </para> + + <para> + Another workaround is avoiding the direct use of the user-defined + types in ECPG and instead create a function or cast that converts + between the user-defined type and a primitive type that ECPG can + handle. Note, however, that type casts, especially implicit + ones, should be introduced into the type system very carefully. + </para> + + <para> + For example, +<programlisting> +CREATE FUNCTION create_complex(r double, i double) RETURNS complex +LANGUAGE SQL +IMMUTABLE +AS $$ SELECT $1 * complex '(1,0')' + $2 * complex '(0,1)' $$; +</programlisting> + After this definition, the following +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; +double a, b, c, d; +EXEC SQL END DECLARE SECTION; + +a = 1; +b = 2; +c = 3; +d = 4; + +EXEC SQL INSERT INTO test_complex VALUES (create_complex(:a, :b), create_complex(:c, :d)); +</programlisting> + has the same effect as +<programlisting> +EXEC SQL INSERT INTO test_complex VALUES ('(1,2)', '(3,4)'); +</programlisting> + </para> + </sect3> + </sect2> + + <sect2 id="ecpg-indicators"> <title>Indicators</title> <para> @@ -668,6 +1745,16 @@ EXEC SQL SELECT b INTO :val :val_ind FROM test1; positive, it means that the value is not null, but it was truncated when it was stored in the host variable. </para> + + <para> + If the argument <literal>-r no_indicator</literal> is passed to + the preprocessor <command>ecpg</command>, it works in + <quote>no-indicator</quote> mode. In no-indicator mode, if no + indicator variable is specified, null values are signaled (on + input and output) for character string types as empty string and + for integer types as the lowest possible value for type (for + example, <symbol>INT_MIN</symbol> for <type>int</type>). + </para> </sect2> </sect1> @@ -684,9 +1771,12 @@ EXEC SQL SELECT b INTO :val :val_ind FROM test1; provide in a string variable. </para> - <para> - The simplest way to execute an arbitrary SQL statement is to use - the command <command>EXECUTE IMMEDIATE</command>. For example: + <sect2 id="ecpg-dynamic-without-result"> + <title>Executing Statements without a Result Set</title> + + <para> + The simplest way to execute an arbitrary SQL statement is to use + the command <command>EXECUTE IMMEDIATE</command>. For example: <programlisting> EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "CREATE TABLE test1 (...);"; @@ -694,18 +1784,26 @@ EXEC SQL END DECLARE SECTION; EXEC SQL EXECUTE IMMEDIATE :stmt; </programlisting> - You cannot execute statements that retrieve data (e.g., - <command>SELECT</command>) this way. - </para> + <command>EXECUTE IMMEDIATE</command> can be used for SQL + statements that do not return a result set (e.g., + DDL, <command>INSERT</command>, <command>UPDATE</command>, + <command>DELETE</command>). You cannot execute statements that + retrieve data (e.g., <command>SELECT</command>) this way. The + next section describes how to do that. + </para> + </sect2> - <para> - A more powerful way to execute arbitrary SQL statements is to - prepare them once and execute the prepared statement as often as - you like. It is also possible to prepare a generalized version of - a statement and then execute specific versions of it by - substituting parameters. When preparing the statement, write - question marks where you want to substitute parameters later. For - example: + <sect2 id="ecpg-dynamic-input"> + <title>Executing a Statement with Input Parameters</title> + + <para> + A more powerful way to execute arbitrary SQL statements is to + prepare them once and execute the prepared statement as often as + you like. It is also possible to prepare a generalized version of + a statement and then execute specific versions of it by + substituting parameters. When preparing the statement, write + question marks where you want to substitute parameters later. For + example: <programlisting> EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "INSERT INTO test1 VALUES(?, ?);"; @@ -715,37 +1813,81 @@ EXEC SQL PREPARE mystmt FROM :stmt; ... EXEC SQL EXECUTE mystmt USING 42, 'foobar'; </programlisting> - If the statement you are executing returns values, then add an - <literal>INTO</literal> clause: + </para> + + <para> + When you don't need the prepared statement anymore, you should + deallocate it: +<programlisting> +EXEC SQL DEALLOCATE PREPARE <replaceable>name</replaceable>; +</programlisting> + </para> + </sect2> + + <sect2 id="ecpg-dynamic-with-result"> + <title>Executing a Statement with a Result Set</title> + + <para> + To execute an SQL statement with a single result row, + <command>EXECUTE</command> can be used. To save the result, add + an <literal>INTO</literal> clause. <programlisting><![CDATA[ EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "SELECT a, b, c FROM test1 WHERE a > ?"; int v1, v2; -VARCHAR v3; +VARCHAR v3[50]; EXEC SQL END DECLARE SECTION; EXEC SQL PREPARE mystmt FROM :stmt; ... -EXEC SQL EXECUTE mystmt INTO v1, v2, v3 USING 37; +EXEC SQL EXECUTE mystmt INTO :v1, :v2, :v3 USING 37; ]]> </programlisting> - An <command>EXECUTE</command> command can have an - <literal>INTO</literal> clause, a <literal>USING</literal> clause, - both, or neither. - </para> + An <command>EXECUTE</command> command can have an + <literal>INTO</literal> clause, a <literal>USING</literal> clause, + both, or neither. + </para> - <para> - When you don't need the prepared statement anymore, you should - deallocate it: + <para> + If a query is expected to return more than one result row, a + cursor should be used, as in the following example. + (See <xref linkend="ecpg-cursors"> for more details about the + cursor.) <programlisting> -EXEC SQL DEALLOCATE PREPARE <replaceable>name</replaceable>; +EXEC SQL BEGIN DECLARE SECTION; +char dbaname[128]; +char datname[128]; +char *stmt = "SELECT u.usename as dbaname, d.datname " + " FROM pg_database d, pg_user u " + " WHERE d.datdba = u.usesysid"; +EXEC SQL END DECLARE SECTION; + +EXEC SQL CONNECT TO testdb AS con1 USER testuser; + +EXEC SQL PREPARE stmt1 FROM :stmt; + +EXEC SQL DECLARE cursor1 CURSOR FOR stmt1; +EXEC SQL OPEN cursor1; + +EXEC SQL WHENEVER NOT FOUND DO BREAK; + +while (1) +{ + EXEC SQL FETCH cursor1 INTO :dbaname,:datname; + printf("dbaname=%s, datname=%s\n", dbaname, datname); +} + +EXEC SQL CLOSE cursor1; + +EXEC SQL COMMIT; +EXEC SQL DISCONNECT ALL; </programlisting> - </para> + </para> + </sect2> </sect1> - <sect1 id="ecpg-pgtypes"> - <title>pgtypes library</title> + <title>pgtypes Library</title> <para> The pgtypes library maps <productname>PostgreSQL</productname> database @@ -771,16 +1913,16 @@ free(out); </programlisting> </para> - <sect2> - <title>The numeric type</title> + <sect2 id="ecpg-pgtypes-numeric"> + <title>The numeric Type</title> <para> The numeric type offers to do calculations with arbitrary precision. See <xref linkend="datatype-numeric"> for the equivalent type in the <productname>PostgreSQL</> server. Because of the arbitrary precision this variable needs to be able to expand and shrink dynamically. That's why you - can only create variables on the heap by means of the + can only create numeric variables on the heap, by means of the <function>PGTYPESnumeric_new</> and <function>PGTYPESnumeric_free</> - functions. The decimal type, which is similar but limited in the precision, + functions. The decimal type, which is similar but limited in precision, can be created on the stack as well as on the heap. </para> <para> @@ -825,7 +1967,7 @@ numeric *PGTYPESnumeric_from_asc(char *str, char **endptr); <literal>592.49E07</literal> or <literal>-32.84e-4</literal>. If the value could be parsed successfully, a valid pointer is returned, - else the NULL pointer. At the moment ecpg always parses the complete + else the NULL pointer. At the moment ECPG always parses the complete string and so it currently does not support to store the address of the first invalid character in <literal>*endptr</literal>. You can safely set <literal>endptr</literal> to NULL. @@ -1094,8 +2236,8 @@ int PGTYPESnumeric_from_decimal(decimal *src, numeric *dst); </para> </sect2> - <sect2> - <title>The date type</title> + <sect2 id="ecpg-pgtypes-date"> + <title>The date Type</title> <para> The date type in C enables your programs to deal with data of the SQL type date. See <xref linkend="datatype-datetime"> for the equivalent type in the @@ -1127,20 +2269,20 @@ date PGTYPESdate_from_timestamp(timestamp dt); date PGTYPESdate_from_asc(char *str, char **endptr); </synopsis> The function receives a C char* string <literal>str</> and a pointer to - a C char* string <literal>endptr</>. At the moment ecpg always parses + a C char* string <literal>endptr</>. At the moment ECPG always parses the complete string and so it currently does not support to store the address of the first invalid character in <literal>*endptr</literal>. You can safely set <literal>endptr</literal> to NULL. </para> <para> Note that the function always assumes MDY-formatted dates and there is - currently no variable to change that within ecpg. + currently no variable to change that within ECPG. </para> <para> <xref linkend="ecpg-pgtypesdate-from-asc-table"> shows the allowed input formats. </para> <table id="ecpg-pgtypesdate-from-asc-table"> - <title>Valid input formats for <function>PGTYPESdate_from_asc</function></title> + <title>Valid Input Formats for <function>PGTYPESdate_from_asc</function></title> <tgroup cols="2"> <thead> <row> @@ -1397,12 +2539,12 @@ int PGTYPESdate_fmt_asc(date dDate, char *fmtstring, char *outbuf); the same date: November 23, 1959. </para> <table id="ecpg-pgtypesdate-fmt-asc-example-table"> - <title>Valid input formats for <function>PGTYPESdate_fmt_asc</function></title> + <title>Valid Input Formats for <function>PGTYPESdate_fmt_asc</function></title> <tgroup cols="2"> <thead> <row> - <entry>fmt</entry> - <entry>result</entry> + <entry>Format</entry> + <entry>Result</entry> </row> </thead> <tbody> @@ -1464,7 +2606,7 @@ int PGTYPESdate_fmt_asc(date dDate, char *fmtstring, char *outbuf); <term><function>PGTYPESdate_defmt_asc</function></term> <listitem> <para> - Use a format mask to convert a C char* string to a value of type + Use a format mask to convert a C <type>char*</type> string to a value of type date. <synopsis> int PGTYPESdate_defmt_asc(date *d, char *fmt, char *str); @@ -1487,13 +2629,13 @@ int PGTYPESdate_defmt_asc(date *d, char *fmt, char *str); you an idea of how to use this function. </para> <table id="ecpg-rdefmtdate-example-table"> - <title>Valid input formats for <function>rdefmtdate</function></title> + <title>Valid Input Formats for <function>rdefmtdate</function></title> <tgroup cols="3"> <thead> <row> - <entry>fmt</entry> - <entry>str</entry> - <entry>result</entry> + <entry>Format</entry> + <entry>String</entry> + <entry>Result</entry> </row> </thead> <tbody> @@ -1570,9 +2712,9 @@ int PGTYPESdate_defmt_asc(date *d, char *fmt, char *str); </variablelist> </para> </sect2> - - <sect2> - <title>The timestamp type</title> + + <sect2 id="ecpg-pgtypes-timestamp"> + <title>The timestamp Type</title> <para> The timestamp type in C enables your programs to deal with data of the SQL type timestamp. See <xref linkend="datatype-datetime"> for the equivalent @@ -1592,21 +2734,20 @@ timestamp PGTYPEStimestamp_from_asc(char *str, char **endptr); </synopsis> The function receives the string to parse (<literal>str</>) and a pointer to a C char* (<literal>endptr</>). - At the moment ecpg always parses + At the moment ECPG always parses the complete string and so it currently does not support to store the address of the first invalid character in <literal>*endptr</literal>. You can safely set <literal>endptr</literal> to NULL. </para> <para> The function returns the parsed timestamp on success. On error, - <literal>PGTYPESInvalidTimestamp</literal> is returned and errno is + <literal>PGTYPESInvalidTimestamp</literal> is returned and <varname>errno</> is set to <literal>PGTYPES_TS_BAD_TIMESTAMP</>. See <xref linkend="PGTYPESInvalidTimestamp"> for important notes on this value. - </para> <para> In general, the input string can contain any combination of an allowed date specification, a whitespace character and an allowed time - specification. Note that timezones are not supported by ecpg. It can + specification. Note that timezones are not supported by ECPG. It can parse them but does not apply any calculation as the <productname>PostgreSQL</> server does for example. Timezone specifiers are silently discarded. @@ -1615,7 +2756,7 @@ timestamp PGTYPEStimestamp_from_asc(char *str, char **endptr); <xref linkend="ecpg-pgtypestimestamp-from-asc-example-table"> contains a few examples for input strings. </para> <table id="ecpg-pgtypestimestamp-from-asc-example-table"> - <title>Valid input formats for <function>PGTYPEStimestamp_from_asc</function></title> + <title>Valid Input Formats for <function>PGTYPEStimestamp_from_asc</function></title> <tgroup cols="2"> <thead> <row> @@ -1697,7 +2838,7 @@ int PGTYPEStimestamp_fmt_asc(timestamp *ts, char *output, int str_len, char *fmt You can use the following format specifiers for the format mask. The format specifiers are the same ones that are used in the <function>strftime</> function in <productname>libc</productname>. Any - non-format specifier will be copied into the output buffer. + non-format specifier will be copied into the output buffer. <!-- This is from the FreeBSD man page: http://www.freebsd.org/cgi/man.cgi?query=strftime&apropos=0&sektion=3&manpath=FreeBSD+7.0-current&format=html --> @@ -1755,24 +2896,24 @@ int PGTYPEStimestamp_fmt_asc(timestamp *ts, char *output, int str_len, char *fmt <literal>%E*</literal> <literal>%O*</literal> - POSIX locale extensions. The sequences <literal>%Ec</literal> - <literal>%EC</literal> - <literal>%Ex</literal> - <literal>%EX</literal> - <literal>%Ey</literal> - <literal>%EY</literal> - <literal>%Od</literal> + <literal>%EC</literal> + <literal>%Ex</literal> + <literal>%EX</literal> + <literal>%Ey</literal> + <literal>%EY</literal> + <literal>%Od</literal> <literal>%Oe</literal> - <literal>%OH</literal> - <literal>%OI</literal> - <literal>%Om</literal> - <literal>%OM</literal> - <literal>%OS</literal> - <literal>%Ou</literal> - <literal>%OU</literal> - <literal>%OV</literal> - <literal>%Ow</literal> - <literal>%OW</literal> - <literal>%Oy</literal> + <literal>%OH</literal> + <literal>%OI</literal> + <literal>%Om</literal> + <literal>%OM</literal> + <literal>%OS</literal> + <literal>%Ou</literal> + <literal>%OU</literal> + <literal>%OV</literal> + <literal>%Ow</literal> + <literal>%OW</literal> + <literal>%Oy</literal> are supposed to provide alternative representations. </para> <para> @@ -1865,7 +3006,7 @@ int PGTYPEStimestamp_fmt_asc(timestamp *ts, char *output, int str_len, char *fmt <listitem> <para> <literal>%p</literal> - is replaced by national representation of - either "ante meridiem" or "post meridiem" as appropriate. + either <quote>ante meridiem</quote> or <quote>post meridiem</quote> as appropriate. </para> </listitem> <listitem> @@ -2101,8 +3242,8 @@ int PGTYPEStimestamp_sub_interval(timestamp *tin, interval *span, timestamp *tou </para> </sect2> - <sect2> - <title>The interval type</title> + <sect2 id="ecpg-pgtypes-interval"> + <title>The interval Type</title> <para> The interval type in C enables your programs to deal with data of the SQL type interval. See <xref linkend="datatype-datetime"> for the equivalent @@ -2146,7 +3287,7 @@ interval *PGTYPESinterval_from_asc(char *str, char **endptr); </synopsis> The function parses the input string <literal>str</> and returns a pointer to an allocated interval variable. - At the moment ecpg always parses + At the moment ECPG always parses the complete string and so it currently does not support to store the address of the first invalid character in <literal>*endptr</literal>. You can safely set <literal>endptr</literal> to NULL. @@ -2188,16 +3329,18 @@ int PGTYPESinterval_copy(interval *intvlsrc, interval *intvldest); </para> </sect2> - <sect2> - <title>The decimal type</title> + <sect2 id="ecpg-pgtypes-decimal"> + <title>The decimal Type</title> <para> The decimal type is similar to the numeric type. However it is limited to - a maximal precision of 30 significant digits. In contrast to the numeric + a maximum precision of 30 significant digits. In contrast to the numeric type which can be created on the heap only, the decimal type can be created either on the stack or on the heap (by means of the functions - PGTYPESdecimal_new() and PGTYPESdecimal_free(). There are a lot of other - functions that deal with the decimal type in the <productname>Informix</productname> compatibility - mode described in <xref linkend="ecpg-informix-compat">. + <function>PGTYPESdecimal_new</> and + <function>PGTYPESdecimal_free</>). + There are a lot of other functions that deal with the decimal type in the + <productname>Informix</productname> compatibility mode described in <xref + linkend="ecpg-informix-compat">. </para> <para> The following functions can be used to work with the decimal type and are @@ -2229,9 +3372,9 @@ void PGTYPESdecimal_free(decimal *var); </variablelist> </para> </sect2> - - <sect2> - <title>errno values of pgtypeslib </title> + + <sect2 id="ecpg-pgtypes-errno"> + <title>errno Values of pgtypeslib</title> <para> <variablelist> <varlistentry> @@ -2279,7 +3422,8 @@ void PGTYPESdecimal_free(decimal *var); <term><literal>PGTYPES_DATE_BAD_DATE</literal></term> <listitem> <para> - + An invalid date string was passed to + the <function>PGTYPESdate_from_asc</function> function. </para> </listitem> </varlistentry> @@ -2288,7 +3432,8 @@ void PGTYPESdecimal_free(decimal *var); <term><literal>PGTYPES_DATE_ERR_EARGS</literal></term> <listitem> <para> - + Invalid arguments were passed to the + <function>PGTYPESdate_defmt_asc</function> function. </para> </listitem> </varlistentry> @@ -2297,7 +3442,8 @@ void PGTYPESdecimal_free(decimal *var); <term><literal>PGTYPES_DATE_ERR_ENOSHORTDATE</literal></term> <listitem> <para> - + An invalid token in the input string was found by the + <function>PGTYPESdate_defmt_asc</function> function. </para> </listitem> </varlistentry> @@ -2306,7 +3452,10 @@ void PGTYPESdecimal_free(decimal *var); <term><literal>PGTYPES_INTVL_BAD_INTERVAL</literal></term> <listitem> <para> - + An invalid interval string was passed to the + <function>PGTYPESinterval_from_asc</function> function, or an + invalid interval value was passed to the + <function>PGTYPESinterval_to_asc</function> function. </para> </listitem> </varlistentry> @@ -2315,7 +3464,8 @@ void PGTYPESdecimal_free(decimal *var); <term><literal>PGTYPES_DATE_ERR_ENOTDMY</literal></term> <listitem> <para> - + There was a mismatch in the day/month/year assignment in the + <function>PGTYPESdate_defmt_asc</function> function. </para> </listitem> </varlistentry> @@ -2324,7 +3474,8 @@ void PGTYPESdecimal_free(decimal *var); <term><literal>PGTYPES_DATE_BAD_DAY</literal></term> <listitem> <para> - + An invalid day of the month value was found by + the <function>PGTYPESdate_defmt_asc</function> function. </para> </listitem> </varlistentry> @@ -2333,7 +3484,8 @@ void PGTYPESdecimal_free(decimal *var); <term><literal>PGTYPES_DATE_BAD_MONTH</literal></term> <listitem> <para> - + An invalid month value was found by + the <function>PGTYPESdate_defmt_asc</function> function. </para> </listitem> </varlistentry> @@ -2342,7 +3494,20 @@ void PGTYPESdecimal_free(decimal *var); <term><literal>PGTYPES_TS_BAD_TIMESTAMP</literal></term> <listitem> <para> - + An invalid timestamp string pass passed to + the <function>PGTYPEStimestamp_from_asc</function> function, + or an invalid timestamp value was passed to + the <function>PGTYPEStimestamp_to_asc</function> function. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>PGTYPES_TS_ERR_EINFTIME</literal></term> + <listitem> + <para> + An infinite timestamp value was encountered in a context that + cannot handle it. </para> </listitem> </varlistentry> @@ -2350,8 +3515,8 @@ void PGTYPESdecimal_free(decimal *var); </para> </sect2> - <sect2> - <title>Special constants of pgtypeslib </title> + <sect2 id="ecpg-pgtypes-constants"> + <title>Special Constants of pgtypeslib</title> <para> <variablelist> <varlistentry id="PGTYPESInvalidTimestamp"> @@ -2361,7 +3526,7 @@ void PGTYPESdecimal_free(decimal *var); A value of type timestamp representing an invalid time stamp. This is returned by the function <function>PGTYPEStimestamp_from_asc</> on parse error. - Note that due to the internal representation of the timestamp datatype, + Note that due to the internal representation of the <type>timestamp</type> data type, <literal>PGTYPESInvalidTimestamp</literal> is also a valid timestamp at the same time. It is set to <literal>1899-12-31 23:59:59</>. In order to detect errors, make sure that your application does not only test @@ -2421,14 +3586,14 @@ EXEC SQL DEALLOCATE DESCRIPTOR <replaceable>identifier</replaceable>; <programlisting> EXEC SQL FETCH NEXT FROM mycursor INTO SQL DESCRIPTOR mydesc; </programlisting> - If the resultset is empty, the Descriptor Area will still contain + If the result set is empty, the Descriptor Area will still contain the metadata from the query, i.e. the field names. </para> <para> For not yet executed prepared queries, the <command>DESCRIBE</command> - statement can be used to get the metadata of the resultset: -<programlisting> + statement can be used to get the metadata of the result set: +<programlisting> EXEC SQL BEGIN DECLARE SECTION; char *sql_stmt = "SELECT * FROM table1"; EXEC SQL END DECLARE SECTION; @@ -2443,13 +3608,13 @@ EXEC SQL DESCRIBE stmt1 INTO SQL DESCRIPTOR mydesc; so using <literal>DESCRIPTOR</literal> and <literal>SQL DESCRIPTOR</literal> produced named SQL Descriptor Areas. Now it is mandatory, omitting the <literal>SQL</literal> keyword produces SQLDA Descriptor Areas, - see <xref linkend="ecpg-sqlda-descriptors">. + see <xref linkend="ecpg-sqlda-descriptors">. </para> <para> In <command>DESCRIBE</command> and <command>FETCH</command> statements, the <literal>INTO</literal> and <literal>USING</literal> keywords can be - used to similarly: they produce the resultset and the metadata in a + used to similarly: they produce the result set and the metadata in a Descriptor Area. </para> @@ -2497,7 +3662,13 @@ EXEC SQL GET DESCRIPTOR <replaceable>name</replaceable> VALUE <replaceable>num</ <term><literal>DATETIME_INTERVAL_CODE</literal> (integer)</term> <listitem> <para> - ? + When <literal>TYPE</literal> is <literal>9</literal>, + <literal>DATETIME_INTERVAL_CODE</literal> will have a value of + <literal>1</literal> for <literal>DATE</literal>, + <literal>2</literal> for <literal>TIME</literal>, + <literal>3</literal> for <literal>TIMESTAMP</literal>, + <literal>4</literal> for <literal>TIME WITH TIME ZONE</literal>, or + <literal>5</literal> for <literal>TIMESTAMP WITH TIME ZONE</literal>. </para> </listitem> </varlistentry> @@ -2648,8 +3819,8 @@ EXEC SQL GET DESCRIPTOR mydesc VALUE 1 :id = DATA; <para> An SQLDA Descriptor Area is a C language structure which can be also used - to get the resultset and the metadata of a query. One structure stores one - record from the resultset. + to get the result set and the metadata of a query. One structure stores one + record from the result set. <programlisting> EXEC SQL include sqlda.h; sqlda_t *mysqlda; @@ -2666,56 +3837,80 @@ EXEC SQL DESCRIBE prepared_statement INTO mysqlda; </programlisting> </para> - <para> - The structure of SQLDA is: -<programlisting> -#define NAMEDATALEN 64 + <procedure> + <para> + The general flow of a program that uses SQLDA is: + </para> + <step><simpara>Prepare a query, and declare a cursor for it.</simpara></step> + <step><simpara>Declare an SQLDA for the result rows.</simpara></step> + <step><simpara>Declare an SQLDA for the input parameters, and initialize them (memory allocation, parameter settings).</simpara></step> + <step><simpara>Open a cursor with the input SQLDA.</simpara></step> + <step><simpara>Fetch rows from the cursor, and store them into an output SQLDA.</simpara></step> + <step><simpara>Read values from the output SQLDA into the host variables (with conversion if necessary).</simpara></step> + <step><simpara>Close the cursor.</simpara></step> + <step><simpara>Free the memory area allocated for the input SQLDA.</simpara></step> + </procedure> + + <sect3> + <title>SQLDA Data Structure</title> -struct sqlname -{ - short length; - char data[NAMEDATALEN]; -}; + <para> + SQLDA uses three data structure + types: <type>sqlda_t</type>, <type>sqlvar_t</type>, + and <type>struct sqlname</type>. + </para> -struct sqlvar_struct -{ - short sqltype; - short sqllen; - char *sqldata; - short *sqlind; - struct sqlname sqlname; -}; + <tip> + <para> + PostgreSQL's SQLDA has a similar data structure to the one in + IBM DB2 Universal Database, so some technical information on + DB2's SQLDA could help understanding PostgreSQL's one better. + </para> + </tip> + + <sect4 id="ecpg-sqlda-sqlda"> + <title>sqlda_t Structure</title> + + <para> + The structure type <type>sqlda_t</type> is the type of the + actual SQLDA. It holds one record. And two or + more <type>sqlda_t</type> structures can be connected in a + linked list with the pointer in + the <structfield>desc_next</structfield> field, thus + representing an ordered collection of rows. So, when two or + more rows are fetched, the application can read them by + following the <structfield>desc_next</structfield> pointer in + each <type>sqlda_t</type> node. + </para> + <para> + The definition of <type>sqlda_t</type> is: +<programlisting> struct sqlda_struct { - char sqldaid[8]; - long sqldabc; - short sqln; - short sqld; - struct sqlda_struct *desc_next; - struct sqlvar_struct sqlvar[1]; + char sqldaid[8]; + long sqldabc; + short sqln; + short sqld; + struct sqlda_struct *desc_next; + struct sqlvar_struct sqlvar[1]; }; -typedef struct sqlvar_struct sqlvar_t; -typedef struct sqlda_struct sqlda_t; +typedef struct sqlda_struct sqlda_t; </programlisting> - </para> - <para> - The allocated data for an SQLDA structure is variable as it depends on the - number of fields in a resultset and also depends on the length of the string - data values in a record. The individual fields of the <literal>SQLDA</literal> - structure are: + The meaning of the fields is: <variablelist> <varlistentry> <term><literal>sqldaid</></term> <listitem> <para> - It contains the "<literal>SQLDA </literal>" literal string. + It contains the literal string <literal>"SQLDA "</literal>. </para> </listitem> </varlistentry> + <varlistentry> <term><literal>sqldabc</></term> <listitem> @@ -2724,6 +3919,7 @@ typedef struct sqlda_struct sqlda_t; </para> </listitem> </varlistentry> + <varlistentry> <term><literal>sqln</></term> <listitem> @@ -2738,20 +3934,23 @@ typedef struct sqlda_struct sqlda_t; </para> </listitem> </varlistentry> + <varlistentry> <term><literal>sqld</></term> <listitem> <para> - It contains the number of fields in a resultset. + It contains the number of fields in a result set. </para> </listitem> </varlistentry> + <varlistentry> <term><literal>desc_next</></term> <listitem> <para> - If the query returns more than one records, multiple linked SQLDA structures - are returned, the first record is stored in the SQLDA returned in the + If the query returns more than one record, multiple linked + SQLDA structures are returned, and <literal>desc_next</> holds + a pointer to the next entry in the list. </para> </listitem> </varlistentry> @@ -2759,15 +3958,43 @@ typedef struct sqlda_struct sqlda_t; <term><literal>sqlvar</></term> <listitem> <para> - This is the array of the fields in the resultset. The fields are: + This is the array of the columns in the result set. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </sect4> - <variablelist> + <sect4 id="ecpg-sqlda-sqlvar"> + <title>sqlvar_t Structure</title> + + <para> + The structure type <type>sqlvar_t</type> holds a column value + and metadata such as type and length. The definition of the type + is: + +<programlisting> +struct sqlvar_struct +{ + short sqltype; + short sqllen; + char *sqldata; + short *sqlind; + struct sqlname sqlname; +}; + +typedef struct sqlvar_struct sqlvar_t; +</programlisting> + + The meaning of the fields is: + <variablelist> <varlistentry> <term><literal>sqltype</></term> <listitem> <para> - It contains the type identifier of the field. For values, + Contains the type identifier of the field. For values, see <literal>enum ECPGttype</literal> in <literal>ecpgtype.h</literal>. </para> </listitem> @@ -2777,7 +4004,7 @@ typedef struct sqlda_struct sqlda_t; <term><literal>sqllen</></term> <listitem> <para> - It contains the binary length of the field. E.g. 4 bytes for ECPGt_int. + Contains the binary length of the field. e.g. 4 bytes for <type>ECPGt_int</type>. </para> </listitem> </varlistentry> @@ -2786,7 +4013,8 @@ typedef struct sqlda_struct sqlda_t; <term><literal>sqldata</></term> <listitem> <para> - <literal>(char *)sqldata</literal> points to the data. + Points to the data. The format of the data is described + in <xref linkend="ecpg-variables-type-mapping">. </para> </listitem> </varlistentry> @@ -2795,8 +4023,8 @@ typedef struct sqlda_struct sqlda_t; <term><literal>sqlind</></term> <listitem> <para> - <literal>(char *)sqlind</literal> points to the NULL indicator for data. - 0 means NOT NULL, -1 means NULL. + Points to the null indicator. 0 means not null, -1 means + null. </para> </listitem> </varlistentry> @@ -2805,22 +4033,37 @@ typedef struct sqlda_struct sqlda_t; <term><literal>sqlname</></term> <listitem> <para> - <literal>struct sqlname sqlname</literal> contains the name of the field - in a structure: + The the name of the field. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </sect4> + + <sect4 id="ecpg-sqlda-sqlname"> + <title>struct sqlname Structure</title> + + <para> + A <type>struct sqlname</type> structure holds a column name. It + is used as a member of the <type>sqlvar_t</type> structure. The + definition of the structure is: <programlisting> +#define NAMEDATALEN 64 + struct sqlname { short length; char data[NAMEDATALEN]; }; </programlisting> - + The meaning of the fields is: <variablelist> <varlistentry> <term><literal>length</></term> <listitem> <para> - <literal>sqlname.length</literal> contains the length of the field name. + Contains the length of the field name. </para> </listitem> </varlistentry> @@ -2828,57 +4071,3796 @@ struct sqlname <term><literal>data</></term> <listitem> <para> - <literal>sqlname.data</literal> contains the actual field name. + Contains the actual field name. </para> </listitem> </varlistentry> </variablelist> + </para> + </sect4> + </sect3> + + <sect3 id="ecpg-sqlda-output"> + <title>Retrieving a Result Set Using an SQLDA</title> + + <procedure> + <para> + The general steps to retrieve a query result set through an + SQLDA are: + </para> + <step><simpara>Declare an <type>sqlda_t</type> structure to receive the result set.</simpara></step> + <step><simpara>Execute <command>FETCH</>/<command>EXECUTE</>/<command>DESCRIBE</> commands to process a query specifying the declared SQLDA.</simpara></step> + <step><simpara>Check the number of records in the result set by looking at <structfield>sqln</>, a member of the <type>sqlda_t</type> structure.</simpara></step> + <step><simpara>Get the values of each column from <literal>sqlvar[0]</>, <literal>sqlvar[1]</>, etc., members of the <type>sqlda_t</type> structure.</simpara></step> + <step><simpara>Go to next row (<type>sqlda_t</type> structure) by following the <structfield>desc_next</> pointer, a member of the <type>sqlda_t</type> structure.</simpara></step> + <step><simpara>Repeat above as you need.</simpara></step> + </procedure> + + <para> + Here is an example retrieving a result set through an SQLDA. + </para> + + <para> + First, declare a <type>sqlda_t</type> structure to receive the result set. +<programlisting> +sqlda_t *sqlda1; +</programlisting> + </para> + + <para> + Next, specify the SQLDA in a command. This is + a <command>FETCH</> command example. +<programlisting> +EXEC SQL FETCH NEXT FROM cur1 INTO DESCRIPTOR sqlda1; +</programlisting> + </para> + + <para> + Run a loop following the linked list to retrieve the rows. +<programlisting> +sqlda_t *cur_sqlda; + +for (cur_sqlda = sqlda1; + cur_sqlda != NULL; + cur_sqlda = cur_sqlda->desc_next) +{ + ... +} +</programlisting> + </para> + + <para> + Inside the loop, run another loop to retrieve each column data + (<type>sqlvar_t</type> structure) of the row. +<programlisting> +for (i = 0; i < cur_sqlda->sqld; i++) +{ + sqlvar_t v = cur_sqlda->sqlvar[i]; + char *sqldata = v.sqldata; + short sqllen = v.sqllen; + ... +} +</programlisting> + </para> + + <para> + To get a column value, check the <structfield>sqltype</> value, + a member of the <type>sqlvar_t</type> structure. Then, switch + to an appropriate way, depending on the column type, to copy + data from the <structfield>sqlvar</> field to a host variable. +<programlisting> +char var_buf[1024]; + +switch (v.sqltype) +{ + case ECPGt_char: + memset(&var_buf, 0, sizeof(var_buf)); + memcpy(&var_buf, sqldata, (sizeof(var_buf) <= sqllen ? sizeof(var_buf) - 1 : sqllen)); + break; + + case ECPGt_int: /* integer */ + memcpy(&intval, sqldata, sqllen); + snprintf(var_buf, sizeof(var_buf), "%d", intval); + break; + + ... +} +</programlisting> + </para> + </sect3> + + <sect3 id="ecpg-sqlda-input"> + <title>Passing Query Parameters Using an SQLDA</title> + + <procedure> + <para> + The general steps to use an SQLDA to pass input + parameters to a prepared query are: + </para> + <step><simpara>Create a prepared query (prepared statement)</simpara></step> + <step><simpara>Declare a sqlda_t structure as an input SQLDA.</simpara></step> + <step><simpara>Allocate memory area (as sqlda_t structure) for the input SQLDA.</simpara></step> + <step><simpara>Set (copy) input values in the allocated memory.</simpara></step> + <step><simpara>Open a cursor with specifying the input SQLDA.</simpara></step> + </procedure> + + <para> + Here is an example. + </para> + + <para> + First, create a prepared statement. +<programlisting> +EXEC SQL BEGIN DECLARE SECTION; +char query[1024] = "SELECT d.oid, * FROM pg_database d, pg_stat_database s WHERE d.oid = s.datid AND (d.datname = ? OR d.oid = ?)"; +EXEC SQL END DECLARE SECTION; + +EXEC SQL PREPARE stmt1 FROM :query; +</programlisting> + </para> + + <para> + Next, allocate memory for an SQLDA, and set the number of input + parameters in <structfield>sqln</>, a member variable of + the <type>sqlda_t</type> structure. When two or more input + parameters are required for the prepared query, the application + has to allocate additional memory space which is calculated by + (nr. of params - 1) * sizeof(sqlvar_t). The example shown here + allocates memory space for two input parameters. +<programlisting> +sqlda_t *sqlda2; + +sqlda2 = (sqlda_t *) malloc(sizeof(sqlda_t) + sizeof(sqlvar_t)); +memset(sqlda2, 0, sizeof(sqlda_t) + sizeof(sqlvar_t)); + +sqlda2->sqln = 2; /* number of input variables */ +</programlisting> + </para> + + <para> + After memory allocation, store the parameter values into the + <literal>sqlvar[]</literal> array. (This is same array used for + retrieving column values when the SQLDA is receiving a result + set.) In this example, the input parameters + are <literal>"postgres"</literal>, having a string type, + and <literal>1</literal>, having an integer type. +<programlisting> +sqlda2->sqlvar[0].sqltype = ECPGt_char; +sqlda2->sqlvar[0].sqldata = "postgres"; +sqlda2->sqlvar[0].sqllen = 8; + +int intval = 1; +sqlda2->sqlvar[1].sqltype = ECPGt_int; +sqlda2->sqlvar[1].sqldata = (char *) &intval; +sqlda2->sqlvar[1].sqllen = sizeof(intval); +</programlisting> + </para> + + <para> + By opening a cursor and specifying the SQLDA that was set up + beforehand, the input parameters are passed to the prepared + statement. +<programlisting> +EXEC SQL OPEN cur1 USING DESCRIPTOR sqlda2; +</programlisting> + </para> + + <para> + Finally, after using input SQLDAs, the allocated memory space + must be freed explicitly, unlike SQLDAs used for receiving query + results. +<programlisting> +free(sqlda2); +</programlisting> + </para> + </sect3> + + <sect3 id="ecpg-sqlda-example"> + <title>A Sample Application Using SQLDA</title> + + <para> + Here is an example program, which describes how to fetch access + statistics of the databases, specified by the input parameters, + from the system catalogs. + </para> + + <para> + This application joins two system tables, pg_database and + pg_stat_database on the database OID, and also fetches and shows + the database statistics which are retrieved by two input + parameters (a database <literal>postgres</literal>, and OID <literal>1</literal>). + </para> + + <para> + First, declare an SQLDA for input and an SQLDA for output. +<programlisting> +EXEC SQL include sqlda.h; + +sqlda_t *sqlda1; /* an output descriptor */ +sqlda_t *sqlda2; /* an input descriptor */ +</programlisting> + </para> + + <para> + Next, connect to the database, prepare a statement, and declare a + cursor for the prepared statement. +<programlisting> +int +main(void) +{ + EXEC SQL BEGIN DECLARE SECTION; + char query[1024] = "SELECT d.oid,* FROM pg_database d, pg_stat_database s WHERE d.oid=s.datid AND ( d.datname=? OR d.oid=? )"; + EXEC SQL END DECLARE SECTION; + + EXEC SQL CONNECT TO testdb AS con1 USER testuser; + + EXEC SQL PREPARE stmt1 FROM :query; + EXEC SQL DECLARE cur1 CURSOR FOR stmt1; +</programlisting> + </para> + + <para> + Next, put some values in the input SQLDA for the input + parameters. Allocate memory for the input SQLDA, and set the + number of input parameters to <literal>sqln</literal>. Store + type, value, and value length into <literal>sqltype</literal>, + <literal>sqldata</literal>, and <literal>sqllen</literal> in the + <literal>sqlvar</literal> structure. + +<programlisting> + /* Create SQLDA structure for input parameters. */ + sqlda2 = (sqlda_t *) malloc(sizeof(sqlda_t) + sizeof(sqlvar_t)); + memset(sqlda2, 0, sizeof(sqlda_t) + sizeof(sqlvar_t)); + sqlda2->sqln = 2; /* number of input variables */ + + sqlda2->sqlvar[0].sqltype = ECPGt_char; + sqlda2->sqlvar[0].sqldata = "postgres"; + sqlda2->sqlvar[0].sqllen = 8; + + intval = 1; + sqlda2->sqlvar[1].sqltype = ECPGt_int; + sqlda2->sqlvar[1].sqldata = (char *)&intval; + sqlda2->sqlvar[1].sqllen = sizeof(intval); +</programlisting> + </para> + + <para> + After setting up the input SQLDA, open a cursor with the input + SQLDA. + +<programlisting> + /* Open a cursor with input parameters. */ + EXEC SQL OPEN cur1 USING DESCRIPTOR sqlda2; +</programlisting> + </para> + + <para> + Fetch rows into the output SQLDA from the opened cursor. + (Generally, you have to call <command>FETCH</command> repeatedly + in the loop, to fetch all rows in the result set.) +<programlisting> + while (1) + { + sqlda_t *cur_sqlda; + + /* Assign descriptor to the cursor */ + EXEC SQL FETCH NEXT FROM cur1 INTO DESCRIPTOR sqlda1; +</programlisting> + </para> + + <para> + Next, retrieve the fetched records from the SQLDA, by following + the linked list of the <type>sqlda_t</type> structure. +<programlisting> + for (cur_sqlda = sqlda1 ; + cur_sqlda != NULL ; + cur_sqlda = cur_sqlda->desc_next) + { + ... +</programlisting> + </para> + + <para> + Read each columns in the first record. The number of columns is + stored in <structfield>sqld</>, the actual data of the first + column is stored in <literal>sqlvar[0]</>, both members of + the <type>sqlda_t</type> structure. + +<programlisting> + /* Print every column in a row. */ + for (i = 0; i < sqlda1->sqld; i++) + { + sqlvar_t v = sqlda1->sqlvar[i]; + char *sqldata = v.sqldata; + short sqllen = v.sqllen; + + strncpy(name_buf, v.sqlname.data, v.sqlname.length); + name_buf[v.sqlname.length] = '\0'; +</programlisting> + </para> + + <para> + Now, the column data is stored in the variable <varname>v</>. + Copy every datum into host variables, looking + at <literal>v.sqltype</> for the type of the column. +<programlisting> + switch (v.sqltype) { + int intval; + double doubleval; + unsigned long long int longlongval; + + case ECPGt_char: + memset(&var_buf, 0, sizeof(var_buf)); + memcpy(&var_buf, sqldata, (sizeof(var_buf) <= sqllen ? sizeof(var_buf)-1 : sqllen)); + break; + + case ECPGt_int: /* integer */ + memcpy(&intval, sqldata, sqllen); + snprintf(var_buf, sizeof(var_buf), "%d", intval); + break; + + ... + + default: + ... + } + + printf("%s = %s (type: %d)\n", name_buf, var_buf, v.sqltype); + } +</programlisting> + </para> + + <para> + Close the cursor after processing all of records, and disconnect + from the database. +<programlisting> + EXEC SQL CLOSE cur1; + EXEC SQL COMMIT; + + EXEC SQL DISCONNECT ALL; +</programlisting> + </para> + + <para> + The whole program is shown + in <xref linkend="ecpg-sqlda-example-example">. + </para> + + <example id="ecpg-sqlda-example-example"> + <title>Example SQLDA Program</title> +<programlisting> +#include <stdlib.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +EXEC SQL include sqlda.h; + +sqlda_t *sqlda1; /* descriptor for output */ +sqlda_t *sqlda2; /* descriptor for input */ + +EXEC SQL WHENEVER NOT FOUND DO BREAK; +EXEC SQL WHENEVER SQLERROR STOP; + +int +main(void) +{ + EXEC SQL BEGIN DECLARE SECTION; + char query[1024] = "SELECT d.oid,* FROM pg_database d, pg_stat_database s WHERE d.oid=s.datid AND ( d.datname=? OR d.oid=? )"; + + int intval; + unsigned long long int longlongval; + EXEC SQL END DECLARE SECTION; + + EXEC SQL CONNECT TO uptimedb AS con1 USER uptime; + + EXEC SQL PREPARE stmt1 FROM :query; + EXEC SQL DECLARE cur1 CURSOR FOR stmt1; + + /* Create a SQLDA structure for an input parameter */ + sqlda2 = (sqlda_t *)malloc(sizeof(sqlda_t) + sizeof(sqlvar_t)); + memset(sqlda2, 0, sizeof(sqlda_t) + sizeof(sqlvar_t)); + sqlda2->sqln = 2; /* a number of input variables */ + + sqlda2->sqlvar[0].sqltype = ECPGt_char; + sqlda2->sqlvar[0].sqldata = "postgres"; + sqlda2->sqlvar[0].sqllen = 8; + + intval = 1; + sqlda2->sqlvar[1].sqltype = ECPGt_int; + sqlda2->sqlvar[1].sqldata = (char *) &intval; + sqlda2->sqlvar[1].sqllen = sizeof(intval); + + /* Open a cursor with input parameters. */ + EXEC SQL OPEN cur1 USING DESCRIPTOR sqlda2; + + while (1) + { + sqlda_t *cur_sqlda; + + /* Assign descriptor to the cursor */ + EXEC SQL FETCH NEXT FROM cur1 INTO DESCRIPTOR sqlda1; + + for (cur_sqlda = sqlda1 ; + cur_sqlda != NULL ; + cur_sqlda = cur_sqlda->desc_next) + { + int i; + char name_buf[1024]; + char var_buf[1024]; + + /* Print every column in a row. */ + for (i=0 ; i<cur_sqlda->sqld ; i++) + { + sqlvar_t v = cur_sqlda->sqlvar[i]; + char *sqldata = v.sqldata; + short sqllen = v.sqllen; + + strncpy(name_buf, v.sqlname.data, v.sqlname.length); + name_buf[v.sqlname.length] = '\0'; + + switch (v.sqltype) + { + case ECPGt_char: + memset(&var_buf, 0, sizeof(var_buf)); + memcpy(&var_buf, sqldata, (sizeof(var_buf)<=sqllen ? sizeof(var_buf)-1 : sqllen) ); + break; + + case ECPGt_int: /* integer */ + memcpy(&intval, sqldata, sqllen); + snprintf(var_buf, sizeof(var_buf), "%d", intval); + break; + + case ECPGt_long_long: /* bigint */ + memcpy(&longlongval, sqldata, sqllen); + snprintf(var_buf, sizeof(var_buf), "%lld", longlongval); + break; + + default: + { + int i; + memset(var_buf, 0, sizeof(var_buf)); + for (i = 0; i < sqllen; i++) + { + char tmpbuf[16]; + snprintf(tmpbuf, sizeof(tmpbuf), "%02x ", (unsigned char) sqldata[i]); + strncat(var_buf, tmpbuf, sizeof(var_buf)); + } + } + break; + } + + printf("%s = %s (type: %d)\n", name_buf, var_buf, v.sqltype); + } + + printf("\n"); + } + } + + EXEC SQL CLOSE cur1; + EXEC SQL COMMIT; + + EXEC SQL DISCONNECT ALL; + + return 0; +} +</programlisting> + + <para> + The output of this example should look something like the + following (some numbers will vary). + </para> + +<screen> +oid = 1 (type: 1) +datname = template1 (type: 1) +datdba = 10 (type: 1) +encoding = 0 (type: 5) +datistemplate = t (type: 1) +datallowconn = t (type: 1) +datconnlimit = -1 (type: 5) +datlastsysoid = 11510 (type: 1) +datfrozenxid = 379 (type: 1) +dattablespace = 1663 (type: 1) +datconfig = (type: 1) +datacl = {=c/uptime,uptime=CTc/uptime} (type: 1) +datid = 1 (type: 1) +datname = template1 (type: 1) +numbackends = 0 (type: 5) +xact_commit = 113606 (type: 9) +xact_rollback = 0 (type: 9) +blks_read = 130 (type: 9) +blks_hit = 7341714 (type: 9) +tup_returned = 38262679 (type: 9) +tup_fetched = 1836281 (type: 9) +tup_inserted = 0 (type: 9) +tup_updated = 0 (type: 9) +tup_deleted = 0 (type: 9) + +oid = 11511 (type: 1) +datname = postgres (type: 1) +datdba = 10 (type: 1) +encoding = 0 (type: 5) +datistemplate = f (type: 1) +datallowconn = t (type: 1) +datconnlimit = -1 (type: 5) +datlastsysoid = 11510 (type: 1) +datfrozenxid = 379 (type: 1) +dattablespace = 1663 (type: 1) +datconfig = (type: 1) +datacl = (type: 1) +datid = 11511 (type: 1) +datname = postgres (type: 1) +numbackends = 0 (type: 5) +xact_commit = 221069 (type: 9) +xact_rollback = 18 (type: 9) +blks_read = 1176 (type: 9) +blks_hit = 13943750 (type: 9) +tup_returned = 77410091 (type: 9) +tup_fetched = 3253694 (type: 9) +tup_inserted = 0 (type: 9) +tup_updated = 0 (type: 9) +tup_deleted = 0 (type: 9) +</screen> + </example> + </sect3> + </sect2> + </sect1> + + <sect1 id="ecpg-errors"> + <title>Error Handling</title> + + <para> + This section describes how you can handle exceptional conditions + and warnings in an embedded SQL program. There are two + nonexclusive facilities for this. + + <itemizedlist> + <listitem> + <simpara> + Callbacks can be configured to handle warning and error + conditions using the <literal>WHENEVER</literal> command. + </simpara> + </listitem> + + <listitem> + <simpara> + Detailed information about the error or warning can be obtained + from the <varname>sqlca</varname> variable. + </simpara> + </listitem> + </itemizedlist> + </para> + + <sect2 id="ecpg-whenever"> + <title>Setting Callbacks</title> + + <para> + One simple method to catch errors and warnings is to set a + specific action to be executed whenever a particular condition + occurs. In general: +<programlisting> +EXEC SQL WHENEVER <replaceable>condition</replaceable> <replaceable>action</replaceable>; +</programlisting> + </para> + + <para> + <replaceable>condition</replaceable> can be one of the following: + + <variablelist> + <varlistentry> + <term><literal>SQLERROR</literal></term> + <listitem> + <para> + The specified action is called whenever an error occurs during + the execution of an SQL statement. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>SQLWARNING</literal></term> + <listitem> + <para> + The specified action is called whenever a warning occurs + during the execution of an SQL statement. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>NOT FOUND</literal></term> + <listitem> + <para> + The specified action is called whenever an SQL statement + retrieves or affects zero rows. (This condition is not an + error, but you might be interested in handling it specially.) + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <para> + <replaceable>action</replaceable> can be one of the following: + + <variablelist> + <varlistentry> + <term><literal>CONTINUE</literal></term> + <listitem> + <para> + This effectively means that the condition is ignored. This is + the default. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>GOTO <replaceable>label</replaceable></literal></term> + <term><literal>GO TO <replaceable>label</replaceable></literal></term> + <listitem> + <para> + Jump to the specified label (using a C <literal>goto</literal> + statement). + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>SQLPRINT</literal></term> + <listitem> + <para> + Print a message to standard error. This is useful for simple + programs or during prototyping. The details of the message + cannot be configured. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>STOP</literal></term> + <listitem> + <para> + Call <literal>exit(1)</literal>, which will terminate the + program. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>DO BREAK</literal></term> + <listitem> + <para> + Execute the C statement <literal>break</literal>. This should + only be used in loops or <literal>switch</literal> statements. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>CALL <replaceable>name</replaceable> (<replaceable>args</replaceable>)</literal></term> + <term><literal>DO <replaceable>name</replaceable> (<replaceable>args</replaceable>)</literal></term> + <listitem> + <para> + Call the specified C functions with the specified arguments. + </para> + </listitem> + </varlistentry> + </variablelist> + + The SQL standard only provides for the actions + <literal>CONTINUE</literal> and <literal>GOTO</literal> (and + <literal>GO TO</literal>). + </para> + + <para> + Here is an example that you might want to use in a simple program. + It prints a simple message when a warning occurs and aborts the + program when an error happens: +<programlisting> +EXEC SQL WHENEVER SQLWARNING SQLPRINT; +EXEC SQL WHENEVER SQLERROR STOP; +</programlisting> + </para> + + <para> + The statement <literal>EXEC SQL WHENEVER</literal> is a directive + of the SQL preprocessor, not a C statement. The error or warning + actions that it sets apply to all embedded SQL statements that + appear below the point where the handler is set, unless a + different action was set for the same condition between the first + <literal>EXEC SQL WHENEVER</literal> and the SQL statement causing + the condition, regardless of the flow of control in the C program. + So neither of the two following C program excerpts will have the + desired effect: +<programlisting> +/* + * WRONG + */ +int main(int argc, char *argv[]) +{ + ... + if (verbose) { + EXEC SQL WHENEVER SQLWARNING SQLPRINT; + } + ... + EXEC SQL SELECT ...; + ... +} +</programlisting> + +<programlisting> +/* + * WRONG + */ +int main(int argc, char *argv[]) +{ + ... + set_error_handler(); + ... + EXEC SQL SELECT ...; + ... +} + +static void set_error_handler(void) +{ + EXEC SQL WHENEVER SQLERROR STOP; +} +</programlisting> + </para> + </sect2> + + <sect2 id="ecpg-sqlca"> + <title>sqlca</title> + + <para> + For more powerful error handling, the embedded SQL interface + provides a global variable with the name <varname>sqlca</varname> + (SQL communication area) + that has the following structure: +<programlisting> +struct +{ + char sqlcaid[8]; + long sqlabc; + long sqlcode; + struct + { + int sqlerrml; + char sqlerrmc[SQLERRMC_LEN]; + } sqlerrm; + char sqlerrp[8]; + long sqlerrd[6]; + char sqlwarn[8]; + char sqlstate[5]; +} sqlca; +</programlisting> + (In a multithreaded program, every thread automatically gets its + own copy of <varname>sqlca</varname>. This works similarly to the + handling of the standard C global variable + <varname>errno</varname>.) + </para> + + <para> + <varname>sqlca</varname> covers both warnings and errors. If + multiple warnings or errors occur during the execution of a + statement, then <varname>sqlca</varname> will only contain + information about the last one. + </para> + + <para> + If no error occurred in the last <acronym>SQL</acronym> statement, + <literal>sqlca.sqlcode</literal> will be 0 and + <literal>sqlca.sqlstate</literal> will be + <literal>"00000"</literal>. If a warning or error occurred, then + <literal>sqlca.sqlcode</literal> will be negative and + <literal>sqlca.sqlstate</literal> will be different from + <literal>"00000"</literal>. A positive + <literal>sqlca.sqlcode</literal> indicates a harmless condition, + such as that the last query returned zero rows. + <literal>sqlcode</literal> and <literal>sqlstate</literal> are two + different error code schemes; details appear below. + </para> + + <para> + If the last SQL statement was successful, then + <literal>sqlca.sqlerrd[1]</literal> contains the OID of the + processed row, if applicable, and + <literal>sqlca.sqlerrd[2]</literal> contains the number of + processed or returned rows, if applicable to the command. + </para> + + <para> + In case of an error or warning, + <literal>sqlca.sqlerrm.sqlerrmc</literal> will contain a string + that describes the error. The field + <literal>sqlca.sqlerrm.sqlerrml</literal> contains the length of + the error message that is stored in + <literal>sqlca.sqlerrm.sqlerrmc</literal> (the result of + <function>strlen()</function>, not really interesting for a C + programmer). Note that some messages are too long to fit in the + fixed-size <literal>sqlerrmc</literal> array; they will be truncated. + </para> + + <para> + In case of a warning, <literal>sqlca.sqlwarn[2]</literal> is set + to <literal>W</literal>. (In all other cases, it is set to + something different from <literal>W</literal>.) If + <literal>sqlca.sqlwarn[1]</literal> is set to + <literal>W</literal>, then a value was truncated when it was + stored in a host variable. <literal>sqlca.sqlwarn[0]</literal> is + set to <literal>W</literal> if any of the other elements are set + to indicate a warning. + </para> + + <para> + The fields <structfield>sqlcaid</structfield>, + <structfield>sqlcabc</structfield>, + <structfield>sqlerrp</structfield>, and the remaining elements of + <structfield>sqlerrd</structfield> and + <structfield>sqlwarn</structfield> currently contain no useful + information. + </para> + + <para> + The structure <varname>sqlca</varname> is not defined in the SQL + standard, but is implemented in several other SQL database + systems. The definitions are similar at the core, but if you want + to write portable applications, then you should investigate the + different implementations carefully. + </para> + + <para> + Here is one example that combines the use of <literal>WHENEVER</> + and <varname>sqlca</varname>, printing out the contents + of <varname>sqlca</varname> when an error occurs. This is perhaps + useful for debugging or prototyping applications, before + installing a more <quote>user-friendly</quote> error handler. + +<programlisting> +EXEC SQL WHENEVER SQLERROR CALL print_sqlca(); + +void +print_sqlca() +{ + fprintf(stderr, "==== sqlca ====\n"); + fprintf(stderr, "sqlcode: %ld\n", sqlca.sqlcode); + fprintf(stderr, "sqlerrm.sqlerrml: %d\n", sqlca.sqlerrm.sqlerrml); + fprintf(stderr, "sqlerrm.sqlerrmc: %s\n", sqlca.sqlerrm.sqlerrmc); + fprintf(stderr, "sqlerrd: %ld %ld %ld %ld %ld %ld\n", sqlca.sqlerrd[0],sqlca.sqlerrd[1],sqlca.sqlerrd[2], + sqlca.sqlerrd[3],sqlca.sqlerrd[4],sqlca.sqlerrd[5]); + fprintf(stderr, "sqlwarn: %d %d %d %d %d %d %d %d\n", sqlca.sqlwarn[0], sqlca.sqlwarn[1], sqlca.sqlwarn[2], + sqlca.sqlwarn[3], sqlca.sqlwarn[4], sqlca.sqlwarn[5], + sqlca.sqlwarn[6], sqlca.sqlwarn[7]); + fprintf(stderr, "sqlstate: %5s\n", sqlca.sqlstate); + fprintf(stderr, "===============\n"); +} +</programlisting> + + The result could look as follows (here an error due to a + misspelled table name): + +<screen> +==== sqlca ==== +sqlcode: -400 +sqlerrm.sqlerrml: 49 +sqlerrm.sqlerrmc: relation "pg_databasep" does not exist on line 38 +sqlerrd: 0 0 0 0 0 0 +sqlwarn: 0 0 0 0 0 0 0 0 +sqlstate: 42P01 +=============== +</screen> + </para> + </sect2> + + <sect2 id="ecpg-sqlstate-sqlcode"> + <title><literal>SQLSTATE</literal> vs. <literal>SQLCODE</literal></title> + + <para> + The fields <literal>sqlca.sqlstate</literal> and + <literal>sqlca.sqlcode</literal> are two different schemes that + provide error codes. Both are derived from the SQL standard, but + <literal>SQLCODE</literal> has been marked deprecated in the SQL-92 + edition of the standard and has been dropped in later editions. + Therefore, new applications are strongly encouraged to use + <literal>SQLSTATE</literal>. + </para> + + <para> + <literal>SQLSTATE</literal> is a five-character array. The five + characters contain digits or upper-case letters that represent + codes of various error and warning conditions. + <literal>SQLSTATE</literal> has a hierarchical scheme: the first + two characters indicate the general class of the condition, the + last three characters indicate a subclass of the general + condition. A successful state is indicated by the code + <literal>00000</literal>. The <literal>SQLSTATE</literal> codes are for + the most part defined in the SQL standard. The + <productname>PostgreSQL</productname> server natively supports + <literal>SQLSTATE</literal> error codes; therefore a high degree + of consistency can be achieved by using this error code scheme + throughout all applications. For further information see + <xref linkend="errcodes-appendix">. + </para> + + <para> + <literal>SQLCODE</literal>, the deprecated error code scheme, is a + simple integer. A value of 0 indicates success, a positive value + indicates success with additional information, a negative value + indicates an error. The SQL standard only defines the positive + value +100, which indicates that the last command returned or + affected zero rows, and no specific negative values. Therefore, + this scheme can only achieve poor portability and does not have a + hierarchical code assignment. Historically, the embedded SQL + processor for <productname>PostgreSQL</productname> has assigned + some specific <literal>SQLCODE</literal> values for its use, which + are listed below with their numeric value and their symbolic name. + Remember that these are not portable to other SQL implementations. + To simplify the porting of applications to the + <literal>SQLSTATE</literal> scheme, the corresponding + <literal>SQLSTATE</literal> is also listed. There is, however, no + one-to-one or one-to-many mapping between the two schemes (indeed + it is many-to-many), so you should consult the global + <literal>SQLSTATE</literal> listing in <xref linkend="errcodes-appendix"> + in each case. + </para> + + <para> + These are the assigned <literal>SQLCODE</literal> values: + + <variablelist> + <varlistentry> + <term>0 (<symbol>ECPG_NO_ERROR</symbol>)</term> + <listitem> + <para> + Indicates no error. (SQLSTATE 00000) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>100 (<symbol>ECPG_NOT_FOUND</symbol>)</term> + <listitem> + <para> + This is a harmless condition indicating that the last command + retrieved or processed zero rows, or that you are at the end of + the cursor. (SQLSTATE 02000) + </para> + + <para> + When processing a cursor in a loop, you could use this code as + a way to detect when to abort the loop, like this: +<programlisting> +while (1) +{ + EXEC SQL FETCH ... ; + if (sqlca.sqlcode == ECPG_NOT_FOUND) + break; +} +</programlisting> + But <literal>WHENEVER NOT FOUND DO BREAK</literal> effectively + does this internally, so there is usually no advantage in + writing this out explicitly. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-12 (<symbol>ECPG_OUT_OF_MEMORY</symbol>)</term> + <listitem> + <para> + Indicates that your virtual memory is exhausted. The numeric + value is defined as <literal>-ENOMEM</literal>. (SQLSTATE + YE001) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-200 (<symbol>ECPG_UNSUPPORTED</symbol>)</term> + <listitem> + <para> + Indicates the preprocessor has generated something that the + library does not know about. Perhaps you are running + incompatible versions of the preprocessor and the + library. (SQLSTATE YE002) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-201 (<symbol>ECPG_TOO_MANY_ARGUMENTS</symbol>)</term> + <listitem> + <para> + This means that the command specified more host variables than + the command expected. (SQLSTATE 07001 or 07002) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-202 (<symbol>ECPG_TOO_FEW_ARGUMENTS</symbol>)</term> + <listitem> + <para> + This means that the command specified fewer host variables than + the command expected. (SQLSTATE 07001 or 07002) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-203 (<symbol>ECPG_TOO_MANY_MATCHES</symbol>)</term> + <listitem> + <para> + This means a query has returned multiple rows but the statement + was only prepared to store one result row (for example, because + the specified variables are not arrays). (SQLSTATE 21000) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-204 (<symbol>ECPG_INT_FORMAT</symbol>)</term> + <listitem> + <para> + The host variable is of type <type>int</type> and the datum in + the database is of a different type and contains a value that + cannot be interpreted as an <type>int</type>. The library uses + <function>strtol()</function> for this conversion. (SQLSTATE + 42804) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-205 (<symbol>ECPG_UINT_FORMAT</symbol>)</term> + <listitem> + <para> + The host variable is of type <type>unsigned int</type> and the + datum in the database is of a different type and contains a + value that cannot be interpreted as an <type>unsigned + int</type>. The library uses <function>strtoul()</function> + for this conversion. (SQLSTATE 42804) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-206 (<symbol>ECPG_FLOAT_FORMAT</symbol>)</term> + <listitem> + <para> + The host variable is of type <type>float</type> and the datum + in the database is of another type and contains a value that + cannot be interpreted as a <type>float</type>. The library + uses <function>strtod()</function> for this conversion. + (SQLSTATE 42804) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-207 (<symbol>ECPG_NUMERIC_FORMAT</symbol>)</term> + <listitem> + <para> + The host variable is of type <type>numeric</type> and the datum + in the database is of another type and contains a value that + cannot be interpreted as a <type>numeric</type> value. + (SQLSTATE 42804) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-208 (<symbol>ECPG_INTERVAL_FORMAT</symbol>)</term> + <listitem> + <para> + The host variable is of type <type>interval</type> and the datum + in the database is of another type and contains a value that + cannot be interpreted as an <type>interval</type> value. + (SQLSTATE 42804) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-209 (<symbol>ECPG_DATE_FORMAT</symbol>)</term> + <listitem> + <para> + The host variable is of type <type>date</type> and the datum in + the database is of another type and contains a value that + cannot be interpreted as a <type>date</type> value. + (SQLSTATE 42804) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-210 (<symbol>ECPG_TIMESTAMP_FORMAT</symbol>)</term> + <listitem> + <para> + The host variable is of type <type>timestamp</type> and the + datum in the database is of another type and contains a value + that cannot be interpreted as a <type>timestamp</type> value. + (SQLSTATE 42804) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-211 (<symbol>ECPG_CONVERT_BOOL</symbol>)</term> + <listitem> + <para> + This means the host variable is of type <type>bool</type> and + the datum in the database is neither <literal>'t'</> nor + <literal>'f'</>. (SQLSTATE 42804) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-212 (<symbol>ECPG_EMPTY</symbol>)</term> + <listitem> + <para> + The statement sent to the <productname>PostgreSQL</productname> + server was empty. (This cannot normally happen in an embedded + SQL program, so it might point to an internal error.) (SQLSTATE + YE002) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-213 (<symbol>ECPG_MISSING_INDICATOR</symbol>)</term> + <listitem> + <para> + A null value was returned and no null indicator variable was + supplied. (SQLSTATE 22002) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-214 (<symbol>ECPG_NO_ARRAY</symbol>)</term> + <listitem> + <para> + An ordinary variable was used in a place that requires an + array. (SQLSTATE 42804) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-215 (<symbol>ECPG_DATA_NOT_ARRAY</symbol>)</term> + <listitem> + <para> + The database returned an ordinary variable in a place that + requires array value. (SQLSTATE 42804) + </para> + </listitem> + </varlistentry> + +<![IGNORE[ + <!-- disabled by #if 0 in ecpglib --> + <varlistentry> + <term>-216 (<symbol>ECPG_ARRAY_INSERT</symbol>)</term> + <listitem> + <para> + The value could not be inserted into the array. (SQLSTATE + 42804) + </para> + </listitem> + </varlistentry> +]]> + + <varlistentry> + <term>-220 (<symbol>ECPG_NO_CONN</symbol>)</term> + <listitem> + <para> + The program tried to access a connection that does not exist. + (SQLSTATE 08003) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-221 (<symbol>ECPG_NOT_CONN</symbol>)</term> + <listitem> + <para> + The program tried to access a connection that does exist but is + not open. (This is an internal error.) (SQLSTATE YE002) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-230 (<symbol>ECPG_INVALID_STMT</symbol>)</term> + <listitem> + <para> + The statement you are trying to use has not been prepared. + (SQLSTATE 26000) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-239 (<symbol>ECPG_INFORMIX_DUPLICATE_KEY</symbol>)</term> + <listitem> + <para> + Duplicate key error, violation of unique constraint (Informix + compatibility mode). (SQLSTATE 23505) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-240 (<symbol>ECPG_UNKNOWN_DESCRIPTOR</symbol>)</term> + <listitem> + <para> + The descriptor specified was not found. The statement you are + trying to use has not been prepared. (SQLSTATE 33000) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-241 (<symbol>ECPG_INVALID_DESCRIPTOR_INDEX</symbol>)</term> + <listitem> + <para> + The descriptor index specified was out of range. (SQLSTATE + 07009) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-242 (<symbol>ECPG_UNKNOWN_DESCRIPTOR_ITEM</symbol>)</term> + <listitem> + <para> + An invalid descriptor item was requested. (This is an internal + error.) (SQLSTATE YE002) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-243 (<symbol>ECPG_VAR_NOT_NUMERIC</symbol>)</term> + <listitem> + <para> + During the execution of a dynamic statement, the database + returned a numeric value and the host variable was not numeric. + (SQLSTATE 07006) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-244 (<symbol>ECPG_VAR_NOT_CHAR</symbol>)</term> + <listitem> + <para> + During the execution of a dynamic statement, the database + returned a non-numeric value and the host variable was numeric. + (SQLSTATE 07006) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-284 (<symbol>ECPG_INFORMIX_SUBSELECT_NOT_ONE</symbol>)</term> + <listitem> + <para> + A result of the subquery is not single row (Informix + compatibility mode). (SQLSTATE 21000) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-400 (<symbol>ECPG_PGSQL</symbol>)</term> + <listitem> + <para> + Some error caused by the <productname>PostgreSQL</productname> + server. The message contains the error message from the + <productname>PostgreSQL</productname> server. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-401 (<symbol>ECPG_TRANS</symbol>)</term> + <listitem> + <para> + The <productname>PostgreSQL</productname> server signaled that + we cannot start, commit, or rollback the transaction. + (SQLSTATE 08007) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-402 (<symbol>ECPG_CONNECT</symbol>)</term> + <listitem> + <para> + The connection attempt to the database did not succeed. + (SQLSTATE 08001) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-403 (<symbol>ECPG_DUPLICATE_KEY</symbol>)</term> + <listitem> + <para> + Duplicate key error, violation of unique constraint. (SQLSTATE + 23505) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-404 (<symbol>ECPG_SUBSELECT_NOT_ONE</symbol>)</term> + <listitem> + <para> + A result for the subquery is not single row. (SQLSTATE 21000) + </para> + </listitem> + </varlistentry> + +<![IGNORE[ + <!-- currently not used by the code --> + <varlistentry> + <term>-600 (<symbol>ECPG_WARNING_UNRECOGNIZED</symbol>)</term> + <listitem> + <para> + An unrecognized warning was received from the server. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-601 (<symbol>ECPG_WARNING_QUERY_IGNORED</symbol>)</term> + <listitem> + <para> + Current transaction is aborted. Queries are ignored until the + end of the transaction block. + </para> + </listitem> + </varlistentry> +]]> + + <varlistentry> + <term>-602 (<symbol>ECPG_WARNING_UNKNOWN_PORTAL</symbol>)</term> + <listitem> + <para> + An invalid cursor name was specified. (SQLSTATE 34000) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-603 (<symbol>ECPG_WARNING_IN_TRANSACTION</symbol>)</term> + <listitem> + <para> + Transaction is in progress. (SQLSTATE 25001) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-604 (<symbol>ECPG_WARNING_NO_TRANSACTION</symbol>)</term> + <listitem> + <para> + There is no active (in-progress) transaction. (SQLSTATE 25P01) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-605 (<symbol>ECPG_WARNING_PORTAL_EXISTS</symbol>)</term> + <listitem> + <para> + An existing cursor name was specified. (SQLSTATE 42P03) + </para> + </listitem> + </varlistentry> + + </variablelist> + </para> + </sect2> + </sect1> + + <sect1 id="ecpg-preproc"> + <title>Preprocessor Directives</title> + + <para> + Several preprocessor directives are available that modify how + the <command>ecpg</command> preprocessor parses and processes a + file. + </para> + + <sect2 id="ecpg-include"> + <title>Including Files</title> + + <para> + To include an external file into your embedded SQL program, use: +<programlisting> +EXEC SQL INCLUDE <replaceable>filename</replaceable>; +EXEC SQL INCLUDE <<replaceable>filename</replaceable>>; +EXEC SQL INCLUDE "<replaceable>filename</replaceable>"; +</programlisting> + The embedded SQL preprocessor will look for a file named + <literal><replaceable>filename</replaceable>.h</literal>, + preprocess it, and include it in the resulting C output. Thus, + embedded SQL statements in the included file are handled correctly. + </para> + + <para> + The <command>ecpg</command> preprocessor will search a file at + several directories in following order: + + <itemizedlist> + <listitem><simpara>current directory</simpara></listitem> + <listitem><simpara><filename>/usr/local/include</filename></simpara></listitem> + <listitem><simpara>PostgreSQL include directory, defined at build time (e.g., <filename>/usr/local/pgsql/include</filename>)</simpara></listitem> + <listitem><simpara><filename>/usr/include</filename></simpara></listitem> + </itemizedlist> + + But when <literal>EXEC SQL INCLUDE + "<replaceable>filename</replaceable>"</literal> is used, only the + current directory is searched. + </para> + + <para> + In each directory, the preprocessor will first look for the file + name as given, and if not found will append <literal>.h</literal> + to the file name and try again (unless the specified file name + already has that suffix). + </para> + + <para> + Note that <command>EXEC SQL INCLUDE</command> is <emphasis>not</emphasis> the same as: +<programlisting> +#include <<replaceable>filename</replaceable>.h> +</programlisting> + because this file would not be subject to SQL command preprocessing. + Naturally, you can continue to use the C + <literal>#include</literal> directive to include other header + files. + </para> + + <note> + <para> + The include file name is case-sensitive, even though the rest of + the <literal>EXEC SQL INCLUDE</literal> command follows the normal + SQL case-sensitivity rules. + </para> + </note> + </sect2> + + <sect2 id="ecpg-define"> + <title>The define and undef Directives</title> + <para> + Similar to the directive <literal>#define</literal> that is known from C, + embedded SQL has a similar concept: +<programlisting> +EXEC SQL DEFINE <replaceable>name</>; +EXEC SQL DEFINE <replaceable>name</> <replaceable>value</>; +</programlisting> + So you can define a name: +<programlisting> +EXEC SQL DEFINE HAVE_FEATURE; +</programlisting> + And you can also define constants: +<programlisting> +EXEC SQL DEFINE MYNUMBER 12; +EXEC SQL DEFINE MYSTRING 'abc'; +</programlisting> + Use <literal>undef</> to remove a previous definition: +<programlisting> +EXEC SQL UNDEF MYNUMBER; +</programlisting> + </para> + + <para> + Of course you can continue to use the C versions <literal>#define</literal> + and <literal>#undef</literal> in your embedded SQL program. The difference + is where your defined values get evaluated. If you use <literal>EXEC SQL + DEFINE</> then the <command>ecpg</> preprocessor evaluates the defines and substitutes + the values. For example if you write: +<programlisting> +EXEC SQL DEFINE MYNUMBER 12; +... +EXEC SQL UPDATE Tbl SET col = MYNUMBER; +</programlisting> + then <command>ecpg</> will already do the substitution and your C compiler will never + see any name or identifier <literal>MYNUMBER</>. Note that you cannot use + <literal>#define</literal> for a constant that you are going to use in an + embedded SQL query because in this case the embedded SQL precompiler is not + able to see this declaration. + </para> + </sect2> + + <sect2 id="ecpg-ifdef"> + <title>ifdef, ifndef, else, elif, and endif Directives</title> + <para> + You can use the following directives to compile code sections conditionally: + + <variablelist> + <varlistentry> + <term><literal>EXEC SQL ifdef <replaceable>name</>;</literal></term> + <listitem> + <para> + Checks a <replaceable>name</> and processes subsequent lines if + <replaceable>name</> has been created with <literal>EXEC SQL define + <replaceable>name</></literal>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>EXEC SQL ifndef <replaceable>name</>;</literal></term> + <listitem> + <para> + Checks a <replaceable>name</> and processes subsequent lines if + <replaceable>name</> has <emphasis>not</emphasis> been created with + <literal>EXEC SQL define <replaceable>name</></literal>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>EXEC SQL else;</literal></term> + <listitem> + <para> + Starts processing an alternative section to a section introduced by + either <literal>EXEC SQL ifdef <replaceable>name</></literal> or + <literal>EXEC SQL ifndef <replaceable>name</></literal>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>EXEC SQL elif <replaceable>name</>;</literal></term> + <listitem> + <para> + Checks <replaceable>name</> and starts an alternative section if + <replaceable>name</> has been created with <literal>EXEC SQL define + <replaceable>name</></literal>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>EXEC SQL endif;</literal></term> + <listitem> + <para> + Ends an alternative section. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <para> + Example: +<programlisting> +EXEC SQL ifndef TZVAR; +EXEC SQL SET TIMEZONE TO 'GMT'; +EXEC SQL elif TZNAME; +EXEC SQL SET TIMEZONE TO TZNAME; +EXEC SQL else; +EXEC SQL SET TIMEZONE TO TZVAR; +EXEC SQL endif; +</programlisting> + </para> + + </sect2> + </sect1> + + <sect1 id="ecpg-process"> + <title>Processing Embedded SQL Programs</title> + + <para> + Now that you have an idea how to form embedded SQL C programs, you + probably want to know how to compile them. Before compiling you + run the file through the embedded <acronym>SQL</acronym> + <acronym>C</acronym> preprocessor, which converts the + <acronym>SQL</acronym> statements you used to special function + calls. After compiling, you must link with a special library that + contains the needed functions. These functions fetch information + from the arguments, perform the <acronym>SQL</acronym> command using + the <application>libpq</application> interface, and put the result + in the arguments specified for output. + </para> + + <para> + The preprocessor program is called <filename>ecpg</filename> and is + included in a normal <productname>PostgreSQL</> installation. + Embedded SQL programs are typically named with an extension + <filename>.pgc</filename>. If you have a program file called + <filename>prog1.pgc</filename>, you can preprocess it by simply + calling: +<programlisting> +ecpg prog1.pgc +</programlisting> + This will create a file called <filename>prog1.c</filename>. If + your input files do not follow the suggested naming pattern, you + can specify the output file explicitly using the + <option>-o</option> option. + </para> + + <para> + The preprocessed file can be compiled normally, for example: +<programlisting> +cc -c prog1.c +</programlisting> + The generated C source files include header files from the + <productname>PostgreSQL</> installation, so if you installed + <productname>PostgreSQL</> in a location that is not searched by + default, you have to add an option such as + <literal>-I/usr/local/pgsql/include</literal> to the compilation + command line. + </para> + + <para> + To link an embedded SQL program, you need to include the + <filename>libecpg</filename> library, like so: +<programlisting> +cc -o myprog prog1.o prog2.o ... -lecpg +</programlisting> + Again, you might have to add an option like + <literal>-L/usr/local/pgsql/lib</literal> to that command line. + </para> + + <para> + If you manage the build process of a larger project using + <application>make</application>, it might be convenient to include + the following implicit rule to your makefiles: +<programlisting> +ECPG = ecpg + +%.c: %.pgc + $(ECPG) $< +</programlisting> + </para> + + <para> + The complete syntax of the <command>ecpg</command> command is + detailed in <xref linkend="app-ecpg">. + </para> + + <para> + The <application>ecpg</application> library is thread-safe by + default. However, you might need to use some threading + command-line options to compile your client code. + </para> + </sect1> + + <sect1 id="ecpg-library"> + <title>Library Functions</title> + + <para> + The <filename>libecpg</filename> library primarily contains + <quote>hidden</quote> functions that are used to implement the + functionality expressed by the embedded SQL commands. But there + are some functions that can usefully be called directly. Note that + this makes your code unportable. + </para> + + <itemizedlist> + <listitem> + <para> + <function>ECPGdebug(int <replaceable>on</replaceable>, FILE + *<replaceable>stream</replaceable>)</function> turns on debug + logging if called with the first argument non-zero. Debug logging + is done on <replaceable>stream</replaceable>. The log contains + all <acronym>SQL</acronym> statements with all the input + variables inserted, and the results from the + <productname>PostgreSQL</productname> server. This can be very + useful when searching for errors in your <acronym>SQL</acronym> + statements. + </para> + <note> + <para> + On Windows, if the <application>ecpg</> libraries and an application are + compiled with different flags, this function call will crash the + application because the internal representation of the + <literal>FILE</> pointers differ. Specifically, + multithreaded/single-threaded, release/debug, and static/dynamic + flags should be the same for the library and all applications using + that library. + </para> + </note> + </listitem> + + <listitem> + <para> + <function>ECPGget_PGconn(const char *<replaceable>connection_name</replaceable>) + </function> returns the library database connection handle identified by the given name. + If <replaceable>connection_name</replaceable> is set to <literal>NULL</literal>, the current + connection handle is returned. If no connection handle can be identified, the function returns + <literal>NULL</literal>. The returned connection handle can be used to call any other functions + from <application>libpq</application>, if necessary. + </para> + <note> + <para> + It is a bad idea to manipulate database connection handles made from <application>ecpg</application> directly + with <application>libpq</application> routines. + </para> + </note> + </listitem> + + <listitem> + <para> + <function>ECPGtransactionStatus(const char *<replaceable>connection_name</replaceable>)</function> + returns the current transaction status of the given connection identified by <replaceable>connection_name</replaceable>. + See <xref linkend="libpq-status"> and libpq's <function>PQtransactionStatus()</function> for details about the returned status codes. + </para> + </listitem> + + <listitem> + <para> + <function>ECPGstatus(int <replaceable>lineno</replaceable>, + const char* <replaceable>connection_name</replaceable>)</function> + returns true if you are connected to a database and false if not. + <replaceable>connection_name</replaceable> can be <literal>NULL</> + if a single connection is being used. + </para> + </listitem> + </itemizedlist> + </sect1> + + <sect1 id="ecpg-lo"> + <title>Large Objects</title> + + <para> + Large objects are not directly supported by ECPG, but ECPG + application can manipulate large objects through the libpq large + object functions, obtaining the necessary <type>PGconn</type> + object by calling the <function>ECPGget_PGconn()</function> + function. (However, use of + the <function>ECPGget_PGconn()</function> function and touching + <type>PGconn</type> objects directly should be done very carefully + and ideally not mixed with other ECPG database access calls.) + </para> + + <para> + For more details about the <function>ECPGget_PGconn()</function>, see + <xref linkend="ecpg-library">. For information about the large + object function interface, see <xref linkend="largeObjects">. + </para> + + <para> + Large object functions have to be called in a transaction block, so + when autocommit is off, <command>BEGIN</command> commands have to + be issued explicitly. + </para> + + <para> + <xref linkend="ecpg-lo-example"> shows an example program that + illustrates how to create, write, and read a large object in an + ECPG application. + </para> + + <example id="ecpg-lo-example"> + <title>ECPG Program Accessing Large Objects</title> +<programlisting><![CDATA[ +#include <stdio.h> +#include <stdlib.h> +#include <libpq-fe.h> +#include <libpq/libpq-fs.h> + +EXEC SQL WHENEVER SQLERROR STOP; + +int +main(void) +{ + PGconn *conn; + Oid loid; + int fd; + char buf[256]; + int buflen = 256; + char buf2[256]; + int rc; + + memset(buf, 1, buflen); + + EXEC SQL CONNECT TO testdb AS con1; + + conn = ECPGget_PGconn("con1"); + printf("conn = %p\n", conn); + + /* create */ + loid = lo_create(conn, 0); + if (loid < 0) + printf("lo_create() failed: %s", PQerrorMessage(conn)); + + printf("loid = %d\n", loid); + + /* write test */ + fd = lo_open(conn, loid, INV_READ|INV_WRITE); + if (fd < 0) + printf("lo_open() failed: %s", PQerrorMessage(conn)); + + printf("fd = %d\n", fd); + + rc = lo_write(conn, fd, buf, buflen); + if (rc < 0) + printf("lo_write() failed\n"); + + rc = lo_close(conn, fd); + if (rc < 0) + printf("lo_close() failed: %s", PQerrorMessage(conn)); + + /* read test */ + fd = lo_open(conn, loid, INV_READ); + if (fd < 0) + printf("lo_open() failed: %s", PQerrorMessage(conn)); + + printf("fd = %d\n", fd); + + rc = lo_read(conn, fd, buf2, buflen); + if (rc < 0) + printf("lo_read() failed\n"); + + rc = lo_close(conn, fd); + if (rc < 0) + printf("lo_close() failed: %s", PQerrorMessage(conn)); + + /* check */ + rc = memcmp(buf, buf2, buflen); + printf("memcmp() = %d\n", rc); + + /* cleanup */ + rc = lo_unlink(conn, loid); + if (rc < 0) + printf("lo_unlink() failed: %s", PQerrorMessage(conn)); + + EXEC SQL COMMIT; + EXEC SQL DISCONNECT ALL; + return 0; +} +]]></programlisting> + </example> + </sect1> + + <sect1 id="ecpg-cpp"> + <title><acronym>C++</acronym> Applications</title> + + <para> + ECPG has some limited support for C++ applications. This section + describes some caveats. + </para> + + <para> + The <command>ecpg</command> preprocessor takes an input file + written in C (or something like C) and embedded SQL commands, + converts the embedded SQL commands into C language chunks, and + finally generates a <filename>.c</filename> file. The header file + declarations of the library functions used by the C language chunks + that <command>ecpg</command> generates are wrapped + in <literal>extern "C" { ... }</literal> blocks when used under + C++, so they should work seamlessly in C++. + </para> + + <para> + In general, however, the <command>ecpg</command> preprocessor only + understands C; it does not handle the special syntax and reserved + words of the C++ language. So, some embedded SQL code written in + C++ application code that uses complicated features specific to C++ + might fail to be preprocessed correctly or might not work as + expected. + </para> + + <para> + A safe way to use the embedded SQL code in a C++ application is + hiding the ECPG calls in a C module, which the C++ application code + calls into to access the database, and linking that together with + the rest of the C++ code. See <xref linkend="ecpg-cpp-and-c"> + about that. + </para> + + <sect2 id="ecpg-cpp-scope"> + <title>Scope for Host Variables</title> + + <para> + The <command>ecpg</command> preprocessor understands the scope of + variables in C. In the C language, this is rather simple because + the scopes of variables is based on their code blocks. In C++, + however, the class member variables are referenced in a different + code block from the declared position, so + the <command>ecpg</command> preprocessor will not understand the + scope of the class member variables. + </para> + + <para> + For example, in the following case, the <command>ecpg</command> + preprocessor cannot find any declaration for the + variable <literal>dbname</literal> in the <literal>test</literal> + method, so an error will occur. + +<programlisting> +class TestCpp +{ + EXEC SQL BEGIN DECLARE SECTION; + char dbname[1024]; + EXEC SQL END DECLARE SECTION; + + public: + TestCpp(); + void test(); + ~TestCpp(); +}; + +TestCpp::TestCpp() +{ + EXEC SQL CONNECT TO testdb1; +} + +void Test::test() +{ + EXEC SQL SELECT current_database() INTO :dbname; + printf("current_database = %s\n", dbname); +} + +TestCpp::~TestCpp() +{ + EXEC SQL DISCONNECT ALL; +} +</programlisting> + + This code will result in an error like this: +<screen> +<userinput>ecpg test_cpp.pgc</userinput> +test_cpp.pgc:28: ERROR: variable "dbname" is not declared +</screen> + </para> + + <para> + To avoid this scope issue, the <literal>test</literal> method + could be modified to use a local variable as intermediate storage. + But this approach is only a poor workaround, because it uglifies + the code and reduces performance. + +<programlisting> +void TestCpp::test() +{ + EXEC SQL BEGIN DECLARE SECTION; + char tmp[1024]; + EXEC SQL END DECLARE SECTION; + + EXEC SQL SELECT current_database() INTO :tmp; + strlcpy(dbname, tmp, sizeof(tmp)); + + printf("current_database = %s\n", dbname); +} +</programlisting> + </para> + </sect2> + + <sect2 id="ecpg-cpp-and-c"> + <title>C++ Application Development with External C Module</title> + + <para> + If you understand these technical limitations of + the <command>ecpg</command> preprocessor in C++, you might come to + the conclusion that linking C objects and C++ objects at the link + stage to enable C++ applications to use ECPG features could be + better than writing some embedded SQL commands in C++ code + directly. This section describes a way to separate some embedded + SQL commands from C++ application code with a simple example. In + this example, the application is implemented in C++, while C and + ECPG is used to connect to the PostgreSQL server. + </para> + + <para> + Three kinds of files have to be created: a C file + (<filename>*.pgc</filename>), a header file, and a C++ file: + + <variablelist> + <varlistentry> + <term><filename>test_mod.pgc</filename></term> + <listitem> + <para> + A sub-routine module to execute SQL commands embedded in C. + It is going to be converted + into <filename>test_mod.c</filename> by the preprocessor. + +<programlisting> +#include "test_mod.h" +#include <stdio.h> + +void +db_connect() +{ + EXEC SQL CONNECT TO testdb1; +} + +void +db_test() +{ + EXEC SQL BEGIN DECLARE SECTION; + char dbname[1024]; + EXEC SQL END DECLARE SECTION; + + EXEC SQL SELECT current_database() INTO :dbname; + printf("current_database = %s\n", dbname); +} + +void +db_disconnect() +{ + EXEC SQL DISCONNECT ALL; +} +</programlisting> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><filename>test_mod.h</filename></term> + <listitem> + <para> + A header file with declarations of the functions in the C + module (<filename>test_mod.pgc</filename>). It is included by + <filename>test_cpp.cpp</filename>. This file has to have an + <literal>extern "C"</literal> block around the declarations, + because it will be linked from the C++ module. + +<programlisting> +#ifdef __cplusplus +extern "C" { +#endif + +void db_connect(); +void db_test(); +void db_disconnect(); + +#ifdef __cplusplus +} +#endif +</programlisting> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><filename>test_cpp.cpp</filename></term> + <listitem> + <para> + The main code for the application, including + the <function>main</function> routine, and in this example a + C++ class. + +<programlisting> +#include "test_mod.h" + +class TestCpp +{ + public: + TestCpp(); + void test(); + ~TestCpp(); +}; + +TestCpp::TestCpp() +{ + db_connect(); +} + +void +TestCpp::test() +{ + db_test(); +} + +TestCpp::~TestCpp() +{ + db_disconnect(); +} + +int +main(void) +{ + TestCpp *t = new TestCpp(); + + t->test(); + return 0; +} +</programlisting> + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <para> + To build the application, proceed as follows. Convert + <filename>test_mod.pgc</> into <filename>test_mod.c</> by + running <command>ecpg</command>, and generate + <filename>test_mod.o</> by compiling + <filename>test_mod.c</> with the C compiler: +<programlisting> +ecpg -o test_mod.c test_mod.pgc +cc -c test_mod.c -o test_mod.o +</programlisting> + </para> + + <para> + Next, generate <filename>test_cpp.o</> by compiling + <filename>test_cpp.cpp</> with the C++ compiler:. +<programlisting> +c++ -c test_cpp.cpp -o test_cpp.o +</programlisting> + </para> + + <para> + Finally, link these object files, <filename>test_cpp.o</> + and <filename>test_mod.o</>, into one executable, using the C++ + compiler driver: +<programlisting> +c++ test_cpp.o test_mod.o -lecpg -o test_cpp +</programlisting> + </para> + </sect2> + </sect1> + + <sect1 id="ecpg-sql-commands"> + <title>Embedded SQL Commands</title> + + <para> + This section describes all SQL commands that are specific to + embedded SQL. Also refer to the SQL commands listed + in <xref linkend="sql-commands">, which can also be used in + embedded SQL, unless stated otherwise. + </para> + + <refentry id="ecpg-sql-allocate-descriptor"> + <refnamediv> + <refname>ALLOCATE DESCRIPTOR</refname> + <refpurpose>allocate an SQL descriptor area</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +ALLOCATE DESCRIPTOR <replaceable class="PARAMETER">name</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>ALLOCATE DESCRIPTOR</command> allocates a new named SQL + descriptor area, which can be used to exchange data between the + PostgreSQL server and the host program. + </para> + + <para> + Descriptor areas should be freed after use using + the <command>DEALLOCATE DESCRIPTOR</command> command. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">name</replaceable></term> + <listitem> + <para> + A name of SQL descriptor, case sensitive. This can be an SQL + identifier or a host variable. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + +<programlisting> +EXEC SQL ALLOCATE DESCRIPTOR mydesc; +</programlisting> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>ALLOCATE DESCRIPTOR</command> is specified in the SQL + standard. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="ecpg-sql-deallocate-descriptor"></member> + <member><xref linkend="ecpg-sql-get-descriptor"></member> + <member><xref linkend="ecpg-sql-set-descriptor"></member> + </simplelist> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-connect"> + <refnamediv> + <refname>CONNECT</refname> + <refpurpose>establish a database connection</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +CONNECT TO <replaceable>connection_target</replaceable> [ AS <replaceable>connection_name</replaceable> ] [ USER <replaceable>connection_user_name</replaceable> ] +CONNECT TO DEFAULT +CONNECT <replaceable>connection_user_name</replaceable> +DATABASE <replaceable>connection_target</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + The <command>CONNECT</command> command establishes a connection + between the client and the PostgreSQL server. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">connection_target</replaceable></term> + <listitem> + <para> + <replaceable class="PARAMETER">connection_target</replaceable> + specifies the target server of the connection on one of + several forms. + + <variablelist> + <varlistentry> + <term>[ <replaceable>database_name</replaceable> ] [ <literal>@</literal><replaceable>host</replaceable> ] [ <literal>:</literal><replaceable>port</replaceable> ]</term> + <listitem> + <para> + Connect over TCP/IP + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>unix:postgresql://</literal><replaceable>host</replaceable> [ <literal>:</literal><replaceable>port</replaceable> ] <literal>/</literal> [ <replaceable>database_name</replaceable> ] [ <literal>?</literal><replaceable>connection_option</replaceable> ]</term> + <listitem> + <para> + Connect over Unix-domain sockets + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>tcp:postgresql://</literal><replaceable>host</replaceable> [ <literal>:</literal><replaceable>port</replaceable> ] <literal>/</literal> [ <replaceable>database_name</replaceable> ] [ <literal>?</literal><replaceable>connection_option</replaceable> ]</term> + <listitem> + <para> + Connect over TCP/IP </para> </listitem> </varlistentry> + <varlistentry> + <term>SQL string constant</term> + <listitem> + <para> + containing a value in one of the above forms + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>host variable</term> + <listitem> + <para> + host variable of type <type>char[]</type> + or <type>VARCHAR[]</type> containing a value in one of the + above forms + </para> + </listitem> + </varlistentry> </variablelist> </para> </listitem> </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">connection_object</replaceable></term> + <listitem> + <para> + An optional identifier for the connection, so that it can be + referred to in other commands. This can be an SQL identifier + or a host variable. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">connection_user</replaceable></term> + <listitem> + <para> + The user name for the database connection. + </para> + + <para> + This parameter can also specify user name and password, using one the forms + <literal><replaceable>user_name</replaceable>/<replaceable>password</replaceable></literal>, + <literal><replaceable>user_name</replaceable> IDENTIFIED BY <replaceable>password</replaceable></literal>, or + <literal><replaceable>user_name</replaceable> USING <replaceable>password</replaceable></literal>. + </para> + + <para> + User name and password can be SQL identifiers, string + constants, or host variables. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>DEFAULT</literal></term> + <listitem> + <para> + Use all default connection parameters, as defined by libpq. + </para> + </listitem> + </varlistentry> </variablelist> - </para> + </refsect1> - </sect2> + <refsect1> + <title>Examples</title> + + <para> + Here a several variants for specifying connection parameters: +<programlisting> +EXEC SQL CONNECT TO "connectdb" AS main; +EXEC SQL CONNECT TO "connectdb" AS second; +EXEC SQL CONNECT TO "unix:postgresql://200.46.204.71/connectdb" AS main USER connectuser; +EXEC SQL CONNECT TO "unix:postgresql://localhost/connectdb" AS main USER connectuser; +EXEC SQL CONNECT TO 'connectdb' AS main; +EXEC SQL CONNECT TO 'unix:postgresql://localhost/connectdb' AS main USER :user; +EXEC SQL CONNECT TO :db AS :id; +EXEC SQL CONNECT TO :db USER connectuser USING :pw; +EXEC SQL CONNECT TO @localhost AS main USER connectdb; +EXEC SQL CONNECT TO REGRESSDB1 as main; +EXEC SQL CONNECT TO AS main USER connectdb; +EXEC SQL CONNECT TO connectdb AS :id; +EXEC SQL CONNECT TO connectdb AS main USER connectuser/connectdb; +EXEC SQL CONNECT TO connectdb AS main; +EXEC SQL CONNECT TO connectdb@localhost AS main; +EXEC SQL CONNECT TO tcp:postgresql://localhost/ USER connectdb; +EXEC SQL CONNECT TO tcp:postgresql://localhost/connectdb USER connectuser IDENTIFIED BY connectpw; +EXEC SQL CONNECT TO tcp:postgresql://localhost:20/connectdb USER connectuser IDENTIFIED BY connectpw; +EXEC SQL CONNECT TO unix:postgresql://localhost/ AS main USER connectdb; +EXEC SQL CONNECT TO unix:postgresql://localhost/connectdb AS main USER connectuser; +EXEC SQL CONNECT TO unix:postgresql://localhost/connectdb USER connectuser IDENTIFIED BY "connectpw"; +EXEC SQL CONNECT TO unix:postgresql://localhost/connectdb USER connectuser USING "connectpw"; +EXEC SQL CONNECT TO unix:postgresql://localhost/connectdb?connect_timeout=14 USER connectuser; +</programlisting> + </para> + + <para> + Here is an example program that illustrates the use of host + variables to specify connection parameters: +<programlisting> +int +main(void) +{ +EXEC SQL BEGIN DECLARE SECTION; + char *dbname = "testdb"; /* database name */ + char *user = "testuser"; /* connection user name */ + char *connection = "tcp:postgresql://localhost:5432/testdb"; + /* connection string */ + char ver[256]; /* buffer to store the version string */ +EXEC SQL END DECLARE SECTION; + + ECPGdebug(1, stderr); + + EXEC SQL CONNECT TO :dbname USER :user; + EXEC SQL SELECT version() INTO :ver; + EXEC SQL DISCONNECT; + + printf("version: %s\n", ver); + + EXEC SQL CONNECT TO :connection USER :user; + EXEC SQL SELECT version() INTO :ver; + EXEC SQL DISCONNECT; + + printf("version: %s\n", ver); + + return 0; +} +</programlisting> + </para> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>CONNECT</command> is specified in the SQL standard, but + the format of the connection parameters is + implementation-specific. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="ecpg-sql-disconnect"></member> + <member><xref linkend="ecpg-sql-set-connection"></member> + </simplelist> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-deallocate-descriptor"> + <refnamediv> + <refname>DEALLOCATE DESCRIPTOR</refname> + <refpurpose>deallocate an SQL descriptor area</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +DEALLOCATE DESCRIPTOR <replaceable class="PARAMETER">name</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>DEALLOCATE DESCRIPTOR</command> deallocates a named SQL + descriptor area. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">name</replaceable></term> + <listitem> + <para> + The name of the descriptor which is going to be deallocated. + It is case sensitive. This can be an SQL identifier or a host + variable. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + +<programlisting> +EXEC SQL DEALLOCATE DESCRIPTOR mydesc; +</programlisting> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>DEALLOCATE DESCRIPTOR</command> is specified in the SQL + standard. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="ecpg-sql-allocate-descriptor"></member> + <member><xref linkend="ecpg-sql-get-descriptor"></member> + <member><xref linkend="ecpg-sql-set-descriptor"></member> + </simplelist> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-declare"> + <refnamediv> + <refname>DECLARE</refname> + <refpurpose>define a cursor</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +DECLARE <replaceable class="PARAMETER">cursor_name</replaceable> [ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ] CURSOR [ { WITH | WITHOUT } HOLD ] FOR <replaceable class="PARAMETER">prepared_name</replaceable> +DECLARE <replaceable class="PARAMETER">cursor_name</replaceable> [ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ] CURSOR [ { WITH | WITHOUT } HOLD ] FOR <replaceable class="PARAMETER">query</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>DECLARE</command> declares a cursor for iterating over + the result set of a prepared statement. This command has + slightly different semantics from the direct SQL + command <command>DECLARE</command>: Whereas the latter executes a + query and prepares the result set for retrieval, this embedded + SQL command merely declares a name as a <quote>loop + variable</quote> for iterating over the result set of a query; + the actual execution happens when the cursor is opened with + the <command>OPEN</command> command. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + <variablelist> + + <varlistentry> + <term><replaceable class="PARAMETER">cursor_name</replaceable></term> + <listitem> + <para> + A cursor name, case sensitive. This can be an SQL identifier + or a host variable. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">prepared_name</replaceable></term> + <listitem> + <para> + The name of a prepared query, either as an SQL identifier or a + host variable. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="parameter">query</replaceable></term> + <listitem> + <para> + A <xref linkend="sql-select"> or + <xref linkend="sql-values"> command which will provide the + rows to be returned by the cursor. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + For the meaning of the cursor options, + see <xref linkend="sql-declare">. + </para> + </refsect1> + + <refsect1> + <title>Examples</title> + + <para> + Examples declaring a cursor for a query: +<programlisting> +EXEC SQL DECLARE C CURSOR FOR SELECT * FROM My_Table; +EXEC SQL DECLARE C CURSOR FOR SELECT Item1 FROM T; +EXEC SQL DECLARE cur1 CURSOR FOR SELECT version(); +</programlisting> + </para> + + <para> + An example declaring a cursor for a prepared statement: +<programlisting> +EXEC SQL PREPARE stmt1 AS SELECT version(); +EXEC SQL DECLARE cur1 CURSOR FOR stmt1; +</programlisting> + </para> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>DECLARE</command> is specified in the SQL standard. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="ecpg-sql-open"></member> + <member><xref linkend="sql-close"></member> + <member><xref linkend="sql-declare"></member> + </simplelist> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-describe"> + <refnamediv> + <refname>DESCRIBE</refname> + <refpurpose>obtain information about a prepared statement or result set</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +DESCRIBE [ OUTPUT ] <replaceable class="PARAMETER">prepared_name</replaceable> USING [ SQL ] DESCRIPTOR <replaceable class="PARAMETER">descriptor_name</replaceable> +DESCRIBE [ OUTPUT ] <replaceable class="PARAMETER">prepared_name</replaceable> INTO [ SQL ] DESCRIPTOR <replaceable class="PARAMETER">descriptor_name</replaceable> +DESCRIBE [ OUTPUT ] <replaceable class="PARAMETER">prepared_name</replaceable> INTO <replaceable class="PARAMETER">sqlda_name</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>DESCRIBE</command> retrieves metadata information about + the result columns contained in a prepared statement, without + actually fetching a row. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">prepared_name</replaceable></term> + <listitem> + <para> + The name of a prepared statement. This can be an SQL + identifier or a host variable. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">descriptor_name</replaceable></term> + <listitem> + <para> + A descriptor name. It is case sensitive. It can be an SQL + identifier or a host variable. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">sqlda_name</replaceable></term> + <listitem> + <para> + The name of an SQLDA variable. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + +<programlisting> +EXEC SQL ALLOCATE DESCRIPTOR mydesc; +EXEC SQL PREPARE stmt1 FROM :sql_stmt; +EXEC SQL DESCRIBE stmt1 INTO SQL DESCRIPTOR mydesc; +EXEC SQL GET DESCRIPTOR mydesc VALUE 1 :charvar = NAME; +EXEC SQL DEALLOCATE DESCRIPTOR mydesc; +</programlisting> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>DESCRIBE</command> is specified in the SQL standard. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="ecpg-sql-allocate-descriptor"></member> + <member><xref linkend="ecpg-sql-get-descriptor"></member> + </simplelist> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-disconnect"> + <refnamediv> + <refname>DISCONNECT</refname> + <refpurpose>terminate a database connection</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +DISCONNECT <replaceable class="PARAMETER">connection_name</replaceable> +DISCONNECT [ CURRENT ] +DISCONNECT DEFAULT +DISCONNECT ALL +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>DISCONNECT</command> closes a connection (or all + connections) to the database. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">connection_name</replaceable></term> + <listitem> + <para> + A database connection name established by + the <command>CONNECT</command> command. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>CURRENT</literal></term> + <listitem> + <para> + Close the <quote>current</quote> connection, which is either + the most recently opened connection, or the connection set by + the <command>SET CONNECTION</command> command. This is also + the default if no argument is given to + the <command>DISCONNECT</command> command. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>DEFAULT</literal></term> + <listitem> + <para> + Close the default connection. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>ALL</literal></term> + <listitem> + <para> + Close all open connections. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + +<programlisting> +int +main(void) +{ + EXEC SQL CONNECT TO testdb AS DEFAULT USER testuser; + EXEC SQL CONNECT TO testdb AS con1 USER testuser; + EXEC SQL CONNECT TO testdb AS con2 USER testuser; + EXEC SQL CONNECT TO testdb AS con3 USER testuser; + + EXEC SQL DISCONNECT CURRENT; /* close con3 */ + EXEC SQL DISCONNECT DEFAULT; /* close DEFAULT */ + EXEC SQL DISCONNECT ALL; /* close con2 and con1 */ + + return 0; +} +</programlisting> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>DISCONNECT</command> is specified in the SQL standard. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="ecpg-sql-connect"></member> + <member><xref linkend="ecpg-sql-set-connection"></member> + </simplelist> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-execute-immediate"> + <refnamediv> + <refname>EXECUTE IMMEDIATE</refname> + <refpurpose>dynamically prepare and execute a statement</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +EXECUTE IMMEDIATE <replaceable class="PARAMETER">string</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>EXECUTE IMMEDIATE</command> immediately prepares and + executes a dynamically specified SQL statement, without + retrieving result rows. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">string</replaceable></term> + <listitem> + <para> + A literal C string or a host variable containing the SQL + statement to be executed. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + + <para> + Here is an example that executes an <command>INSERT</command> + statement using <command>EXECUTE IMMEDIATE</command> and a host + variable named <varname>command</varname>: +<programlisting> +sprintf(command, "INSERT INTO test (name, amount, letter) VALUES ('db: ''r1''', 1, 'f')"); +EXEC SQL EXECUTE IMMEDIATE :command; +</programlisting> + </para> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>EXECUTE IMMEDIATE</command> is specified in the SQL standard. + </para> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-get-descriptor"> + <refnamediv> + <refname>GET DESCRIPTOR</refname> + <refpurpose>get information from an SQL descriptor area</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +GET DESCRIPTOR <replaceable class="PARAMETER">descriptor_name</replaceable> <replaceable class="PARAMETER">:cvariable</replaceable> = <replaceable class="PARAMETER">descriptor_header_item</replaceable> [, ... ] +GET DESCRIPTOR <replaceable class="PARAMETER">descriptor_name</replaceable> VALUE <replaceable class="PARAMETER">column_number</replaceable> <replaceable class="PARAMETER">:cvariable</replaceable> = <replaceable class="PARAMETER">descriptor_item</replaceable> [, ... ] +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>GET DESCRIPTOR</command> retrieves information about a + query result set from an SQL descriptor area and stores it into + host variables. A descriptor area is typically populated + using <command>FETCH</command> or <command>SELECT</command> + before using this command to transfer the information into host + language variables. + </para> + + <para> + This command has two forms: The first form retrieves + descriptor <quote>header</quote> items, which apply to the result + set in its entirety. One example is the row count. The second + form, which requires the column number as additional parameter, + retrieves information about a particular column. Examples are + the column name and the actual column value. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">descriptor_name</replaceable></term> + <listitem> + <para> + A descriptor name. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">descriptor_header_item</replaceable></term> + <listitem> + <para> + A token identifying which header information item to retrieve. + Only <literal>COUNT</literal>, to get the number of columns in the + result set, is currently supported. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">column_number</replaceable></term> + <listitem> + <para> + The number of the column about which information is to be + retrieved. The count starts at 1. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">descriptor_item</replaceable></term> + <listitem> + <para> + A token identifying which item of information about a column + to retrieve. See <xref linkend="ecpg-named-descriptors"> for + a list of supported items. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">cvariable</replaceable></term> + <listitem> + <para> + A host variable that will receive the data retrieved from the + descriptor area. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + + <para> + An example to retrieve the number of columns in a result set: +<programlisting> +EXEC SQL GET DESCRIPTOR d :d_count = COUNT; +</programlisting> + </para> + + <para> + An example to retrieve a data length in the first column: +<programlisting> +EXEC SQL GET DESCRIPTOR d VALUE 1 :d_returned_octet_length = RETURNED_OCTET_LENGTH; +</programlisting> + </para> + + <para> + An example to retrieve the data body of the second column as a + string: +<programlisting> +EXEC SQL GET DESCRIPTOR d VALUE 2 :d_data = DATA; +</programlisting> + </para> + + <para> + Here is an example for a whole procedure of + executing <literal>SELECT current_database();</> and showing the number of + columns, the column data length, and the column data: +<programlisting> +int +main(void) +{ +EXEC SQL BEGIN DECLARE SECTION; + int d_count; + char d_data[1024]; + int d_returned_octet_length; +EXEC SQL END DECLARE SECTION; + + EXEC SQL CONNECT TO testdb AS con1 USER testuser; + EXEC SQL ALLOCATE DESCRIPTOR d; + + /* Declare, open a cursor, and assign a descriptor to the cursor */ + EXEC SQL DECLARE cur CURSOR FOR SELECT current_database(); + EXEC SQL OPEN cur; + EXEC SQL FETCH NEXT FROM cur INTO SQL DESCRIPTOR d; + + /* Get a number of total columns */ + EXEC SQL GET DESCRIPTOR d :d_count = COUNT; + printf("d_count = %d\n", d_count); + + /* Get length of a returned column */ + EXEC SQL GET DESCRIPTOR d VALUE 1 :d_returned_octet_length = RETURNED_OCTET_LENGTH; + printf("d_returned_octet_length = %d\n", d_returned_octet_length); + + /* Fetch the returned column as a string */ + EXEC SQL GET DESCRIPTOR d VALUE 1 :d_data = DATA; + printf("d_data = %s\n", d_data); + + /* Closing */ + EXEC SQL CLOSE cur; + EXEC SQL COMMIT; + + EXEC SQL DEALLOCATE DESCRIPTOR d; + EXEC SQL DISCONNECT ALL; + + return 0; +} +</programlisting> + When the example is executed, the result will look like this: +<screen> +d_count = 1 +d_returned_octet_length = 6 +d_data = testdb +</screen> + </para> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>GET DESCRIPTOR</command> is specified in the SQL standard. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="ecpg-sql-allocate-descriptor"></member> + <member><xref linkend="ecpg-sql-set-descriptor"></member> + </simplelist> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-open"> + <refnamediv> + <refname>OPEN</refname> + <refpurpose>open a dynamic cursor</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +OPEN <replaceable class="PARAMETER">cursor_name</replaceable> +OPEN <replaceable class="PARAMETER">cursor_name</replaceable> USING <replaceable class="PARAMETER">value</replaceable> [, ... ] +OPEN <replaceable class="PARAMETER">cursor_name</replaceable> USING SQL DESCRIPTOR <replaceable class="PARAMETER">descriptor_name</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>OPEN</command> opens a cursor and optionally binds + actual values to the placeholders in the cursor's declaration. + The cursor must previously have been declared with + the <command>DECLARE</command> command. The execution + of <command>OPEN</command> causes the query to start executing on + the server. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">cursor_name</replaceable></term> + <listitem> + <para> + The name of the cursor to be opened. This can be an SQL + identifier or a host variable. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">value</replaceable></term> + <listitem> + <para> + A value to be bound to a placeholder in the cursor. This can + be an SQL constant, a host variable, or a host variable with + indicator. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">descriptor_name</replaceable></term> + <listitem> + <para> + The name of a descriptor containing values to be bound to the + placeholders in the cursor. This can be an SQL identifier or + a host variable. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + +<programlisting> +EXEC SQL OPEN a; +EXEC SQL OPEN d USING 1, 'test'; +EXEC SQL OPEN c1 USING SQL DESCRIPTOR mydesc; +EXEC SQL OPEN :curname1; +</programlisting> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>OPEN</command> is specified in the SQL standard. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="ecpg-sql-declare"></member> + <member><xref linkend="sql-close"></member> + </simplelist> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-prepare"> + <refnamediv> + <refname>PREPARE</refname> + <refpurpose>prepare a statement for execution</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +PREPARE <replaceable class="PARAMETER">name</replaceable> FROM <replaceable class="PARAMETER">string</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>PREPARE</command> prepares a statement dynamically + specified as a string for execution. This is different from the + direct SQL statement <xref linkend="sql-prepare">, which can also + be used in embedded programs. The <xref linkend="sql-execute"> + command is used to execute either kind of prepared statement. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">prepared_name</replaceable></term> + <listitem> + <para> + An identifier for the prepared query. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">string</replaceable></term> + <listitem> + <para> + A literal C string or a host variable containing a preparable + statement, one of the SELECT, INSERT, UPDATE, or + DELETE. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> +<programlisting> +char *stmt = "SELECT * FROM test1 WHERE a = ? AND b = ?"; + +EXEC SQL ALLOCATE DESCRIPTOR outdesc; +EXEC SQL PREPARE foo FROM :stmt; + +EXEC SQL EXECUTE foo USING SQL DESCRIPTOR indesc INTO SQL DESCRIPTOR outdesc; +</programlisting> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>PREPARE</command> is specified in the SQL standard. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="sql-execute"></member> + </simplelist> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-set-autocommit"> + <refnamediv> + <refname>SET AUTOCOMMIT</refname> + <refpurpose>set the autocommit behavior of the current session</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +SET AUTOCOMMIT { = | TO } { ON | OFF } +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>SET AUTOCOMMIT</command> sets the autocommit behavior of + the current database session. By default, embedded SQL programs + are <emphasis>not</emphasis> in autocommit mode, + so <command>COMMIT</command> needs to be issued explicitly when + desired. This command can change the session to autocommit mode, + where each individual statement is committed implicitly. + </para> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>SET AUTOCOMMIT</command> is an extension of PostgreSQL ECPG. + </para> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-set-connection"> + <refnamediv> + <refname>SET CONNECTION</refname> + <refpurpose>select a database connection</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +SET CONNECTION [ TO | = ] <replaceable class="PARAMETER">connection_name</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>SET CONNECTION</command> sets the <quote>current</quote> + database connection, which is the one that all commands use + unless overridden. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">connection_name</replaceable></term> + <listitem> + <para> + A database connection name established by + the <command>CONNECT</command> command. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>DEFAULT</literal></term> + <listitem> + <para> + Set the connection to the default connection. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + +<programlisting> +EXEC SQL SET CONNECTION TO con2; +EXEC SQL SET CONNECTION = con1; +</programlisting> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>SET CONNECTION</command> is specified in the SQL standard. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="ecpg-sql-connect"></member> + <member><xref linkend="ecpg-sql-disconnect"></member> + </simplelist> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-set-descriptor"> + <refnamediv> + <refname>SET DESCRIPTOR</refname> + <refpurpose>set information in an SQL descriptor area</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +SET DESCRIPTOR <replaceable class="PARAMETER">descriptor_name</replaceable> <replaceable class="PARAMETER">descriptor_header_item</replaceable> = <replaceable>value</replaceable> [, ... ] +SET DESCRIPTOR <replaceable class="PARAMETER">descriptor_name</replaceable> VALUE <replaceable class="PARAMETER">number</replaceable> <replaceable class="PARAMETER">descriptor_item</replaceable> = <replaceable>value</replaceable> [, ...] +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>SET DESCRIPTOR</command> populates an SQL descriptor + area with values. The descriptor area is then typically used to + bind parameters in a prepared query execution. + </para> + + <para> + This command has two forms: The first form applies to the + descriptor <quote>header</quote>, which is independent of a + particular datum. The second form assigns values to particular + datums, identified by number. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">descriptor_name</replaceable></term> + <listitem> + <para> + A descriptor name. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">descriptor_header_item</replaceable></term> + <listitem> + <para> + A token identifying which header information item to set. + Only <literal>COUNT</literal>, to set the number of descriptor + items, is currently supported. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">number</replaceable></term> + <listitem> + <para> + The number of the descriptor item to set. The count starts at + 1. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">descriptor_item</replaceable></term> + <listitem> + <para> + A token identifying which item of information to set in the + descriptor. See <xref linkend="ecpg-named-descriptors"> for a + list of supported items. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">value</replaceable></term> + <listitem> + <para> + A value to store into the descriptor item. This can be an SQL + constant or a host variable. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> +<programlisting> +EXEC SQL SET DESCRIPTOR indesc COUNT = 1; +EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = 2; +EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = :val1; +EXEC SQL SET DESCRIPTOR indesc VALUE 2 INDICATOR = :val1, DATA = 'some string'; +EXEC SQL SET DESCRIPTOR indesc VALUE 2 INDICATOR = :val2null, DATA = :val2; +</programlisting> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>SET DESCRIPTOR</command> is specified in the SQL standard. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="ecpg-sql-allocate-descriptor"></member> + <member><xref linkend="ecpg-sql-get-descriptor"></member> + </simplelist> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-type"> + <refnamediv> + <refname>TYPE</refname> + <refpurpose>define a new data type</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +TYPE <replaceable class="PARAMETER">type_name</replaceable> IS <replaceable class="PARAMETER">ctype</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + The <command>TYPE</command> command defines a new C type. It is + equivalent to putting a <literal>typedef</literal> into a declare + section. + </para> + + <para> + This command is only recognized when <command>ecpg</command> is + run with the <option>-c</option> option. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">type_name</replaceable></term> + <listitem> + <para> + The name for the new type. It must be a valid C type name. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">ctype</replaceable></term> + <listitem> + <para> + A C type specification. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + +<programlisting> +EXEC SQL TYPE customer IS + struct + { + varchar name[50]; + int phone; + }; + +EXEC SQL TYPE cust_ind IS + struct ind + { + short name_ind; + short phone_ind; + }; + +EXEC SQL TYPE c IS char reference; +EXEC SQL TYPE ind IS union { int integer; short smallint; }; +EXEC SQL TYPE intarray IS int[AMOUNT]; +EXEC SQL TYPE str IS varchar[BUFFERSIZ]; +EXEC SQL TYPE string IS char[11]; +</programlisting> + + <para> + Here is an example program that uses <command>EXEC SQL + TYPE</command>: +<programlisting> +EXEC SQL WHENEVER SQLERROR SQLPRINT; + +EXEC SQL TYPE tt IS + struct + { + varchar v[256]; + int i; + }; + +EXEC SQL TYPE tt_ind IS + struct ind { + short v_ind; + short i_ind; + }; + +int +main(void) +{ +EXEC SQL BEGIN DECLARE SECTION; + tt t; + tt_ind t_ind; +EXEC SQL END DECLARE SECTION; + + EXEC SQL CONNECT TO testdb AS con1; + + EXEC SQL SELECT current_database(), 256 INTO :t:t_ind LIMIT 1; + + printf("t.v = %s\n", t.v.arr); + printf("t.i = %d\n", t.i); + + printf("t_ind.v_ind = %d\n", t_ind.v_ind); + printf("t_ind.i_ind = %d\n", t_ind.i_ind); + + EXEC SQL DISCONNECT con1; + + return 0; +} +</programlisting> + + The output from this program looks like this: +<screen> +t.v = testdb +t.i = 256 +t_ind.v_ind = 0 +t_ind.i_ind = 0 +</screen> + </para> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + The <command>TYPE</command> command is a PostgreSQL extension. + </para> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-var"> + <refnamediv> + <refname>VAR</refname> + <refpurpose>define a variable</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +VAR <replaceable>varname</replaceable> IS <replaceable>ctype</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + The <command>VAR</command> command defines a host variable. It + is equivalent to an ordinary C variable definition inside a + declare section. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">varname</replaceable></term> + <listitem> + <para> + A C variable name. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">ctype</replaceable></term> + <listitem> + <para> + A C type specification. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + +<programlisting> +EXEC SQL VAR vc IS VARCHAR[10]; +EXEC SQL VAR boolvar IS bool; +</programlisting> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + The <command>VAR</command> command is a PostgreSQL extension. + </para> + </refsect1> + </refentry> + + <refentry id="ecpg-sql-whenever"> + <refnamediv> + <refname>WHENEVER</refname> + <refpurpose>specify the action to be taken when an SQL statement causes a specific class condition to be raised</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +WHENEVER { NOT FOUND | SQLERROR | SQLWARNING } <replaceable class="PARAMETER">action</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + Define a behavior which is called on the special cases (Rows not + found, SQL warnings or errors) in the result of SQL execution. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <para> + See <xref linkend="ecpg-whenever"> for a description of the + parameters. + </para> + </refsect1> + + <refsect1> + <title>Examples</title> + +<programlisting> +EXEC SQL WHENEVER NOT FOUND CONTINUE; +EXEC SQL WHENEVER NOT FOUND DO BREAK; +EXEC SQL WHENEVER SQLWARNING SQLPRINT; +EXEC SQL WHENEVER SQLWARNING DO warn(); +EXEC SQL WHENEVER SQLERROR sqlprint; +EXEC SQL WHENEVER SQLERROR CALL print2(); +EXEC SQL WHENEVER SQLERROR DO handle_error("select"); +EXEC SQL WHENEVER SQLERROR DO sqlnotice(NULL, NONO); +EXEC SQL WHENEVER SQLERROR DO sqlprint(); +EXEC SQL WHENEVER SQLERROR GOTO error_label; +EXEC SQL WHENEVER SQLERROR STOP; +</programlisting> + + <para> + A typical application is the use of <literal>WHENEVER NOT FOUND + BREAK</literal> to handle looping through result sets: +<programlisting> +int +main(void) +{ + EXEC SQL CONNECT TO testdb AS con1; + EXEC SQL ALLOCATE DESCRIPTOR d; + EXEC SQL DECLARE cur CURSOR FOR SELECT current_database(), 'hoge', 256; + EXEC SQL OPEN cur; + + /* when end of result set reached, break out of while loop */ + EXEC SQL WHENEVER NOT FOUND DO BREAK; + + while (1) + { + EXEC SQL FETCH NEXT FROM cur INTO SQL DESCRIPTOR d; + ... + } + + EXEC SQL CLOSE cur; + EXEC SQL COMMIT; + EXEC SQL DEALLOCATE DESCRIPTOR d; + EXEC SQL DISCONNECT ALL; + + return 0; +} +</programlisting> + </para> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>WHENEVER</command> is specified in the SQL standard, but + most of the actions are PostgreSQL extensions. + </para> + </refsect1> + </refentry> </sect1> <sect1 id="ecpg-informix-compat"> - <title><productname>Informix</productname> compatibility mode</title> + <title><productname>Informix</productname> Compatibility Mode</title> <para> - ecpg can be run in a so-called <firstterm>Informix compatibility mode</>. If + <command>ecpg</command> can be run in a so-called <firstterm>Informix compatibility mode</>. If this mode is active, it tries to behave as if it were the <productname>Informix</productname> precompiler for <productname>Informix</productname> E/SQL. Generally spoken this will allow you to use the dollar sign instead of the <literal>EXEC SQL</> primitive to introduce embedded SQL commands.: <programlisting> - $int j = 3; - $CONNECT TO :dbname; - $CREATE TABLE test(i INT PRIMARY KEY, j INT); - $INSERT INTO test(i, j) VALUES (7, :j); - $COMMIT; +$int j = 3; +$CONNECT TO :dbname; +$CREATE TABLE test(i INT PRIMARY KEY, j INT); +$INSERT INTO test(i, j) VALUES (7, :j); +$COMMIT; </programlisting> </para> + + <note> + <para> + There must not be any white space between the <literal>$</literal> + and a following preprocessor directive, that is, + <literal>include</literal>, <literal>define</literal>, <literal>ifdef</literal>, + etc. Otherwise, the preprocessor will parse the token as a host + variable. + </para> + </note> + <para> - There are two compatibility modes: INFORMIX, INFORMIX_SE + There are two compatibility modes: <literal>INFORMIX</>, <literal>INFORMIX_SE</> </para> <para> When linking programs that use this compatibility mode, remember to link - against <literal>libcompat</> that is shipped with ecpg. + against <literal>libcompat</> that is shipped with ECPG. </para> <para> Besides the previously explained syntactic sugar, the <productname>Informix</productname> compatibility mode ports some functions for input, output and transformation of data as - well as embedded SQL statements known from E/SQL to ecpg. + well as embedded SQL statements known from E/SQL to ECPG. </para> <para> <productname>Informix</productname> compatibility mode is closely connected to the pgtypeslib library - of ecpg. pgtypeslib maps SQL data types to data types within the C host + of ECPG. pgtypeslib maps SQL data types to data types within the C host program and most of the additional functions of the <productname>Informix</productname> compatibility mode allow you to operate on those C host program types. Note however that the extent of the compatibility is limited. It does not try to copy <productname>Informix</productname> @@ -2888,27 +7870,27 @@ struct sqlname some of the data types are different. For example, <productname>PostgreSQL's</productname> datetime and interval types do not know about ranges like for example <literal>YEAR TO MINUTE</> so you won't - find support in ecpg for that either. + find support in ECPG for that either. </para> - <sect2> - <title>Additional types</title> + <sect2 id="ecpg-informix-types"> + <title>Additional Types</title> <para> The Informix-special "string" pseudo-type for storing right-trimmed character string data is now supported in Informix-mode without using <literal>typedef</literal>. In fact, in Informix-mode, ECPG refuses to process source files that contain <literal>typedef sometype string;</literal> <programlisting> - EXEC SQL BEGIN DECLARE SECTION; - string userid; /* this variable will contain trimmed data */ - EXEC SQL END DECLARE SECTION; +EXEC SQL BEGIN DECLARE SECTION; +string userid; /* this variable will contain trimmed data */ +EXEC SQL END DECLARE SECTION; - EXEC SQL FETCH MYCUR INTO :userid; +EXEC SQL FETCH MYCUR INTO :userid; </programlisting> </para> </sect2> - <sect2> - <title>Additional/missing embedded SQL statements</title> + <sect2 id="ecpg-informix-statements"> + <title>Additional/Missing Embedded SQL Statements</title> <para> <variablelist> <varlistentry> @@ -2916,10 +7898,10 @@ struct sqlname <listitem> <para> This statement closes the current connection. In fact, this is a - synonym for ecpg's <literal>DISCONNECT CURRENT</>.: + synonym for ECPG's <literal>DISCONNECT CURRENT</>.: <programlisting> - $CLOSE DATABASE; /* close the current connection */ - EXEC SQL CLOSE DATABASE; +$CLOSE DATABASE; /* close the current connection */ +EXEC SQL CLOSE DATABASE; </programlisting> </para> </listitem> @@ -2929,11 +7911,11 @@ struct sqlname <listitem> <para> Due to the differences how ECPG works compared to Informix's ESQL/C (i.e. which steps - are purely grammar transformations and which steps rely on the underlying runtime library) + are purely grammar transformations and which steps rely on the underlying run-time library) there is no <literal>FREE cursor_name</> statement in ECPG. This is because in ECPG, <literal>DECLARE CURSOR</literal> doesn't translate to a function call into - the runtime library that uses to the cursor name. This means that there's no runtime - bookkeeping of SQL cursors in the ECPG runtime library, only in the PostgreSQL server. + the run-time library that uses to the cursor name. This means that there's no run-time + bookkeeping of SQL cursors in the ECPG run-time library, only in the PostgreSQL server. </para> </listitem> </varlistentry> @@ -2942,14 +7924,14 @@ struct sqlname <listitem> <para> <literal>FREE statement_name</> is a synonym for <literal>DEALLOCATE PREPARE statement_name</>. - </para> - </listitem> + </para> + </listitem> </varlistentry> </variablelist> </para> </sect2> - <sect2> + <sect2 id="ecpg-informix-sqlda"> <title>Informix-compatible SQLDA Descriptor Areas</title> <para> Informix-compatible mode supports a different structure than the one described in @@ -2957,36 +7939,35 @@ struct sqlname <programlisting> struct sqlvar_compat { - short sqltype; - int sqllen; - char *sqldata; - short *sqlind; - char *sqlname; - char *sqlformat; - short sqlitype; - short sqlilen; - char *sqlidata; - int sqlxid; - char *sqltypename; - short sqltypelen; - short sqlownerlen; - short sqlsourcetype; - char *sqlownername; - int sqlsourceid; - - char *sqlilongdata; - int sqlflags; - void *sqlreserved; + short sqltype; + int sqllen; + char *sqldata; + short *sqlind; + char *sqlname; + char *sqlformat; + short sqlitype; + short sqlilen; + char *sqlidata; + int sqlxid; + char *sqltypename; + short sqltypelen; + short sqlownerlen; + short sqlsourcetype; + char *sqlownername; + int sqlsourceid; + char *sqlilongdata; + int sqlflags; + void *sqlreserved; }; struct sqlda_compat { - short sqld; - struct sqlvar_compat *sqlvar; - char desc_name[19]; - short desc_occ; - struct sqlda_compat *desc_next; - void *reserved; + short sqld; + struct sqlvar_compat *sqlvar; + char desc_name[19]; + short desc_occ; + struct sqlda_compat *desc_next; + void *reserved; }; typedef struct sqlvar_compat sqlvar_t; @@ -2996,7 +7977,7 @@ typedef struct sqlda_compat sqlda_t; <para> The global properties are: - <variablelist> + <variablelist> <varlistentry> <term><literal>sqld</></term> @@ -3008,7 +7989,7 @@ typedef struct sqlda_compat sqlda_t; </varlistentry> <varlistentry> - <term><literal>sqlvar</></term> + <term><literal>sqlvar</></term> <listitem> <para> Pointer to the per-field properties. @@ -3020,7 +8001,7 @@ typedef struct sqlda_compat sqlda_t; <term><literal>desc_name</></term> <listitem> <para> - Unused, filled with zerobytes. + Unused, filled with zero-bytes. </para> </listitem> </varlistentry> @@ -3038,7 +8019,7 @@ typedef struct sqlda_compat sqlda_t; <term><literal>desc_next</></term> <listitem> <para> - Pointer to the next SQLDA structure if the resultset contains more than one records. + Pointer to the next SQLDA structure if the result set contains more than one record. </para> </listitem> </varlistentry> @@ -3083,15 +8064,15 @@ typedef struct sqlda_compat sqlda_t; Pointer to the field data. The pointer is of <literal>char *</literal> type, the data pointed by it is in a binary format. Example: <programlisting> - int intval; +int intval; - switch (sqldata->sqlvar[i].sqltype) - { - case SQLINTEGER: +switch (sqldata->sqlvar[i].sqltype) +{ + case SQLINTEGER: intval = *(int *)sqldata->sqlvar[i].sqldata; break; - ... - } + ... +} </programlisting> </para> </listitem> @@ -3102,12 +8083,12 @@ typedef struct sqlda_compat sqlda_t; <listitem> <para> Pointer to the NULL indicator. If returned by DESCRIBE or FETCH then it's always a valid pointer. - If used as input for <literal>EXECUTE ... USING sqlda;</literal> then NULL-pointer value means + If used as input for <literal>EXECUTE ... USING sqlda;</literal> then NULL-pointer value means that the value for this field is non-NULL. Otherwise a valid pointer and <literal>sqlitype</literal> has to be properly set. Example: <programlisting> - if (*(int2 *)sqldata->sqlvar[i].sqlind != 0) - printf("value is NULL\n"); +if (*(int2 *)sqldata->sqlvar[i].sqlind != 0) + printf("value is NULL\n"); </programlisting> </para> </listitem> @@ -3126,7 +8107,7 @@ typedef struct sqlda_compat sqlda_t; <term><literal>sqlformat</></term> <listitem> <para> - Reserved in Informix, value of PQfformat() for the field. + Reserved in Informix, value of <function>PQfformat()</> for the field. </para> </listitem> </varlistentry> @@ -3136,7 +8117,7 @@ typedef struct sqlda_compat sqlda_t; <listitem> <para> Type of the NULL indicator data. It's always SQLSMINT when returning data from the server. - When the <literal>SQLDA</literal> is used for a parametrized query, the data is treated + When the <literal>SQLDA</literal> is used for a parametrized query, the data is treated according to the set type. </para> </listitem> @@ -3155,20 +8136,20 @@ typedef struct sqlda_compat sqlda_t; <term><literal>sqlxid</></term> <listitem> <para> - Extended type of the field, result of PQftype(). + Extended type of the field, result of <function>PQftype()</>. </para> </listitem> </varlistentry> <varlistentry> <term><literal>sqltypename</></term> - <term><literal>sqltypelen</></term> + <term><literal>sqltypelen</></term> <term><literal>sqlownerlen</></term> <term><literal>sqlsourcetype</></term> - <term><literal>sqlownername</></term> - <term><literal>sqlsourceid</></term> - <term><literal>sqlflags</></term> - <term><literal>sqlreserved</></term> + <term><literal>sqlownername</></term> + <term><literal>sqlsourceid</></term> + <term><literal>sqlflags</></term> + <term><literal>sqlreserved</></term> <listitem> <para> Unused. @@ -3227,8 +8208,8 @@ EXEC SQL INCLUDE sqlda.h; </para> </sect2> - <sect2> - <title>Additional functions</title> + <sect2 id="ecpg-informix-functions"> + <title>Additional Functions</title> <para> <variablelist> <varlistentry> @@ -3243,9 +8224,9 @@ int decadd(decimal *arg1, decimal *arg2, decimal *sum); (<literal>arg1</>), a pointer to the second operand of type decimal (<literal>arg2</>) and a pointer to a value of type decimal that will contain the sum (<literal>sum</>). On success, the function returns 0. - ECPG_INFORMIX_NUM_OVERFLOW is returned in case of overflow and - ECPG_INFORMIX_NUM_UNDERFLOW in case of underflow. -1 is returned for - other failures and errno is set to the respective errno number of the + <symbol>ECPG_INFORMIX_NUM_OVERFLOW</> is returned in case of overflow and + <symbol>ECPG_INFORMIX_NUM_UNDERFLOW</> in case of underflow. -1 is returned for + other failures and <varname>errno</> is set to the respective <varname>errno</> number of the pgtypeslib. </para> </listitem> @@ -3481,14 +8462,14 @@ int dectoasc(decimal *np, char *cp, int len, int right) <literal>right</> to -1 indicates that all available decimal digits should be included in the output. If the length of the output buffer, which is indicated by <literal>len</> is not sufficient to hold the - textual representation including the trailing NUL character, only a + textual representation including the trailing zero byte, only a single <literal>*</> character is stored in the result and -1 is returned. </para> <para> The function returns either -1 if the buffer <literal>cp</> was too small or <literal>ECPG_INFORMIX_OUT_OF_MEMORY</> if memory was - exhausted. + exhausted. </para> </listitem> </varlistentry> @@ -3530,9 +8511,9 @@ int dectoint(decimal *np, int *ip); is returned. </para> <para> - Note that the ecpg implementation differs from the <productname>Informix</productname> + Note that the ECPG implementation differs from the <productname>Informix</productname> implementation. <productname>Informix</productname> limits an integer to the range from -32767 to - 32767, while the limits in the ecpg implementation depend on the + 32767, while the limits in the ECPG implementation depend on the architecture (<literal>-INT_MAX .. INT_MAX</>). </para> </listitem> @@ -3556,9 +8537,9 @@ int dectolong(decimal *np, long *lngp); is returned. </para> <para> - Note that the ecpg implementation differs from the <productname>Informix</productname> + Note that the ECPG implementation differs from the <productname>Informix</productname> implementation. <productname>Informix</productname> limits a long integer to the range from - -2,147,483,647 to 2,147,483,647, while the limits in the ecpg + -2,147,483,647 to 2,147,483,647, while the limits in the ECPG implementation depend on the architecture (<literal>-LONG_MAX .. LONG_MAX</>). </para> @@ -3576,7 +8557,7 @@ int rdatestr(date d, char *str); The function receives two arguments, the first one is the date to convert (<literal>d</> and the second one is a pointer to the target string. The output format is always <literal>yyyy-mm-dd</>, so you need - to allocate at least 11 bytes (including the NUL-terminator) for the + to allocate at least 11 bytes (including the zero-byte terminator) for the string. </para> <para> @@ -3584,9 +8565,9 @@ int rdatestr(date d, char *str); error. </para> <para> - Note that ecpg's implementation differs from the <productname>Informix</productname> + Note that ECPG's implementation differs from the <productname>Informix</productname> implementation. In <productname>Informix</productname> the format can be influenced by setting - environment variables. In ecpg however, you cannot change the output + environment variables. In ECPG however, you cannot change the output format. </para> </listitem> @@ -3881,11 +8862,12 @@ dtcvfmtasc(char *inbuf, char *fmtstr, timestamp *dtvalue) </synopsis> The function receives the string to parse (<literal>inbuf</>), the format mask to use (<literal>fmtstr</>) and a pointer to the timestamp - variable that should hold the result of the operation (<literal>ts</>). + variable that should hold the result of the operation + (<literal>dtvalue</>). </para> <para> - This functions is implemented by means of the <xref - linkend="PGTYPEStimestampdefmtasc">. See the documentation + This function is implemented by means of the <xref + linkend="PGTYPEStimestampdefmtasc"> function. See the documentation there for a list of format specifiers that can be used. </para> <para> @@ -4284,8 +9266,8 @@ risnull(CINTTYPE, (char *) &i); </para> </sect2> - <sect2> - <title>Additional constants</title> + <sect2 id="ecpg-informix-constants"> + <title>Additional Constants</title> <para> Note that all constants here describe errors and all of them are defined to represent negative values. In the descriptions of the different @@ -4299,7 +9281,7 @@ risnull(CINTTYPE, (char *) &i); <listitem> <para> Functions return this value if an overflow occurred in a - calculation. Internally it is defined to -1200 (the <productname>Informix</productname> + calculation. Internally it is defined as -1200 (the <productname>Informix</productname> definition). </para> </listitem> @@ -4310,7 +9292,7 @@ risnull(CINTTYPE, (char *) &i); <listitem> <para> Functions return this value if an underflow occurred in a calculation. - Internally it is defined to -1201 (the <productname>Informix</productname> definition). + Internally it is defined as -1201 (the <productname>Informix</productname> definition). </para> </listitem> </varlistentry> @@ -4320,7 +9302,7 @@ risnull(CINTTYPE, (char *) &i); <listitem> <para> Functions return this value if an attempt to divide by zero is - observed. Internally it is defined to -1202 (the <productname>Informix</productname> definition). + observed. Internally it is defined as -1202 (the <productname>Informix</productname> definition). </para> </listitem> </varlistentry> @@ -4330,7 +9312,7 @@ risnull(CINTTYPE, (char *) &i); <listitem> <para> Functions return this value if a bad value for a year was found while - parsing a date. Internally it is defined to -1204 (the <productname>Informix</productname> + parsing a date. Internally it is defined as -1204 (the <productname>Informix</productname> definition). </para> </listitem> @@ -4341,7 +9323,7 @@ risnull(CINTTYPE, (char *) &i); <listitem> <para> Functions return this value if a bad value for a month was found while - parsing a date. Internally it is defined to -1205 (the <productname>Informix</productname> + parsing a date. Internally it is defined as -1205 (the <productname>Informix</productname> definition). </para> </listitem> @@ -4352,7 +9334,7 @@ risnull(CINTTYPE, (char *) &i); <listitem> <para> Functions return this value if a bad value for a day was found while - parsing a date. Internally it is defined to -1206 (the <productname>Informix</productname> + parsing a date. Internally it is defined as -1206 (the <productname>Informix</productname> definition). </para> </listitem> @@ -4364,7 +9346,7 @@ risnull(CINTTYPE, (char *) &i); <para> Functions return this value if a parsing routine needs a short date representation but did not get the date string in the right length. - Internally it is defined to -1209 (the <productname>Informix</productname> definition). + Internally it is defined as -1209 (the <productname>Informix</productname> definition). </para> </listitem> </varlistentry> @@ -4373,7 +9355,8 @@ risnull(CINTTYPE, (char *) &i); <term><literal>ECPG_INFORMIX_DATE_CONVERT</></term> <listitem> <para> - Functions return this value if Internally it is defined to -1210 (the + Functions return this value if an error occurred during date + formatting. Internally it is defined as -1210 (the <productname>Informix</productname> definition). </para> </listitem> @@ -4383,7 +9366,8 @@ risnull(CINTTYPE, (char *) &i); <term><literal>ECPG_INFORMIX_OUT_OF_MEMORY</></term> <listitem> <para> - Functions return this value if Internally it is defined to -1211 (the + Functions return this value if memory was exhausted during + their operation. Internally it is defined as -1211 (the <productname>Informix</productname> definition). </para> </listitem> @@ -4395,7 +9379,7 @@ risnull(CINTTYPE, (char *) &i); <para> Functions return this value if a parsing routine was supposed to get a format mask (like <literal>mmddyy</>) but not all fields were listed - correctly. Internally it is defined to -1212 (the <productname>Informix</productname> definition). + correctly. Internally it is defined as -1212 (the <productname>Informix</productname> definition). </para> </listitem> </varlistentry> @@ -4408,7 +9392,7 @@ risnull(CINTTYPE, (char *) &i); the textual representation for a numeric value because it contains errors or if a routine cannot complete a calculation involving numeric variables because at least one of the numeric variables is invalid. - Internally it is defined to -1213 (the <productname>Informix</productname> definition). + Internally it is defined as -1213 (the <productname>Informix</productname> definition). </para> </listitem> </varlistentry> @@ -4417,7 +9401,8 @@ risnull(CINTTYPE, (char *) &i); <term><literal>ECPG_INFORMIX_BAD_EXPONENT</></term> <listitem> <para> - Functions return this value if Internally it is defined to -1216 (the + Functions return this value if a parsing routine cannot parse + an exponent. Internally it is defined as -1216 (the <productname>Informix</productname> definition). </para> </listitem> @@ -4427,7 +9412,8 @@ risnull(CINTTYPE, (char *) &i); <term><literal>ECPG_INFORMIX_BAD_DATE</></term> <listitem> <para> - Functions return this value if Internally it is defined to -1218 (the + Functions return this value if a parsing routine cannot parse + a date. Internally it is defined as -1218 (the <productname>Informix</productname> definition). </para> </listitem> @@ -4437,7 +9423,8 @@ risnull(CINTTYPE, (char *) &i); <term><literal>ECPG_INFORMIX_EXTRA_CHARS</></term> <listitem> <para> - Functions return this value if Internally it is defined to -1264 (the + Functions return this value if a parsing routine is passed extra + characters is cannot parse. Internally it is defined as -1264 (the <productname>Informix</productname> definition). </para> </listitem> @@ -4447,933 +9434,6 @@ risnull(CINTTYPE, (char *) &i); </sect2> </sect1> - <sect1 id="ecpg-errors"> - <title>Error Handling</title> - - <para> - This section describes how you can handle exceptional conditions - and warnings in an embedded SQL program. There are several - nonexclusive facilities for this. - </para> - - <sect2> - <title>Setting Callbacks</title> - - <para> - One simple method to catch errors and warnings is to set a - specific action to be executed whenever a particular condition - occurs. In general: -<programlisting> -EXEC SQL WHENEVER <replaceable>condition</replaceable> <replaceable>action</replaceable>; -</programlisting> - </para> - - <para> - <replaceable>condition</replaceable> can be one of the following: - - <variablelist> - <varlistentry> - <term><literal>SQLERROR</literal></term> - <listitem> - <para> - The specified action is called whenever an error occurs during - the execution of an SQL statement. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><literal>SQLWARNING</literal></term> - <listitem> - <para> - The specified action is called whenever a warning occurs - during the execution of an SQL statement. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><literal>NOT FOUND</literal></term> - <listitem> - <para> - The specified action is called whenever an SQL statement - retrieves or affects zero rows. (This condition is not an - error, but you might be interested in handling it specially.) - </para> - </listitem> - </varlistentry> - </variablelist> - </para> - - <para> - <replaceable>action</replaceable> can be one of the following: - - <variablelist> - <varlistentry> - <term><literal>CONTINUE</literal></term> - <listitem> - <para> - This effectively means that the condition is ignored. This is - the default. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><literal>GOTO <replaceable>label</replaceable></literal></term> - <term><literal>GO TO <replaceable>label</replaceable></literal></term> - <listitem> - <para> - Jump to the specified label (using a C <literal>goto</literal> - statement). - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><literal>SQLPRINT</literal></term> - <listitem> - <para> - Print a message to standard error. This is useful for simple - programs or during prototyping. The details of the message - cannot be configured. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><literal>STOP</literal></term> - <listitem> - <para> - Call <literal>exit(1)</literal>, which will terminate the - program. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><literal>DO BREAK</literal></term> - <listitem> - <para> - Execute the C statement <literal>break</literal>. This should - only be used in loops or <literal>switch</literal> statements. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><literal>CALL <replaceable>name</replaceable> (<replaceable>args</replaceable>)</literal></term> - <term><literal>DO <replaceable>name</replaceable> (<replaceable>args</replaceable>)</literal></term> - <listitem> - <para> - Call the specified C functions with the specified arguments. - </para> - </listitem> - </varlistentry> - </variablelist> - - The SQL standard only provides for the actions - <literal>CONTINUE</literal> and <literal>GOTO</literal> (and - <literal>GO TO</literal>). - </para> - - <para> - Here is an example that you might want to use in a simple program. - It prints a simple message when a warning occurs and aborts the - program when an error happens: -<programlisting> -EXEC SQL WHENEVER SQLWARNING SQLPRINT; -EXEC SQL WHENEVER SQLERROR STOP; -</programlisting> - </para> - - <para> - The statement <literal>EXEC SQL WHENEVER</literal> is a directive - of the SQL preprocessor, not a C statement. The error or warning - actions that it sets apply to all embedded SQL statements that - appear below the point where the handler is set, unless a - different action was set for the same condition between the first - <literal>EXEC SQL WHENEVER</literal> and the SQL statement causing - the condition, regardless of the flow of control in the C program. - So neither of the two following C program excerpts will have the - desired effect: -<programlisting> -/* - * WRONG - */ -int main(int argc, char *argv[]) -{ - ... - if (verbose) { - EXEC SQL WHENEVER SQLWARNING SQLPRINT; - } - ... - EXEC SQL SELECT ...; - ... -} -</programlisting> - -<programlisting> -/* - * WRONG - */ -int main(int argc, char *argv[]) -{ - ... - set_error_handler(); - ... - EXEC SQL SELECT ...; - ... -} - -static void set_error_handler(void) -{ - EXEC SQL WHENEVER SQLERROR STOP; -} -</programlisting> - </para> - </sect2> - - <sect2> - <title>sqlca</title> - - <para> - For more powerful error handling, the embedded SQL interface - provides a global variable with the name <varname>sqlca</varname> - that has the following structure: -<programlisting> -struct -{ - char sqlcaid[8]; - long sqlabc; - long sqlcode; - struct - { - int sqlerrml; - char sqlerrmc[SQLERRMC_LEN]; - } sqlerrm; - char sqlerrp[8]; - long sqlerrd[6]; - char sqlwarn[8]; - char sqlstate[5]; -} sqlca; -</programlisting> - (In a multithreaded program, every thread automatically gets its - own copy of <varname>sqlca</varname>. This works similarly to the - handling of the standard C global variable - <varname>errno</varname>.) - </para> - - <para> - <varname>sqlca</varname> covers both warnings and errors. If - multiple warnings or errors occur during the execution of a - statement, then <varname>sqlca</varname> will only contain - information about the last one. - </para> - - <para> - If no error occurred in the last <acronym>SQL</acronym> statement, - <literal>sqlca.sqlcode</literal> will be 0 and - <literal>sqlca.sqlstate</literal> will be - <literal>"00000"</literal>. If a warning or error occurred, then - <literal>sqlca.sqlcode</literal> will be negative and - <literal>sqlca.sqlstate</literal> will be different from - <literal>"00000"</literal>. A positive - <literal>sqlca.sqlcode</literal> indicates a harmless condition, - such as that the last query returned zero rows. - <literal>sqlcode</literal> and <literal>sqlstate</literal> are two - different error code schemes; details appear below. - </para> - - <para> - If the last SQL statement was successful, then - <literal>sqlca.sqlerrd[1]</literal> contains the OID of the - processed row, if applicable, and - <literal>sqlca.sqlerrd[2]</literal> contains the number of - processed or returned rows, if applicable to the command. - </para> - - <para> - In case of an error or warning, - <literal>sqlca.sqlerrm.sqlerrmc</literal> will contain a string - that describes the error. The field - <literal>sqlca.sqlerrm.sqlerrml</literal> contains the length of - the error message that is stored in - <literal>sqlca.sqlerrm.sqlerrmc</literal> (the result of - <function>strlen()</function>, not really interesting for a C - programmer). Note that some messages are too long to fit in the - fixed-size <literal>sqlerrmc</literal> array; they will be truncated. - </para> - - <para> - In case of a warning, <literal>sqlca.sqlwarn[2]</literal> is set - to <literal>W</literal>. (In all other cases, it is set to - something different from <literal>W</literal>.) If - <literal>sqlca.sqlwarn[1]</literal> is set to - <literal>W</literal>, then a value was truncated when it was - stored in a host variable. <literal>sqlca.sqlwarn[0]</literal> is - set to <literal>W</literal> if any of the other elements are set - to indicate a warning. - </para> - - <para> - The fields <structfield>sqlcaid</structfield>, - <structfield>sqlcabc</structfield>, - <structfield>sqlerrp</structfield>, and the remaining elements of - <structfield>sqlerrd</structfield> and - <structfield>sqlwarn</structfield> currently contain no useful - information. - </para> - - <para> - The structure <varname>sqlca</varname> is not defined in the SQL - standard, but is implemented in several other SQL database - systems. The definitions are similar at the core, but if you want - to write portable applications, then you should investigate the - different implementations carefully. - </para> - </sect2> - - <sect2> - <title><literal>SQLSTATE</literal> vs <literal>SQLCODE</literal></title> - - <para> - The fields <literal>sqlca.sqlstate</literal> and - <literal>sqlca.sqlcode</literal> are two different schemes that - provide error codes. Both are derived from the SQL standard, but - <literal>SQLCODE</literal> has been marked deprecated in the SQL-92 - edition of the standard and has been dropped in later editions. - Therefore, new applications are strongly encouraged to use - <literal>SQLSTATE</literal>. - </para> - - <para> - <literal>SQLSTATE</literal> is a five-character array. The five - characters contain digits or upper-case letters that represent - codes of various error and warning conditions. - <literal>SQLSTATE</literal> has a hierarchical scheme: the first - two characters indicate the general class of the condition, the - last three characters indicate a subclass of the general - condition. A successful state is indicated by the code - <literal>00000</literal>. The <literal>SQLSTATE</literal> codes are for - the most part defined in the SQL standard. The - <productname>PostgreSQL</productname> server natively supports - <literal>SQLSTATE</literal> error codes; therefore a high degree - of consistency can be achieved by using this error code scheme - throughout all applications. For further information see - <xref linkend="errcodes-appendix">. - </para> - - <para> - <literal>SQLCODE</literal>, the deprecated error code scheme, is a - simple integer. A value of 0 indicates success, a positive value - indicates success with additional information, a negative value - indicates an error. The SQL standard only defines the positive - value +100, which indicates that the last command returned or - affected zero rows, and no specific negative values. Therefore, - this scheme can only achieve poor portability and does not have a - hierarchical code assignment. Historically, the embedded SQL - processor for <productname>PostgreSQL</productname> has assigned - some specific <literal>SQLCODE</literal> values for its use, which - are listed below with their numeric value and their symbolic name. - Remember that these are not portable to other SQL implementations. - To simplify the porting of applications to the - <literal>SQLSTATE</literal> scheme, the corresponding - <literal>SQLSTATE</literal> is also listed. There is, however, no - one-to-one or one-to-many mapping between the two schemes (indeed - it is many-to-many), so you should consult the global - <literal>SQLSTATE</literal> listing in <xref linkend="errcodes-appendix"> - in each case. - </para> - - <para> - These are the assigned <literal>SQLCODE</literal> values: - - <variablelist> - <varlistentry> - <term>-12 (<symbol>ECPG_OUT_OF_MEMORY</symbol>)</term> - <listitem> - <para> - Indicates that your virtual memory is exhausted. (SQLSTATE - YE001) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-200 (<symbol>ECPG_UNSUPPORTED</symbol>)</term> - <listitem> - <para> - Indicates the preprocessor has generated something that the - library does not know about. Perhaps you are running - incompatible versions of the preprocessor and the - library. (SQLSTATE YE002) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-201 (<symbol>ECPG_TOO_MANY_ARGUMENTS</symbol>)</term> - <listitem> - <para> - This means that the command specified more host variables than - the command expected. (SQLSTATE 07001 or 07002) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-202 (<symbol>ECPG_TOO_FEW_ARGUMENTS</symbol>)</term> - <listitem> - <para> - This means that the command specified fewer host variables than - the command expected. (SQLSTATE 07001 or 07002) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-203 (<symbol>ECPG_TOO_MANY_MATCHES</symbol>)</term> - <listitem> - <para> - This means a query has returned multiple rows but the statement - was only prepared to store one result row (for example, because - the specified variables are not arrays). (SQLSTATE 21000) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-204 (<symbol>ECPG_INT_FORMAT</symbol>)</term> - <listitem> - <para> - The host variable is of type <type>int</type> and the datum in - the database is of a different type and contains a value that - cannot be interpreted as an <type>int</type>. The library uses - <function>strtol()</function> for this conversion. (SQLSTATE - 42804) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-205 (<symbol>ECPG_UINT_FORMAT</symbol>)</term> - <listitem> - <para> - The host variable is of type <type>unsigned int</type> and the - datum in the database is of a different type and contains a - value that cannot be interpreted as an <type>unsigned - int</type>. The library uses <function>strtoul()</function> - for this conversion. (SQLSTATE 42804) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-206 (<symbol>ECPG_FLOAT_FORMAT</symbol>)</term> - <listitem> - <para> - The host variable is of type <type>float</type> and the datum - in the database is of another type and contains a value that - cannot be interpreted as a <type>float</type>. The library - uses <function>strtod()</function> for this conversion. - (SQLSTATE 42804) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-207 (<symbol>ECPG_CONVERT_BOOL</symbol>)</term> - <listitem> - <para> - This means the host variable is of type <type>bool</type> and - the datum in the database is neither <literal>'t'</> nor - <literal>'f'</>. (SQLSTATE 42804) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-208 (<symbol>ECPG_EMPTY</symbol>)</term> - <listitem> - <para> - The statement sent to the <productname>PostgreSQL</productname> - server was empty. (This cannot normally happen in an embedded - SQL program, so it might point to an internal error.) (SQLSTATE - YE002) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-209 (<symbol>ECPG_MISSING_INDICATOR</symbol>)</term> - <listitem> - <para> - A null value was returned and no null indicator variable was - supplied. (SQLSTATE 22002) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-210 (<symbol>ECPG_NO_ARRAY</symbol>)</term> - <listitem> - <para> - An ordinary variable was used in a place that requires an - array. (SQLSTATE 42804) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-211 (<symbol>ECPG_DATA_NOT_ARRAY</symbol>)</term> - <listitem> - <para> - The database returned an ordinary variable in a place that - requires array value. (SQLSTATE 42804) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-220 (<symbol>ECPG_NO_CONN</symbol>)</term> - <listitem> - <para> - The program tried to access a connection that does not exist. - (SQLSTATE 08003) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-221 (<symbol>ECPG_NOT_CONN</symbol>)</term> - <listitem> - <para> - The program tried to access a connection that does exist but is - not open. (This is an internal error.) (SQLSTATE YE002) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-230 (<symbol>ECPG_INVALID_STMT</symbol>)</term> - <listitem> - <para> - The statement you are trying to use has not been prepared. - (SQLSTATE 26000) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-240 (<symbol>ECPG_UNKNOWN_DESCRIPTOR</symbol>)</term> - <listitem> - <para> - The descriptor specified was not found. The statement you are - trying to use has not been prepared. (SQLSTATE 33000) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-241 (<symbol>ECPG_INVALID_DESCRIPTOR_INDEX</symbol>)</term> - <listitem> - <para> - The descriptor index specified was out of range. (SQLSTATE - 07009) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-242 (<symbol>ECPG_UNKNOWN_DESCRIPTOR_ITEM</symbol>)</term> - <listitem> - <para> - An invalid descriptor item was requested. (This is an internal - error.) (SQLSTATE YE002) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-243 (<symbol>ECPG_VAR_NOT_NUMERIC</symbol>)</term> - <listitem> - <para> - During the execution of a dynamic statement, the database - returned a numeric value and the host variable was not numeric. - (SQLSTATE 07006) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-244 (<symbol>ECPG_VAR_NOT_CHAR</symbol>)</term> - <listitem> - <para> - During the execution of a dynamic statement, the database - returned a non-numeric value and the host variable was numeric. - (SQLSTATE 07006) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-400 (<symbol>ECPG_PGSQL</symbol>)</term> - <listitem> - <para> - Some error caused by the <productname>PostgreSQL</productname> - server. The message contains the error message from the - <productname>PostgreSQL</productname> server. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-401 (<symbol>ECPG_TRANS</symbol>)</term> - <listitem> - <para> - The <productname>PostgreSQL</productname> server signaled that - we cannot start, commit, or rollback the transaction. - (SQLSTATE 08007) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-402 (<symbol>ECPG_CONNECT</symbol>)</term> - <listitem> - <para> - The connection attempt to the database did not succeed. - (SQLSTATE 08001) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>100 (<symbol>ECPG_NOT_FOUND</symbol>)</term> - <listitem> - <para> - This is a harmless condition indicating that the last command - retrieved or processed zero rows, or that you are at the end of - the cursor. (SQLSTATE 02000) - </para> - </listitem> - </varlistentry> - </variablelist> - </para> - </sect2> - </sect1> - - <sect1 id="ecpg-preproc"> - <title>Preprocessor directives</title> - - <sect2> - <title>Including files</title> - - <para> - To include an external file into your embedded SQL program, use: -<programlisting> -EXEC SQL INCLUDE <replaceable>filename</replaceable>; -</programlisting> - The embedded SQL preprocessor will look for a file named - <literal><replaceable>filename</replaceable>.h</literal>, - preprocess it, and include it in the resulting C output. Thus, - embedded SQL statements in the included file are handled correctly. - </para> - - <para> - Note that this is <emphasis>not</emphasis> the same as: -<programlisting> -#include <<replaceable>filename</replaceable>.h> -</programlisting> - because this file would not be subject to SQL command preprocessing. - Naturally, you can continue to use the C - <literal>#include</literal> directive to include other header - files. - </para> - - <note> - <para> - The include file name is case-sensitive, even though the rest of - the <literal>EXEC SQL INCLUDE</literal> command follows the normal - SQL case-sensitivity rules. - </para> - </note> - </sect2> - - <sect2> - <title>The #define and #undef directives</title> - <para> - Similar to the directive <literal>#define</literal> that is known from C, - embedded SQL has a similar concept: -<programlisting> -EXEC SQL DEFINE <replaceable>name</>; -EXEC SQL DEFINE <replaceable>name</> <replaceable>value</>; -</programlisting> - So you can define a name: -<programlisting> -EXEC SQL DEFINE HAVE_FEATURE; -</programlisting> - And you can also define constants: -<programlisting> -EXEC SQL DEFINE MYNUMBER 12; -EXEC SQL DEFINE MYSTRING 'abc'; -</programlisting> - Use <literal>undef</> to remove a previous definition: -<programlisting> -EXEC SQL UNDEF MYNUMBER; -</programlisting> - </para> - - <para> - Of course you can continue to use the C versions <literal>#define</literal> - and <literal>#undef</literal> in your embedded SQL program. The difference - is where your defined values get evaluated. If you use <literal>EXEC SQL - DEFINE</> then the ecpg preprocessor evaluates the defines and substitutes - the values. For example if you write: -<programlisting> -EXEC SQL DEFINE MYNUMBER 12; -... -EXEC SQL UPDATE Tbl SET col = MYNUMBER; -</programlisting> - then ecpg will already do the substitution and your C compiler will never - see any name or identifier <literal>MYNUMBER</>. Note that you cannot use - <literal>#define</literal> for a constant that you are going to use in an - embedded SQL query because in this case the embedded SQL precompiler is not - able to see this declaration. - </para> - </sect2> - - <sect2> - <title>ifdef, ifndef, else, elif and endif directives</title> - <para> - You can use the following directives to compile code sections conditionally: - - <variablelist> - <varlistentry> - <term><literal>EXEC SQL ifdef <replaceable>name</>;</literal></term> - <listitem> - <para> - Checks a <replaceable>name</> and processes subsequent lines if - <replaceable>name</> has been created with <literal>EXEC SQL define - <replaceable>name</></literal>. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><literal>EXEC SQL ifndef <replaceable>name</>;</literal></term> - <listitem> - <para> - Checks a <replaceable>name</> and processes subsequent lines if - <replaceable>name</> has <emphasis>not</emphasis> been created with - <literal>EXEC SQL define <replaceable>name</></literal>. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><literal>EXEC SQL else;</literal></term> - <listitem> - <para> - Starts processing an alternative section to a section introduced by - either <literal>EXEC SQL ifdef <replaceable>name</></literal> or - <literal>EXEC SQL ifndef <replaceable>name</></literal>. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><literal>EXEC SQL elif <replaceable>name</>;</literal></term> - <listitem> - <para> - Checks <replaceable>name</> and starts an alternative section if - <replaceable>name</> has been created with <literal>EXEC SQL define - <replaceable>name</></literal>. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><literal>EXEC SQL endif;</literal></term> - <listitem> - <para> - Ends an alternative section. - </para> - </listitem> - </varlistentry> - </variablelist> - </para> - - <para> - Example: -<programlisting> - exec sql ifndef TZVAR; - exec sql SET TIMEZONE TO 'GMT'; - exec sql elif TZNAME; - exec sql SET TIMEZONE TO TZNAME; - exec sql else; - exec sql SET TIMEZONE TO TZVAR; - exec sql endif; -</programlisting> - </para> - - </sect2> - </sect1> - - <sect1 id="ecpg-process"> - <title>Processing Embedded SQL Programs</title> - - <para> - Now that you have an idea how to form embedded SQL C programs, you - probably want to know how to compile them. Before compiling you - run the file through the embedded <acronym>SQL</acronym> - <acronym>C</acronym> preprocessor, which converts the - <acronym>SQL</acronym> statements you used to special function - calls. After compiling, you must link with a special library that - contains the needed functions. These functions fetch information - from the arguments, perform the <acronym>SQL</acronym> command using - the <application>libpq</application> interface, and put the result - in the arguments specified for output. - </para> - - <para> - The preprocessor program is called <filename>ecpg</filename> and is - included in a normal <productname>PostgreSQL</> installation. - Embedded SQL programs are typically named with an extension - <filename>.pgc</filename>. If you have a program file called - <filename>prog1.pgc</filename>, you can preprocess it by simply - calling: -<programlisting> -ecpg prog1.pgc -</programlisting> - This will create a file called <filename>prog1.c</filename>. If - your input files do not follow the suggested naming pattern, you - can specify the output file explicitly using the - <option>-o</option> option. - </para> - - <para> - The preprocessed file can be compiled normally, for example: -<programlisting> -cc -c prog1.c -</programlisting> - The generated C source files include header files from the - <productname>PostgreSQL</> installation, so if you installed - <productname>PostgreSQL</> in a location that is not searched by - default, you have to add an option such as - <literal>-I/usr/local/pgsql/include</literal> to the compilation - command line. - </para> - - <para> - To link an embedded SQL program, you need to include the - <filename>libecpg</filename> library, like so: -<programlisting> -cc -o myprog prog1.o prog2.o ... -lecpg -</programlisting> - Again, you might have to add an option like - <literal>-L/usr/local/pgsql/lib</literal> to that command line. - </para> - - <para> - If you manage the build process of a larger project using - <application>make</application>, it might be convenient to include - the following implicit rule to your makefiles: -<programlisting> -ECPG = ecpg - -%.c: %.pgc - $(ECPG) $< -</programlisting> - </para> - - <para> - The complete syntax of the <command>ecpg</command> command is - detailed in <xref linkend="app-ecpg">. - </para> - - <para> - The <application>ecpg</application> library is thread-safe by - default. However, you might need to use some threading - command-line options to compile your client code. - </para> - </sect1> - - <sect1 id="ecpg-library"> - <title>Library Functions</title> - - <para> - The <filename>libecpg</filename> library primarily contains - <quote>hidden</quote> functions that are used to implement the - functionality expressed by the embedded SQL commands. But there - are some functions that can usefully be called directly. Note that - this makes your code unportable. - </para> - - <itemizedlist> - <listitem> - <para> - <function>ECPGdebug(int <replaceable>on</replaceable>, FILE - *<replaceable>stream</replaceable>)</function> turns on debug - logging if called with the first argument non-zero. Debug logging - is done on <replaceable>stream</replaceable>. The log contains - all <acronym>SQL</acronym> statements with all the input - variables inserted, and the results from the - <productname>PostgreSQL</productname> server. This can be very - useful when searching for errors in your <acronym>SQL</acronym> - statements. - </para> - <note> - <para> - On Windows, if the <application>ecpg</> libraries and an application are - compiled with different flags, this function call will crash the - application because the internal representation of the - <literal>FILE</> pointers differ. Specifically, - multithreaded/single-threaded, release/debug, and static/dynamic - flags should be the same for the library and all applications using - that library. - </para> - </note> - </listitem> - - <listitem> - <para> - <function>ECPGget_PGconn(const char *<replaceable>connection_name</replaceable>) - </function> returns the library database connection handle identified by the given name. - If <replaceable>connection_name</replaceable> is set to <literal>NULL</literal>, the current - connection handle is returned. If no connection handle can be identified, the function returns - <literal>NULL</literal>. The returned connection handle can be used to call any other functions - from <application>libpq</application>, if necessary. - </para> - <note> - <para> - It is a bad idea to manipulate database connection handles made from <application>ecpg</application> directly - with <application>libpq</application> routines. - </para> - </note> - </listitem> - - <listitem> - <para> - <function>ECPGtransactionStatus(const char *<replaceable>connection_name</replaceable>)</function> - returns the current transaction status of the given connection identified by <replaceable>connection_name</replaceable>. - See <xref linkend="libpq-status"> and libpq's <function>PQtransactionStatus()</function> for details about the returned status codes. - </para> - </listitem> - - <listitem> - <para> - <function>ECPGstatus(int <replaceable>lineno</replaceable>, - const char* <replaceable>connection_name</replaceable>)</function> - returns true if you are connected to a database and false if not. - <replaceable>connection_name</replaceable> can be <literal>NULL</> - if a single connection is being used. - </para> - </listitem> - </itemizedlist> - </sect1> - <sect1 id="ecpg-develop"> <title>Internals</title> @@ -5493,7 +9553,7 @@ ECPG = ecpg </listitem> <listitem> - <para> + <para> A pointer to the value or a pointer to the pointer. </para> </listitem> diff --git a/doc/src/sgml/errcodes.sgml b/doc/src/sgml/errcodes.sgml index b5962f98cd..16cb6c7fcd 100644 --- a/doc/src/sgml/errcodes.sgml +++ b/doc/src/sgml/errcodes.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/errcodes.sgml,v 1.29 2010/03/13 14:55:57 momjian Exp $ --> +<!-- doc/src/sgml/errcodes.sgml --> <appendix id="errcodes-appendix"> <title><productname>PostgreSQL</productname> Error Codes</title> @@ -42,1424 +42,32 @@ </para> <para> - The <application>PL/pgSQL</> condition name for each error code is the - same as the phrase shown in the table, with underscores substituted - for spaces. For example, code <literal>22012</>, DIVISION BY ZERO, - has condition name <literal>DIVISION_BY_ZERO</>. Condition names can - be written in either upper or lower case. (Note that + The symbol shown in the column <quote>Condition Name</quote> is also + the condition name to use in <application>PL/pgSQL</>. Condition + names can be written in either upper or lower case. (Note that <application>PL/pgSQL</> does not recognize warning, as opposed to error, condition names; those are classes 00, 01, and 02.) </para> -<!-- - The following table should correspond to the contents of - src/include/utils/errcodes.h and src/pl/plpgsql/src/plerrcodes.h. ---> - <table id="errcodes-table"> <title><productname>PostgreSQL</productname> Error Codes</title> - <tgroup cols="3"> + <tgroup cols="2"> <colspec colnum="1" colname="errorcode"> - <colspec colnum="3" colname="condname"> - <spanspec namest="errorcode" nameend="condname" spanname="span13"> + <colspec colnum="2" colname="condname"> + <spanspec namest="errorcode" nameend="condname" spanname="span12"> <thead> <row> <entry>Error Code</entry> - <entry>Meaning</entry> <entry>Condition Name</entry> </row> </thead> <tbody> -<row> -<entry spanname="span13"><emphasis role="bold">Class 00 — Successful Completion</></entry> -</row> - -<row> -<entry><literal>00000</literal></entry> -<entry>SUCCESSFUL COMPLETION</entry> -<entry>successful_completion</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 01 — Warning</></entry> -</row> - -<row> -<entry><literal>01000</literal></entry> -<entry>WARNING</entry> -<entry>warning</entry> -</row> - -<row> -<entry><literal>0100C</literal></entry> -<entry>DYNAMIC RESULT SETS RETURNED</entry> -<entry>dynamic_result_sets_returned</entry> -</row> - -<row> -<entry><literal>01008</literal></entry> -<entry>IMPLICIT ZERO BIT PADDING</entry> -<entry>implicit_zero_bit_padding</entry> -</row> - -<row> -<entry><literal>01003</literal></entry> -<entry>NULL VALUE ELIMINATED IN SET FUNCTION</entry> -<entry>null_value_eliminated_in_set_function</entry> -</row> - -<row> -<entry><literal>01007</literal></entry> -<entry>PRIVILEGE NOT GRANTED</entry> -<entry>privilege_not_granted</entry> -</row> - -<row> -<entry><literal>01006</literal></entry> -<entry>PRIVILEGE NOT REVOKED</entry> -<entry>privilege_not_revoked</entry> -</row> - -<row> -<entry><literal>01004</literal></entry> -<entry>STRING DATA RIGHT TRUNCATION</entry> -<entry>string_data_right_truncation</entry> -</row> - -<row> -<entry><literal>01P01</literal></entry> -<entry>DEPRECATED FEATURE</entry> -<entry>deprecated_feature</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 02 — No Data (this is also a warning class per the SQL standard)</></entry> -</row> - -<row> -<entry><literal>02000</literal></entry> -<entry>NO DATA</entry> -<entry>no_data</entry> -</row> - -<row> -<entry><literal>02001</literal></entry> -<entry>NO ADDITIONAL DYNAMIC RESULT SETS RETURNED</entry> -<entry>no_additional_dynamic_result_sets_returned</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 03 — SQL Statement Not Yet Complete</></entry> -</row> - -<row> -<entry><literal>03000</literal></entry> -<entry>SQL STATEMENT NOT YET COMPLETE</entry> -<entry>sql_statement_not_yet_complete</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 08 — Connection Exception</></entry> -</row> - -<row> -<entry><literal>08000</literal></entry> -<entry>CONNECTION EXCEPTION</entry> -<entry>connection_exception</entry> -</row> - -<row> -<entry><literal>08003</literal></entry> -<entry>CONNECTION DOES NOT EXIST</entry> -<entry>connection_does_not_exist</entry> -</row> - -<row> -<entry><literal>08006</literal></entry> -<entry>CONNECTION FAILURE</entry> -<entry>connection_failure</entry> -</row> - -<row> -<entry><literal>08001</literal></entry> -<entry>SQLCLIENT UNABLE TO ESTABLISH SQLCONNECTION</entry> -<entry>sqlclient_unable_to_establish_sqlconnection</entry> -</row> - -<row> -<entry><literal>08004</literal></entry> -<entry>SQLSERVER REJECTED ESTABLISHMENT OF SQLCONNECTION</entry> -<entry>sqlserver_rejected_establishment_of_sqlconnection</entry> -</row> - -<row> -<entry><literal>08007</literal></entry> -<entry>TRANSACTION RESOLUTION UNKNOWN</entry> -<entry>transaction_resolution_unknown</entry> -</row> - -<row> -<entry><literal>08P01</literal></entry> -<entry>PROTOCOL VIOLATION</entry> -<entry>protocol_violation</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 09 — Triggered Action Exception</></entry> -</row> - -<row> -<entry><literal>09000</literal></entry> -<entry>TRIGGERED ACTION EXCEPTION</entry> -<entry>triggered_action_exception</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 0A — Feature Not Supported</></entry> -</row> - -<row> -<entry><literal>0A000</literal></entry> -<entry>FEATURE NOT SUPPORTED</entry> -<entry>feature_not_supported</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 0B — Invalid Transaction Initiation</></entry> -</row> - -<row> -<entry><literal>0B000</literal></entry> -<entry>INVALID TRANSACTION INITIATION</entry> -<entry>invalid_transaction_initiation</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 0F — Locator Exception</></entry> -</row> - -<row> -<entry><literal>0F000</literal></entry> -<entry>LOCATOR EXCEPTION</entry> -<entry>locator_exception</entry> -</row> - -<row> -<entry><literal>0F001</literal></entry> -<entry>INVALID LOCATOR SPECIFICATION</entry> -<entry>invalid_locator_specification</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 0L — Invalid Grantor</></entry> -</row> - -<row> -<entry><literal>0L000</literal></entry> -<entry>INVALID GRANTOR</entry> -<entry>invalid_grantor</entry> -</row> - -<row> -<entry><literal>0LP01</literal></entry> -<entry>INVALID GRANT OPERATION</entry> -<entry>invalid_grant_operation</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 0P — Invalid Role Specification</></entry> -</row> - -<row> -<entry><literal>0P000</literal></entry> -<entry>INVALID ROLE SPECIFICATION</entry> -<entry>invalid_role_specification</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 20 — Case Not Found</></entry> -</row> - -<row> -<entry><literal>20000</literal></entry> -<entry>CASE NOT FOUND</entry> -<entry>case_not_found</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 21 — Cardinality Violation</></entry> -</row> - -<row> -<entry><literal>21000</literal></entry> -<entry>CARDINALITY VIOLATION</entry> -<entry>cardinality_violation</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 22 — Data Exception</></entry> -</row> - -<row> -<entry><literal>22000</literal></entry> -<entry>DATA EXCEPTION</entry> -<entry>data_exception</entry> -</row> - -<row> -<entry><literal>2202E</literal></entry> -<entry>ARRAY SUBSCRIPT ERROR</entry> -<entry>array_subscript_error</entry> -</row> - -<row> -<entry><literal>22021</literal></entry> -<entry>CHARACTER NOT IN REPERTOIRE</entry> -<entry>character_not_in_repertoire</entry> -</row> - -<row> -<entry><literal>22008</literal></entry> -<entry>DATETIME FIELD OVERFLOW</entry> -<entry>datetime_field_overflow</entry> -</row> - -<row> -<entry><literal>22012</literal></entry> -<entry>DIVISION BY ZERO</entry> -<entry>division_by_zero</entry> -</row> - -<row> -<entry><literal>22005</literal></entry> -<entry>ERROR IN ASSIGNMENT</entry> -<entry>error_in_assignment</entry> -</row> - -<row> -<entry><literal>2200B</literal></entry> -<entry>ESCAPE CHARACTER CONFLICT</entry> -<entry>escape_character_conflict</entry> -</row> - -<row> -<entry><literal>22022</literal></entry> -<entry>INDICATOR OVERFLOW</entry> -<entry>indicator_overflow</entry> -</row> - -<row> -<entry><literal>22015</literal></entry> -<entry>INTERVAL FIELD OVERFLOW</entry> -<entry>interval_field_overflow</entry> -</row> - -<row> -<entry><literal>2201E</literal></entry> -<entry>INVALID ARGUMENT FOR LOGARITHM</entry> -<entry>invalid_argument_for_logarithm</entry> -</row> - -<row> -<entry><literal>22014</literal></entry> -<entry>INVALID ARGUMENT FOR NTILE FUNCTION</entry> -<entry>invalid_argument_for_ntile_function</entry> -</row> - -<row> -<entry><literal>22016</literal></entry> -<entry>INVALID ARGUMENT FOR NTH_VALUE FUNCTION</entry> -<entry>invalid_argument_for_nth_value_function</entry> -</row> - -<row> -<entry><literal>2201F</literal></entry> -<entry>INVALID ARGUMENT FOR POWER FUNCTION</entry> -<entry>invalid_argument_for_power_function</entry> -</row> - -<row> -<entry><literal>2201G</literal></entry> -<entry>INVALID ARGUMENT FOR WIDTH BUCKET FUNCTION</entry> -<entry>invalid_argument_for_width_bucket_function</entry> -</row> - -<row> -<entry><literal>22018</literal></entry> -<entry>INVALID CHARACTER VALUE FOR CAST</entry> -<entry>invalid_character_value_for_cast</entry> -</row> - -<row> -<entry><literal>22007</literal></entry> -<entry>INVALID DATETIME FORMAT</entry> -<entry>invalid_datetime_format</entry> -</row> - -<row> -<entry><literal>22019</literal></entry> -<entry>INVALID ESCAPE CHARACTER</entry> -<entry>invalid_escape_character</entry> -</row> - -<row> -<entry><literal>2200D</literal></entry> -<entry>INVALID ESCAPE OCTET</entry> -<entry>invalid_escape_octet</entry> -</row> - -<row> -<entry><literal>22025</literal></entry> -<entry>INVALID ESCAPE SEQUENCE</entry> -<entry>invalid_escape_sequence</entry> -</row> - -<row> -<entry><literal>22P06</literal></entry> -<entry>NONSTANDARD USE OF ESCAPE CHARACTER</entry> -<entry>nonstandard_use_of_escape_character</entry> -</row> - -<row> -<entry><literal>22010</literal></entry> -<entry>INVALID INDICATOR PARAMETER VALUE</entry> -<entry>invalid_indicator_parameter_value</entry> -</row> - -<row> -<entry><literal>22023</literal></entry> -<entry>INVALID PARAMETER VALUE</entry> -<entry>invalid_parameter_value</entry> -</row> - -<row> -<entry><literal>2201B</literal></entry> -<entry>INVALID REGULAR EXPRESSION</entry> -<entry>invalid_regular_expression</entry> -</row> - -<row> -<entry><literal>2201W</literal></entry> -<entry>INVALID ROW COUNT IN LIMIT CLAUSE</entry> -<entry>invalid_row_count_in_limit_clause</entry> -</row> - -<row> -<entry><literal>2201X</literal></entry> -<entry>INVALID ROW COUNT IN RESULT OFFSET CLAUSE</entry> -<entry>invalid_row_count_in_result_offset_clause</entry> -</row> - -<row> -<entry><literal>22009</literal></entry> -<entry>INVALID TIME ZONE DISPLACEMENT VALUE</entry> -<entry>invalid_time_zone_displacement_value</entry> -</row> - -<row> -<entry><literal>2200C</literal></entry> -<entry>INVALID USE OF ESCAPE CHARACTER</entry> -<entry>invalid_use_of_escape_character</entry> -</row> - -<row> -<entry><literal>2200G</literal></entry> -<entry>MOST SPECIFIC TYPE MISMATCH</entry> -<entry>most_specific_type_mismatch</entry> -</row> - -<row> -<entry><literal>22004</literal></entry> -<entry>NULL VALUE NOT ALLOWED</entry> -<entry>null_value_not_allowed</entry> -</row> - -<row> -<entry><literal>22002</literal></entry> -<entry>NULL VALUE NO INDICATOR PARAMETER</entry> -<entry>null_value_no_indicator_parameter</entry> -</row> - -<row> -<entry><literal>22003</literal></entry> -<entry>NUMERIC VALUE OUT OF RANGE</entry> -<entry>numeric_value_out_of_range</entry> -</row> - -<row> -<entry><literal>22026</literal></entry> -<entry>STRING DATA LENGTH MISMATCH</entry> -<entry>string_data_length_mismatch</entry> -</row> - -<row> -<entry><literal>22001</literal></entry> -<entry>STRING DATA RIGHT TRUNCATION</entry> -<entry>string_data_right_truncation</entry> -</row> - -<row> -<entry><literal>22011</literal></entry> -<entry>SUBSTRING ERROR</entry> -<entry>substring_error</entry> -</row> - -<row> -<entry><literal>22027</literal></entry> -<entry>TRIM ERROR</entry> -<entry>trim_error</entry> -</row> - -<row> -<entry><literal>22024</literal></entry> -<entry>UNTERMINATED C STRING</entry> -<entry>unterminated_c_string</entry> -</row> - -<row> -<entry><literal>2200F</literal></entry> -<entry>ZERO LENGTH CHARACTER STRING</entry> -<entry>zero_length_character_string</entry> -</row> - -<row> -<entry><literal>22P01</literal></entry> -<entry>FLOATING POINT EXCEPTION</entry> -<entry>floating_point_exception</entry> -</row> - -<row> -<entry><literal>22P02</literal></entry> -<entry>INVALID TEXT REPRESENTATION</entry> -<entry>invalid_text_representation</entry> -</row> - -<row> -<entry><literal>22P03</literal></entry> -<entry>INVALID BINARY REPRESENTATION</entry> -<entry>invalid_binary_representation</entry> -</row> - -<row> -<entry><literal>22P04</literal></entry> -<entry>BAD COPY FILE FORMAT</entry> -<entry>bad_copy_file_format</entry> -</row> - -<row> -<entry><literal>22P05</literal></entry> -<entry>UNTRANSLATABLE CHARACTER</entry> -<entry>untranslatable_character</entry> -</row> - -<row> -<entry><literal>2200L</literal></entry> -<entry>NOT AN XML DOCUMENT</entry> -<entry>not_an_xml_document</entry> -</row> - -<row> -<entry><literal>2200M</literal></entry> -<entry>INVALID XML DOCUMENT</entry> -<entry>invalid_xml_document</entry> -</row> - -<row> -<entry><literal>2200N</literal></entry> -<entry>INVALID XML CONTENT</entry> -<entry>invalid_xml_content</entry> -</row> - -<row> -<entry><literal>2200S</literal></entry> -<entry>INVALID XML COMMENT</entry> -<entry>invalid_xml_comment</entry> -</row> - -<row> -<entry><literal>2200T</literal></entry> -<entry>INVALID XML PROCESSING INSTRUCTION</entry> -<entry>invalid_xml_processing_instruction</entry> -</row> - -<row> -<entry spanname="span13"><emphasis role="bold">Class 23 — Integrity Constraint Violation</></entry> -</row> - -<row> -<entry><literal>23000</literal></entry> -<entry>INTEGRITY CONSTRAINT VIOLATION</entry> -<entry>integrity_constraint_violation</entry> -</row> - -<row> -<entry><literal>23001</literal></entry> -<entry>RESTRICT VIOLATION</entry> -<entry>restrict_violation</entry> -</row> - -<row> -<entry><literal>23502</literal></entry> -<entry>NOT NULL VIOLATION</entry> -<entry>not_null_violation</entry> -</row> - -<row> -<entry><literal>23503</literal></entry> -<entry>FOREIGN KEY VIOLATION</entry> -<entry>foreign_key_violation</entry> -</row> - -<row> -<entry><literal>23505</literal></entry> -<entry>UNIQUE VIOLATION</entry> -<entry>unique_violation</entry> -</row> - -<row> -<entry><literal>23514</literal></entry> -<entry>CHECK VIOLATION</entry> -<entry>check_violation</entry> -</row> - -<row> -<entry><literal>23P01</literal></entry> -<entry>EXCLUSION VIOLATION</entry> -<entry>exclusion_violation</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 24 — Invalid Cursor State</></entry> -</row> - -<row> -<entry><literal>24000</literal></entry> -<entry>INVALID CURSOR STATE</entry> -<entry>invalid_cursor_state</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 25 — Invalid Transaction State</></entry> -</row> - -<row> -<entry><literal>25000</literal></entry> -<entry>INVALID TRANSACTION STATE</entry> -<entry>invalid_transaction_state</entry> -</row> - -<row> -<entry><literal>25001</literal></entry> -<entry>ACTIVE SQL TRANSACTION</entry> -<entry>active_sql_transaction</entry> -</row> - -<row> -<entry><literal>25002</literal></entry> -<entry>BRANCH TRANSACTION ALREADY ACTIVE</entry> -<entry>branch_transaction_already_active</entry> -</row> - -<row> -<entry><literal>25008</literal></entry> -<entry>HELD CURSOR REQUIRES SAME ISOLATION LEVEL</entry> -<entry>held_cursor_requires_same_isolation_level</entry> -</row> - -<row> -<entry><literal>25003</literal></entry> -<entry>INAPPROPRIATE ACCESS MODE FOR BRANCH TRANSACTION</entry> -<entry>inappropriate_access_mode_for_branch_transaction</entry> -</row> - -<row> -<entry><literal>25004</literal></entry> -<entry>INAPPROPRIATE ISOLATION LEVEL FOR BRANCH TRANSACTION</entry> -<entry>inappropriate_isolation_level_for_branch_transaction</entry> -</row> - -<row> -<entry><literal>25005</literal></entry> -<entry>NO ACTIVE SQL TRANSACTION FOR BRANCH TRANSACTION</entry> -<entry>no_active_sql_transaction_for_branch_transaction</entry> -</row> - -<row> -<entry><literal>25006</literal></entry> -<entry>READ ONLY SQL TRANSACTION</entry> -<entry>read_only_sql_transaction</entry> -</row> - -<row> -<entry><literal>25007</literal></entry> -<entry>SCHEMA AND DATA STATEMENT MIXING NOT SUPPORTED</entry> -<entry>schema_and_data_statement_mixing_not_supported</entry> -</row> - -<row> -<entry><literal>25P01</literal></entry> -<entry>NO ACTIVE SQL TRANSACTION</entry> -<entry>no_active_sql_transaction</entry> -</row> - -<row> -<entry><literal>25P02</literal></entry> -<entry>IN FAILED SQL TRANSACTION</entry> -<entry>in_failed_sql_transaction</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 26 — Invalid SQL Statement Name</></entry> -</row> - -<row> -<entry><literal>26000</literal></entry> -<entry>INVALID SQL STATEMENT NAME</entry> -<entry>invalid_sql_statement_name</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 27 — Triggered Data Change Violation</></entry> -</row> - -<row> -<entry><literal>27000</literal></entry> -<entry>TRIGGERED DATA CHANGE VIOLATION</entry> -<entry>triggered_data_change_violation</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 28 — Invalid Authorization Specification</></entry> -</row> - -<row> -<entry><literal>28000</literal></entry> -<entry>INVALID AUTHORIZATION SPECIFICATION</entry> -<entry>invalid_authorization_specification</entry> -</row> - -<row> -<entry><literal>28P01</literal></entry> -<entry>INVALID PASSWORD</entry> -<entry>invalid_password</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 2B — Dependent Privilege Descriptors Still Exist</></entry> -</row> - -<row> -<entry><literal>2B000</literal></entry> -<entry>DEPENDENT PRIVILEGE DESCRIPTORS STILL EXIST</entry> -<entry>dependent_privilege_descriptors_still_exist</entry> -</row> - -<row> -<entry><literal>2BP01</literal></entry> -<entry>DEPENDENT OBJECTS STILL EXIST</entry> -<entry>dependent_objects_still_exist</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 2D — Invalid Transaction Termination</></entry> -</row> - -<row> -<entry><literal>2D000</literal></entry> -<entry>INVALID TRANSACTION TERMINATION</entry> -<entry>invalid_transaction_termination</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 2F — SQL Routine Exception</></entry> -</row> - -<row> -<entry><literal>2F000</literal></entry> -<entry>SQL ROUTINE EXCEPTION</entry> -<entry>sql_routine_exception</entry> -</row> - -<row> -<entry><literal>2F005</literal></entry> -<entry>FUNCTION EXECUTED NO RETURN STATEMENT</entry> -<entry>function_executed_no_return_statement</entry> -</row> - -<row> -<entry><literal>2F002</literal></entry> -<entry>MODIFYING SQL DATA NOT PERMITTED</entry> -<entry>modifying_sql_data_not_permitted</entry> -</row> - -<row> -<entry><literal>2F003</literal></entry> -<entry>PROHIBITED SQL STATEMENT ATTEMPTED</entry> -<entry>prohibited_sql_statement_attempted</entry> -</row> - -<row> -<entry><literal>2F004</literal></entry> -<entry>READING SQL DATA NOT PERMITTED</entry> -<entry>reading_sql_data_not_permitted</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 34 — Invalid Cursor Name</></entry> -</row> - -<row> -<entry><literal>34000</literal></entry> -<entry>INVALID CURSOR NAME</entry> -<entry>invalid_cursor_name</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 38 — External Routine Exception</></entry> -</row> - -<row> -<entry><literal>38000</literal></entry> -<entry>EXTERNAL ROUTINE EXCEPTION</entry> -<entry>external_routine_exception</entry> -</row> - -<row> -<entry><literal>38001</literal></entry> -<entry>CONTAINING SQL NOT PERMITTED</entry> -<entry>containing_sql_not_permitted</entry> -</row> - -<row> -<entry><literal>38002</literal></entry> -<entry>MODIFYING SQL DATA NOT PERMITTED</entry> -<entry>modifying_sql_data_not_permitted</entry> -</row> - -<row> -<entry><literal>38003</literal></entry> -<entry>PROHIBITED SQL STATEMENT ATTEMPTED</entry> -<entry>prohibited_sql_statement_attempted</entry> -</row> - -<row> -<entry><literal>38004</literal></entry> -<entry>READING SQL DATA NOT PERMITTED</entry> -<entry>reading_sql_data_not_permitted</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 39 — External Routine Invocation Exception</></entry> -</row> - -<row> -<entry><literal>39000</literal></entry> -<entry>EXTERNAL ROUTINE INVOCATION EXCEPTION</entry> -<entry>external_routine_invocation_exception</entry> -</row> - -<row> -<entry><literal>39001</literal></entry> -<entry>INVALID SQLSTATE RETURNED</entry> -<entry>invalid_sqlstate_returned</entry> -</row> - -<row> -<entry><literal>39004</literal></entry> -<entry>NULL VALUE NOT ALLOWED</entry> -<entry>null_value_not_allowed</entry> -</row> - -<row> -<entry><literal>39P01</literal></entry> -<entry>TRIGGER PROTOCOL VIOLATED</entry> -<entry>trigger_protocol_violated</entry> -</row> - -<row> -<entry><literal>39P02</literal></entry> -<entry>SRF PROTOCOL VIOLATED</entry> -<entry>srf_protocol_violated</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 3B — Savepoint Exception</></entry> -</row> - -<row> -<entry><literal>3B000</literal></entry> -<entry>SAVEPOINT EXCEPTION</entry> -<entry>savepoint_exception</entry> -</row> - -<row> -<entry><literal>3B001</literal></entry> -<entry>INVALID SAVEPOINT SPECIFICATION</entry> -<entry>invalid_savepoint_specification</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 3D — Invalid Catalog Name</></entry> -</row> - -<row> -<entry><literal>3D000</literal></entry> -<entry>INVALID CATALOG NAME</entry> -<entry>invalid_catalog_name</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 3F — Invalid Schema Name</></entry> -</row> - -<row> -<entry><literal>3F000</literal></entry> -<entry>INVALID SCHEMA NAME</entry> -<entry>invalid_schema_name</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 40 — Transaction Rollback</></entry> -</row> - -<row> -<entry><literal>40000</literal></entry> -<entry>TRANSACTION ROLLBACK</entry> -<entry>transaction_rollback</entry> -</row> - -<row> -<entry><literal>40002</literal></entry> -<entry>TRANSACTION INTEGRITY CONSTRAINT VIOLATION</entry> -<entry>transaction_integrity_constraint_violation</entry> -</row> - -<row> -<entry><literal>40001</literal></entry> -<entry>SERIALIZATION FAILURE</entry> -<entry>serialization_failure</entry> -</row> - -<row> -<entry><literal>40003</literal></entry> -<entry>STATEMENT COMPLETION UNKNOWN</entry> -<entry>statement_completion_unknown</entry> -</row> - -<row> -<entry><literal>40P01</literal></entry> -<entry>DEADLOCK DETECTED</entry> -<entry>deadlock_detected</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 42 — Syntax Error or Access Rule Violation</></entry> -</row> - -<row> -<entry><literal>42000</literal></entry> -<entry>SYNTAX ERROR OR ACCESS RULE VIOLATION</entry> -<entry>syntax_error_or_access_rule_violation</entry> -</row> - -<row> -<entry><literal>42601</literal></entry> -<entry>SYNTAX ERROR</entry> -<entry>syntax_error</entry> -</row> - -<row> -<entry><literal>42501</literal></entry> -<entry>INSUFFICIENT PRIVILEGE</entry> -<entry>insufficient_privilege</entry> -</row> - -<row> -<entry><literal>42846</literal></entry> -<entry>CANNOT COERCE</entry> -<entry>cannot_coerce</entry> -</row> - -<row> -<entry><literal>42803</literal></entry> -<entry>GROUPING ERROR</entry> -<entry>grouping_error</entry> -</row> - -<row> -<entry><literal>42P20</literal></entry> -<entry>WINDOWING ERROR</entry> -<entry>windowing_error</entry> -</row> - -<row> -<entry><literal>42P19</literal></entry> -<entry>INVALID RECURSION</entry> -<entry>invalid_recursion</entry> -</row> - -<row> -<entry><literal>42830</literal></entry> -<entry>INVALID FOREIGN KEY</entry> -<entry>invalid_foreign_key</entry> -</row> - -<row> -<entry><literal>42602</literal></entry> -<entry>INVALID NAME</entry> -<entry>invalid_name</entry> -</row> - -<row> -<entry><literal>42622</literal></entry> -<entry>NAME TOO LONG</entry> -<entry>name_too_long</entry> -</row> - -<row> -<entry><literal>42939</literal></entry> -<entry>RESERVED NAME</entry> -<entry>reserved_name</entry> -</row> - -<row> -<entry><literal>42804</literal></entry> -<entry>DATATYPE MISMATCH</entry> -<entry>datatype_mismatch</entry> -</row> - -<row> -<entry><literal>42P18</literal></entry> -<entry>INDETERMINATE DATATYPE</entry> -<entry>indeterminate_datatype</entry> -</row> - -<row> -<entry><literal>42809</literal></entry> -<entry>WRONG OBJECT TYPE</entry> -<entry>wrong_object_type</entry> -</row> - -<row> -<entry><literal>42703</literal></entry> -<entry>UNDEFINED COLUMN</entry> -<entry>undefined_column</entry> -</row> - -<row> -<entry><literal>42883</literal></entry> -<entry>UNDEFINED FUNCTION</entry> -<entry>undefined_function</entry> -</row> - -<row> -<entry><literal>42P01</literal></entry> -<entry>UNDEFINED TABLE</entry> -<entry>undefined_table</entry> -</row> - -<row> -<entry><literal>42P02</literal></entry> -<entry>UNDEFINED PARAMETER</entry> -<entry>undefined_parameter</entry> -</row> - -<row> -<entry><literal>42704</literal></entry> -<entry>UNDEFINED OBJECT</entry> -<entry>undefined_object</entry> -</row> - -<row> -<entry><literal>42701</literal></entry> -<entry>DUPLICATE COLUMN</entry> -<entry>duplicate_column</entry> -</row> - -<row> -<entry><literal>42P03</literal></entry> -<entry>DUPLICATE CURSOR</entry> -<entry>duplicate_cursor</entry> -</row> - -<row> -<entry><literal>42P04</literal></entry> -<entry>DUPLICATE DATABASE</entry> -<entry>duplicate_database</entry> -</row> - -<row> -<entry><literal>42723</literal></entry> -<entry>DUPLICATE FUNCTION</entry> -<entry>duplicate_function</entry> -</row> - -<row> -<entry><literal>42P05</literal></entry> -<entry>DUPLICATE PREPARED STATEMENT</entry> -<entry>duplicate_prepared_statement</entry> -</row> - -<row> -<entry><literal>42P06</literal></entry> -<entry>DUPLICATE SCHEMA</entry> -<entry>duplicate_schema</entry> -</row> - -<row> -<entry><literal>42P07</literal></entry> -<entry>DUPLICATE TABLE</entry> -<entry>duplicate_table</entry> -</row> - -<row> -<entry><literal>42712</literal></entry> -<entry>DUPLICATE ALIAS</entry> -<entry>duplicate_alias</entry> -</row> - -<row> -<entry><literal>42710</literal></entry> -<entry>DUPLICATE OBJECT</entry> -<entry>duplicate_object</entry> -</row> - -<row> -<entry><literal>42702</literal></entry> -<entry>AMBIGUOUS COLUMN</entry> -<entry>ambiguous_column</entry> -</row> - -<row> -<entry><literal>42725</literal></entry> -<entry>AMBIGUOUS FUNCTION</entry> -<entry>ambiguous_function</entry> -</row> - -<row> -<entry><literal>42P08</literal></entry> -<entry>AMBIGUOUS PARAMETER</entry> -<entry>ambiguous_parameter</entry> -</row> - -<row> -<entry><literal>42P09</literal></entry> -<entry>AMBIGUOUS ALIAS</entry> -<entry>ambiguous_alias</entry> -</row> - -<row> -<entry><literal>42P10</literal></entry> -<entry>INVALID COLUMN REFERENCE</entry> -<entry>invalid_column_reference</entry> -</row> - -<row> -<entry><literal>42611</literal></entry> -<entry>INVALID COLUMN DEFINITION</entry> -<entry>invalid_column_definition</entry> -</row> - -<row> -<entry><literal>42P11</literal></entry> -<entry>INVALID CURSOR DEFINITION</entry> -<entry>invalid_cursor_definition</entry> -</row> - -<row> -<entry><literal>42P12</literal></entry> -<entry>INVALID DATABASE DEFINITION</entry> -<entry>invalid_database_definition</entry> -</row> - -<row> -<entry><literal>42P13</literal></entry> -<entry>INVALID FUNCTION DEFINITION</entry> -<entry>invalid_function_definition</entry> -</row> - -<row> -<entry><literal>42P14</literal></entry> -<entry>INVALID PREPARED STATEMENT DEFINITION</entry> -<entry>invalid_prepared_statement_definition</entry> -</row> - -<row> -<entry><literal>42P15</literal></entry> -<entry>INVALID SCHEMA DEFINITION</entry> -<entry>invalid_schema_definition</entry> -</row> - -<row> -<entry><literal>42P16</literal></entry> -<entry>INVALID TABLE DEFINITION</entry> -<entry>invalid_table_definition</entry> -</row> - -<row> -<entry><literal>42P17</literal></entry> -<entry>INVALID OBJECT DEFINITION</entry> -<entry>invalid_object_definition</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 44 — WITH CHECK OPTION Violation</></entry> -</row> - -<row> -<entry><literal>44000</literal></entry> -<entry>WITH CHECK OPTION VIOLATION</entry> -<entry>with_check_option_violation</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 53 — Insufficient Resources</></entry> -</row> - -<row> -<entry><literal>53000</literal></entry> -<entry>INSUFFICIENT RESOURCES</entry> -<entry>insufficient_resources</entry> -</row> - -<row> -<entry><literal>53100</literal></entry> -<entry>DISK FULL</entry> -<entry>disk_full</entry> -</row> - -<row> -<entry><literal>53200</literal></entry> -<entry>OUT OF MEMORY</entry> -<entry>out_of_memory</entry> -</row> - -<row> -<entry><literal>53300</literal></entry> -<entry>TOO MANY CONNECTIONS</entry> -<entry>too_many_connections</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 54 — Program Limit Exceeded</></entry> -</row> - -<row> -<entry><literal>54000</literal></entry> -<entry>PROGRAM LIMIT EXCEEDED</entry> -<entry>program_limit_exceeded</entry> -</row> - -<row> -<entry><literal>54001</literal></entry> -<entry>STATEMENT TOO COMPLEX</entry> -<entry>statement_too_complex</entry> -</row> - -<row> -<entry><literal>54011</literal></entry> -<entry>TOO MANY COLUMNS</entry> -<entry>too_many_columns</entry> -</row> - -<row> -<entry><literal>54023</literal></entry> -<entry>TOO MANY ARGUMENTS</entry> -<entry>too_many_arguments</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 55 — Object Not In Prerequisite State</></entry> -</row> - -<row> -<entry><literal>55000</literal></entry> -<entry>OBJECT NOT IN PREREQUISITE STATE</entry> -<entry>object_not_in_prerequisite_state</entry> -</row> - -<row> -<entry><literal>55006</literal></entry> -<entry>OBJECT IN USE</entry> -<entry>object_in_use</entry> -</row> - -<row> -<entry><literal>55P02</literal></entry> -<entry>CANT CHANGE RUNTIME PARAM</entry> -<entry>cant_change_runtime_param</entry> -</row> - -<row> -<entry><literal>55P03</literal></entry> -<entry>LOCK NOT AVAILABLE</entry> -<entry>lock_not_available</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 57 — Operator Intervention</></entry> -</row> - -<row> -<entry><literal>57000</literal></entry> -<entry>OPERATOR INTERVENTION</entry> -<entry>operator_intervention</entry> -</row> - -<row> -<entry><literal>57014</literal></entry> -<entry>QUERY CANCELED</entry> -<entry>query_canceled</entry> -</row> - -<row> -<entry><literal>57P01</literal></entry> -<entry>ADMIN SHUTDOWN</entry> -<entry>admin_shutdown</entry> -</row> - -<row> -<entry><literal>57P02</literal></entry> -<entry>CRASH SHUTDOWN</entry> -<entry>crash_shutdown</entry> -</row> - -<row> -<entry><literal>57P03</literal></entry> -<entry>CANNOT CONNECT NOW</entry> -<entry>cannot_connect_now</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class 58 — System Error (errors external to <productname>PostgreSQL</> itself)</></entry> -</row> - -<row> -<entry><literal>58030</literal></entry> -<entry>IO ERROR</entry> -<entry>io_error</entry> -</row> - -<row> -<entry><literal>58P01</literal></entry> -<entry>UNDEFINED FILE</entry> -<entry>undefined_file</entry> -</row> - -<row> -<entry><literal>58P02</literal></entry> -<entry>DUPLICATE FILE</entry> -<entry>duplicate_file</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class F0 — Configuration File Error</></entry> -</row> - -<row> -<entry><literal>F0000</literal></entry> -<entry>CONFIG FILE ERROR</entry> -<entry>config_file_error</entry> -</row> - -<row> -<entry><literal>F0001</literal></entry> -<entry>LOCK FILE EXISTS</entry> -<entry>lock_file_exists</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class P0 — PL/pgSQL Error</></entry> -</row> - -<row> -<entry><literal>P0000</literal></entry> -<entry>PLPGSQL ERROR</entry> -<entry>plpgsql_error</entry> -</row> - -<row> -<entry><literal>P0001</literal></entry> -<entry>RAISE EXCEPTION</entry> -<entry>raise_exception</entry> -</row> - -<row> -<entry><literal>P0002</literal></entry> -<entry>NO DATA FOUND</entry> -<entry>no_data_found</entry> -</row> - -<row> -<entry><literal>P0003</literal></entry> -<entry>TOO MANY ROWS</entry> -<entry>too_many_rows</entry> -</row> - - -<row> -<entry spanname="span13"><emphasis role="bold">Class XX — Internal Error</></entry> -</row> - -<row> -<entry><literal>XX000</literal></entry> -<entry>INTERNAL ERROR</entry> -<entry>internal_error</entry> -</row> - -<row> -<entry><literal>XX001</literal></entry> -<entry>DATA CORRUPTED</entry> -<entry>data_corrupted</entry> -</row> - -<row> -<entry><literal>XX002</literal></entry> -<entry>INDEX CORRUPTED</entry> -<entry>index_corrupted</entry> -</row> + &errcodes-table; </tbody> </tgroup> diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml index d3b93dbe34..ab538cb500 100644 --- a/doc/src/sgml/extend.sgml +++ b/doc/src/sgml/extend.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/extend.sgml,v 1.44 2010/06/03 14:41:25 momjian Exp $ --> +<!-- doc/src/sgml/extend.sgml --> <chapter id="extend"> <title>Extending <acronym>SQL</acronym></title> @@ -9,7 +9,7 @@ <para> In the sections that follow, we will discuss how you - can extend the <productname>PostgreSQL</productname> + can extend the <productname>PostgreSQL</productname> <acronym>SQL</acronym> query language by adding: <itemizedlist spacing="compact" mark="bullet"> @@ -38,6 +38,11 @@ operator classes for indexes (starting in <xref linkend="xindex">) </para> </listitem> + <listitem> + <para> + packages of related objects (starting in <xref linkend="extend-extensions">) + </para> + </listitem> </itemizedlist> </para> @@ -45,8 +50,8 @@ <title>How Extensibility Works</title> <para> - <productname>PostgreSQL</productname> is extensible because its operation is - catalog-driven. If you are familiar with standard + <productname>PostgreSQL</productname> is extensible because its operation is + catalog-driven. If you are familiar with standard relational database systems, you know that they store information about databases, tables, columns, etc., in what are commonly known as system catalogs. (Some systems call @@ -54,14 +59,14 @@ user as tables like any other, but the <acronym>DBMS</acronym> stores its internal bookkeeping in them. One key difference between <productname>PostgreSQL</productname> and standard relational database systems is - that <productname>PostgreSQL</productname> stores much more information in its + that <productname>PostgreSQL</productname> stores much more information in its catalogs: not only information about tables and columns, but also information about data types, functions, access methods, and so on. These tables can be modified by - the user, and since <productname>PostgreSQL</productname> bases its operation + the user, and since <productname>PostgreSQL</productname> bases its operation on these tables, this means that <productname>PostgreSQL</productname> can be extended by users. By comparison, conventional - database systems can only be extended by changing hardcoded + database systems can only be extended by changing hardcoded procedures in the source code or by loading modules specially written by the <acronym>DBMS</acronym> vendor. </para> @@ -209,7 +214,7 @@ parsed. Each position (either argument or return value) declared as <type>anyelement</type> is allowed to have any specific actual data type, but in any given call they must all be the - <emphasis>same</emphasis> actual type. Each + <emphasis>same</emphasis> actual type. Each position declared as <type>anyarray</type> can have any array data type, but similarly they must all be the same type. If there are positions declared <type>anyarray</type> and others declared @@ -273,67 +278,881 @@ &xoper; &xindex; - <sect1 id="extend-Cpp"> - <title>Using C++ for Extensibility</title> - <indexterm zone="extend-Cpp"> - <primary>C++</primary> + <sect1 id="extend-extensions"> + <title>Packaging Related Objects into an Extension</title> + + <indexterm zone="extend-extensions"> + <primary>extension</primary> </indexterm> <para> - It is possible to use a compiler in C++ mode to build - <productname>PostgreSQL</productname> extensions by following these - guidelines: + A useful extension to <productname>PostgreSQL</> typically includes + multiple SQL objects; for example, a new data type will require new + functions, new operators, and probably new index operator classes. + It is helpful to collect all these objects into a single package + to simplify database management. <productname>PostgreSQL</> calls + such a package an <firstterm>extension</>. To define an extension, + you need at least a <firstterm>script file</> that contains the + <acronym>SQL</> commands to create the extension's objects, and a + <firstterm>control file</> that specifies a few basic properties + of the extension itself. If the extension includes C code, there + will typically also be a shared library file into which the C code + has been built. Once you have these files, a simple + <xref linkend="sql-createextension"> command loads the objects into + your database. + </para> + + <para> + The main advantage of using an extension, rather than just running the + <acronym>SQL</> script to load a bunch of <quote>loose</> objects + into your database, is that <productname>PostgreSQL</> will then + understand that the objects of the extension go together. You can + drop all the objects with a single <xref linkend="sql-dropextension"> + command (no need to maintain a separate <quote>uninstall</> script). + Even more useful, <application>pg_dump</> knows that it should not + dump the individual member objects of the extension — it will + just include a <command>CREATE EXTENSION</> command in dumps, instead. + This vastly simplifies migration to a new version of the extension + that might contain more or different objects than the old version. + Note however that you must have the extension's control, script, and + other files available when loading such a dump into a new database. + </para> + + <para> + <productname>PostgreSQL</> will not let you drop an individual object + contained in an extension, except by dropping the whole extension. + Also, while you can change the definition of an extension member object + (for example, via <command>CREATE OR REPLACE FUNCTION</command> for a + function), bear in mind that the modified definition will not be dumped + by <application>pg_dump</>. Such a change is usually only sensible if + you concurrently make the same change in the extension's script file. + (But there are special provisions for tables containing configuration + data; see below.) + </para> + + <para> + The extension mechanism also has provisions for packaging modification + scripts that adjust the definitions of the SQL objects contained in an + extension. For example, if version 1.1 of an extension adds one function + and changes the body of another function compared to 1.0, the extension + author can provide an <firstterm>update script</> that makes just those + two changes. The <command>ALTER EXTENSION UPDATE</> command can then + be used to apply these changes and track which version of the extension + is actually installed in a given database. + </para> + + <para> + The kinds of SQL objects that can be members of an extension are shown in + the description of <xref linkend="sql-alterextension">. Notably, objects + that are database-cluster-wide, such as databases, roles, and tablespaces, + cannot be extension members since an extension is only known within one + database. (Although an extension script is not prohibited from creating + such objects, if it does so they will not be tracked as part of the + extension.) Also notice that while a table can be a member of an + extension, its subsidiary objects such as indexes are not directly + considered members of the extension. + </para> + + <sect2> + <title>Extension Files</title> + + <indexterm> + <primary>control file</primary> + </indexterm> + + <para> + The <xref linkend="sql-createextension"> command relies on a control + file for each extension, which must be named the same as the extension + with a suffix of <literal>.control</>, and must be placed in the + installation's <literal>SHAREDIR/extension</literal> directory. There + must also be at least one <acronym>SQL</> script file, which follows the + naming pattern + <literal><replaceable>extension</>--<replaceable>version</>.sql</literal> + (for example, <literal>foo--1.0.sql</> for version <literal>1.0</> of + extension <literal>foo</>). By default, the script file(s) are also + placed in the <literal>SHAREDIR/extension</literal> directory; but the + control file can specify a different directory for the script file(s). + </para> + + <para> + The file format for an extension control file is the same as for the + <filename>postgresql.conf</> file, namely a list of + <replaceable>parameter_name</> <literal>=</> <replaceable>value</> + assignments, one per line. Blank lines and comments introduced by + <literal>#</> are allowed. Be sure to quote any value that is not + a single word or number. + </para> + + <para> + A control file can set the following parameters: + </para> + + <variablelist> + <varlistentry> + <term><varname>directory</varname> (<type>string</type>)</term> + <listitem> + <para> + The directory containing the extension's <acronym>SQL</> script + file(s). Unless an absolute path is given, the name is relative to + the installation's <literal>SHAREDIR</literal> directory. The + default behavior is equivalent to specifying + <literal>directory = 'extension'</>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>default_version</varname> (<type>string</type>)</term> + <listitem> + <para> + The default version of the extension (the one that will be installed + if no version is specified in <command>CREATE EXTENSION</>). Although + this can be omitted, that will result in <command>CREATE EXTENSION</> + failing if no <literal>VERSION</> option appears, so you generally + don't want to do that. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>comment</varname> (<type>string</type>)</term> + <listitem> + <para> + A comment (any string) about the extension. Alternatively, + the comment can be set by means of the <xref linkend="sql-comment"> + command in the script file. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>encoding</varname> (<type>string</type>)</term> + <listitem> + <para> + The character set encoding used by the script file(s). This should + be specified if the script files contain any non-ASCII characters. + Otherwise the files will be assumed to be in the database encoding. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>module_pathname</varname> (<type>string</type>)</term> + <listitem> + <para> + The value of this parameter will be substituted for each occurrence + of <literal>MODULE_PATHNAME</> in the script file(s). If it is not + set, no substitution is made. Typically, this is set to + <literal>$libdir/<replaceable>shared_library_name</></literal> and + then <literal>MODULE_PATHNAME</> is used in <command>CREATE + FUNCTION</> commands for C-language functions, so that the script + files do not need to hard-wire the name of the shared library. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>requires</varname> (<type>string</type>)</term> + <listitem> + <para> + A list of names of extensions that this extension depends on, + for example <literal>requires = 'foo, bar'</literal>. Those + extensions must be installed before this one can be installed. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>superuser</varname> (<type>boolean</type>)</term> + <listitem> + <para> + If this parameter is <literal>true</> (which is the default), + only superusers can create the extension or update it to a new + version. If it is set to <literal>false</>, just the privileges + required to execute the commands in the installation or update script + are required. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>relocatable</varname> (<type>boolean</type>)</term> + <listitem> + <para> + An extension is <firstterm>relocatable</> if it is possible to move + its contained objects into a different schema after initial creation + of the extension. The default is <literal>false</>, i.e. the + extension is not relocatable. + See below for more information. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>schema</varname> (<type>string</type>)</term> + <listitem> + <para> + This parameter can only be set for non-relocatable extensions. + It forces the extension to be loaded into exactly the named schema + and not any other. See below for more information. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + In addition to the primary control file + <literal><replaceable>extension</>.control</literal>, + an extension can have secondary control files named in the style + <literal><replaceable>extension</>--<replaceable>version</>.control</literal>. + If supplied, these must be located in the script file directory. + Secondary control files follow the same format as the primary control + file. Any parameters set in a secondary control file override the + primary control file when installing or updating to that version of + the extension. However, the parameters <varname>directory</> and + <varname>default_version</> cannot be set in a secondary control file. + </para> + + <para> + An extension's <acronym>SQL</> script files can contain any SQL commands, + except for transaction control commands (<command>BEGIN</>, + <command>COMMIT</>, etc) and commands that cannot be executed inside a + transaction block (such as <command>VACUUM</>). This is because the + script files are implicitly executed within a transaction block. + </para> + + <para> + While the script files can contain any characters allowed by the specified + encoding, control files should contain only plain ASCII, because there + is no way for <productname>PostgreSQL</> to know what encoding a + control file is in. In practice this is only an issue if you want to + use non-ASCII characters in the extension's comment. Recommended + practice in that case is to not use the control file <varname>comment</> + parameter, but instead use <command>COMMENT ON EXTENSION</> + within a script file to set the comment. + </para> + + </sect2> + + <sect2> + <title>Extension Relocatability</title> + + <para> + Users often wish to load the objects contained in an extension into a + different schema than the extension's author had in mind. There are + three supported levels of relocatability: + </para> <itemizedlist> <listitem> <para> - All functions accessed by the backend must present a C interface - to the backend; these C functions can then call C++ functions. - For example, <literal>extern C</> linkage is required for - backend-accessed functions. This is also necessary for any - functions that are passed as pointers between the backend and - C++ code. - </para> - </listitem> - <listitem> - <para> - Free memory using the appropriate deallocation method. For example, - most backend memory is allocated using <function>palloc()</>, so use - <function>pfree()</> to free it, i.e. using C++ - <function>delete()</> in such cases will fail. + A fully relocatable extension can be moved into another schema + at any time, even after it's been loaded into a database. + This is done with the <command>ALTER EXTENSION SET SCHEMA</> + command, which automatically renames all the member objects into + the new schema. Normally, this is only possible if the extension + contains no internal assumptions about what schema any of its + objects are in. Also, the extension's objects must all be in one + schema to begin with (ignoring objects that do not belong to any + schema, such as procedural languages). Mark a fully relocatable + extension by setting <literal>relocatable = true</> in its control + file. </para> </listitem> + <listitem> <para> - Prevent exceptions from propagating into the C code (use a - catch-all block at the top level of all <literal>extern C</> - functions). This is necessary even if the C++ code does not - throw any exceptions because events like out-of-memory still - throw exceptions. Any exceptions must be caught and appropriate - errors passed back to the C interface. If possible, compile C++ - with <option>-fno-exceptions</> to eliminate exceptions entirely; - in such cases, you must check for failures in your C++ code, e.g. - check for NULL returned by <function>new()</>. + An extension might be relocatable during installation but not + afterwards. This is typically the case if the extension's script + file needs to reference the target schema explicitly, for example + in setting <literal>search_path</> properties for SQL functions. + For such an extension, set <literal>relocatable = false</> in its + control file, and use <literal>@extschema@</> to refer to the target + schema in the script file. All occurrences of this string will be + replaced by the actual target schema's name before the script is + executed. The user can set the target schema using the + <literal>SCHEMA</> option of <command>CREATE EXTENSION</>. </para> </listitem> + <listitem> <para> - If calling backend functions from C++ code, be sure that the - C++ call stack contains only plain old data structure - (<acronym>POD</>). This is necessary because backend errors - generate a distant <function>longjump()</> that does not properly - unroll a C++ call stack with non-POD objects. + If the extension does not support relocation at all, set + <literal>relocatable = false</> in its control file, and also set + <literal>schema</> to the name of the intended target schema. This + will prevent use of the <literal>SCHEMA</> option of <command>CREATE + EXTENSION</>, unless it specifies the same schema named in the control + file. This choice is typically necessary if the extension contains + internal assumptions about schema names that can't be replaced by + uses of <literal>@extschema@</>. The <literal>@extschema@</> + substitution mechanism is available in this case too, although it is + of limited use since the schema name is determined by the control file. </para> </listitem> </itemizedlist> + + <para> + In all cases, the script file will be executed with + <xref linkend="guc-search-path"> initially set to point to the target + schema; that is, <command>CREATE EXTENSION</> does the equivalent of + this: +<programlisting> +SET LOCAL search_path TO @extschema@; +</programlisting> + This allows the objects created by the script file to go into the target + schema. The script file can change <varname>search_path</> if it wishes, + but that is generally undesirable. <varname>search_path</> is restored + to its previous setting upon completion of <command>CREATE EXTENSION</>. + </para> + + <para> + The target schema is determined by the <varname>schema</> parameter in + the control file if that is given, otherwise by the <literal>SCHEMA</> + option of <command>CREATE EXTENSION</> if that is given, otherwise the + current default object creation schema (the first one in the caller's + <varname>search_path</>). When the control file <varname>schema</> + parameter is used, the target schema will be created if it doesn't + already exist, but in the other two cases it must already exist. + </para> + + <para> + If any prerequisite extensions are listed in <varname>requires</varname> + in the control file, their target schemas are appended to the initial + setting of <varname>search_path</>. This allows their objects to be + visible to the new extension's script file. + </para> + + <para> + Although a non-relocatable extension can contain objects spread across + multiple schemas, it is usually desirable to place all the objects meant + for external use into a single schema, which is considered the extension's + target schema. Such an arrangement works conveniently with the default + setting of <varname>search_path</> during creation of dependent + extensions. + </para> + </sect2> + + <sect2> + <title>Extension Configuration Tables</title> + + <para> + Some extensions include configuration tables, which contain data that + might be added or changed by the user after installation of the + extension. Ordinarily, if a table is part of an extension, neither + the table's definition nor its content will be dumped by + <application>pg_dump</>. But that behavior is undesirable for a + configuration table; any data changes made by the user need to be + included in dumps, or the extension will behave differently after a dump + and reload. + </para> + + <para> + To solve this problem, an extension's script file can mark a table + it has created as a configuration table, which will cause + <application>pg_dump</> to include the table's contents (not its + definition) in dumps. To do that, call the function + <function>pg_extension_config_dump(regclass, text)</> after creating the + table, for example +<programlisting> +CREATE TABLE my_config (key text, value text); + +SELECT pg_catalog.pg_extension_config_dump('my_config', ''); +</programlisting> + Any number of tables can be marked this way. + </para> + + <para> + When the second argument of <function>pg_extension_config_dump</> is + an empty string, the entire contents of the table are dumped by + <application>pg_dump</>. This is usually only correct if the table + is initially empty as created by the extension script. If there is + a mixture of initial data and user-provided data in the table, + the second argument of <function>pg_extension_config_dump</> provides + a <literal>WHERE</> condition that selects the data to be dumped. + For example, you might do +<programlisting> +CREATE TABLE my_config (key text, value text, standard_entry boolean); + +SELECT pg_catalog.pg_extension_config_dump('my_config', 'WHERE NOT standard_entry'); +</programlisting> + and then make sure that <structfield>standard_entry</> is true only + in the rows created by the extension's script. + </para> + + <para> + More complicated situations, such as initially-provided rows that might + be modified by users, can be handled by creating triggers on the + configuration table to ensure that modified rows are marked correctly. + </para> + </sect2> + + <sect2> + <title>Extension Updates</title> + + <para> + One advantage of the extension mechanism is that it provides convenient + ways to manage updates to the SQL commands that define an extension's + objects. This is done by associating a version name or number with + each released version of the extension's installation script. + In addition, if you want users to be able to update their databases + dynamically from one version to the next, you should provide + <firstterm>update scripts</> that make the necessary changes to go from + one version to the next. Update scripts have names following the pattern + <literal><replaceable>extension</>--<replaceable>oldversion</>--<replaceable>newversion</>.sql</literal> + (for example, <literal>foo--1.0--1.1.sql</> contains the commands to modify + version <literal>1.0</> of extension <literal>foo</> into version + <literal>1.1</>). + </para> + + <para> + Given that a suitable update script is available, the command + <command>ALTER EXTENSION UPDATE</> will update an installed extension + to the specified new version. The update script is run in the same + environment that <command>CREATE EXTENSION</> provides for installation + scripts: in particular, <varname>search_path</> is set up in the same + way, and any new objects created by the script are automatically added + to the extension. + </para> + + <para> + If an extension has secondary control files, the control parameters + that are used for an update script are those associated with the script's + target (new) version. + </para> + + <para> + The update mechanism can be used to solve an important special case: + converting a <quote>loose</> collection of objects into an extension. + Before the extension mechanism was added to + <productname>PostgreSQL</productname> (in 9.1), many people wrote + extension modules that simply created assorted unpackaged objects. + Given an existing database containing such objects, how can we convert + the objects into a properly packaged extension? Dropping them and then + doing a plain <command>CREATE EXTENSION</> is one way, but it's not + desirable if the objects have dependencies (for example, if there are + table columns of a data type created by the extension). The way to fix + this situation is to create an empty extension, then use <command>ALTER + EXTENSION ADD</> to attach each pre-existing object to the extension, + then finally create any new objects that are in the current extension + version but were not in the unpackaged release. <command>CREATE + EXTENSION</> supports this case with its <literal>FROM</> <replaceable + class="parameter">old_version</> option, which causes it to not run the + normal installation script for the target version, but instead the update + script named + <literal><replaceable>extension</>--<replaceable>old_version</>--<replaceable>target_version</>.sql</literal>. + The choice of the dummy version name to use as <replaceable + class="parameter">old_version</> is up to the extension author, though + <literal>unpackaged</> is a common convention. If you have multiple + prior versions you need to be able to update into extension style, use + multiple dummy version names to identify them. + </para> + + <para> + <command>ALTER EXTENSION</> is able to execute sequences of update + script files to achieve a requested update. For example, if only + <literal>foo--1.0--1.1.sql</> and <literal>foo--1.1--2.0.sql</> are + available, <command>ALTER EXTENSION</> will apply them in sequence if an + update to version <literal>2.0</> is requested when <literal>1.0</> is + currently installed. + </para> + + <para> + <productname>PostgreSQL</> doesn't assume anything about the properties + of version names: for example, it does not know whether <literal>1.1</> + follows <literal>1.0</>. It just matches up the available version names + and follows the path that requires applying the fewest update scripts. + (A version name can actually be any string that doesn't contain + <literal>--</> or leading or trailing <literal>-</>.) + </para> + + <para> + Sometimes it is useful to provide <quote>downgrade</> scripts, for + example <literal>foo--1.1--1.0.sql</> to allow reverting the changes + associated with version <literal>1.1</>. If you do that, be careful + of the possibility that a downgrade script might unexpectedly + get applied because it yields a shorter path. The risky case is where + there is a <quote>fast path</> update script that jumps ahead several + versions as well as a downgrade script to the fast path's start point. + It might take fewer steps to apply the downgrade and then the fast + path than to move ahead one version at a time. If the downgrade script + drops any irreplaceable objects, this will yield undesirable results. + </para> + + <para> + To check for unexpected update paths, use this command: +<programlisting> +SELECT * FROM pg_extension_update_paths('<replaceable>extension_name</>'); +</programlisting> + This shows each pair of distinct known version names for the specified + extension, together with the update path sequence that would be taken to + get from the source version to the target version, or <literal>NULL</> if + there is no available update path. The path is shown in textual form + with <literal>--</> separators. You can use + <literal>regexp_split_to_array(path,'--')</> if you prefer an array + format. + </para> + </sect2> + + <sect2> + <title>Extension Example</title> + + <para> + Here is a complete example of an <acronym>SQL</>-only + extension, a two-element composite type that can store any type of value + in its slots, which are named <quote>k</> and <quote>v</>. Non-text + values are automatically coerced to text for storage. + </para> + + <para> + The script file <filename>pair--1.0.sql</> looks like this: + +<programlisting><![CDATA[ +CREATE TYPE pair AS ( k text, v text ); + +CREATE OR REPLACE FUNCTION pair(anyelement, text) +RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::pair'; + +CREATE OR REPLACE FUNCTION pair(text, anyelement) +RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::pair'; + +CREATE OR REPLACE FUNCTION pair(anyelement, anyelement) +RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::pair'; + +CREATE OR REPLACE FUNCTION pair(text, text) +RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::pair;'; + +CREATE OPERATOR ~> (LEFTARG = text, RIGHTARG = anyelement, PROCEDURE = pair); +CREATE OPERATOR ~> (LEFTARG = anyelement, RIGHTARG = text, PROCEDURE = pair); +CREATE OPERATOR ~> (LEFTARG = anyelement, RIGHTARG = anyelement, PROCEDURE = pair); +CREATE OPERATOR ~> (LEFTARG = text, RIGHTARG = text, PROCEDURE = pair); +]]> +</programlisting> + </para> + + <para> + The control file <filename>pair.control</> looks like this: + +<programlisting> +# pair extension +comment = 'A key/value pair data type' +default_version = '1.0' +relocatable = true +</programlisting> + </para> + + <para> + While you hardly need a makefile to install these two files into the + correct directory, you could use a <filename>Makefile</> containing this: + +<programlisting> +EXTENSION = pair +DATA = pair--1.0.sql + +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +</programlisting> + + This makefile relies on <acronym>PGXS</acronym>, which is described + in <xref linkend="extend-pgxs">. The command <literal>make install</> + will install the control and script files into the correct + directory as reported by <application>pg_config</>. + </para> + + <para> + Once the files are installed, use the + <xref linkend="sql-createextension"> command to load the objects into + any particular database. + </para> + </sect2> + </sect1> + + <sect1 id="extend-pgxs"> + <title>Extension Building Infrastructure</title> + + <indexterm zone="extend-pgxs"> + <primary>pgxs</primary> + </indexterm> + + <para> + If you are thinking about distributing your + <productname>PostgreSQL</> extension modules, setting up a + portable build system for them can be fairly difficult. Therefore + the <productname>PostgreSQL</> installation provides a build + infrastructure for extensions, called <acronym>PGXS</acronym>, so + that simple extension modules can be built simply against an + already installed server. <acronym>PGXS</acronym> is mainly intended + for extensions that include C code, although it can be used for + pure-SQL extensions too. Note that <acronym>PGXS</acronym> is not + intended to be a universal build system framework that can be used + to build any software interfacing to <productname>PostgreSQL</>; + it simply automates common build rules for simple server extension + modules. For more complicated packages, you might need to write your + own build system. </para> <para> - In summary, it is best to place C++ code behind a wall of - <literal>extern C</> functions that interface to the backend, - and avoid exception, memory, and call stack leakage. + To use the <acronym>PGXS</acronym> infrastructure for your extension, + you must write a simple makefile. + In the makefile, you need to set some variables + and finally include the global <acronym>PGXS</acronym> makefile. + Here is an example that builds an extension module named + <literal>isbn_issn</literal>, consisting of a shared library containing + some C code, an extension control file, a SQL script, and a documentation + text file: +<programlisting> +MODULES = isbn_issn +EXTENSION = isbn_issn +DATA = isbn_issn--1.0.sql +DOCS = README.isbn_issn + +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +</programlisting> + The last three lines should always be the same. Earlier in the + file, you assign variables or add custom + <application>make</application> rules. </para> + + <para> + Set one of these three variables to specify what is built: + + <variablelist> + <varlistentry> + <term><varname>MODULES</varname></term> + <listitem> + <para> + list of shared-library objects to be built from source files with same + stem (do not include library suffixes in this list) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>MODULE_big</varname></term> + <listitem> + <para> + a shared library to build from multiple source files + (list object files in <varname>OBJS</varname>) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>PROGRAM</varname></term> + <listitem> + <para> + an executable program to build + (list object files in <varname>OBJS</varname>) + </para> + </listitem> + </varlistentry> + </variablelist> + + The following variables can also be set: + + <variablelist> + <varlistentry> + <term><varname>EXTENSION</varname></term> + <listitem> + <para> + extension name(s); for each name you must provide an + <literal><replaceable>extension</replaceable>.control</literal> file, + which will be installed into + <literal><replaceable>prefix</replaceable>/share/extension</literal> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>MODULEDIR</varname></term> + <listitem> + <para> + subdirectory of <literal><replaceable>prefix</>/share</literal> + into which DATA and DOCS files should be installed + (if not set, default is <literal>extension</literal> if + <varname>EXTENSION</varname> is set, + or <literal>contrib</literal> if not) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>DATA</varname></term> + <listitem> + <para> + random files to install into <literal><replaceable>prefix</replaceable>/share/$MODULEDIR</literal> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>DATA_built</varname></term> + <listitem> + <para> + random files to install into + <literal><replaceable>prefix</replaceable>/share/$MODULEDIR</literal>, + which need to be built first + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>DATA_TSEARCH</varname></term> + <listitem> + <para> + random files to install under + <literal><replaceable>prefix</replaceable>/share/tsearch_data</literal> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>DOCS</varname></term> + <listitem> + <para> + random files to install under + <literal><replaceable>prefix</replaceable>/doc/$MODULEDIR</literal> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>SCRIPTS</varname></term> + <listitem> + <para> + script files (not binaries) to install into + <literal><replaceable>prefix</replaceable>/bin</literal> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>SCRIPTS_built</varname></term> + <listitem> + <para> + script files (not binaries) to install into + <literal><replaceable>prefix</replaceable>/bin</literal>, + which need to be built first + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>REGRESS</varname></term> + <listitem> + <para> + list of regression test cases (without suffix), see below + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>EXTRA_CLEAN</varname></term> + <listitem> + <para> + extra files to remove in <literal>make clean</literal> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>PG_CPPFLAGS</varname></term> + <listitem> + <para> + will be added to <varname>CPPFLAGS</varname> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>PG_LIBS</varname></term> + <listitem> + <para> + will be added to <varname>PROGRAM</varname> link line + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>SHLIB_LINK</varname></term> + <listitem> + <para> + will be added to <varname>MODULE_big</varname> link line + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>PG_CONFIG</varname></term> + <listitem> + <para> + path to <application>pg_config</> program for the + <productname>PostgreSQL</productname> installation to build against + (typically just <literal>pg_config</> to use the first one in your + <varname>PATH</>) + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <para> + Put this makefile as <literal>Makefile</literal> in the directory + which holds your extension. Then you can do + <literal>make</literal> to compile, and then <literal>make + install</literal> to install your module. By default, the extension is + compiled and installed for the + <productname>PostgreSQL</productname> installation that + corresponds to the first <command>pg_config</command> program + found in your <varname>PATH</>. You can use a different installation by + setting <varname>PG_CONFIG</varname> to point to its + <command>pg_config</command> program, either within the makefile + or on the <literal>make</literal> command line. + </para> + + <caution> + <para> + Changing <varname>PG_CONFIG</varname> only works when building + against <productname>PostgreSQL</productname> 8.3 or later. + With older releases it does not work to set it to anything except + <literal>pg_config</>; you must alter your <varname>PATH</> + to select the installation to build against. + </para> + </caution> + + <para> + The scripts listed in the <varname>REGRESS</> variable are used for + regression testing of your module, which can be invoked by <literal>make + installcheck</literal> after doing <literal>make install</>. For this to + work you must have a running <productname>PostgreSQL</productname> server. + The script files listed in <varname>REGRESS</> must appear in a + subdirectory named <literal>sql/</literal> in your extension's directory. + These files must have extension <literal>.sql</literal>, which must not be + included in the <varname>REGRESS</varname> list in the makefile. For each + test there should also be a file containing the expected output in a + subdirectory named <literal>expected/</literal>, with the same stem and + extension <literal>.out</literal>. <literal>make installcheck</literal> + executes each test script with <application>psql</>, and compares the + resulting output to the matching expected file. Any differences will be + written to the file <literal>regression.diffs</literal> in <command>diff + -c</command> format. Note that trying to run a test that is missing its + expected file will be reported as <quote>trouble</quote>, so make sure you + have all expected files. + </para> + + <tip> + <para> + The easiest way to create the expected files is to create empty files, + then do a test run (which will of course report differences). Inspect + the actual result files found in the <literal>results/</literal> + directory, then copy them to <literal>expected/</literal> if they match + what you expect from the test. + </para> + + </tip> </sect1> </chapter> diff --git a/doc/src/sgml/external-projects.sgml b/doc/src/sgml/external-projects.sgml index 7e647cc985..ef516b4214 100644 --- a/doc/src/sgml/external-projects.sgml +++ b/doc/src/sgml/external-projects.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/external-projects.sgml,v 1.20 2010/06/07 02:01:08 itagaki Exp $ --> +<!-- doc/src/sgml/external-projects.sgml --> <appendix id="external-projects"> <title>External Projects</title> @@ -17,10 +17,10 @@ projects that are maintained outside the core <productname>PostgreSQL</> distribution. PgFoundry is built using the GForge software project and is similar to <ulink url="http://sourceforge.net">SourceForge.net</> in its - feature set, providing mailing lists, forums, bug tracking, CVS, and web + feature set, providing mailing lists, forums, bug tracking, SCM, and web hosting. If you have a <productname>PostgreSQL</>-related open source - project that you would like to have hosted at PgFoundy, please feel free - to create a new project. + project that you would like to have hosted at PgFoundry, please feel free + to create a new project there. </para> <sect1 id="external-interfaces"> @@ -45,7 +45,7 @@ <listitem> <para> - <link linkend="ecpg">ecpg</link> is included because it depends on the + <link linkend="ecpg">ECPG</link> is included because it depends on the server-side SQL grammar, and is therefore sensitive to changes in <productname>PostgreSQL</productname> itself. </para> @@ -61,7 +61,7 @@ </para> <table id="language-interface-table"> - <title>Externally Maintained Client Interfaces</> + <title>Externally Maintained Client Interfaces</title> <tgroup cols="4"> <thead> @@ -134,6 +134,22 @@ </table> </sect1> + <sect1 id="external-admin-tools"> + <title>Administration Tools</title> + + <indexterm> + <primary>administration tools</primary> + <secondary>externally maintained</secondary> + </indexterm> + + <para> + There are several administration tools available for + <productname>PostgreSQL</>. The most popular is + <application><ulink url="http://www.pgadmin.org/">pgAdmin III</ulink></>, + and there are several commercially available ones as well. + </para> + </sect1> + <sect1 id="external-pl"> <title>Procedural Languages</title> @@ -145,7 +161,7 @@ <para> <productname>PostgreSQL</productname> includes several procedural languages with the base distribution: <link - linkend="plpgsql">PL/PgSQL</link>, <link linkend="pltcl">PL/Tcl</link>, + linkend="plpgsql">PL/pgSQL</link>, <link linkend="pltcl">PL/Tcl</link>, <link linkend="plperl">PL/Perl</link>, and <link linkend="plpython">PL/Python</link>. </para> @@ -218,37 +234,29 @@ </tgroup> </table> </sect1> - + <sect1 id="external-extensions"> <title>Extensions</title> <indexterm> - <primary>extensions</primary> + <primary>extension</primary> + <secondary>externally maintained</secondary> </indexterm> <para> <productname>PostgreSQL</> is designed to be easily extensible. For - this reason, extensions loaded into the database can function just - like features that are packaged with the database. The + this reason, extensions loaded into the database can function + just like features that are built in. The <filename>contrib/</> directory shipped with the source code - contains a large number of extensions. The <filename>README</> file - in that directory contains a summary. They include conversion - tools, full-text indexing, <acronym>XML</> tools, and additional - data types and indexing methods. Other extensions are developed + contains several extensions, which are described in + <xref linkend="contrib">. Other extensions are developed independently, like <application><ulink url="http://www.postgis.org/">PostGIS</ulink></>. Even - <productname>PostgreSQL</> replication solutions are developed + <productname>PostgreSQL</> replication solutions can be developed externally. For example, <application> <ulink url="http://www.slony.info">Slony-I</ulink></> is a popular master/standby replication solution that is developed independently from the core project. </para> - - <para> - There are several administration tools available for - <productname>PostgreSQL</>. The most popular is - <application><ulink url="http://www.pgadmin.org/">pgAdmin III</ulink></>, - and there are several commercially available ones as well. - </para> </sect1> </appendix> diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml new file mode 100644 index 0000000000..fc07f129b7 --- /dev/null +++ b/doc/src/sgml/fdwhandler.sgml @@ -0,0 +1,212 @@ +<!-- doc/src/sgml/fdwhandler.sgml --> + + <chapter id="fdwhandler"> + <title>Writing A Foreign Data Wrapper</title> + + <indexterm zone="fdwhandler"> + <primary>foreign data wrapper</primary> + <secondary>handler for</secondary> + </indexterm> + + <para> + All operations on a foreign table are handled through its foreign data + wrapper, which consists of a set of functions that the planner and + executor call. The foreign data wrapper is responsible for fetching + data from the remote data source and returning it to the + <productname>PostgreSQL</productname> executor. This chapter outlines how + to write a new foreign data wrapper. + </para> + + <para> + The FDW author needs to implement a handler function, and optionally + a validator function. Both functions must be written in a compiled + language such as C, using the version-1 interface. + For details on C language calling conventions and dynamic loading, + see <xref linkend="xfunc-c">. + </para> + + <para> + The handler function simply returns a struct of function pointers to + callback functions that will be called by the planner and executor. + Most of the effort in writing an FDW is in implementing these callback + functions. + The handler function must be registered with + <productname>PostgreSQL</productname> as taking no arguments and returning + the special pseudo-type <type>fdw_handler</type>. + The callback functions are plain C functions and are not visible or + callable at the SQL level. + </para> + + <para> + The validator function is responsible for validating options given in the + <command>CREATE FOREIGN DATA WRAPPER</command>, <command>CREATE + SERVER</command> and <command>CREATE FOREIGN TABLE</command> commands. + The validator function must be registered as taking two arguments, a text + array containing the options to be validated, and an OID representing the + type of object the options are associated with (in the form of the OID + of the system catalog the object would be stored in). If no validator + function is supplied, the options are not checked at object creation time. + </para> + + <para> + The foreign data wrappers included in the standard distribution are good + references when trying to write your own. Look into the + <filename>contrib/file_fdw</> subdirectory of the source tree. + The <xref linkend="sql-createforeigndatawrapper"> reference page also has + some useful details. + </para> + + <note> + <para> + The SQL standard specifies an interface for writing foreign data wrappers. + However, PostgreSQL does not implement that API, because the effort to + accommodate it into PostgreSQL would be large, and the standard API hasn't + gained wide adoption anyway. + </para> + </note> + + <sect1 id="fdw-routines"> + <title>Foreign Data Wrapper Callback Routines</title> + + <para> + The FDW handler function returns a palloc'd <structname>FdwRoutine</> + struct containing pointers to the following callback functions: + </para> + + <para> +<programlisting> +FdwPlan * +PlanForeignScan (Oid foreigntableid, + PlannerInfo *root, + RelOptInfo *baserel); +</programlisting> + + Plan a scan on a foreign table. This is called when a query is planned. + <literal>foreigntableid</> is the <structname>pg_class</> OID of the + foreign table. <literal>root</> is the planner's global information + about the query, and <literal>baserel</> is the planner's information + about this table. + The function must return a palloc'd struct that contains cost estimates + plus any FDW-private information that is needed to execute the foreign + scan at a later time. (Note that the private information must be + represented in a form that <function>copyObject</> knows how to copy.) + </para> + + <para> + The information in <literal>root</> and <literal>baserel</> can be used + to reduce the amount of information that has to be fetched from the + foreign table (and therefore reduce the cost estimate). + <literal>baserel->baserestrictinfo</> is particularly interesting, as + it contains restriction quals (<literal>WHERE</> clauses) that can be + used to filter the rows to be fetched. (The FDW is not required to + enforce these quals, as the finished plan will recheck them anyway.) + <literal>baserel->reltargetlist</> can be used to determine which + columns need to be fetched. + </para> + + <para> + In addition to returning cost estimates, the function should update + <literal>baserel->rows</> to be the expected number of rows returned + by the scan, after accounting for the filtering done by the restriction + quals. The initial value of <literal>baserel->rows</> is just a + constant default estimate, which should be replaced if at all possible. + The function may also choose to update <literal>baserel->width</> if + it can compute a better estimate of the average result row width. + </para> + + <para> +<programlisting> +void +ExplainForeignScan (ForeignScanState *node, + ExplainState *es); +</programlisting> + + Print additional <command>EXPLAIN</> output for a foreign table scan. + This can just return if there is no need to print anything. + Otherwise, it should call <function>ExplainPropertyText</> and + related functions to add fields to the <command>EXPLAIN</> output. + The flag fields in <literal>es</> can be used to determine what to + print, and the state of the <structname>ForeignScanState</> node + can be inspected to provide runtime statistics in the <command>EXPLAIN + ANALYZE</> case. + </para> + + <para> +<programlisting> +void +BeginForeignScan (ForeignScanState *node, + int eflags); +</programlisting> + + Begin executing a foreign scan. This is called during executor startup. + It should perform any initialization needed before the scan can start. + The <structname>ForeignScanState</> node has already been created, but + its <structfield>fdw_state</> field is still NULL. Information about + the table to scan is accessible through the + <structname>ForeignScanState</> node (in particular, from the underlying + <structname>ForeignScan</> plan node, which contains a pointer to the + <structname>FdwPlan</> structure returned by + <function>PlanForeignScan</>). + </para> + + <para> + Note that when <literal>(eflags & EXEC_FLAG_EXPLAIN_ONLY)</> is + true, this function should not perform any externally-visible actions; + it should only do the minimum required to make the node state valid + for <function>ExplainForeignScan</> and <function>EndForeignScan</>. + </para> + + <para> +<programlisting> +TupleTableSlot * +IterateForeignScan (ForeignScanState *node); +</programlisting> + + Fetch one row from the foreign source, returning it in a tuple table slot + (the node's <structfield>ScanTupleSlot</> should be used for this + purpose). Return NULL if no more rows are available. The tuple table + slot infrastructure allows either a physical or virtual tuple to be + returned; in most cases the latter choice is preferable from a + performance standpoint. Note that this is called in a short-lived memory + context that will be reset between invocations. Create a memory context + in <function>BeginForeignScan</> if you need longer-lived storage, or use + the <structfield>es_query_cxt</> of the node's <structname>EState</>. + </para> + + <para> + The rows returned must match the column signature of the foreign table + being scanned. If you choose to optimize away fetching columns that + are not needed, you should insert nulls in those column positions. + </para> + + <para> +<programlisting> +void +ReScanForeignScan (ForeignScanState *node); +</programlisting> + + Restart the scan from the beginning. Note that any parameters the + scan depends on may have changed value, so the new scan does not + necessarily return exactly the same rows. + </para> + + <para> +<programlisting> +void +EndForeignScan (ForeignScanState *node); +</programlisting> + + End the scan and release resources. It is normally not important + to release palloc'd memory, but for example open files and connections + to remote servers should be cleaned up. + </para> + + <para> + The <structname>FdwRoutine</> and <structname>FdwPlan</> struct types + are declared in <filename>src/include/foreign/fdwapi.h</>, which see + for additional details. + </para> + + </sect1> + + </chapter> diff --git a/doc/src/sgml/features.sgml b/doc/src/sgml/features.sgml index 56b5be3318..fbaeca6ed3 100644 --- a/doc/src/sgml/features.sgml +++ b/doc/src/sgml/features.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/features.sgml,v 2.30 2008/12/19 16:25:16 petere Exp $ --> +<!-- doc/src/sgml/features.sgml --> <appendix id="features"> <title>SQL Conformance</title> diff --git a/doc/src/sgml/file-fdw.sgml b/doc/src/sgml/file-fdw.sgml new file mode 100644 index 0000000000..8497d9a45f --- /dev/null +++ b/doc/src/sgml/file-fdw.sgml @@ -0,0 +1,138 @@ +<!-- doc/src/sgml/file-fdw.sgml --> + +<sect1 id="file-fdw" xreflabel="file_fdw"> + <title>file_fdw</title> + + <indexterm zone="file-fdw"> + <primary>file_fdw</primary> + </indexterm> + + <para> + The <filename>file_fdw</> module provides the foreign-data wrapper + <function>file_fdw</function>, which can be used to access data + files in the server's file system. Data files must be in a format + that can be read by <command>COPY FROM</command>; + see <xref linkend="sql-copy"> for details. + </para> + + <para> + A foreign table created using this wrapper can have the following options: + </para> + + <variablelist> + + <varlistentry> + <term><literal>filename</literal></term> + + <listitem> + <para> + Specifies the file to be read. Required. Must be an absolute path name. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>format</literal></term> + + <listitem> + <para> + Specifies the file's format, + the same as <command>COPY</>'s <literal>FORMAT</literal> option. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>header</literal></term> + + <listitem> + <para> + Specifies whether the file has a header line, + the same as <command>COPY</>'s <literal>HEADER</literal> option. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>delimiter</literal></term> + + <listitem> + <para> + Specifies the file's delimiter character, + the same as <command>COPY</>'s <literal>DELIMITER</literal> option. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>quote</literal></term> + + <listitem> + <para> + Specifies the file's quote character, + the same as <command>COPY</>'s <literal>QUOTE</literal> option. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>escape</literal></term> + + <listitem> + <para> + Specifies the file's escape character, + the same as <command>COPY</>'s <literal>ESCAPE</literal> option. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>null</literal></term> + + <listitem> + <para> + Specifies the file's null string, + the same as <command>COPY</>'s <literal>NULL</literal> option. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>encoding</literal></term> + + <listitem> + <para> + Specifies the file's encoding. + the same as <command>COPY</>'s <literal>ENCODING</literal> option. + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + <command>COPY</>'s <literal>OIDS</literal>, <literal>FORCE_QUOTE</literal>, + and <literal>FORCE_NOT_NULL</literal> options are currently not supported by + <literal>file_fdw</>. + </para> + + <para> + These options can only be specified for a foreign table, not in the + options of the <literal>file_fdw</> foreign-data wrapper, nor in the + options of a server or user mapping using the wrapper. + </para> + + <para> + Changing table-level options requires superuser privileges, for security + reasons: only a superuser should be able to determine which file is read. + In principle non-superusers could be allowed to change the other options, + but that's not supported at present. + </para> + + <para> + For a foreign table using <literal>file_fdw</>, <command>EXPLAIN</> shows + the name of the file to be read. Unless <literal>COSTS OFF</> is + specified, the file size (in bytes) is shown as well. + </para> + +</sect1> diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index 30b5fca72d..ed39e0b661 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -1,167 +1,176 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/filelist.sgml,v 1.69 2010/06/14 17:25:24 sriggs Exp $ --> +<!-- doc/src/sgml/filelist.sgml --> -<!entity history SYSTEM "history.sgml"> -<!entity info SYSTEM "info.sgml"> -<!entity intro SYSTEM "intro.sgml"> -<!entity legal SYSTEM "legal.sgml"> -<!entity notation SYSTEM "notation.sgml"> -<!entity problems SYSTEM "problems.sgml"> +<!ENTITY history SYSTEM "history.sgml"> +<!ENTITY info SYSTEM "info.sgml"> +<!ENTITY intro SYSTEM "intro.sgml"> +<!ENTITY legal SYSTEM "legal.sgml"> +<!ENTITY notation SYSTEM "notation.sgml"> +<!ENTITY problems SYSTEM "problems.sgml"> <!-- tutorial --> -<!entity advanced SYSTEM "advanced.sgml"> -<!entity query SYSTEM "query.sgml"> -<!entity start SYSTEM "start.sgml"> +<!ENTITY advanced SYSTEM "advanced.sgml"> +<!ENTITY query SYSTEM "query.sgml"> +<!ENTITY start SYSTEM "start.sgml"> <!-- currently unused, but contains some interesting information --> -<!entity sql SYSTEM "sql.sgml"> +<!ENTITY sql SYSTEM "sql.sgml"> <!-- user's guide --> -<!entity array SYSTEM "array.sgml"> -<!entity datatype SYSTEM "datatype.sgml"> -<!entity ddl SYSTEM "ddl.sgml"> -<!entity dml SYSTEM "dml.sgml"> -<!entity func SYSTEM "func.sgml"> -<!entity indices SYSTEM "indices.sgml"> -<!entity mvcc SYSTEM "mvcc.sgml"> -<!entity perform SYSTEM "perform.sgml"> -<!entity queries SYSTEM "queries.sgml"> -<!entity rowtypes SYSTEM "rowtypes.sgml"> -<!entity syntax SYSTEM "syntax.sgml"> -<!entity textsearch SYSTEM "textsearch.sgml"> -<!entity typeconv SYSTEM "typeconv.sgml"> +<!ENTITY array SYSTEM "array.sgml"> +<!ENTITY datatype SYSTEM "datatype.sgml"> +<!ENTITY ddl SYSTEM "ddl.sgml"> +<!ENTITY dml SYSTEM "dml.sgml"> +<!ENTITY func SYSTEM "func.sgml"> +<!ENTITY indices SYSTEM "indices.sgml"> +<!ENTITY mvcc SYSTEM "mvcc.sgml"> +<!ENTITY perform SYSTEM "perform.sgml"> +<!ENTITY queries SYSTEM "queries.sgml"> +<!ENTITY rowtypes SYSTEM "rowtypes.sgml"> +<!ENTITY syntax SYSTEM "syntax.sgml"> +<!ENTITY textsearch SYSTEM "textsearch.sgml"> +<!ENTITY typeconv SYSTEM "typeconv.sgml"> <!-- administrator's guide --> -<!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 installw SYSTEM "install-win32.sgml"> -<!entity maintenance SYSTEM "maintenance.sgml"> -<!entity manage-ag SYSTEM "manage-ag.sgml"> -<!entity monitoring SYSTEM "monitoring.sgml"> -<!entity regress SYSTEM "regress.sgml"> -<!entity recovery-config SYSTEM "recovery-config.sgml"> -<!entity runtime SYSTEM "runtime.sgml"> -<!entity config SYSTEM "config.sgml"> -<!entity user-manag SYSTEM "user-manag.sgml"> -<!entity wal SYSTEM "wal.sgml"> +<!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 installw SYSTEM "install-windows.sgml"> +<!ENTITY maintenance SYSTEM "maintenance.sgml"> +<!ENTITY manage-ag SYSTEM "manage-ag.sgml"> +<!ENTITY monitoring SYSTEM "monitoring.sgml"> +<!ENTITY regress SYSTEM "regress.sgml"> +<!ENTITY recovery-config SYSTEM "recovery-config.sgml"> +<!ENTITY runtime SYSTEM "runtime.sgml"> +<!ENTITY config SYSTEM "config.sgml"> +<!ENTITY user-manag SYSTEM "user-manag.sgml"> +<!ENTITY wal SYSTEM "wal.sgml"> <!-- programmer's guide --> -<!entity dfunc SYSTEM "dfunc.sgml"> -<!entity ecpg SYSTEM "ecpg.sgml"> -<!entity extend SYSTEM "extend.sgml"> -<!entity external-projects SYSTEM "external-projects.sgml"> -<!entity func-ref SYSTEM "func-ref.sgml"> -<!entity infoschema SYSTEM "information_schema.sgml"> -<!entity libpq SYSTEM "libpq.sgml"> -<!entity lobj SYSTEM "lobj.sgml"> -<!entity rules SYSTEM "rules.sgml"> -<!entity spi SYSTEM "spi.sgml"> -<!entity trigger SYSTEM "trigger.sgml"> -<!entity xaggr SYSTEM "xaggr.sgml"> -<!entity xfunc SYSTEM "xfunc.sgml"> -<!entity xindex SYSTEM "xindex.sgml"> -<!entity xplang SYSTEM "xplang.sgml"> -<!entity xoper SYSTEM "xoper.sgml"> -<!entity xtypes SYSTEM "xtypes.sgml"> -<!entity plperl SYSTEM "plperl.sgml"> -<!entity plpython SYSTEM "plpython.sgml"> -<!entity plsql SYSTEM "plpgsql.sgml"> -<!entity pltcl SYSTEM "pltcl.sgml"> +<!ENTITY dfunc SYSTEM "dfunc.sgml"> +<!ENTITY ecpg SYSTEM "ecpg.sgml"> +<!ENTITY extend SYSTEM "extend.sgml"> +<!ENTITY external-projects SYSTEM "external-projects.sgml"> +<!ENTITY func-ref SYSTEM "func-ref.sgml"> +<!ENTITY infoschema SYSTEM "information_schema.sgml"> +<!ENTITY libpq SYSTEM "libpq.sgml"> +<!ENTITY lobj SYSTEM "lobj.sgml"> +<!ENTITY rules SYSTEM "rules.sgml"> +<!ENTITY spi SYSTEM "spi.sgml"> +<!ENTITY trigger SYSTEM "trigger.sgml"> +<!ENTITY xaggr SYSTEM "xaggr.sgml"> +<!ENTITY xfunc SYSTEM "xfunc.sgml"> +<!ENTITY xindex SYSTEM "xindex.sgml"> +<!ENTITY xplang SYSTEM "xplang.sgml"> +<!ENTITY xoper SYSTEM "xoper.sgml"> +<!ENTITY xtypes SYSTEM "xtypes.sgml"> +<!ENTITY plperl SYSTEM "plperl.sgml"> +<!ENTITY plpython SYSTEM "plpython.sgml"> +<!ENTITY plsql SYSTEM "plpgsql.sgml"> +<!ENTITY pltcl SYSTEM "pltcl.sgml"> <!-- reference pages --> -<!entity % allfiles SYSTEM "ref/allfiles.sgml"> +<!ENTITY % allfiles SYSTEM "ref/allfiles.sgml"> %allfiles; <!-- developer's guide --> -<!entity arch-dev SYSTEM "arch-dev.sgml"> -<!entity bki SYSTEM "bki.sgml"> -<!entity catalogs SYSTEM "catalogs.sgml"> -<!entity geqo SYSTEM "geqo.sgml"> -<!entity gist SYSTEM "gist.sgml"> -<!entity gin SYSTEM "gin.sgml"> -<!entity planstats SYSTEM "planstats.sgml"> -<!entity indexam SYSTEM "indexam.sgml"> -<!entity nls SYSTEM "nls.sgml"> -<!entity plhandler SYSTEM "plhandler.sgml"> -<!entity protocol SYSTEM "protocol.sgml"> -<!entity sources SYSTEM "sources.sgml"> -<!entity storage SYSTEM "storage.sgml"> +<!ENTITY arch-dev SYSTEM "arch-dev.sgml"> +<!ENTITY bki SYSTEM "bki.sgml"> +<!ENTITY catalogs SYSTEM "catalogs.sgml"> +<!ENTITY geqo SYSTEM "geqo.sgml"> +<!ENTITY gist SYSTEM "gist.sgml"> +<!ENTITY gin SYSTEM "gin.sgml"> +<!ENTITY planstats SYSTEM "planstats.sgml"> +<!ENTITY indexam SYSTEM "indexam.sgml"> +<!ENTITY nls SYSTEM "nls.sgml"> +<!ENTITY plhandler SYSTEM "plhandler.sgml"> +<!ENTITY fdwhandler SYSTEM "fdwhandler.sgml"> +<!ENTITY protocol SYSTEM "protocol.sgml"> +<!ENTITY sources SYSTEM "sources.sgml"> +<!ENTITY storage SYSTEM "storage.sgml"> <!-- contrib information --> -<!entity contrib SYSTEM "contrib.sgml"> -<!entity adminpack SYSTEM "adminpack.sgml"> -<!entity auto-explain SYSTEM "auto-explain.sgml"> -<!entity btree-gin SYSTEM "btree-gin.sgml"> -<!entity btree-gist SYSTEM "btree-gist.sgml"> -<!entity chkpass SYSTEM "chkpass.sgml"> -<!entity citext SYSTEM "citext.sgml"> -<!entity cube SYSTEM "cube.sgml"> -<!entity dblink SYSTEM "dblink.sgml"> -<!entity dict-int SYSTEM "dict-int.sgml"> -<!entity dict-xsyn SYSTEM "dict-xsyn.sgml"> -<!entity earthdistance SYSTEM "earthdistance.sgml"> -<!entity fuzzystrmatch SYSTEM "fuzzystrmatch.sgml"> -<!entity hstore SYSTEM "hstore.sgml"> -<!entity intagg SYSTEM "intagg.sgml"> -<!entity intarray SYSTEM "intarray.sgml"> -<!entity isn SYSTEM "isn.sgml"> -<!entity lo SYSTEM "lo.sgml"> -<!entity ltree SYSTEM "ltree.sgml"> -<!entity oid2name SYSTEM "oid2name.sgml"> -<!entity pageinspect SYSTEM "pageinspect.sgml"> -<!entity passwordcheck SYSTEM "passwordcheck.sgml"> -<!entity pgbench SYSTEM "pgbench.sgml"> -<!entity pgarchivecleanup SYSTEM "pgarchivecleanup.sgml"> -<!entity pgbuffercache SYSTEM "pgbuffercache.sgml"> -<!entity pgcrypto SYSTEM "pgcrypto.sgml"> -<!entity pgfreespacemap SYSTEM "pgfreespacemap.sgml"> -<!entity pgrowlocks SYSTEM "pgrowlocks.sgml"> -<!entity pgstandby SYSTEM "pgstandby.sgml"> -<!entity pgstatstatements SYSTEM "pgstatstatements.sgml"> -<!entity pgstattuple SYSTEM "pgstattuple.sgml"> -<!entity pgtrgm SYSTEM "pgtrgm.sgml"> -<!entity pgupgrade SYSTEM "pgupgrade.sgml"> -<!entity seg SYSTEM "seg.sgml"> -<!entity contrib-spi SYSTEM "contrib-spi.sgml"> -<!entity sslinfo SYSTEM "sslinfo.sgml"> -<!entity tablefunc SYSTEM "tablefunc.sgml"> -<!entity test-parser SYSTEM "test-parser.sgml"> -<!entity tsearch2 SYSTEM "tsearch2.sgml"> -<!entity unaccent SYSTEM "unaccent.sgml"> -<!entity uuid-ossp SYSTEM "uuid-ossp.sgml"> -<!entity vacuumlo SYSTEM "vacuumlo.sgml"> -<!entity xml2 SYSTEM "xml2.sgml"> +<!ENTITY contrib SYSTEM "contrib.sgml"> +<!ENTITY adminpack SYSTEM "adminpack.sgml"> +<!ENTITY auth-delay SYSTEM "auth-delay.sgml"> +<!ENTITY auto-explain SYSTEM "auto-explain.sgml"> +<!ENTITY btree-gin SYSTEM "btree-gin.sgml"> +<!ENTITY btree-gist SYSTEM "btree-gist.sgml"> +<!ENTITY chkpass SYSTEM "chkpass.sgml"> +<!ENTITY citext SYSTEM "citext.sgml"> +<!ENTITY cube SYSTEM "cube.sgml"> +<!ENTITY dblink SYSTEM "dblink.sgml"> +<!ENTITY dict-int SYSTEM "dict-int.sgml"> +<!ENTITY dict-xsyn SYSTEM "dict-xsyn.sgml"> +<!ENTITY dummy-seclabel SYSTEM "dummy-seclabel.sgml"> +<!ENTITY earthdistance SYSTEM "earthdistance.sgml"> +<!ENTITY file-fdw SYSTEM "file-fdw.sgml"> +<!ENTITY fuzzystrmatch SYSTEM "fuzzystrmatch.sgml"> +<!ENTITY hstore SYSTEM "hstore.sgml"> +<!ENTITY intagg SYSTEM "intagg.sgml"> +<!ENTITY intarray SYSTEM "intarray.sgml"> +<!ENTITY isn SYSTEM "isn.sgml"> +<!ENTITY lo SYSTEM "lo.sgml"> +<!ENTITY ltree SYSTEM "ltree.sgml"> +<!ENTITY oid2name SYSTEM "oid2name.sgml"> +<!ENTITY pageinspect SYSTEM "pageinspect.sgml"> +<!ENTITY passwordcheck SYSTEM "passwordcheck.sgml"> +<!ENTITY pgbench SYSTEM "pgbench.sgml"> +<!ENTITY pgarchivecleanup SYSTEM "pgarchivecleanup.sgml"> +<!ENTITY pgbuffercache SYSTEM "pgbuffercache.sgml"> +<!ENTITY pgcrypto SYSTEM "pgcrypto.sgml"> +<!ENTITY pgfreespacemap SYSTEM "pgfreespacemap.sgml"> +<!ENTITY pgrowlocks SYSTEM "pgrowlocks.sgml"> +<!ENTITY pgstandby SYSTEM "pgstandby.sgml"> +<!ENTITY pgstatstatements SYSTEM "pgstatstatements.sgml"> +<!ENTITY pgstattuple SYSTEM "pgstattuple.sgml"> +<!ENTITY pgtestfsync SYSTEM "pgtestfsync.sgml"> +<!ENTITY pgtrgm SYSTEM "pgtrgm.sgml"> +<!ENTITY pgupgrade SYSTEM "pgupgrade.sgml"> +<!ENTITY seg SYSTEM "seg.sgml"> +<!ENTITY contrib-spi SYSTEM "contrib-spi.sgml"> +<!ENTITY sepgsql SYSTEM "sepgsql.sgml"> +<!ENTITY sslinfo SYSTEM "sslinfo.sgml"> +<!ENTITY tablefunc SYSTEM "tablefunc.sgml"> +<!ENTITY test-parser SYSTEM "test-parser.sgml"> +<!ENTITY tsearch2 SYSTEM "tsearch2.sgml"> +<!ENTITY unaccent SYSTEM "unaccent.sgml"> +<!ENTITY uuid-ossp SYSTEM "uuid-ossp.sgml"> +<!ENTITY vacuumlo SYSTEM "vacuumlo.sgml"> +<!ENTITY xml2 SYSTEM "xml2.sgml"> <!-- appendixes --> -<!entity contacts SYSTEM "contacts.sgml"> -<!entity cvs SYSTEM "cvs.sgml"> -<!entity datetime SYSTEM "datetime.sgml"> -<!entity docguide SYSTEM "docguide.sgml"> -<!entity errcodes SYSTEM "errcodes.sgml"> -<!entity features SYSTEM "features.sgml"> -<!entity keywords SYSTEM "keywords.sgml"> - -<!entity release SYSTEM "release.sgml"> -<!entity release-9.0 SYSTEM "release-9.0.sgml"> -<!entity release-8.4 SYSTEM "release-8.4.sgml"> -<!entity release-8.3 SYSTEM "release-8.3.sgml"> -<!entity release-8.2 SYSTEM "release-8.2.sgml"> -<!entity release-8.1 SYSTEM "release-8.1.sgml"> -<!entity release-8.0 SYSTEM "release-8.0.sgml"> -<!entity release-7.4 SYSTEM "release-7.4.sgml"> -<!entity release-old SYSTEM "release-old.sgml"> - -<!entity acronyms SYSTEM "acronyms.sgml"> - -<!entity features-supported SYSTEM "features-supported.sgml"> -<!entity features-unsupported SYSTEM "features-unsupported.sgml"> +<!ENTITY contacts SYSTEM "contacts.sgml"> +<!ENTITY datetime SYSTEM "datetime.sgml"> +<!ENTITY docguide SYSTEM "docguide.sgml"> +<!ENTITY errcodes SYSTEM "errcodes.sgml"> +<!ENTITY features SYSTEM "features.sgml"> +<!ENTITY keywords SYSTEM "keywords.sgml"> +<!ENTITY sourcerepo SYSTEM "sourcerepo.sgml"> + +<!ENTITY release SYSTEM "release.sgml"> +<!ENTITY release-9.1 SYSTEM "release-9.1.sgml"> +<!ENTITY release-9.0 SYSTEM "release-9.0.sgml"> +<!ENTITY release-8.4 SYSTEM "release-8.4.sgml"> +<!ENTITY release-8.3 SYSTEM "release-8.3.sgml"> +<!ENTITY release-8.2 SYSTEM "release-8.2.sgml"> +<!ENTITY release-8.1 SYSTEM "release-8.1.sgml"> +<!ENTITY release-8.0 SYSTEM "release-8.0.sgml"> +<!ENTITY release-7.4 SYSTEM "release-7.4.sgml"> +<!ENTITY release-old SYSTEM "release-old.sgml"> + +<!ENTITY acronyms SYSTEM "acronyms.sgml"> + +<!ENTITY features-supported SYSTEM "features-supported.sgml"> +<!ENTITY features-unsupported SYSTEM "features-unsupported.sgml"> + +<!ENTITY errcodes-table SYSTEM "errcodes-table.sgml"> <!-- back matter --> -<!entity biblio SYSTEM "biblio.sgml"> -<!entity bookindex SYSTEM "bookindex.sgml"> +<!ENTITY biblio SYSTEM "biblio.sgml"> +<!ENTITY bookindex SYSTEM "bookindex.sgml"> <!-- Some parts of the documentation are also source for some plain-text @@ -169,11 +178,11 @@ some parts (e.g., external xref's) when generating these files we use these parameter entities. See also standalone-install.sgml. --> -<!entity % standalone-ignore "INCLUDE"> -<!entity % standalone-include "IGNORE"> +<!ENTITY % standalone-ignore "INCLUDE"> +<!ENTITY % standalone-include "IGNORE"> <!-- By default, no index is included. Use -i include-index on the command line to include it. --> -<!entity % include-index "IGNORE"> +<!ENTITY % include-index "IGNORE"> diff --git a/doc/src/sgml/fixrtf b/doc/src/sgml/fixrtf index d5beeea4e6..31cb5f85c0 100755 --- a/doc/src/sgml/fixrtf +++ b/doc/src/sgml/fixrtf @@ -1,7 +1,7 @@ #!/bin/sh # fixrtf -# $PostgreSQL: pgsql/doc/src/sgml/fixrtf,v 2.3 2006/03/11 04:38:30 momjian Exp $ +# doc/src/sgml/fixrtf # Repair (slightly) damaged RTF generated by jade # Applixware wants the s0 stylesheet defined, whereas diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 659da49a84..8f223d6891 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.521 2010/07/03 17:21:48 momjian Exp $ --> +<!-- doc/src/sgml/func.sgml --> <chapter id="functions"> <title>Functions and Operators</title> @@ -30,7 +30,7 @@ is present in other <acronym>SQL</acronym> database management systems, and in many cases this functionality is compatible and consistent between the various implementations. This chapter is also - not exhaustive; additional functions appear in relevant sections of + not exhaustive; additional functions appear in relevant sections of the manual. </para> @@ -82,8 +82,9 @@ <member><literal>NOT</></member> </simplelist> - <acronym>SQL</acronym> uses a three-valued Boolean logic where the null value represents - <quote>unknown</quote>. Observe the following truth tables: + <acronym>SQL</acronym> uses a three-valued logic system with true, + false, and <literal>null</>, which represents <quote>unknown</quote>. + Observe the following truth tables: <informaltable> <tgroup cols="4"> @@ -416,7 +417,7 @@ <literal>IS NOT NULL</literal>, respectively, except that the input expression must be of Boolean type. </para> - + <!-- IS OF does not conform to the ISO SQL behavior, so it is undocumented here <para> <indexterm> @@ -610,67 +611,6 @@ boundary cases can therefore vary depending on the host system. </para> - <indexterm> - <primary>abs</primary> - </indexterm> - <indexterm> - <primary>cbrt</primary> - </indexterm> - <indexterm> - <primary>ceiling</primary> - </indexterm> - <indexterm> - <primary>degrees</primary> - </indexterm> - <indexterm> - <primary>div</primary> - </indexterm> - <indexterm> - <primary>exp</primary> - </indexterm> - <indexterm> - <primary>floor</primary> - </indexterm> - <indexterm> - <primary>ln</primary> - </indexterm> - <indexterm> - <primary>log</primary> - </indexterm> - <indexterm> - <primary>mod</primary> - </indexterm> - <indexterm> - <primary>pi</primary> - </indexterm> - <indexterm> - <primary>power</primary> - </indexterm> - <indexterm> - <primary>radians</primary> - </indexterm> - <indexterm> - <primary>random</primary> - </indexterm> - <indexterm> - <primary>round</primary> - </indexterm> - <indexterm> - <primary>setseed</primary> - </indexterm> - <indexterm> - <primary>sign</primary> - </indexterm> - <indexterm> - <primary>sqrt</primary> - </indexterm> - <indexterm> - <primary>trunc</primary> - </indexterm> - <indexterm> - <primary>width_bucket</primary> - </indexterm> - <table id="functions-math-func-table"> <title>Mathematical Functions</title> <tgroup cols="5"> @@ -686,7 +626,12 @@ <tbody> <row> - <entry><literal><function>abs</>(<replaceable>x</replaceable>)</literal></entry> + <entry> + <indexterm> + <primary>abs</primary> + </indexterm> + <literal><function>abs(<replaceable>x</replaceable>)</function></literal> + </entry> <entry>(same as input)</entry> <entry>absolute value</entry> <entry><literal>abs(-17.4)</literal></entry> @@ -694,7 +639,12 @@ </row> <row> - <entry><literal><function>cbrt</function>(<type>dp</type>)</literal></entry> + <entry> + <indexterm> + <primary>cbrt</primary> + </indexterm> + <literal><function>cbrt(<type>dp</type>)</function></literal> + </entry> <entry><type>dp</type></entry> <entry>cube root</entry> <entry><literal>cbrt(27.0)</literal></entry> @@ -702,7 +652,12 @@ </row> <row> - <entry><literal><function>ceil</function>(<type>dp</type> or <type>numeric</type>)</literal></entry> + <entry> + <indexterm> + <primary>ceil</primary> + </indexterm> + <literal><function>ceil(<type>dp</type> or <type>numeric</type>)</function></literal> + </entry> <entry>(same as input)</entry> <entry>smallest integer not less than argument</entry> <entry><literal>ceil(-42.8)</literal></entry> @@ -710,7 +665,12 @@ </row> <row> - <entry><literal><function>ceiling</function>(<type>dp</type> or <type>numeric</type>)</literal></entry> + <entry> + <indexterm> + <primary>ceiling</primary> + </indexterm> + <literal><function>ceiling(<type>dp</type> or <type>numeric</type>)</function></literal> + </entry> <entry>(same as input)</entry> <entry>smallest integer not less than argument (alias for <function>ceil</function>)</entry> <entry><literal>ceiling(-95.3)</literal></entry> @@ -718,7 +678,12 @@ </row> <row> - <entry><literal><function>degrees</function>(<type>dp</type>)</literal></entry> + <entry> + <indexterm> + <primary>degrees</primary> + </indexterm> + <literal><function>degrees(<type>dp</type>)</function></literal> + </entry> <entry><type>dp</type></entry> <entry>radians to degrees</entry> <entry><literal>degrees(0.5)</literal></entry> @@ -726,8 +691,13 @@ </row> <row> - <entry><literal><function>div</function>(<parameter>y</parameter> <type>numeric</>, - <parameter>x</parameter> <type>numeric</>)</literal></entry> + <entry> + <indexterm> + <primary>div</primary> + </indexterm> + <literal><function>div(<parameter>y</parameter> <type>numeric</>, + <parameter>x</parameter> <type>numeric</>)</function></literal> + </entry> <entry><type>numeric</></entry> <entry>integer quotient of <parameter>y</parameter>/<parameter>x</parameter></entry> <entry><literal>div(9,4)</literal></entry> @@ -735,7 +705,12 @@ </row> <row> - <entry><literal><function>exp</function>(<type>dp</type> or <type>numeric</type>)</literal></entry> + <entry> + <indexterm> + <primary>exp</primary> + </indexterm> + <literal><function>exp(<type>dp</type> or <type>numeric</type>)</function></literal> + </entry> <entry>(same as input)</entry> <entry>exponential</entry> <entry><literal>exp(1.0)</literal></entry> @@ -743,7 +718,12 @@ </row> <row> - <entry><literal><function>floor</function>(<type>dp</type> or <type>numeric</type>)</literal></entry> + <entry> + <indexterm> + <primary>floor</primary> + </indexterm> + <literal><function>floor(<type>dp</type> or <type>numeric</type>)</function></literal> + </entry> <entry>(same as input)</entry> <entry>largest integer not greater than argument</entry> <entry><literal>floor(-42.8)</literal></entry> @@ -751,7 +731,12 @@ </row> <row> - <entry><literal><function>ln</function>(<type>dp</type> or <type>numeric</type>)</literal></entry> + <entry> + <indexterm> + <primary>ln</primary> + </indexterm> + <literal><function>ln(<type>dp</type> or <type>numeric</type>)</function></literal> + </entry> <entry>(same as input)</entry> <entry>natural logarithm</entry> <entry><literal>ln(2.0)</literal></entry> @@ -759,7 +744,12 @@ </row> <row> - <entry><literal><function>log</function>(<type>dp</type> or <type>numeric</type>)</literal></entry> + <entry> + <indexterm> + <primary>log</primary> + </indexterm> + <literal><function>log(<type>dp</type> or <type>numeric</type>)</function></literal> + </entry> <entry>(same as input)</entry> <entry>base 10 logarithm</entry> <entry><literal>log(100.0)</literal></entry> @@ -767,8 +757,8 @@ </row> <row> - <entry><literal><function>log</function>(<parameter>b</parameter> <type>numeric</type>, - <parameter>x</parameter> <type>numeric</type>)</literal></entry> + <entry><literal><function>log(<parameter>b</parameter> <type>numeric</type>, + <parameter>x</parameter> <type>numeric</type>)</function></literal></entry> <entry><type>numeric</type></entry> <entry>logarithm to base <parameter>b</parameter></entry> <entry><literal>log(2.0, 64.0)</literal></entry> @@ -776,8 +766,13 @@ </row> <row> - <entry><literal><function>mod</function>(<parameter>y</parameter>, - <parameter>x</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>mod</primary> + </indexterm> + <literal><function>mod(<parameter>y</parameter>, + <parameter>x</parameter>)</function></literal> + </entry> <entry>(same as argument types)</entry> <entry>remainder of <parameter>y</parameter>/<parameter>x</parameter></entry> <entry><literal>mod(9,4)</literal></entry> @@ -785,7 +780,12 @@ </row> <row> - <entry><literal><function>pi</function>()</literal></entry> + <entry> + <indexterm> + <primary>pi</primary> + </indexterm> + <literal><function>pi()</function></literal> + </entry> <entry><type>dp</type></entry> <entry><quote>π</quote> constant</entry> <entry><literal>pi()</literal></entry> @@ -793,8 +793,13 @@ </row> <row> - <entry><literal><function>power</function>(<parameter>a</parameter> <type>dp</type>, - <parameter>b</parameter> <type>dp</type>)</literal></entry> + <entry> + <indexterm> + <primary>power</primary> + </indexterm> + <literal><function>power(<parameter>a</parameter> <type>dp</type>, + <parameter>b</parameter> <type>dp</type>)</function></literal> + </entry> <entry><type>dp</type></entry> <entry><parameter>a</> raised to the power of <parameter>b</parameter></entry> <entry><literal>power(9.0, 3.0)</literal></entry> @@ -802,8 +807,8 @@ </row> <row> - <entry><literal><function>power</function>(<parameter>a</parameter> <type>numeric</type>, - <parameter>b</parameter> <type>numeric</type>)</literal></entry> + <entry><literal><function>power(<parameter>a</parameter> <type>numeric</type>, + <parameter>b</parameter> <type>numeric</type>)</function></literal></entry> <entry><type>numeric</type></entry> <entry><parameter>a</> raised to the power of <parameter>b</parameter></entry> <entry><literal>power(9.0, 3.0)</literal></entry> @@ -811,7 +816,12 @@ </row> <row> - <entry><literal><function>radians</function>(<type>dp</type>)</literal></entry> + <entry> + <indexterm> + <primary>radians</primary> + </indexterm> + <literal><function>radians(<type>dp</type>)</function></literal> + </entry> <entry><type>dp</type></entry> <entry>degrees to radians</entry> <entry><literal>radians(45.0)</literal></entry> @@ -819,7 +829,12 @@ </row> <row> - <entry><literal><function>random</function>()</literal></entry> + <entry> + <indexterm> + <primary>random</primary> + </indexterm> + <literal><function>random()</function></literal> + </entry> <entry><type>dp</type></entry> <entry>random value in the range 0.0 <= x < 1.0</entry> <entry><literal>random()</literal></entry> @@ -827,7 +842,12 @@ </row> <row> - <entry><literal><function>round</function>(<type>dp</type> or <type>numeric</type>)</literal></entry> + <entry> + <indexterm> + <primary>round</primary> + </indexterm> + <literal><function>round(<type>dp</type> or <type>numeric</type>)</function></literal> + </entry> <entry>(same as input)</entry> <entry>round to nearest integer</entry> <entry><literal>round(42.4)</literal></entry> @@ -835,7 +855,7 @@ </row> <row> - <entry><literal><function>round</function>(<parameter>v</parameter> <type>numeric</type>, <parameter>s</parameter> <type>int</type>)</literal></entry> + <entry><literal><function>round(<parameter>v</parameter> <type>numeric</type>, <parameter>s</parameter> <type>int</type>)</function></literal></entry> <entry><type>numeric</type></entry> <entry>round to <parameter>s</parameter> decimal places</entry> <entry><literal>round(42.4382, 2)</literal></entry> @@ -843,7 +863,12 @@ </row> <row> - <entry><literal><function>setseed</function>(<type>dp</type>)</literal></entry> + <entry> + <indexterm> + <primary>setseed</primary> + </indexterm> + <literal><function>setseed(<type>dp</type>)</function></literal> + </entry> <entry><type>void</type></entry> <entry>set seed for subsequent <literal>random()</literal> calls (value between -1.0 and 1.0, inclusive)</entry> @@ -852,7 +877,12 @@ </row> <row> - <entry><literal><function>sign</function>(<type>dp</type> or <type>numeric</type>)</literal></entry> + <entry> + <indexterm> + <primary>sign</primary> + </indexterm> + <literal><function>sign(<type>dp</type> or <type>numeric</type>)</function></literal> + </entry> <entry>(same as input)</entry> <entry>sign of the argument (-1, 0, +1)</entry> <entry><literal>sign(-8.4)</literal></entry> @@ -860,7 +890,12 @@ </row> <row> - <entry><literal><function>sqrt</function>(<type>dp</type> or <type>numeric</type>)</literal></entry> + <entry> + <indexterm> + <primary>sqrt</primary> + </indexterm> + <literal><function>sqrt(<type>dp</type> or <type>numeric</type>)</function></literal> + </entry> <entry>(same as input)</entry> <entry>square root</entry> <entry><literal>sqrt(2.0)</literal></entry> @@ -868,7 +903,12 @@ </row> <row> - <entry><literal><function>trunc</function>(<type>dp</type> or <type>numeric</type>)</literal></entry> + <entry> + <indexterm> + <primary>trunc</primary> + </indexterm> + <literal><function>trunc(<type>dp</type> or <type>numeric</type>)</function></literal> + </entry> <entry>(same as input)</entry> <entry>truncate toward zero</entry> <entry><literal>trunc(42.8)</literal></entry> @@ -876,7 +916,7 @@ </row> <row> - <entry><literal><function>trunc</function>(<parameter>v</parameter> <type>numeric</type>, <parameter>s</parameter> <type>int</type>)</literal></entry> + <entry><literal><function>trunc(<parameter>v</parameter> <type>numeric</type>, <parameter>s</parameter> <type>int</type>)</function></literal></entry> <entry><type>numeric</type></entry> <entry>truncate to <parameter>s</parameter> decimal places</entry> <entry><literal>trunc(42.4382, 2)</literal></entry> @@ -884,7 +924,12 @@ </row> <row> - <entry><literal><function>width_bucket</function>(<parameter>op</parameter> <type>numeric</type>, <parameter>b1</parameter> <type>numeric</type>, <parameter>b2</parameter> <type>numeric</type>, <parameter>count</parameter> <type>int</type>)</literal></entry> + <entry> + <indexterm> + <primary>width_bucket</primary> + </indexterm> + <literal><function>width_bucket(<parameter>op</parameter> <type>numeric</type>, <parameter>b1</parameter> <type>numeric</type>, <parameter>b2</parameter> <type>numeric</type>, <parameter>count</parameter> <type>int</type>)</function></literal> + </entry> <entry><type>int</type></entry> <entry>return the bucket to which <parameter>operand</> would be assigned in an equidepth histogram with <parameter>count</> @@ -894,7 +939,7 @@ </row> <row> - <entry><literal><function>width_bucket</function>(<parameter>op</parameter> <type>dp</type>, <parameter>b1</parameter> <type>dp</type>, <parameter>b2</parameter> <type>dp</type>, <parameter>count</parameter> <type>int</type>)</literal></entry> + <entry><literal><function>width_bucket(<parameter>op</parameter> <type>dp</type>, <parameter>b1</parameter> <type>dp</type>, <parameter>b2</parameter> <type>dp</type>, <parameter>count</parameter> <type>int</type>)</function></literal></entry> <entry><type>int</type></entry> <entry>return the bucket to which <parameter>operand</> would be assigned in an equidepth histogram with <parameter>count</> @@ -913,35 +958,10 @@ precision</type>. Trigonometric functions arguments are expressed in radians. Inverse functions return values are expressed in radians. See unit transformation functions - <literal><function>radians</function>()</literal> and - <literal><function>degrees</function>()</literal> above. + <literal><function>radians()</function></literal> and + <literal><function>degrees()</function></literal> above. </para> - <indexterm> - <primary>acos</primary> - </indexterm> - <indexterm> - <primary>asin</primary> - </indexterm> - <indexterm> - <primary>atan</primary> - </indexterm> - <indexterm> - <primary>atan2</primary> - </indexterm> - <indexterm> - <primary>cos</primary> - </indexterm> - <indexterm> - <primary>cot</primary> - </indexterm> - <indexterm> - <primary>sin</primary> - </indexterm> - <indexterm> - <primary>tan</primary> - </indexterm> - <table id="functions-math-trig-table"> <title>Trigonometric Functions</title> @@ -955,44 +975,83 @@ <tbody> <row> - <entry><literal><function>acos</function>(<replaceable>x</replaceable>)</literal></entry> + <entry> + <indexterm> + <primary>acos</primary> + </indexterm><literal><function>acos(<replaceable>x</replaceable>)</function></literal> + </entry> <entry>inverse cosine</entry> </row> <row> - <entry><literal><function>asin</function>(<replaceable>x</replaceable>)</literal></entry> + <entry> + <indexterm> + <primary>asin</primary> + </indexterm> + <literal><function>asin(<replaceable>x</replaceable>)</function></literal> + </entry> <entry>inverse sine</entry> </row> <row> - <entry><literal><function>atan</function>(<replaceable>x</replaceable>)</literal></entry> + <entry> + <indexterm> + <primary>atan</primary> + </indexterm> + <literal><function>atan(<replaceable>x</replaceable>)</function></literal> + </entry> <entry>inverse tangent</entry> </row> <row> - <entry><literal><function>atan2</function>(<replaceable>y</replaceable>, - <replaceable>x</replaceable>)</literal></entry> + <entry> + <indexterm> + <primary>atan2</primary> + </indexterm> + <literal><function>atan2(<replaceable>y</replaceable>, + <replaceable>x</replaceable>)</function></literal> + </entry> <entry>inverse tangent of <literal><replaceable>y</replaceable>/<replaceable>x</replaceable></literal></entry> </row> <row> - <entry><literal><function>cos</function>(<replaceable>x</replaceable>)</literal></entry> + <entry> + <indexterm> + <primary>cos</primary> + </indexterm> + <literal><function>cos(<replaceable>x</replaceable>)</function></literal> + </entry> <entry>cosine</entry> </row> <row> - <entry><literal><function>cot</function>(<replaceable>x</replaceable>)</literal></entry> + <entry> + <indexterm> + <primary>cot</primary> + </indexterm> + <literal><function>cot(<replaceable>x</replaceable>)</function></literal> + </entry> <entry>cotangent</entry> </row> <row> - <entry><literal><function>sin</function>(<replaceable>x</replaceable>)</literal></entry> + <entry> + <indexterm> + <primary>sin</primary> + </indexterm> + <literal><function>sin(<replaceable>x</replaceable>)</function></literal> + </entry> <entry>sine</entry> </row> <row> - <entry><literal><function>tan</function>(<replaceable>x</replaceable>)</literal></entry> + <entry> + <indexterm> + <primary>tan</primary> + </indexterm> + <literal><function>tan(<replaceable>x</replaceable>)</function></literal> + </entry> <entry>tangent</entry> </row> </tbody> @@ -1040,34 +1099,6 @@ </para> </note> - <indexterm> - <primary>bit_length</primary> - </indexterm> - <indexterm> - <primary>char_length</primary> - </indexterm> - <indexterm> - <primary>lower</primary> - </indexterm> - <indexterm> - <primary>octet_length</primary> - </indexterm> - <indexterm> - <primary>overlay</primary> - </indexterm> - <indexterm> - <primary>position</primary> - </indexterm> - <indexterm> - <primary>substring</primary> - </indexterm> - <indexterm> - <primary>trim</primary> - </indexterm> - <indexterm> - <primary>upper</primary> - </indexterm> - <table id="functions-string-sql"> <title><acronym>SQL</acronym> String Functions and Operators</title> <tgroup cols="5"> @@ -1077,7 +1108,7 @@ <entry>Return Type</entry> <entry>Description</entry> <entry>Example</entry> - <entry>Result</entry> + <entry>Result</entry> </row> </thead> @@ -1114,7 +1145,12 @@ </row> <row> - <entry><literal><function>bit_length</function>(<parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>bit_length</primary> + </indexterm> + <literal><function>bit_length(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>int</type></entry> <entry>Number of bits in string</entry> <entry><literal>bit_length('jose')</literal></entry> @@ -1122,7 +1158,12 @@ </row> <row> - <entry><literal><function>char_length</function>(<parameter>string</parameter>)</literal> or <literal><function>character_length</function>(<parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>char_length</primary> + </indexterm> + <literal><function>char_length(<parameter>string</parameter>)</function></literal> or <literal><function>character_length(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>int</type></entry> <entry> Number of characters in string @@ -1141,7 +1182,12 @@ </row> <row> - <entry><literal><function>lower</function>(<parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>lower</primary> + </indexterm> + <literal><function>lower(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>text</type></entry> <entry>Convert string to lower case</entry> <entry><literal>lower('TOM')</literal></entry> @@ -1149,7 +1195,12 @@ </row> <row> - <entry><literal><function>octet_length</function>(<parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>octet_length</primary> + </indexterm> + <literal><function>octet_length(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>int</type></entry> <entry>Number of bytes in string</entry> <entry><literal>octet_length('jose')</literal></entry> @@ -1157,7 +1208,12 @@ </row> <row> - <entry><literal><function>overlay</function>(<parameter>string</parameter> placing <parameter>string</parameter> from <type>int</type> <optional>for <type>int</type></optional>)</literal></entry> + <entry> + <indexterm> + <primary>overlay</primary> + </indexterm> + <literal><function>overlay(<parameter>string</parameter> placing <parameter>string</parameter> from <type>int</type> <optional>for <type>int</type></optional>)</function></literal> + </entry> <entry><type>text</type></entry> <entry> Replace substring @@ -1167,7 +1223,12 @@ </row> <row> - <entry><literal><function>position</function>(<parameter>substring</parameter> in <parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>position</primary> + </indexterm> + <literal><function>position(<parameter>substring</parameter> in <parameter>string</parameter>)</function></literal> + </entry> <entry><type>int</type></entry> <entry>Location of specified substring</entry> <entry><literal>position('om' in 'Thomas')</literal></entry> @@ -1175,7 +1236,12 @@ </row> <row> - <entry><literal><function>substring</function>(<parameter>string</parameter> <optional>from <type>int</type></optional> <optional>for <type>int</type></optional>)</literal></entry> + <entry> + <indexterm> + <primary>substring</primary> + </indexterm> + <literal><function>substring(<parameter>string</parameter> <optional>from <type>int</type></optional> <optional>for <type>int</type></optional>)</function></literal> + </entry> <entry><type>text</type></entry> <entry> Extract substring @@ -1185,7 +1251,7 @@ </row> <row> - <entry><literal><function>substring</function>(<parameter>string</parameter> from <replaceable>pattern</replaceable>)</literal></entry> + <entry><literal><function>substring(<parameter>string</parameter> from <replaceable>pattern</replaceable>)</function></literal></entry> <entry><type>text</type></entry> <entry> Extract substring matching POSIX regular expression. See @@ -1197,7 +1263,7 @@ </row> <row> - <entry><literal><function>substring</function>(<parameter>string</parameter> from <replaceable>pattern</replaceable> for <replaceable>escape</replaceable>)</literal></entry> + <entry><literal><function>substring(<parameter>string</parameter> from <replaceable>pattern</replaceable> for <replaceable>escape</replaceable>)</function></literal></entry> <entry><type>text</type></entry> <entry> Extract substring matching <acronym>SQL</acronym> regular expression. @@ -1210,9 +1276,12 @@ <row> <entry> - <literal><function>trim</function>(<optional>leading | trailing | both</optional> + <indexterm> + <primary>trim</primary> + </indexterm> + <literal><function>trim(<optional>leading | trailing | both</optional> <optional><parameter>characters</parameter></optional> from - <parameter>string</parameter>)</literal> + <parameter>string</parameter>)</function></literal> </entry> <entry><type>text</type></entry> <entry> @@ -1225,7 +1294,12 @@ </row> <row> - <entry><literal><function>upper</function>(<parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>upper</primary> + </indexterm> + <literal><function>upper(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>text</type></entry> <entry>Convert string to upper case</entry> <entry><literal>upper('tom')</literal></entry> @@ -1241,85 +1315,6 @@ <acronym>SQL</acronym>-standard string functions listed in <xref linkend="functions-string-sql">. </para> - <indexterm> - <primary>ascii</primary> - </indexterm> - <indexterm> - <primary>btrim</primary> - </indexterm> - <indexterm> - <primary>chr</primary> - </indexterm> - <indexterm> - <primary>convert</primary> - </indexterm> - <indexterm> - <primary>convert_from</primary> - </indexterm> - <indexterm> - <primary>convert_to</primary> - </indexterm> - <indexterm> - <primary>decode</primary> - </indexterm> - <indexterm> - <primary>encode</primary> - </indexterm> - <indexterm> - <primary>initcap</primary> - </indexterm> - <indexterm> - <primary>lpad</primary> - </indexterm> - <indexterm> - <primary>ltrim</primary> - </indexterm> - <indexterm> - <primary>md5</primary> - </indexterm> - <indexterm> - <primary>pg_client_encoding</primary> - </indexterm> - <indexterm> - <primary>quote_ident</primary> - </indexterm> - <indexterm> - <primary>quote_literal</primary> - </indexterm> - <indexterm> - <primary>quote_nullable</primary> - </indexterm> - <indexterm> - <primary>repeat</primary> - </indexterm> - <indexterm> - <primary>replace</primary> - </indexterm> - <indexterm> - <primary>rpad</primary> - </indexterm> - <indexterm> - <primary>rtrim</primary> - </indexterm> - <indexterm> - <primary>split_part</primary> - </indexterm> - <indexterm> - <primary>strpos</primary> - </indexterm> - <indexterm> - <primary>substr</primary> - </indexterm> - <indexterm> - <primary>to_ascii</primary> - </indexterm> - <indexterm> - <primary>to_hex</primary> - </indexterm> - <indexterm> - <primary>translate</primary> - </indexterm> - <table id="functions-string-other"> <title>Other String Functions</title> <tgroup cols="5"> @@ -1335,7 +1330,12 @@ <tbody> <row> - <entry><literal><function>ascii</function>(<parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>ascii</primary> + </indexterm> + <literal><function>ascii(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>int</type></entry> <entry> <acronym>ASCII</acronym> code of the first character of the @@ -1348,8 +1348,13 @@ </row> <row> - <entry><literal><function>btrim</function>(<parameter>string</parameter> <type>text</type> - <optional>, <parameter>characters</parameter> <type>text</type></optional>)</literal></entry> + <entry> + <indexterm> + <primary>btrim</primary> + </indexterm> + <literal><function>btrim(<parameter>string</parameter> <type>text</type> + <optional>, <parameter>characters</parameter> <type>text</type></optional>)</function></literal> + </entry> <entry><type>text</type></entry> <entry> Remove the longest string consisting only of characters @@ -1361,7 +1366,12 @@ </row> <row> - <entry><literal><function>chr</function>(<type>int</type>)</literal></entry> + <entry> + <indexterm> + <primary>chr</primary> + </indexterm> + <literal><function>chr(<type>int</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry> Character with the given code. For <acronym>UTF8</acronym> the @@ -1376,9 +1386,46 @@ <row> <entry> - <literal><function>convert</function>(<parameter>string</parameter> <type>bytea</type>, + <indexterm> + <primary>concat</primary> + </indexterm> + <literal><function>concat(<parameter>str</parameter> <type>"any"</type> + [, <parameter>str</parameter> <type>"any"</type> [, ...] ])</function></literal> + </entry> + <entry><type>text</type></entry> + <entry> + Concatenate all arguments. NULL arguments are ignored. + </entry> + <entry><literal>concat('abcde', 2, NULL, 22)</literal></entry> + <entry><literal>abcde222</literal></entry> + </row> + + <row> + <entry> + <indexterm> + <primary>concat_ws</primary> + </indexterm> + <literal><function>concat_ws(<parameter>sep</parameter> <type>text</type>, + <parameter>str</parameter> <type>"any"</type> + [, <parameter>str</parameter> <type>"any"</type> [, ...] ])</function></literal> + </entry> + <entry><type>text</type></entry> + <entry> + Concatenate all but first arguments with separators. The first + parameter is used as a separator. NULL arguments are ignored. + </entry> + <entry><literal>concat_ws(',', 'abcde', 2, NULL, 22)</literal></entry> + <entry><literal>abcde,2,22</literal></entry> + </row> + + <row> + <entry> + <indexterm> + <primary>convert</primary> + </indexterm> + <literal><function>convert(<parameter>string</parameter> <type>bytea</type>, <parameter>src_encoding</parameter> <type>name</type>, - <parameter>dest_encoding</parameter> <type>name</type>)</literal> + <parameter>dest_encoding</parameter> <type>name</type>)</function></literal> </entry> <entry><type>bytea</type></entry> <entry> @@ -1386,7 +1433,7 @@ original encoding is specified by <parameter>src_encoding</parameter>. The <parameter>string</parameter> must be valid in this encoding. - Conversions can be defined by <command>CREATE CONVERSION</command>. + Conversions can be defined by <command>CREATE CONVERSION</command>. Also there are some predefined conversions. See <xref linkend="conversion-names"> for available conversions. </entry> @@ -1397,8 +1444,11 @@ <row> <entry> - <literal><function>convert_from</function>(<parameter>string</parameter> <type>bytea</type>, - <parameter>src_encoding</parameter> <type>name</type>)</literal> + <indexterm> + <primary>convert_from</primary> + </indexterm> + <literal><function>convert_from(<parameter>string</parameter> <type>bytea</type>, + <parameter>src_encoding</parameter> <type>name</type>)</function></literal> </entry> <entry><type>text</type></entry> <entry> @@ -1412,8 +1462,11 @@ <row> <entry> - <literal><function>convert_to</function>(<parameter>string</parameter> <type>text</type>, - <parameter>dest_encoding</parameter> <type>name</type>)</literal> + <indexterm> + <primary>convert_to</primary> + </indexterm> + <literal><function>convert_to(<parameter>string</parameter> <type>text</type>, + <parameter>dest_encoding</parameter> <type>name</type>)</function></literal> </entry> <entry><type>bytea</type></entry> <entry> @@ -1425,22 +1478,28 @@ <row> <entry> - <literal><function>decode</function>(<parameter>string</parameter> <type>text</type>, - <parameter>type</parameter> <type>text</type>)</literal> + <indexterm> + <primary>decode</primary> + </indexterm> + <literal><function>decode(<parameter>string</parameter> <type>text</type>, + <parameter>type</parameter> <type>text</type>)</function></literal> </entry> <entry><type>bytea</type></entry> <entry> - Decode binary data from <parameter>string</parameter> previously + Decode binary data from <parameter>string</parameter> previously encoded with <function>encode</>. Parameter type is same as in <function>encode</>. </entry> <entry><literal>decode('MTIzAAE=', 'base64')</literal></entry> <entry><literal>123\000\001</literal></entry> - </row> + </row> <row> <entry> - <literal><function>encode</function>(<parameter>data</parameter> <type>bytea</type>, - <parameter>type</parameter> <type>text</type>)</literal> + <indexterm> + <primary>encode</primary> + </indexterm> + <literal><function>encode(<parameter>data</parameter> <type>bytea</type>, + <parameter>type</parameter> <type>text</type>)</function></literal> </entry> <entry><type>text</type></entry> <entry> @@ -1451,10 +1510,40 @@ </entry> <entry><literal>encode(E'123\\000\\001', 'base64')</literal></entry> <entry><literal>MTIzAAE=</literal></entry> - </row> + </row> <row> - <entry><literal><function>initcap</function>(<parameter>string</parameter>)</literal></entry> + <entry id="format"> + <indexterm> + <primary>format</primary> + </indexterm> + <literal><function>format</function>(<parameter>formatstr</parameter> <type>text</type> + [, <parameter>str</parameter> <type>"any"</type> [, ...] ])</literal> + </entry> + <entry><type>text</type></entry> + <entry> + Format a string. This function is similar to the C function + <function>sprintf</>; but only the following conversions + are recognized: <literal>%s</literal> interpolates the corresponding + argument as a string; <literal>%I</literal> escapes its argument as + an SQL identifier; <literal>%L</literal> escapes its argument as an + SQL literal; <literal>%%</literal> outputs a literal <literal>%</>. + A conversion can reference an explicit parameter position by preceding + the conversion specifier with <literal><replaceable>n</>$</>, where + <replaceable>n</replaceable> is the argument position. + See also <xref linkend="plpgsql-quote-literal-example">. + </entry> + <entry><literal>format('Hello %s, %1$s', 'World')</literal></entry> + <entry><literal>Hello World, World</literal></entry> + </row> + + <row> + <entry> + <indexterm> + <primary>initcap</primary> + </indexterm> + <literal><function>initcap(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>text</type></entry> <entry> Convert the first letter of each word to upper case and the @@ -1466,7 +1555,29 @@ </row> <row> - <entry><literal><function>length</function>(<parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>left</primary> + </indexterm> + <literal><function>left(<parameter>str</parameter> <type>text</type>, + <parameter>n</parameter> <type>int</type>)</function></literal> + </entry> + <entry><type>text</type></entry> + <entry> + Return first <replaceable>n</> characters in the string. When <replaceable>n</> + is negative, return all but last |<replaceable>n</>| characters. + </entry> + <entry><literal>left('abcde', 2)</literal></entry> + <entry><literal>ab</literal></entry> + </row> + + <row> + <entry> + <indexterm> + <primary>length</primary> + </indexterm> + <literal><function>length(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>int</type></entry> <entry> Number of characters in <parameter>string</parameter> @@ -1476,8 +1587,8 @@ </row> <row> - <entry><literal><function>length</function>(<parameter>string</parameter><type>bytea</type>, - <parameter>encoding</parameter> <type>name</type> )</literal></entry> + <entry><literal><function>length(<parameter>string</parameter><type>bytea</type>, + <parameter>encoding</parameter> <type>name</type> )</function></literal></entry> <entry><type>int</type></entry> <entry> Number of characters in <parameter>string</parameter> in the given @@ -1490,9 +1601,12 @@ <row> <entry> - <literal><function>lpad</function>(<parameter>string</parameter> <type>text</type>, + <indexterm> + <primary>lpad</primary> + </indexterm> + <literal><function>lpad(<parameter>string</parameter> <type>text</type>, <parameter>length</parameter> <type>int</type> - <optional>, <parameter>fill</parameter> <type>text</type></optional>)</literal> + <optional>, <parameter>fill</parameter> <type>text</type></optional>)</function></literal> </entry> <entry><type>text</type></entry> <entry> @@ -1508,8 +1622,12 @@ </row> <row> - <entry><literal><function>ltrim</function>(<parameter>string</parameter> <type>text</type> - <optional>, <parameter>characters</parameter> <type>text</type></optional>)</literal> + <entry> + <indexterm> + <primary>ltrim</primary> + </indexterm> + <literal><function>ltrim(<parameter>string</parameter> <type>text</type> + <optional>, <parameter>characters</parameter> <type>text</type></optional>)</function></literal> </entry> <entry><type>text</type></entry> <entry> @@ -1522,7 +1640,12 @@ </row> <row> - <entry><literal><function>md5</function>(<parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>md5</primary> + </indexterm> + <literal><function>md5(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>text</type></entry> <entry> Calculates the MD5 hash of <parameter>string</parameter>, @@ -1533,7 +1656,12 @@ </row> <row> - <entry><literal><function>pg_client_encoding</function>()</literal></entry> + <entry> + <indexterm> + <primary>pg_client_encoding</primary> + </indexterm> + <literal><function>pg_client_encoding()</function></literal> + </entry> <entry><type>name</type></entry> <entry> Current client encoding name @@ -1543,7 +1671,12 @@ </row> <row> - <entry><literal><function>quote_ident</function>(<parameter>string</parameter> <type>text</type>)</literal></entry> + <entry> + <indexterm> + <primary>quote_ident</primary> + </indexterm> + <literal><function>quote_ident(<parameter>string</parameter> <type>text</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry> Return the given string suitably quoted to be used as an identifier @@ -1558,7 +1691,12 @@ </row> <row> - <entry><literal><function>quote_literal</function>(<parameter>string</parameter> <type>text</type>)</literal></entry> + <entry> + <indexterm> + <primary>quote_literal</primary> + </indexterm> + <literal><function>quote_literal(<parameter>string</parameter> <type>text</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry> Return the given string suitably quoted to be used as a string literal @@ -1574,7 +1712,7 @@ </row> <row> - <entry><literal><function>quote_literal</function>(<parameter>value</parameter> <type>anyelement</type>)</literal></entry> + <entry><literal><function>quote_literal(<parameter>value</parameter> <type>anyelement</type>)</function></literal></entry> <entry><type>text</type></entry> <entry> Coerce the given value to text and then quote it as a literal. @@ -1585,7 +1723,12 @@ </row> <row> - <entry><literal><function>quote_nullable</function>(<parameter>string</parameter> <type>text</type>)</literal></entry> + <entry> + <indexterm> + <primary>quote_nullable</primary> + </indexterm> + <literal><function>quote_nullable(<parameter>string</parameter> <type>text</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry> Return the given string suitably quoted to be used as a string literal @@ -1599,7 +1742,7 @@ </row> <row> - <entry><literal><function>quote_nullable</function>(<parameter>value</parameter> <type>anyelement</type>)</literal></entry> + <entry><literal><function>quote_nullable(<parameter>value</parameter> <type>anyelement</type>)</function></literal></entry> <entry><type>text</type></entry> <entry> Coerce the given value to text and then quote it as a literal; @@ -1611,7 +1754,12 @@ </row> <row> - <entry><literal><function>regexp_matches</function>(<parameter>string</parameter> <type>text</type>, <parameter>pattern</parameter> <type>text</type> [, <parameter>flags</parameter> <type>text</type>])</literal></entry> + <entry> + <indexterm> + <primary>regexp_matches</primary> + </indexterm> + <literal><function>regexp_matches(<parameter>string</parameter> <type>text</type>, <parameter>pattern</parameter> <type>text</type> [, <parameter>flags</parameter> <type>text</type>])</function></literal> + </entry> <entry><type>setof text[]</type></entry> <entry> Return all captured substrings resulting from matching a POSIX regular @@ -1623,7 +1771,12 @@ </row> <row> - <entry><literal><function>regexp_replace</function>(<parameter>string</parameter> <type>text</type>, <parameter>pattern</parameter> <type>text</type>, <parameter>replacement</parameter> <type>text</type> [, <parameter>flags</parameter> <type>text</type>])</literal></entry> + <entry> + <indexterm> + <primary>regexp_replace</primary> + </indexterm> + <literal><function>regexp_replace(<parameter>string</parameter> <type>text</type>, <parameter>pattern</parameter> <type>text</type>, <parameter>replacement</parameter> <type>text</type> [, <parameter>flags</parameter> <type>text</type>])</function></literal> + </entry> <entry><type>text</type></entry> <entry> Replace substring(s) matching a POSIX regular expression. See @@ -1634,7 +1787,12 @@ </row> <row> - <entry><literal><function>regexp_split_to_array</function>(<parameter>string</parameter> <type>text</type>, <parameter>pattern</parameter> <type>text</type> [, <parameter>flags</parameter> <type>text</type> ])</literal></entry> + <entry> + <indexterm> + <primary>regexp_split_to_array</primary> + </indexterm> + <literal><function>regexp_split_to_array(<parameter>string</parameter> <type>text</type>, <parameter>pattern</parameter> <type>text</type> [, <parameter>flags</parameter> <type>text</type> ])</function></literal> + </entry> <entry><type>text[]</type></entry> <entry> Split <parameter>string</parameter> using a POSIX regular expression as @@ -1646,7 +1804,12 @@ </row> <row> - <entry><literal><function>regexp_split_to_table</function>(<parameter>string</parameter> <type>text</type>, <parameter>pattern</parameter> <type>text</type> [, <parameter>flags</parameter> <type>text</type>])</literal></entry> + <entry> + <indexterm> + <primary>regexp_split_to_table</primary> + </indexterm> + <literal><function>regexp_split_to_table(<parameter>string</parameter> <type>text</type>, <parameter>pattern</parameter> <type>text</type> [, <parameter>flags</parameter> <type>text</type>])</function></literal> + </entry> <entry><type>setof text</type></entry> <entry> Split <parameter>string</parameter> using a POSIX regular expression as @@ -1658,7 +1821,12 @@ </row> <row> - <entry><literal><function>repeat</function>(<parameter>string</parameter> <type>text</type>, <parameter>number</parameter> <type>int</type>)</literal></entry> + <entry> + <indexterm> + <primary>repeat</primary> + </indexterm> + <literal><function>repeat(<parameter>string</parameter> <type>text</type>, <parameter>number</parameter> <type>int</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry>Repeat <parameter>string</parameter> the specified <parameter>number</parameter> of times</entry> @@ -1667,9 +1835,14 @@ </row> <row> - <entry><literal><function>replace</function>(<parameter>string</parameter> <type>text</type>, - <parameter>from</parameter> <type>text</type>, - <parameter>to</parameter> <type>text</type>)</literal></entry> + <entry> + <indexterm> + <primary>replace</primary> + </indexterm> + <literal><function>replace(<parameter>string</parameter> <type>text</type>, + <parameter>from</parameter> <type>text</type>, + <parameter>to</parameter> <type>text</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry>Replace all occurrences in <parameter>string</parameter> of substring <parameter>from</parameter> with substring <parameter>to</parameter> @@ -1680,9 +1853,44 @@ <row> <entry> - <literal><function>rpad</function>(<parameter>string</parameter> <type>text</type>, + <indexterm> + <primary>reverse</primary> + </indexterm> + <literal><function>reverse(<parameter>str</parameter>)</function></literal> + </entry> + <entry><type>text</type></entry> + <entry> + Return reversed string. + </entry> + <entry><literal>reverse('abcde')</literal></entry> + <entry><literal>edcba</literal></entry> + </row> + + <row> + <entry> + <indexterm> + <primary>right</primary> + </indexterm> + <literal><function>right(<parameter>str</parameter> <type>text</type>, + <parameter>n</parameter> <type>int</type>)</function></literal> + </entry> + <entry><type>text</type></entry> + <entry> + Return last <replaceable>n</> characters in the string. When <replaceable>n</> + is negative, return all but first |<replaceable>n</>| characters. + </entry> + <entry><literal>right('abcde', 2)</literal></entry> + <entry><literal>de</literal></entry> + </row> + + <row> + <entry> + <indexterm> + <primary>rpad</primary> + </indexterm> + <literal><function>rpad(<parameter>string</parameter> <type>text</type>, <parameter>length</parameter> <type>int</type> - <optional>, <parameter>fill</parameter> <type>text</type></optional>)</literal> + <optional>, <parameter>fill</parameter> <type>text</type></optional>)</function></literal> </entry> <entry><type>text</type></entry> <entry> @@ -1697,8 +1905,12 @@ </row> <row> - <entry><literal><function>rtrim</function>(<parameter>string</parameter> <type>text</type> - <optional>, <parameter>characters</parameter> <type>text</type></optional>)</literal> + <entry> + <indexterm> + <primary>rtrim</primary> + </indexterm> + <literal><function>rtrim(<parameter>string</parameter> <type>text</type> + <optional>, <parameter>characters</parameter> <type>text</type></optional>)</function></literal> </entry> <entry><type>text</type></entry> <entry> @@ -1711,9 +1923,14 @@ </row> <row> - <entry><literal><function>split_part</function>(<parameter>string</parameter> <type>text</type>, - <parameter>delimiter</parameter> <type>text</type>, - <parameter>field</parameter> <type>int</type>)</literal></entry> + <entry> + <indexterm> + <primary>split_part</primary> + </indexterm> + <literal><function>split_part(<parameter>string</parameter> <type>text</type>, + <parameter>delimiter</parameter> <type>text</type>, + <parameter>field</parameter> <type>int</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry>Split <parameter>string</parameter> on <parameter>delimiter</parameter> and return the given field (counting from one) @@ -1723,7 +1940,12 @@ </row> <row> - <entry><literal><function>strpos</function>(<parameter>string</parameter>, <parameter>substring</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>strpos</primary> + </indexterm> + <literal><function>strpos(<parameter>string</parameter>, <parameter>substring</parameter>)</function></literal> + </entry> <entry><type>int</type></entry> <entry> Location of specified substring (same as @@ -1736,7 +1958,12 @@ </row> <row> - <entry><literal><function>substr</function>(<parameter>string</parameter>, <parameter>from</parameter> <optional>, <parameter>count</parameter></optional>)</literal></entry> + <entry> + <indexterm> + <primary>substr</primary> + </indexterm> + <literal><function>substr(<parameter>string</parameter>, <parameter>from</parameter> <optional>, <parameter>count</parameter></optional>)</function></literal> + </entry> <entry><type>text</type></entry> <entry> Extract substring (same as @@ -1747,23 +1974,31 @@ </row> <row> - <entry><literal><function>to_ascii</function>(<parameter>string</parameter> <type>text</type> - <optional>, <parameter>encoding</parameter> <type>text</type></optional>)</literal></entry> + <entry> + <indexterm> + <primary>to_ascii</primary> + </indexterm> + <literal><function>to_ascii(<parameter>string</parameter> <type>text</type> + <optional>, <parameter>encoding</parameter> <type>text</type></optional>)</function></literal> + </entry> <entry><type>text</type></entry> - <entry> Convert <parameter>string</parameter> to <acronym>ASCII</acronym> from another encoding (only supports conversion from <literal>LATIN1</>, <literal>LATIN2</>, <literal>LATIN9</>, and <literal>WIN1250</> encodings) </entry> - <entry><literal>to_ascii('Karel')</literal></entry> <entry><literal>Karel</literal></entry> </row> <row> - <entry><literal><function>to_hex</function>(<parameter>number</parameter> <type>int</type> - or <type>bigint</type>)</literal></entry> + <entry> + <indexterm> + <primary>to_hex</primary> + </indexterm> + <literal><function>to_hex(<parameter>number</parameter> <type>int</type> + or <type>bigint</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry>Convert <parameter>number</parameter> to its equivalent hexadecimal representation @@ -1774,21 +2009,26 @@ <row> <entry> - <literal><function>translate</function>(<parameter>string</parameter> <type>text</type>, + <indexterm> + <primary>translate</primary> + </indexterm> + <literal><function>translate(<parameter>string</parameter> <type>text</type>, <parameter>from</parameter> <type>text</type>, - <parameter>to</parameter> <type>text</type>)</literal> + <parameter>to</parameter> <type>text</type>)</function></literal> </entry> <entry><type>text</type></entry> <entry> Any character in <parameter>string</parameter> that matches a character in the <parameter>from</parameter> set is replaced by the corresponding character in the <parameter>to</parameter> - set + set. If <parameter>from</parameter> is longer than + <parameter>to</parameter>, occurrences of the extra characters in + <parameter>from</parameter> are removed. </entry> - <entry><literal>translate('12345', '14', 'ax')</literal></entry> - <entry><literal>a23x5</literal></entry> - </row> - + <entry><literal>translate('12345', '143', 'ax')</literal></entry> + <entry><literal>a2x5</literal></entry> + </row> + </tbody> </tgroup> </table> @@ -2649,7 +2889,12 @@ </row> <row> - <entry><literal><function>octet_length</function>(<parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>octet_length</primary> + </indexterm> + <literal><function>octet_length(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>int</type></entry> <entry>Number of bytes in binary string</entry> <entry><literal>octet_length(E'jo\\000se'::bytea)</literal></entry> @@ -2657,7 +2902,12 @@ </row> <row> - <entry><literal><function>overlay</function>(<parameter>string</parameter> placing <parameter>string</parameter> from <type>int</type> <optional>for <type>int</type></optional>)</literal></entry> + <entry> + <indexterm> + <primary>overlay</primary> + </indexterm> + <literal><function>overlay(<parameter>string</parameter> placing <parameter>string</parameter> from <type>int</type> <optional>for <type>int</type></optional>)</function></literal> + </entry> <entry><type>bytea</type></entry> <entry> Replace substring @@ -2667,7 +2917,12 @@ </row> <row> - <entry><literal><function>position</function>(<parameter>substring</parameter> in <parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>position</primary> + </indexterm> + <literal><function>position(<parameter>substring</parameter> in <parameter>string</parameter>)</function></literal> + </entry> <entry><type>int</type></entry> <entry>Location of specified substring</entry> <entry><literal>position(E'\\000om'::bytea in E'Th\\000omas'::bytea)</literal></entry> @@ -2675,13 +2930,15 @@ </row> <row> - <entry><literal><function>substring</function>(<parameter>string</parameter> <optional>from <type>int</type></optional> <optional>for <type>int</type></optional>)</literal></entry> - <entry><type>bytea</type></entry> <entry> - Extract substring <indexterm> <primary>substring</primary> </indexterm> + <literal><function>substring(<parameter>string</parameter> <optional>from <type>int</type></optional> <optional>for <type>int</type></optional>)</function></literal> + </entry> + <entry><type>bytea</type></entry> + <entry> + Extract substring </entry> <entry><literal>substring(E'Th\\000omas'::bytea from 2 for 3)</literal></entry> <entry><literal>h\000o</literal></entry> @@ -2689,9 +2946,12 @@ <row> <entry> - <literal><function>trim</function>(<optional>both</optional> + <indexterm> + <primary>trim</primary> + </indexterm> + <literal><function>trim(<optional>both</optional> <parameter>bytes</parameter> from - <parameter>string</parameter>)</literal> + <parameter>string</parameter>)</function></literal> </entry> <entry><type>bytea</type></entry> <entry> @@ -2729,8 +2989,13 @@ <tbody> <row> - <entry><literal><function>btrim</function>(<parameter>string</parameter> - <type>bytea</type>, <parameter>bytes</parameter> <type>bytea</type>)</literal></entry> + <entry> + <indexterm> + <primary>btrim</primary> + </indexterm> + <literal><function>btrim(<parameter>string</parameter> + <type>bytea</type>, <parameter>bytes</parameter> <type>bytea</type>)</function></literal> + </entry> <entry><type>bytea</type></entry> <entry> Remove the longest string consisting only of bytes @@ -2743,8 +3008,11 @@ <row> <entry> - <literal><function>decode</function>(<parameter>string</parameter> <type>text</type>, - <parameter>type</parameter> <type>text</type>)</literal> + <indexterm> + <primary>decode</primary> + </indexterm> + <literal><function>decode(<parameter>string</parameter> <type>text</type>, + <parameter>type</parameter> <type>text</type>)</function></literal> </entry> <entry><type>bytea</type></entry> <entry> @@ -2757,8 +3025,11 @@ <row> <entry> - <literal><function>encode</function>(<parameter>string</parameter> <type>bytea</type>, - <parameter>type</parameter> <type>text</type>)</literal> + <indexterm> + <primary>encode</primary> + </indexterm> + <literal><function>encode(<parameter>string</parameter> <type>bytea</type>, + <parameter>type</parameter> <type>text</type>)</function></literal> </entry> <entry><type>text</type></entry> <entry> @@ -2771,14 +3042,14 @@ <row> <entry> - <literal><function>get_bit</function>(<parameter>string</parameter>, <parameter>offset</parameter>)</literal> + <indexterm> + <primary>get_bit</primary> + </indexterm> + <literal><function>get_bit(<parameter>string</parameter>, <parameter>offset</parameter>)</function></literal> </entry> <entry><type>int</type></entry> <entry> Extract bit from string - <indexterm> - <primary>get_bit</primary> - </indexterm> </entry> <entry><literal>get_bit(E'Th\\000omas'::bytea, 45)</literal></entry> <entry><literal>1</literal></entry> @@ -2786,21 +3057,26 @@ <row> <entry> - <literal><function>get_byte</function>(<parameter>string</parameter>, <parameter>offset</parameter>)</literal> + <indexterm> + <primary>get_byte</primary> + </indexterm> + <literal><function>get_byte(<parameter>string</parameter>, <parameter>offset</parameter>)</function></literal> </entry> <entry><type>int</type></entry> <entry> Extract byte from string - <indexterm> - <primary>get_byte</primary> - </indexterm> </entry> <entry><literal>get_byte(E'Th\\000omas'::bytea, 4)</literal></entry> <entry><literal>109</literal></entry> </row> <row> - <entry><literal><function>length</function>(<parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>length</primary> + </indexterm> + <literal><function>length(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>int</type></entry> <entry> Length of binary string @@ -2819,7 +3095,12 @@ </row> <row> - <entry><literal><function>md5</function>(<parameter>string</parameter>)</literal></entry> + <entry> + <indexterm> + <primary>md5</primary> + </indexterm> + <literal><function>md5(<parameter>string</parameter>)</function></literal> + </entry> <entry><type>text</type></entry> <entry> Calculates the MD5 hash of <parameter>string</parameter>, @@ -2831,15 +3112,15 @@ <row> <entry> - <literal><function>set_bit</function>(<parameter>string</parameter>, - <parameter>offset</parameter>, <parameter>newvalue</>)</literal> + <indexterm> + <primary>set_bit</primary> + </indexterm> + <literal><function>set_bit(<parameter>string</parameter>, + <parameter>offset</parameter>, <parameter>newvalue</>)</function></literal> </entry> <entry><type>bytea</type></entry> <entry> Set bit in string - <indexterm> - <primary>set_bit</primary> - </indexterm> </entry> <entry><literal>set_bit(E'Th\\000omas'::bytea, 45, 0)</literal></entry> <entry><literal>Th\000omAs</literal></entry> @@ -2847,15 +3128,15 @@ <row> <entry> - <literal><function>set_byte</function>(<parameter>string</parameter>, - <parameter>offset</parameter>, <parameter>newvalue</>)</literal> + <indexterm> + <primary>set_byte</primary> + </indexterm> + <literal><function>set_byte(<parameter>string</parameter>, + <parameter>offset</parameter>, <parameter>newvalue</>)</function></literal> </entry> <entry><type>bytea</type></entry> <entry> Set byte in string - <indexterm> - <primary>set_byte</primary> - </indexterm> </entry> <entry><literal>set_byte(E'Th\\000omas'::bytea, 4, 64)</literal></entry> <entry><literal>Th\000o@as</literal></entry> @@ -2864,6 +3145,13 @@ </tgroup> </table> + <para> + <function>get_byte</> and <function>set_byte</> number the first byte + of a binary string as byte 0. + <function>get_bit</> and <function>set_bit</> number bits from the + right within each byte; for example bit 0 is the least significant bit of + the first byte, and bit 15 is the most significant bit of the second byte. + </para> </sect1> @@ -2969,6 +3257,8 @@ strings: <literal><function>get_bit</function></literal>, <literal><function>set_bit</function></literal>. + When working with a bit string, these functions number the first + (leftmost) bit of the string as bit 0. </para> <para> @@ -3416,8 +3706,8 @@ substring('foobar' from 'o(.)b') <lineannotation>o</lineannotation> match, the <replaceable>source</> string is returned with the <replaceable>replacement</> string substituted for the matching substring. The <replaceable>replacement</> string can contain - <literal>\</><replaceable>n</>, where <replaceable>n</> is <literal>1</> - through <literal>9</>, to indicate that the source substring matching the + <literal>\</><replaceable>n</>, where <replaceable>n</> is 1 + through 9, to indicate that the source substring matching the <replaceable>n</>'th parenthesized subexpression of the pattern should be inserted, and it can contain <literal>\&</> to indicate that the substring matching the entire pattern should be inserted. Write @@ -4061,7 +4351,7 @@ SELECT foo FROM regexp_split_to_table('the quick brown fox', E'\\s*') AS foo; </note> <table id="posix-character-entry-escapes-table"> - <title>Regular Expression Character-Entry Escapes</title> + <title>Regular Expression Character-entry Escapes</title> <tgroup cols="2"> <thead> @@ -4189,7 +4479,7 @@ SELECT foo FROM regexp_split_to_table('the quick brown fox', E'\\s*') AS foo; </para> <table id="posix-class-shorthand-escapes-table"> - <title>Regular Expression Class-Shorthand Escapes</title> + <title>Regular Expression Class-shorthand Escapes</title> <tgroup cols="2"> <thead> @@ -4383,7 +4673,7 @@ SELECT foo FROM regexp_split_to_table('the quick brown fox', E'\\s*') AS foo; </para> <table id="posix-embedded-options-table"> - <title>ARE Embedded-Option Letters</title> + <title>ARE Embedded-option Letters</title> <tgroup cols="2"> <thead> @@ -4796,19 +5086,6 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <primary>formatting</primary> </indexterm> - <indexterm> - <primary>to_char</primary> - </indexterm> - <indexterm> - <primary>to_date</primary> - </indexterm> - <indexterm> - <primary>to_number</primary> - </indexterm> - <indexterm> - <primary>to_timestamp</primary> - </indexterm> - <para> The <productname>PostgreSQL</productname> formatting functions provide a powerful set of tools for converting various data types @@ -4842,19 +5119,24 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </thead> <tbody> <row> - <entry><literal><function>to_char</function>(<type>timestamp</type>, <type>text</type>)</literal></entry> + <entry> + <indexterm> + <primary>to_char</primary> + </indexterm> + <literal><function>to_char(<type>timestamp</type>, <type>text</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry>convert time stamp to string</entry> <entry><literal>to_char(current_timestamp, 'HH12:MI:SS')</literal></entry> </row> <row> - <entry><literal><function>to_char</function>(<type>interval</type>, <type>text</type>)</literal></entry> + <entry><literal><function>to_char(<type>interval</type>, <type>text</type>)</function></literal></entry> <entry><type>text</type></entry> <entry>convert interval to string</entry> <entry><literal>to_char(interval '15h 2m 12s', 'HH24:MI:SS')</literal></entry> </row> <row> - <entry><literal><function>to_char</function>(<type>int</type>, <type>text</type>)</literal></entry> + <entry><literal><function>to_char(<type>int</type>, <type>text</type>)</function></literal></entry> <entry><type>text</type></entry> <entry>convert integer to string</entry> <entry><literal>to_char(125, '999')</literal></entry> @@ -4867,31 +5149,46 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <entry><literal>to_char(125.8::real, '999D9')</literal></entry> </row> <row> - <entry><literal><function>to_char</function>(<type>numeric</type>, <type>text</type>)</literal></entry> + <entry><literal><function>to_char(<type>numeric</type>, <type>text</type>)</function></literal></entry> <entry><type>text</type></entry> <entry>convert numeric to string</entry> <entry><literal>to_char(-125.8, '999D99S')</literal></entry> </row> <row> - <entry><literal><function>to_date</function>(<type>text</type>, <type>text</type>)</literal></entry> + <entry> + <indexterm> + <primary>to_date</primary> + </indexterm> + <literal><function>to_date(<type>text</type>, <type>text</type>)</function></literal> + </entry> <entry><type>date</type></entry> <entry>convert string to date</entry> <entry><literal>to_date('05 Dec 2000', 'DD Mon YYYY')</literal></entry> </row> <row> - <entry><literal><function>to_number</function>(<type>text</type>, <type>text</type>)</literal></entry> + <entry> + <indexterm> + <primary>to_number</primary> + </indexterm> + <literal><function>to_number(<type>text</type>, <type>text</type>)</function></literal> + </entry> <entry><type>numeric</type></entry> <entry>convert string to numeric</entry> <entry><literal>to_number('12,454.8-', '99G999D9S')</literal></entry> </row> <row> - <entry><literal><function>to_timestamp</function>(<type>text</type>, <type>text</type>)</literal></entry> + <entry> + <indexterm> + <primary>to_timestamp</primary> + </indexterm> + <literal><function>to_timestamp(<type>text</type>, <type>text</type>)</function></literal> + </entry> <entry><type>timestamp with time zone</type></entry> <entry>convert string to time stamp</entry> <entry><literal>to_timestamp('05 Dec 2000', 'DD Mon YYYY')</literal></entry> </row> <row> - <entry><literal><function>to_timestamp</function>(<type>double precision</type>)</literal></entry> + <entry><literal><function>to_timestamp(<type>double precision</type>)</function></literal></entry> <entry><type>timestamp with time zone</type></entry> <entry>convert Unix epoch to time stamp</entry> <entry><literal>to_timestamp(1284352323)</literal></entry> @@ -4931,15 +5228,15 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <row> <entry><literal>HH12</literal></entry> <entry>hour of day (01-12)</entry> - </row> + </row> <row> <entry><literal>HH24</literal></entry> <entry>hour of day (00-23)</entry> - </row> + </row> <row> <entry><literal>MI</literal></entry> <entry>minute (00-59)</entry> - </row> + </row> <row> <entry><literal>SS</literal></entry> <entry>second (00-59)</entry> @@ -5087,7 +5384,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <row> <entry><literal>W</literal></entry> <entry>week of month (1-5) (The first week starts on the first day of the month.)</entry> - </row> + </row> <row> <entry><literal>WW</literal></entry> <entry>week number of year (1-53) (The first week starts on the first day of the year.)</entry> @@ -5150,14 +5447,14 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <tbody> <row> <entry><literal>FM</literal> prefix</entry> - <entry>fill mode (suppress padding blanks and zeroes)</entry> + <entry>fill mode (suppress padding blanks and trailing zeroes)</entry> <entry><literal>FMMonth</literal></entry> </row> <row> <entry><literal>TH</literal> suffix</entry> <entry>upper case ordinal number suffix</entry> <entry><literal>DDTH</literal>, e.g., <literal>12TH</></entry> - </row> + </row> <row> <entry><literal>th</literal> suffix</entry> <entry>lower case ordinal number suffix</entry> @@ -5167,18 +5464,18 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <entry><literal>FX</literal> prefix</entry> <entry>fixed format global option (see usage notes)</entry> <entry><literal>FX Month DD Day</literal></entry> - </row> + </row> <row> <entry><literal>TM</literal> prefix</entry> <entry>translation mode (print localized day and month names based on <xref linkend="guc-lc-time">)</entry> <entry><literal>TMMonth</literal></entry> - </row> + </row> <row> <entry><literal>SP</literal> suffix</entry> <entry>spell mode (not implemented)</entry> <entry><literal>DDSP</literal></entry> - </row> + </row> </tbody> </tgroup> </table> @@ -5250,8 +5547,8 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); use some non-digit character or template after <literal>YYYY</literal>, otherwise the year is always interpreted as 4 digits. For example (with the year 20000): - <literal>to_date('200001131', 'YYYYMMDD')</literal> will be - interpreted as a 4-digit year; instead use a non-digit + <literal>to_date('200001131', 'YYYYMMDD')</literal> will be + interpreted as a 4-digit year; instead use a non-digit separator after the year, like <literal>to_date('20000-1131', 'YYYY-MMDD')</literal> or <literal>to_date('20000Nov31', 'YYYYMonDD')</literal>. @@ -5306,7 +5603,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); In a conversion from string to <type>timestamp</type>, millisecond (<literal>MS</literal>) or microsecond (<literal>US</literal>) values are used as the - seconds digits after the decimal point. For example + seconds digits after the decimal point. For example <literal>to_timestamp('12:3', 'SS:MS')</literal> is not 3 milliseconds, but 300, because the conversion counts it as 12 + 0.3 seconds. This means for the format <literal>SS:MS</literal>, the input values @@ -5317,11 +5614,11 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </para> <para> - Here is a more - complex example: + Here is a more + complex example: <literal>to_timestamp('15:12:02.020.001230', 'HH:MI:SS.MS.US')</literal> is 15 hours, 12 minutes, and 2 seconds + 20 milliseconds + - 1230 microseconds = 2.021230 seconds. + 1230 microseconds = 2.021230 seconds. </para> </listitem> @@ -5372,7 +5669,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <row> <entry><literal>.</literal> (period)</entry> <entry>decimal point</entry> - </row> + </row> <row> <entry><literal>,</literal> (comma)</entry> <entry>group (thousand) separator</entry> @@ -5449,7 +5746,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <listitem> <para> - <literal>9</literal> results in a value with the same number of + <literal>9</literal> results in a value with the same number of digits as there are <literal>9</literal>s. If a digit is not available it outputs a space. </para> @@ -5466,7 +5763,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <para> <literal>PL</literal>, <literal>SG</literal>, and <literal>TH</literal> are <productname>PostgreSQL</productname> - extensions. + extensions. </para> </listitem> @@ -5516,14 +5813,14 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <tbody> <row> <entry><literal>FM</literal> prefix</entry> - <entry>fill mode (suppress padding blanks and zeroes)</entry> + <entry>fill mode (suppress padding blanks and trailing zeroes)</entry> <entry><literal>FM9999</literal></entry> </row> <row> <entry><literal>TH</literal> suffix</entry> <entry>upper case ordinal number suffix</entry> <entry><literal>999TH</literal></entry> - </row> + </row> <row> <entry><literal>th</literal> suffix</entry> <entry>lower case ordinal number suffix</entry> @@ -5555,7 +5852,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <row> <entry><literal>to_char(current_timestamp, 'FMDay, FMDD HH12:MI:SS')</literal></entry> <entry><literal>'Tuesday, 6 05:39:18'</literal></entry> - </row> + </row> <row> <entry><literal>to_char(-0.1, '99.99')</literal></entry> <entry><literal>' -.10'</literal></entry> @@ -5610,7 +5907,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> <entry><literal>to_char(148.5, '999D999')</literal></entry> - <entry><literal>' 148,500'</literal></entry> + <entry><literal>' 148,500'</literal></entry> </row> <row> <entry><literal>to_char(3148.5, '9G999D999')</literal></entry> @@ -5620,57 +5917,57 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <entry><literal>to_char(-485, '999S')</literal></entry> <entry><literal>'485-'</literal></entry> </row> - <row> + <row> <entry><literal>to_char(-485, '999MI')</literal></entry> - <entry><literal>'485-'</literal></entry> + <entry><literal>'485-'</literal></entry> </row> <row> <entry><literal>to_char(485, '999MI')</literal></entry> - <entry><literal>'485 '</literal></entry> + <entry><literal>'485 '</literal></entry> </row> <row> <entry><literal>to_char(485, 'FM999MI')</literal></entry> - <entry><literal>'485'</literal></entry> + <entry><literal>'485'</literal></entry> </row> <row> <entry><literal>to_char(485, 'PL999')</literal></entry> - <entry><literal>'+485'</literal></entry> + <entry><literal>'+485'</literal></entry> </row> - <row> + <row> <entry><literal>to_char(485, 'SG999')</literal></entry> - <entry><literal>'+485'</literal></entry> + <entry><literal>'+485'</literal></entry> </row> <row> <entry><literal>to_char(-485, 'SG999')</literal></entry> - <entry><literal>'-485'</literal></entry> + <entry><literal>'-485'</literal></entry> </row> <row> <entry><literal>to_char(-485, '9SG99')</literal></entry> - <entry><literal>'4-85'</literal></entry> + <entry><literal>'4-85'</literal></entry> </row> <row> <entry><literal>to_char(-485, '999PR')</literal></entry> - <entry><literal>'<485>'</literal></entry> + <entry><literal>'<485>'</literal></entry> </row> <row> <entry><literal>to_char(485, 'L999')</literal></entry> - <entry><literal>'DM 485</literal></entry> + <entry><literal>'DM 485</literal></entry> </row> <row> - <entry><literal>to_char(485, 'RN')</literal></entry> + <entry><literal>to_char(485, 'RN')</literal></entry> <entry><literal>' CDLXXXV'</literal></entry> </row> <row> - <entry><literal>to_char(485, 'FMRN')</literal></entry> + <entry><literal>to_char(485, 'FMRN')</literal></entry> <entry><literal>'CDLXXXV'</literal></entry> </row> <row> <entry><literal>to_char(5.2, 'FMRN')</literal></entry> - <entry><literal>'V'</literal></entry> + <entry><literal>'V'</literal></entry> </row> <row> <entry><literal>to_char(482, '999th')</literal></entry> - <entry><literal>' 482nd'</literal></entry> + <entry><literal>' 482nd'</literal></entry> </row> <row> <entry><literal>to_char(485, '"Good number:"999')</literal></entry> @@ -5681,14 +5978,14 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <entry><literal>'Pre: 485 Post: .800'</literal></entry> </row> <row> - <entry><literal>to_char(12, '99V999')</literal></entry> + <entry><literal>to_char(12, '99V999')</literal></entry> <entry><literal>' 12000'</literal></entry> </row> <row> <entry><literal>to_char(12.4, '99V999')</literal></entry> <entry><literal>' 12400'</literal></entry> </row> - <row> + <row> <entry><literal>to_char(12.45, '99V9')</literal></entry> <entry><literal>' 125'</literal></entry> </row> @@ -5858,61 +6155,6 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </tgroup> </table> - <indexterm> - <primary>age</primary> - </indexterm> - <indexterm> - <primary>clock_timestamp</primary> - </indexterm> - <indexterm> - <primary>current_date</primary> - </indexterm> - <indexterm> - <primary>current_time</primary> - </indexterm> - <indexterm> - <primary>current_timestamp</primary> - </indexterm> - <indexterm> - <primary>date_part</primary> - </indexterm> - <indexterm> - <primary>date_trunc</primary> - </indexterm> - <indexterm> - <primary>extract</primary> - </indexterm> - <indexterm> - <primary>isfinite</primary> - </indexterm> - <indexterm> - <primary>justify_days</primary> - </indexterm> - <indexterm> - <primary>justify_hours</primary> - </indexterm> - <indexterm> - <primary>justify_interval</primary> - </indexterm> - <indexterm> - <primary>localtime</primary> - </indexterm> - <indexterm> - <primary>localtimestamp</primary> - </indexterm> - <indexterm> - <primary>now</primary> - </indexterm> - <indexterm> - <primary>statement_timestamp</primary> - </indexterm> - <indexterm> - <primary>timeofday</primary> - </indexterm> - <indexterm> - <primary>transaction_timestamp</primary> - </indexterm> - <table id="functions-datetime-table"> <title>Date/Time Functions</title> <tgroup cols="5"> @@ -5928,7 +6170,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); <tbody> <row> - <entry><literal><function>age</function>(<type>timestamp</type>, <type>timestamp</type>)</literal></entry> + <entry> + <indexterm> + <primary>age</primary> + </indexterm> + <literal><function>age(<type>timestamp</type>, <type>timestamp</type>)</function></literal> + </entry> <entry><type>interval</type></entry> <entry>Subtract arguments, producing a <quote>symbolic</> result that uses years and months</entry> @@ -5937,7 +6184,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>age</function>(<type>timestamp</type>)</literal></entry> + <entry><literal><function>age(<type>timestamp</type>)</function></literal></entry> <entry><type>interval</type></entry> <entry>Subtract from <function>current_date</function> (at midnight)</entry> <entry><literal>age(timestamp '1957-06-13')</literal></entry> @@ -5945,7 +6192,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>clock_timestamp</function>()</literal></entry> + <entry> + <indexterm> + <primary>clock_timestamp</primary> + </indexterm> + <literal><function>clock_timestamp()</function></literal> + </entry> <entry><type>timestamp with time zone</type></entry> <entry>Current date and time (changes during statement execution); see <xref linkend="functions-datetime-current"> @@ -5955,7 +6207,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>current_date</function></literal></entry> + <entry> + <indexterm> + <primary>current_date</primary> + </indexterm> + <literal><function>current_date</function></literal> + </entry> <entry><type>date</type></entry> <entry>Current date; see <xref linkend="functions-datetime-current"> @@ -5965,7 +6222,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>current_time</function></literal></entry> + <entry> + <indexterm> + <primary>current_time</primary> + </indexterm> + <literal><function>current_time</function></literal> + </entry> <entry><type>time with time zone</type></entry> <entry>Current time of day; see <xref linkend="functions-datetime-current"> @@ -5975,7 +6237,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>current_timestamp</function></literal></entry> + <entry> + <indexterm> + <primary>current_timestamp</primary> + </indexterm> + <literal><function>current_timestamp</function></literal> + </entry> <entry><type>timestamp with time zone</type></entry> <entry>Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"> @@ -5985,7 +6252,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>date_part</function>(<type>text</type>, <type>timestamp</type>)</literal></entry> + <entry> + <indexterm> + <primary>date_part</primary> + </indexterm> + <literal><function>date_part(<type>text</type>, <type>timestamp</type>)</function></literal> + </entry> <entry><type>double precision</type></entry> <entry>Get subfield (equivalent to <function>extract</function>); see <xref linkend="functions-datetime-extract"> @@ -5995,7 +6267,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>date_part</function>(<type>text</type>, <type>interval</type>)</literal></entry> + <entry><literal><function>date_part(<type>text</type>, <type>interval</type>)</function></literal></entry> <entry><type>double precision</type></entry> <entry>Get subfield (equivalent to <function>extract</function>); see <xref linkend="functions-datetime-extract"> @@ -6005,7 +6277,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>date_trunc</function>(<type>text</type>, <type>timestamp</type>)</literal></entry> + <entry> + <indexterm> + <primary>date_trunc</primary> + </indexterm> + <literal><function>date_trunc(<type>text</type>, <type>timestamp</type>)</function></literal> + </entry> <entry><type>timestamp</type></entry> <entry>Truncate to specified precision; see also <xref linkend="functions-datetime-trunc"> </entry> @@ -6014,8 +6291,13 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>extract</function>(<parameter>field</parameter> from - <type>timestamp</type>)</literal></entry> + <entry> + <indexterm> + <primary>extract</primary> + </indexterm> + <literal><function>extract</function>(<parameter>field</parameter> from + <type>timestamp</type>)</literal> + </entry> <entry><type>double precision</type></entry> <entry>Get subfield; see <xref linkend="functions-datetime-extract"> </entry> @@ -6034,7 +6316,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>isfinite</function>(<type>date</type>)</literal></entry> + <entry> + <indexterm> + <primary>isfinite</primary> + </indexterm> + <literal><function>isfinite(<type>date</type>)</function></literal> + </entry> <entry><type>boolean</type></entry> <entry>Test for finite date (not +/-infinity)</entry> <entry><literal>isfinite(date '2001-02-16')</literal></entry> @@ -6042,7 +6329,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>isfinite</function>(<type>timestamp</type>)</literal></entry> + <entry><literal><function>isfinite(<type>timestamp</type>)</function></literal></entry> <entry><type>boolean</type></entry> <entry>Test for finite time stamp (not +/-infinity)</entry> <entry><literal>isfinite(timestamp '2001-02-16 21:28:30')</literal></entry> @@ -6050,7 +6337,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>isfinite</function>(<type>interval</type>)</literal></entry> + <entry><literal><function>isfinite(<type>interval</type>)</function></literal></entry> <entry><type>boolean</type></entry> <entry>Test for finite interval</entry> <entry><literal>isfinite(interval '4 hours')</literal></entry> @@ -6058,7 +6345,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>justify_days</function>(<type>interval</type>)</literal></entry> + <entry> + <indexterm> + <primary>justify_days</primary> + </indexterm> + <literal><function>justify_days(<type>interval</type>)</function></literal> + </entry> <entry><type>interval</type></entry> <entry>Adjust interval so 30-day time periods are represented as months</entry> <entry><literal>justify_days(interval '35 days')</literal></entry> @@ -6066,7 +6358,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>justify_hours</function>(<type>interval</type>)</literal></entry> + <entry> + <indexterm> + <primary>justify_hours</primary> + </indexterm> + <literal><function>justify_hours(<type>interval</type>)</function></literal> + </entry> <entry><type>interval</type></entry> <entry>Adjust interval so 24-hour time periods are represented as days</entry> <entry><literal>justify_hours(interval '27 hours')</literal></entry> @@ -6074,7 +6371,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>justify_interval</function>(<type>interval</type>)</literal></entry> + <entry> + <indexterm> + <primary>justify_interval</primary> + </indexterm> + <literal><function>justify_interval(<type>interval</type>)</function></literal> + </entry> <entry><type>interval</type></entry> <entry>Adjust interval using <function>justify_days</> and <function>justify_hours</>, with additional sign adjustments</entry> <entry><literal>justify_interval(interval '1 mon -1 hour')</literal></entry> @@ -6082,7 +6384,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>localtime</function></literal></entry> + <entry> + <indexterm> + <primary>localtime</primary> + </indexterm> + <literal><function>localtime</function></literal> + </entry> <entry><type>time</type></entry> <entry>Current time of day; see <xref linkend="functions-datetime-current"> @@ -6092,7 +6399,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>localtimestamp</function></literal></entry> + <entry> + <indexterm> + <primary>localtimestamp</primary> + </indexterm> + <literal><function>localtimestamp</function></literal> + </entry> <entry><type>timestamp</type></entry> <entry>Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"> @@ -6102,7 +6414,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>now</function>()</literal></entry> + <entry> + <indexterm> + <primary>now</primary> + </indexterm> + <literal><function>now()</function></literal> + </entry> <entry><type>timestamp with time zone</type></entry> <entry>Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"> @@ -6112,7 +6429,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>statement_timestamp</function>()</literal></entry> + <entry> + <indexterm> + <primary>statement_timestamp</primary> + </indexterm> + <literal><function>statement_timestamp()</function></literal> + </entry> <entry><type>timestamp with time zone</type></entry> <entry>Current date and time (start of current statement); see <xref linkend="functions-datetime-current"> @@ -6122,7 +6444,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>timeofday</function>()</literal></entry> + <entry> + <indexterm> + <primary>timeofday</primary> + </indexterm> + <literal><function>timeofday()</function></literal> + </entry> <entry><type>text</type></entry> <entry>Current date and time (like <function>clock_timestamp</>, but as a <type>text</> string); @@ -6133,7 +6460,12 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); </row> <row> - <entry><literal><function>transaction_timestamp</function>()</literal></entry> + <entry> + <indexterm> + <primary>transaction_timestamp</primary> + </indexterm> + <literal><function>transaction_timestamp()</function></literal> + </entry> <entry><type>timestamp with time zone</type></entry> <entry>Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"> @@ -6182,20 +6514,20 @@ SELECT (DATE '2001-10-30', DATE '2001-10-30') OVERLAPS </screen> <para> - When adding an <type>interval</type> value to (or subtracting an - <type>interval</type> value from) a <type>timestamp with time zone</type> - value, the days component advances (or decrements) the date of the - <type>timestamp with time zone</type> by the indicated number of days. - Across daylight saving time changes (with the session time zone set to a - time zone that recognizes DST), this means <literal>interval '1 day'</literal> - does not necessarily equal <literal>interval '24 hours'</literal>. + When adding an <type>interval</type> value to (or subtracting an + <type>interval</type> value from) a <type>timestamp with time zone</type> + value, the days component advances (or decrements) the date of the + <type>timestamp with time zone</type> by the indicated number of days. + Across daylight saving time changes (with the session time zone set to a + time zone that recognizes DST), this means <literal>interval '1 day'</literal> + does not necessarily equal <literal>interval '24 hours'</literal>. For example, with the session time zone set to <literal>CST7CDT</literal>, <literal>timestamp with time zone '2005-04-02 12:00-07' + interval '1 day' </literal> - will produce <literal>timestamp with time zone '2005-04-03 12:00-06'</literal>, - while adding <literal>interval '24 hours'</literal> to the same initial + will produce <literal>timestamp with time zone '2005-04-03 12:00-06'</literal>, + while adding <literal>interval '24 hours'</literal> to the same initial <type>timestamp with time zone</type> produces <literal>timestamp with time zone '2005-04-03 13:00-06'</literal>, as there is - a change in daylight saving time at <literal>2005-04-03 02:00</literal> in time zone + a change in daylight saving time at <literal>2005-04-03 02:00</literal> in time zone <literal>CST7CDT</literal>. </para> @@ -6274,13 +6606,20 @@ SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40'); <term><literal>day</literal></term> <listitem> <para> - The day (of the month) field (1 - 31) + For <type>timestamp</type> values, the day (of the month) field + (1 - 31) ; for <type>interval</type> values, the number of days </para> <screen> SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40'); <lineannotation>Result: </lineannotation><computeroutput>16</computeroutput> + +SELECT EXTRACT(DAY FROM INTERVAL '40 days 1 minute'); +<lineannotation>Result: </lineannotation><computeroutput>40</computeroutput> </screen> + + + </listitem> </varlistentry> @@ -6496,7 +6835,7 @@ SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40'); <listitem> <para> For <type>timestamp</type> values, the number of the month - within the year (1 - 12) ; for <type>interval</type> values + within the year (1 - 12) ; for <type>interval</type> values, the number of months, modulo 12 (0 - 11) </para> @@ -6585,9 +6924,9 @@ SELECT EXTRACT(SECOND FROM TIME '17:12:28.5'); a year is in week 1 of that year. </para> <para> - Because of this, it is possible for early January dates to be part of the + Because of this, it is possible for early January dates to be part of the 52nd or 53rd week of the previous year. For example, <literal>2005-01-01</> - is part of the 53rd week of year 2004, and <literal>2006-01-01</> is part of + is part of the 53rd week of year 2004, and <literal>2006-01-01</> is part of the 52nd week of year 2005. </para> @@ -6602,7 +6941,7 @@ SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40'); <term><literal>year</literal></term> <listitem> <para> - The year field. Keep in mind there is no <literal>0 AD</>, so subtracting + The year field. Keep in mind there is no <literal>0 AD</>, so subtracting <literal>BC</> years from <literal>AD</> years should be done with care. </para> @@ -6781,7 +7120,7 @@ SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'MST'; <lineannotation>Result: </lineannotation><computeroutput>2001-02-16 18:38:40</computeroutput> </screen> The first example takes a time stamp without time zone and interprets it as MST time - (UTC-7), which is then converted to PST (UTC-8) for display. The second example takes + (UTC-7), which is then converted to PST (UTC-8) for display. The second example takes a time stamp specified in EST (UTC-5) and converts it to local time in MST (UTC-7). </para> @@ -6789,7 +7128,7 @@ SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'MST'; The function <literal><function>timezone</function>(<replaceable>zone</>, <replaceable>timestamp</>)</literal> is equivalent to the SQL-conforming construct <literal><replaceable>timestamp</> AT TIME ZONE - <replaceable>zone</></literal>. + <replaceable>zone</></literal>. </para> </sect2> @@ -6991,7 +7330,7 @@ SELECT pg_sleep(1.5); </sect1> - + <sect1 id="functions-enum"> <title>Enum Support Functions</title> @@ -7021,19 +7360,34 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple </thead> <tbody> <row> - <entry><literal>enum_first(anyenum)</literal></entry> + <entry> + <indexterm> + <primary>enum_first</primary> + </indexterm> + <literal>enum_first(anyenum)</literal> + </entry> <entry>Returns the first value of the input enum type</entry> <entry><literal>enum_first(null::rainbow)</literal></entry> <entry><literal>red</literal></entry> </row> <row> - <entry><literal>enum_last(anyenum)</literal></entry> + <entry> + <indexterm> + <primary>enum_last</primary> + </indexterm> + <literal>enum_last(anyenum)</literal> + </entry> <entry>Returns the last value of the input enum type</entry> <entry><literal>enum_last(null::rainbow)</literal></entry> <entry><literal>purple</literal></entry> </row> <row> - <entry><literal>enum_range(anyenum)</literal></entry> + <entry> + <indexterm> + <primary>enum_range</primary> + </indexterm> + <literal>enum_range(anyenum)</literal> + </entry> <entry>Returns all values of the input enum type in an ordered array</entry> <entry><literal>enum_range(null::rainbow)</literal></entry> <entry><literal>{red,orange,yellow,green,blue,purple}</literal></entry> @@ -7327,61 +7681,61 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple </thead> <tbody> <row> - <entry><literal><function>area</function>(<replaceable>object</>)</literal></entry> + <entry><literal><function>area(<replaceable>object</>)</function></literal></entry> <entry><type>double precision</type></entry> <entry>area</entry> <entry><literal>area(box '((0,0),(1,1))')</literal></entry> </row> <row> - <entry><literal><function>center</function>(<replaceable>object</>)</literal></entry> + <entry><literal><function>center(<replaceable>object</>)</function></literal></entry> <entry><type>point</type></entry> <entry>center</entry> <entry><literal>center(box '((0,0),(1,2))')</literal></entry> </row> <row> - <entry><literal><function>diameter</function>(<type>circle</>)</literal></entry> + <entry><literal><function>diameter(<type>circle</>)</function></literal></entry> <entry><type>double precision</type></entry> <entry>diameter of circle</entry> <entry><literal>diameter(circle '((0,0),2.0)')</literal></entry> </row> <row> - <entry><literal><function>height</function>(<type>box</>)</literal></entry> + <entry><literal><function>height(<type>box</>)</function></literal></entry> <entry><type>double precision</type></entry> <entry>vertical size of box</entry> <entry><literal>height(box '((0,0),(1,1))')</literal></entry> </row> <row> - <entry><literal><function>isclosed</function>(<type>path</>)</literal></entry> + <entry><literal><function>isclosed(<type>path</>)</function></literal></entry> <entry><type>boolean</type></entry> <entry>a closed path?</entry> <entry><literal>isclosed(path '((0,0),(1,1),(2,0))')</literal></entry> </row> <row> - <entry><literal><function>isopen</function>(<type>path</>)</literal></entry> + <entry><literal><function>isopen(<type>path</>)</function></literal></entry> <entry><type>boolean</type></entry> <entry>an open path?</entry> <entry><literal>isopen(path '[(0,0),(1,1),(2,0)]')</literal></entry> </row> <row> - <entry><literal><function>length</function>(<replaceable>object</>)</literal></entry> + <entry><literal><function>length(<replaceable>object</>)</function></literal></entry> <entry><type>double precision</type></entry> <entry>length</entry> <entry><literal>length(path '((-1,0),(1,0))')</literal></entry> </row> <row> - <entry><literal><function>npoints</function>(<type>path</>)</literal></entry> + <entry><literal><function>npoints(<type>path</>)</function></literal></entry> <entry><type>int</type></entry> <entry>number of points</entry> <entry><literal>npoints(path '[(0,0),(1,1),(2,0)]')</literal></entry> </row> <row> - <entry><literal><function>npoints</function>(<type>polygon</>)</literal></entry> + <entry><literal><function>npoints(<type>polygon</>)</function></literal></entry> <entry><type>int</type></entry> <entry>number of points</entry> <entry><literal>npoints(polygon '((1,1),(0,0))')</literal></entry> </row> <row> - <entry><literal><function>pclose</function>(<type>path</>)</literal></entry> + <entry><literal><function>pclose(<type>path</>)</function></literal></entry> <entry><type>path</type></entry> <entry>convert path to closed</entry> <entry><literal>pclose(path '[(0,0),(1,1),(2,0)]')</literal></entry> @@ -7389,26 +7743,26 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple <![IGNORE[ <!-- Not defined by this name. Implements the intersection operator '#' --> <row> - <entry><literal><function>point</function>(<type>lseg</>, <type>lseg</>)</literal></entry> + <entry><literal><function>point(<type>lseg</>, <type>lseg</>)</function></literal></entry> <entry><type>point</type></entry> <entry>intersection</entry> <entry><literal>point(lseg '((-1,0),(1,0))',lseg '((-2,-2),(2,2))')</literal></entry> </row> ]]> <row> - <entry><literal><function>popen</function>(<type>path</>)</literal></entry> + <entry><literal><function>popen(<type>path</>)</function></literal></entry> <entry><type>path</type></entry> <entry>convert path to open</entry> <entry><literal>popen(path '((0,0),(1,1),(2,0))')</literal></entry> </row> <row> - <entry><literal><function>radius</function>(<type>circle</type>)</literal></entry> + <entry><literal><function>radius(<type>circle</type>)</function></literal></entry> <entry><type>double precision</type></entry> <entry>radius of circle</entry> <entry><literal>radius(circle '((0,0),2.0)')</literal></entry> </row> <row> - <entry><literal><function>width</function>(<type>box</>)</literal></entry> + <entry><literal><function>width(<type>box</>)</function></literal></entry> <entry><type>double precision</type></entry> <entry>horizontal size of box</entry> <entry><literal>width(box '((0,0),(1,1))')</literal></entry> @@ -7430,110 +7784,140 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple </thead> <tbody> <row> - <entry><literal><function>box</function>(<type>circle</type>)</literal></entry> + <entry> + <indexterm> + <primary>box</primary> + </indexterm> + <literal><function>box(<type>circle</type>)</function></literal> + </entry> <entry><type>box</type></entry> <entry>circle to box</entry> <entry><literal>box(circle '((0,0),2.0)')</literal></entry> </row> <row> - <entry><literal><function>box</function>(<type>point</type>, <type>point</type>)</literal></entry> + <entry><literal><function>box(<type>point</type>, <type>point</type>)</function></literal></entry> <entry><type>box</type></entry> <entry>points to box</entry> <entry><literal>box(point '(0,0)', point '(1,1)')</literal></entry> </row> <row> - <entry><literal><function>box</function>(<type>polygon</type>)</literal></entry> + <entry><literal><function>box(<type>polygon</type>)</function></literal></entry> <entry><type>box</type></entry> <entry>polygon to box</entry> <entry><literal>box(polygon '((0,0),(1,1),(2,0))')</literal></entry> </row> <row> - <entry><literal><function>circle</function>(<type>box</type>)</literal></entry> + <entry> + <indexterm> + <primary>circle</primary> + </indexterm> + <literal><function>circle(<type>box</type>)</function></literal> + </entry> <entry><type>circle</type></entry> <entry>box to circle</entry> <entry><literal>circle(box '((0,0),(1,1))')</literal></entry> </row> <row> - <entry><literal><function>circle</function>(<type>point</type>, <type>double precision</type>)</literal></entry> + <entry><literal><function>circle(<type>point</type>, <type>double precision</type>)</function></literal></entry> <entry><type>circle</type></entry> <entry>center and radius to circle</entry> <entry><literal>circle(point '(0,0)', 2.0)</literal></entry> </row> <row> - <entry><literal><function>circle</function>(<type>polygon</type>)</literal></entry> + <entry><literal><function>circle(<type>polygon</type>)</function></literal></entry> <entry><type>circle</type></entry> <entry>polygon to circle</entry> <entry><literal>circle(polygon '((0,0),(1,1),(2,0))')</literal></entry> </row> <row> - <entry><literal><function>lseg</function>(<type>box</type>)</literal></entry> + <entry> + <indexterm> + <primary>lseg</primary> + </indexterm> + <literal><function>lseg(<type>box</type>)</function></literal> + </entry> <entry><type>lseg</type></entry> <entry>box diagonal to line segment</entry> <entry><literal>lseg(box '((-1,0),(1,0))')</literal></entry> </row> <row> - <entry><literal><function>lseg</function>(<type>point</type>, <type>point</type>)</literal></entry> + <entry><literal><function>lseg(<type>point</type>, <type>point</type>)</function></literal></entry> <entry><type>lseg</type></entry> <entry>points to line segment</entry> <entry><literal>lseg(point '(-1,0)', point '(1,0)')</literal></entry> </row> <row> - <entry><literal><function>path</function>(<type>polygon</type>)</literal></entry> + <entry> + <indexterm> + <primary>path</primary> + </indexterm> + <literal><function>path(<type>polygon</type>)</function></literal> + </entry> <entry><type>point</type></entry> <entry>polygon to path</entry> <entry><literal>path(polygon '((0,0),(1,1),(2,0))')</literal></entry> </row> <row> - <entry><literal><function>point</function>(<type>double - precision</type>, <type>double precision</type>)</literal></entry> + <entry> + <indexterm> + <primary>point</primary> + </indexterm> + <literal><function>point</function>(<type>double + precision</type>, <type>double precision</type>)</literal> + </entry> <entry><type>point</type></entry> <entry>construct point</entry> <entry><literal>point(23.4, -44.5)</literal></entry> </row> <row> - <entry><literal><function>point</function>(<type>box</type>)</literal></entry> + <entry><literal><function>point(<type>box</type>)</function></literal></entry> <entry><type>point</type></entry> <entry>center of box</entry> <entry><literal>point(box '((-1,0),(1,0))')</literal></entry> </row> <row> - <entry><literal><function>point</function>(<type>circle</type>)</literal></entry> + <entry><literal><function>point(<type>circle</type>)</function></literal></entry> <entry><type>point</type></entry> <entry>center of circle</entry> <entry><literal>point(circle '((0,0),2.0)')</literal></entry> </row> <row> - <entry><literal><function>point</function>(<type>lseg</type>)</literal></entry> + <entry><literal><function>point(<type>lseg</type>)</function></literal></entry> <entry><type>point</type></entry> <entry>center of line segment</entry> <entry><literal>point(lseg '((-1,0),(1,0))')</literal></entry> </row> <row> - <entry><literal><function>point</function>(<type>polygon</type>)</literal></entry> + <entry><literal><function>point(<type>polygon</type>)</function></literal></entry> <entry><type>point</type></entry> <entry>center of polygon</entry> <entry><literal>point(polygon '((0,0),(1,1),(2,0))')</literal></entry> </row> <row> - <entry><literal><function>polygon</function>(<type>box</type>)</literal></entry> + <entry> + <indexterm> + <primary>polygon</primary> + </indexterm> + <literal><function>polygon(<type>box</type>)</function></literal> + </entry> <entry><type>polygon</type></entry> <entry>box to 4-point polygon</entry> <entry><literal>polygon(box '((0,0),(1,1))')</literal></entry> </row> <row> - <entry><literal><function>polygon</function>(<type>circle</type>)</literal></entry> + <entry><literal><function>polygon(<type>circle</type>)</function></literal></entry> <entry><type>polygon</type></entry> <entry>circle to 12-point polygon</entry> <entry><literal>polygon(circle '((0,0),2.0)')</literal></entry> </row> <row> - <entry><literal><function>polygon</function>(<replaceable class="parameter">npts</replaceable>, <type>circle</type>)</literal></entry> + <entry><literal><function>polygon(<replaceable class="parameter">npts</replaceable>, <type>circle</type>)</function></literal></entry> <entry><type>polygon</type></entry> <entry>circle to <replaceable class="parameter">npts</replaceable>-point polygon</entry> <entry><literal>polygon(12, circle '((0,0),2.0)')</literal></entry> </row> <row> - <entry><literal><function>polygon</function>(<type>path</type>)</literal></entry> + <entry><literal><function>polygon(<type>path</type>)</function></literal></entry> <entry><type>polygon</type></entry> <entry>path to polygon</entry> <entry><literal>polygon(path '((0,0),(1,1),(2,0))')</literal></entry> @@ -7703,28 +8087,43 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple </thead> <tbody> <row> - <entry><literal><function>abbrev</function>(<type>inet</type>)</literal></entry> + <entry> + <indexterm> + <primary>abbrev</primary> + </indexterm> + <literal><function>abbrev(<type>inet</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry>abbreviated display format as text</entry> <entry><literal>abbrev(inet '10.1.0.0/16')</literal></entry> <entry><literal>10.1.0.0/16</literal></entry> </row> <row> - <entry><literal><function>abbrev</function>(<type>cidr</type>)</literal></entry> + <entry><literal><function>abbrev(<type>cidr</type>)</function></literal></entry> <entry><type>text</type></entry> <entry>abbreviated display format as text</entry> <entry><literal>abbrev(cidr '10.1.0.0/16')</literal></entry> <entry><literal>10.1/16</literal></entry> </row> <row> - <entry><literal><function>broadcast</function>(<type>inet</type>)</literal></entry> + <entry> + <indexterm> + <primary>broadcast</primary> + </indexterm> + <literal><function>broadcast(<type>inet</type>)</function></literal> + </entry> <entry><type>inet</type></entry> <entry>broadcast address for network</entry> <entry><literal>broadcast('192.168.1.5/24')</literal></entry> <entry><literal>192.168.1.255/24</literal></entry> </row> <row> - <entry><literal><function>family</function>(<type>inet</type>)</literal></entry> + <entry> + <indexterm> + <primary>family</primary> + </indexterm> + <literal><function>family(<type>inet</type>)</function></literal> + </entry> <entry><type>int</type></entry> <entry>extract family of address; <literal>4</literal> for IPv4, <literal>6</literal> for IPv6</entry> @@ -7732,56 +8131,91 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple <entry><literal>6</literal></entry> </row> <row> - <entry><literal><function>host</function>(<type>inet</type>)</literal></entry> + <entry> + <indexterm> + <primary>host</primary> + </indexterm> + <literal><function>host(<type>inet</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry>extract IP address as text</entry> <entry><literal>host('192.168.1.5/24')</literal></entry> <entry><literal>192.168.1.5</literal></entry> </row> <row> - <entry><literal><function>hostmask</function>(<type>inet</type>)</literal></entry> + <entry> + <indexterm> + <primary>hostmask</primary> + </indexterm> + <literal><function>hostmask(<type>inet</type>)</function></literal> + </entry> <entry><type>inet</type></entry> <entry>construct host mask for network</entry> <entry><literal>hostmask('192.168.23.20/30')</literal></entry> <entry><literal>0.0.0.3</literal></entry> </row> <row> - <entry><literal><function>masklen</function>(<type>inet</type>)</literal></entry> + <entry> + <indexterm> + <primary>masklen</primary> + </indexterm> + <literal><function>masklen(<type>inet</type>)</function></literal> + </entry> <entry><type>int</type></entry> <entry>extract netmask length</entry> <entry><literal>masklen('192.168.1.5/24')</literal></entry> <entry><literal>24</literal></entry> </row> <row> - <entry><literal><function>netmask</function>(<type>inet</type>)</literal></entry> + <entry> + <indexterm> + <primary>netmask</primary> + </indexterm> + <literal><function>netmask(<type>inet</type>)</function></literal> + </entry> <entry><type>inet</type></entry> <entry>construct netmask for network</entry> <entry><literal>netmask('192.168.1.5/24')</literal></entry> <entry><literal>255.255.255.0</literal></entry> </row> <row> - <entry><literal><function>network</function>(<type>inet</type>)</literal></entry> + <entry> + <indexterm> + <primary>network</primary> + </indexterm> + <literal><function>network(<type>inet</type>)</function></literal> + </entry> <entry><type>cidr</type></entry> <entry>extract network part of address</entry> <entry><literal>network('192.168.1.5/24')</literal></entry> <entry><literal>192.168.1.0/24</literal></entry> </row> <row> - <entry><literal><function>set_masklen</function>(<type>inet</type>, <type>int</type>)</literal></entry> + <entry> + <indexterm> + <primary>set_masklen</primary> + </indexterm> + <literal><function>set_masklen(<type>inet</type>, <type>int</type>)</function></literal> + </entry> <entry><type>inet</type></entry> <entry>set netmask length for <type>inet</type> value</entry> <entry><literal>set_masklen('192.168.1.5/24', 16)</literal></entry> <entry><literal>192.168.1.5/16</literal></entry> </row> <row> - <entry><literal><function>set_masklen</function>(<type>cidr</type>, <type>int</type>)</literal></entry> + <entry><literal><function>set_masklen(<type>cidr</type>, <type>int</type>)</function></literal></entry> <entry><type>cidr</type></entry> <entry>set netmask length for <type>cidr</type> value</entry> <entry><literal>set_masklen('192.168.1.0/24'::cidr, 16)</literal></entry> <entry><literal>192.168.0.0/16</literal></entry> </row> <row> - <entry><literal><function>text</function>(<type>inet</type>)</literal></entry> + <entry> + <indexterm> + <primary>text</primary> + </indexterm> + <literal><function>text(<type>inet</type>)</function></literal> + </entry> <entry><type>text</type></entry> <entry>extract IP address and netmask length as text</entry> <entry><literal>text(inet '192.168.1.5')</literal></entry> @@ -7810,7 +8244,7 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple <para> <xref linkend="macaddr-functions-table"> shows the functions available for use with the <type>macaddr</type> type. The function - <literal><function>trunc</function>(<type>macaddr</type>)</literal> returns a MAC + <literal><function>trunc(<type>macaddr</type>)</function></literal> returns a MAC address with the last 3 bytes set to zero. This can be used to associate the remaining prefix with a manufacturer. </para> @@ -7829,7 +8263,12 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple </thead> <tbody> <row> - <entry><literal><function>trunc</function>(<type>macaddr</type>)</literal></entry> + <entry> + <indexterm> + <primary>trunc</primary> + </indexterm> + <literal><function>trunc(<type>macaddr</type>)</function></literal> + </entry> <entry><type>macaddr</type></entry> <entry>set last 3 bytes to zero</entry> <entry><literal>trunc(macaddr '12:34:56:78:90:ab')</literal></entry> @@ -7964,117 +8403,191 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple </thead> <tbody> <row> - <entry><literal><function>to_tsvector</function>(<optional> <replaceable class="PARAMETER">config</> <type>regconfig</> , </optional> <replaceable class="PARAMETER">document</> <type>text</type>)</literal></entry> - <entry><type>tsvector</type></entry> - <entry>reduce document text to <type>tsvector</></entry> - <entry><literal>to_tsvector('english', 'The Fat Rats')</literal></entry> - <entry><literal>'fat':2 'rat':3</literal></entry> + <entry> + <indexterm> + <primary>get_current_ts_config</primary> + </indexterm> + <literal><function>get_current_ts_config()</function></literal> + </entry> + <entry><type>regconfig</type></entry> + <entry>get default text search configuration</entry> + <entry><literal>get_current_ts_config()</literal></entry> + <entry><literal>english</literal></entry> </row> <row> - <entry><literal><function>length</function>(<type>tsvector</>)</literal></entry> + <entry> + <indexterm> + <primary>length</primary> + </indexterm> + <literal><function>length(<type>tsvector</>)</function></literal> + </entry> <entry><type>integer</type></entry> <entry>number of lexemes in <type>tsvector</></entry> <entry><literal>length('fat:2,4 cat:3 rat:5A'::tsvector)</literal></entry> <entry><literal>3</literal></entry> </row> <row> - <entry><literal><function>setweight</function>(<type>tsvector</>, <type>"char"</>)</literal></entry> + <entry> + <indexterm> + <primary>numnode</primary> + </indexterm> + <literal><function>numnode(<type>tsquery</>)</function></literal> + </entry> + <entry><type>integer</type></entry> + <entry>number of lexemes plus operators in <type>tsquery</></entry> + <entry><literal> numnode('(fat & rat) | cat'::tsquery)</literal></entry> + <entry><literal>5</literal></entry> + </row> + <row> + <entry> + <indexterm> + <primary>plainto_tsquery</primary> + </indexterm> + <literal><function>plainto_tsquery(<optional> <replaceable class="PARAMETER">config</> <type>regconfig</> , </optional> <replaceable class="PARAMETER">query</> <type>text</type>)</function></literal> + </entry> + <entry><type>tsquery</type></entry> + <entry>produce <type>tsquery</> ignoring punctuation</entry> + <entry><literal>plainto_tsquery('english', 'The Fat Rats')</literal></entry> + <entry><literal>'fat' & 'rat'</literal></entry> + </row> + <row> + <entry> + <indexterm> + <primary>querytree</primary> + </indexterm> + <literal><function>querytree(<replaceable class="PARAMETER">query</replaceable> <type>tsquery</>)</function></literal> + </entry> + <entry><type>text</type></entry> + <entry>get indexable part of a <type>tsquery</></entry> + <entry><literal>querytree('foo & ! bar'::tsquery)</literal></entry> + <entry><literal>'foo'</literal></entry> + </row> + <row> + <entry> + <indexterm> + <primary>setweight</primary> + </indexterm> + <literal><function>setweight(<type>tsvector</>, <type>"char"</>)</function></literal> + </entry> <entry><type>tsvector</type></entry> <entry>assign weight to each element of <type>tsvector</></entry> <entry><literal>setweight('fat:2,4 cat:3 rat:5B'::tsvector, 'A')</literal></entry> <entry><literal>'cat':3A 'fat':2A,4A 'rat':5A</literal></entry> </row> <row> - <entry><literal><function>strip</function>(<type>tsvector</>)</literal></entry> + <entry> + <indexterm> + <primary>strip</primary> + </indexterm> + <literal><function>strip(<type>tsvector</>)</function></literal> + </entry> <entry><type>tsvector</type></entry> <entry>remove positions and weights from <type>tsvector</></entry> <entry><literal>strip('fat:2,4 cat:3 rat:5A'::tsvector)</literal></entry> <entry><literal>'cat' 'fat' 'rat'</literal></entry> </row> <row> - <entry><literal><function>to_tsquery</function>(<optional> <replaceable class="PARAMETER">config</> <type>regconfig</> , </optional> <replaceable class="PARAMETER">query</> <type>text</type>)</literal></entry> + <entry> + <indexterm> + <primary>to_tsquery</primary> + </indexterm> + <literal><function>to_tsquery(<optional> <replaceable class="PARAMETER">config</> <type>regconfig</> , </optional> <replaceable class="PARAMETER">query</> <type>text</type>)</function></literal> + </entry> <entry><type>tsquery</type></entry> <entry>normalize words and convert to <type>tsquery</></entry> <entry><literal>to_tsquery('english', 'The & Fat & Rats')</literal></entry> <entry><literal>'fat' & 'rat'</literal></entry> </row> <row> - <entry><literal><function>plainto_tsquery</function>(<optional> <replaceable class="PARAMETER">config</> <type>regconfig</> , </optional> <replaceable class="PARAMETER">query</> <type>text</type>)</literal></entry> - <entry><type>tsquery</type></entry> - <entry>produce <type>tsquery</> ignoring punctuation</entry> - <entry><literal>plainto_tsquery('english', 'The Fat Rats')</literal></entry> - <entry><literal>'fat' & 'rat'</literal></entry> - </row> - <row> - <entry><literal><function>numnode</function>(<type>tsquery</>)</literal></entry> - <entry><type>integer</type></entry> - <entry>number of lexemes plus operators in <type>tsquery</></entry> - <entry><literal> numnode('(fat & rat) | cat'::tsquery)</literal></entry> - <entry><literal>5</literal></entry> + <entry> + <indexterm> + <primary>to_tsvector</primary> + </indexterm> + <literal><function>to_tsvector(<optional> <replaceable class="PARAMETER">config</> <type>regconfig</> , </optional> <replaceable class="PARAMETER">document</> <type>text</type>)</function></literal> + </entry> + <entry><type>tsvector</type></entry> + <entry>reduce document text to <type>tsvector</></entry> + <entry><literal>to_tsvector('english', 'The Fat Rats')</literal></entry> + <entry><literal>'fat':2 'rat':3</literal></entry> </row> <row> - <entry><literal><function>querytree</function>(<replaceable class="PARAMETER">query</replaceable> <type>tsquery</>)</literal></entry> + <entry> + <indexterm> + <primary>ts_headline</primary> + </indexterm> + <literal><function>ts_headline(<optional> <replaceable class="PARAMETER">config</replaceable> <type>regconfig</>, </optional> <replaceable class="PARAMETER">document</replaceable> <type>text</>, <replaceable class="PARAMETER">query</replaceable> <type>tsquery</> <optional>, <replaceable class="PARAMETER">options</replaceable> <type>text</> </optional>)</function></literal> + </entry> <entry><type>text</type></entry> - <entry>get indexable part of a <type>tsquery</></entry> - <entry><literal>querytree('foo & ! bar'::tsquery)</literal></entry> - <entry><literal>'foo'</literal></entry> + <entry>display a query match</entry> + <entry><literal>ts_headline('x y z', 'z'::tsquery)</literal></entry> + <entry><literal>x y <b>z</b></literal></entry> </row> <row> - <entry><literal><function>ts_rank</function>(<optional> <replaceable class="PARAMETER">weights</replaceable> <type>float4[]</>, </optional> <replaceable class="PARAMETER">vector</replaceable> <type>tsvector</>, <replaceable class="PARAMETER">query</replaceable> <type>tsquery</> <optional>, <replaceable class="PARAMETER">normalization</replaceable> <type>integer</> </optional>)</literal></entry> + <entry> + <indexterm> + <primary>ts_rank</primary> + </indexterm> + <literal><function>ts_rank(<optional> <replaceable class="PARAMETER">weights</replaceable> <type>float4[]</>, </optional> <replaceable class="PARAMETER">vector</replaceable> <type>tsvector</>, <replaceable class="PARAMETER">query</replaceable> <type>tsquery</> <optional>, <replaceable class="PARAMETER">normalization</replaceable> <type>integer</> </optional>)</function></literal> + </entry> <entry><type>float4</type></entry> <entry>rank document for query</entry> <entry><literal>ts_rank(textsearch, query)</literal></entry> <entry><literal>0.818</literal></entry> </row> <row> - <entry><literal><function>ts_rank_cd</function>(<optional> <replaceable class="PARAMETER">weights</replaceable> <type>float4[]</>, </optional> <replaceable class="PARAMETER">vector</replaceable> <type>tsvector</>, <replaceable class="PARAMETER">query</replaceable> <type>tsquery</> <optional>, <replaceable class="PARAMETER">normalization</replaceable> <type>integer</> </optional>)</literal></entry> + <entry> + <indexterm> + <primary>ts_rank_cd</primary> + </indexterm> + <literal><function>ts_rank_cd(<optional> <replaceable class="PARAMETER">weights</replaceable> <type>float4[]</>, </optional> <replaceable class="PARAMETER">vector</replaceable> <type>tsvector</>, <replaceable class="PARAMETER">query</replaceable> <type>tsquery</> <optional>, <replaceable class="PARAMETER">normalization</replaceable> <type>integer</> </optional>)</function></literal> + </entry> <entry><type>float4</type></entry> <entry>rank document for query using cover density</entry> <entry><literal>ts_rank_cd('{0.1, 0.2, 0.4, 1.0}', textsearch, query)</literal></entry> <entry><literal>2.01317</literal></entry> </row> <row> - <entry><literal><function>ts_headline</function>(<optional> <replaceable class="PARAMETER">config</replaceable> <type>regconfig</>, </optional> <replaceable class="PARAMETER">document</replaceable> <type>text</>, <replaceable class="PARAMETER">query</replaceable> <type>tsquery</> <optional>, <replaceable class="PARAMETER">options</replaceable> <type>text</> </optional>)</literal></entry> - <entry><type>text</type></entry> - <entry>display a query match</entry> - <entry><literal>ts_headline('x y z', 'z'::tsquery)</literal></entry> - <entry><literal>x y <b>z</b></literal></entry> - </row> - <row> - <entry><literal><function>ts_rewrite</function>(<replaceable class="PARAMETER">query</replaceable> <type>tsquery</>, <replaceable class="PARAMETER">target</replaceable> <type>tsquery</>, <replaceable class="PARAMETER">substitute</replaceable> <type>tsquery</>)</literal></entry> + <entry> + <indexterm> + <primary>ts_rewrite</primary> + </indexterm> + <literal><function>ts_rewrite(<replaceable class="PARAMETER">query</replaceable> <type>tsquery</>, <replaceable class="PARAMETER">target</replaceable> <type>tsquery</>, <replaceable class="PARAMETER">substitute</replaceable> <type>tsquery</>)</function></literal> + </entry> <entry><type>tsquery</type></entry> <entry>replace target with substitute within query</entry> <entry><literal>ts_rewrite('a & b'::tsquery, 'a'::tsquery, 'foo|bar'::tsquery)</literal></entry> <entry><literal>'b' & ( 'foo' | 'bar' )</literal></entry> </row> <row> - <entry><literal><function>ts_rewrite</function>(<replaceable class="PARAMETER">query</replaceable> <type>tsquery</>, <replaceable class="PARAMETER">select</replaceable> <type>text</>)</literal></entry> + <entry><literal><function>ts_rewrite(<replaceable class="PARAMETER">query</replaceable> <type>tsquery</>, <replaceable class="PARAMETER">select</replaceable> <type>text</>)</function></literal></entry> <entry><type>tsquery</type></entry> <entry>replace using targets and substitutes from a <command>SELECT</> command</entry> <entry><literal>SELECT ts_rewrite('a & b'::tsquery, 'SELECT t,s FROM aliases')</literal></entry> <entry><literal>'b' & ( 'foo' | 'bar' )</literal></entry> </row> <row> - <entry><literal><function>get_current_ts_config</function>()</literal></entry> - <entry><type>regconfig</type></entry> - <entry>get default text search configuration</entry> - <entry><literal>get_current_ts_config()</literal></entry> - <entry><literal>english</literal></entry> - </row> - <row> - <entry><literal><function>tsvector_update_trigger</function>()</literal></entry> + <entry> + <indexterm> + <primary>tsvector_update_trigger</primary> + </indexterm> + <literal><function>tsvector_update_trigger()</function></literal> + </entry> <entry><type>trigger</type></entry> <entry>trigger function for automatic <type>tsvector</> column update</entry> <entry><literal>CREATE TRIGGER ... tsvector_update_trigger(tsvcol, 'pg_catalog.swedish', title, body)</literal></entry> <entry><literal></literal></entry> </row> <row> - <entry><literal><function>tsvector_update_trigger_column</function>()</literal></entry> + <entry> + <indexterm> + <primary>tsvector_update_trigger_column</primary> + </indexterm> + <literal><function>tsvector_update_trigger_column()</function></literal> + </entry> <entry><type>trigger</type></entry> <entry>trigger function for automatic <type>tsvector</> column update</entry> <entry><literal>CREATE TRIGGER ... tsvector_update_trigger_column(tsvcol, configcol, title, body)</literal></entry> <entry><literal></literal></entry> - <entry><literal></literal></entry> </row> </tbody> </tgroup> @@ -8111,49 +8624,74 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple </thead> <tbody> <row> - <entry><literal><function>ts_debug</function>(<optional> <replaceable class="PARAMETER">config</replaceable> <type>regconfig</>, </optional> <replaceable class="PARAMETER">document</replaceable> <type>text</>, OUT <replaceable class="PARAMETER">alias</> <type>text</>, OUT <replaceable class="PARAMETER">description</> <type>text</>, OUT <replaceable class="PARAMETER">token</> <type>text</>, OUT <replaceable class="PARAMETER">dictionaries</> <type>regdictionary[]</>, OUT <replaceable class="PARAMETER">dictionary</> <type>regdictionary</>, OUT <replaceable class="PARAMETER">lexemes</> <type>text[]</>)</literal></entry> + <entry> + <indexterm> + <primary>ts_debug</primary> + </indexterm> + <literal><function>ts_debug(<optional> <replaceable class="PARAMETER">config</replaceable> <type>regconfig</>, </optional> <replaceable class="PARAMETER">document</replaceable> <type>text</>, OUT <replaceable class="PARAMETER">alias</> <type>text</>, OUT <replaceable class="PARAMETER">description</> <type>text</>, OUT <replaceable class="PARAMETER">token</> <type>text</>, OUT <replaceable class="PARAMETER">dictionaries</> <type>regdictionary[]</>, OUT <replaceable class="PARAMETER">dictionary</> <type>regdictionary</>, OUT <replaceable class="PARAMETER">lexemes</> <type>text[]</>)</function></literal> + </entry> <entry><type>setof record</type></entry> <entry>test a configuration</entry> <entry><literal>ts_debug('english', 'The Brightest supernovaes')</literal></entry> <entry><literal>(asciiword,"Word, all ASCII",The,{english_stem},english_stem,{}) ...</literal></entry> </row> <row> - <entry><literal><function>ts_lexize</function>(<replaceable class="PARAMETER">dict</replaceable> <type>regdictionary</>, <replaceable class="PARAMETER">token</replaceable> <type>text</>)</literal></entry> + <entry> + <indexterm> + <primary>ts_lexize</primary> + </indexterm> + <literal><function>ts_lexize(<replaceable class="PARAMETER">dict</replaceable> <type>regdictionary</>, <replaceable class="PARAMETER">token</replaceable> <type>text</>)</function></literal> + </entry> <entry><type>text[]</type></entry> <entry>test a dictionary</entry> <entry><literal>ts_lexize('english_stem', 'stars')</literal></entry> <entry><literal>{star}</literal></entry> </row> <row> - <entry><literal><function>ts_parse</function>(<replaceable class="PARAMETER">parser_name</replaceable> <type>text</>, <replaceable class="PARAMETER">document</replaceable> <type>text</>, OUT <replaceable class="PARAMETER">tokid</> <type>integer</>, OUT <replaceable class="PARAMETER">token</> <type>text</>)</literal></entry> + <entry> + <indexterm> + <primary>ts_parse</primary> + </indexterm> + <literal><function>ts_parse(<replaceable class="PARAMETER">parser_name</replaceable> <type>text</>, <replaceable class="PARAMETER">document</replaceable> <type>text</>, OUT <replaceable class="PARAMETER">tokid</> <type>integer</>, OUT <replaceable class="PARAMETER">token</> <type>text</>)</function></literal> + </entry> <entry><type>setof record</type></entry> <entry>test a parser</entry> <entry><literal>ts_parse('default', 'foo - bar')</literal></entry> <entry><literal>(1,foo) ...</literal></entry> </row> <row> - <entry><literal><function>ts_parse</function>(<replaceable class="PARAMETER">parser_oid</replaceable> <type>oid</>, <replaceable class="PARAMETER">document</replaceable> <type>text</>, OUT <replaceable class="PARAMETER">tokid</> <type>integer</>, OUT <replaceable class="PARAMETER">token</> <type>text</>)</literal></entry> + <entry><literal><function>ts_parse(<replaceable class="PARAMETER">parser_oid</replaceable> <type>oid</>, <replaceable class="PARAMETER">document</replaceable> <type>text</>, OUT <replaceable class="PARAMETER">tokid</> <type>integer</>, OUT <replaceable class="PARAMETER">token</> <type>text</>)</function></literal></entry> <entry><type>setof record</type></entry> <entry>test a parser</entry> <entry><literal>ts_parse(3722, 'foo - bar')</literal></entry> <entry><literal>(1,foo) ...</literal></entry> </row> <row> - <entry><literal><function>ts_token_type</function>(<replaceable class="PARAMETER">parser_name</> <type>text</>, OUT <replaceable class="PARAMETER">tokid</> <type>integer</>, OUT <replaceable class="PARAMETER">alias</> <type>text</>, OUT <replaceable class="PARAMETER">description</> <type>text</>)</literal></entry> + <entry> + <indexterm> + <primary>ts_token_type</primary> + </indexterm> + <literal><function>ts_token_type(<replaceable class="PARAMETER">parser_name</> <type>text</>, OUT <replaceable class="PARAMETER">tokid</> <type>integer</>, OUT <replaceable class="PARAMETER">alias</> <type>text</>, OUT <replaceable class="PARAMETER">description</> <type>text</>)</function></literal> + </entry> <entry><type>setof record</type></entry> <entry>get token types defined by parser</entry> <entry><literal>ts_token_type('default')</literal></entry> <entry><literal>(1,asciiword,"Word, all ASCII") ...</literal></entry> </row> <row> - <entry><literal><function>ts_token_type</function>(<replaceable class="PARAMETER">parser_oid</> <type>oid</>, OUT <replaceable class="PARAMETER">tokid</> <type>integer</>, OUT <replaceable class="PARAMETER">alias</> <type>text</>, OUT <replaceable class="PARAMETER">description</> <type>text</>)</literal></entry> + <entry><literal><function>ts_token_type(<replaceable class="PARAMETER">parser_oid</> <type>oid</>, OUT <replaceable class="PARAMETER">tokid</> <type>integer</>, OUT <replaceable class="PARAMETER">alias</> <type>text</>, OUT <replaceable class="PARAMETER">description</> <type>text</>)</function></literal></entry> <entry><type>setof record</type></entry> <entry>get token types defined by parser</entry> <entry><literal>ts_token_type(3722)</literal></entry> <entry><literal>(1,asciiword,"Word, all ASCII") ...</literal></entry> </row> <row> - <entry><literal><function>ts_stat</function>(<replaceable class="PARAMETER">sqlquery</replaceable> <type>text</>, <optional> <replaceable class="PARAMETER">weights</replaceable> <type>text</>, </optional> OUT <replaceable class="PARAMETER">word</replaceable> <type>text</>, OUT <replaceable class="PARAMETER">ndoc</replaceable> <type>integer</>, OUT <replaceable class="PARAMETER">nentry</replaceable> <type>integer</>)</literal></entry> + <entry> + <indexterm> + <primary>ts_stat</primary> + </indexterm> + <literal><function>ts_stat(<replaceable class="PARAMETER">sqlquery</replaceable> <type>text</>, <optional> <replaceable class="PARAMETER">weights</replaceable> <type>text</>, </optional> OUT <replaceable class="PARAMETER">word</replaceable> <type>text</>, OUT <replaceable class="PARAMETER">ndoc</replaceable> <type>integer</>, OUT <replaceable class="PARAMETER">nentry</replaceable> <type>integer</>)</function></literal> + </entry> <entry><type>setof record</type></entry> <entry>get statistics of a <type>tsvector</> column</entry> <entry><literal>ts_stat('SELECT vector from apod')</literal></entry> @@ -8175,12 +8713,12 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple linkend="datatype-xml"> for information about the <type>xml</type> type. The function-like expressions <function>xmlparse</function> and <function>xmlserialize</function> for converting to and from - type <type>xml</type> are not repeated here. Use of many of these + type <type>xml</type> are not repeated here. Use of most of these functions requires the installation to have been built with <command>configure --with-libxml</>. </para> - <sect2> + <sect2 id="functions-producing-xml"> <title>Producing XML Content</title> <para> @@ -8228,10 +8766,10 @@ SELECT xmlcomment('hello'); <primary>xmlconcat</primary> </indexterm> - <synopsis> - <function>xmlconcat</function>(<replaceable>xml</replaceable><optional>, ...</optional>) - </synopsis> - +<synopsis> +<function>xmlconcat</function>(<replaceable>xml</replaceable><optional>, ...</optional>) +</synopsis> + <para> The function <function>xmlconcat</function> concatenates a list of individual XML values to create a single value containing an @@ -8277,18 +8815,18 @@ SELECT xmlconcat('<?xml version="1.1"?><foo/>', '<?xml version="1.1" standalone= ]]></screen> </para> </sect3> - + <sect3> <title><literal>xmlelement</literal></title> - + <indexterm> <primary>xmlelement</primary> </indexterm> - + <synopsis> - <function>xmlelement</function>(name <replaceable>name</replaceable> <optional>, xmlattributes(<replaceable>value</replaceable> <optional>AS <replaceable>attname</replaceable></optional> <optional>, ... </optional>)</optional> <optional><replaceable>, content, ...</replaceable></optional>) - </synopsis> - +<function>xmlelement</function>(name <replaceable>name</replaceable> <optional>, xmlattributes(<replaceable>value</replaceable> <optional>AS <replaceable>attname</replaceable></optional> <optional>, ... </optional>)</optional> <optional><replaceable>, content, ...</replaceable></optional>) +</synopsis> + <para> The <function>xmlelement</function> expression produces an XML element with the given name, attributes, and content. @@ -8375,18 +8913,18 @@ SELECT xmlelement(name foo, xmlattributes('xyz' as bar), at which point a more precise description will appear. </para> </sect3> - + <sect3> <title><literal>xmlforest</literal></title> - + <indexterm> <primary>xmlforest</primary> </indexterm> - - <synopsis> - <function>xmlforest</function>(<replaceable>content</replaceable> <optional>AS <replaceable>name</replaceable></optional> <optional>, ...</optional>) - </synopsis> - + +<synopsis> +<function>xmlforest</function>(<replaceable>content</replaceable> <optional>AS <replaceable>name</replaceable></optional> <optional>, ...</optional>) +</synopsis> + <para> The <function>xmlforest</function> expression produces an XML forest (sequence) of elements using the given names and content. @@ -8432,18 +8970,18 @@ WHERE table_schema = 'pg_catalog'; <function>xmlelement</function>. </para> </sect3> - + <sect3> <title><literal>xmlpi</literal></title> - + <indexterm> <primary>xmlpi</primary> </indexterm> - - <synopsis> - <function>xmlpi</function>(name <replaceable>target</replaceable> <optional>, <replaceable>content</replaceable></optional>) - </synopsis> - + +<synopsis> +<function>xmlpi</function>(name <replaceable>target</replaceable> <optional>, <replaceable>content</replaceable></optional>) +</synopsis> + <para> The <function>xmlpi</function> expression creates an XML processing instruction. The content, if present, must not @@ -8461,18 +8999,18 @@ SELECT xmlpi(name php, 'echo "hello world";'); ]]></screen> </para> </sect3> - + <sect3> <title><literal>xmlroot</literal></title> - + <indexterm> <primary>xmlroot</primary> </indexterm> - - <synopsis> - <function>xmlroot</function>(<replaceable>xml</replaceable>, version <replaceable>text</replaceable> | no value <optional>, standalone yes|no|no value</optional>) - </synopsis> - + +<synopsis> +<function>xmlroot</function>(<replaceable>xml</replaceable>, version <replaceable>text</replaceable> | no value <optional>, standalone yes|no|no value</optional>) +</synopsis> + <para> The <function>xmlroot</function> expression alters the properties of the root node of an XML value. If a version is specified, @@ -8483,7 +9021,7 @@ SELECT xmlpi(name php, 'echo "hello world";'); <para> <screen><![CDATA[ -SELECT xmlroot(xmlparse(document '<?xml version="1.1"?><content>abc</content>'), +SELECT xmlroot(xmlparse(document '<?xml version="1.1"?><content>abc</content>'), version '1.0', standalone yes); xmlroot @@ -8554,10 +9092,19 @@ SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab; ]]></screen> </para> </sect3> + </sect2> - <sect3> + <sect2 id="functions-xml-predicates"> <title>XML Predicates</title> + <para> + The expressions described in this section check properties + of <type>xml</type> values. + </para> + + <sect3> + <title><literal>IS DOCUMENT</literal></title> + <indexterm> <primary>IS DOCUMENT</primary> </indexterm> @@ -8574,6 +9121,126 @@ SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab; between documents and content fragments. </para> </sect3> + + <sect3 id="xml-exists"> + <title><literal>XMLEXISTS</literal></title> + + <indexterm> + <primary>XMLEXISTS</primary> + </indexterm> + +<synopsis> +<function>XMLEXISTS</function>(<replaceable>text</replaceable> PASSING <optional>BY REF</optional> <replaceable>xml</replaceable> <optional>BY REF</optional>) +</synopsis> + + <para> + The function <function>xmlexists</function> returns true if the + XPath expression in the first argument returns any nodes, and + false otherwise. (If either argument is null, the result is + null.) + </para> + + <para> + Example: + <screen><![CDATA[ +SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Toronto</town><town>Ottawa</town></towns>'); + + xmlexists +------------ + t +(1 row) +]]></screen> + </para> + + <para> + The <literal>BY REF</literal> clauses have no effect in + PostgreSQL, but are allowed for SQL conformance and compatibility + with other implementations. Per SQL standard, the + first <literal>BY REF</literal> is required, the second is + optional. Also note that the SQL standard specifies + the <function>xmlexists</function> construct to take an XQuery + expression as first argument, but PostgreSQL currently only + supports XPath, which is a subset of XQuery. + </para> + </sect3> + + <sect3 id="xml-is-well-formed"> + <title><literal>xml_is_well_formed</literal></title> + + <indexterm> + <primary>xml_is_well_formed</primary> + </indexterm> + + <indexterm> + <primary>xml_is_well_formed_document</primary> + </indexterm> + + <indexterm> + <primary>xml_is_well_formed_content</primary> + </indexterm> + +<synopsis> +<function>xml_is_well_formed</function>(<replaceable>text</replaceable>) +<function>xml_is_well_formed_document</function>(<replaceable>text</replaceable>) +<function>xml_is_well_formed_content</function>(<replaceable>text</replaceable>) +</synopsis> + + <para> + These functions check whether a <type>text</> string is well-formed XML, + returning a Boolean result. + <function>xml_is_well_formed_document</function> checks for a well-formed + document, while <function>xml_is_well_formed_content</function> checks + for well-formed content. <function>xml_is_well_formed</function> does + the former if the <xref linkend="guc-xmloption"> configuration + parameter is set to <literal>DOCUMENT</>, or the latter if it is set to + <literal>CONTENT</>. This means that + <function>xml_is_well_formed</function> is useful for seeing whether + a simple cast to type <type>xml</> will succeed, whereas the other two + functions are useful for seeing whether the corresponding variants of + <function>XMLPARSE</> will succeed. + </para> + + <para> + Examples: + +<screen><![CDATA[ +SET xmloption TO DOCUMENT; +SELECT xml_is_well_formed('<>'); + xml_is_well_formed +-------------------- + f +(1 row) + +SELECT xml_is_well_formed('<abc/>'); + xml_is_well_formed +-------------------- + t +(1 row) + +SET xmloption TO CONTENT; +SELECT xml_is_well_formed('abc'); + xml_is_well_formed +-------------------- + t +(1 row) + +SELECT xml_is_well_formed_document('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</pg:foo>'); + xml_is_well_formed_document +----------------------------- + t +(1 row) + +SELECT xml_is_well_formed_document('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</my:foo>'); + xml_is_well_formed_document +----------------------------- + f +(1 row) +]]></screen> + + The last example shows that the checks include whether + namespaces are correctly matched. + </para> + </sect3> </sect2> <sect2 id="functions-xml-processing"> @@ -8585,17 +9252,19 @@ SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab; <para> To process values of data type <type>xml</type>, PostgreSQL offers - the function <function>xpath</function>, which evaluates XPath 1.0 + the functions <function>xpath</function> and + <function>xpath_exists</function>, which evaluate XPath 1.0 expressions. </para> <synopsis> -<function>xpath</function>(<replaceable>xpath</replaceable>, <replaceable>xml</replaceable><optional>, <replaceable>nsarray</replaceable></optional>) +<function>xpath</function>(<replaceable>xpath</replaceable>, <replaceable>xml</replaceable> <optional>, <replaceable>nsarray</replaceable></optional>) </synopsis> <para> The function <function>xpath</function> evaluates the XPath - expression <replaceable>xpath</replaceable> against the XML value + expression <replaceable>xpath</replaceable> (a <type>text</> value) + against the XML value <replaceable>xml</replaceable>. It returns an array of XML values corresponding to the node set produced by the XPath expression. </para> @@ -8606,13 +9275,13 @@ SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab; </para> <para> - The third argument of the function is an array of namespace - mappings. This array should be a two-dimensional array with the - length of the second axis being equal to 2 (i.e., it should be an + The optional third argument of the function is an array of namespace + mappings. This array should be a two-dimensional <type>text</> array with + the length of the second axis being equal to 2 (i.e., it should be an array of arrays, each of which consists of exactly 2 elements). The first element of each array entry is the namespace name (alias), the second the namespace URI. It is not required that aliases provided in - this array are the same that those being used in the XML document itself (in + this array be the same as those being used in the XML document itself (in other words, both in the XML document and in the <function>xpath</function> function context, aliases are <emphasis>local</>). </para> @@ -8620,7 +9289,7 @@ SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab; <para> Example: <screen><![CDATA[ -SELECT xpath('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>', +SELECT xpath('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>', ARRAY[ARRAY['my', 'http://example.com']]); xpath @@ -8631,7 +9300,7 @@ SELECT xpath('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>', </para> <para> - How to deal with default (anonymous) namespaces: + To deal with default (anonymous) namespaces, do something like this: <screen><![CDATA[ SELECT xpath('//mydefns:b/text()', '<a xmlns="http://example.com"><b>test</b></a>', ARRAY[ARRAY['mydefns', 'http://example.com']]); @@ -8642,12 +9311,42 @@ SELECT xpath('//mydefns:b/text()', '<a xmlns="http://example.com"><b>test</b></a (1 row) ]]></screen> </para> + + <indexterm> + <primary>xpath_exists</primary> + </indexterm> + +<synopsis> +<function>xpath_exists</function>(<replaceable>xpath</replaceable>, <replaceable>xml</replaceable> <optional>, <replaceable>nsarray</replaceable></optional>) +</synopsis> + + <para> + The function <function>xpath_exists</function> is a specialized form + of the <function>xpath</function> function. Instead of returning the + individual XML values that satisfy the XPath, this function returns a + Boolean indicating whether the query was satisfied or not. This + function is equivalent to the standard <literal>XMLEXISTS</> predicate, + except that it also offers support for a namespace mapping argument. + </para> + + <para> + Example: +<screen><![CDATA[ +SELECT xpath_exists('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>', + ARRAY[ARRAY['my', 'http://example.com']]); + + xpath_exists +-------------- + t +(1 row) +]]></screen> + </para> </sect2> <sect2 id="functions-xml-mapping"> <title>Mapping Tables to XML</title> - <indexterm zone="functions-xml-mapping"> + <indexterm zone="functions-xml-mapping"> <primary>XML export</primary> </indexterm> @@ -8657,7 +9356,7 @@ SELECT xpath('//mydefns:b/text()', '<a xmlns="http://example.com"><b>test</b></a <synopsis> table_to_xml(tbl regclass, nulls boolean, tableforest boolean, targetns text) query_to_xml(query text, nulls boolean, tableforest boolean, targetns text) -cursor_to_xml(cursor refcursor, count int, nulls boolean, +cursor_to_xml(cursor refcursor, count int, nulls boolean, tableforest boolean, targetns text) </synopsis> The return type of each function is <type>xml</type>. @@ -8844,7 +9543,7 @@ table2-mapping </para> <figure id="xslt-xml-html"> - <title>XSLT stylesheet for converting SQL/XML output to HTML</title> + <title>XSLT Stylesheet for Converting SQL/XML Output to HTML</title> <programlisting><![CDATA[ <?xml version="1.0"?> <xsl:stylesheet version="1.0" @@ -8937,29 +9636,29 @@ table2-mapping <tbody> <row> - <entry><literal><function>currval</function>(<type>regclass</type>)</literal></entry> + <entry><literal><function>currval(<type>regclass</type>)</function></literal></entry> <entry><type>bigint</type></entry> <entry>Return value most recently obtained with <function>nextval</function> for specified sequence</entry> </row> <row> - <entry><literal><function>lastval</function>()</literal></entry> + <entry><literal><function>lastval()</function></literal></entry> <entry><type>bigint</type></entry> <entry>Return value most recently obtained with <function>nextval</function> for any sequence</entry> </row> <row> - <entry><literal><function>nextval</function>(<type>regclass</type>)</literal></entry> + <entry><literal><function>nextval(<type>regclass</type>)</function></literal></entry> <entry><type>bigint</type></entry> <entry>Advance sequence and return new value</entry> </row> <row> - <entry><literal><function>setval</function>(<type>regclass</type>, <type>bigint</type>)</literal></entry> + <entry><literal><function>setval(<type>regclass</type>, <type>bigint</type>)</function></literal></entry> <entry><type>bigint</type></entry> <entry>Set sequence's current value</entry> </row> <row> - <entry><literal><function>setval</function>(<type>regclass</type>, <type>bigint</type>, <type>boolean</type>)</literal></entry> + <entry><literal><function>setval(<type>regclass</type>, <type>bigint</type>, <type>boolean</type>)</function></literal></entry> <entry><type>bigint</type></entry> <entry>Set sequence's current value and <literal>is_called</literal> flag</entry> </row> @@ -8997,7 +9696,7 @@ nextval('foo') <lineannotation>searches search path for <literal>fo Before <productname>PostgreSQL</productname> 8.1, the arguments of the sequence functions were of type <type>text</>, not <type>regclass</>, and the above-described conversion from a text string to an OID value would - happen at run time during each call. For backwards compatibility, this + happen at run time during each call. For backward compatibility, this facility still exists, but internally it is now handled as an implicit coercion from <type>text</> to <type>regclass</> before the function is invoked. @@ -9156,7 +9855,7 @@ SELECT setval('foo', 42, false); <lineannotation>Next <function>nextval</> wi </para> </tip> - <sect2> + <sect2 id="functions-case"> <title><literal>CASE</></title> <para> @@ -9268,7 +9967,7 @@ SELECT ... WHERE CASE WHEN x <> 0 THEN y/x > 1.5 ELSE false END; </para> </sect2> - <sect2> + <sect2 id="functions-coalesce-nvl-ifnull"> <title><literal>COALESCE</></title> <indexterm> @@ -9290,7 +9989,7 @@ SELECT ... WHERE CASE WHEN x <> 0 THEN y/x > 1.5 ELSE false END; <para> The <function>COALESCE</function> function returns the first of its arguments that is not null. Null is returned only if all arguments - are null. It is often used to substitute a default value for + are null. It is often used to substitute a default value for null values when data is retrieved for display, for example: <programlisting> SELECT COALESCE(description, short_description, '(none)') ... @@ -9307,7 +10006,7 @@ SELECT COALESCE(description, short_description, '(none)') ... </para> </sect2> - <sect2> + <sect2 id="functions-nullif"> <title><literal>NULLIF</></title> <indexterm> @@ -9336,7 +10035,7 @@ SELECT NULLIF(value, '(none)') ... </sect2> - <sect2> + <sect2 id="functions-greatest-least"> <title><literal>GREATEST</literal> and <literal>LEAST</literal></title> <indexterm> @@ -9488,7 +10187,7 @@ SELECT NULLIF(value, '(none)') ... <para> Array comparisons compare the array contents element-by-element, - using the default B-Tree comparison function for the element data type. + using the default B-tree comparison function for the element data type. In multidimensional arrays the elements are visited in row-major order (last subscript varies most rapidly). If the contents of two arrays are equal but the dimensionality is @@ -9653,13 +10352,14 @@ SELECT NULLIF(value, '(none)') ... <row> <entry> <literal> - <function>array_to_string</function>(<type>anyarray</type>, <type>text</type>) + <function>array_to_string</function>(<type>anyarray</type>, <type>text</type> <optional>, <type>text</type></optional>) </literal> </entry> <entry><type>text</type></entry> - <entry>concatenates array elements using supplied delimiter</entry> - <entry><literal>array_to_string(ARRAY[1, 2, 3], '~^~')</literal></entry> - <entry><literal>1~^~2~^~3</literal></entry> + <entry>concatenates array elements using supplied delimiter and + optional null string</entry> + <entry><literal>array_to_string(ARRAY[1, 2, 3, NULL, 5], ',', '*')</literal></entry> + <entry><literal>1,2,3,*,5</literal></entry> </row> <row> <entry> @@ -9669,19 +10369,20 @@ SELECT NULLIF(value, '(none)') ... </entry> <entry><type>int</type></entry> <entry>returns upper bound of the requested array dimension</entry> - <entry><literal>array_upper(ARRAY[1,2,3,4], 1)</literal></entry> + <entry><literal>array_upper(ARRAY[1,8,3,7], 1)</literal></entry> <entry><literal>4</literal></entry> </row> <row> <entry> <literal> - <function>string_to_array</function>(<type>text</type>, <type>text</type>) + <function>string_to_array</function>(<type>text</type>, <type>text</type> <optional>, <type>text</type></optional>) </literal> </entry> <entry><type>text[]</type></entry> - <entry>splits string into array elements using supplied delimiter</entry> - <entry><literal>string_to_array('xx~^~yy~^~zz', '~^~')</literal></entry> - <entry><literal>{xx,yy,zz}</literal></entry> + <entry>splits string into array elements using supplied delimiter and + optional null string</entry> + <entry><literal>string_to_array('xx~^~yy~^~zz', '~^~', 'yy')</literal></entry> + <entry><literal>{xx,NULL,zz}</literal></entry> </row> <row> <entry> @@ -9692,13 +10393,42 @@ SELECT NULLIF(value, '(none)') ... <entry><type>setof anyelement</type></entry> <entry>expand an array to a set of rows</entry> <entry><literal>unnest(ARRAY[1,2])</literal></entry> - <entry><literal>1</literal><para><literal>2</literal></para> (2 rows)</entry> + <entry><literallayout class="monospaced">1 +2</literallayout>(2 rows)</entry> </row> </tbody> </tgroup> </table> <para> + In <function>string_to_array</function>, if the delimiter parameter is + NULL, each character in the input string will become a separate element in + the resulting array. If the delimiter is an empty string, then the entire + input string is returned as a one-element array. Otherwise the input + string is split at each occurrence of the delimiter string. + </para> + + <para> + In <function>string_to_array</function>, if the null-string parameter + is omitted or NULL, none of the substrings of the input will be replaced + by NULL. + In <function>array_to_string</function>, if the null-string parameter + is omitted or NULL, any null elements in the array are simply skipped + and not represented in the output string. + </para> + + <note> + <para> + There are two differences in the behavior of <function>string_to_array</> + from pre-9.1 versions of <productname>PostgreSQL</>. + First, it will return an empty (zero-element) array rather than NULL when + the input string is of zero length. Second, if the delimiter string is + NULL, the function splits the input into individual characters, rather + than returning NULL as before. + </para> + </note> + + <para> See also <xref linkend="functions-aggregate"> about the aggregate function <function>array_agg</function> for use with arrays. </para> @@ -9731,7 +10461,7 @@ SELECT NULLIF(value, '(none)') ... <thead> <row> <entry>Function</entry> - <entry>Argument Type</entry> + <entry>Argument Type(s)</entry> <entry>Return Type</entry> <entry>Description</entry> </row> @@ -9751,7 +10481,7 @@ SELECT NULLIF(value, '(none)') ... <entry> array of the argument type </entry> - <entry>input values concatenated into an array</entry> + <entry>input values, including nulls, concatenated into an array</entry> </row> <row> @@ -9759,6 +10489,9 @@ SELECT NULLIF(value, '(none)') ... <indexterm> <primary>average</primary> </indexterm> + <indexterm> + <primary>avg</primary> + </indexterm> <function>avg(<replaceable class="parameter">expression</replaceable>)</function> </entry> <entry> @@ -9841,7 +10574,12 @@ SELECT NULLIF(value, '(none)') ... </row> <row> - <entry><function>count(*)</function></entry> + <entry> + <indexterm> + <primary>count</primary> + </indexterm> + <function>count(*)</function> + </entry> <entry></entry> <entry><type>bigint</type></entry> <entry>number of input rows</entry> @@ -9874,7 +10612,12 @@ SELECT NULLIF(value, '(none)') ... </row> <row> - <entry><function>max(<replaceable class="parameter">expression</replaceable>)</function></entry> + <entry> + <indexterm> + <primary>max</primary> + </indexterm> + <function>max(<replaceable class="parameter">expression</replaceable>)</function> + </entry> <entry>any array, numeric, string, or date/time type</entry> <entry>same as argument type</entry> <entry> @@ -9885,7 +10628,12 @@ SELECT NULLIF(value, '(none)') ... </row> <row> - <entry><function>min(<replaceable class="parameter">expression</replaceable>)</function></entry> + <entry> + <indexterm> + <primary>min</primary> + </indexterm> + <function>min(<replaceable class="parameter">expression</replaceable>)</function> + </entry> <entry>any array, numeric, string, or date/time type</entry> <entry>same as argument type</entry> <entry> @@ -9901,21 +10649,26 @@ SELECT NULLIF(value, '(none)') ... <primary>string_agg</primary> </indexterm> <function> - string_agg(<replaceable class="parameter">expression</replaceable> - [, <replaceable class="parameter">delimiter</replaceable> ] ) + string_agg(<replaceable class="parameter">expression</replaceable>, + <replaceable class="parameter">delimiter</replaceable>) </function> </entry> <entry> - <type>text</type> + <type>text</type>, <type>text</type> </entry> <entry> <type>text</type> </entry> - <entry>input values concatenated into a string, optionally with delimiters</entry> + <entry>input values concatenated into a string, separated by delimiter</entry> </row> <row> - <entry><function>sum(<replaceable class="parameter">expression</replaceable>)</function></entry> + <entry> + <indexterm> + <primary>sum</primary> + </indexterm> + <function>sum(<replaceable class="parameter">expression</replaceable>)</function> + </entry> <entry> <type>smallint</type>, <type>int</type>, <type>bigint</type>, <type>real</type>, <type>double @@ -9979,8 +10732,8 @@ SELECT NULLIF(value, '(none)') ... SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...; </programlisting> Here <function>ANY</function> can be considered either as introducing - a subquery, or as being an aggregate function, if the sub-select - returns one row with a boolean value. + a subquery, or as being an aggregate function, if the subquery + returns one row with a Boolean value. Thus the standard name cannot be given to these aggregates. </para> </note> @@ -10057,6 +10810,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <indexterm> <primary>correlation</primary> </indexterm> + <indexterm> + <primary>corr</primary> + </indexterm> <function>corr(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10074,6 +10830,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <primary>covariance</primary> <secondary>population</secondary> </indexterm> + <indexterm> + <primary>covar_pop</primary> + </indexterm> <function>covar_pop(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10091,6 +10850,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <primary>covariance</primary> <secondary>sample</secondary> </indexterm> + <indexterm> + <primary>covar_samp</primary> + </indexterm> <function>covar_samp(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10104,6 +10866,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <row> <entry> + <indexterm> + <primary>regr_avgx</primary> + </indexterm> <function>regr_avgx(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10118,6 +10883,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <row> <entry> + <indexterm> + <primary>regr_avgy</primary> + </indexterm> <function>regr_avgy(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10132,6 +10900,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <row> <entry> + <indexterm> + <primary>regr_count</primary> + </indexterm> <function>regr_count(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10148,6 +10919,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <indexterm> <primary>regression intercept</primary> </indexterm> + <indexterm> + <primary>regr_intercept</primary> + </indexterm> <function>regr_intercept(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10164,6 +10938,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <row> <entry> + <indexterm> + <primary>regr_r2</primary> + </indexterm> <function>regr_r2(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10180,6 +10957,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <indexterm> <primary>regression slope</primary> </indexterm> + <indexterm> + <primary>regr_slope</primary> + </indexterm> <function>regr_slope(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10195,6 +10975,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <row> <entry> + <indexterm> + <primary>regr_sxx</primary> + </indexterm> <function>regr_sxx(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10212,6 +10995,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <row> <entry> + <indexterm> + <primary>regr_sxy</primary> + </indexterm> <function>regr_sxy(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10232,6 +11018,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <row> <entry> + <indexterm> + <primary>regr_syy</primary> + </indexterm> <function>regr_syy(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function> </entry> <entry> @@ -10252,6 +11041,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <indexterm> <primary>standard deviation</primary> </indexterm> + <indexterm> + <primary>stddev</primary> + </indexterm> <function>stddev(<replaceable class="parameter">expression</replaceable>)</function> </entry> <entry> @@ -10272,6 +11064,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <primary>standard deviation</primary> <secondary>population</secondary> </indexterm> + <indexterm> + <primary>stddev_pop</primary> + </indexterm> <function>stddev_pop(<replaceable class="parameter">expression</replaceable>)</function> </entry> <entry> @@ -10292,6 +11087,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <primary>standard deviation</primary> <secondary>sample</secondary> </indexterm> + <indexterm> + <primary>stddev_samp</primary> + </indexterm> <function>stddev_samp(<replaceable class="parameter">expression</replaceable>)</function> </entry> <entry> @@ -10331,6 +11129,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <primary>variance</primary> <secondary>population</secondary> </indexterm> + <indexterm> + <primary>var_pop</primary> + </indexterm> <function>var_pop</function>(<replaceable class="parameter">expression</replaceable>) </entry> <entry> @@ -10351,6 +11152,9 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; <primary>variance</primary> <secondary>sample</secondary> </indexterm> + <indexterm> + <primary>var_samp</primary> + </indexterm> <function>var_samp</function>(<replaceable class="parameter">expression</replaceable>) </entry> <entry> @@ -10689,7 +11493,7 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; Boolean (true/false) results. </para> - <sect2> + <sect2 id="functions-subquery-exists"> <title><literal>EXISTS</literal></title> <synopsis> @@ -10739,7 +11543,7 @@ WHERE EXISTS (SELECT 1 FROM tab2 WHERE col2 = tab1.col2); </para> </sect2> - <sect2> + <sect2 id="functions-subquery-in"> <title><literal>IN</literal></title> <synopsis> @@ -10795,7 +11599,7 @@ WHERE EXISTS (SELECT 1 FROM tab2 WHERE col2 = tab1.col2); </para> </sect2> - <sect2> + <sect2 id="functions-subquery-notin"> <title><literal>NOT IN</literal></title> <synopsis> @@ -10851,7 +11655,7 @@ WHERE EXISTS (SELECT 1 FROM tab2 WHERE col2 = tab1.col2); </para> </sect2> - <sect2> + <sect2 id="functions-subquery-any-some"> <title><literal>ANY</literal>/<literal>SOME</literal></title> <synopsis> @@ -10916,7 +11720,7 @@ WHERE EXISTS (SELECT 1 FROM tab2 WHERE col2 = tab1.col2); </para> </sect2> - <sect2> + <sect2 id="functions-subquery-all"> <title><literal>ALL</literal></title> <synopsis> @@ -11215,8 +12019,8 @@ AND <literal>></> or <literal>>=</>, or has semantics similar to one of these. (To be specific, an operator - can be a row comparison operator if it is a member of a B-Tree operator - class, or is the negator of the <literal>=</> member of a B-Tree operator + can be a row comparison operator if it is a member of a B-tree operator + class, or is the negator of the <literal>=</> member of a B-tree operator class.) </para> @@ -11327,7 +12131,7 @@ AND <tbody> <row> - <entry><literal><function>generate_series</function>(<parameter>start</parameter>, <parameter>stop</parameter>)</literal></entry> + <entry><literal><function>generate_series(<parameter>start</parameter>, <parameter>stop</parameter>)</function></literal></entry> <entry><type>int</type> or <type>bigint</type></entry> <entry><type>setof int</type> or <type>setof bigint</type> (same as argument type)</entry> <entry> @@ -11337,7 +12141,7 @@ AND </row> <row> - <entry><literal><function>generate_series</function>(<parameter>start</parameter>, <parameter>stop</parameter>, <parameter>step</parameter>)</literal></entry> + <entry><literal><function>generate_series(<parameter>start</parameter>, <parameter>stop</parameter>, <parameter>step</parameter>)</function></literal></entry> <entry><type>int</type> or <type>bigint</type></entry> <entry><type>setof int</type> or <type>setof bigint</type> (same as argument type)</entry> <entry> @@ -11347,7 +12151,7 @@ AND </row> <row> - <entry><literal><function>generate_series</function>(<parameter>start</parameter>, <parameter>stop</parameter>, <parameter>step</parameter> <type>interval</>)</literal></entry> + <entry><literal><function>generate_series(<parameter>start</parameter>, <parameter>stop</parameter>, <parameter>step</parameter> <type>interval</>)</function></literal></entry> <entry><type>timestamp</type> or <type>timestamp with time zone</type></entry> <entry><type>setof timestamp</type> or <type>setof timestamp with time zone</type> (same as argument type)</entry> <entry> @@ -11428,7 +12232,7 @@ SELECT * FROM generate_series('2008-03-01 00:00'::timestamp, <tbody> <row> - <entry><literal><function>generate_subscripts</function>(<parameter>array anyarray</parameter>, <parameter>dim int</parameter>)</literal></entry> + <entry><literal><function>generate_subscripts(<parameter>array anyarray</parameter>, <parameter>dim int</parameter>)</function></literal></entry> <entry><type>setof int</type></entry> <entry> Generate a series comprising the given array's subscripts. @@ -11436,7 +12240,7 @@ SELECT * FROM generate_series('2008-03-01 00:00'::timestamp, </row> <row> - <entry><literal><function>generate_subscripts</function>(<parameter>array anyarray</parameter>, <parameter>dim int</parameter>, <parameter>reverse boolean</parameter>)</literal></entry> + <entry><literal><function>generate_subscripts(<parameter>array anyarray</parameter>, <parameter>dim int</parameter>, <parameter>reverse boolean</parameter>)</function></literal></entry> <entry><type>setof int</type></entry> <entry> Generate a series comprising the given array's subscripts. When @@ -11494,7 +12298,7 @@ FROM (SELECT generate_subscripts(a, 1) AS s, a FROM arrays) foo; -- unnest a 2D array CREATE OR REPLACE FUNCTION unnest2(anyarray) RETURNS SETOF anyelement AS $$ -select $1[i][j] +select $1[i][j] from generate_subscripts($1,1) g1(i), generate_subscripts($1,2) g2(j); $$ LANGUAGE sql IMMUTABLE; @@ -11542,19 +12346,26 @@ postgres=# SELECT * FROM unnest2(ARRAY[[1,2],[3,4]]); </row> <row> - <entry><literal><function>current_database</function>()</literal></entry> + <entry><literal><function>current_database()</function></literal></entry> <entry><type>name</type></entry> <entry>name of current database</entry> </row> <row> + <entry><literal><function>current_query()</function></literal></entry> + <entry><type>text</type></entry> + <entry>text of the currently executing query, as submitted + by the client (might contain more than one statement)</entry> + </row> + + <row> <entry><literal><function>current_schema</function>[()]</literal></entry> <entry><type>name</type></entry> <entry>name of current schema</entry> </row> <row> - <entry><literal><function>current_schemas</function>(<type>boolean</type>)</literal></entry> + <entry><literal><function>current_schemas(<type>boolean</type>)</function></literal></entry> <entry><type>name[]</type></entry> <entry>names of schemas in search path, optionally including implicit schemas</entry> </row> @@ -11566,73 +12377,66 @@ postgres=# SELECT * FROM unnest2(ARRAY[[1,2],[3,4]]); </row> <row> - <entry><literal><function>current_query</function>()</literal></entry> - <entry><type>text</type></entry> - <entry>text of the currently executing query, as submitted - by the client (might contain more than one statement)</entry> - </row> - - <row> - <!-- See also the entry for this in monitoring.sgml --> - <entry><literal><function>pg_backend_pid</function>()</literal></entry> - <entry><type>int</type></entry> - <entry> - Process ID of the server process attached to the current session - </entry> - </row> - - <row> - <entry><literal><function>pg_listening_channels</function>()</literal></entry> - <entry><type>setof text</type></entry> - <entry>channel names that the session is currently listening on</entry> - </row> - - <row> - <entry><literal><function>inet_client_addr</function>()</literal></entry> + <entry><literal><function>inet_client_addr()</function></literal></entry> <entry><type>inet</type></entry> <entry>address of the remote connection</entry> </row> <row> - <entry><literal><function>inet_client_port</function>()</literal></entry> + <entry><literal><function>inet_client_port()</function></literal></entry> <entry><type>int</type></entry> <entry>port of the remote connection</entry> </row> <row> - <entry><literal><function>inet_server_addr</function>()</literal></entry> + <entry><literal><function>inet_server_addr()</function></literal></entry> <entry><type>inet</type></entry> <entry>address of the local connection</entry> </row> <row> - <entry><literal><function>inet_server_port</function>()</literal></entry> + <entry><literal><function>inet_server_port()</function></literal></entry> <entry><type>int</type></entry> <entry>port of the local connection</entry> </row> <row> - <entry><literal><function>pg_my_temp_schema</function>()</literal></entry> - <entry><type>oid</type></entry> - <entry>OID of session's temporary schema, or 0 if none</entry> + <!-- See also the entry for this in monitoring.sgml --> + <entry><literal><function>pg_backend_pid()</function></literal></entry> + <entry><type>int</type></entry> + <entry> + Process ID of the server process attached to the current session + </entry> + </row> + + <row> + <entry><literal><function>pg_conf_load_time()</function></literal></entry> + <entry><type>timestamp with time zone</type></entry> + <entry>configuration load time</entry> </row> <row> - <entry><literal><function>pg_is_other_temp_schema</function>(<type>oid</type>)</literal></entry> + <entry><literal><function>pg_is_other_temp_schema(<type>oid</type>)</function></literal></entry> <entry><type>boolean</type></entry> <entry>is schema another session's temporary schema?</entry> </row> <row> - <entry><literal><function>pg_postmaster_start_time</function>()</literal></entry> - <entry><type>timestamp with time zone</type></entry> - <entry>server start time</entry> + <entry><literal><function>pg_listening_channels()</function></literal></entry> + <entry><type>setof text</type></entry> + <entry>channel names that the session is currently listening on</entry> </row> <row> - <entry><literal><function>pg_conf_load_time</function>()</literal></entry> + <entry><literal><function>pg_my_temp_schema()</function></literal></entry> + <entry><type>oid</type></entry> + <entry>OID of session's temporary schema, or 0 if none</entry> + </row> + + <row> + <entry><literal><function>pg_postmaster_start_time()</function></literal></entry> <entry><type>timestamp with time zone</type></entry> - <entry>configuration load time</entry> + <entry>server start time</entry> </row> <row> @@ -11648,7 +12452,7 @@ postgres=# SELECT * FROM unnest2(ARRAY[[1,2],[3,4]]); </row> <row> - <entry><literal><function>version</function>()</literal></entry> + <entry><literal><function>version()</function></literal></entry> <entry><type>text</type></entry> <entry><productname>PostgreSQL</> version information</entry> </row> @@ -11668,34 +12472,54 @@ postgres=# SELECT * FROM unnest2(ARRAY[[1,2],[3,4]]); </note> <indexterm> - <primary>user</primary> - <secondary>current</secondary> + <primary>current_catalog</primary> </indexterm> <indexterm> - <primary>schema</primary> - <secondary>current</secondary> + <primary>current_database</primary> </indexterm> <indexterm> - <primary>search path</primary> + <primary>current_query</primary> + </indexterm> + + <indexterm> + <primary>current_schema</primary> + </indexterm> + + <indexterm> + <primary>current_schemas</primary> + </indexterm> + + <indexterm> + <primary>current_user</primary> + </indexterm> + + <indexterm> + <primary>pg_backend_pid</primary> + </indexterm> + + <indexterm> + <primary>schema</primary> <secondary>current</secondary> </indexterm> <indexterm> - <primary>current_catalog</primary> + <primary>search path</primary> + <secondary>current</secondary> </indexterm> <indexterm> - <primary>current_database</primary> + <primary>session_user</primary> </indexterm> <indexterm> - <primary>current_schema</primary> + <primary>user</primary> + <secondary>current</secondary> </indexterm> <indexterm> - <primary>current_user</primary> + <primary>user</primary> </indexterm> <para> @@ -11948,34 +12772,34 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, .. <entry>does current user have privilege for schema</entry> </row> <row> - <entry><literal><function>has_server_privilege</function>(<parameter>user</parameter>, - <parameter>server</parameter>, + <entry><literal><function>has_sequence_privilege</function>(<parameter>user</parameter>, + <parameter>sequence</parameter>, <parameter>privilege</parameter>)</literal> </entry> <entry><type>boolean</type></entry> - <entry>does user have privilege for foreign server</entry> + <entry>does user have privilege for sequence</entry> </row> <row> - <entry><literal><function>has_server_privilege</function>(<parameter>server</parameter>, + <entry><literal><function>has_sequence_privilege</function>(<parameter>sequence</parameter>, <parameter>privilege</parameter>)</literal> </entry> <entry><type>boolean</type></entry> - <entry>does current user have privilege for foreign server</entry> + <entry>does current user have privilege for sequence</entry> </row> <row> - <entry><literal><function>has_sequence_privilege</function>(<parameter>user</parameter>, - <parameter>sequence</parameter>, + <entry><literal><function>has_server_privilege</function>(<parameter>user</parameter>, + <parameter>server</parameter>, <parameter>privilege</parameter>)</literal> </entry> <entry><type>boolean</type></entry> - <entry>does user have privilege for sequence</entry> + <entry>does user have privilege for foreign server</entry> </row> <row> - <entry><literal><function>has_sequence_privilege</function>(<parameter>sequence</parameter>, + <entry><literal><function>has_server_privilege</function>(<parameter>server</parameter>, <parameter>privilege</parameter>)</literal> </entry> <entry><type>boolean</type></entry> - <entry>does current user have privilege for sequence</entry> + <entry>does current user have privilege for foreign server</entry> </row> <row> <entry><literal><function>has_table_privilege</function>(<parameter>user</parameter>, @@ -12066,8 +12890,8 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, .. <para> <function>has_table_privilege</function> checks whether a user can access a table in a particular way. The user can be - specified by name or by OID - (<literal>pg_authid.oid</literal>), or if the argument is + specified by name, by OID (<literal>pg_authid.oid</literal>), + <literal>public</> to indicate the PUBLIC pseudo-role, or if the argument is omitted <function>current_user</function> is assumed. The table can be specified by name or by OID. (Thus, there are actually six variants of @@ -12214,7 +13038,8 @@ SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute'); <function>pg_has_role</function> checks whether a user can access a role in a particular way. Its argument possibilities - are analogous to <function>has_table_privilege</function>. + are analogous to <function>has_table_privilege</function>, + except that <literal>public</> is not allowed as a user name. The desired access privilege type must evaluate to some combination of <literal>MEMBER</literal> or <literal>USAGE</literal>. @@ -12247,61 +13072,67 @@ SELECT relname FROM pg_class WHERE pg_table_is_visible(oid); <tbody> <row> - <entry><literal><function>pg_conversion_is_visible</function>(<parameter>conversion_oid</parameter>)</literal> + <entry><literal><function>pg_collation_is_visible(<parameter>collation_oid</parameter>)</function></literal> + </entry> + <entry><type>boolean</type></entry> + <entry>is collation visible in search path</entry> + </row> + <row> + <entry><literal><function>pg_conversion_is_visible(<parameter>conversion_oid</parameter>)</function></literal> </entry> <entry><type>boolean</type></entry> <entry>is conversion visible in search path</entry> </row> <row> - <entry><literal><function>pg_function_is_visible</function>(<parameter>function_oid</parameter>)</literal> + <entry><literal><function>pg_function_is_visible(<parameter>function_oid</parameter>)</function></literal> </entry> <entry><type>boolean</type></entry> <entry>is function visible in search path</entry> </row> <row> - <entry><literal><function>pg_operator_is_visible</function>(<parameter>operator_oid</parameter>)</literal> + <entry><literal><function>pg_opclass_is_visible(<parameter>opclass_oid</parameter>)</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>is operator visible in search path</entry> + <entry>is operator class visible in search path</entry> </row> <row> - <entry><literal><function>pg_opclass_is_visible</function>(<parameter>opclass_oid</parameter>)</literal> + <entry><literal><function>pg_operator_is_visible(<parameter>operator_oid</parameter>)</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>is operator class visible in search path</entry> + <entry>is operator visible in search path</entry> </row> <row> - <entry><literal><function>pg_table_is_visible</function>(<parameter>table_oid</parameter>)</literal> + <entry><literal><function>pg_table_is_visible(<parameter>table_oid</parameter>)</function></literal> </entry> <entry><type>boolean</type></entry> <entry>is table visible in search path</entry> </row> <row> - <entry><literal><function>pg_ts_config_is_visible</function>(<parameter>config_oid</parameter>)</literal> + <entry><literal><function>pg_ts_config_is_visible(<parameter>config_oid</parameter>)</function></literal> </entry> <entry><type>boolean</type></entry> <entry>is text search configuration visible in search path</entry> </row> <row> - <entry><literal><function>pg_ts_dict_is_visible</function>(<parameter>dict_oid</parameter>)</literal> + <entry><literal><function>pg_ts_dict_is_visible(<parameter>dict_oid</parameter>)</function></literal> </entry> <entry><type>boolean</type></entry> <entry>is text search dictionary visible in search path</entry> </row> <row> - <entry><literal><function>pg_ts_parser_is_visible</function>(<parameter>parser_oid</parameter>)</literal> + <entry><literal><function>pg_ts_parser_is_visible(<parameter>parser_oid</parameter>)</function></literal> </entry> <entry><type>boolean</type></entry> <entry>is text search parser visible in search path</entry> </row> <row> - <entry><literal><function>pg_ts_template_is_visible</function>(<parameter>template_oid</parameter>)</literal> + <entry><literal><function>pg_ts_template_is_visible(<parameter>template_oid</parameter>)</function></literal> </entry> <entry><type>boolean</type></entry> <entry>is text search template visible in search path</entry> </row> <row> - <entry><literal><function>pg_type_is_visible</function>(<parameter>type_oid</parameter>)</literal> + <entry><literal><function>pg_type_is_visible(<parameter>type_oid</parameter>)</function></literal> </entry> <entry><type>boolean</type></entry> <entry>is type (or domain) visible in search path</entry> @@ -12311,16 +13142,19 @@ SELECT relname FROM pg_class WHERE pg_table_is_visible(oid); </table> <indexterm> + <primary>pg_collation_is_visible</primary> + </indexterm> + <indexterm> <primary>pg_conversion_is_visible</primary> </indexterm> <indexterm> <primary>pg_function_is_visible</primary> </indexterm> <indexterm> - <primary>pg_operator_is_visible</primary> + <primary>pg_opclass_is_visible</primary> </indexterm> <indexterm> - <primary>pg_opclass_is_visible</primary> + <primary>pg_operator_is_visible</primary> </indexterm> <indexterm> <primary>pg_table_is_visible</primary> @@ -12370,15 +13204,15 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); </indexterm> <indexterm> - <primary>pg_get_keywords</primary> + <primary>pg_describe_object</primary> </indexterm> <indexterm> - <primary>pg_get_viewdef</primary> + <primary>pg_get_constraintdef</primary> </indexterm> <indexterm> - <primary>pg_get_ruledef</primary> + <primary>pg_get_expr</primary> </indexterm> <indexterm> @@ -12402,15 +13236,19 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); </indexterm> <indexterm> - <primary>pg_get_triggerdef</primary> + <primary>pg_get_keywords</primary> </indexterm> <indexterm> - <primary>pg_get_constraintdef</primary> + <primary>pg_get_ruledef</primary> </indexterm> <indexterm> - <primary>pg_get_expr</primary> + <primary>pg_get_serial_sequence</primary> + </indexterm> + + <indexterm> + <primary>pg_get_triggerdef</primary> </indexterm> <indexterm> @@ -12418,7 +13256,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); </indexterm> <indexterm> - <primary>pg_get_serial_sequence</primary> + <primary>pg_get_viewdef</primary> + </indexterm> + + <indexterm> + <primary>pg_options_to_table</primary> </indexterm> <indexterm> @@ -12443,81 +13285,86 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); <tbody> <row> - <entry><literal><function>format_type</function>(<parameter>type_oid</parameter>, <parameter>typemod</>)</literal></entry> + <entry><literal><function>format_type(<parameter>type_oid</parameter>, <parameter>typemod</>)</function></literal></entry> <entry><type>text</type></entry> <entry>get SQL name of a data type</entry> </row> <row> - <entry><literal><function>pg_get_keywords</function>()</literal></entry> - <entry><type>setof record</type></entry> - <entry>get list of SQL keywords and their categories</entry> + <entry><literal><function>pg_describe_object(<parameter>catalog_id</parameter>, <parameter>object_id</parameter>, <parameter>object_sub_id</parameter>)</function></literal></entry> + <entry><type>text</type></entry> + <entry>get description of a database object</entry> </row> <row> - <entry><literal><function>pg_get_constraintdef</function>(<parameter>constraint_oid</parameter>)</literal></entry> + <entry><literal><function>pg_get_constraintdef(<parameter>constraint_oid</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get definition of a constraint</entry> </row> <row> - <entry><literal><function>pg_get_constraintdef</function>(<parameter>constraint_oid</parameter>, <parameter>pretty_bool</>)</literal></entry> + <entry><literal><function>pg_get_constraintdef(<parameter>constraint_oid</parameter>, <parameter>pretty_bool</>)</function></literal></entry> <entry><type>text</type></entry> <entry>get definition of a constraint</entry> </row> <row> - <entry><literal><function>pg_get_expr</function>(<parameter>expr_text</parameter>, <parameter>relation_oid</>)</literal></entry> + <entry><literal><function>pg_get_expr(<parameter>pg_node_tree</parameter>, <parameter>relation_oid</>)</function></literal></entry> <entry><type>text</type></entry> <entry>decompile internal form of an expression, assuming that any Vars in it refer to the relation indicated by the second parameter</entry> </row> <row> - <entry><literal><function>pg_get_expr</function>(<parameter>expr_text</parameter>, <parameter>relation_oid</>, <parameter>pretty_bool</>)</literal></entry> + <entry><literal><function>pg_get_expr(<parameter>pg_node_tree</parameter>, <parameter>relation_oid</>, <parameter>pretty_bool</>)</function></literal></entry> <entry><type>text</type></entry> <entry>decompile internal form of an expression, assuming that any Vars in it refer to the relation indicated by the second parameter</entry> </row> <row> - <entry><literal><function>pg_get_functiondef</function>(<parameter>func_oid</parameter>)</literal></entry> + <entry><literal><function>pg_get_functiondef(<parameter>func_oid</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get definition of a function</entry> </row> <row> - <entry><literal><function>pg_get_function_arguments</function>(<parameter>func_oid</parameter>)</literal></entry> + <entry><literal><function>pg_get_function_arguments(<parameter>func_oid</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get argument list of function's definition (with default values)</entry> </row> <row> - <entry><literal><function>pg_get_function_identity_arguments</function>(<parameter>func_oid</parameter>)</literal></entry> + <entry><literal><function>pg_get_function_identity_arguments(<parameter>func_oid</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get argument list to identify a function (without default values)</entry> </row> <row> - <entry><literal><function>pg_get_function_result</function>(<parameter>func_oid</parameter>)</literal></entry> + <entry><literal><function>pg_get_function_result(<parameter>func_oid</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get <literal>RETURNS</> clause for function</entry> </row> <row> - <entry><literal><function>pg_get_indexdef</function>(<parameter>index_oid</parameter>)</literal></entry> + <entry><literal><function>pg_get_indexdef(<parameter>index_oid</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get <command>CREATE INDEX</> command for index</entry> </row> <row> - <entry><literal><function>pg_get_indexdef</function>(<parameter>index_oid</parameter>, <parameter>column_no</>, <parameter>pretty_bool</>)</literal></entry> + <entry><literal><function>pg_get_indexdef(<parameter>index_oid</parameter>, <parameter>column_no</>, <parameter>pretty_bool</>)</function></literal></entry> <entry><type>text</type></entry> <entry>get <command>CREATE INDEX</> command for index, or definition of just one index column when <parameter>column_no</> is not zero</entry> </row> <row> - <entry><literal><function>pg_get_ruledef</function>(<parameter>rule_oid</parameter>)</literal></entry> + <entry><literal><function>pg_get_keywords()</function></literal></entry> + <entry><type>setof record</type></entry> + <entry>get list of SQL keywords and their categories</entry> + </row> + <row> + <entry><literal><function>pg_get_ruledef(<parameter>rule_oid</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get <command>CREATE RULE</> command for rule</entry> </row> <row> - <entry><literal><function>pg_get_ruledef</function>(<parameter>rule_oid</parameter>, <parameter>pretty_bool</>)</literal></entry> + <entry><literal><function>pg_get_ruledef(<parameter>rule_oid</parameter>, <parameter>pretty_bool</>)</function></literal></entry> <entry><type>text</type></entry> <entry>get <command>CREATE RULE</> command for rule</entry> </row> <row> - <entry><literal><function>pg_get_serial_sequence</function>(<parameter>table_name</parameter>, <parameter>column_name</parameter>)</literal></entry> + <entry><literal><function>pg_get_serial_sequence(<parameter>table_name</parameter>, <parameter>column_name</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get name of the sequence that a <type>serial</type> or <type>bigserial</type> column uses</entry> @@ -12533,37 +13380,42 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); <entry>get <command>CREATE [ CONSTRAINT ] TRIGGER</> command for trigger</entry> </row> <row> - <entry><literal><function>pg_get_userbyid</function>(<parameter>role_oid</parameter>)</literal></entry> + <entry><literal><function>pg_get_userbyid(<parameter>role_oid</parameter>)</function></literal></entry> <entry><type>name</type></entry> <entry>get role name with given OID</entry> </row> <row> - <entry><literal><function>pg_get_viewdef</function>(<parameter>view_name</parameter>)</literal></entry> + <entry><literal><function>pg_get_viewdef(<parameter>view_name</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get underlying <command>SELECT</command> command for view (<emphasis>deprecated</emphasis>)</entry> </row> <row> - <entry><literal><function>pg_get_viewdef</function>(<parameter>view_name</parameter>, <parameter>pretty_bool</>)</literal></entry> + <entry><literal><function>pg_get_viewdef(<parameter>view_name</parameter>, <parameter>pretty_bool</>)</function></literal></entry> <entry><type>text</type></entry> <entry>get underlying <command>SELECT</command> command for view (<emphasis>deprecated</emphasis>)</entry> </row> <row> - <entry><literal><function>pg_get_viewdef</function>(<parameter>view_oid</parameter>)</literal></entry> + <entry><literal><function>pg_get_viewdef(<parameter>view_oid</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get underlying <command>SELECT</command> command for view</entry> </row> <row> - <entry><literal><function>pg_get_viewdef</function>(<parameter>view_oid</parameter>, <parameter>pretty_bool</>)</literal></entry> + <entry><literal><function>pg_get_viewdef(<parameter>view_oid</parameter>, <parameter>pretty_bool</>)</function></literal></entry> <entry><type>text</type></entry> <entry>get underlying <command>SELECT</command> command for view</entry> </row> <row> - <entry><literal><function>pg_tablespace_databases</function>(<parameter>tablespace_oid</parameter>)</literal></entry> + <entry><literal><function>pg_options_to_table(<parameter>reloptions</parameter>)</function></literal></entry> + <entry><type>setof record</type></entry> + <entry>get the set of storage option name/value pairs</entry> + </row> + <row> + <entry><literal><function>pg_tablespace_databases(<parameter>tablespace_oid</parameter>)</function></literal></entry> <entry><type>setof oid</type></entry> <entry>get the set of database OIDs that have objects in the tablespace</entry> </row> <row> - <entry><literal><function>pg_typeof</function>(<parameter>any</parameter>)</literal></entry> + <entry><literal><function>pg_typeof(<parameter>any</parameter>)</function></literal></entry> <entry><type>regtype</type></entry> <entry>get the data type of any value</entry> </row> @@ -12646,6 +13498,14 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); </para> <para> + <function>pg_options_to_table</function> returns the set of storage + option name/value pairs + (<literal>option_name</>/<literal>option_value</>) when passed + <structname>pg_class</>.<structfield>reloptions</> or + <structname>pg_attribute</>.<structfield>attoptions</>. + </para> + + <para> <function>pg_tablespace_databases</function> allows a tablespace to be examined. It returns the set of OIDs of databases that have objects stored in the tablespace. If this function returns any rows, the tablespace is not @@ -12656,6 +13516,13 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); </para> <para> + <function>pg_describe_object</function> returns a description of a database + object specified by catalog OID, object OID and a (possibly zero) sub-object ID. + This is useful to determine the identity of an object as stored in the + <structname>pg_depend</structname> catalog. + </para> + + <para> <function>pg_typeof</function> returns the OID of the data type of the value that is passed to it. This can be helpful for troubleshooting or dynamically constructing SQL queries. The function is declared as @@ -12711,22 +13578,22 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33); <tbody> <row> - <entry><literal><function>col_description</function>(<parameter>table_oid</parameter>, <parameter>column_number</parameter>)</literal></entry> + <entry><literal><function>col_description(<parameter>table_oid</parameter>, <parameter>column_number</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get comment for a table column</entry> </row> <row> - <entry><literal><function>obj_description</function>(<parameter>object_oid</parameter>, <parameter>catalog_name</parameter>)</literal></entry> + <entry><literal><function>obj_description(<parameter>object_oid</parameter>, <parameter>catalog_name</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get comment for a database object</entry> </row> <row> - <entry><literal><function>obj_description</function>(<parameter>object_oid</parameter>)</literal></entry> + <entry><literal><function>obj_description(<parameter>object_oid</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get comment for a database object (<emphasis>deprecated</emphasis>)</entry> </row> <row> - <entry><literal><function>shobj_description</function>(<parameter>object_oid</parameter>, <parameter>catalog_name</parameter>)</literal></entry> + <entry><literal><function>shobj_description(<parameter>object_oid</parameter>, <parameter>catalog_name</parameter>)</function></literal></entry> <entry><type>text</type></entry> <entry>get comment for a shared database object</entry> </row> @@ -12735,10 +13602,10 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33); </table> <para> - <function>col_description</function> returns the comment for a table column, - which is specified by the OID of its table and its column number. - <function>obj_description</function> cannot be used for table columns since - columns do not have OIDs of their own. + <function>col_description</function> returns the comment for a table + column, which is specified by the OID of its table and its column number. + (<function>obj_description</function> cannot be used for table columns + since columns do not have OIDs of their own.) </para> <para> @@ -12757,8 +13624,8 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33); <function>shobj_description</function> is used just like <function>obj_description</function> except it is used for retrieving comments on shared objects. Some system catalogs are global to all - databases within each cluster and their descriptions are stored globally - as well. + databases within each cluster, and the descriptions for objects in them + are stored globally as well. </para> <indexterm> @@ -12770,7 +13637,7 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33); </indexterm> <indexterm> - <primary>txid_snapshot_xmin</primary> + <primary>txid_snapshot_xip</primary> </indexterm> <indexterm> @@ -12778,7 +13645,7 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33); </indexterm> <indexterm> - <primary>txid_snapshot_xip</primary> + <primary>txid_snapshot_xmin</primary> </indexterm> <indexterm> @@ -12793,7 +13660,7 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33); </para> <table id="functions-txid-snapshot"> - <title>Transaction IDs and snapshots</title> + <title>Transaction IDs and Snapshots</title> <tgroup cols="3"> <thead> <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row> @@ -12801,32 +13668,32 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33); <tbody> <row> - <entry><literal><function>txid_current</function>()</literal></entry> + <entry><literal><function>txid_current()</function></literal></entry> <entry><type>bigint</type></entry> <entry>get current transaction ID</entry> </row> <row> - <entry><literal><function>txid_current_snapshot</function>()</literal></entry> + <entry><literal><function>txid_current_snapshot()</function></literal></entry> <entry><type>txid_snapshot</type></entry> <entry>get current snapshot</entry> </row> <row> - <entry><literal><function>txid_snapshot_xmin</function>(<parameter>txid_snapshot</parameter>)</literal></entry> - <entry><type>bigint</type></entry> - <entry>get xmin of snapshot</entry> + <entry><literal><function>txid_snapshot_xip(<parameter>txid_snapshot</parameter>)</function></literal></entry> + <entry><type>setof bigint</type></entry> + <entry>get in-progress transaction IDs in snapshot</entry> </row> <row> - <entry><literal><function>txid_snapshot_xmax</function>(<parameter>txid_snapshot</parameter>)</literal></entry> + <entry><literal><function>txid_snapshot_xmax(<parameter>txid_snapshot</parameter>)</function></literal></entry> <entry><type>bigint</type></entry> - <entry>get xmax of snapshot</entry> + <entry>get <literal>xmax</literal> of snapshot</entry> </row> <row> - <entry><literal><function>txid_snapshot_xip</function>(<parameter>txid_snapshot</parameter>)</literal></entry> - <entry><type>setof bigint</type></entry> - <entry>get in-progress transaction IDs in snapshot</entry> + <entry><literal><function>txid_snapshot_xmin(<parameter>txid_snapshot</parameter>)</function></literal></entry> + <entry><type>bigint</type></entry> + <entry>get <literal>xmin</literal> of snapshot</entry> </row> <row> - <entry><literal><function>txid_visible_in_snapshot</function>(<parameter>bigint</parameter>, <parameter>txid_snapshot</parameter>)</literal></entry> + <entry><literal><function>txid_visible_in_snapshot(<parameter>bigint</parameter>, <parameter>txid_snapshot</parameter>)</function></literal></entry> <entry><type>boolean</type></entry> <entry>is transaction ID visible in snapshot? (do not use with subtransaction ids)</entry> </row> @@ -12846,7 +13713,7 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33); </para> <table id="functions-txid-snapshot-parts"> - <title>Snapshot components</title> + <title>Snapshot Components</title> <tgroup cols="2"> <thead> <row> @@ -12918,13 +13785,19 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33); <tbody> <row> <entry> - <literal><function>current_setting</function>(<parameter>setting_name</parameter>)</literal> + <indexterm> + <primary>current_setting</primary> + </indexterm> + <literal><function>current_setting(<parameter>setting_name</parameter>)</function></literal> </entry> <entry><type>text</type></entry> <entry>get current value of setting</entry> </row> <row> <entry> + <indexterm> + <primary>set_config</primary> + </indexterm> <literal><function>set_config(<parameter>setting_name</parameter>, <parameter>new_value</parameter>, <parameter>is_local</parameter>)</function></literal> @@ -12988,14 +13861,14 @@ SELECT set_config('log_statement_stats', 'off', false); <primary>pg_cancel_backend</primary> </indexterm> <indexterm> - <primary>pg_terminate_backend</primary> - </indexterm> - <indexterm> <primary>pg_reload_conf</primary> </indexterm> <indexterm> <primary>pg_rotate_logfile</primary> </indexterm> + <indexterm> + <primary>pg_terminate_backend</primary> + </indexterm> <indexterm> <primary>signal</primary> @@ -13020,31 +13893,31 @@ SELECT set_config('log_statement_stats', 'off', false); <tbody> <row> <entry> - <literal><function>pg_cancel_backend</function>(<parameter>pid</parameter> <type>int</>)</literal> + <literal><function>pg_cancel_backend(<parameter>pid</parameter> <type>int</>)</function></literal> </entry> <entry><type>boolean</type></entry> <entry>Cancel a backend's current query</entry> </row> <row> <entry> - <literal><function>pg_terminate_backend</function>(<parameter>pid</parameter> <type>int</>)</literal> + <literal><function>pg_reload_conf()</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>Terminate a backend</entry> + <entry>Cause server processes to reload their configuration files</entry> </row> <row> <entry> - <literal><function>pg_reload_conf</function>()</literal> + <literal><function>pg_rotate_logfile()</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>Cause server processes to reload their configuration files</entry> + <entry>Rotate server's log file</entry> </row> <row> <entry> - <literal><function>pg_rotate_logfile</function>()</literal> + <literal><function>pg_terminate_backend(<parameter>pid</parameter> <type>int</>)</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>Rotate server's log file</entry> + <entry>Terminate a backend</entry> </row> </tbody> </tgroup> @@ -13076,40 +13949,42 @@ SELECT set_config('log_statement_stats', 'off', false); <para> <function>pg_rotate_logfile</> signals the log-file manager to switch to a new output file immediately. This works only when the built-in - log collector is running, since otherwise there is no log-file manager + log collector is running, since otherwise there is no log-file manager subprocess. </para> <indexterm> - <primary>pg_start_backup</primary> + <primary>backup</primary> </indexterm> <indexterm> - <primary>pg_stop_backup</primary> + <primary>pg_create_restore_point</primary> </indexterm> <indexterm> - <primary>pg_switch_xlog</primary> + <primary>pg_current_xlog_insert_location</primary> </indexterm> <indexterm> <primary>pg_current_xlog_location</primary> </indexterm> <indexterm> - <primary>pg_current_xlog_insert_location</primary> + <primary>pg_start_backup</primary> </indexterm> <indexterm> - <primary>pg_xlogfile_name_offset</primary> + <primary>pg_stop_backup</primary> + </indexterm> + <indexterm> + <primary>pg_switch_xlog</primary> </indexterm> <indexterm> <primary>pg_xlogfile_name</primary> </indexterm> <indexterm> - <primary>backup</primary> + <primary>pg_xlogfile_name_offset</primary> </indexterm> <para> The functions shown in <xref linkend="functions-admin-backup-table"> assist in making on-line backups. These functions cannot be executed during recovery. - Use of the first three functions is restricted to superusers. </para> <table id="functions-admin-backup-table"> @@ -13123,53 +13998,60 @@ SELECT set_config('log_statement_stats', 'off', false); <tbody> <row> <entry> - <literal><function>pg_start_backup</function>(<parameter>label</> <type>text</> <optional>, <parameter>fast</> <type>boolean</> </optional>)</literal> + <literal><function>pg_create_restore_point(<parameter>name</> <type>text</>)</function></literal> </entry> <entry><type>text</type></entry> - <entry>Prepare for performing on-line backup</entry> + <entry>Create a named point for performing restore (restricted to superusers)</entry> </row> <row> <entry> - <literal><function>pg_stop_backup</function>()</literal> + <literal><function>pg_current_xlog_insert_location()</function></literal> </entry> <entry><type>text</type></entry> - <entry>Finish performing on-line backup</entry> + <entry>Get current transaction log insert location</entry> </row> <row> <entry> - <literal><function>pg_switch_xlog</function>()</literal> + <literal><function>pg_current_xlog_location()</function></literal> </entry> <entry><type>text</type></entry> - <entry>Force switch to a new transaction log file</entry> + <entry>Get current transaction log write location</entry> </row> <row> <entry> - <literal><function>pg_current_xlog_location</function>()</literal> + <literal><function>pg_start_backup(<parameter>label</> <type>text</> <optional>, <parameter>fast</> <type>boolean</> </optional>)</function></literal> </entry> <entry><type>text</type></entry> - <entry>Get current transaction log write location</entry> + <entry>Prepare for performing on-line backup (restricted to superusers or replication roles)</entry> </row> <row> <entry> - <literal><function>pg_current_xlog_insert_location</function>()</literal> + <literal><function>pg_stop_backup()</function></literal> </entry> <entry><type>text</type></entry> - <entry>Get current transaction log insert location</entry> + <entry>Finish performing on-line backup (restricted to superusers or replication roles)</entry> </row> <row> <entry> - <literal><function>pg_xlogfile_name_offset</function>(<parameter>location</> <type>text</>)</literal> + <literal><function>pg_switch_xlog()</function></literal> </entry> - <entry><type>text</>, <type>integer</></entry> - <entry>Convert transaction log location string to file name and decimal byte offset within file</entry> + <entry><type>text</type></entry> + <entry>Force switch to a new transaction log file (restricted to superusers)</entry> </row> <row> <entry> - <literal><function>pg_xlogfile_name</function>(<parameter>location</> <type>text</>)</literal> + <literal><function>pg_xlogfile_name(<parameter>location</> <type>text</>)</function></literal> </entry> <entry><type>text</type></entry> <entry>Convert transaction log location string to file name</entry> </row> + <row> + <entry> + <literal><function>pg_xlogfile_name_offset(<parameter>location</> <type>text</>)</function></literal> + </entry> + <entry><type>text</>, <type>integer</></entry> + <entry>Convert transaction log location string to file name and decimal byte offset within file</entry> + </row> </tbody> </tgroup> </table> @@ -13190,7 +14072,7 @@ postgres=# select pg_start_backup('label_goes_here'); 0/D4445B8 (1 row) </programlisting> - There is an optional boolean second parameter. If <literal>true</>, + There is an optional second parameter of type <type>boolean</type>. If <literal>true</>, it specifies executing <function>pg_start_backup</> as quickly as possible. This forces an immediate checkpoint which will cause a spike in I/O operations, slowing any concurrently executing queries. @@ -13219,6 +14101,16 @@ postgres=# select pg_start_backup('label_goes_here'); </para> <para> + <function>pg_create_restore_point</> creates a named transaction log + record that can be used as recovery target, and returns the corresponding + transaction log location. The given name can then be used with + <xref linkend="recovery-target-name"> to specify the point up to which + recovery will proceed. Avoid creating multiple restore points with the + same name, since recovery will stop at the first one whose name matches + the recovery target. + </para> + + <para> <function>pg_current_xlog_location</> displays the current transaction log write location in the same format used by the above functions. Similarly, <function>pg_current_xlog_insert_location</> displays the current transaction log @@ -13266,6 +14158,9 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); <indexterm> <primary>pg_last_xlog_replay_location</primary> </indexterm> + <indexterm> + <primary>pg_last_xact_replay_timestamp</primary> + </indexterm> <para> The functions shown in <xref @@ -13285,7 +14180,7 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); <tbody> <row> <entry> - <literal><function>pg_is_in_recovery</function>()</literal> + <literal><function>pg_is_in_recovery()</function></literal> </entry> <entry><type>bool</type></entry> <entry>True if recovery is still in progress. @@ -13293,15 +14188,13 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); </row> <row> <entry> - <literal><function>pg_last_xlog_receive_location</function>()</literal> + <literal><function>pg_last_xlog_receive_location()</function></literal> </entry> <entry><type>text</type></entry> <entry>Get last transaction log location received and synced to disk by streaming replication. While streaming replication is in progress - this will increase monotonically. But when streaming replication is - restarted this will back off to the replication starting position, - typically the beginning of the WAL file containing the current - replay location. If recovery has completed this will remain static at + this will increase monotonically. If recovery has completed this will + remain static at the value of the last WAL record received and synced to disk during recovery. If streaming replication is disabled, or if it has not yet started, the function returns NULL. @@ -13309,7 +14202,7 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); </row> <row> <entry> - <literal><function>pg_last_xlog_replay_location</function>()</literal> + <literal><function>pg_last_xlog_replay_location()</function></literal> </entry> <entry><type>text</type></entry> <entry>Get last transaction log location replayed during recovery. @@ -13320,10 +14213,94 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); the function returns NULL. </entry> </row> + <row> + <entry> + <literal><function>pg_last_xact_replay_timestamp()</function></literal> + </entry> + <entry><type>timestamp with time zone</type></entry> + <entry>Get time stamp of last transaction replayed during recovery. + This is the time at which the commit or abort WAL record for that + transaction was generated on the primary. + If no transactions have been replayed during recovery, this function + returns NULL. Otherwise, if recovery is still in progress this will + increase monotonically. If recovery has completed then this value will + remain static at the value of the last transaction applied during that + recovery. When the server has been started normally without recovery + the function returns NULL. + </entry> + </row> </tbody> </tgroup> </table> + <indexterm> + <primary>pg_is_xlog_replay_paused</primary> + </indexterm> + <indexterm> + <primary>pg_xlog_replay_pause</primary> + </indexterm> + <indexterm> + <primary>pg_xlog_replay_resume</primary> + </indexterm> + + <para> + The functions shown in <xref + linkend="functions-recovery-control-table"> control the progress of recovery. + These functions may be executed only during recovery. + </para> + + <table id="functions-recovery-control-table"> + <title>Recovery Control Functions</title> + <tgroup cols="3"> + <thead> + <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry> + <literal><function>pg_is_xlog_replay_paused()</function></literal> + </entry> + <entry><type>bool</type></entry> + <entry>True if recovery is paused. + </entry> + </row> + <row> + <entry> + <literal><function>pg_xlog_replay_pause()</function></literal> + </entry> + <entry><type>void</type></entry> + <entry>Pauses recovery immediately. + </entry> + </row> + <row> + <entry> + <literal><function>pg_xlog_replay_resume()</function></literal> + </entry> + <entry><type>void</type></entry> + <entry>Restarts recovery if it was paused. + </entry> + </row> + </tbody> + </tgroup> + </table> + + <para> + While recovery is paused no further database changes are applied. + If in hot standby, all new queries will see the same consistent snapshot + of the database, and no further query conflicts will be generated until + recovery is resumed. + </para> + + <para> + If streaming replication is disabled, the paused state may continue + indefinitely without problem. While streaming replication is in + progress WAL records will continue to be received, which will + eventually fill available disk space, depending upon the duration of + the pause, the rate of WAL generation and available disk space. + </para> + <para> The functions shown in <xref linkend="functions-admin-dbsize"> calculate the disk space usage of database objects. @@ -13333,25 +14310,25 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); <primary>pg_column_size</primary> </indexterm> <indexterm> - <primary>pg_total_relation_size</primary> + <primary>pg_database_size</primary> </indexterm> <indexterm> - <primary>pg_table_size</primary> + <primary>pg_indexes_size</primary> </indexterm> <indexterm> - <primary>pg_indexes_size</primary> + <primary>pg_relation_size</primary> </indexterm> <indexterm> - <primary>pg_database_size</primary> + <primary>pg_size_pretty</primary> </indexterm> <indexterm> - <primary>pg_tablespace_size</primary> + <primary>pg_table_size</primary> </indexterm> <indexterm> - <primary>pg_relation_size</primary> + <primary>pg_tablespace_size</primary> </indexterm> <indexterm> - <primary>pg_size_pretty</primary> + <primary>pg_total_relation_size</primary> </indexterm> <table id="functions-admin-dbsize"> @@ -13364,96 +14341,94 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); <tbody> <row> - <entry><literal><function>pg_column_size</function>(<type>any</type>)</literal></entry> + <entry><literal><function>pg_column_size(<type>any</type>)</function></literal></entry> <entry><type>int</type></entry> <entry>Number of bytes used to store a particular value (possibly compressed)</entry> </row> <row> <entry> - <literal><function>pg_total_relation_size</function>(<type>regclass</type>)</literal> + <literal><function>pg_database_size(<type>oid</type>)</function></literal> </entry> <entry><type>bigint</type></entry> + <entry>Disk space used by the database with the specified OID</entry> + </row> + <row> <entry> - Total disk space used by the table with the specified OID or name, - including all indexes and <acronym>TOAST</> data - </entry> + <literal><function>pg_database_size(<type>name</type>)</function></literal> + </entry> + <entry><type>bigint</type></entry> + <entry>Disk space used by the database with the specified name</entry> </row> <row> <entry> - <literal><function>pg_table_size</function>(<type>regclass</type>)</literal> + <literal><function>pg_indexes_size(<type>regclass</type>)</function></literal> </entry> <entry><type>bigint</type></entry> <entry> - Disk space used by the table with the specified OID or name, - excluding indexes (but including TOAST, free space map, and visibility - map) + Total disk space used by indexes attached to the specified table </entry> </row> <row> <entry> - <literal><function>pg_indexes_size</function>(<type>regclass</type>)</literal> + <literal><function>pg_relation_size(<parameter>relation</parameter> <type>regclass</type>, <parameter>fork</parameter> <type>text</type>)</function></literal> </entry> <entry><type>bigint</type></entry> <entry> - Total disk space used by indexes attached to the table with the - specified OID or name + Disk space used by the specified fork (<literal>'main'</literal>, + <literal>'fsm'</literal> or <literal>'vm'</>) + of the specified table or index </entry> </row> <row> <entry> - <literal><function>pg_database_size</function>(<type>oid</type>)</literal> + <literal><function>pg_relation_size(<parameter>relation</parameter> <type>regclass</type>)</function></literal> </entry> <entry><type>bigint</type></entry> - <entry>Disk space used by the database with the specified OID</entry> + <entry> + Shorthand for <literal>pg_relation_size(..., 'main')</literal> + </entry> </row> <row> <entry> - <literal><function>pg_database_size</function>(<type>name</type>)</literal> + <literal><function>pg_size_pretty(<type>bigint</type>)</function></literal> </entry> - <entry><type>bigint</type></entry> - <entry>Disk space used by the database with the specified name</entry> + <entry><type>text</type></entry> + <entry>Converts a size in bytes into a human-readable format with size units</entry> </row> <row> <entry> - <literal><function>pg_tablespace_size</function>(<type>oid</type>)</literal> + <literal><function>pg_table_size(<type>regclass</type>)</function></literal> </entry> <entry><type>bigint</type></entry> - <entry>Disk space used by the tablespace with the specified OID</entry> + <entry> + Disk space used by the specified table, excluding indexes + (but including TOAST, free space map, and visibility map) + </entry> </row> <row> <entry> - <literal><function>pg_tablespace_size</function>(<type>name</type>)</literal> + <literal><function>pg_tablespace_size(<type>oid</type>)</function></literal> </entry> <entry><type>bigint</type></entry> - <entry>Disk space used by the tablespace with the specified name</entry> + <entry>Disk space used by the tablespace with the specified OID</entry> </row> <row> <entry> - <literal><function>pg_relation_size</function>(<parameter>relation</parameter> <type>regclass</type>, <parameter>fork</parameter> <type>text</type>)</literal> + <literal><function>pg_tablespace_size(<type>name</type>)</function></literal> </entry> <entry><type>bigint</type></entry> - <entry> - Disk space used by the specified fork (<literal>'main'</literal>, - <literal>'fsm'</literal> or <literal>'vm'</>) - of the table or index with the specified OID or name - </entry> + <entry>Disk space used by the tablespace with the specified name</entry> </row> <row> <entry> - <literal><function>pg_relation_size</function>(<parameter>relation</parameter> <type>regclass</type>)</literal> + <literal><function>pg_total_relation_size(<type>regclass</type>)</function></literal> </entry> <entry><type>bigint</type></entry> <entry> - Shorthand for <literal>pg_relation_size(..., 'main')</literal> + Total disk space used by the specified table, + including all indexes and <acronym>TOAST</> data </entry> </row> - <row> - <entry> - <literal><function>pg_size_pretty</function>(<type>bigint</type>)</literal> - </entry> - <entry><type>text</type></entry> - <entry>Converts a size in bytes into a human-readable format with size units</entry> - </row> </tbody> </tgroup> </table> @@ -13511,6 +14486,18 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); </para> <para> + The functions above that operate on tables or indexes accept a + <type>regclass</> argument, which is simply the OID of the table or index + in the <structname>pg_class</> system catalog. You do not have to look up + the OID by hand, however, since the <type>regclass</> data type's input + converter will do the work for you. Just write the table name enclosed in + single quotes so that it looks like a literal constant. For compatibility + with the handling of ordinary <acronym>SQL</acronym> names, the string + will be converted to lower case unless it contains double quotes around + the table name. + </para> + + <para> The functions shown in <xref linkend="functions-admin-dblocation"> assist in identifying the specific disk files associated with database objects. </para> @@ -13533,20 +14520,20 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); <tbody> <row> <entry> - <literal><function>pg_relation_filenode</function>(<parameter>relation</parameter> <type>regclass</type>)</literal> + <literal><function>pg_relation_filenode(<parameter>relation</parameter> <type>regclass</type>)</function></literal> </entry> <entry><type>oid</type></entry> <entry> - Filenode number of the relation with the specified OID or name + Filenode number of the specified relation </entry> </row> <row> <entry> - <literal><function>pg_relation_filepath</function>(<parameter>relation</parameter> <type>regclass</type>)</literal> + <literal><function>pg_relation_filepath(<parameter>relation</parameter> <type>regclass</type>)</function></literal> </entry> <entry><type>text</type></entry> <entry> - File path name of the relation with the specified OID or name + File path name of the specified relation </entry> </row> </tbody> @@ -13567,7 +14554,7 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); <para> <function>pg_relation_filepath</> is similar to - <function>pg_relation_filenode</>, but it returns the entire file pathname + <function>pg_relation_filenode</>, but it returns the entire file path name (relative to the database cluster's data directory <varname>PGDATA</>) of the relation. </para> @@ -13593,21 +14580,28 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); <tbody> <row> <entry> - <literal><function>pg_ls_dir</function>(<parameter>dirname</> <type>text</>)</literal> + <literal><function>pg_ls_dir(<parameter>dirname</> <type>text</>)</function></literal> </entry> <entry><type>setof text</type></entry> <entry>List the contents of a directory</entry> </row> <row> <entry> - <literal><function>pg_read_file</function>(<parameter>filename</> <type>text</>, <parameter>offset</> <type>bigint</>, <parameter>length</> <type>bigint</>)</literal> + <literal><function>pg_read_file(<parameter>filename</> <type>text</> [, <parameter>offset</> <type>bigint</>, <parameter>length</> <type>bigint</>])</function></literal> </entry> <entry><type>text</type></entry> <entry>Return the contents of a text file</entry> </row> <row> <entry> - <literal><function>pg_stat_file</function>(<parameter>filename</> <type>text</>)</literal> + <literal><function>pg_read_binary_file(<parameter>filename</> <type>text</> [, <parameter>offset</> <type>bigint</>, <parameter>length</> <type>bigint</>])</function></literal> + </entry> + <entry><type>bytea</type></entry> + <entry>Return the contents of a file</entry> + </row> + <row> + <entry> + <literal><function>pg_stat_file(<parameter>filename</> <type>text</>)</function></literal> </entry> <entry><type>record</type></entry> <entry>Return information about a file</entry> @@ -13633,6 +14627,24 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); at the given <parameter>offset</>, returning at most <parameter>length</> bytes (less if the end of file is reached first). If <parameter>offset</> is negative, it is relative to the end of the file. + If <parameter>offset</> and <parameter>length</> are omitted, the entire + file is returned. The bytes read from the file are interpreted as a string + in the server encoding; an error is thrown if they are not valid in that + encoding. + </para> + + <indexterm> + <primary>pg_read_binary_file</primary> + </indexterm> + <para> + <function>pg_read_binary_file</> is similar to + <function>pg_read_file</>, except that the result is a <type>bytea</type> value; + accordingly, no encoding checks are performed. + In combination with the <function>convert_from</> function, this function + can be used to read a file in a specified encoding: +<programlisting> +SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8'); +</programlisting> </para> <indexterm> @@ -13667,102 +14679,151 @@ SELECT (pg_stat_file('filename')).modification; <tbody> <row> <entry> - <literal><function>pg_advisory_lock</function>(<parameter>key</> <type>bigint</>)</literal> + <literal><function>pg_advisory_lock(<parameter>key</> <type>bigint</>)</function></literal> </entry> <entry><type>void</type></entry> - <entry>Obtain exclusive advisory lock</entry> + <entry>Obtain exclusive session level advisory lock</entry> </row> <row> <entry> - <literal><function>pg_advisory_lock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal> + <literal><function>pg_advisory_lock(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</function></literal> </entry> <entry><type>void</type></entry> - <entry>Obtain exclusive advisory lock</entry> + <entry>Obtain exclusive session level advisory lock</entry> </row> - <row> <entry> - <literal><function>pg_advisory_lock_shared</function>(<parameter>key</> <type>bigint</>)</literal> + <literal><function>pg_advisory_lock_shared(<parameter>key</> <type>bigint</>)</function></literal> </entry> <entry><type>void</type></entry> - <entry>Obtain shared advisory lock</entry> + <entry>Obtain shared session level advisory lock</entry> </row> <row> <entry> - <literal><function>pg_advisory_lock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal> + <literal><function>pg_advisory_lock_shared(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</function></literal> </entry> <entry><type>void</type></entry> - <entry>Obtain shared advisory lock</entry> + <entry>Obtain shared session level advisory lock</entry> </row> - <row> <entry> - <literal><function>pg_try_advisory_lock</function>(<parameter>key</> <type>bigint</>)</literal> + <literal><function>pg_advisory_unlock(<parameter>key</> <type>bigint</>)</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>Obtain exclusive advisory lock if available</entry> + <entry>Release an exclusive session level advisory lock</entry> </row> <row> <entry> - <literal><function>pg_try_advisory_lock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal> + <literal><function>pg_advisory_unlock(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>Obtain exclusive advisory lock if available</entry> + <entry>Release an exclusive session level advisory lock</entry> + </row> + <row> + <entry> + <literal><function>pg_advisory_unlock_all()</function></literal> + </entry> + <entry><type>void</type></entry> + <entry>Release all session level advisory locks held by the current session</entry> </row> - <row> <entry> - <literal><function>pg_try_advisory_lock_shared</function>(<parameter>key</> <type>bigint</>)</literal> + <literal><function>pg_advisory_unlock_shared(<parameter>key</> <type>bigint</>)</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>Obtain shared advisory lock if available</entry> + <entry>Release a shared session level advisory lock</entry> </row> <row> <entry> - <literal><function>pg_try_advisory_lock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal> + <literal><function>pg_advisory_unlock_shared(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>Obtain shared advisory lock if available</entry> + <entry>Release a shared session level advisory lock</entry> + </row> + <row> + <entry> + <literal><function>pg_advisory_xact_lock(<parameter>key</> <type>bigint</>)</function></literal> + </entry> + <entry><type>void</type></entry> + <entry>Obtain exclusive transaction level advisory lock</entry> + </row> + <row> + <entry> + <literal><function>pg_advisory_xact_lock(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</function></literal> + </entry> + <entry><type>void</type></entry> + <entry>Obtain exclusive transaction level advisory lock</entry> + </row> + <row> + <entry> + <literal><function>pg_advisory_xact_lock_shared(<parameter>key</> <type>bigint</>)</function></literal> + </entry> + <entry><type>void</type></entry> + <entry>Obtain shared transaction level advisory lock</entry> + </row> + <row> + <entry> + <literal><function>pg_advisory_xact_lock_shared(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</function></literal> + </entry> + <entry><type>void</type></entry> + <entry>Obtain shared advisory lock for the current transaction</entry> </row> - <row> <entry> - <literal><function>pg_advisory_unlock</function>(<parameter>key</> <type>bigint</>)</literal> + <literal><function>pg_try_advisory_lock(<parameter>key</> <type>bigint</>)</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>Release an exclusive advisory lock</entry> + <entry>Obtain exclusive session level advisory lock if available</entry> </row> <row> <entry> - <literal><function>pg_advisory_unlock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal> + <literal><function>pg_try_advisory_lock(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>Release an exclusive advisory lock</entry> + <entry>Obtain exclusive session level advisory lock if available</entry> </row> - <row> <entry> - <literal><function>pg_advisory_unlock_shared</function>(<parameter>key</> <type>bigint</>)</literal> + <literal><function>pg_try_advisory_lock_shared(<parameter>key</> <type>bigint</>)</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>Release a shared advisory lock</entry> + <entry>Obtain shared session level advisory lock if available</entry> </row> <row> <entry> - <literal><function>pg_advisory_unlock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal> + <literal><function>pg_try_advisory_lock_shared(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</function></literal> </entry> <entry><type>boolean</type></entry> - <entry>Release a shared advisory lock</entry> + <entry>Obtain shared session level advisory lock if available</entry> </row> - <row> <entry> - <literal><function>pg_advisory_unlock_all</function>()</literal> + <literal><function>pg_try_advisory_xact_lock(<parameter>key</> <type>bigint</>)</function></literal> </entry> - <entry><type>void</type></entry> - <entry>Release all advisory locks held by the current session</entry> + <entry><type>boolean</type></entry> + <entry>Obtain exclusive transaction level advisory lock if available</entry> + </row> + <row> + <entry> + <literal><function>pg_try_advisory_xact_lock(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</function></literal> + </entry> + <entry><type>boolean</type></entry> + <entry>Obtain exclusive transaction level advisory lock if available</entry> + </row> + <row> + <entry> + <literal><function>pg_try_advisory_xact_lock_shared(<parameter>key</> <type>bigint</>)</function></literal> + </entry> + <entry><type>boolean</type></entry> + <entry>Obtain shared transaction level advisory lock if available</entry> + </row> + <row> + <entry> + <literal><function>pg_try_advisory_xact_lock_shared(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</function></literal> + </entry> + <entry><type>boolean</type></entry> + <entry>Obtain shared transaction level advisory lock if available</entry> </row> - </tbody> </tgroup> </table> @@ -13773,7 +14834,7 @@ SELECT (pg_stat_file('filename')).modification; <para> <function>pg_advisory_lock</> locks an application-defined resource, which can be identified either by a single 64-bit key value or two - 32-bit key values (note that these two key spaces do not overlap). + 32-bit key values (note that these two key spaces do not overlap). The key type is specified in <literal>pg_locks.objid</>. If another session already holds a lock on the same resource, the function will wait until the resource becomes available. The lock @@ -13813,11 +14874,49 @@ SELECT (pg_stat_file('filename')).modification; </para> <indexterm> + <primary>pg_advisory_xact_lock</primary> + </indexterm> + <para> + <function>pg_advisory_xact_lock</> works the same as + <function>pg_advisory_lock</>, expect the lock is automatically released + at the end of the current transaction and can not be released explicitly. + </para> + + <indexterm> + <primary>pg_advisory_xact_lock_shared</primary> + </indexterm> + <para> + <function>pg_advisory_xact_lock_shared</> works the same as + <function>pg_advisory_lock_shared</>, expect the lock is automatically released + at the end of the current transaction and can not be released explicitly. + </para> + + <indexterm> + <primary>pg_try_advisory_xact_lock</primary> + </indexterm> + <para> + <function>pg_try_advisory_xact_lock</> works the same as + <function>pg_try_advisory_lock</>, expect the lock, if acquired, + is automatically released at the end of the current transaction and + can not be released explicitly. + </para> + + <indexterm> + <primary>pg_try_advisory_xact_lock_shared</primary> + </indexterm> + <para> + <function>pg_try_advisory_xact_lock_shared</> works the same as + <function>pg_try_advisory_lock_shared</>, expect the lock, if acquired, + is automatically released at the end of the current transaction and + can not be released explicitly. + </para> + + <indexterm> <primary>pg_advisory_unlock</primary> </indexterm> <para> <function>pg_advisory_unlock</> will release a previously-acquired - exclusive advisory lock. It + exclusive session level advisory lock. It returns <literal>true</> if the lock is successfully released. If the lock was not held, it will return <literal>false</>, and in addition, an SQL warning will be raised by the server. @@ -13829,15 +14928,15 @@ SELECT (pg_stat_file('filename')).modification; <para> <function>pg_advisory_unlock_shared</> works the same as <function>pg_advisory_unlock</>, - except it releases a shared advisory lock. + except it releases a shared session level advisory lock. </para> <indexterm> <primary>pg_advisory_unlock_all</primary> </indexterm> <para> - <function>pg_advisory_unlock_all</> will release all advisory locks - held by the current session. (This function is implicitly invoked + <function>pg_advisory_unlock_all</> will release all session level advisory + locks held by the current session. (This function is implicitly invoked at session end, even if the client disconnects ungracefully.) </para> @@ -13852,7 +14951,7 @@ SELECT (pg_stat_file('filename')).modification; <para> Currently <productname>PostgreSQL</> provides one built in trigger - function, <function>suppress_redundant_updates_trigger</>, + function, <function>suppress_redundant_updates_trigger</>, which will prevent any update that does not actually change the data in the row from taking place, in contrast to the normal behavior which always performs the update @@ -13868,19 +14967,19 @@ SELECT (pg_stat_file('filename')).modification; and space in dead rows that will eventually have to be vacuumed. However, detecting such situations in client code is not always easy, or even possible, and writing expressions to detect - them can be error-prone. An alternative is to use + them can be error-prone. An alternative is to use <function>suppress_redundant_updates_trigger</>, which will skip updates that don't change the data. You should use this with care, - however. The trigger takes a small but non-trivial time for each record, + however. The trigger takes a small but non-trivial time for each record, so if most of the records affected by an update are actually changed, use of this trigger will actually make the update run slower. </para> <para> - The <function>suppress_redundant_updates_trigger</> function can be + The <function>suppress_redundant_updates_trigger</> function can be added to a table like this: <programlisting> -CREATE TRIGGER z_min_update +CREATE TRIGGER z_min_update BEFORE UPDATE ON tablename FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); </programlisting> diff --git a/doc/src/sgml/fuzzystrmatch.sgml b/doc/src/sgml/fuzzystrmatch.sgml index 0349f12c5f..5078bf82da 100644 --- a/doc/src/sgml/fuzzystrmatch.sgml +++ b/doc/src/sgml/fuzzystrmatch.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/fuzzystrmatch.sgml,v 1.5 2009/04/06 15:43:00 tgl Exp $ --> +<!-- doc/src/sgml/fuzzystrmatch.sgml --> -<sect1 id="fuzzystrmatch"> +<sect1 id="fuzzystrmatch" xreflabel="fuzzystrmatch"> <title>fuzzystrmatch</title> <indexterm zone="fuzzystrmatch"> @@ -14,8 +14,9 @@ <caution> <para> - At present, <filename>fuzzystrmatch</> does not work well with - multi-byte encodings (such as UTF-8). + At present, the <function>soundex</>, <function>metaphone</>, + <function>dmetaphone</>, and <function>dmetaphone_alt</> functions do + not work well with multibyte encodings (such as UTF-8). </para> </caution> @@ -34,10 +35,10 @@ for working with Soundex codes: </para> - <programlisting> - soundex(text) returns text - difference(text, text) returns int - </programlisting> +<synopsis> +soundex(text) returns text +difference(text, text) returns int +</synopsis> <para> The <function>soundex</> function converts a string to its Soundex code. @@ -53,7 +54,7 @@ Here are some usage examples: </para> - <programlisting> +<programlisting> SELECT soundex('hello world!'); SELECT soundex('Anne'), soundex('Ann'), difference('Anne', 'Ann'); @@ -70,7 +71,7 @@ INSERT INTO s VALUES ('jack'); SELECT * FROM s WHERE soundex(nm) = soundex('john'); SELECT * FROM s WHERE difference(s.nm, 'john') > 2; - </programlisting> +</programlisting> </sect2> <sect2> @@ -80,10 +81,12 @@ SELECT * FROM s WHERE difference(s.nm, 'john') > 2; This function calculates the Levenshtein distance between two strings: </para> - <programlisting> - levenshtein(text source, text target, int ins_cost, int del_cost, int sub_cost) returns int - levenshtein(text source, text target) returns int - </programlisting> +<synopsis> +levenshtein(text source, text target, int ins_cost, int del_cost, int sub_cost) returns int +levenshtein(text source, text target) returns int +levenshtein_less_equal(text source, text target, int ins_cost, int del_cost, int sub_cost, int max_d) returns int +levenshtein_less_equal(text source, text target, int max_d) returns int +</synopsis> <para> Both <literal>source</literal> and <literal>target</literal> can be any @@ -91,13 +94,18 @@ SELECT * FROM s WHERE difference(s.nm, 'john') > 2; specify how much to charge for a character insertion, deletion, or substitution, respectively. You can omit the cost parameters, as in the second version of the function; in that case they all default to 1. + <literal>levenshtein_less_equal</literal> is accelerated version of + levenshtein function for low values of distance. If actual distance + is less or equal then max_d, then <literal>levenshtein_less_equal</literal> + returns accurate value of it. Otherwise this function returns value + which is greater than max_d. </para> <para> Examples: </para> - <programlisting> +<screen> test=# SELECT levenshtein('GUMBO', 'GAMBOL'); levenshtein ------------- @@ -109,7 +117,19 @@ test=# SELECT levenshtein('GUMBO', 'GAMBOL', 2,1,1); ------------- 3 (1 row) - </programlisting> + +test=# SELECT levenshtein_less_equal('extensive', 'exhaustive',2); + levenshtein_less_equal +------------------------ + 3 +(1 row) + +test=# SELECT levenshtein_less_equal('extensive', 'exhaustive',4); + levenshtein_less_equal +------------------------ + 4 +(1 row) +</screen> </sect2> <sect2> @@ -125,9 +145,9 @@ test=# SELECT levenshtein('GUMBO', 'GAMBOL', 2,1,1); This function calculates the metaphone code of an input string: </para> - <programlisting> - metaphone(text source, int max_output_length) returns text - </programlisting> +<synopsis> +metaphone(text source, int max_output_length) returns text +</synopsis> <para> <literal>source</literal> has to be a non-null string with a maximum of @@ -140,13 +160,13 @@ test=# SELECT levenshtein('GUMBO', 'GAMBOL', 2,1,1); Example: </para> - <programlisting> +<screen> test=# SELECT metaphone('GUMBO', 4); metaphone ----------- KM (1 row) - </programlisting> +</screen> </sect2> <sect2> @@ -160,10 +180,10 @@ test=# SELECT metaphone('GUMBO', 4); These functions compute the primary and alternate codes: </para> - <programlisting> - dmetaphone(text source) returns text - dmetaphone_alt(text source) returns text - </programlisting> +<synopsis> +dmetaphone(text source) returns text +dmetaphone_alt(text source) returns text +</synopsis> <para> There is no length limit on the input strings. @@ -173,13 +193,13 @@ test=# SELECT metaphone('GUMBO', 4); Example: </para> - <programlisting> +<screen> test=# select dmetaphone('gumbo'); dmetaphone ------------ KMP (1 row) - </programlisting> +</screen> </sect2> </sect1> diff --git a/doc/src/sgml/generate-errcodes-table.pl b/doc/src/sgml/generate-errcodes-table.pl new file mode 100644 index 0000000000..0ac020ee24 --- /dev/null +++ b/doc/src/sgml/generate-errcodes-table.pl @@ -0,0 +1,56 @@ +#!/usr/bin/perl +# +# Generate the errcodes-table.sgml file from errcodes.txt +# Copyright (c) 2000-2011, PostgreSQL Global Development Group + +use warnings; +use strict; + +print "<!-- autogenerated from src/backend/utils/errcodes.txt, do not edit -->\n"; + +open my $errcodes, $ARGV[0] or die; + +while (<$errcodes>) { + chomp; + + # Skip comments + next if /^#/; + next if /^\s*$/; + + # Emit section headers + if (/^Section:/) { + + # Remove the Section: string + s/^Section: //; + # Escape dashes for SGML + s/-/—/; + # Wrap PostgreSQL in <productname/> + s/PostgreSQL/<productname>PostgreSQL<\/>/g; + + print "\n\n"; + print "<row>\n"; + print "<entry spanname=\"span12\">"; + print "<emphasis role=\"bold\">$_</></entry>\n"; + print "</row>\n"; + + next; + } + + die unless /^([^\s]{5})\s+([EWS])\s+([^\s]+)(?:\s+)?([^\s]+)?/; + + (my $sqlstate, + my $type, + my $errcode_macro, + my $condition_name) = ($1, $2, $3, $4); + + # Skip lines without PL/pgSQL condition names + next unless defined($condition_name); + + print "\n"; + print "<row>\n"; + print "<entry><literal>$sqlstate</literal></entry>\n"; + print "<entry><symbol>$condition_name</symbol></entry>\n"; + print "</row>\n"; +} + +close $errcodes; diff --git a/doc/src/sgml/generate_history.pl b/doc/src/sgml/generate_history.pl index 20f3d0e87c..a6c0bd77c2 100644 --- a/doc/src/sgml/generate_history.pl +++ b/doc/src/sgml/generate_history.pl @@ -9,14 +9,14 @@ # in a standalone build of the release notes. To make sure this is done # everywhere, we have to fold in the sub-files of the release notes. # -# $PostgreSQL: pgsql/doc/src/sgml/generate_history.pl,v 1.1 2009/05/02 20:17:19 tgl Exp $ +# doc/src/sgml/generate_history.pl use strict; -my($srcdir) = shift; -defined($srcdir) || die "$0: missing required argument: srcdir\n"; -my($infile) = shift; -defined($infile) || die "$0: missing required argument: inputfile\n"; +my $srcdir = shift; +die "$0: missing required argument: srcdir\n" if !defined($srcdir); +my $infile = shift; +die "$0: missing required argument: inputfile\n" if !defined($infile); # Emit DOCTYPE header so that the output is a self-contained SGML document print "<!DOCTYPE appendix PUBLIC \"-//OASIS//DTD DocBook V4.2//EN\">\n"; @@ -26,11 +26,11 @@ process_file($infile); exit 0; sub process_file { - my($filename) = @_; + my $filename = shift; local *FILE; # need a local filehandle so we can recurse - my($f) = $srcdir . '/' . $filename; + my $f = $srcdir . '/' . $filename; open(FILE, $f) || die "could not read $f: $!\n"; while (<FILE>) { diff --git a/doc/src/sgml/geqo.sgml b/doc/src/sgml/geqo.sgml index 75ebdaa4c9..92276fcd76 100644 --- a/doc/src/sgml/geqo.sgml +++ b/doc/src/sgml/geqo.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/geqo.sgml,v 1.43 2010/04/03 07:22:54 petere Exp $ --> +<!-- doc/src/sgml/geqo.sgml --> <chapter id="geqo"> <chapterinfo> diff --git a/doc/src/sgml/gin.sgml b/doc/src/sgml/gin.sgml index 2241dd5d9a..7b4d9c4e9e 100644 --- a/doc/src/sgml/gin.sgml +++ b/doc/src/sgml/gin.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/gin.sgml,v 2.20 2010/04/03 07:22:54 petere Exp $ --> +<!-- doc/src/sgml/gin.sgml --> <chapter id="GIN"> <title>GIN Indexes</title> @@ -12,17 +12,38 @@ <title>Introduction</title> <para> - <acronym>GIN</acronym> stands for Generalized Inverted Index. It is - an index structure storing a set of (key, posting list) pairs, where - a <quote>posting list</> is a set of rows in which the key occurs. Each - indexed value can contain many keys, so the same row ID can appear in - multiple posting lists. + <acronym>GIN</acronym> stands for Generalized Inverted Index. + <acronym>GIN</acronym> is designed for handling cases where the items + to be indexed are composite values, and the queries to be handled by + the index need to search for element values that appear within + the composite items. For example, the items could be documents, + and the queries could be searches for documents containing specific words. </para> <para> - It is generalized in the sense that a <acronym>GIN</acronym> index - does not need to be aware of the operation that it accelerates. - Instead, it uses custom strategies defined for particular data types. + We use the word <firstterm>item</> to refer to a composite value that + is to be indexed, and the word <firstterm>key</> to refer to an element + value. <acronym>GIN</acronym> always stores and searches for keys, + not item values per se. + </para> + + <para> + A <acronym>GIN</acronym> index stores a set of (key, posting list) pairs, + where a <firstterm>posting list</> is a set of row IDs in which the key + occurs. The same row ID can appear in multiple posting lists, since + an item can contain more than one key. Each key value is stored only + once, so a <acronym>GIN</acronym> index is very compact for cases + where the same key appears many times. + </para> + + <para> + <acronym>GIN</acronym> is generalized in the sense that the + <acronym>GIN</acronym> access method code does not need to know the + specific operations that it accelerates. + Instead, it uses custom strategies defined for particular data types. + The strategy defines how keys are extracted from indexed items and + query conditions, and how to determine whether a row that contains + some of the key values in a query actually satisfies the query. </para> <para> @@ -54,7 +75,7 @@ <para> All it takes to get a <acronym>GIN</acronym> access method working is to implement four (or five) user-defined methods, which define the behavior of - keys in the tree and the relationships between keys, indexed values, + keys in the tree and the relationships between keys, indexed items, and indexable queries. In short, <acronym>GIN</acronym> combines extensibility with generality, code reuse, and a clean interface. </para> @@ -62,51 +83,86 @@ <para> The four methods that an operator class for <acronym>GIN</acronym> must provide are: - </para> <variablelist> <varlistentry> - <term>int compare(Datum a, Datum b)</term> + <term><function>int compare(Datum a, Datum b)</></term> <listitem> <para> - Compares keys (not indexed values!) and returns an integer less than + Compares two keys (not indexed items!) and returns an integer less than zero, zero, or greater than zero, indicating whether the first key is - less than, equal to, or greater than the second. + less than, equal to, or greater than the second. Null keys are never + passed to this function. </para> </listitem> </varlistentry> <varlistentry> - <term>Datum *extractValue(Datum inputValue, int32 *nkeys)</term> + <term><function>Datum *extractValue(Datum itemValue, int32 *nkeys, + bool **nullFlags)</></term> <listitem> <para> - Returns an array of keys given a value to be indexed. The + Returns a palloc'd array of keys given an item to be indexed. The number of returned keys must be stored into <literal>*nkeys</>. + If any of the keys can be null, also palloc an array of + <literal>*nkeys</> booleans, store its address at + <literal>*nullFlags</>, and set these null flags as needed. + <literal>*nullFlags</> can be left NULL (its initial value) + if all keys are non-null. + The return value can be NULL if the item contains no keys. </para> </listitem> </varlistentry> <varlistentry> - <term>Datum *extractQuery(Datum query, int32 *nkeys, - StrategyNumber n, bool **pmatch, Pointer **extra_data)</term> + <term><function>Datum *extractQuery(Datum query, int32 *nkeys, + StrategyNumber n, bool **pmatch, Pointer **extra_data, + bool **nullFlags, int32 *searchMode)</></term> <listitem> <para> - Returns an array of keys given a value to be queried; that is, + Returns a palloc'd array of keys given a value to be queried; that is, <literal>query</> is the value on the right-hand side of an indexable operator whose left-hand side is the indexed column. <literal>n</> is the strategy number of the operator within the operator class (see <xref linkend="xindex-strategies">). Often, <function>extractQuery</> will need to consult <literal>n</> to determine the data type of - <literal>query</> and the key values that need to be extracted. + <literal>query</> and the method it should use to extract key values. The number of returned keys must be stored into <literal>*nkeys</>. - If the query contains no keys then <function>extractQuery</> - should store 0 or -1 into <literal>*nkeys</>, depending on the - semantics of the operator. 0 means that every - value matches the <literal>query</> and a full-index scan should be - performed (but see <xref linkend="gin-limit">). - -1 means that nothing can match the <literal>query</>, and - so the index scan can be skipped entirely. + If any of the keys can be null, also palloc an array of + <literal>*nkeys</> booleans, store its address at + <literal>*nullFlags</>, and set these null flags as needed. + <literal>*nullFlags</> can be left NULL (its initial value) + if all keys are non-null. + The return value can be NULL if the <literal>query</> contains no keys. + </para> + + <para> + <literal>searchMode</> is an output argument that allows + <function>extractQuery</> to specify details about how the search + will be done. + If <literal>*searchMode</> is set to + <literal>GIN_SEARCH_MODE_DEFAULT</> (which is the value it is + initialized to before call), only items that match at least one of + the returned keys are considered candidate matches. + If <literal>*searchMode</> is set to + <literal>GIN_SEARCH_MODE_INCLUDE_EMPTY</>, then in addition to items + containing at least one matching key, items that contain no keys at + all are considered candidate matches. (This mode is useful for + implementing is-subset-of operators, for example.) + If <literal>*searchMode</> is set to <literal>GIN_SEARCH_MODE_ALL</>, + then all non-null items in the index are considered candidate + matches, whether they match any of the returned keys or not. (This + mode is much slower than the other two choices, since it requires + scanning essentially the entire index, but it may be necessary to + implement corner cases correctly. An operator that needs this mode + in most cases is probably not a good candidate for a GIN operator + class.) + The symbols to use for setting this mode are defined in + <filename>access/gin.h</>. + </para> + + <para> <literal>pmatch</> is an output argument for use when partial match is supported. To use it, <function>extractQuery</> must allocate an array of <literal>*nkeys</> booleans and store its address at @@ -116,6 +172,9 @@ is not required. The variable is initialized to NULL before call, so this argument can simply be ignored by operator classes that do not support partial match. + </para> + + <para> <literal>extra_data</> is an output argument that allows <function>extractQuery</> to pass additional data to the <function>consistent</> and <function>comparePartial</> methods. @@ -133,45 +192,67 @@ </varlistentry> <varlistentry> - <term>bool consistent(bool check[], StrategyNumber n, Datum query, - int32 nkeys, Pointer extra_data[], bool *recheck)</term> + <term><function>bool consistent(bool check[], StrategyNumber n, Datum query, + int32 nkeys, Pointer extra_data[], bool *recheck, + Datum queryKeys[], bool nullFlags[])</></term> <listitem> <para> - Returns TRUE if the indexed value satisfies the query operator with - strategy number <literal>n</> (or might satisfy, if the recheck - indication is returned). The <literal>check</> array has length + Returns TRUE if an indexed item satisfies the query operator with + strategy number <literal>n</> (or might satisfy it, if the recheck + indication is returned). This function does not have direct access + to the indexed item's value, since <acronym>GIN</acronym> does not + store items explicitly. Rather, what is available is knowledge + about which key values extracted from the query appear in a given + indexed item. The <literal>check</> array has length <literal>nkeys</>, which is the same as the number of keys previously returned by <function>extractQuery</> for this <literal>query</> datum. Each element of the - <literal>check</> array is TRUE if the indexed value contains the + <literal>check</> array is TRUE if the indexed item contains the corresponding query key, ie, if (check[i] == TRUE) the i-th key of the - <function>extractQuery</> result array is present in the indexed value. - The original <literal>query</> datum (not the extracted key array!) is - passed in case the <function>consistent</> method needs to consult it. + <function>extractQuery</> result array is present in the indexed item. + The original <literal>query</> datum is + passed in case the <function>consistent</> method needs to consult it, + and so are the <literal>queryKeys[]</> and <literal>nullFlags[]</> + arrays previously returned by <function>extractQuery</>. <literal>extra_data</> is the extra-data array returned by <function>extractQuery</>, or NULL if none. + </para> + + <para> + When <function>extractQuery</> returns a null key in + <literal>queryKeys[]</>, the corresponding <literal>check[]</> element + is TRUE if the indexed item contains a null key; that is, the + semantics of <literal>check[]</> are like <literal>IS NOT DISTINCT + FROM</>. The <function>consistent</> function can examine the + corresponding <literal>nullFlags[]</> element if it needs to tell + the difference between a regular value match and a null match. + </para> + + <para> On success, <literal>*recheck</> should be set to TRUE if the heap tuple needs to be rechecked against the query operator, or FALSE if - the index test is exact. + the index test is exact. That is, a FALSE return value guarantees + that the heap tuple does not match the query; a TRUE return value with + <literal>*recheck</> set to FALSE guarantees that the heap tuple does + match the query; and a TRUE return value with + <literal>*recheck</> set to TRUE means that the heap tuple might match + the query, so it needs to be fetched and rechecked by evaluating the + query operator directly against the originally indexed item. </para> </listitem> </varlistentry> - </variablelist> - <para> Optionally, an operator class for <acronym>GIN</acronym> can supply a fifth method: - </para> <variablelist> - <varlistentry> - <term>int comparePartial(Datum partial_key, Datum key, StrategyNumber n, - Pointer extra_data)</term> + <term><function>int comparePartial(Datum partial_key, Datum key, StrategyNumber n, + Pointer extra_data)</></term> <listitem> <para> - Compare a partial-match query to an index key. Returns an integer + Compare a partial-match query key to an index key. Returns an integer whose sign indicates the result: less than zero means the index key does not match the query, but the index scan should continue; zero means that the index key does match the query; greater than zero @@ -181,11 +262,12 @@ semantics are needed to determine when to end the scan. Also, <literal>extra_data</> is the corresponding element of the extra-data array made by <function>extractQuery</>, or NULL if none. + Null keys are never passed to this function. </para> </listitem> </varlistentry> - </variablelist> + </para> <para> To support <quote>partial match</> queries, an operator class must @@ -195,6 +277,18 @@ <xref linkend="gin-partial-match"> for details. </para> + <para> + The actual data types of the various <literal>Datum</> values mentioned + above vary depending on the operator class. The item values passed to + <function>extractValue</> are always of the operator class's input type, and + all key values must be of the class's <literal>STORAGE</> type. The type of + the <literal>query</> argument passed to <function>extractQuery</> and + <function>consistent</> is whatever is specified as the right-hand input + type of the class member operator identified by the strategy number. + This need not be the same as the item type, so long as key values of the + correct type can be extracted from it. + </para> + </sect1> <sect1 id="gin-implementation"> @@ -202,20 +296,36 @@ <para> Internally, a <acronym>GIN</acronym> index contains a B-tree index - constructed over keys, where each key is an element of the indexed value - (a member of an array, for example) and where each tuple in a leaf page is - either a pointer to a B-tree over heap pointers (PT, posting tree), or a - list of heap pointers (PL, posting list) if the list is small enough. + constructed over keys, where each key is an element of one or more indexed + items (a member of an array, for example) and where each tuple in a leaf + page contains either a pointer to a B-tree of heap pointers (a + <quote>posting tree</>), or a simple list of heap pointers (a <quote>posting + list</>) when the list is small enough to fit into a single index tuple along + with the key value. + </para> + + <para> + As of <productname>PostgreSQL</productname> 9.1, NULL key values can be + included in the index. Also, placeholder NULLs are included in the index + for indexed items that are NULL or contain no keys according to + <function>extractValue</>. This allows searches that should find empty + items to do so. + </para> + + <para> + Multi-column <acronym>GIN</acronym> indexes are implemented by building + a single B-tree over composite values (column number, key value). The + key values for different columns can be of different types. </para> <sect2 id="gin-fast-update"> - <title>GIN fast update technique</title> + <title>GIN Fast Update Technique</title> <para> Updating a <acronym>GIN</acronym> index tends to be slow because of the intrinsic nature of inverted indexes: inserting or updating one heap row can cause many inserts into the index (one for each key extracted - from the indexed value). As of <productname>PostgreSQL</productname> 8.4, + from the indexed item). As of <productname>PostgreSQL</productname> 8.4, <acronym>GIN</> is capable of postponing much of this work by inserting new tuples into a temporary, unsorted list of pending entries. When the table is vacuumed, or if the pending list becomes too large @@ -223,7 +333,7 @@ main <acronym>GIN</acronym> data structure using the same bulk insert techniques used during initial index creation. This greatly improves <acronym>GIN</acronym> index update speed, even counting the additional - vacuum overhead. Moreover the overhead can be done by a background + vacuum overhead. Moreover the overhead work can be done by a background process instead of in foreground query processing. </para> @@ -247,7 +357,7 @@ </sect2> <sect2 id="gin-partial-match"> - <title>Partial match algorithm</title> + <title>Partial Match Algorithm</title> <para> GIN can support <quote>partial match</> queries, in which the query @@ -257,9 +367,9 @@ The <function>extractQuery</> method, instead of returning a key value to be matched exactly, returns a key value that is the lower bound of the range to be searched, and sets the <literal>pmatch</> flag true. - The key range is then searched using the <function>comparePartial</> - method. <function>comparePartial</> must return zero for an actual - match, less than zero for a non-match that is still within the range + The key range is then scanned using the <function>comparePartial</> + method. <function>comparePartial</> must return zero for a matching + index key, less than zero for a non-match that is still within the range to be searched, or greater than zero if the index key is past the range that could match. </para> @@ -268,15 +378,15 @@ </sect1> <sect1 id="gin-tips"> -<title>GIN tips and tricks</title> +<title>GIN Tips and Tricks</title> <variablelist> <varlistentry> - <term>Create vs insert</term> + <term>Create vs. insert</term> <listitem> <para> Insertion into a <acronym>GIN</acronym> index can be slow - due to the likelihood of many keys being inserted for each value. + due to the likelihood of many keys being inserted for each item. So, for bulk insertions into a table it is advisable to drop the GIN index and recreate it after finishing bulk insertion. </para> @@ -307,7 +417,7 @@ <para> During a series of insertions into an existing <acronym>GIN</acronym> index that has <literal>FASTUPDATE</> enabled, the system will clean up - the pending-entry list whenever it grows larger than + the pending-entry list whenever the list grows larger than <varname>work_mem</>. To avoid fluctuations in observed response time, it's desirable to have pending-list cleanup occur in the background (i.e., via autovacuum). Foreground cleanup operations can be avoided by @@ -323,7 +433,7 @@ <listitem> <para> The primary goal of developing <acronym>GIN</acronym> indexes was - to create support for highly scalable, full-text search in + to create support for highly scalable full-text search in <productname>PostgreSQL</productname>, and there are often situations when a full-text search returns a very large set of results. Moreover, this often happens when the query contains very frequent words, so that the @@ -333,9 +443,9 @@ fast.) </para> <para> - To facilitate controlled execution of such queries + To facilitate controlled execution of such queries, <acronym>GIN</acronym> has a configurable soft upper limit on the - number of rows returned, the + number of rows returned: the <varname>gin_fuzzy_search_limit</varname> configuration parameter. It is set to 0 (meaning no limit) by default. If a non-zero limit is set, then the returned set is a subset of @@ -343,9 +453,13 @@ </para> <para> <quote>Soft</quote> means that the actual number of returned results - could differ slightly from the specified limit, depending on the query + could differ somewhat from the specified limit, depending on the query and the quality of the system's random number generator. </para> + <para> + From experience, values in the thousands (e.g., 5000 — 20000) + work well. + </para> </listitem> </varlistentry> </variablelist> @@ -356,44 +470,13 @@ <title>Limitations</title> <para> - <acronym>GIN</acronym> doesn't support full index scans. The reason for - this is that <function>extractValue</> is allowed to return zero keys, - as for example might happen with an empty string or empty array. In such - a case the indexed value will be unrepresented in the index. It is - therefore impossible for <acronym>GIN</acronym> to guarantee that a - scan of the index can find every row in the table. - </para> - - <para> - Because of this limitation, when <function>extractQuery</function> returns - <literal>nkeys = 0</> to indicate that all values match the query, - <acronym>GIN</acronym> will emit an error. (If there are multiple ANDed - indexable operators in the query, this happens only if they all return zero - for <literal>nkeys</>.) - </para> - - <para> - It is possible for an operator class to circumvent the restriction against - full index scan. To do that, <function>extractValue</> must return at least - one (possibly dummy) key for every indexed value, and - <function>extractQuery</function> must convert an unrestricted search into - a partial-match query that will scan the whole index. This is inefficient - but might be necessary to avoid corner-case failures with operators such - as <literal>LIKE</> or subset inclusion. - </para> - - <para> - <acronym>GIN</acronym> assumes that indexable operators are strict. - This means that <function>extractValue</> will not be called at all on - a NULL value (so the value will go unindexed), and - <function>extractQuery</function> will not be called on a NULL comparison - value either (instead, the query is presumed to be unmatchable). - </para> - - <para> - A possibly more serious limitation is that <acronym>GIN</acronym> cannot - handle NULL keys — for example, an array containing a NULL cannot - be handled except by ignoring the NULL. + <acronym>GIN</acronym> assumes that indexable operators are strict. This + means that <function>extractValue</> will not be called at all on a NULL + item value (instead, a placeholder index entry is created automatically), + and <function>extractQuery</function> will not be called on a NULL query + value either (instead, the query is presumed to be unsatisfiable). Note + however that NULL key values contained within a non-null composite item + or query value are supported. </para> </sect1> @@ -408,37 +491,37 @@ feature. The following <filename>contrib</> modules also contain <acronym>GIN</acronym> operator classes: - </para> <variablelist> <varlistentry> - <term>btree-gin</term> + <term><filename>btree_gin</></term> <listitem> - <para>B-Tree equivalent functionality for several data types</para> + <para>B-tree equivalent functionality for several data types</para> </listitem> </varlistentry> <varlistentry> - <term>hstore</term> + <term><filename>hstore</></term> <listitem> <para>Module for storing (key, value) pairs</para> </listitem> </varlistentry> <varlistentry> - <term>intarray</term> + <term><filename>intarray</></term> <listitem> - <para>Enhanced support for int4[]</para> + <para>Enhanced support for <type>int[]</type></para> </listitem> </varlistentry> <varlistentry> - <term>pg_trgm</term> + <term><filename>pg_trgm</></term> <listitem> <para>Text similarity using trigram matching</para> </listitem> </varlistentry> </variablelist> + </para> </sect1> </chapter> diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml index eddaaad5df..78171cfa3f 100644 --- a/doc/src/sgml/gist.sgml +++ b/doc/src/sgml/gist.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.31 2009/06/12 19:48:53 tgl Exp $ --> +<!-- doc/src/sgml/gist.sgml --> <chapter id="GiST"> <title>GiST Indexes</title> @@ -78,7 +78,7 @@ <para> All it takes to get a <acronym>GiST</acronym> access method up and running - is to implement seven user-defined methods, which define the behavior of + is to implement several user-defined methods, which define the behavior of keys in the tree. Of course these methods have to be pretty fancy to support fancy queries, but for all the standard queries (B-trees, R-trees, etc.) they're relatively straightforward. In short, @@ -93,19 +93,23 @@ <para> There are seven methods that an index operator class for - <acronym>GiST</acronym> must provide. Correctness of the index is ensured + <acronym>GiST</acronym> must provide, and an eighth that is optional. + Correctness of the index is ensured by proper implementation of the <function>same</>, <function>consistent</> and <function>union</> methods, while efficiency (size and speed) of the index will depend on the <function>penalty</> and <function>picksplit</> methods. - The remaining two methods are <function>compress</> and + The remaining two basic methods are <function>compress</> and <function>decompress</>, which allow an index to have internal tree data of a different type than the data it indexes. The leaves are to be of the indexed data type, while the other tree nodes can be of any C struct (but - you still have to follow <productname>PostgreSQL</> datatype rules here, + you still have to follow <productname>PostgreSQL</> data type rules here, see about <literal>varlena</> for variable sized data). If the tree's internal data type exists at the SQL level, the <literal>STORAGE</> option of the <command>CREATE OPERATOR CLASS</> command can be used. + The optional eighth method is <function>distance</>, which is needed + if the operator class wishes to support ordered scans (nearest-neighbor + searches). </para> <variablelist> @@ -374,6 +378,8 @@ my_decompress(PG_FUNCTION_ARGS) Returns a value indicating the <quote>cost</quote> of inserting the new entry into a particular branch of the tree. Items will be inserted down the path of least <function>penalty</function> in the tree. + Values returned by <function>penalty</function> should be non-negative. + If a negative value is returned, it will be treated as zero. </para> <para> @@ -561,12 +567,79 @@ my_same(PG_FUNCTION_ARGS) </programlisting> For historical reasons, the <function>same</> function doesn't - just return a boolean result; instead it has to store the flag + just return a Boolean result; instead it has to store the flag at the location indicated by the third argument. </para> </listitem> </varlistentry> + <varlistentry> + <term><function>distance</></term> + <listitem> + <para> + Given an index entry <literal>p</> and a query value <literal>q</>, + this function determines the index entry's + <quote>distance</> from the query value. This function must be + supplied if the operator class contains any ordering operators. + A query using the ordering operator will be implemented by returning + index entries with the smallest <quote>distance</> values first, + so the results must be consistent with the operator's semantics. + For a leaf index entry the result just represents the distance to + the index entry; for an internal tree node, the result must be the + smallest distance that any child entry could have. + </para> + + <para> + The <acronym>SQL</> declaration of the function must look like this: + +<programlisting> +CREATE OR REPLACE FUNCTION my_distance(internal, data_type, smallint, oid) +RETURNS float8 +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT; +</programlisting> + + And the matching code in the C module could then follow this skeleton: + +<programlisting> +Datum my_distance(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(my_distance); + +Datum +my_distance(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + data_type *query = PG_GETARG_DATA_TYPE_P(1); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + /* Oid subtype = PG_GETARG_OID(3); */ + data_type *key = DatumGetDataType(entry->key); + double retval; + + /* + * determine return value as a function of strategy, key and query. + */ + + PG_RETURN_FLOAT8(retval); +} +</programlisting> + + The arguments to the <function>distance</> function are identical to + the arguments of the <function>consistent</> function, except that no + recheck flag is used. The distance to a leaf index entry must always + be determined exactly, since there is no way to re-order the tuples + once they are returned. Some approximation is allowed when determining + the distance to an internal tree node, so long as the result is never + greater than any child's actual distance. Thus, for example, distance + to a bounding box is usually sufficient in geometric applications. The + result value can be any finite <type>float8</> value. (Infinity and + minus infinity are used internally to handle cases such as nulls, so it + is not recommended that <function>distance</> functions return these + values.) + </para> + + </listitem> + </varlistentry> + </variablelist> </sect1> @@ -583,88 +656,59 @@ my_same(PG_FUNCTION_ARGS) (see <filename>src/backend/access/gist/gistproc.c</>). The following <filename>contrib</> modules also contain <acronym>GiST</acronym> operator classes: - </para> <variablelist> <varlistentry> - <term>btree_gist</term> + <term><filename>btree_gist</></term> <listitem> - <para>B-Tree equivalent functionality for several data types</para> + <para>B-tree equivalent functionality for several data types</para> </listitem> </varlistentry> <varlistentry> - <term>cube</term> + <term><filename>cube</></term> <listitem> <para>Indexing for multidimensional cubes</para> </listitem> </varlistentry> <varlistentry> - <term>hstore</term> + <term><filename>hstore</></term> <listitem> <para>Module for storing (key, value) pairs</para> </listitem> </varlistentry> <varlistentry> - <term>intarray</term> + <term><filename>intarray</></term> <listitem> <para>RD-Tree for one-dimensional array of int4 values</para> </listitem> </varlistentry> <varlistentry> - <term>ltree</term> + <term><filename>ltree</></term> <listitem> <para>Indexing for tree-like structures</para> </listitem> </varlistentry> <varlistentry> - <term>pg_trgm</term> + <term><filename>pg_trgm</></term> <listitem> <para>Text similarity using trigram matching</para> </listitem> </varlistentry> <varlistentry> - <term>seg</term> + <term><filename>seg</></term> <listitem> <para>Indexing for <quote>float ranges</quote></para> </listitem> </varlistentry> </variablelist> - -</sect1> - -<sect1 id="gist-recovery"> - <title>Crash Recovery</title> - - <para> - Usually, replay of the WAL log is sufficient to restore the integrity - of a GiST index following a database crash. However, there are some - corner cases in which the index state is not fully rebuilt. The index - will still be functionally correct, but there might be some performance - degradation. When this occurs, the index can be repaired by - <command>VACUUM</>ing its table, or by rebuilding the index using - <command>REINDEX</>. In some cases a plain <command>VACUUM</> is - not sufficient, and either <command>VACUUM FULL</> or <command>REINDEX</> - is needed. The need for one of these procedures is indicated by occurrence - of this log message during crash recovery: -<programlisting> -LOG: index NNN/NNN/NNN needs VACUUM or REINDEX to finish crash recovery -</programlisting> - or this log message during routine index insertions: -<programlisting> -LOG: index "FOO" needs VACUUM or REINDEX to finish crash recovery -</programlisting> - If a plain <command>VACUUM</> finds itself unable to complete recovery - fully, it will return a notice: -<programlisting> -NOTICE: index "FOO" needs VACUUM FULL or REINDEX to finish crash recovery -</programlisting> </para> + </sect1> </chapter> diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml index 857fcfea00..80665a5cb2 100644 --- a/doc/src/sgml/high-availability.sgml +++ b/doc/src/sgml/high-availability.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/high-availability.sgml,v 1.77 2010/07/03 20:43:57 tgl Exp $ --> +<!-- doc/src/sgml/high-availability.sgml --> <chapter id="high-availability"> <title>High Availability, Load Balancing, and Replication</title> @@ -82,7 +82,7 @@ </para> <sect1 id="different-replication-solutions"> - <title>Comparison of different solutions</title> + <title>Comparison of Different Solutions</title> <variablelist> @@ -188,9 +188,10 @@ protocol to make nodes agree on a serializable transactional order. <para> With statement-based replication middleware, a program intercepts every SQL query and sends it to one or all servers. Each server - operates independently. Read-write queries are sent to all servers, - while read-only queries can be sent to just one server, allowing - the read workload to be distributed. + operates independently. Read-write queries must be sent to all servers, + so that every server receives any changes. But read-only queries can be + sent to just one server, allowing the read workload to be distributed + among them. </para> <para> @@ -209,8 +210,8 @@ protocol to make nodes agree on a serializable transactional order. transactions either commit or abort on all servers, perhaps using two-phase commit (<xref linkend="sql-prepare-transaction"> and <xref linkend="sql-commit-prepared">. - <productname>Pgpool-II</> and <productname>Sequoia</> are examples of - this type of replication. + <productname>Pgpool-II</> and <productname>Continuent Tungsten</> + are examples of this type of replication. </para> </listitem> </varlistentry> @@ -449,7 +450,7 @@ protocol to make nodes agree on a serializable transactional order. part of the query and return results to a central server where they are combined and returned to the user. <productname>Pgpool-II</> has this capability. Also, this can be implemented using the - <productname>PL/Proxy</> toolset. + <productname>PL/Proxy</> tool set. </para> </listitem> @@ -486,18 +487,19 @@ protocol to make nodes agree on a serializable transactional order. <para> Directly moving WAL records from one database server to another is typically described as log shipping. <productname>PostgreSQL</> - implements file-based log shipping, which means that WAL records are - transferred one file (WAL segment) at a time. WAL files (16MB) can be + implements file-based log shipping by transferring WAL records + one file (WAL segment) at a time. WAL files (16MB) can be shipped easily and cheaply over any distance, whether it be to an adjacent system, another system at the same site, or another system on the far side of the globe. The bandwidth required for this technique varies according to the transaction rate of the primary server. - Record-based log shipping is also possible with streaming replication - (see <xref linkend="streaming-replication">). + Record-based log shipping is more granular and streams WAL changes + incrementally over a network connection (see <xref + linkend="streaming-replication">). </para> <para> - It should be noted that the log shipping is asynchronous, i.e., the WAL + It should be noted that log shipping is asynchronous, i.e., the WAL records are shipped after transaction commit. As a result, there is a window for data loss should the primary server suffer a catastrophic failure; transactions not yet shipped will be lost. The size of the @@ -505,8 +507,8 @@ protocol to make nodes agree on a serializable transactional order. <varname>archive_timeout</varname> parameter, which can be set as low as a few seconds. However such a low setting will substantially increase the bandwidth required for file shipping. - If you need a window of less than a minute or so, consider using - streaming replication (see <xref linkend="streaming-replication">). + Streaming replication (see <xref linkend="streaming-replication">) + allows a much smaller window of data loss. </para> <para> @@ -589,7 +591,7 @@ protocol to make nodes agree on a serializable transactional order. <para> In standby mode, the server continuously applies WAL received from the master server. The standby server can read WAL from a WAL archive - (see <varname>restore_command</>) or directly from the master + (see <xref linkend="restore-command">) or directly from the master over a TCP connection (streaming replication). The standby server will also attempt to restore any WAL found in the standby cluster's <filename>pg_xlog</> directory. That typically happens after a server @@ -602,21 +604,22 @@ protocol to make nodes agree on a serializable transactional order. At startup, the standby begins by restoring all WAL available in the archive location, calling <varname>restore_command</>. Once it reaches the end of WAL available there and <varname>restore_command</> - fails, it tries to restore any WAL available in the pg_xlog directory. + fails, it tries to restore any WAL available in the <filename>pg_xlog</> directory. If that fails, and streaming replication has been configured, the standby tries to connect to the primary server and start streaming WAL - from the last valid record found in archive or pg_xlog. If that fails + from the last valid record found in archive or <filename>pg_xlog</>. If that fails or streaming replication is not configured, or if the connection is later disconnected, the standby goes back to step 1 and tries to restore the file from the archive again. This loop of retries from the - archive, pg_xlog, and via streaming replication goes on until the server + archive, <filename>pg_xlog</>, and via streaming replication goes on until the server is stopped or failover is triggered by a trigger file. </para> <para> - Standby mode is exited and the server switches to normal operation, - when a trigger file is found (<varname>trigger_file</>). Before failover, - any WAL immediately available in the archive or in pg_xlog will be + Standby mode is exited and the server switches to normal operation + when <command>pg_ctl promote</> is run or a trigger file is found + (<varname>trigger_file</>). Before failover, + any WAL immediately available in the archive or in <filename>pg_xlog</> will be restored, but no attempt is made to connect to the master. </para> </sect2> @@ -636,8 +639,8 @@ protocol to make nodes agree on a serializable transactional order. <para> If you want to use streaming replication, set up authentication on the primary server to allow replication connections from the standby - server(s); that is, provide a suitable entry or entries in - <filename>pg_hba.conf</> with the database field set to + server(s); that is, create a role and provide a suitable entry or + entries in <filename>pg_hba.conf</> with the database field set to <literal>replication</>. Also ensure <varname>max_wal_senders</> is set to a sufficiently large value in the configuration file of the primary server. @@ -658,7 +661,10 @@ protocol to make nodes agree on a serializable transactional order. command file <filename>recovery.conf</> in the standby's cluster data directory, and turn on <varname>standby_mode</>. Set <varname>restore_command</> to a simple command to copy files from - the WAL archive. + the WAL archive. If you plan to have multiple standby servers for high + availability purposes, set <varname>recovery_target_timeline</> to + <literal>latest</>, to make the standby server follow the timeline change + that occurs at failover to another standby. </para> <note> @@ -681,19 +687,22 @@ protocol to make nodes agree on a serializable transactional order. </para> <para> - You can use <varname>archive_cleanup_command</> to prune the archive of - files no longer needed by the standby. - </para> - - <para> If you're setting up the standby server for high availability purposes, set up WAL archiving, connections and authentication like the primary server, because the standby server will work as a primary server after - failover. You will also need to set <varname>trigger_file</> to make - it possible to fail over. - If you're setting up the standby server for reporting - purposes, with no plans to fail over to it, <varname>trigger_file</> - is not required. + failover. + </para> + + <para> + If you're using a WAL archive, its size can be minimized using the <xref + linkend="archive-cleanup-command"> parameter to remove files that are no + longer required by the standby server. + The <application>pg_archivecleanup</> utility is designed specifically to + be used with <varname>archive_cleanup_command</> in typical single-standby + configurations, see <xref linkend="pgarchivecleanup">. + Note however, that if you're using the archive for backup purposes, you + need to retain files needed to recover from at least the latest base + backup, even if they're no longer needed by the standby. </para> <para> @@ -702,7 +711,7 @@ protocol to make nodes agree on a serializable transactional order. standby_mode = 'on' primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass' restore_command = 'cp /path/to/archive/%f %p' -trigger_file = '/path/to/trigger_file' +archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r' </programlisting> </para> @@ -712,14 +721,6 @@ trigger_file = '/path/to/trigger_file' the primary to allow them to be connected simultaneously. </para> - <para> - If you're using a WAL archive, its size can be minimized using - the <varname>archive_cleanup_command</> option to remove files that are - no longer required by the standby server. Note however, that if you're - using the archive for backup purposes, you need to retain files needed - to recover from at least the latest base backup, even if they're no - longer needed by the standby. - </para> </sect2> <sect2 id="streaming-replication"> @@ -753,7 +754,7 @@ trigger_file = '/path/to/trigger_file' too early, while the standby might still need them to catch up. If the standby falls behind too much, it needs to be reinitialized from a new base backup. If you set up a WAL archive that's accessible from the - standby, wal_keep_segments is not required as the standby can always + standby, <varname>wal_keep_segments</> is not required as the standby can always use the archive to catch up. </para> @@ -796,15 +797,28 @@ trigger_file = '/path/to/trigger_file' It is very important that the access privileges for replication be set up so that only trusted users can read the WAL stream, because it is easy to extract privileged information from it. Standby servers must - authenticate to the primary as a superuser account. - So a role with the <literal>SUPERUSER</> and <literal>LOGIN</> - privileges needs to be created on the primary. + authenticate to the primary as an account that has the + <literal>REPLICATION</> privilege. So a role with the + <literal>REPLICATION</> and <literal>LOGIN</> privileges needs to be + created on the primary. </para> + + <note> + <para> + It is recommended that a dedicated user account is used for replication. + While the <literal>REPLICATION</> privilege is granted to superuser + accounts by default, it is not recommended to use superuser accounts + for replication. While <literal>REPLICATION</> privilege gives very high + permissions, it does not allow the user to modify any data on the + primary system, which the <literal>SUPERUSER</> privilege does. + </para> + </note> + <para> Client authentication for replication is controlled by a <filename>pg_hba.conf</> record specifying <literal>replication</> in the <replaceable>database</> field. For example, if the standby is running on - host IP <literal>192.168.1.100</> and the superuser's name for replication + host IP <literal>192.168.1.100</> and the account name for replication is <literal>foo</>, the administrator can add the following line to the <filename>pg_hba.conf</> file on the primary: @@ -812,7 +826,7 @@ trigger_file = '/path/to/trigger_file' # Allow the user "foo" from host 192.168.1.100 to connect to the primary # as a replication standby if the user's password is correctly supplied. # -# TYPE DATABASE USER CIDR-ADDRESS METHOD +# TYPE DATABASE USER ADDRESS METHOD host replication foo 192.168.1.100/32 md5 </programlisting> </para> @@ -823,7 +837,7 @@ host replication foo 192.168.1.100/32 md5 standby (specify <literal>replication</> in the <replaceable>database</> field). For example, if the primary is running on host IP <literal>192.168.1.50</>, - port <literal>5432</literal>, the superuser's name for replication is + port <literal>5432</literal>, the account name for replication is <literal>foo</>, and the password is <literal>foopass</>, the administrator can add the following line to the <filename>recovery.conf</> file on the standby: @@ -852,9 +866,212 @@ primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass' process status of the WAL receiver process, displayed using the <command>ps</> command (see <xref linkend="monitoring-ps"> for details). </para> + <para> + You can retrieve a list of WAL sender processes via the + <link linkend="monitoring-stats-views-table"> + <literal>pg_stat_replication</></link> view. Large differences between + <function>pg_current_xlog_location</> and <literal>sent_location</> field + might indicate that the master server is under heavy load, while + differences between <literal>sent_location</> and + <function>pg_last_xlog_receive_location</> on the standby might indicate + network delay, or that the standby is under heavy load. + </para> </sect3> </sect2> + <sect2 id="synchronous-replication"> + <title>Synchronous Replication</title> + + <indexterm zone="high-availability"> + <primary>Synchronous Replication</primary> + </indexterm> + + <para> + <productname>PostgreSQL</> streaming replication is asynchronous by + default. If the primary server + crashes then some transactions that were committed may not have been + replicated to the standby server, causing data loss. The amount + of data loss is proportional to the replication delay at the time of + failover. + </para> + + <para> + Synchronous replication offers the ability to confirm that all changes + made by a transaction have been transferred to one synchronous standby + server. This extends the standard level of durability + offered by a transaction commit. This level of protection is referred + to as 2-safe replication in computer science theory. + </para> + + <para> + When requesting synchronous replication, each commit of a + write transaction will wait until confirmation is + received that the commit has been written to the transaction log on disk + of both the primary and standby server. The only possibility that data + can be lost is if both the primary and the standby suffer crashes at the + same time. This can provide a much higher level of durability, though only + if the sysadmin is cautious about the placement and management of the two + servers. Waiting for confirmation increases the user's confidence that the + changes will not be lost in the event of server crashes but it also + necessarily increases the response time for the requesting transaction. + The minimum wait time is the roundtrip time between primary to standby. + </para> + + <para> + Read only transactions and transaction rollbacks need not wait for + replies from standby servers. Subtransaction commits do not wait for + responses from standby servers, only top-level commits. Long + running actions such as data loading or index building do not wait + until the very final commit message. All two-phase commit actions + require commit waits, including both prepare and commit. + </para> + + <sect3 id="synchronous-replication-config"> + <title>Basic Configuration</title> + + <para> + Once streaming replication has been configured, configuring synchronous + replication requires only one additional configuration step: + <xref linkend="guc-synchronous-standby-names"> must be set to + a non-empty value. <varname>synchronous_commit</> must also be set to + <literal>on</>, but since this is the default value, typically no change is + required. This configuration will cause each commit to wait for + confirmation that the standby has written the commit record to durable + storage, even if that takes a very long time. + <varname>synchronous_commit</> can be set by individual + users, so can be configured in the configuration file, for particular + users or databases, or dynamically by applications, in order to control + the durability guarantee on a per-transaction basis. + </para> + + <para> + After a commit record has been written to disk on the primary, the + WAL record is then sent to the standby. The standby sends reply + messages each time a new batch of WAL data is written to disk, unless + <varname>wal_receiver_status_interval</> is set to zero on the standby. + If the standby is the first matching standby, as specified in + <varname>synchronous_standby_names</> on the primary, the reply + messages from that standby will be used to wake users waiting for + confirmation that the commit record has been received. These parameters + allow the administrator to specify which standby servers should be + synchronous standbys. Note that the configuration of synchronous + replication is mainly on the master. + </para> + + <para> + Users will stop waiting if a fast shutdown is requested. However, as + when using asynchronous replication, the server will does not fully + shutdown until all outstanding WAL records are transferred to the currently + connected standby servers. + </para> + + </sect3> + + <sect3 id="synchronous-replication-performance"> + <title>Planning for Performance</title> + + <para> + Synchronous replication usually requires carefully planned and placed + standby servers to ensure applications perform acceptably. Waiting + doesn't utilise system resources, but transaction locks continue to be + held until the transfer is confirmed. As a result, incautious use of + synchronous replication will reduce performance for database + applications because of increased response times and higher contention. + </para> + + <para> + <productname>PostgreSQL</> allows the application developer + to specify the durability level required via replication. This can be + specified for the system overall, though it can also be specified for + specific users or connections, or even individual transactions. + </para> + + <para> + For example, an application workload might consist of: + 10% of changes are important customer details, while + 90% of changes are less important data that the business can more + easily survive if it is lost, such as chat messages between users. + </para> + + <para> + With synchronous replication options specified at the application level + (on the primary) we can offer synchronous replication for the most + important changes, without slowing down the bulk of the total workload. + Application level options are an important and practical tool for allowing + the benefits of synchronous replication for high performance applications. + </para> + + <para> + You should consider that the network bandwidth must be higher than + the rate of generation of WAL data. + </para> + + </sect3> + + <sect3 id="synchronous-replication-ha"> + <title>Planning for High Availability</title> + + <para> + Commits made when <varname>synchronous_commit</> is set to <literal>on</> + will wait until the sync standby responds. The response may never occur + if the last, or only, standby should crash. + </para> + + <para> + The best solution for avoiding data loss is to ensure you don't lose + your last remaining sync standby. This can be achieved by naming multiple + potential synchronous standbys using <varname>synchronous_standby_names</>. + The first named standby will be used as the synchronous standby. Standbys + listed after this will take over the role of synchronous standby if the + first one should fail. + </para> + + <para> + When a standby first attaches to the primary, it will not yet be properly + synchronized. This is described as <literal>CATCHUP</> mode. Once + the lag between standby and primary reaches zero for the first time + we move to real-time <literal>STREAMING</> state. + The catch-up duration may be long immediately after the standby has + been created. If the standby is shut down, then the catch-up period + will increase according to the length of time the standby has been down. + The standby is only able to become a synchronous standby + once it has reached <literal>STREAMING</> state. + </para> + + <para> + If primary restarts while commits are waiting for acknowledgement, those + waiting transactions will be marked fully committed once the primary + database recovers. + There is no way to be certain that all standbys have received all + outstanding WAL data at time of the crash of the primary. Some + transactions may not show as committed on the standby, even though + they show as committed on the primary. The guarantee we offer is that + the application will not receive explicit acknowledgement of the + successful commit of a transaction until the WAL data is known to be + safely received by the standby. + </para> + + <para> + If you really do lose your last standby server then you should disable + <varname>synchronous_standby_names</> and reload the configuration file + on the primary server. + </para> + + <para> + If the primary is isolated from remaining standby servers you should + fail over to the best candidate of those other remaining standby servers. + </para> + + <para> + If you need to re-create a standby server while transactions are + waiting, make sure that the commands to run pg_start_backup() and + pg_stop_backup() are run in a session with + <varname>synchronous_commit</> = <literal>off</>, otherwise those + requests will wait forever for the standby to appear. + </para> + + </sect3> + </sect2> </sect1> <sect1 id="warm-standby-failover"> @@ -907,7 +1124,7 @@ primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass' and might stay down. To return to normal operation, a standby server must be recreated, either on the former primary system when it comes up, or on a third, - possibly new, system. Once complete the primary and standby can be + possibly new, system. Once complete, the primary and standby can be considered to have switched roles. Some people choose to use a third server to provide backup for the new primary until the new standby server is recreated, @@ -925,26 +1142,27 @@ primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass' </para> <para> - To trigger failover of a log-shipping standby server, create a trigger - file with the filename and path specified by the <varname>trigger_file</> - setting in <filename>recovery.conf</>. If <varname>trigger_file</> is - not given, there is no way to exit recovery in the standby and promote - it to a master. That can be useful for e.g reporting servers that are + To trigger failover of a log-shipping standby server, + run <command>pg_ctl promote</> or create a trigger + file with the file name and path specified by the <varname>trigger_file</> + setting in <filename>recovery.conf</>. If you're planning to use + <command>pg_ctl promote</> to fail over, <varname>trigger_file</> is + not required. If you're setting up the reporting servers that are only used to offload read-only queries from the primary, not for high - availability purposes. + availability purposes, you don't need to promote it. </para> </sect1> <sect1 id="log-shipping-alternative"> - <title>Alternative method for log shipping</title> + <title>Alternative Method for Log Shipping</title> <para> An alternative to the built-in standby mode described in the previous sections is to use a <varname>restore_command</> that polls the archive location. This was the only option available in versions 8.4 and below. In this setup, set <varname>standby_mode</> off, because you are implementing - the polling required for standby operation yourself. See - contrib/pg_standby (<xref linkend="pgstandby">) for a reference + the polling required for standby operation yourself. See the + <xref linkend="pgstandby"> module for a reference implementation of this. </para> @@ -1004,7 +1222,7 @@ if (!triggered) <para> A working example of a waiting <varname>restore_command</> is provided - as a <filename>contrib</> module named <application>pg_standby</>. It + in the <xref linkend="pgstandby"> module. It should be used as a reference on how to correctly implement the logic described above. It can also be extended as needed to support specific configurations and environments. @@ -1353,7 +1571,7 @@ if (!triggered) </sect2> <sect2 id="hot-standby-conflict"> - <title>Handling query conflicts</title> + <title>Handling Query Conflicts</title> <para> The primary and standby servers are in many ways loosely connected. Actions @@ -1462,23 +1680,6 @@ if (!triggered) </para> <para> - The most common reason for conflict between standby queries and WAL replay - is <quote>early cleanup</>. Normally, <productname>PostgreSQL</> allows - cleanup of old row versions when there are no transactions that need to - see them to ensure correct visibility of data according to MVCC rules. - However, this rule can only be applied for transactions executing on the - master. So it is possible that cleanup on the master will remove row - versions that are still visible to a transaction on the standby. - </para> - - <para> - Experienced users should note that both row version cleanup and row version - freezing will potentially conflict with standby queries. Running a manual - <command>VACUUM FREEZE</> is likely to cause conflicts even on tables with - no updated or deleted rows. - </para> - - <para> Once the delay specified by <varname>max_standby_archive_delay</> or <varname>max_standby_streaming_delay</> has been exceeded, conflicting queries will be cancelled. This usually results just in a cancellation @@ -1505,6 +1706,23 @@ if (!triggered) </para> <para> + The most common reason for conflict between standby queries and WAL replay + is <quote>early cleanup</>. Normally, <productname>PostgreSQL</> allows + cleanup of old row versions when there are no transactions that need to + see them to ensure correct visibility of data according to MVCC rules. + However, this rule can only be applied for transactions executing on the + master. So it is possible that cleanup on the master will remove row + versions that are still visible to a transaction on the standby. + </para> + + <para> + Experienced users should note that both row version cleanup and row version + freezing will potentially conflict with standby queries. Running a manual + <command>VACUUM FREEZE</> is likely to cause conflicts even on tables with + no updated or deleted rows. + </para> + + <para> Users should be clear that tables that are regularly and heavily updated on the primary server will quickly cause cancellation of longer running queries on the standby. In such cases the setting of a finite value for @@ -1515,12 +1733,10 @@ if (!triggered) <para> Remedial possibilities exist if the number of standby-query cancellations - is found to be unacceptable. The first option is to connect to the - primary server and keep a query active for as long as needed to - run queries on the standby. This prevents <command>VACUUM</> from removing - recently-dead rows and so cleanup conflicts do not occur. - This could be done using <filename>contrib/dblink</> and - <function>pg_sleep()</>, or via other mechanisms. If you do this, you + is found to be unacceptable. The first option is to set the parameter + <varname>hot_standby_feedback</>, which prevents <command>VACUUM</> from + removing recently-dead rows and so cleanup conflicts do not occur. + If you do this, you should note that this will delay cleanup of dead rows on the primary, which may result in undesirable table bloat. However, the cleanup situation will be no worse than if the standby queries were running @@ -1541,6 +1757,13 @@ if (!triggered) approach, since <varname>vacuum_defer_cleanup_age</> is measured in transactions executed on the primary server. </para> + + <para> + The number of query cancels and the reason for them can be viewed using + the <structname>pg_stat_database_conflicts</> system view on the standby + server. The <structname>pg_stat_database</> system view also contains + summary information. + </para> </sect2> <sect2 id="hot-standby-admin"> @@ -1743,7 +1966,7 @@ LOG: database system is ready to accept read only connections </para> <para> - New oids cannot be assigned, though some <acronym>UUID</> generators may still + New OIDs cannot be assigned, though some <acronym>UUID</> generators may still work as long as they do not rely on writing new status to the database. </para> @@ -1764,12 +1987,15 @@ LOG: database system is ready to accept read only connections </para> <para> - Running <command>DROP DATABASE</>, <command>ALTER DATABASE ... SET - TABLESPACE</>, or <command>ALTER DATABASE ... RENAME</> on the primary + Running <command>DROP DATABASE</> or <command>ALTER DATABASE ... SET + TABLESPACE</> on the primary will generate a WAL entry that will cause all users connected to that database on the standby to be forcibly disconnected. This action occurs immediately, whatever the setting of - <varname>max_standby_streaming_delay</>. + <varname>max_standby_streaming_delay</>. Note that + <command>ALTER DATABASE ... RENAME</> does not disconnect users, which + in most cases will go unnoticed, though might in some cases cause a + program confusion if it depends in some way upon database name. </para> <para> @@ -1842,8 +2068,7 @@ LOG: database system is ready to accept read only connections <listitem> <para> Operations on hash indexes are not presently WAL-logged, so - replay will not update these indexes. Hash indexes will not be - used for query plans during recovery. + replay will not update these indexes. </para> </listitem> <listitem> @@ -1880,7 +2105,16 @@ LOG: database system is ready to accept read only connections advised to select a larger value of <varname>max_locks_per_transaction</>, perhaps as much as twice the value of the parameter on the primary server. You need not consider this at all if - your setting of <varname>max_prepared_transactions</> is <literal>0</>. + your setting of <varname>max_prepared_transactions</> is 0. + </para> + </listitem> + <listitem> + <para> + The Serializable transaction isolation level is not yet available in hot + standby. (See <xref linkend="xact-serializable"> and + <xref linkend="serializable-consistency"> for details.) + An attempt to set a transaction to the serializable isolation level in + hot standby mode will generate an error. </para> </listitem> </itemizedlist> @@ -1890,95 +2124,4 @@ LOG: database system is ready to accept read only connections </sect1> - <sect1 id="backup-incremental-updated"> - <title>Incrementally Updated Backups</title> - - <indexterm zone="high-availability"> - <primary>incrementally updated backups</primary> - </indexterm> - - <indexterm zone="high-availability"> - <primary>change accumulation</primary> - </indexterm> - - <para> - In a standby configuration, it is possible to offload the expense of - taking periodic base backups from the primary server; instead base backups - can be made by backing - up a standby server's files. This concept is generally known as - incrementally updated backups, log change accumulation, or more simply, - change accumulation. - </para> - - <para> - If we take a file system backup of the standby server's data - directory while it is processing - logs shipped from the primary, we will be able to reload that backup and - restart the standby's recovery process from the last restart point. - We no longer need to keep WAL files from before the standby's restart point. - If recovery is needed, it will be faster to recover from the incrementally - updated backup than from the original base backup. - </para> - - <para> - The procedure for taking a file system backup of the standby server's - data directory while it's processing logs shipped from the primary is: - <orderedlist> - <listitem> - <para> - Perform the backup, without using <function>pg_start_backup</> and - <function>pg_stop_backup</>. Note that the <filename>pg_control</> - file must be backed up <emphasis>first</>, as in: -<programlisting> -cp /var/lib/pgsql/data/global/pg_control /tmp -cp -r /var/lib/pgsql/data /path/to/backup -mv /tmp/pg_control /path/to/backup/data/global -</programlisting> - <filename>pg_control</> contains the location where WAL replay will - begin after restoring from the backup; backing it up first ensures - that it points to the last restartpoint when the backup started, not - some later restartpoint that happened while files were copied to the - backup. - </para> - </listitem> - <listitem> - <para> - Make note of the backup ending WAL location by calling the <function> - pg_last_xlog_replay_location</> function at the end of the backup, - and keep it with the backup. -<programlisting> -psql -c "select pg_last_xlog_replay_location();" > /path/to/backup/end_location -</programlisting> - When recovering from the incrementally updated backup, the server - can begin accepting connections and complete the recovery successfully - before the database has become consistent. To avoid that, you must - ensure the database is consistent before users try to connect to the - server and when the recovery ends. You can do that by comparing the - progress of the recovery with the stored backup ending WAL location: - the server is not consistent until recovery has reached the backup end - location. The progress of the recovery can also be observed with the - <function>pg_last_xlog_replay_location</> function, but that required - connecting to the server while it might not be consistent yet, so - care should be taken with that method. - </para> - <para> - </para> - </listitem> - </orderedlist> - </para> - - <para> - Since the standby server is not <quote>live</>, it is not possible to - use <function>pg_start_backup()</> and <function>pg_stop_backup()</> - to manage the backup process; it will be up to you to determine how - far back you need to keep WAL segment files to have a recoverable - backup. That is determined by the last restartpoint when the backup - was taken, any WAL older than that can be deleted from the archive - once the backup is complete. You can determine the last restartpoint - by running <application>pg_controldata</> on the standby server before - taking the backup, or by using the <varname>log_checkpoints</> option - to print values to the standby's server log. - </para> - </sect1> - </chapter> diff --git a/doc/src/sgml/history.sgml b/doc/src/sgml/history.sgml index c2ae854d8f..9bd5c22d8e 100644 --- a/doc/src/sgml/history.sgml +++ b/doc/src/sgml/history.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/history.sgml,v 1.31 2009/04/27 16:27:35 momjian Exp $ --> +<!-- doc/src/sgml/history.sgml --> <sect1 id="history"> <title>A Brief History of <productname>PostgreSQL</productname></title> @@ -63,13 +63,13 @@ database, and several geographic information systems. <productname>POSTGRES</productname> has also been used as an educational tool at several universities. Finally, Illustra - Information Technologies (later merged into + Information Technologies (later merged into <ulink url="http://www.informix.com/"><productname>Informix</productname></ulink>, which is now owned by <ulink url="http://www.ibm.com/">IBM</ulink>) picked up the code and commercialized it. In late 1992, <productname>POSTGRES</productname> became the primary data manager - for the + for the <ulink url="http://meteora.ucsd.edu/s2k/s2k_home.html"> Sequoia 2000 scientific computing project</ulink>. </para> diff --git a/doc/src/sgml/hstore.sgml b/doc/src/sgml/hstore.sgml index c5effb88e0..aa21295265 100644 --- a/doc/src/sgml/hstore.sgml +++ b/doc/src/sgml/hstore.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/hstore.sgml,v 1.12 2010/07/02 20:36:49 rhaas Exp $ --> +<!-- doc/src/sgml/hstore.sgml --> -<sect1 id="hstore"> +<sect1 id="hstore" xreflabel="hstore"> <title>hstore</title> <indexterm zone="hstore"> @@ -24,11 +24,11 @@ includes zero or more <replaceable>key</> <literal>=></> <replaceable>value</> pairs separated by commas. Some examples: - <programlisting> - k => v - foo => bar, baz => whatever - "1-a" => "anything at all" - </programlisting> +<synopsis> +k => v +foo => bar, baz => whatever +"1-a" => "anything at all" +</synopsis> The order of the pairs is not significant (and may not be reproduced on output). Whitespace between pairs or around the <literal>=></> sign is @@ -42,23 +42,23 @@ with duplicate keys, only one will be stored in the <type>hstore</> and there is no guarantee as to which will be kept: - <programlisting> -% select 'a=>1,a=>2'::hstore; +<programlisting> +SELECT 'a=>1,a=>2'::hstore; hstore ---------- "a"=>"1" - </programlisting> +</programlisting> </para> <para> A value (but not a key) can be an SQL <literal>NULL</>. For example: - <programlisting> - key => NULL - </programlisting> +<programlisting> +key => NULL +</programlisting> The <literal>NULL</> keyword is case-insensitive. Double-quote the - <literal>NULL</> to treat it as the ordinary string "NULL". + <literal>NULL</> to treat it as the ordinary string <quote>NULL</quote>. </para> <note> @@ -85,6 +85,12 @@ <sect2> <title><type>hstore</> Operators and Functions</title> + <para> + The operators provided by the <literal>hstore</literal> module are + shown in <xref linkend="hstore-op-table">, the functions + in <xref linkend="hstore-func-table">. + </para> + <table id="hstore-op-table"> <title><type>hstore</> Operators</title> @@ -214,7 +220,7 @@ and <literal><@</> were called <literal>@</> and <literal>~</>, respectively. These names are still available, but are deprecated and will eventually be removed. Notice that the old names are reversed from the - convention formerly followed by the core geometric datatypes! + convention formerly followed by the core geometric data types! </para> </note> @@ -409,7 +415,7 @@ b <para> The function <function>populate_record</function> is actually declared with <type>anyelement</>, not <type>record</>, as its first argument, - but it will reject non-record types with a runtime error. + but it will reject non-record types with a run-time error. </para> </note> </sect2> @@ -421,11 +427,11 @@ b <type>hstore</> has GiST and GIN index support for the <literal>@></>, <literal>?</>, <literal>?&</> and <literal>?|</> operators. For example: </para> - <programlisting> +<programlisting> CREATE INDEX hidx ON testhstore USING GIST (h); CREATE INDEX hidx ON testhstore USING GIN (h); - </programlisting> +</programlisting> <para> <type>hstore</> also supports <type>btree</> or <type>hash</> indexes for @@ -436,11 +442,11 @@ CREATE INDEX hidx ON testhstore USING GIN (h); may be useful for equivalence lookups. Create indexes for <literal>=</> comparisons as follows: </para> - <programlisting> +<programlisting> CREATE INDEX hidx ON testhstore USING BTREE (h); CREATE INDEX hidx ON testhstore USING HASH (h); - </programlisting> +</programlisting> </sect2> <sect2> @@ -448,22 +454,21 @@ CREATE INDEX hidx ON testhstore USING HASH (h); <para> Add a key, or update an existing key with a new value: - </para> - <programlisting> +<programlisting> UPDATE tab SET h = h || ('c' => '3'); - </programlisting> +</programlisting> + </para> <para> Delete a key: - </para> - <programlisting> +<programlisting> UPDATE tab SET h = delete(h, 'k1'); - </programlisting> +</programlisting> + </para> <para> Convert a <type>record</> to an <type>hstore</>: - </para> - <programlisting> +<programlisting> CREATE TABLE test (col1 integer, col2 text, col3 text); INSERT INTO test VALUES (123, 'foo', 'bar'); @@ -472,12 +477,12 @@ SELECT hstore(t) FROM test AS t; --------------------------------------------- "col1"=>"123", "col2"=>"foo", "col3"=>"bar" (1 row) - </programlisting> +</programlisting> + </para> <para> Convert an <type>hstore</> to a predefined <type>record</> type: - </para> - <programlisting> +<programlisting> CREATE TABLE test (col1 integer, col2 text, col3 text); SELECT * FROM populate_record(null::test, @@ -486,12 +491,12 @@ SELECT * FROM populate_record(null::test, ------+------+------ 456 | zzz | (1 row) - </programlisting> +</programlisting> + </para> <para> Modify an existing record using the values from an <type>hstore</>: - </para> - <programlisting> +<programlisting> CREATE TABLE test (col1 integer, col2 text, col3 text); INSERT INTO test VALUES (123, 'foo', 'bar'); @@ -500,7 +505,8 @@ SELECT (r).* FROM (SELECT t #= '"col3"=>"baz"' AS r FROM test t) s; ------+------+------ 123 | foo | baz (1 row) - </programlisting> +</programlisting> + </para> </sect2> <sect2> @@ -515,22 +521,21 @@ SELECT (r).* FROM (SELECT t #= '"col3"=>"baz"' AS r FROM test t) s; <para> Simple example: - </para> - <programlisting> +<programlisting> SELECT * FROM each('aaa=>bq, b=>NULL, ""=>1'); - </programlisting> +</programlisting> + </para> <para> Using a table: - </para> - <programlisting> +<programlisting> SELECT (each(h)).key, (each(h)).value INTO stat FROM testhstore; - </programlisting> +</programlisting> + </para> <para> Online statistics: - </para> - <programlisting> +<programlisting> SELECT key, count(*) FROM (SELECT (each(h)).key FROM testhstore) AS stat GROUP BY key @@ -547,19 +552,14 @@ SELECT key, count(*) FROM title | 190 org | 189 ................... - </programlisting> +</programlisting> + </para> </sect2> <sect2> <title>Compatibility</title> <para> - <emphasis>When upgrading from older versions, always load the new - version of this module into the database before restoring a dump. - Otherwise, many new features will be unavailable.</emphasis> - </para> - - <para> As of PostgreSQL 9.0, <type>hstore</> uses a different internal representation than previous versions. This presents no obstacle for dump/restore upgrades since the text representation (used in the dump) is @@ -572,16 +572,16 @@ SELECT key, count(*) FROM performance penalty when processing data that has not yet been modified by the new code. It is possible to force an upgrade of all values in a table column by doing an <literal>UPDATE</> statement as follows: - </para> - <programlisting> +<programlisting> UPDATE tablename SET hstorecol = hstorecol || ''; - </programlisting> +</programlisting> + </para> <para> Another way to do it is: - <programlisting> +<programlisting> ALTER TABLE tablename ALTER hstorecol TYPE hstore USING hstorecol || ''; - </programlisting> +</programlisting> The <command>ALTER TABLE</> method requires an exclusive lock on the table, but does not result in bloating the table with old row versions. </para> diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index 93f3411a2d..c7e997793d 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.33 2010/02/08 04:33:51 tgl Exp $ --> +<!-- doc/src/sgml/indexam.sgml --> <chapter id="indexam"> <title>Index Access Method Interface Definition</title> @@ -105,14 +105,15 @@ where no indexable restriction clause is given for the first index column. When <structfield>amcanmulticol</structfield> is false, <structfield>amoptionalkey</structfield> essentially says whether the - access method allows full-index scans without any restriction clause. + access method supports full-index scans without any restriction clause. Access methods that support multiple index columns <emphasis>must</> support scans that omit restrictions on any or all of the columns after the first; however they are permitted to require some restriction to appear for the first index column, and this is signaled by setting <structfield>amoptionalkey</structfield> false. - <structfield>amindexnulls</structfield> asserts that index entries are - created for NULL key values. Since most indexable operators are + One reason that an index AM might set + <structfield>amoptionalkey</structfield> false is if it doesn't index + NULLs. Since most indexable operators are strict and hence cannot return TRUE for NULL inputs, it is at first sight attractive to not store index entries for null values: they could never be returned by an index scan anyway. However, this @@ -129,10 +130,7 @@ used to scan for rows with <literal>a = 4</literal>, which is wrong if the index omits rows where <literal>b</> is null. It is, however, OK to omit rows where the first indexed column is null. - Thus, <structfield>amindexnulls</structfield> should be set true only if the - index access method indexes all rows, including arbitrary combinations of - null values. An index access method that sets - <structfield>amindexnulls</structfield> may also set + An index access method that does index nulls may also set <structfield>amsearchnulls</structfield>, indicating that it supports <literal>IS NULL</> and <literal>IS NOT NULL</> clauses as search conditions. @@ -167,6 +165,17 @@ ambuild (Relation heapRelation, <para> <programlisting> +void +ambuildempty (Relation indexRelation); +</programlisting> + Build an empty index, and write it to the initialization fork (INIT_FORKNUM) + of the given relation. This method is called only for unlogged tables; the + empty index written to the initialization fork will be copied over the main + relation fork on each server restart. + </para> + + <para> +<programlisting> bool aminsert (Relation indexRelation, Datum *values, @@ -189,7 +198,7 @@ aminsert (Relation indexRelation, </para> <para> - The function's boolean result value is significant only when + The function's Boolean result value is significant only when <literal>checkUnique</> is <literal>UNIQUE_CHECK_PARTIAL</>. In this case a TRUE result means the new entry is known unique, whereas FALSE means it might be non-unique (and a deferred uniqueness check must @@ -268,6 +277,7 @@ void amcostestimate (PlannerInfo *root, IndexOptInfo *index, List *indexQuals, + List *indexOrderBys, RelOptInfo *outer_rel, Cost *indexStartupCost, Cost *indexTotalCost, @@ -318,19 +328,42 @@ amoptions (ArrayType *reloptions, IndexScanDesc ambeginscan (Relation indexRelation, int nkeys, - ScanKey key); + int norderbys); </programlisting> - Begin a new scan. The <literal>key</> array (of length <literal>nkeys</>) - describes the scan key(s) for the index scan. The result must be a - palloc'd struct. For implementation reasons the index access method + Prepare for an index scan. The <literal>nkeys</> and <literal>norderbys</> + parameters indicate the number of quals and ordering operators that will be + used in the scan; these may be useful for space allocation purposes. + Note that the actual values of the scan keys aren't provided yet. + The result must be a palloc'd struct. + For implementation reasons the index access method <emphasis>must</> create this struct by calling <function>RelationGetIndexScan()</>. In most cases - <function>ambeginscan</> itself does little beyond making that call; + <function>ambeginscan</> does little beyond making that call and perhaps + acquiring locks; the interesting parts of index-scan startup are in <function>amrescan</>. </para> <para> <programlisting> +void +amrescan (IndexScanDesc scan, + ScanKey keys, + int nkeys, + ScanKey orderbys, + int norderbys); +</programlisting> + Start or restart an indexscan, possibly with new scan keys. (To restart + using previously-passed keys, NULL is passed for <literal>keys</> and/or + <literal>orderbys</>.) Note that it is not allowed for + the number of keys or order-by operators to be larger than + what was passed to <function>ambeginscan</>. In practice the restart + feature is used when a new outer tuple is selected by a nested-loop join + and so a new key comparison value is needed, but the scan key structure + remains the same. + </para> + + <para> +<programlisting> boolean amgettuple (IndexScanDesc scan, ScanDirection direction); @@ -366,7 +399,7 @@ amgetbitmap (IndexScanDesc scan, TIDBitmap *tbm); </programlisting> Fetch all tuples in the given scan and add them to the caller-supplied - TIDBitmap (that is, OR the set of tuple IDs into whatever set is already + <type>TIDBitmap</type> (that is, OR the set of tuple IDs into whatever set is already in the bitmap). The number of tuples fetched is returned (this might be just an approximate count, for instance some AMs do not detect duplicates). While inserting tuple IDs into the bitmap, <function>amgetbitmap</> can @@ -393,22 +426,6 @@ amgetbitmap (IndexScanDesc scan, <para> <programlisting> void -amrescan (IndexScanDesc scan, - ScanKey key); -</programlisting> - Restart the given scan, possibly with new scan keys (to continue using - the old keys, NULL is passed for <literal>key</>). Note that it is not - possible for the number of keys to be changed. In practice the restart - feature is used when a new outer tuple is selected by a nested-loop join - and so a new key comparison value is needed, but the scan key structure - remains the same. This function is also called by - <function>RelationGetIndexScan()</>, so it is used for initial setup - of an index scan as well as rescanning. - </para> - - <para> -<programlisting> -void amendscan (IndexScanDesc scan); </programlisting> End a scan and release resources. The <literal>scan</> struct itself @@ -497,11 +514,31 @@ amrestrpos (IndexScanDesc scan); <para> Some access methods return index entries in a well-defined order, others - do not. If entries are returned in sorted order, the access method should - set <structname>pg_am</>.<structfield>amcanorder</> true to indicate that - it supports ordered scans. - All such access methods must use btree-compatible strategy numbers for - their equality and ordering operators. + do not. There are actually two different ways that an access method can + support sorted output: + + <itemizedlist> + <listitem> + <para> + Access methods that always return entries in the natural ordering + of their data (such as btree) should set + <structname>pg_am</>.<structfield>amcanorder</> to true. + Currently, such access methods must use btree-compatible strategy + numbers for their equality and ordering operators. + </para> + </listitem> + <listitem> + <para> + Access methods that support ordering operators should set + <structname>pg_am</>.<structfield>amcanorderbyop</> to true. + This indicates that the index is capable of returning entries in + an order satisfying <literal>ORDER BY</> <replaceable>index_key</> + <replaceable>operator</> <replaceable>constant</>. Scan modifiers + of that form can be passed to <function>amrescan</> as described + previously. + </para> + </listitem> + </itemizedlist> </para> <para> @@ -513,7 +550,7 @@ amrestrpos (IndexScanDesc scan); the normal front-to-back direction, so <function>amgettuple</> must return the last matching tuple in the index, rather than the first one as it normally would. (This will only occur for access - methods that advertise they support ordered scans.) After the + methods that set <structfield>amcanorder</> to true.) After the first call, <function>amgettuple</> must be prepared to advance the scan in either direction from the most recently returned entry. (But if <structname>pg_am</>.<structfield>amcanbackward</> is false, all subsequent @@ -555,7 +592,8 @@ amrestrpos (IndexScanDesc scan); tuples at once and marking or restoring scan positions isn't supported. Secondly, the tuples are returned in a bitmap which doesn't have any specific ordering, which is why <function>amgetbitmap</> doesn't - take a <literal>direction</> argument. Finally, <function>amgetbitmap</> + take a <literal>direction</> argument. (Ordering operators will never be + supplied for such a scan, either.) Finally, <function>amgetbitmap</> does not guarantee any locking of the returned tuples, with implications spelled out in <xref linkend="index-locking">. </para> @@ -667,6 +705,19 @@ amrestrpos (IndexScanDesc scan); it is only safe to use such scans with MVCC-compliant snapshots. </para> + <para> + When the <structfield>ampredlocks</> flag is not set, any scan using that + index access method within a serializable transaction will acquire a + non-blocking predicate lock on the full index. This will generate a + read-write conflict with the insert of any tuple into that index by a + concurrent serializable transaction. If certain patterns of read-write + conflicts are detected among a set of concurrent serializable + transactions, one of those transactions may be cancelled to protect data + integrity. When the flag is set, it indicates that the index access + method implements finer-grained predicate locking, which will tend to + reduce the frequency of such transaction cancellations. + </para> + </sect1> <sect1 id="index-unique-checks"> @@ -820,25 +871,27 @@ amrestrpos (IndexScanDesc scan); <title>Index Cost Estimation Functions</title> <para> - The amcostestimate function is given a list of WHERE clauses that have - been determined to be usable with the index. It must return estimates + The <function>amcostestimate</> function is given information describing + a possible index scan, including lists of WHERE and ORDER BY clauses that + have been determined to be usable with the index. It must return estimates of the cost of accessing the index and the selectivity of the WHERE clauses (that is, the fraction of parent-table rows that will be retrieved during the index scan). For simple cases, nearly all the work of the cost estimator can be done by calling standard routines - in the optimizer; the point of having an amcostestimate function is + in the optimizer; the point of having an <function>amcostestimate</> function is to allow index access methods to provide index-type-specific knowledge, in case it is possible to improve on the standard estimates. </para> <para> - Each amcostestimate function must have the signature: + Each <function>amcostestimate</> function must have the signature: <programlisting> void amcostestimate (PlannerInfo *root, IndexOptInfo *index, List *indexQuals, + List *indexOrderBys, RelOptInfo *outer_rel, Cost *indexStartupCost, Cost *indexTotalCost, @@ -846,11 +899,11 @@ amcostestimate (PlannerInfo *root, double *indexCorrelation); </programlisting> - The first four parameters are inputs: + The first five parameters are inputs: <variablelist> <varlistentry> - <term>root</term> + <term><parameter>root</></term> <listitem> <para> The planner's information about the query being processed. @@ -859,7 +912,7 @@ amcostestimate (PlannerInfo *root, </varlistentry> <varlistentry> - <term>index</term> + <term><parameter>index</></term> <listitem> <para> The index being considered. @@ -868,23 +921,34 @@ amcostestimate (PlannerInfo *root, </varlistentry> <varlistentry> - <term>indexQuals</term> + <term><parameter>indexQuals</></term> <listitem> <para> List of index qual clauses (implicitly ANDed); - a NIL list indicates no qualifiers are available. + a <symbol>NIL</> list indicates no qualifiers are available. + Note that the list contains expression trees with RestrictInfo nodes + at the top, not ScanKeys. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><parameter>indexOrderBys</></term> + <listitem> + <para> + List of indexable ORDER BY operators, or <symbol>NIL</> if none. Note that the list contains expression trees, not ScanKeys. </para> </listitem> </varlistentry> <varlistentry> - <term>outer_rel</term> + <term><parameter>outer_rel</></term> <listitem> <para> If the index is being considered for use in a join inner indexscan, the planner's information about the outer side of the join. Otherwise - NULL. When non-NULL, some of the qual clauses will be join clauses + <symbol>NULL</>. When non-<symbol>NULL</>, some of the qual clauses will be join clauses with this rel rather than being simple restriction clauses. Also, the cost estimator should expect that the index scan will be repeated for each row of the outer rel. @@ -899,7 +963,7 @@ amcostestimate (PlannerInfo *root, <variablelist> <varlistentry> - <term>*indexStartupCost</term> + <term><parameter>*indexStartupCost</></term> <listitem> <para> Set to cost of index start-up processing @@ -908,7 +972,7 @@ amcostestimate (PlannerInfo *root, </varlistentry> <varlistentry> - <term>*indexTotalCost</term> + <term><parameter>*indexTotalCost</></term> <listitem> <para> Set to total cost of index processing @@ -917,7 +981,7 @@ amcostestimate (PlannerInfo *root, </varlistentry> <varlistentry> - <term>*indexSelectivity</term> + <term><parameter>*indexSelectivity</></term> <listitem> <para> Set to index selectivity @@ -926,7 +990,7 @@ amcostestimate (PlannerInfo *root, </varlistentry> <varlistentry> - <term>*indexCorrelation</term> + <term><parameter>*indexCorrelation</></term> <listitem> <para> Set to correlation coefficient between index scan order and @@ -951,7 +1015,7 @@ amcostestimate (PlannerInfo *root, row should usually be taken as <varname>cpu_index_tuple_cost</>. In addition, an appropriate multiple of <varname>cpu_operator_cost</> should be charged for any comparison operators invoked during index processing - (especially evaluation of the indexQuals themselves). + (especially evaluation of the <literal>indexQuals</> themselves). </para> <para> @@ -968,14 +1032,14 @@ amcostestimate (PlannerInfo *root, </para> <para> - The indexSelectivity should be set to the estimated fraction of the parent + The <parameter>indexSelectivity</> should be set to the estimated fraction of the parent table rows that will be retrieved during the index scan. In the case of a lossy query, this will typically be higher than the fraction of rows that actually pass the given qual conditions. </para> <para> - The indexCorrelation should be set to the correlation (ranging between + The <parameter>indexCorrelation</> should be set to the correlation (ranging between -1.0 and 1.0) between the index order and the table order. This is used to adjust the estimate for the cost of fetching rows from the parent table. @@ -1009,16 +1073,16 @@ amcostestimate (PlannerInfo *root, <step> <para> Estimate the number of index rows that will be visited during the - scan. For many index types this is the same as indexSelectivity times + scan. For many index types this is the same as <parameter>indexSelectivity</> times the number of rows in the index, but it might be more. (Note that the - index's size in pages and rows is available from the IndexOptInfo struct.) + index's size in pages and rows is available from the <structname>IndexOptInfo</> struct.) </para> </step> <step> <para> Estimate the number of index pages that will be retrieved during the scan. - This might be just indexSelectivity times the index's size in pages. + This might be just <parameter>indexSelectivity</> times the index's size in pages. </para> </step> @@ -1027,16 +1091,16 @@ amcostestimate (PlannerInfo *root, Compute the index access cost. A generic estimator might do this: <programlisting> - /* - * Our generic assumption is that the index pages will be read - * sequentially, so they cost seq_page_cost each, not random_page_cost. - * Also, we charge for evaluation of the indexquals at each index row. - * All the costs are assumed to be paid incrementally during the scan. - */ - cost_qual_eval(&index_qual_cost, indexQuals, root); - *indexStartupCost = index_qual_cost.startup; - *indexTotalCost = seq_page_cost * numIndexPages + - (cpu_index_tuple_cost + index_qual_cost.per_tuple) * numIndexTuples; +/* + * Our generic assumption is that the index pages will be read + * sequentially, so they cost seq_page_cost each, not random_page_cost. + * Also, we charge for evaluation of the indexquals at each index row. + * All the costs are assumed to be paid incrementally during the scan. + */ +cost_qual_eval(&index_qual_cost, indexQuals, root); +*indexStartupCost = index_qual_cost.startup; +*indexTotalCost = seq_page_cost * numIndexPages + + (cpu_index_tuple_cost + index_qual_cost.per_tuple) * numIndexTuples; </programlisting> However, the above does not account for amortization of index reads diff --git a/doc/src/sgml/indices.sgml b/doc/src/sgml/indices.sgml index 6f2887bd16..2dedb153c0 100644 --- a/doc/src/sgml/indices.sgml +++ b/doc/src/sgml/indices.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/indices.sgml,v 1.81 2010/04/03 07:22:54 petere Exp $ --> +<!-- doc/src/sgml/indices.sgml --> <chapter id="indexes"> <title>Indexes</title> @@ -92,9 +92,9 @@ CREATE INDEX test1_id_index ON test1 (id); <para> Creating an index on a large table can take a long time. By default, - <productname>PostgreSQL</productname> allows reads (selects) to occur - on the table in parallel with index creation, but writes (INSERTs, - UPDATEs, DELETEs) are blocked until the index build is finished. + <productname>PostgreSQL</productname> allows reads (<command>SELECT</command> statements) to occur + on the table in parallel with index creation, but writes (<command>INSERT</command>, + <command>UPDATE</command>, <command>DELETE</command>) are blocked until the index build is finished. In production environments this is often unacceptable. It is possible to allow writes to occur in parallel with index creation, but there are several caveats to be aware of — @@ -167,6 +167,11 @@ CREATE INDEX test1_id_index ON test1 (id); upper/lower case conversion. </para> + <para> + B-tree indexes can also be used to retrieve data in sorted order. + This is not always faster than a simple scan and sort, but it is + often helpful. + </para> <para> <indexterm> @@ -187,14 +192,15 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> </synopsis> </para> - <note> + <caution> <para> Hash index operations are not presently WAL-logged, so hash indexes might need to be rebuilt with <command>REINDEX</> - after a database crash. - For this reason, hash index use is presently discouraged. + after a database crash. They are also not replicated over streaming or + file-based replication. + For these reasons, hash index use is presently discouraged. </para> - </note> + </caution> <para> <indexterm> @@ -235,6 +241,18 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> classes are available in the <literal>contrib</> collection or as separate projects. For more information see <xref linkend="GiST">. </para> + + <para> + GiST indexes are also capable of optimizing <quote>nearest-neighbor</> + searches, such as +<programlisting><![CDATA[ +SELECT * FROM places ORDER BY location <-> point '(101,456)' LIMIT 10; +]]> +</programlisting> + which finds the ten places closest to a given target point. The ability + to do this is again dependent on the particular operator class being used. + </para> + <para> <indexterm> <primary>index</primary> @@ -903,6 +921,7 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> defining two operator classes for the data type and then selecting the proper class when making an index. The operator class determines the basic sort ordering (which can then be modified by adding sort options + <literal>COLLATE</literal>, <literal>ASC</>/<literal>DESC</> and/or <literal>NULLS FIRST</>/<literal>NULLS LAST</>). </para> @@ -984,6 +1003,44 @@ SELECT am.amname AS index_method, </sect1> + <sect1 id="indexes-collations"> + <title>Indexes and Collations</title> + + <para> + An index can support only one collation per index column. + If multiple collations are of interest, multiple indexes may be needed. + </para> + + <para> + Consider these statements: +<programlisting> +CREATE TABLE test1c ( + id integer, + content varchar COLLATE "x" +); + +CREATE INDEX test1c_content_index ON test1c (content); +</programlisting> + The index automatically uses the collation of the + underlying column. So a query of the form +<programlisting> +SELECT * FROM test1c WHERE content > <replaceable>constant</replaceable>; +</programlisting> + could use the index, because the comparison will by default use the + collation of the column. However, this index cannot accelerate queries + that involve some other collation. So if queries of the form, say, +<programlisting> +SELECT * FROM test1c WHERE content > <replaceable>constant</replaceable> COLLATE "y"; +</programlisting> + are also of interest, an additional index could be created that supports + the <literal>"y"</literal> collation, like this: +<programlisting> +CREATE INDEX test1c_content_y_index ON test1c (content COLLATE "y"); +</programlisting> + </para> + </sect1> + + <sect1 id="indexes-examine"> <title>Examining Index Usage</title> diff --git a/doc/src/sgml/info.sgml b/doc/src/sgml/info.sgml index 6e358e7719..a59d0c8a43 100644 --- a/doc/src/sgml/info.sgml +++ b/doc/src/sgml/info.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/info.sgml,v 1.27 2009/04/27 16:27:35 momjian Exp $ --> +<!-- doc/src/sgml/info.sgml --> <sect1 id="resources"> <title>Further Information</title> @@ -27,7 +27,7 @@ <term>Web Site</term> <listitem> <para> - The <productname>PostgreSQL</productname> + The <productname>PostgreSQL</productname> <ulink url="http://www.postgresql.org">web site</ulink> carries details on the latest release and other information to make your work or play with diff --git a/doc/src/sgml/information_schema.sgml b/doc/src/sgml/information_schema.sgml index 124bbc3ac2..6df69db4aa 100644 --- a/doc/src/sgml/information_schema.sgml +++ b/doc/src/sgml/information_schema.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/information_schema.sgml,v 1.45 2010/01/28 23:21:10 petere Exp $ --> +<!-- doc/src/sgml/information_schema.sgml --> <chapter id="information-schema"> <title>The Information Schema</title> @@ -21,6 +21,30 @@ <productname>PostgreSQL</productname>-specific views. </para> + <note> + <para> + When querying the database for constraint information, it is possible + for a standard-compliant query that expects to return one row to + return several. This is because the SQL standard requires constraint + names to be unique within a schema, but + <productname>PostgreSQL</productname> does not enforce this + restriction. <productname>PostgreSQL</productname> + automatically-generated constraint names avoid duplicates in the + same schema, but users can specify such duplicate names. + </para> + + <para> + This problem can appear when querying information schema views such + as <literal>check_constraint_routine_usage</>, + <literal>check_constraints</>, <literal>domain_constraints</>, and + <literal>referential_constraints</>. Some other views have similar + issues but contain the table name to help distinguish duplicate + rows, e.g., <literal>constraint_column_usage</>, + <literal>constraint_table_usage</>, <literal>table_constraints</>. + </para> + </note> + + <sect1 id="infoschema-schema"> <title>The Schema</title> @@ -498,6 +522,140 @@ </para> </sect1> + <sect1 id="infoschema-character-sets"> + <title><literal>character_sets</literal></title> + + <para> + The view <literal>character_sets</literal> identifies the character + sets available in the current database. Since PostgreSQL does not + support multiple character sets within one database, this view only + shows one, which is the database encoding. + </para> + + <para> + Take note of how the following terms are used in the SQL standard: + <variablelist> + <varlistentry> + <term>character repertoire</term> + <listitem> + <para> + An abstract collection of characters, for + example <literal>UNICODE</literal>, <literal>UCS</literal>, or + <literal>LATIN1</literal>. Not exposed as an SQL object, but + visible in this view. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>character encoding form</term> + <listitem> + <para> + An encoding of some character repertoire. Most older character + repertoires only use one encoding form, and so there are no + separate names for them (e.g., <literal>LATIN1</literal> is an + encoding form applicable to the <literal>LATIN1</literal> + repertoire). But for example Unicode has the encoding forms + <literal>UTF8</literal>, <literal>UTF16</literal>, etc. (not + all supported by PostgreSQL). Encoding forms are not exposed + as an SQL object, but are visible in this view. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>character set</term> + <listitem> + <para> + A named SQL object that identifies a character repertoire, a + character encoding, and a default collation. A predefined + character set would typically have the same name as an encoding + form, but users could define other names. For example, the + character set <literal>UTF8</literal> would typically identify + the character repertoire <literal>UCS</literal>, encoding + form <literal>UTF8</literal>, and some default collation. + </para> + </listitem> + </varlistentry> + </variablelist> + + You can think of an <quote>encoding</quote> in PostgreSQL either as + a character set or a character encoding form. They will have the + same name, and there can only be one in one database. + </para> + + <table> + <title><literal>character_sets</literal> Columns</title> + + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Data Type</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><literal>character_set_catalog</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Character sets are currently not implemented as schema objects, so this column is null.</entry> + </row> + + <row> + <entry><literal>character_set_schema</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Character sets are currently not implemented as schema objects, so this column is null.</entry> + </row> + + <row> + <entry><literal>character_set_name</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Name of the character set, currently implemented as showing the name of the database encoding</entry> + </row> + + <row> + <entry><literal>character_repertoire</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Character repertoire, showing <literal>UCS</literal> if the encoding is <literal>UTF8</literal>, else just the encoding name</entry> + </row> + + <row> + <entry><literal>form_of_use</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Character encoding form, same as the database encoding</entry> + </row> + + <row> + <entry><literal>default_collate_catalog</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Name of the database containing the default collation (always the current database, if any collation is identified)</entry> + </row> + + <row> + <entry><literal>default_collate_schema</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Name of the schema containing the default collation</entry> + </row> + + <row> + <entry><literal>default_collate_name</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry> + Name of the default collation. The default collation is + identified as the collation that matches + the <literal>COLLATE</literal> and <literal>CTYPE</literal> + settings of the current database. If there is no such + collation, then this column and the associated schema and + catalog columns are null. + </entry> + </row> + </tbody> + </tgroup> + </table> + </sect1> + <sect1 id="infoschema-check-constraint-routine-usage"> <title><literal>check_constraint_routine_usage</literal></title> @@ -615,6 +773,123 @@ </table> </sect1> + <sect1 id="infoschema-collations"> + <title><literal>collations</literal></title> + + <para> + The view <literal>collations</literal> contains the collations + available in the current database. + </para> + + <table> + <title><literal>collations</literal> Columns</title> + + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Data Type</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><literal>collation_catalog</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Name of the database containing the collation (always the current database)</entry> + </row> + + <row> + <entry><literal>collation_schema</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Name of the schema containing the collation</entry> + </row> + + <row> + <entry><literal>collation_name</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Name of the default collation</entry> + </row> + + <row> + <entry><literal>pad_attribute</literal></entry> + <entry><literal>character_data</literal></entry> + <entry> + Always <literal>NO PAD</literal> (The alternative <literal>PAD + SPACE</literal> is not supported by PostgreSQL.) + </entry> + </row> + </tbody> + </tgroup> + </table> + </sect1> + + <sect1 id="infoschema-collation-character-set-applicab"> <!-- max 44 characters --> + <title><literal>collation_character_set_applicability</literal></title> + + <para> + The view <literal>collation_character_set_applicability</literal> + identifies which character set the available collations are + applicable to. In PostgreSQL, there is only one character set per + database (see explanation + in <xref linkend="infoschema-character-sets">), so this view does + not provide much useful information. + </para> + + <table> + <title><literal>collation_character_set_applicability</literal> Columns</title> + + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Data Type</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><literal>collation_catalog</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Name of the database containing the collation (always the current database)</entry> + </row> + + <row> + <entry><literal>collation_schema</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Name of the schema containing the collation</entry> + </row> + + <row> + <entry><literal>collation_name</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Name of the default collation</entry> + </row> + + <row> + <entry><literal>character_set_catalog</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Character sets are currently not implemented as schema objects, so this column is null</entry> + </row> + + <row> + <entry><literal>character_set_schema</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Character sets are currently not implemented as schema objects, so this column is null</entry> + </row> + + <row> + <entry><literal>character_set_name</literal></entry> + <entry><literal>sql_identifier</literal></entry> + <entry>Name of the character set</entry> + </row> + </tbody> + </tgroup> + </table> + </sect1> + <sect1 id="infoschema-column-domain-usage"> <title><literal>column_domain_usage</literal></title> @@ -1884,7 +2159,7 @@ SELECT c.column_name, c.data_type, e.data_type AS element_type FROM information_schema.columns c LEFT JOIN information_schema.element_types e ON ((c.table_catalog, c.table_schema, c.table_name, 'TABLE', c.dtd_identifier) - = (e.object_catalog, e.object_schema, e.object_name, e.object_type, e.dtd_identifier)) + = (e.object_catalog, e.object_schema, e.object_name, e.object_type, e.collection_type_identifier)) WHERE c.table_schema = '...' AND c.table_name = '...' ORDER BY c.ordinal_position; </programlisting> @@ -1944,11 +2219,13 @@ ORDER BY c.ordinal_position; </row> <row> - <entry><literal>dtd_identifier</literal></entry> + <entry><literal>collection_type_identifier</literal></entry> <entry><type>sql_identifier</type></entry> <entry> The identifier of the data type descriptor of the array being - described + described. Use this to join with the + <literal>dtd_identifier</literal> columns of other information + schema views. </entry> </row> @@ -2103,6 +2380,14 @@ ORDER BY c.ordinal_position; <entry>Always null, because arrays always have unlimited maximum cardinality in <productname>PostgreSQL</></entry> </row> + <row> + <entry><literal>dtd_identifier</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry> + An identifier of the data type descriptor of the element. This + is currently not useful. + </entry> + </row> </tbody> </tgroup> </table> @@ -2384,6 +2669,132 @@ ORDER BY c.ordinal_position; </table> </sect1> + <sect1 id="infoschema-foreign-table-options"> + <title><literal>foreign_table_options</literal></title> + + <para> + The view <literal>foreign_table_options</literal> contains all the + options defined for foreign tables in the current database. Only + those foreign tables are shown that the current user has access to + (by way of being the owner or having some privilege). + </para> + + <table> + <title><literal>foreign_table_options</literal> Columns</title> + + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Data Type</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><literal>foreign_table_catalog</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry>Name of the database that contains the foreign table (always the current database)</entry> + </row> + + <row> + <entry><literal>foreign_table_schema</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry>Name of the schema that contains the foreign table</entry> + </row> + + <row> + <entry><literal>foreign_table_name</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry>Name of the foreign table</entry> + </row> + + <row> + <entry><literal>foreign_server_catalog</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry>Name of the database that the foreign server is defined in (always the current database)</entry> + </row> + + <row> + <entry><literal>foreign_server_name</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry>Name of the foreign server</entry> + </row> + + <row> + <entry><literal>option_name</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry>Name of an option</entry> + </row> + + <row> + <entry><literal>option_value</literal></entry> + <entry><type>character_data</type></entry> + <entry>Value of the option</entry> + </row> + </tbody> + </tgroup> + </table> + </sect1> + + <sect1 id="infoschema-foreign-tables"> + <title><literal>foreign_tables</literal></title> + + <para> + The view <literal>foreign_tables</literal> contains all foreign + tables defined in the current database. Only those foreign + tables are shown that the current user has access to (by way of + being the owner or having some privilege). + </para> + + <table> + <title><literal>foreign_tables</literal> Columns</title> + + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Data Type</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><literal>foreign_table_catalog</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry>Name of the database that the foreign table is defined in (always the current database)</entry> + </row> + + <row> + <entry><literal>foreign_table_schema</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry>Name of the schema that contains the foreign table</entry> + </row> + + <row> + <entry><literal>foreign_table_name</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry>Name of the foreign table</entry> + </row> + + <row> + <entry><literal>foreign_server_catalog</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry>Name of the database that the foreign server is defined in (always the current database)</entry> + </row> + + <row> + <entry><literal>foreign_server_name</literal></entry> + <entry><type>sql_identifier</type></entry> + <entry>Name of the foreign server</entry> + </row> + </tbody> + </tgroup> + </table> + </sect1> + <sect1 id="infoschema-key-column-usage"> <title><literal>key_column_usage</literal></title> @@ -2834,6 +3245,7 @@ ORDER BY c.ordinal_position; </tbody> </tgroup> </table> + </sect1> <sect1 id="infoschema-role-column-grants"> @@ -3158,7 +3570,7 @@ ORDER BY c.ordinal_position; <row> <entry><literal>object_type</literal></entry> <entry><type>character_data</type></entry> - <entry><literal>DOMAIN</literal> or <literal>FOREIGN DATA WRAPPER</literal> or <literal>FOREIGN SERVER</literal></entry> + <entry><literal>COLLATION</literal> or <literal>DOMAIN</literal> or <literal>FOREIGN DATA WRAPPER</literal> or <literal>FOREIGN SERVER</literal></entry> </row> <row> @@ -4013,31 +4425,42 @@ ORDER BY c.ordinal_position; </row> <row> - <entry><literal>maximum_value</literal></entry> - <entry><type>cardinal_number</type></entry> - <entry>Not yet implemented</entry> + <entry><literal>start_value</literal></entry> + <entry><type>character_data</type></entry> + <entry>The start value of the sequence</entry> </row> <row> <entry><literal>minimum_value</literal></entry> - <entry><type>cardinal_number</type></entry> - <entry>Not yet implemented</entry> + <entry><type>character_data</type></entry> + <entry>The minimum value of the sequence</entry> + </row> + + <row> + <entry><literal>maximum_value</literal></entry> + <entry><type>character_data</type></entry> + <entry>The maximum value of the sequence</entry> </row> <row> <entry><literal>increment</literal></entry> - <entry><type>cardinal_number</type></entry> - <entry>Not yet implemented</entry> + <entry><type>character_data</type></entry> + <entry>The increment of the sequence</entry> </row> <row> <entry><literal>cycle_option</literal></entry> <entry><type>yes_or_no</type></entry> - <entry>Not yet implemented</entry> + <entry><literal>YES</literal> if the sequence cycles, else <literal>NO</literal></entry> </row> </tbody> </tgroup> </table> + + <para> + Note that in accordance with the SQL standard, the start, minimum, + maximum, and increment values are returned as character strings. + </para> </sect1> <sect1 id="infoschema-sql-features"> @@ -4730,8 +5153,9 @@ ORDER BY c.ordinal_position; <entry> Type of the table: <literal>BASE TABLE</literal> for a persistent base table (the normal table type), - <literal>VIEW</literal> for a view, or <literal>LOCAL - TEMPORARY</literal> for a temporary table + <literal>VIEW</literal> for a view, <literal>FOREIGN TABLE</literal> + for a foreign table, or + <literal>LOCAL TEMPORARY</literal> for a temporary table </entry> </row> @@ -4885,8 +5309,8 @@ ORDER BY c.ordinal_position; <para> The view <literal>triggers</literal> contains all triggers defined - in the current database on tables that the current user owns or has - some non-SELECT privilege on. + in the current database on tables and views that the current user owns + or has some non-SELECT privilege on. </para> <table> @@ -4987,34 +5411,34 @@ ORDER BY c.ordinal_position; </row> <row> - <entry><literal>condition_timing</literal></entry> + <entry><literal>action_timing</literal></entry> <entry><type>character_data</type></entry> <entry> - Time at which the trigger fires (<literal>BEFORE</literal> or - <literal>AFTER</literal>) + Time at which the trigger fires (<literal>BEFORE</literal>, + <literal>AFTER</literal>, or <literal>INSTEAD OF</literal>) </entry> </row> <row> - <entry><literal>condition_reference_old_table</literal></entry> + <entry><literal>action_reference_old_table</literal></entry> <entry><type>sql_identifier</type></entry> <entry>Applies to a feature not available in <productname>PostgreSQL</></entry> </row> <row> - <entry><literal>condition_reference_new_table</literal></entry> + <entry><literal>action_reference_new_table</literal></entry> <entry><type>sql_identifier</type></entry> <entry>Applies to a feature not available in <productname>PostgreSQL</></entry> </row> <row> - <entry><literal>condition_reference_old_row</literal></entry> + <entry><literal>action_reference_old_row</literal></entry> <entry><type>sql_identifier</type></entry> <entry>Applies to a feature not available in <productname>PostgreSQL</></entry> </row> <row> - <entry><literal>condition_reference_new_row</literal></entry> + <entry><literal>action_reference_new_row</literal></entry> <entry><type>sql_identifier</type></entry> <entry>Applies to a feature not available in <productname>PostgreSQL</></entry> </row> @@ -5032,9 +5456,9 @@ ORDER BY c.ordinal_position; Triggers in <productname>PostgreSQL</productname> have two incompatibilities with the SQL standard that affect the representation in the information schema. First, trigger names are - local to the table in <productname>PostgreSQL</productname>, rather + local to each table in <productname>PostgreSQL</productname>, rather than being independent schema objects. Therefore there can be duplicate - trigger names defined in one schema, as long as they belong to + trigger names defined in one schema, so long as they belong to different tables. (<literal>trigger_catalog</literal> and <literal>trigger_schema</literal> are really the values pertaining to the table that the trigger is defined on.) Second, triggers can @@ -5045,14 +5469,34 @@ ORDER BY c.ordinal_position; multiple rows in the information schema, one for each type of event. As a consequence of these two issues, the primary key of the view <literal>triggers</literal> is really - <literal>(trigger_catalog, trigger_schema, trigger_name, - event_object_table, event_manipulation)</literal> instead of + <literal>(trigger_catalog, trigger_schema, event_object_table, + trigger_name, event_manipulation)</literal> instead of <literal>(trigger_catalog, trigger_schema, trigger_name)</literal>, which is what the SQL standard specifies. Nonetheless, if you define your triggers in a manner that conforms with the SQL standard (trigger names unique in the schema and only one event type per trigger), this will not affect you. </para> + + <note> + <para> + Prior to <productname>PostgreSQL</> 9.1, this view's columns + <structfield>action_timing</structfield>, + <structfield>action_reference_old_table</structfield>, + <structfield>action_reference_new_table</structfield>, + <structfield>action_reference_old_row</structfield>, and + <structfield>action_reference_new_row</structfield> + were named + <structfield>condition_timing</structfield>, + <structfield>condition_reference_old_table</structfield>, + <structfield>condition_reference_new_table</structfield>, + <structfield>condition_reference_old_row</structfield>, and + <structfield>condition_reference_new_row</structfield> + respectively. + That was how they were named in the SQL:1999 standard. + The new naming conforms to SQL:2003 and later. + </para> + </note> </sect1> <sect1 id="infoschema-usage-privileges"> @@ -5063,15 +5507,15 @@ ORDER BY c.ordinal_position; <literal>USAGE</literal> privileges granted on various kinds of objects to a currently enabled role or by a currently enabled role. In <productname>PostgreSQL</productname>, this currently applies to - domains, foreign-data wrappers, and foreign servers. There is one + collations, domains, foreign-data wrappers, and foreign servers. There is one row for each combination of object, grantor, and grantee. </para> <para> - Since domains do not have real privileges + Since collations and domains do not have real privileges in <productname>PostgreSQL</productname>, this view shows implicit non-grantable <literal>USAGE</literal> privileges granted by the - owner to <literal>PUBLIC</literal> for all domains. The other + owner to <literal>PUBLIC</literal> for all collations and domains. The other object types, however, show real privileges. </para> @@ -5122,7 +5566,7 @@ ORDER BY c.ordinal_position; <row> <entry><literal>object_type</literal></entry> <entry><type>character_data</type></entry> - <entry><literal>DOMAIN</literal> or <literal>FOREIGN DATA WRAPPER</literal> or <literal>FOREIGN SERVER</literal></entry> + <entry><literal>COLLATION</literal> or <literal>DOMAIN</literal> or <literal>FOREIGN DATA WRAPPER</literal> or <literal>FOREIGN SERVER</literal></entry> </row> <row> @@ -5562,19 +6006,28 @@ ORDER BY c.ordinal_position; <row> <entry><literal>is_trigger_updatable</literal></entry> <entry><type>yes_or_no</type></entry> - <entry>Applies to a feature not available in <productname>PostgreSQL</></entry> + <entry> + <literal>YES</> if the view has an <literal>INSTEAD OF</> + <command>UPDATE</> trigger defined on it, <literal>NO</> if not + </entry> </row> <row> <entry><literal>is_trigger_deletable</literal></entry> <entry><type>yes_or_no</type></entry> - <entry>Applies to a feature not available in <productname>PostgreSQL</></entry> + <entry> + <literal>YES</> if the view has an <literal>INSTEAD OF</> + <command>DELETE</> trigger defined on it, <literal>NO</> if not + </entry> </row> <row> <entry><literal>is_trigger_insertable_into</literal></entry> <entry><type>yes_or_no</type></entry> - <entry>Applies to a feature not available in <productname>PostgreSQL</></entry> + <entry> + <literal>YES</> if the view has an <literal>INSTEAD OF</> + <command>INSERT</> trigger defined on it, <literal>NO</> if not + </entry> </row> </tbody> </tgroup> diff --git a/doc/src/sgml/install-win32.sgml b/doc/src/sgml/install-windows.sgml index dd12a190b0..cb8bca9c63 100644 --- a/doc/src/sgml/install-win32.sgml +++ b/doc/src/sgml/install-windows.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/install-win32.sgml,v 1.57 2010/03/17 17:12:31 petere Exp $ --> +<!-- doc/src/sgml/install-windows.sgml --> -<chapter id="install-win32"> +<chapter id="install-windows"> <title>Installation from Source Code on <productname>Windows</productname></title> <indexterm> @@ -9,7 +9,7 @@ </indexterm> <para> - It is recommended that most users download the binary distribution for + It is recommended that most users download the binary distribution for Windows, available as a one-click installer package from the <productname>PostgreSQL</productname> website. Building from source is only intended for people developing <productname>PostgreSQL</productname> @@ -19,7 +19,7 @@ <para> There are several different ways of building PostgreSQL on <productname>Windows</productname>. The simplest way to build with - Microsoft tools is to intall a modern version of the + Microsoft tools is to install a supported version of the <productname>Microsoft Platform SDK</productname> and use use the included compiler. It is also possible to build with the full <productname>Microsoft Visual C++ 2005 or 2008</productname>. In some cases @@ -37,7 +37,7 @@ <para> Finally, the client access library (<application>libpq</application>) can be built using - <productname>Visual C++ 7.1</productname> or + <productname>Visual C++ 7.1</productname> or <productname>Borland C++</productname> for compatibility with statically linked applications built using these tools. </para> @@ -47,23 +47,34 @@ <productname>Cygwin</productname> uses the normal build system, see <xref linkend="installation"> and the specific notes in <xref linkend="installation-notes-mingw"> and <xref linkend="installation-notes-cygwin">. - These builds cannot generate 64-bit binaries. - <productname>Cygwin</productname> is not recommended and should - only be used for older versions of <productname>Windows</productname> where - the native build does not work, such as - <productname>Windows 98</productname>. <productname>MinGW</productname> is - only recommended if you are building other modules using it. The official + To produce native 64 bit binaries in these environments, use the tools from + <productname>MinGW-w64</productname>. These tools can also be used to + cross-compile for 32 bit and 64 bit <productname>Windows</productname> + targets on other hosts, such as <productname>Linux</productname> and + <productname>Darwin</productname>. + <productname>Cygwin</productname> is not recommended for running a + production server, and it should only be used for running on + older versions of <productname>Windows</productname> where + the native build does not work, such as + <productname>Windows 98</productname>. The official binaries are built using <productname>Visual Studio</productname>. </para> - <sect1 id="install-win32-full"> + <para> + Native builds of <application>psql</application> don't support command + line editing. The <productname>Cygwin</productname> build does support + command line editing, so it should be used where psql is needed for + interactive use on <productname>Windows</productname>. + </para> + + <sect1 id="install-windows-full"> <title>Building with <productname>Visual C++</productname> or the <productname>Platform SDK</productname></title> <para> PostgreSQL can be built using the Visual C++ compiler suite from Microsoft. These compilers can be either from <productname>Visual Studio</productname>, - <productname>Visual Studio Express</productname> or recent versions of the + <productname>Visual Studio Express</productname> or some versions of the <productname>Platform SDK</productname>. If you do not already have a <productname>Visual Studio</productname> environment set up, the easiest way us to use the compilers in the <productname>Platform SDK</productname>, @@ -76,6 +87,14 @@ <productname>Visual Studio 2008</productname>. When using the Platform SDK only, or when building for 64-bit Windows, only <productname>Visual Studio 2008</productname> is supported. + <productname>Visual Studio 2010</productname> is not yet supported. + </para> + + <para> + When building using the <productname>Platform SDK</productname>, versions + 6.0 to 7.0 of the SDK are supported. Older or newer versions will not work. + In particular, versions from 7.0a and later will not work, since + they include compilers from <productname>Visual Studio 2010</productname>. </para> <para> @@ -102,9 +121,9 @@ and then apply any changes from <filename>config.pl</filename>. For example, to specify the location of your <productname>Python</productname> installation, put the following in <filename>config.pl</filename>: - <screen> - $config->{python} = 'c:\python26'; - </screen> +<programlisting> +$config->{python} = 'c:\python26'; +</programlisting> You only need to specify those parameters that are different from what's in <filename>config_default.pl</filename>. </para> @@ -114,9 +133,9 @@ <filename>buildenv.pl</filename> and put the required commands there. For example, to add the path for bison when it's not in the PATH, create a file containing: - <screen> - $ENV{PATH}=$ENV{PATH} . ';c:\some\where\bison\bin'; - </screen> +<programlisting> +$ENV{PATH}=$ENV{PATH} . ';c:\some\where\bison\bin'; +</programlisting> </para> <sect2> @@ -131,9 +150,10 @@ <varlistentry> <term><productname>Microsoft Platform SDK</productname></term> <listitem><para> - It is recommended that you upgrade to the latest available version - of the <productname>Microsoft Platform SDK</productname>, available - for download from <ulink url="http://www.microsoft.com/downloads/"></>. + It is recommended that you upgrade to the latest supported version + of the <productname>Microsoft Platform SDK</productname> (currently + version 7.0), available for download from + <ulink url="http://www.microsoft.com/downloads/"></>. </para> <para> You must always include the @@ -176,13 +196,24 @@ <term><productname>Bison</productname> and <productname>Flex</productname></term> <listitem><para> - Bison and Flex are required to build from CVS, but not required when + Bison and Flex are required to build from Git, but not required when building from a release file. Note that only Bison 1.875 or versions 2.2 and later will work. Also, Flex version 2.5.31 or later is required. Bison can be downloaded from <ulink url="http://gnuwin32.sourceforge.net"></>. - Flex can be downloaded from + Flex can be downloaded from <ulink url="http://www.postgresql.org/ftp/misc/winflex/"></>. - </para></listitem> + </para> + + <note> + <para> + The Bison distribution from GnuWin32 appears to have a bug that + causes Bison to malfunction when installed in a directory with + spaces in the name, such as the default location on English + installations <filename>C:\Program Files\GnuWin32</filename>. + Consider installing into <filename>C:\GnuWin32</filename> instead. + </para> + </note> + </listitem> </varlistentry> <varlistentry> @@ -206,7 +237,7 @@ <term><productname>MIT Kerberos</productname></term> <listitem><para> Required for Kerberos authentication support. MIT Kerberos can be - downloaded from + downloaded from <ulink url="http://web.mit.edu/Kerberos/dist/index.html"></>. </para></listitem> </varlistentry> @@ -234,7 +265,7 @@ <varlistentry> <term><productname>ossp-uuid</productname></term> <listitem><para> - Required for UUID-OSSP support (contrib only). Source can be + Required for UUID-OSSP support (contrib only). Source can be downloaded from <ulink url="http://www.ossp.org/pkg/lib/uuid/"></>. </para></listitem> @@ -262,7 +293,7 @@ </sect2> <sect2> - <title>Special considerations for 64-bit Windows</title> + <title>Special Considerations for 64-bit Windows</title> <para> PostgreSQL will only build for the x64 architecture on 64-bit Windows, there @@ -292,43 +323,31 @@ <para> To build all of PostgreSQL in release configuration (the default), run the command: - <screen> - <userinput> - build - </userinput> - </screen> +<screen> +<userinput>build</userinput> +</screen> To build all of PostgreSQL in debug configuration, run the command: - <screen> - <userinput> - build DEBUG - </userinput> - </screen> +<screen> +<userinput>build DEBUG</userinput> +</screen> To build just a single project, for example psql, run the commands: - <screen> - <userinput> - build psql - </userinput> - <userinput> - build DEBUG psql - </userinput> - </screen> +<screen> +<userinput>build psql</userinput> +<userinput>build DEBUG psql</userinput> +</screen> To change the default build configuration to debug, put the following in the <filename>buildenv.pl</filename> file: - <screen> - <userinput> - $ENV{CONFIG}="Debug"; - </userinput> - </screen> +<programlisting> +$ENV{CONFIG}="Debug"; +</programlisting> </para> <para> It is also possible to build from inside the Visual Studio GUI. In this case, you need to run: - <screen> - <userinput> - perl mkvcbuild.pl - </userinput> - </screen> +<screen> +<userinput>perl mkvcbuild.pl</userinput> +</screen> from the command prompt, and then open the generated <filename>pgsql.sln</filename> (in the root directory of the source tree) in Visual Studio. @@ -336,7 +355,7 @@ </sect2> <sect2> - <title>Cleaning and installing</title> + <title>Cleaning and Installing</title> <para> Most of the time, the automatic dependency tracking in Visual Studio will @@ -354,16 +373,14 @@ <filename>debug</filename> or <filename>release</filename> directories. To install these files using the standard layout, and also generate the files required to initialize and use the database, run the command: - <screen> - <userinput> - install c:\destination\directory - </userinput> - </screen> +<screen> +<userinput>install c:\destination\directory</userinput> +</screen> </para> </sect2> <sect2> - <title>Running the regression tests</title> + <title>Running the Regression Tests</title> <para> To run the regression tests, make sure you have completed the build of all @@ -373,28 +390,18 @@ the <filename>buildenv.pl</filename> file. To run the tests, run one of the following commands from the <filename>src\tools\msvc</filename> directory: - <screen> - <userinput> - vcregress check - </userinput> - <userinput> - vcregress installcheck - </userinput> - <userinput> - vcregress plcheck - </userinput> - <userinput> - vcregress contribcheck - </userinput> - </screen> +<screen> +<userinput>vcregress check</userinput> +<userinput>vcregress installcheck</userinput> +<userinput>vcregress plcheck</userinput> +<userinput>vcregress contribcheck</userinput> +</screen> To change the schedule used (default is parallel), append it to the command line like: - <screen> - <userinput> - vcregress check serial - </userinput> - </screen> +<screen> +<userinput>vcregress check serial</userinput> +</screen> For more information about the regression tests, see <xref linkend="regress">. @@ -402,7 +409,7 @@ </sect2> <sect2> - <title>Building the documentation</title> + <title>Building the Documentation</title> <para> Building the PostgreSQL documentation in HTML format requires several tools @@ -448,9 +455,9 @@ </variablelist> Edit the <filename>buildenv.pl</filename> file, and add a variable for the location of the root directory, for example: - <screen> - $ENV{DOCROOT}='c:\docbook'; - </screen> +<programlisting> +$ENV{DOCROOT}='c:\docbook'; +</programlisting> To build the documentation, run the command <filename>builddoc.bat</filename>. Note that this will actually run the build twice, in order to generate the indexes. The generated HTML files @@ -460,7 +467,7 @@ </sect1> - <sect1 id="install-win32-libpq"> + <sect1 id="install-windows-libpq"> <title>Building <application>libpq</application> with <productname>Visual C++</productname> or <productname>Borland C++</productname></title> @@ -505,7 +512,7 @@ </para> <sect2> - <title>Generated files</title> + <title>Generated Files</title> <para> The following files will be built: @@ -518,7 +525,7 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term><filename>interfaces\libpq\Release\libpqdll.lib</filename></term> <listitem> diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index 01f57a70e3..0410cff4ac 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -1,4 +1,10 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/installation.sgml,v 1.348 2010/07/05 18:54:37 tgl Exp $ --> +<!-- doc/src/sgml/installation.sgml --> +<!-- + +Use </link> not just </> so INSTALL.html can be created without links +to the main documentation. Don't use <xref>. + +--> <chapter id="installation"> <title><![%standalone-include[<productname>PostgreSQL</>]]> @@ -68,8 +74,8 @@ su - postgres <primary>make</primary> </indexterm> - <acronym>GNU</> <application>make</> is required; other - <application>make</> programs will <emphasis>not</> work. + <acronym>GNU</> <application>make</> version 3.80 or newer is required; other + <application>make</> programs or older <acronym>GNU</> <application>make</> versions will <emphasis>not</> work. <acronym>GNU</> <application>make</> is often installed under the name <filename>gmake</filename>; this document will always refer to it by that name. (On some systems @@ -79,7 +85,6 @@ su - postgres <screen> <userinput>gmake --version</userinput> </screen> - It is recommended to use version 3.79.1 or later. </para> </listitem> @@ -97,9 +102,7 @@ su - postgres <para> <application>tar</> is required to unpack the source distribution, in addition to either - <application>gzip</> or <application>bzip2</>. In - addition, <application>gzip</> is required to install the - documentation. + <application>gzip</> or <application>bzip2</>. </para> </listitem> @@ -139,7 +142,7 @@ su - postgres <primary>zlib</primary> </indexterm> - The <productname>zlib</productname> compression library will be + The <productname>zlib</productname> compression library is used by default. If you don't want to use it then you must specify the <option>--without-zlib</option> option to <filename>configure</filename>. Using this option disables @@ -169,6 +172,11 @@ su - postgres recent <productname>Perl</productname> versions, but it was not in earlier versions, and in any case it is the choice of whomever installed Perl at your site. + If you intend to make more than incidental use of + <application>PL/Perl</application>, you should ensure that the + <productname>Perl</productname> installation was built with the + <literal>usemultiplicity</> option enabled (<literal>perl -V</> + will show whether this is the case). </para> <para> @@ -237,7 +245,7 @@ su - postgres <listitem> <para> - If you want to build the <application>PL/Tcl</application> + To build the <application>PL/Tcl</application> procedural language, you of course need a <productname>Tcl</> installation. If you are using a pre-8.4 release of <productname>Tcl</>, ensure that it was built without multithreading @@ -266,17 +274,17 @@ su - postgres <listitem> <para> - <application>Kerberos</>, <productname>OpenSSL</>, + You need <application>Kerberos</>, <productname>OpenSSL</>, <productname>OpenLDAP</>, and/or <application>PAM</>, if you want to support authentication or - encryption using these services. + encryption using those services. </para> </listitem> </itemizedlist> </para> <para> - If you are building from a <acronym>CVS</acronym> tree instead of + If you are building from a <productname>Git</productname> tree instead of using a released source package, or if you want to do server development, you also need the following packages: @@ -297,7 +305,7 @@ su - postgres </indexterm> GNU <application>Flex</> and <application>Bison</> - are needed to build from a CVS checkout, or if you changed the actual + are needed to build from a Git checkout, or if you changed the actual scanner and parser definition files. If you need them, be sure to get <application>Flex</> 2.5.31 or later and <application>Bison</> 1.875 or later. Other <application>lex</> @@ -310,7 +318,7 @@ su - postgres <primary>perl</primary> </indexterm> - <application>Perl</> 5.8 or later is needed to build from a CVS checkout, + <application>Perl</> 5.8 or later is needed to build from a Git checkout, or if you changed the input files for any of the build steps that use Perl scripts. If building on Windows you will need <application>Perl</> in any case. @@ -363,169 +371,18 @@ su - postgres <para> You can also get the source directly from the version control repository, see - <xref linkend="cvs">. + <xref linkend="sourcerepo">. </para> </sect1> ]]> - <sect1 id="install-upgrading"> - <title>Upgrading</title> - - <indexterm zone="install-upgrading"> - <primary>upgrading</primary> - </indexterm> - - <para> - These instructions assume that your existing installation is under the - <filename>/usr/local/pgsql</> directory, and that the data area is in - <filename>/usr/local/pgsql/data</>. Substitute your paths - appropriately. - </para> - - <para> - The internal data storage format typically changes in every major - release of <productname>PostgreSQL</>. Therefore, if you are upgrading - an existing installation that does not have a version number of - <quote>&majorversion;.x</quote>, you must back up and restore your - data. If you are upgrading from <productname>PostgreSQL</> - <quote>&majorversion;.x</quote>, the new version can use your current - data files so you should skip the backup and restore steps below because - they are unnecessary. - </para> - - <procedure> - <step> - <para> - If making a backup, make sure that your database is not being updated. - This does not affect the integrity of the backup, but the changed - data would of course not be included. If necessary, edit the - permissions in the file <filename>/usr/local/pgsql/data/pg_hba.conf</> - (or equivalent) to disallow access from everyone except you. - </para> - - <para> - <indexterm> - <primary>pg_dumpall</primary> - <secondary>use during upgrade</secondary> - </indexterm> - - To back up your database installation, type: -<screen> -<userinput>pg_dumpall > <replaceable>outputfile</></userinput> -</screen> - If you need to preserve OIDs (such as when using them as - foreign keys), then use the <option>-o</option> option when running - <application>pg_dumpall</>. - </para> - - <para> - To make the backup, you can use the <application>pg_dumpall</application> - command from the version you are currently running. For best - results, however, try to use the <application>pg_dumpall</application> - command from <productname>PostgreSQL</productname> &version;, - since this version contains bug fixes and improvements over older - versions. While this advice might seem idiosyncratic since you - haven't installed the new version yet, it is advisable to follow - it if you plan to install the new version in parallel with the - old version. In that case you can complete the installation - normally and transfer the data later. This will also decrease - the downtime. - </para> - </step> - - <step> - <para> - Shut down the old server: -<screen> -<userinput>pg_ctl stop</> -</screen> - On systems that have <productname>PostgreSQL</> started at boot time, - there is probably a start-up file that will accomplish the same thing. For - example, on a <systemitem class="osname">Red Hat Linux</> system one - might find that this works: -<screen> -<userinput>/etc/rc.d/init.d/postgresql stop</userinput> -</screen> - </para> - </step> - - <step> - <para> - If restoring from backup, rename or delete the old installation - directory. It is a good idea to rename the directory, rather than - delete it, in case you have trouble and need to revert to it. Keep - in mind the directory might consume significant disk space. To rename - the directory, use a command like this: -<screen> -<userinput>mv /usr/local/pgsql /usr/local/pgsql.old</> -</screen> - </para> - </step> - - <step> - <para> - Install the new version of <productname>PostgreSQL</productname> as - outlined in <![%standalone-include[the next section.]]> - <![%standalone-ignore[<xref linkend="install-procedure">.]]> - </para> - </step> - - <step> - <para> - Create a new database cluster if needed. Remember that you must - execute these commands while logged in to the special database user - account (which you already have if you are upgrading). -<programlisting> -<userinput>/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data</> -</programlisting> - </para> - </step> - - <step> - <para> - Restore your previous <filename>pg_hba.conf</> and any - <filename>postgresql.conf</> modifications. - </para> - </step> - - <step> - <para> - Start the database server, again using the special database user - account: -<programlisting> -<userinput>/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data</> -</programlisting> - </para> - </step> - - <step> - <para> - Finally, restore your data from backup with: -<screen> -<userinput>/usr/local/pgsql/bin/psql -d postgres -f <replaceable>outputfile</></userinput> -</screen> - using the <emphasis>new</> <application>psql</>. - </para> - </step> - </procedure> - - <para> - Further discussion appears in - <![%standalone-include[the documentation,]]> - <![%standalone-ignore[<xref linkend="migration">,]]> - including instructions on how the previous installation can continue - running while the new installation is installed. - </para> - </sect1> - - <sect1 id="install-procedure"> <title>Installation Procedure</title> <procedure> <step id="configure"> - <title>Configuration</> + <title>Configuration</title> <indexterm zone="configure"> <primary>configure</primary> @@ -1004,9 +861,12 @@ su - postgres <term><option>--with-ossp-uuid</option></term> <listitem> <para> - Use the <ulink url="http://www.ossp.org/pkg/lib/uuid/">OSSP UUID - library</ulink> when building <filename>contrib/uuid-ossp</>. - The library provides functions to generate + Build components using the <ulink + url="http://www.ossp.org/pkg/lib/uuid/">OSSP UUID + library</ulink>. Specifically, build the + <![%standalone-include[uuid-ossp]]> + <![%standalone-ignore[<xref linkend="uuid-ossp">]]> module, + which provides functions to generate UUIDs.<indexterm><primary>UUID</primary></indexterm> </para> </listitem> @@ -1039,9 +899,11 @@ su - postgres <term><option>--with-libxslt</option></term> <listitem> <para> - Use libxslt when building <filename>contrib/xml2</>. - <filename>contrib/xml2</> relies on this library to perform - XSL transformations of XML. + Use libxslt when building the + <![%standalone-include[xml2]]> + <![%standalone-ignore[<xref linkend="xml2">]]> + module. <application>xml2</> relies on this library + to perform XSL transformations of XML. </para> </listitem> </varlistentry> @@ -1219,14 +1081,15 @@ su - postgres pointed to works correctly with <productname>PostgreSQL</>. </para> + <indexterm><primary>cross compilation</primary></indexterm> + <para> This option is mainly aimed at binary package distributors who know their target operating system well. The main advantage of using this option is that the PostgreSQL package won't need to be upgraded whenever any of the many local daylight-saving time rules change. Another advantage is that - PostgreSQL can be cross-compiled<indexterm><primary>cross - compilation</primary></indexterm> more straightforwardly if the + PostgreSQL can be cross-compiled more straightforwardly if the time zone database files do not need to be built during the installation. </para> @@ -1515,7 +1378,14 @@ su - postgres <listitem> <para> Full path to the Python interpreter. This will be used to - determine the dependencies for building PL/Python. + determine the dependencies for building PL/Python. Also, + whether Python 2 or 3 is specified here (or otherwise + implicitly chosen) determines which variant of the PL/Python + language becomes available. See + <![%standalone-include[the <application>PL/Python</> + documentation]]> + <![%standalone-ignore[<xref linkend="plpython-python23">]]> + for more information. </para> </listitem> </varlistentry> @@ -1605,10 +1475,11 @@ PostgreSQL, contrib and HTML documentation successfully made. Ready to install. <note> <para> - If you are upgrading an existing system and are going to install - the new files over the old ones, be sure to back up - your data and shut down the old server before proceeding, as explained in - <xref linkend="install-upgrading"> above. + If you are upgrading an existing system be sure to read + <![%standalone-include[the documentation,]]> + <![%standalone-ignore[<xref linkend="upgrading">]]> + which has instructions about upgrading a + cluster. </para> </note> @@ -2090,7 +1961,7 @@ kill `cat /usr/local/pgsql/data/postmaster.pid` </sect1> <sect1 id="installation-platform-notes"> - <title>Platform-Specific Notes</title> + <title>Platform-specific Notes</title> <para> This section documents additional platform-specific issues @@ -2119,87 +1990,59 @@ kill `cat /usr/local/pgsql/data/postmaster.pid` <para> PostgreSQL works on AIX, but getting it installed properly can be challenging. AIX versions from 4.3.3 to 6.1 are considered supported. - You can use GCC or the native IBM compiler xlc. In + You can use GCC or the native IBM compiler <command>xlc</command>. In general, using recent versions of AIX and PostgreSQL helps. Check the build farm for up to date information about which versions of AIX are known to work. </para> <para> - Use the following <command>configure</command> flags in addition - to your own if you have installed Readline or libz - there: <literal>--with-includes=/usr/local/include - --with-libraries=/usr/local/lib</literal>. + The minimum recommended fix levels for supported AIX versions are: </para> - <para> - If you don't have a PowerPC or use GCC you might see rounding - differences in the geometry regression test. There will probably - be warnings about 0.0/0.0 division and duplicate symbols which you - can safely ignore. - </para> - - <para> - Some of the AIX tools may be <quote>a little different</quote> - from what you may be accustomed to on other platforms. If you are - looking for a version of <command>ldd</command>, useful for - determining what object code depends on what libraries, the - following URLs may help you: - <ulink url="http://www.faqs.org/faqs/aix-faq/part4/section-22.html"></ulink>, - <ulink url="http://www.han.de/~jum/aix/ldd.c"></ulink>. - </para> + <variablelist> + <varlistentry> + <term>AIX 4.3.3</term> + <listitem><para>Maintenance Level 11 + post ML11 bundle</para></listitem> + </varlistentry> + + <varlistentry> + <term>AIX 5.1</term> + <listitem><para>Maintenance Level 9 + post ML9 bundle</para></listitem> + </varlistentry> + + <varlistentry> + <term>AIX 5.2</term> + <listitem><para>Technology Level 10 Service Pack 3</para></listitem> + </varlistentry> + + <varlistentry> + <term>AIX 5.3</term> + <listitem><para>Technology Level 7</para></listitem> + </varlistentry> + + <varlistentry> + <term>AIX 6.1</term> + <listitem><para>Base Level</para></listitem> + </varlistentry> + </variablelist> <para> - <xref linkend="AIX-fixlevels"> shows the minimum recommended fix levels - for various AIX versions. To check your current fix level, use + To check your current fix level, use <command>oslevel -r</command> in AIX 4.3.3 to AIX 5.2 ML 7, or <command>oslevel -s</command> in later versions. </para> - <table id="AIX-fixlevels"> - <title> - Minimum recommended <systemitem class="osname">AIX</systemitem> fix levels - </title> - - <tgroup cols="2"> - <thead> - <row> - <entry>AIX version</entry> - <entry>fix level</entry> - </row> - </thead> - - <tbody> - <row> - <entry>AIX 4.3.3</entry> - <entry>Maintenance Level 11 + post ML11 bundle</entry> - </row> - - <row> - <entry>AIX 5.1</entry> - <entry>Maintenance Level 9 + post ML9 bundle</entry> - </row> - - <row> - <entry>AIX 5.2</entry> - <entry>Technology Level 10 Service Pack 3</entry> - </row> - - <row> - <entry>AIX 5.3</entry> - <entry>Technology Level 7</entry> - </row> - - <row> - <entry>AIX 6.1</entry> - <entry>Base Level</entry> - </row> - </tbody> - </tgroup> - </table> + <para> + Use the following <command>configure</command> flags in addition + to your own if you have installed Readline or libz in + <literal>/usr/local</>: + <literal>--with-includes=/usr/local/include + --with-libraries=/usr/local/lib</literal>. + </para> <sect3> - <title>GCC issues</title> + <title>GCC Issues</title> <para> On AIX 5.3, there have been some problems getting PostgreSQL to @@ -2217,7 +2060,7 @@ kill `cat /usr/local/pgsql/data/postmaster.pid` </sect3> <sect3> - <title>Unix-domain sockets broken</title> + <title>Unix-Domain Sockets Broken</title> <para> AIX 5.3 has a problem @@ -2243,15 +2086,15 @@ kill `cat /usr/local/pgsql/data/postmaster.pid` </sect3> <sect3> - <title>Internet address issues</title> + <title>Internet Address Issues</title> <para> PostgreSQL relies on the system's <function>getaddrinfo</> function to parse IP addresses in <varname>listen_addresses</>, <filename>pg_hba.conf</>, etc. Older versions of AIX have assorted bugs in this function. If you have problems related to these settings, - updating to the appropriate fix level shown in <xref - linkend="AIX-fixlevels"> should take care of it. + updating to the appropriate AIX fix level shown above + should take care of it. </para> <!-- http://archives.postgresql.org/message-id/6064jt6cfm.fsf_-_@dba2.int.libertyrms.com --> @@ -2301,19 +2144,21 @@ hosts=local4,bind4 </itemizedlist> </para> - <warning> <para> This is really a workaround of problems relating - to immaturity of IPv6 support, which improved visibly during the - course of AIX 5.3 releases. It has worked with AIX version 5.3, - but does not represent an elegant solution to the problem. It has - been reported that this workaround is not only unnecessary, but - causes problems on AIX 6.1, where IPv6 support has become more - mature. </para> + <warning> + <para> + This is really a workaround for problems relating + to immaturity of IPv6 support, which improved visibly during the + course of AIX 5.3 releases. It has worked with AIX version 5.3, + but does not represent an elegant solution to the problem. It has + been reported that this workaround is not only unnecessary, but + causes problems on AIX 6.1, where IPv6 support has become more mature. + </para> </warning> </sect3> <sect3> - <title>Memory management</title> + <title>Memory Management</title> <!-- http://archives.postgresql.org/message-id/603bgqmpl9.fsf@dba2.int.libertyrms.com --> <para> @@ -2327,7 +2172,7 @@ hosts=local4,bind4 -bash-3.00$ createlang plperl template1 createlang: language installation failed: ERROR: could not load library "/opt/dbs/pgsql748/lib/plperl.so": A memory address is not in the address space for the process. </screen> - Running as a non-owner in the group posessing the PostgreSQL + Running as a non-owner in the group possessing the PostgreSQL installation: <screen> -bash-3.00$ createlang plperl template1 @@ -2408,7 +2253,7 @@ createlang: language installation failed: ERROR: could not load library "/opt/d </para> <bibliography> - <title>References and resources</title> + <title>References and Resources</title> <biblioentry> <biblioset relation="article"> @@ -2476,8 +2321,8 @@ createlang: language installation failed: ERROR: could not load library "/opt/d <para> PostgreSQL can be built using Cygwin, a Linux-like environment for Windows, but that method is inferior to the native Windows build - <![%standalone-ignore[(see <xref linkend="install-win32">)]]> and - is no longer recommended. + <![%standalone-ignore[(see <xref linkend="install-windows">)]]> and + running a server under Cygwin is no longer recommended. </para> <para> @@ -2497,7 +2342,7 @@ createlang: language installation failed: ERROR: could not load library "/opt/d <listitem> <para> - The GNU make command is called "make" not "gmake". + The GNU make command is called <command>make</command>, not <command>gmake</command>. </para> </listitem> @@ -2538,6 +2383,16 @@ createlang: language installation failed: ERROR: could not load library "/opt/d <listitem> <para> + Building might fail on some systems where a locale other than + C is in use. To fix this, set the locale to C by doing + <command>export LANG=C.utf8</command> before building, and then + setting it back to the previous setting, after you have installed + PostgreSQL. + </para> + </listitem> + + <listitem> + <para> The parallel regression tests (<literal>make check</literal>) can generate spurious regression test failures due to overflowing the <function>listen()</function> backlog queue @@ -2583,7 +2438,7 @@ make MAX_CONNECTIONS=5 check <para> Aside from the PostgreSQL source distribution, you will need GNU make (HP's make will not do), and either GCC or HP's full ANSI C - compiler. If you intend to build from CVS sources rather than a + compiler. If you intend to build from Git sources rather than a distribution tarball, you will also need Flex (GNU lex) and Bison (GNU yacc). We also recommend making sure you are fairly up-to-date on HP patches. At a minimum, if you are building 64 @@ -2727,7 +2582,7 @@ cc-1020 cc: ERROR File = pqcomm.c, Line = 427 The MinGW build variant uses the normal build system described in this chapter; the Visual C++ build works completely differently and is described in <![%standalone-include[the - documentation]]><![%standalone-ignore[<xref linkend="install-win32">]]>. + documentation]]><![%standalone-ignore[<xref linkend="install-windows">]]>. It is a fully native build and uses no additional software like MinGW. A ready-made installer is available on the main PostgreSQL web site. @@ -2746,11 +2601,35 @@ cc-1020 cc: ERROR File = pqcomm.c, Line = 427 </para> <para> + To build 64 bit binaries using MinGW, install the 64 bit tool set + from <ulink url="http://mingw-w64.sourceforge.net/"></ulink>, put its bin + directory in the <envar>PATH</envar>, and run + <command>configure</command> with the + <command>--host=x86_64-w64-mingw</command> option. + </para> + + <para> After you have everything installed, it is suggested that you run <application>psql</application> under <command>CMD.EXE</command>, as the MSYS console has buffering issues. </para> + + <sect3 id="windows-crash-dumps"> + <title>Collecting Crash Dumps on Windows</title> + + <para> + If PostgreSQL on Windows crashes, it has the ability to generate + <productname>minidumps</> that can be used to track down the cause + for the crash, similar to core dumps on Unix. These dumps can be + read using the <productname>Windows Debugger Tools</> or using + <productname>Visual Studio</>. To enable the generation of dumps + on Windows, create a subdirectory named <filename>crashdumps</filename> + inside the cluster data directory. The dumps will then be written + into this directory with a unique name based on the identifier of + the crashing process and the current time of the crash. + </para> + </sect3> </sect2> <sect2 id="installation-notes-sco"> @@ -2859,7 +2738,7 @@ cc-1020 cc: ERROR File = pqcomm.c, Line = 427 </sect3> <sect3> - <title>Reading the PostgreSQL man pages</title> + <title>Reading the PostgreSQL Man Pages</title> <para> By default, the PostgreSQL man pages are installed into @@ -2933,13 +2812,13 @@ MANPATH=/usr/lib/scohelp/%L/man:/usr/dt/man:/usr/man:/usr/share/man:scohelp:/usr </para> <sect3> - <title>Required tools</title> + <title>Required Tools</title> <para> You can build with either GCC or Sun's compiler suite. For better code optimization, Sun's compiler is strongly recommended on the SPARC architecture. We have heard reports of problems - when using GCC 2.95.1; gcc 2.95.3 or later is recommended. If + when using GCC 2.95.1; GCC 2.95.3 or later is recommended. If you are using Sun's compiler, be careful not to select <filename>/usr/ucb/cc</filename>; use <filename>/opt/SUNWspro/bin/cc</filename>. @@ -2983,7 +2862,7 @@ MANPATH=/usr/lib/scohelp/%L/man:/usr/dt/man:/usr/man:/usr/share/man:scohelp:/usr </sect3> <sect3> - <title>configure complains about a failed test program</title> + <title>configure Complains About a Failed Test Program</title> <para> If <command>configure</command> complains about a failed test @@ -3002,13 +2881,13 @@ configure ... LDFLAGS="-R /usr/sfw/lib:/opt/sfw/lib:/usr/local/lib" </sect3> <sect3> - <title>64-bit build sometimes crashes</title> + <title>64-bit Build Sometimes Crashes</title> <para> On Solaris 7 and older, the 64-bit version of libc has a buggy <function>vsnprintf</function> routine, which leads to erratic core dumps in PostgreSQL. The simplest known workaround is to - force PostgreSQL to use its own version of vsnprintf rather than + force PostgreSQL to use its own version of <function>vsnprintf</function> rather than the library copy. To do this, after you run <command>configure</command> edit a file produced by <command>configure</command>: @@ -3026,7 +2905,7 @@ LIBOBJS = snprintf.o </sect3> <sect3> - <title>Compiling for optimal performance</title> + <title>Compiling for Optimal Performance</title> <para> On the SPARC architecture, Sun Studio is strongly recommended for @@ -3059,7 +2938,7 @@ LIBOBJS = snprintf.o </sect3> <sect3> - <title>Using DTrace for tracing PostgreSQL</title> + <title>Using DTrace for Tracing PostgreSQL</title> <para> Yes, using DTrace is possible. See <![%standalone-include[the @@ -3070,7 +2949,7 @@ LIBOBJS = snprintf.o </para> <para> - If you see the linking of the postgres executable abort with an + If you see the linking of the <command>postgres</command> executable abort with an error message like: <screen> Undefined first referenced diff --git a/doc/src/sgml/intagg.sgml b/doc/src/sgml/intagg.sgml index b33e7c62de..ea5acbe91f 100644 --- a/doc/src/sgml/intagg.sgml +++ b/doc/src/sgml/intagg.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/intagg.sgml,v 1.4 2008/11/14 19:58:45 tgl Exp $ --> +<!-- doc/src/sgml/intagg.sgml --> -<sect1 id="intagg"> +<sect1 id="intagg" xreflabel="intagg"> <title>intagg</title> <indexterm zone="intagg"> @@ -44,24 +44,20 @@ <para> Many database systems have the notion of a one to many table. Such a table usually sits between two indexed tables, for example: - </para> - <programlisting> +<programlisting> CREATE TABLE left (id INT PRIMARY KEY, ...); CREATE TABLE right (id INT PRIMARY KEY, ...); CREATE TABLE one_to_many(left INT REFERENCES left, right INT REFERENCES right); - </programlisting> +</programlisting> - <para> It is typically used like this: - </para> - <programlisting> - SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right) - WHERE one_to_many.left = <replaceable>item</>; - </programlisting> +<programlisting> +SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right) + WHERE one_to_many.left = <replaceable>item</>; +</programlisting> - <para> This will return all the items in the right hand table for an entry in the left hand table. This is a very common construct in SQL. </para> @@ -74,35 +70,29 @@ CREATE TABLE one_to_many(left INT REFERENCES left, right INT REFERENCES right); left hand entry. If you have a very dynamic system, there is not much you can do. However, if you have some data which is fairly static, you can create a summary table with the aggregator. - </para> - <programlisting> -CREATE TABLE summary as +<programlisting> +CREATE TABLE summary AS SELECT left, int_array_aggregate(right) AS right FROM one_to_many GROUP BY left; - </programlisting> +</programlisting> - <para> This will create a table with one row per left item, and an array of right items. Now this is pretty useless without some way of using the array; that's why there is an array enumerator. You can do - </para> - <programlisting> +<programlisting> SELECT left, int_array_enum(right) FROM summary WHERE left = <replaceable>item</>; - </programlisting> +</programlisting> - <para> The above query using <function>int_array_enum</> produces the same results as - </para> - <programlisting> +<programlisting> SELECT left, right FROM one_to_many WHERE left = <replaceable>item</>; - </programlisting> +</programlisting> - <para> The difference is that the query against the summary table has to get only one row from the table, whereas the direct query against <structname>one_to_many</> must index scan and fetch a row for each entry. @@ -112,9 +102,8 @@ SELECT left, right FROM one_to_many WHERE left = <replaceable>item</>; On one system, an <command>EXPLAIN</> showed a query with a cost of 8488 was reduced to a cost of 329. The original query was a join involving the <structname>one_to_many</> table, which was replaced by: - </para> - <programlisting> +<programlisting> SELECT right, count(right) FROM ( SELECT left, int_array_enum(right) AS right FROM summary JOIN (SELECT left FROM left_table WHERE left = <replaceable>item</>) AS lefts @@ -122,7 +111,8 @@ SELECT right, count(right) FROM ) AS list GROUP BY right ORDER BY count DESC; - </programlisting> +</programlisting> + </para> </sect2> diff --git a/doc/src/sgml/intarray.sgml b/doc/src/sgml/intarray.sgml index 8dda468fe3..2bbd98ae37 100644 --- a/doc/src/sgml/intarray.sgml +++ b/doc/src/sgml/intarray.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/intarray.sgml,v 1.10 2010/05/05 15:10:25 heikki Exp $ --> +<!-- doc/src/sgml/intarray.sgml --> -<sect1 id="intarray"> +<sect1 id="intarray" xreflabel="intarray"> <title>intarray</title> <indexterm zone="intarray"> @@ -9,13 +9,30 @@ <para> The <filename>intarray</> module provides a number of useful functions - and operators for manipulating one-dimensional arrays of integers. + and operators for manipulating null-free arrays of integers. There is also support for indexed searches using some of the operators. </para> + <para> + All of these operations will throw an error if a supplied array contains any + NULL elements. + </para> + + <para> + Many of these operations are only sensible for one-dimensional arrays. + Although they will accept input arrays of more dimensions, the data is + treated as though it were a linear array in storage order. + </para> + <sect2> <title><filename>intarray</> Functions and Operators</title> + <para> + The functions provided by the <filename>intarray</filename> module + are shown in <xref linkend="intarray-func-table">, the operators + in <xref linkend="intarray-op-table">. + </para> + <table id="intarray-func-table"> <title><filename>intarray</> Functions</title> @@ -207,18 +224,16 @@ <literal><@</> were respectively called <literal>@</> and <literal>~</>. These names are still available, but are deprecated and will eventually be retired. Notice that the old names are reversed from the convention - formerly followed by the core geometric datatypes!) + formerly followed by the core geometric data types!) </para> <para> - The containment operators <literal>@></> and <literal><@</> are - approximately equivalent to <productname>PostgreSQL</>'s built-in operators - of the same names, except that they work only on integer arrays while the - built-in operators work for any array type. An important difference is - that <filename>intarray</>'s operators do not consider an empty array to be - contained in anything else. This is consistent with the behavior of - GIN-indexed queries, but not with the usual mathematical definition of - containment. + The operators <literal>&&</>, <literal>@></> and + <literal><@</> are equivalent to <productname>PostgreSQL</>'s built-in + operators of the same names, except that they work only on integer arrays + that do not contain nulls, while the built-in operators work for any array + type. This restriction makes them faster than the built-in operators + in many cases. </para> <para> @@ -271,7 +286,7 @@ <sect2> <title>Example</title> - <programlisting> +<programlisting> -- a message can be in one or more <quote>sections</> CREATE TABLE message (mid INT PRIMARY KEY, sections INT[], ...); @@ -286,7 +301,7 @@ SELECT message.mid FROM message WHERE message.sections @> '{1,2}'; -- the same, using QUERY operator SELECT message.mid FROM message WHERE message.sections @@ '1&2'::query_int; - </programlisting> +</programlisting> </sect2> <sect2> @@ -297,13 +312,13 @@ SELECT message.mid FROM message WHERE message.sections @@ '1&2'::query_int; benchmark test suite. To run: </para> - <programlisting> - cd .../bench - createdb TEST - psql TEST < ../_int.sql - ./create_test.pl | psql TEST - ./bench.pl - </programlisting> +<programlisting> +cd .../bench +createdb TEST +psql TEST < ../_int.sql +./create_test.pl | psql TEST +./bench.pl +</programlisting> <para> The <filename>bench.pl</> script has numerous options, which diff --git a/doc/src/sgml/intro.sgml b/doc/src/sgml/intro.sgml index b5945dacac..4d3f93f317 100644 --- a/doc/src/sgml/intro.sgml +++ b/doc/src/sgml/intro.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/intro.sgml,v 1.36 2010/03/17 17:12:31 petere Exp $ --> +<!-- doc/src/sgml/intro.sgml --> <preface id="preface"> <title>Preface</title> diff --git a/doc/src/sgml/isn.sgml b/doc/src/sgml/isn.sgml index 8469a98825..f10285473d 100644 --- a/doc/src/sgml/isn.sgml +++ b/doc/src/sgml/isn.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/isn.sgml,v 1.5 2009/05/18 11:08:24 petere Exp $ --> +<!-- doc/src/sgml/isn.sgml --> -<sect1 id="isn"> +<sect1 id="isn" xreflabel="isn"> <title>isn</title> <indexterm zone="isn"> @@ -10,19 +10,31 @@ <para> The <filename>isn</filename> module provides data types for the following international product numbering standards: EAN13, UPC, ISBN (books), ISMN - (music), and ISSN (serials). Numbers are validated on input, and correctly - hyphenated on output. + (music), and ISSN (serials). Numbers are validated on input according to a + hard-coded list of prefixes; this list of prefixes is also used to hyphenate + numbers on output. Since new prefixes are assigned from time to time, the + list of prefixes may be out of date. It is hoped that a future version of + this module will obtained the prefix list from one or more tables that + can be easily updated by users as needed; however, at present, the + list can only be updated by modifying the source code and recompiling. + Alternatively, prefix validation and hyphenation support may be + dropped from a future version of this module. </para> <sect2> - <title>Data types</title> + <title>Data Types</title> - <table> - <title><filename>isn</filename> data types</title> + <para> + <xref linkend="isn-datatypes"> shows the data types provided by + the <filename>isn</filename> module. + </para> + + <table id="isn-datatypes"> + <title><filename>isn</filename> Data Types</title> <tgroup cols="2"> <thead> <row> - <entry>Data type</entry> + <entry>Data Type</entry> <entry>Description</entry> </row> </thead> @@ -209,14 +221,14 @@ <para> The <filename>isn</> module provides the standard comparison operators, - plus btree and hash indexing support for all these datatypes. In + plus B-tree and hash indexing support for all these data types. In addition there are several specialized functions; shown in <xref linkend="isn-functions">. In this table, <type>isn</> means any one of the module's data types. </para> <table id="isn-functions"> - <title><filename>isn</> functions</title> + <title><filename>isn</> Functions</title> <tgroup cols="3"> <thead> <row> @@ -295,7 +307,7 @@ <sect2> <title>Examples</title> - <programlisting> +<programlisting> --Using the types directly: SELECT isbn('978-0-393-04002-9'); SELECT isbn13('0901690546'); @@ -333,7 +345,7 @@ UPDATE test SET id = make_valid(id) WHERE id = '2-205-00876-X!'; SELECT * FROM test; SELECT isbn13(id) FROM test; - </programlisting> +</programlisting> </sect2> <sect2> @@ -342,24 +354,20 @@ SELECT isbn13(id) FROM test; <para> The information to implement this module was collected from several sites, including: - </para> - <programlisting> - http://www.isbn-international.org/ - http://www.issn.org/ - http://www.ismn-international.org/ - http://www.wikipedia.org/ - </programlisting> + <itemizedlist> + <listitem><para><ulink url="http://www.isbn-international.org/"></ulink></para></listitem> + <listitem><para><ulink url="http://www.issn.org/"></ulink></para></listitem> + <listitem><para><ulink url="http://www.ismn-international.org/"></ulink></para></listitem> + <listitem><para><ulink url="http://www.wikipedia.org/"></ulink></para></listitem> + </itemizedlist> - <para> The prefixes used for hyphenation were also compiled from: - </para> - <programlisting> - http://www.gs1.org/productssolutions/idkeys/support/prefix_list.html - http://www.isbn-international.org/en/identifiers.html - http://www.ismn-international.org/ranges.html - </programlisting> + <itemizedlist> + <listitem><para><ulink url="http://www.gs1.org/productssolutions/idkeys/support/prefix_list.html"></ulink></para></listitem> + <listitem><para><ulink url="http://www.isbn-international.org/en/identifiers.html"></ulink></para></listitem> + <listitem><para><ulink url="http://www.ismn-international.org/ranges.html"></ulink></para></listitem> + </itemizedlist> - <para> Care was taken during the creation of the algorithms and they were meticulously verified against the suggested algorithms in the official ISBN, ISMN, ISSN User Manuals. @@ -369,12 +377,12 @@ SELECT isbn13(id) FROM test; <sect2> <title>Author</title> <para> - Germán Méndez Bravo (Kronuz), 2004 - 2006 + Germán Méndez Bravo (Kronuz), 2004 - 2006 </para> <para> This module was inspired by Garrett A. Wollman's - isbn_issn code. + <filename>isbn_issn</> code. </para> </sect2> diff --git a/doc/src/sgml/jadetex.cfg b/doc/src/sgml/jadetex.cfg index 45ff76ffbb..25b79312eb 100644 --- a/doc/src/sgml/jadetex.cfg +++ b/doc/src/sgml/jadetex.cfg @@ -1,4 +1,4 @@ -% $PostgreSQL: pgsql/doc/src/sgml/jadetex.cfg,v 1.1 2010/04/29 16:32:41 tgl Exp $ +% doc/src/sgml/jadetex.cfg % % This file redefines FlowObjectSetup to eliminate one of the two control % sequences it normally creates, thereby substantially reducing string usage diff --git a/doc/src/sgml/keywords.sgml b/doc/src/sgml/keywords.sgml index 2fc180ae86..9c49e07153 100644 --- a/doc/src/sgml/keywords.sgml +++ b/doc/src/sgml/keywords.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.31 2010/03/02 20:40:48 petere Exp $ --> +<!-- doc/src/sgml/keywords.sgml --> <appendix id="sql-keywords-appendix"> <title><acronym>SQL</acronym> Key Words</title> @@ -18,7 +18,7 @@ <para> SQL distinguishes between <firstterm>reserved</firstterm> and <firstterm>non-reserved</firstterm> key words. According to the standard, - reserved key words + reserved key words are the only real key words; they are never allowed as identifiers. Non-reserved key words only have a special meaning in particular contexts and can be used as identifiers in other contexts. Most @@ -369,7 +369,7 @@ </row> <row> <entry><token>ATTRIBUTE</token></entry> - <entry></entry> + <entry>non-reserved</entry> <entry>non-reserved</entry> <entry>non-reserved</entry> <entry></entry> @@ -817,7 +817,7 @@ </row> <row> <entry><token>COLLATION</token></entry> - <entry></entry> + <entry>non-reserved</entry> <entry>non-reserved</entry> <entry>non-reserved</entry> <entry>reserved</entry> @@ -1152,30 +1152,6 @@ <entry>reserved</entry> </row> <row> - <entry><token>CREATEDB</token></entry> - <entry>non-reserved</entry> - <entry></entry> - <entry></entry> - <entry></entry> - <entry></entry> - </row> - <row> - <entry><token>CREATEROLE</token></entry> - <entry>non-reserved</entry> - <entry></entry> - <entry></entry> - <entry></entry> - <entry></entry> - </row> - <row> - <entry><token>CREATEUSER</token></entry> - <entry>non-reserved</entry> - <entry></entry> - <entry></entry> - <entry></entry> - <entry></entry> - </row> - <row> <entry><token>CROSS</token></entry> <entry>reserved (can be function or type)</entry> <entry>reserved</entry> @@ -1976,6 +1952,14 @@ <entry></entry> </row> <row> + <entry><token>EXTENSION</token></entry> + <entry>non-reserved</entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + </row> + <row> <entry><token>EXTERNAL</token></entry> <entry>non-reserved</entry> <entry>reserved</entry> @@ -2744,6 +2728,14 @@ <entry></entry> </row> <row> + <entry><token>LABEL</token></entry> + <entry>non-reserved</entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + </row> + <row> <entry><token>LAG</token></entry> <entry></entry> <entry>reserved</entry> @@ -2976,14 +2968,6 @@ <entry></entry> </row> <row> - <entry><token>LOGIN</token></entry> - <entry>non-reserved</entry> - <entry></entry> - <entry></entry> - <entry></entry> - <entry></entry> - </row> - <row> <entry><token>LOWER</token></entry> <entry></entry> <entry>reserved</entry> @@ -3336,46 +3320,6 @@ <entry>reserved</entry> </row> <row> - <entry><token>NOCREATEDB</token></entry> - <entry>non-reserved</entry> - <entry></entry> - <entry></entry> - <entry></entry> - <entry></entry> - </row> - <row> - <entry><token>NOCREATEROLE</token></entry> - <entry>non-reserved</entry> - <entry></entry> - <entry></entry> - <entry></entry> - <entry></entry> - </row> - <row> - <entry><token>NOCREATEUSER</token></entry> - <entry>non-reserved</entry> - <entry></entry> - <entry></entry> - <entry></entry> - <entry></entry> - </row> - <row> - <entry><token>NOINHERIT</token></entry> - <entry>non-reserved</entry> - <entry></entry> - <entry></entry> - <entry></entry> - <entry></entry> - </row> - <row> - <entry><token>NOLOGIN</token></entry> - <entry>non-reserved</entry> - <entry></entry> - <entry></entry> - <entry></entry> - <entry></entry> - </row> - <row> <entry><token>NONE</token></entry> <entry>non-reserved (cannot be function or type)</entry> <entry>reserved</entry> @@ -3400,14 +3344,6 @@ <entry></entry> </row> <row> - <entry><token>NOSUPERUSER</token></entry> - <entry>non-reserved</entry> - <entry></entry> - <entry></entry> - <entry></entry> - <entry></entry> - </row> - <row> <entry><token>NOT</token></entry> <entry>reserved</entry> <entry>reserved</entry> @@ -3553,7 +3489,7 @@ </row> <row> <entry><token>OFF</token></entry> - <entry>reserved</entry> + <entry>non-reserved</entry> <entry>non-reserved</entry> <entry>non-reserved</entry> <entry>reserved</entry> @@ -3865,7 +3801,7 @@ </row> <row> <entry><token>PASSING</token></entry> - <entry></entry> + <entry>non-reserved</entry> <entry>non-reserved</entry> <entry></entry> <entry></entry> @@ -4169,7 +4105,7 @@ </row> <row> <entry><token>REF</token></entry> - <entry></entry> + <entry>non-reserved</entry> <entry>reserved</entry> <entry>reserved</entry> <entry>reserved</entry> @@ -5088,14 +5024,6 @@ <entry>reserved</entry> </row> <row> - <entry><token>SUPERUSER</token></entry> - <entry>non-reserved</entry> - <entry></entry> - <entry></entry> - <entry></entry> - <entry></entry> - </row> - <row> <entry><token>SYMMETRIC</token></entry> <entry>reserved</entry> <entry>reserved</entry> @@ -5544,6 +5472,14 @@ <entry></entry> </row> <row> + <entry><token>UNLOGGED</token></entry> + <entry>non-reserved</entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + </row> + <row> <entry><token>UNNAMED</token></entry> <entry></entry> <entry>non-reserved</entry> @@ -5672,6 +5608,14 @@ <entry></entry> </row> <row> + <entry><token>VALIDATE</token></entry> + <entry>non-reserved</entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + </row> + <row> <entry><token>VALIDATOR</token></entry> <entry>non-reserved</entry> <entry></entry> @@ -5961,7 +5905,7 @@ </row> <row> <entry><token>XMLEXISTS</token></entry> - <entry></entry> + <entry>non-reserved (cannot be function or type)</entry> <entry>reserved</entry> <entry></entry> <entry></entry> diff --git a/doc/src/sgml/legal.sgml b/doc/src/sgml/legal.sgml index cbd1ae0d32..4531686341 100644 --- a/doc/src/sgml/legal.sgml +++ b/doc/src/sgml/legal.sgml @@ -1,7 +1,7 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/legal.sgml,v 1.25 2010/01/02 16:57:33 momjian Exp $ --> +<!-- doc/src/sgml/legal.sgml --> <copyright> - <year>1996-2010</year> + <year>1996-2011</year> <holder>The PostgreSQL Global Development Group</holder> </copyright> @@ -9,13 +9,13 @@ <title>Legal Notice</title> <para> - <productname>PostgreSQL</productname> is Copyright © 1996-2010 + <productname>PostgreSQL</productname> is Copyright © 1996-2011 by the PostgreSQL Global Development Group and is distributed under the terms of the license of the University of California below. </para> <para> - <productname>Postgres95</productname> is Copyright © 1994-5 + <productname>Postgres95</productname> is Copyright © 1994-5 by the Regents of the University of California. </para> diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 9e047b110d..b359000ab3 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.313 2010/07/08 10:20:14 mha Exp $ --> +<!-- doc/src/sgml/libpq.sgml --> <chapter id="libpq"> <title><application>libpq</application> - C Library</title> @@ -79,27 +79,27 @@ <para> On Windows, there is a way to improve performance if a single database connection is repeatedly started and shutdown. Internally, - libpq calls WSAStartup() and WSACleanup() for connection startup - and shutdown, respectively. WSAStartup() increments an internal - Windows library reference count which is decremented by WSACleanup(). - When the reference count is just one, calling WSACleanup() frees + libpq calls <function>WSAStartup()</> and <function>WSACleanup()</> for connection startup + and shutdown, respectively. <function>WSAStartup()</> increments an internal + Windows library reference count which is decremented by <function>WSACleanup()</>. + When the reference count is just one, calling <function>WSACleanup()</> frees all resources and all DLLs are unloaded. This is an expensive operation. To avoid this, an application can manually call - WSAStartup() so resources will not be freed when the last database + <function>WSAStartup()</> so resources will not be freed when the last database connection is closed. </para> </note> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqconnectdbparams"> <term><function>PQconnectdbParams</function><indexterm><primary>PQconnectdbParams</></></term> <listitem> <para> Makes a new connection to the database server. - <synopsis> - PGconn *PQconnectdbParams(const char **keywords, const char **values, int expand_dbname); - </synopsis> +<synopsis> +PGconn *PQconnectdbParams(const char **keywords, const char **values, int expand_dbname); +</synopsis> </para> <para> @@ -162,22 +162,40 @@ <para> Using <literal>hostaddr</> instead of <literal>host</> allows the - application to avoid a host name look-up, which might be important in - applications with time constraints. However, Kerberos and GSSAPI authentication - requires the host name. The following therefore applies: If - <literal>host</> is specified without <literal>hostaddr</>, a host name - lookup occurs. If <literal>hostaddr</> is specified without - <literal>host</>, the value for <literal>hostaddr</> gives the remote - address. When Kerberos is used, a reverse name query occurs to obtain - the host name for Kerberos. If both - <literal>host</> and <literal>hostaddr</> are specified, the value for - <literal>hostaddr</> gives the remote address; the value for - <literal>host</> is ignored, unless Kerberos is used, in which case that - value is used for Kerberos authentication. (Note that authentication is - likely to fail if <application>libpq</application> is passed a host name - that is not the name of the machine at <literal>hostaddr</>.) Also, - <literal>host</> rather than <literal>hostaddr</> is used to identify - the connection in <filename>~/.pgpass</> (see + application to avoid a host name look-up, which might be important + in applications with time constraints. However, a host name is + required for Kerberos, GSSAPI, or SSPI authentication + methods, as well as for <literal>verify-full</> SSL + certificate verification. The following rules are used: + <itemizedlist> + <listitem> + <para> + If <literal>host</> is specified without <literal>hostaddr</>, + a host name lookup occurs. + </para> + </listitem> + <listitem> + <para> + If <literal>hostaddr</> is specified without <literal>host</>, + the value for <literal>hostaddr</> gives the server network address. + The connection attempt will fail if the authentication + method requires a host name. + </para> + </listitem> + <listitem> + <para> + If both <literal>host</> and <literal>hostaddr</> are specified, + the value for <literal>hostaddr</> gives the server network address. + The value for <literal>host</> is ignored unless the + authentication method requires it, in which case it will be + used as the host name. + </para> + </listitem> + </itemizedlist> + Note that authentication is likely to fail if <literal>host</> + is not the name of the server at network address <literal>hostaddr</>. + Also, note that <literal>host</> rather than <literal>hostaddr</> + is used to identify the connection in <filename>~/.pgpass</> (see <xref linkend="libpq-pgpass">). </para> @@ -241,6 +259,21 @@ </listitem> </varlistentry> + <varlistentry id="libpq-connect-client-encoding" xreflabel="client_encoding"> + <term><literal>client_encoding</literal></term> + <listitem> + <para> + This sets the <varname>client_encoding</varname> + configuration parameter for this connection. In addition to + the values accepted by the corresponding server option, you + can use <literal>auto</literal> to determine the right + encoding from the current locale in the client + (<envar>LC_CTYPE</envar> environment variable on Unix + systems). + </para> + </listitem> + </varlistentry> + <varlistentry id="libpq-connect-options" xreflabel="options"> <term><literal>options</literal></term> <listitem> @@ -352,63 +385,70 @@ This option determines whether or with what priority a secure <acronym>SSL</> TCP/IP connection will be negotiated with the server. There are six modes: - </para> - <table id="libpq-connect-sslmode-options"> - <title><literal>sslmode</literal> options</title> - <tgroup cols="2"> - <thead> - <row> - <entry>Option</entry> - <entry>Description</entry> - </row> - </thead> - - <tbody> - - <row> - <entry><literal>disable</></entry> - <entry>only try a non-<acronym>SSL</> connection</entry> - </row> - - <row> - <entry><literal>allow</></entry> - <entry>first try a non-<acronym>SSL</> - connection; if that fails, try an <acronym>SSL</> - connection</entry> - </row> - - <row> - <entry><literal>prefer</> (default)</entry> - <entry>first try an <acronym>SSL</> connection; if - that fails, try a non-<acronym>SSL</> - connection</entry> - </row> - - <row> - <entry><literal>require</></entry> - <entry>only try an <acronym>SSL</> connection</entry> - </row> - - <row> - <entry><literal>verify-ca</></entry> - <entry>only try an <acronym>SSL</> connection, and verify that - the server certificate is issued by a trusted <acronym>CA</> - </entry> - </row> - - <row> - <entry><literal>verify-full</></entry> - <entry>only try an <acronym>SSL</> connection, verify that - the server certificate is issued by a trusted <acronym>CA</> and - that the server hostname matches that in the certificate</entry> - </row> - - </tbody> - </tgroup> - </table> + <variablelist> + <varlistentry> + <term><literal>disable</literal></term> + <listitem> + <para> + only try a non-<acronym>SSL</> connection + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>allow</literal></term> + <listitem> + <para> + first try a non-<acronym>SSL</> connection; if that + fails, try an <acronym>SSL</> connection + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>prefer</literal> (default)</term> + <listitem> + <para> + first try an <acronym>SSL</> connection; if that fails, + try a non-<acronym>SSL</> connection + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>require</literal></term> + <listitem> + <para> + only try an <acronym>SSL</> connection + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>verify-ca</literal></term> + <listitem> + <para> + only try an <acronym>SSL</> connection, and verify that + the server certificate is issued by a trusted + certificate authority (<acronym>CA</>) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>verify-full</literal></term> + <listitem> + <para> + only try an <acronym>SSL</> connection, verify that the + server certificate is issued by a + trusted <acronym>CA</> and that the server host name + matches that in the certificate + </para> + </listitem> + </varlistentry> + </variablelist> - <para> See <xref linkend="libpq-ssl"> for a detailed description of how these options work. </para> @@ -457,7 +497,7 @@ This parameter specifies the file name of the client SSL certificate, replacing the default <filename>~/.postgresql/postgresql.crt</>. - This parameter is ignored if an SSL connection is not made. + This parameter is ignored if an SSL connection is not made. </para> </listitem> </varlistentry> @@ -467,7 +507,7 @@ <listitem> <para> This parameter specifies the location for the secret key used for - the client certificate. It can either specify a filename that will + the client certificate. It can either specify a file name that will be used instead of the default <filename>~/.postgresql/postgresql.key</>, or it can specify a key obtained from an external <quote>engine</> (engines are @@ -505,6 +545,29 @@ </listitem> </varlistentry> + <varlistentry id="libpq-connect-requirepeer" xreflabel="requirepeer"> + <term><literal>requirepeer</literal></term> + <listitem> + <para> + This parameter specifies the operating-system user name of the + server, for example <literal>requirepeer=postgres</literal>. + When making a Unix-domain socket connection, if this + parameter is set, the client checks at the beginning of the + connection that the server process is running under the specified + user name; if it is not, the connection is aborted with an error. + This parameter can be used to provide server authentication similar + to that available with SSL certificates on TCP/IP connections. + (Note that if the Unix-domain socket is in + <filename>/tmp</filename> or another publicly writable location, + any user could start a server listening there. Use this parameter + to ensure that you are connected to a server run by a trusted user.) + This option is only supported on platforms for which the + <literal>peer</> authentication method is implemented; see + <xref linkend="auth-peer">. + </para> + </listitem> + </varlistentry> + <varlistentry id="libpq-connect-krbsrvname" xreflabel="krbsrvname"> <term><literal>krbsrvname</literal></term> <listitem> @@ -568,15 +631,15 @@ </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqconnectdb"> <term><function>PQconnectdb</function><indexterm><primary>PQconnectdb</></></term> <listitem> <para> Makes a new connection to the database server. - <synopsis> - PGconn *PQconnectdb(const char *conninfo); - </synopsis> +<synopsis> +PGconn *PQconnectdb(const char *conninfo); +</synopsis> </para> <para> @@ -601,7 +664,7 @@ </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsetdblogin"> <term><function>PQsetdbLogin</function><indexterm><primary>PQsetdbLogin</></></term> <listitem> <para> @@ -633,7 +696,7 @@ PGconn *PQsetdbLogin(const char *pghost, </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsetdb"> <term><function>PQsetdb</function><indexterm><primary>PQsetdb</></></term> <listitem> <para> @@ -655,7 +718,7 @@ PGconn *PQsetdb(char *pghost, </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqconnectstartparams"> <term><function>PQconnectStartParams</function><indexterm><primary>PQconnectStartParams</></></term> <term><function>PQconnectStart</function><indexterm><primary>PQconnectStart</></></term> <term><function>PQconnectPoll</function><indexterm><primary>PQconnectPoll</></></term> @@ -664,17 +727,15 @@ PGconn *PQsetdb(char *pghost, <indexterm><primary>nonblocking connection</primary></indexterm> Make a connection to the database server in a nonblocking manner. - <synopsis> - PGconn *PQconnectStartParams(const char **keywords, const char **values, int expand_dbname); - </synopsis> +<synopsis> +PGconn *PQconnectStartParams(const char **keywords, + const char **values, + int expand_dbname); - <synopsis> - PGconn *PQconnectStart(const char *conninfo); - </synopsis> +PGconn *PQconnectStart(const char *conninfo); - <synopsis> - PostgresPollingStatusType PQconnectPoll(PGconn *conn); - </synopsis> +PostgresPollingStatusType PQconnectPoll(PGconn *conn); +</synopsis> </para> <para> @@ -767,8 +828,8 @@ PGconn *PQsetdb(char *pghost, <para> At any time during connection, the status of the connection can be - checked by calling <function>PQstatus</>. If this gives <symbol>CONNECTION_BAD</>, then the - connection procedure has failed; if it gives <function>CONNECTION_OK</>, then the + checked by calling <function>PQstatus</>. If this call returns <symbol>CONNECTION_BAD</>, then the + connection procedure has failed; if the call returns <function>CONNECTION_OK</>, then the connection is ready. Both of these states are equally detectable from the return value of <function>PQconnectPoll</>, described above. Other states might also occur during (and only during) an asynchronous connection procedure. These @@ -776,7 +837,7 @@ PGconn *PQsetdb(char *pghost, to provide feedback to the user for example. These statuses are: <variablelist> - <varlistentry> + <varlistentry id="libpq-connection-started"> <term><symbol>CONNECTION_STARTED</symbol></term> <listitem> <para> @@ -785,7 +846,7 @@ PGconn *PQsetdb(char *pghost, </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-connection-made"> <term><symbol>CONNECTION_MADE</symbol></term> <listitem> <para> @@ -794,7 +855,7 @@ PGconn *PQsetdb(char *pghost, </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-connection-awaiting-response"> <term><symbol>CONNECTION_AWAITING_RESPONSE</symbol></term> <listitem> <para> @@ -803,7 +864,7 @@ PGconn *PQsetdb(char *pghost, </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-connection-auth-ok"> <term><symbol>CONNECTION_AUTH_OK</symbol></term> <listitem> <para> @@ -812,7 +873,7 @@ PGconn *PQsetdb(char *pghost, </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-connection-ssl-startup"> <term><symbol>CONNECTION_SSL_STARTUP</symbol></term> <listitem> <para> @@ -821,7 +882,7 @@ PGconn *PQsetdb(char *pghost, </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-connection-setenv"> <term><symbol>CONNECTION_SETENV</symbol></term> <listitem> <para> @@ -872,7 +933,7 @@ switch(PQstatus(conn)) </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqconndefaults"> <term><function>PQconndefaults</function><indexterm><primary>PQconndefaults</></></term> <listitem> <para> @@ -918,7 +979,7 @@ typedef struct </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqconninfoparse"> <term><function>PQconninfoParse</function><indexterm><primary>PQconninfoParse</></></term> <listitem> <para> @@ -931,8 +992,8 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <para> Parses a connection string and returns the resulting options as an - array; or returns NULL if there is a problem with the connection - string. This can be used to determine + array; or returns <symbol>NULL</> if there is a problem with the connection + string. This function can be used to extract the <function>PQconnectdb</function> options in the provided connection string. The return value points to an array of <structname>PQconninfoOption</structname> structures, which ends @@ -945,33 +1006,33 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </para> <para> - If <literal>errmsg</> is not NULL, then <literal>*errmsg</> is set - to NULL on success, else to a malloc'd error string explaining + If <literal>errmsg</> is not <symbol>NULL</>, then <literal>*errmsg</> is set + to <symbol>NULL</> on success, else to a <function>malloc</>'d error string explaining the problem. (It is also possible for <literal>*errmsg</> to be - set to NULL even when NULL is returned; this indicates an out-of-memory - situation.) + set to <symbol>NULL</> and the function to return <symbol>NULL</>; + this indicates an out-of-memory condition.) </para> <para> After processing the options array, free it by passing it to <function>PQconninfoFree</function>. If this is not done, some memory is leaked for each call to <function>PQconninfoParse</function>. - Conversely, if an error occurs and <literal>errmsg</> is not NULL, + Conversely, if an error occurs and <literal>errmsg</> is not <symbol>NULL</>, be sure to free the error string using <function>PQfreemem</>. </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqfinish"> <term><function>PQfinish</function><indexterm><primary>PQfinish</></></term> <listitem> <para> Closes the connection to the server. Also frees memory used by the <structname>PGconn</structname> object. - <synopsis> - void PQfinish(PGconn *conn); - </synopsis> +<synopsis> +void PQfinish(PGconn *conn); +</synopsis> </para> <para> @@ -984,14 +1045,14 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqreset"> <term><function>PQreset</function><indexterm><primary>PQreset</></></term> <listitem> <para> Resets the communication channel to the server. - <synopsis> - void PQreset(PGconn *conn); - </synopsis> +<synopsis> +void PQreset(PGconn *conn); +</synopsis> </para> <para> @@ -1004,19 +1065,18 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqresetstart"> <term><function>PQresetStart</function><indexterm><primary>PQresetStart</></></term> <term><function>PQresetPoll</function><indexterm><primary>PQresetPoll</></></term> <listitem> <para> Reset the communication channel to the server, in a nonblocking manner. - <synopsis> - int PQresetStart(PGconn *conn); - </synopsis> - <synopsis> - PostgresPollingStatusType PQresetPoll(PGconn *conn); - </synopsis> +<synopsis> +int PQresetStart(PGconn *conn); + +PostgresPollingStatusType PQresetPoll(PGconn *conn); +</synopsis> </para> <para> @@ -1039,6 +1099,94 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </listitem> </varlistentry> + <varlistentry id="libpq-pqpingparams"> + <term><function>PQpingParams</function><indexterm><primary>PQpingParams</></></term> + <listitem> + <para> + <function>PQpingParams</function> reports the status of the + server. It accepts connection parameters identical to those of + <function>PQconnectdbParams</>, described above. It is not, however, + necessary to supply correct user name, password, or database name + values to obtain the server status. + +<synopsis> +PGPing PQpingParams(const char **keywords, const char **values, int expand_dbname); +</synopsis> + + The function returns one of the following values: + + <variablelist> + <varlistentry id="libpq-pqpingparams-pqping-ok"> + <term><literal>PQPING_OK</literal></term> + <listitem> + <para> + The server is running and appears to be accepting connections. + </para> + </listitem> + </varlistentry> + + <varlistentry id="libpq-pqpingparams-pqping-reject"> + <term><literal>PQPING_REJECT</literal></term> + <listitem> + <para> + The server is running but is in a state that disallows connections + (startup, shutdown, or crash recovery). + </para> + </listitem> + </varlistentry> + + <varlistentry id="libpq-pqpingparams-pqping-no-response"> + <term><literal>PQPING_NO_RESPONSE</literal></term> + <listitem> + <para> + The server could not be contacted. This might indicate that the + server is not running, or that there is something wrong with the + given connection parameters (for example, wrong port number), or + that there is a network connectivity problem (for example, a + firewall blocking the connection request). + </para> + </listitem> + </varlistentry> + + <varlistentry id="libpq-pqpingparams-pqping-no-attempt"> + <term><literal>PQPING_NO_ATTEMPT</literal></term> + <listitem> + <para> + No attempt was made to contact the server, because the supplied + parameters were obviously incorrect or there was some client-side + problem (for example, out of memory). + </para> + </listitem> + </varlistentry> + </variablelist> + + </para> + + </listitem> + </varlistentry> + + <varlistentry id="libpq-pqping"> + <term><function>PQping</function><indexterm><primary>PQping</></></term> + <listitem> + <para> + <function>PQping</function> reports the status of the + server. It accepts connection parameters identical to those of + <function>PQconnectdb</>, described above. It is not, however, + necessary to supply correct user name, password, or database name + values to obtain the server status. + +<synopsis> +PGPing PQping(const char *conninfo); +</synopsis> + </para> + + <para> + The return values are the same as for <function>PQpingParams</>. + </para> + + </listitem> + </varlistentry> + </variablelist> </para> </sect1> @@ -1069,7 +1217,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); These values are fixed for the life of the <structname>PGconn</> object. <variablelist> - <varlistentry> + <varlistentry id="libpq-pqdb"> <term> <function>PQdb</function> <indexterm> @@ -1080,14 +1228,14 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <listitem> <para> Returns the database name of the connection. - <synopsis> - char *PQdb(const PGconn *conn); - </synopsis> +<synopsis> +char *PQdb(const PGconn *conn); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pquser"> <term> <function>PQuser</function> <indexterm> @@ -1098,14 +1246,14 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <listitem> <para> Returns the user name of the connection. - <synopsis> - char *PQuser(const PGconn *conn); - </synopsis> +<synopsis> +char *PQuser(const PGconn *conn); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqpass"> <term> <function>PQpass</function> <indexterm> @@ -1116,14 +1264,14 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <listitem> <para> Returns the password of the connection. - <synopsis> - char *PQpass(const PGconn *conn); - </synopsis> +<synopsis> +char *PQpass(const PGconn *conn); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqhost"> <term> <function>PQhost</function> <indexterm> @@ -1134,14 +1282,14 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <listitem> <para> Returns the server host name of the connection. - <synopsis> - char *PQhost(const PGconn *conn); - </synopsis> +<synopsis> +char *PQhost(const PGconn *conn); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqport"> <term> <function>PQport</function> <indexterm> @@ -1153,14 +1301,14 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <para> Returns the port of the connection. - <synopsis> - char *PQport(const PGconn *conn); - </synopsis> +<synopsis> +char *PQport(const PGconn *conn); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqtty"> <term> <function>PQtty</function> <indexterm> @@ -1173,16 +1321,16 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); Returns the debug <acronym>TTY</acronym> of the connection. (This is obsolete, since the server no longer pays attention to the <acronym>TTY</acronym> setting, but the function remains - for backwards compatibility.) + for backward compatibility.) - <synopsis> - char *PQtty(const PGconn *conn); - </synopsis> +<synopsis> +char *PQtty(const PGconn *conn); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqoptions"> <term> <function>PQoptions</function> <indexterm> @@ -1193,9 +1341,9 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <listitem> <para> Returns the command-line options passed in the connection request. - <synopsis> - char *PQoptions(const PGconn *conn); - </synopsis> +<synopsis> +char *PQoptions(const PGconn *conn); +</synopsis> </para> </listitem> </varlistentry> @@ -1207,7 +1355,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); are executed on the <structname>PGconn</> object. <variablelist> - <varlistentry> + <varlistentry id="libpq-pqstatus"> <term> <function>PQstatus</function> <indexterm> @@ -1218,9 +1366,9 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <listitem> <para> Returns the status of the connection. - <synopsis> - ConnStatusType PQstatus(const PGconn *conn); - </synopsis> +<synopsis> +ConnStatusType PQstatus(const PGconn *conn); +</synopsis> </para> <para> @@ -1241,12 +1389,12 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <para> See the entry for <function>PQconnectStartParams</>, <function>PQconnectStart</> and <function>PQconnectPoll</> with regards to other status codes that - might be seen. + might be returned. </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqtransactionstatus"> <term> <function>PQtransactionStatus</function> <indexterm> @@ -1258,9 +1406,9 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <para> Returns the current in-transaction status of the server. - <synopsis> - PGTransactionStatusType PQtransactionStatus(const PGconn *conn); - </synopsis> +<synopsis> +PGTransactionStatusType PQtransactionStatus(const PGconn *conn); +</synopsis> The status can be <literal>PQTRANS_IDLE</literal> (currently idle), <literal>PQTRANS_ACTIVE</literal> (a command is in progress), @@ -1282,7 +1430,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqparameterstatus"> <term> <function>PQparameterStatus</function> <indexterm> @@ -1294,9 +1442,9 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <para> Looks up a current parameter setting of the server. - <synopsis> - const char *PQparameterStatus(const PGconn *conn, const char *paramName); - </synopsis> +<synopsis> +const char *PQparameterStatus(const PGconn *conn, const char *paramName); +</synopsis> Certain parameter values are reported by the server automatically at connection startup or whenever their values change. @@ -1307,46 +1455,46 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <para> Parameters reported as of the current release include - <literal>server_version</>, - <literal>server_encoding</>, - <literal>client_encoding</>, - <literal>application_name</>, - <literal>is_superuser</>, - <literal>session_authorization</>, - <literal>DateStyle</>, - <literal>IntervalStyle</>, - <literal>TimeZone</>, - <literal>integer_datetimes</>, and - <literal>standard_conforming_strings</>. - (<literal>server_encoding</>, <literal>TimeZone</>, and - <literal>integer_datetimes</> were not reported by releases before 8.0; - <literal>standard_conforming_strings</> was not reported by releases + <varname>server_version</>, + <varname>server_encoding</>, + <varname>client_encoding</>, + <varname>application_name</>, + <varname>is_superuser</>, + <varname>session_authorization</>, + <varname>DateStyle</>, + <varname>IntervalStyle</>, + <varname>TimeZone</>, + <varname>integer_datetimes</>, and + <varname>standard_conforming_strings</>. + (<varname>server_encoding</>, <varname>TimeZone</>, and + <varname>integer_datetimes</> were not reported by releases before 8.0; + <varname>standard_conforming_strings</> was not reported by releases before 8.1; - <literal>IntervalStyle</> was not reported by releases before 8.4; - <literal>application_name</> was not reported by releases before 9.0.) + <varname>IntervalStyle</> was not reported by releases before 8.4; + <varname>application_name</> was not reported by releases before 9.0.) Note that - <literal>server_version</>, - <literal>server_encoding</> and - <literal>integer_datetimes</> + <varname>server_version</>, + <varname>server_encoding</> and + <varname>integer_datetimes</> cannot change after startup. </para> <para> Pre-3.0-protocol servers do not report parameter settings, but <application>libpq</> includes logic to obtain values for - <literal>server_version</> and <literal>client_encoding</> anyway. + <varname>server_version</> and <varname>client_encoding</> anyway. Applications are encouraged to use <function>PQparameterStatus</> rather than <foreignphrase>ad hoc</> code to determine these values. (Beware however that on a pre-3.0 connection, changing - <literal>client_encoding</> via <command>SET</> after connection + <varname>client_encoding</> via <command>SET</> after connection startup will not be reflected by <function>PQparameterStatus</>.) - For <literal>server_version</>, see also + For <varname>server_version</>, see also <function>PQserverVersion</>, which returns the information in a numeric form that is much easier to compare against. </para> <para> - If no value for <literal>standard_conforming_strings</> is reported, + If no value for <varname>standard_conforming_strings</> is reported, applications can assume it is <literal>off</>, that is, backslashes are treated as escapes in string literals. Also, the presence of this parameter can be taken as an indication that the escape string @@ -1361,7 +1509,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqprotocolversion"> <term> <function>PQprotocolVersion</function> <indexterm> @@ -1372,12 +1520,13 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <listitem> <para> Interrogates the frontend/backend protocol being used. - <synopsis> - int PQprotocolVersion(const PGconn *conn); - </synopsis> - Applications might wish to use this to determine whether certain +<synopsis> +int PQprotocolVersion(const PGconn *conn); +</synopsis> + Applications might wish to use this function to determine whether certain features are supported. Currently, the possible values are 2 (2.0 - protocol), 3 (3.0 protocol), or zero (connection bad). This will + protocol), 3 (3.0 protocol), or zero (connection bad). The + protocol version will not change after connection startup is complete, but it could theoretically change during a connection reset. The 3.0 protocol will normally be used when communicating with @@ -1388,7 +1537,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqserverversion"> <term> <function>PQserverVersion</function> <indexterm> @@ -1399,10 +1548,10 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <listitem> <para> Returns an integer representing the backend version. - <synopsis> - int PQserverVersion(const PGconn *conn); - </synopsis> - Applications might use this to determine the version of the database +<synopsis> +int PQserverVersion(const PGconn *conn); +</synopsis> + Applications might use this function to determine the version of the database server they are connected to. The number is formed by converting the major, minor, and revision numbers into two-decimal-digit numbers and appending them together. For example, version 8.1.5 @@ -1413,7 +1562,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqerrormessage"> <term> <function>PQerrorMessage</function> <indexterm> @@ -1426,9 +1575,9 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <indexterm><primary>error message</></> Returns the error message most recently generated by an operation on the connection. - <synopsis> - char *PQerrorMessage(const PGconn *conn); - </synopsis> +<synopsis> +char *PQerrorMessage(const PGconn *conn); +</synopsis> </para> @@ -1436,7 +1585,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); Nearly all <application>libpq</> functions will set a message for <function>PQerrorMessage</function> if they fail. Note that by <application>libpq</application> convention, a nonempty - <function>PQerrorMessage</function> result can be multiple lines, + <function>PQerrorMessage</function> result can consist of multiple lines, and will include a trailing newline. The caller should not free the result directly. It will be freed when the associated <structname>PGconn</> handle is passed to @@ -1447,7 +1596,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsocket"> <term><function>PQsocket</function><indexterm><primary>PQsocket</></></term> <listitem> <para> @@ -1457,26 +1606,28 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); currently open. (This will not change during normal operation, but could change during connection setup or reset.) - <synopsis> - int PQsocket(const PGconn *conn); - </synopsis> +<synopsis> +int PQsocket(const PGconn *conn); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqbackendpid"> <term><function>PQbackendPID</function><indexterm><primary>PQbackendPID</></></term> <listitem> <para> - Returns the process <acronym>ID</acronym> - (PID)<indexterm><primary>PID</><secondary>determining PID of - server process</><tertiary>in libpq</></> of the backend server - process handling this connection. + Returns the process <acronym>ID</acronym> (PID)<indexterm> + <primary>PID</> + <secondary>determining PID of server process</> + <tertiary>in libpq</> + </indexterm> + of the backend process handling this connection. - <synopsis> - int PQbackendPID(const PGconn *conn); - </synopsis> +<synopsis> +int PQbackendPID(const PGconn *conn); +</synopsis> </para> <para> @@ -1490,7 +1641,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqconnectionneedspassword"> <term><function>PQconnectionNeedsPassword</function><indexterm><primary>PQconnectionNeedsPassword</></></term> <listitem> <para> @@ -1498,9 +1649,9 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); required a password, but none was available. Returns false (0) if not. - <synopsis> - int PQconnectionNeedsPassword(const PGconn *conn); - </synopsis> +<synopsis> +int PQconnectionNeedsPassword(const PGconn *conn); +</synopsis> </para> <para> @@ -1510,16 +1661,16 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqconnectionusedpassword"> <term><function>PQconnectionUsedPassword</function><indexterm><primary>PQconnectionUsedPassword</></></term> <listitem> <para> Returns true (1) if the connection authentication method used a password. Returns false (0) if not. - <synopsis> - int PQconnectionUsedPassword(const PGconn *conn); - </synopsis> +<synopsis> +int PQconnectionUsedPassword(const PGconn *conn); +</synopsis> </para> <para> @@ -1529,7 +1680,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqgetssl"> <term><function>PQgetssl</function><indexterm><primary>PQgetssl</></></term> <listitem> <para> @@ -1537,9 +1688,9 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); Returns the SSL structure used in the connection, or null if SSL is not in use. - <synopsis> - SSL *PQgetssl(const PGconn *conn); - </synopsis> +<synopsis> +SSL *PQgetssl(const PGconn *conn); +</synopsis> </para> <para> @@ -1576,7 +1727,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqexec"> <term> <function>PQexec</function> <indexterm> @@ -1588,9 +1739,9 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <para> Submits a command to the server and waits for the result. - <synopsis> - PGresult *PQexec(PGconn *conn, const char *command); - </synopsis> +<synopsis> +PGresult *PQexec(PGconn *conn, const char *command); +</synopsis> </para> <para> @@ -1606,8 +1757,8 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); </varlistentry> </variablelist> - It is allowed to include multiple SQL commands (separated by semicolons) - in the command string. Multiple queries sent in a single + The command string can include multiple SQL commands + (separated by semicolons). Multiple queries sent in a single <function>PQexec</> call are processed in a single transaction, unless there are explicit <command>BEGIN</command>/<command>COMMIT</command> commands included in the query string to divide it into multiple @@ -1620,7 +1771,7 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); <para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqexecparams"> <term> <function>PQexecParams</function> <indexterm> @@ -1740,7 +1891,7 @@ PGresult *PQexecParams(PGconn *conn, to be text strings. </para> <para> - Values passed in binary format require knowlege of + Values passed in binary format require knowledge of the internal representation expected by the backend. For example, integers must be passed in network byte order. Passing <type>numeric</> values requires @@ -1807,7 +1958,7 @@ SELECT * FROM mytable WHERE x = $1::bigint; <para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqprepare"> <term><function>PQprepare</function> <indexterm> <primary>PQprepare</primary> @@ -1874,9 +2025,7 @@ PGresult *PQprepare(PGconn *conn, Prepared statements for use with <function>PQexecPrepared</> can also be created by executing SQL <xref linkend="sql-prepare"> - statements. (But <function>PQprepare</> - is more flexible since it does not require parameter types to be - pre-specified.) Also, although there is no <application>libpq</> + statements. Also, although there is no <application>libpq</> function for deleting a prepared statement, the SQL <xref linkend="sql-deallocate"> statement can be used for that purpose. @@ -1884,7 +2033,7 @@ PGresult *PQprepare(PGconn *conn, <para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqexecprepared"> <term> <function>PQexecPrepared</function> <indexterm> @@ -1928,7 +2077,7 @@ PGresult *PQexecPrepared(PGconn *conn, </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqdescribeprepared"> <term> <function>PQdescribePrepared</function> <indexterm> @@ -1953,7 +2102,7 @@ PGresult *PQdescribePrepared(PGconn *conn, const char *stmtName); </para> <para> - <parameter>stmtName</> can be <literal>""</> or NULL to reference + <parameter>stmtName</> can be <literal>""</> or <symbol>NULL</> to reference the unnamed statement, otherwise it must be the name of an existing prepared statement. On success, a <structname>PGresult</> with status <literal>PGRES_COMMAND_OK</literal> is returned. The @@ -1968,7 +2117,7 @@ PGresult *PQdescribePrepared(PGconn *conn, const char *stmtName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqdescribeportal"> <term> <function>PQdescribePortal</function> <indexterm> @@ -1996,7 +2145,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </para> <para> - <parameter>portalName</> can be <literal>""</> or NULL to reference + <parameter>portalName</> can be <literal>""</> or <symbol>NULL</> to reference the unnamed portal, otherwise it must be the name of an existing portal. On success, a <structname>PGresult</> with status <literal>PGRES_COMMAND_OK</literal> is returned. The functions @@ -2021,7 +2170,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); are subject to change in the future. <variablelist> - <varlistentry> + <varlistentry id="libpq-pqresultstatus"> <term> <function>PQresultStatus</function> <indexterm> @@ -2032,16 +2181,16 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); <listitem> <para> Returns the result status of the command. - <synopsis> - ExecStatusType PQresultStatus(const PGresult *res); - </synopsis> +<synopsis> +ExecStatusType PQresultStatus(const PGresult *res); +</synopsis> </para> <para> <function>PQresultStatus</function> can return one of the following values: <variablelist> - <varlistentry> + <varlistentry id="libpq-pgres-empty-query"> <term><literal>PGRES_EMPTY_QUERY</literal></term> <listitem> <para> @@ -2050,7 +2199,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgres-command-ok"> <term><literal>PGRES_COMMAND_OK</literal></term> <listitem> <para> @@ -2059,7 +2208,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgres-tuples-ok"> <term><literal>PGRES_TUPLES_OK</literal></term> <listitem> <para> @@ -2069,7 +2218,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgres-copy-out"> <term><literal>PGRES_COPY_OUT</literal></term> <listitem> <para> @@ -2078,7 +2227,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgres-copy-in"> <term><literal>PGRES_COPY_IN</literal></term> <listitem> <para> @@ -2087,7 +2236,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgres-bad-response"> <term><literal>PGRES_BAD_RESPONSE</literal></term> <listitem> <para> @@ -2096,7 +2245,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgres-nonfatal-error"> <term><literal>PGRES_NONFATAL_ERROR</literal></term> <listitem> <para> @@ -2105,7 +2254,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgres-fatal-error"> <term><literal>PGRES_FATAL_ERROR</literal></term> <listitem> <para> @@ -2113,6 +2262,16 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </para> </listitem> </varlistentry> + + <varlistentry id="libpq-pgres-copy-both"> + <term><literal>PGRES_COPY_BOTH</literal></term> + <listitem> + <para> + Copy In/Out (to and from server) data transfer started. This is + currently used only for streaming replication. + </para> + </listitem> + </varlistentry> </variablelist> If the result status is <literal>PGRES_TUPLES_OK</literal>, then @@ -2136,7 +2295,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqresstatus"> <term> <function>PQresStatus</function> <indexterm> @@ -2150,14 +2309,14 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); <function>PQresultStatus</> into a string constant describing the status code. The caller should not free the result. - <synopsis> - char *PQresStatus(ExecStatusType status); - </synopsis> +<synopsis> +char *PQresStatus(ExecStatusType status); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqresulterrormessage"> <term> <function>PQresultErrorMessage</function> <indexterm> @@ -2169,9 +2328,9 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); <para> Returns the error message associated with the command, or an empty string if there was no error. - <synopsis> - char *PQresultErrorMessage(const PGresult *res); - </synopsis> +<synopsis> +char *PQresultErrorMessage(const PGresult *res); +</synopsis> If there was an error, the returned string will include a trailing newline. The caller should not free the result directly. It will be freed when the associated <structname>PGresult</> handle is @@ -2195,14 +2354,14 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqresulterrorfield"> <term><function>PQresultErrorField</function><indexterm><primary>PQresultErrorField</></></term> <listitem> <para> Returns an individual field of an error report. - <synopsis> - char *PQresultErrorField(const PGresult *res, int fieldcode); - </synopsis> +<synopsis> +char *PQresultErrorField(const PGresult *res, int fieldcode); +</synopsis> <parameter>fieldcode</> is an error field identifier; see the symbols listed below. <symbol>NULL</symbol> is returned if the <structname>PGresult</structname> is not an error or warning result, @@ -2216,7 +2375,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); <para> The following field codes are available: <variablelist> - <varlistentry> + <varlistentry id="libpq-pg-diag-severity"> <term><symbol>PG_DIAG_SEVERITY</></term> <listitem> <para> @@ -2229,7 +2388,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pg-diag-sqlstate"> <indexterm> <primary>error codes</primary> <secondary>libpq</secondary> @@ -2248,7 +2407,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pg-diag-message-primary"> <term><symbol>PG_DIAG_MESSAGE_PRIMARY</></term> <listitem> <para> @@ -2258,7 +2417,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pg-diag-message-detail"> <term><symbol>PG_DIAG_MESSAGE_DETAIL</></term> <listitem> <para> @@ -2268,7 +2427,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pg-diag-message-hint"> <term><symbol>PG_DIAG_MESSAGE_HINT</></term> <listitem> <para> @@ -2280,7 +2439,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pg-diag-statement-position"> <term><symbol>PG_DIAG_STATEMENT_POSITION</></term> <listitem> <para> @@ -2292,7 +2451,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pg-diag-internal-position"> <term><symbol>PG_DIAG_INTERNAL_POSITION</></term> <listitem> <para> @@ -2306,7 +2465,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pg-diag-internal-query"> <term><symbol>PG_DIAG_INTERNAL_QUERY</></term> <listitem> <para> @@ -2316,7 +2475,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pg-diag-context"> <term><symbol>PG_DIAG_CONTEXT</></term> <listitem> <para> @@ -2328,7 +2487,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pg-diag-source-file"> <term><symbol>PG_DIAG_SOURCE_FILE</></term> <listitem> <para> @@ -2338,7 +2497,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pg-diag-source-line"> <term><symbol>PG_DIAG_SOURCE_LINE</></term> <listitem> <para> @@ -2348,7 +2507,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pg-diag-source-function"> <term><symbol>PG_DIAG_SOURCE_FUNCTION</></term> <listitem> <para> @@ -2382,7 +2541,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqclear"> <term><function>PQclear</function><indexterm><primary>PQclear</></></term> <listitem> <para> @@ -2391,9 +2550,9 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); freed via <function>PQclear</function> when it is no longer needed. - <synopsis> - void PQclear(PGresult *res); - </synopsis> +<synopsis> +void PQclear(PGresult *res); +</synopsis> </para> <para> @@ -2424,7 +2583,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqntuples"> <term> <function>PQntuples</function> <indexterm> @@ -2438,15 +2597,15 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); it returns an integer result, large result sets might overflow the return value on 32-bit operating systems. - <synopsis> - int PQntuples(const PGresult *res); - </synopsis> +<synopsis> +int PQntuples(const PGresult *res); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqnfields"> <term> <function>PQnfields</function> <indexterm> @@ -2459,14 +2618,14 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); Returns the number of columns (fields) in each row of the query result. - <synopsis> - int PQnfields(const PGresult *res); - </synopsis> +<synopsis> +int PQnfields(const PGresult *res); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqfname"> <term> <function>PQfname</function> <indexterm> @@ -2481,10 +2640,10 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); directly. It will be freed when the associated <structname>PGresult</> handle is passed to <function>PQclear</function>. - <synopsis> - char *PQfname(const PGresult *res, - int column_number); - </synopsis> +<synopsis> +char *PQfname(const PGresult *res, + int column_number); +</synopsis> </para> <para> @@ -2493,7 +2652,7 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqfnumber"> <term> <function>PQfnumber</function> <indexterm> @@ -2504,10 +2663,10 @@ PGresult *PQdescribePortal(PGconn *conn, const char *portalName); <listitem> <para> Returns the column number associated with the given column name. - <synopsis> - int PQfnumber(const PGresult *res, - const char *column_name); - </synopsis> +<synopsis> +int PQfnumber(const PGresult *res, + const char *column_name); +</synopsis> </para> <para> @@ -2534,7 +2693,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqftable"> <term> <function>PQftable</function> <indexterm> @@ -2546,10 +2705,10 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> <para> Returns the OID of the table from which the given column was fetched. Column numbers start at 0. - <synopsis> - Oid PQftable(const PGresult *res, - int column_number); - </synopsis> +<synopsis> +Oid PQftable(const PGresult *res, + int column_number); +</synopsis> </para> <para> @@ -2569,7 +2728,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqftablecol"> <term> <function>PQftablecol</function> <indexterm> @@ -2582,10 +2741,10 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> Returns the column number (within its table) of the column making up the specified query result column. Query-result column numbers start at 0, but table columns have nonzero numbers. - <synopsis> - int PQftablecol(const PGresult *res, - int column_number); - </synopsis> +<synopsis> +int PQftablecol(const PGresult *res, + int column_number); +</synopsis> </para> <para> @@ -2596,7 +2755,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqfformat"> <term> <function>PQfformat</function> <indexterm> @@ -2608,10 +2767,10 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> <para> Returns the format code indicating the format of the given column. Column numbers start at 0. - <synopsis> - int PQfformat(const PGresult *res, - int column_number); - </synopsis> +<synopsis> +int PQfformat(const PGresult *res, + int column_number); +</synopsis> </para> <para> @@ -2622,7 +2781,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqftype"> <term> <function>PQftype</function> <indexterm> @@ -2635,10 +2794,10 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> Returns the data type associated with the given column number. The integer returned is the internal OID number of the type. Column numbers start at 0. - <synopsis> - Oid PQftype(const PGresult *res, - int column_number); - </synopsis> +<synopsis> +Oid PQftype(const PGresult *res, + int column_number); +</synopsis> </para> <para> @@ -2651,7 +2810,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqfmod"> <term> <function>PQfmod</function> <indexterm> @@ -2663,10 +2822,10 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> <para> Returns the type modifier of the column associated with the given column number. Column numbers start at 0. - <synopsis> - int PQfmod(const PGresult *res, - int column_number); - </synopsis> +<synopsis> +int PQfmod(const PGresult *res, + int column_number); +</synopsis> </para> <para> @@ -2679,7 +2838,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqfsize"> <term> <function>PQfsize</function> <indexterm> @@ -2691,10 +2850,10 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> <para> Returns the size in bytes of the column associated with the given column number. Column numbers start at 0. - <synopsis> - int PQfsize(const PGresult *res, - int column_number); - </synopsis> +<synopsis> +int PQfsize(const PGresult *res, + int column_number); +</synopsis> </para> <para> @@ -2707,7 +2866,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqbinarytuples"> <term> <function>PQbinaryTuples</function> <indexterm> @@ -2719,9 +2878,9 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> <para> Returns 1 if the <structname>PGresult</> contains binary data and 0 if it contains text data. - <synopsis> - int PQbinaryTuples(const PGresult *res); - </synopsis> +<synopsis> +int PQbinaryTuples(const PGresult *res); +</synopsis> </para> <para> @@ -2735,7 +2894,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqgetvalue"> <term> <function>PQgetvalue</function> <indexterm> @@ -2750,11 +2909,11 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> at 0. The caller should not free the result directly. It will be freed when the associated <structname>PGresult</> handle is passed to <function>PQclear</function>. - <synopsis> - char *PQgetvalue(const PGresult *res, - int row_number, - int column_number); - </synopsis> +<synopsis> +char *PQgetvalue(const PGresult *res, + int row_number, + int column_number); +</synopsis> </para> <para> @@ -2785,7 +2944,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqgetisnull"> <term> <function>PQgetisnull</function> <indexterm> @@ -2801,11 +2960,11 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> <para> Tests a field for a null value. Row and column numbers start at 0. - <synopsis> - int PQgetisnull(const PGresult *res, - int row_number, - int column_number); - </synopsis> +<synopsis> +int PQgetisnull(const PGresult *res, + int row_number, + int column_number); +</synopsis> </para> <para> @@ -2817,7 +2976,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqgetlength"> <term> <function>PQgetlength</function> <indexterm> @@ -2828,11 +2987,11 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> <para> Returns the actual length of a field value in bytes. Row and column numbers start at 0. - <synopsis> - int PQgetlength(const PGresult *res, - int row_number, - int column_number); - </synopsis> +<synopsis> +int PQgetlength(const PGresult *res, + int row_number, + int column_number); +</synopsis> </para> <para> @@ -2847,7 +3006,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqnparams"> <term> <function>PQnparams</function> <indexterm> @@ -2858,9 +3017,9 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> <listitem> <para> Returns the number of parameters of a prepared statement. - <synopsis> - int PQnparams(const PGresult *res); - </synopsis> +<synopsis> +int PQnparams(const PGresult *res); +</synopsis> </para> <para> @@ -2871,7 +3030,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqparamtype"> <term> <function>PQparamtype</function> <indexterm> @@ -2883,9 +3042,9 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> <para> Returns the data type of the indicated statement parameter. Parameter numbers start at 0. - <synopsis> - Oid PQparamtype(const PGresult *res, int param_number); - </synopsis> +<synopsis> +Oid PQparamtype(const PGresult *res, int param_number); +</synopsis> </para> <para> @@ -2896,7 +3055,7 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqprint"> <term> <function>PQprint</function> <indexterm> @@ -2908,23 +3067,24 @@ PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation> <para> Prints out all the rows and, optionally, the column names to the specified output stream. - <synopsis> +<synopsis> void PQprint(FILE *fout, /* output stream */ const PGresult *res, const PQprintOpt *po); -typedef struct { - pqbool header; /* print output field headings and row count */ - pqbool align; /* fill align the fields */ - pqbool standard; /* old brain dead format */ - pqbool html3; /* output HTML tables */ - pqbool expanded; /* expand tables */ - pqbool pager; /* use pager for output if needed */ - char *fieldSep; /* field separator */ - char *tableOpt; /* attributes for HTML table element */ - char *caption; /* HTML table caption */ - char **fieldName; /* null-terminated array of replacement field names */ +typedef struct +{ + pqbool header; /* print output field headings and row count */ + pqbool align; /* fill align the fields */ + pqbool standard; /* old brain dead format */ + pqbool html3; /* output HTML tables */ + pqbool expanded; /* expand tables */ + pqbool pager; /* use pager for output if needed */ + char *fieldSep; /* field separator */ + char *tableOpt; /* attributes for HTML table element */ + char *caption; /* HTML table caption */ + char **fieldName; /* null-terminated array of replacement field names */ } PQprintOpt; - </synopsis> +</synopsis> </para> <para> @@ -2946,7 +3106,7 @@ typedef struct { </para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqcmdstatus"> <term> <function>PQcmdStatus</function> <indexterm> @@ -2958,9 +3118,9 @@ typedef struct { <para> Returns the command status tag from the SQL command that generated the <structname>PGresult</structname>. - <synopsis> - char *PQcmdStatus(PGresult *res); - </synopsis> +<synopsis> +char *PQcmdStatus(PGresult *res); +</synopsis> </para> <para> @@ -2973,7 +3133,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqcmdtuples"> <term> <function>PQcmdTuples</function> <indexterm> @@ -2984,9 +3144,9 @@ typedef struct { <listitem> <para> Returns the number of rows affected by the SQL command. - <synopsis> - char *PQcmdTuples(PGresult *res); - </synopsis> +<synopsis> +char *PQcmdTuples(PGresult *res); +</synopsis> </para> <para> @@ -3007,7 +3167,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqoidvalue"> <term> <function>PQoidValue</function> <indexterm> @@ -3025,14 +3185,14 @@ typedef struct { returns <literal>InvalidOid</literal>. This function will also return <literal>InvalidOid</literal> if the table affected by the <command>INSERT</> statement does not contain OIDs. - <synopsis> - Oid PQoidValue(const PGresult *res); - </synopsis> +<synopsis> +Oid PQoidValue(const PGresult *res); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqoidstatus"> <term> <function>PQoidStatus</function> <indexterm> @@ -3042,23 +3202,15 @@ typedef struct { <listitem> <para> - Returns a string with the OID of the inserted row, if the - <acronym>SQL</acronym> command was an <command>INSERT</command> - that inserted exactly one row, or a <command>EXECUTE</command> of - a prepared statement consisting of a suitable - <command>INSERT</command>. (The string will be <literal>0</> if - the <command>INSERT</command> did not insert exactly one row, or - if the target table does not have OIDs.) If the command was not - an <command>INSERT</command>, returns an empty string. - <synopsis> - char *PQoidStatus(const PGresult *res); - </synopsis> - </para> - - <para> This function is deprecated in favor of - <function>PQoidValue</function>. It is not thread-safe. + <function>PQoidValue</function> and is not thread-safe. + It returns a string with the OID of the inserted row, while + <function>PQoidValue</function> returns the OID value. +<synopsis> +char *PQoidStatus(const PGresult *res); +</synopsis> </para> + </listitem> </varlistentry> </variablelist> @@ -3074,7 +3226,7 @@ typedef struct { </indexterm> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqescapeliteral"> <term> <function>PQescapeLiteral</function> <indexterm> @@ -3084,9 +3236,9 @@ typedef struct { <listitem> <para> - <synopsis> - size_t PQescapeLiteral(PGconn *conn, char *str, size_t len) - </synopsis> +<synopsis> +char *PQescapeLiteral(PGconn *conn, const char *str, size_t length); +</synopsis> </para> <para> @@ -3116,7 +3268,7 @@ typedef struct { </para> <para> - On error, <function>PQescapeLiteral</> returns NULL and a suitable + On error, <function>PQescapeLiteral</> returns <symbol>NULL</> and a suitable message is stored in the <parameter>conn</> object. </para> @@ -3138,7 +3290,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqescapeidentifier"> <term> <function>PQescapeIdentifier</function> <indexterm> @@ -3148,13 +3300,13 @@ typedef struct { <listitem> <para> - <synopsis> - size_t PQescapeIdentifier(PGconn *conn, char *str, size_t len) - </synopsis> +<synopsis> +char *PQescapeIdentifier(PGconn *conn, const char *str, size_t length); +</synopsis> </para> <para> - <function>PQescapeIndentifier</function> escapes a string for + <function>PQescapeIdentifier</function> escapes a string for use as an SQL identifier, such as a table, column, or function name. This is useful when a user-supplied identifier might contain special characters that would otherwise not be interpreted as part @@ -3179,7 +3331,7 @@ typedef struct { </para> <para> - On error, <function>PQescapeIdentifier</> returns NULL and a suitable + On error, <function>PQescapeIdentifier</> returns <symbol>NULL</> and a suitable message is stored in the <parameter>conn</> object. </para> @@ -3193,7 +3345,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqescapestringconn"> <term> <function>PQescapeStringConn</function> <indexterm> @@ -3203,11 +3355,11 @@ typedef struct { <listitem> <para> - <synopsis> - size_t PQescapeStringConn (PGconn *conn, - char *to, const char *from, size_t length, - int *error); - </synopsis> +<synopsis> +size_t PQescapeStringConn(PGconn *conn, + char *to, const char *from, size_t length, + int *error); +</synopsis> </para> <para> @@ -3232,13 +3384,13 @@ typedef struct { </para> <para> - If the <parameter>error</> parameter is not NULL, then + If the <parameter>error</> parameter is not <symbol>NULL</>, then <literal>*error</> is set to zero on success, nonzero on error. Presently the only possible error conditions involve invalid multibyte encoding in the source string. The output string is still generated on error, but it can be expected that the server will reject it as malformed. On error, a suitable message is stored in the - <parameter>conn</> object, whether or not <parameter>error</> is NULL. + <parameter>conn</> object, whether or not <parameter>error</> is <symbol>NULL</>. </para> <para> @@ -3248,7 +3400,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqescapestring"> <term> <function>PQescapeString</function> <indexterm> @@ -3258,15 +3410,17 @@ typedef struct { <listitem> <para> - <synopsis> - size_t PQescapeString (char *to, const char *from, size_t length); - </synopsis> + <function>PQescapeString</> is an older, deprecated version of + <function>PQescapeStringConn</>. +<synopsis> +size_t PQescapeString (char *to, const char *from, size_t length); +</synopsis> </para> <para> - <function>PQescapeString</> is an older, deprecated version of - <function>PQescapeStringConn</>; the difference is that it does - not take <parameter>conn</> or <parameter>error</> parameters. + The only difference from <function>PQescapeStringConn</> is that + <function>PQescapeString</> does not take <structname>PGconn</> + or <parameter>error</> parameters. Because of this, it cannot adjust its behavior depending on the connection properties (such as character encoding) and therefore <emphasis>it might give the wrong results</>. Also, it has no way @@ -3274,7 +3428,7 @@ typedef struct { </para> <para> - <function>PQescapeString</> can be used safely in single-threaded + <function>PQescapeString</> can be used safely in client programs that work with only one <productname>PostgreSQL</> connection at a time (in this case it can find out what it needs to know <quote>behind the scenes</>). In other contexts it is a security @@ -3284,7 +3438,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqescapebyteaconn"> <term> <function>PQescapeByteaConn</function> <indexterm> @@ -3297,25 +3451,20 @@ typedef struct { Escapes binary data for use within an SQL command with the type <type>bytea</type>. As with <function>PQescapeStringConn</function>, this is only used when inserting data directly into an SQL command string. - <synopsis> - unsigned char *PQescapeByteaConn(PGconn *conn, - const unsigned char *from, - size_t from_length, - size_t *to_length); - </synopsis> +<synopsis> +unsigned char *PQescapeByteaConn(PGconn *conn, + const unsigned char *from, + size_t from_length, + size_t *to_length); +</synopsis> </para> <para> - Certain byte values <emphasis>must</emphasis> be escaped (but all - byte values <emphasis>can</emphasis> be escaped) when used as part - of a <type>bytea</type> literal in an <acronym>SQL</acronym> - statement. In general, to escape a byte, it is converted into the - three digit octal number equal to the octet value, and preceded by - usually two backslashes. The single quote (<literal>'</>) and backslash - (<literal>\</>) characters have special alternative escape - sequences. See <xref linkend="datatype-binary"> for more - information. <function>PQescapeByteaConn</function> performs this - operation, escaping only the minimally required bytes. + Certain byte values must be escaped when used as part of a + <type>bytea</type> literal in an <acronym>SQL</acronym> statement. + <function>PQescapeByteaConn</function> escapes bytes using + either hex encoding or backslash escaping. See <xref + linkend="datatype-binary"> for more information. </para> <para> @@ -3343,14 +3492,14 @@ typedef struct { </para> <para> - On error, a NULL pointer is returned, and a suitable error message + On error, a null pointer is returned, and a suitable error message is stored in the <parameter>conn</> object. Currently, the only possible error is insufficient memory for the result string. </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqescapebytea"> <term> <function>PQescapeBytea</function> <indexterm> @@ -3362,35 +3511,28 @@ typedef struct { <para> <function>PQescapeBytea</> is an older, deprecated version of <function>PQescapeByteaConn</>. - <synopsis> - unsigned char *PQescapeBytea(const unsigned char *from, - size_t from_length, - size_t *to_length); - </synopsis> +<synopsis> +unsigned char *PQescapeBytea(const unsigned char *from, + size_t from_length, + size_t *to_length); +</synopsis> </para> <para> The only difference from <function>PQescapeByteaConn</> is that <function>PQescapeBytea</> does not take a <structname>PGconn</> - parameter. Because of this, it cannot adjust its behavior - depending on the connection properties (in particular, whether - standard-conforming strings are enabled) and therefore - <emphasis>it might give the wrong results</>. Also, it has no - way to return an error message on failure. - </para> - - <para> - <function>PQescapeBytea</> can be used safely in single-threaded - client programs that work with only one <productname>PostgreSQL</> - connection at a time (in this case it can find out what it needs - to know <quote>behind the scenes</>). In other contexts it is - a security hazard and should be avoided in favor of - <function>PQescapeByteaConn</>. + parameter. Because of this, <function>PQescapeBytea</> can + only be used safely in client programs that use a single + <productname>PostgreSQL</> connection at a time (in this case + it can find out what it needs to know <quote>behind the + scenes</>). It <emphasis>might give the wrong results</> if + used in programs that use multiple database connections (use + <function>PQescapeByteaConn</> in such cases). </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqunescapebytea"> <term> <function>PQunescapeBytea</function> <indexterm> @@ -3405,9 +3547,9 @@ typedef struct { is needed when retrieving <type>bytea</type> data in text format, but not when retrieving it in binary format. - <synopsis> - unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length); - </synopsis> +<synopsis> +unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length); +</synopsis> </para> <para> @@ -3416,7 +3558,7 @@ typedef struct { to a <type>bytea</type> column. <function>PQunescapeBytea</function> converts this string representation into its binary representation. It returns a pointer to a buffer allocated with - <function>malloc()</function>, or null on error, and puts the size of + <function>malloc()</function>, or <symbol>NULL</> on error, and puts the size of the buffer in <parameter>to_length</parameter>. The result must be freed using <function>PQfreemem</> when it is no longer needed. </para> @@ -3499,7 +3641,7 @@ typedef struct { respectively. <variablelist> - <varlistentry> + <varlistentry id="libpq-pqsendquery"> <term> <function>PQsendQuery</function> <indexterm> @@ -3513,9 +3655,9 @@ typedef struct { 1 is returned if the command was successfully dispatched and 0 if not (in which case, use <function>PQerrorMessage</> to get more information about the failure). - <synopsis> - int PQsendQuery(PGconn *conn, const char *command); - </synopsis> +<synopsis> +int PQsendQuery(PGconn *conn, const char *command); +</synopsis> After successfully calling <function>PQsendQuery</function>, call <function>PQgetResult</function> one or more times to obtain the @@ -3526,7 +3668,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsendqueryparams"> <term> <function>PQsendQueryParams</function> <indexterm> @@ -3538,16 +3680,16 @@ typedef struct { <para> Submits a command and separate parameters to the server without waiting for the result(s). - <synopsis> - int PQsendQueryParams(PGconn *conn, - const char *command, - int nParams, - const Oid *paramTypes, - const char * const *paramValues, - const int *paramLengths, - const int *paramFormats, - int resultFormat); - </synopsis> +<synopsis> +int PQsendQueryParams(PGconn *conn, + const char *command, + int nParams, + const Oid *paramTypes, + const char * const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +</synopsis> This is equivalent to <function>PQsendQuery</function> except that query parameters can be specified separately from the query string. @@ -3559,7 +3701,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsendprepare"> <term> <function>PQsendPrepare</> <indexterm> @@ -3571,13 +3713,13 @@ typedef struct { <para> Sends a request to create a prepared statement with the given parameters, without waiting for completion. - <synopsis> - int PQsendPrepare(PGconn *conn, - const char *stmtName, - const char *query, - int nParams, - const Oid *paramTypes); - </synopsis> +<synopsis> +int PQsendPrepare(PGconn *conn, + const char *stmtName, + const char *query, + int nParams, + const Oid *paramTypes); +</synopsis> This is an asynchronous version of <function>PQprepare</>: it returns 1 if it was able to dispatch the request, and 0 if not. @@ -3591,7 +3733,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsendqueryprepared"> <term> <function>PQsendQueryPrepared</function> <indexterm> @@ -3603,15 +3745,15 @@ typedef struct { <para> Sends a request to execute a prepared statement with given parameters, without waiting for the result(s). - <synopsis> - int PQsendQueryPrepared(PGconn *conn, - const char *stmtName, - int nParams, - const char * const *paramValues, - const int *paramLengths, - const int *paramFormats, - int resultFormat); - </synopsis> +<synopsis> +int PQsendQueryPrepared(PGconn *conn, + const char *stmtName, + int nParams, + const char * const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +</synopsis> This is similar to <function>PQsendQueryParams</function>, but the command to be executed is specified by naming a @@ -3624,7 +3766,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsenddescribeprepared"> <term> <function>PQsendDescribePrepared</> <indexterm> @@ -3636,9 +3778,9 @@ typedef struct { <para> Submits a request to obtain information about the specified prepared statement, without waiting for completion. - <synopsis> - int PQsendDescribePrepared(PGconn *conn, const char *stmtName); - </synopsis> +<synopsis> +int PQsendDescribePrepared(PGconn *conn, const char *stmtName); +</synopsis> This is an asynchronous version of <function>PQdescribePrepared</>: it returns 1 if it was able to dispatch the request, and 0 if not. @@ -3651,7 +3793,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsenddescribeportal"> <term> <function>PQsendDescribePortal</> <indexterm> @@ -3663,9 +3805,9 @@ typedef struct { <para> Submits a request to obtain information about the specified portal, without waiting for completion. - <synopsis> - int PQsendDescribePortal(PGconn *conn, const char *portalName); - </synopsis> +<synopsis> +int PQsendDescribePortal(PGconn *conn, const char *portalName); +</synopsis> This is an asynchronous version of <function>PQdescribePortal</>: it returns 1 if it was able to dispatch the request, and 0 if not. @@ -3678,7 +3820,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqgetresult"> <term> <function>PQgetResult</function> <indexterm> @@ -3695,9 +3837,9 @@ typedef struct { <function>PQsendQueryPrepared</function> call, and returns it. A null pointer is returned when the command is complete and there will be no more results. - <synopsis> - PGresult *PQgetResult(PGconn *conn); - </synopsis> +<synopsis> +PGresult *PQgetResult(PGconn *conn); +</synopsis> </para> <para> @@ -3714,6 +3856,15 @@ typedef struct { active and the necessary response data has not yet been read by <function>PQconsumeInput</function>. </para> + + <note> + <para> + Even when <function>PQresultStatus</function> indicates a fatal + error, <function>PQgetResult</function> should be called until it + returns a null pointer to allow <application>libpq</> to + process the error information completely. + </para> + </note> </listitem> </varlistentry> </variablelist> @@ -3733,7 +3884,7 @@ typedef struct { use of two more functions: <variablelist> - <varlistentry> + <varlistentry id="libpq-pqconsumeinput"> <term> <function>PQconsumeInput</function> <indexterm> @@ -3744,9 +3895,9 @@ typedef struct { <listitem> <para> If input is available from the server, consume it. - <synopsis> - int PQconsumeInput(PGconn *conn); - </synopsis> +<synopsis> +int PQconsumeInput(PGconn *conn); +</synopsis> </para> <para> @@ -3773,7 +3924,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqisbusy"> <term> <function>PQisBusy</function> <indexterm> @@ -3787,9 +3938,9 @@ typedef struct { <function>PQgetResult</function> would block waiting for input. A 0 return indicates that <function>PQgetResult</function> can be called with assurance of not blocking. - <synopsis> - int PQisBusy(PGconn *conn); - </synopsis> +<synopsis> +int PQisBusy(PGconn *conn); +</synopsis> </para> <para> @@ -3842,7 +3993,7 @@ typedef struct { can be used. <variablelist> - <varlistentry> + <varlistentry id="libpq-pqsetnonblocking"> <term> <function>PQsetnonblocking</function> <indexterm> @@ -3853,9 +4004,9 @@ typedef struct { <listitem> <para> Sets the nonblocking status of the connection. - <synopsis> - int PQsetnonblocking(PGconn *conn, int arg); - </synopsis> +<synopsis> +int PQsetnonblocking(PGconn *conn, int arg); +</synopsis> </para> <para> @@ -3879,7 +4030,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqisnonblocking"> <term> <function>PQisnonblocking</function> <indexterm> @@ -3890,9 +4041,9 @@ typedef struct { <listitem> <para> Returns the blocking status of the database connection. - <synopsis> - int PQisnonblocking(const PGconn *conn); - </synopsis> +<synopsis> +int PQisnonblocking(const PGconn *conn); +</synopsis> </para> <para> @@ -3902,7 +4053,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqflush"> <term> <function>PQflush</function> <indexterm> @@ -3917,9 +4068,9 @@ typedef struct { for some reason, or 1 if it was unable to send all the data in the send queue yet (this case can only occur if the connection is nonblocking). - <synopsis> - int PQflush(PGconn *conn); - </synopsis> +<synopsis> +int PQflush(PGconn *conn); +</synopsis> </para> </listitem> </varlistentry> @@ -3950,7 +4101,7 @@ typedef struct { this section. <variablelist> - <varlistentry> + <varlistentry id="libpq-pqgetcancel"> <term> <function>PQgetCancel</function> <indexterm> @@ -3962,16 +4113,16 @@ typedef struct { <para> Creates a data structure containing the information needed to cancel a command issued through a particular database connection. - <synopsis> - PGcancel *PQgetCancel(PGconn *conn); - </synopsis> +<synopsis> +PGcancel *PQgetCancel(PGconn *conn); +</synopsis> </para> <para> <function>PQgetCancel</function> creates a <structname>PGcancel</><indexterm><primary>PGcancel</></> object given a <structname>PGconn</> connection object. It will return - NULL if the given <parameter>conn</> is NULL or an invalid + <symbol>NULL</> if the given <parameter>conn</> is <symbol>NULL</> or an invalid connection. The <structname>PGcancel</> object is an opaque structure that is not meant to be accessed directly by the application; it can only be passed to <function>PQcancel</function> @@ -3980,7 +4131,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqfreecancel"> <term> <function>PQfreeCancel</function> <indexterm> @@ -3991,9 +4142,9 @@ typedef struct { <listitem> <para> Frees a data structure created by <function>PQgetCancel</function>. - <synopsis> - void PQfreeCancel(PGcancel *cancel); - </synopsis> +<synopsis> +void PQfreeCancel(PGcancel *cancel); +</synopsis> </para> <para> @@ -4003,7 +4154,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqcancel"> <term> <function>PQcancel</function> <indexterm> @@ -4014,15 +4165,15 @@ typedef struct { <listitem> <para> Requests that the server abandon processing of the current command. - <synopsis> - int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize); - </synopsis> +<synopsis> +int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize); +</synopsis> </para> <para> The return value is 1 if the cancel request was successfully dispatched and 0 if not. If not, <parameter>errbuf</> is filled - with an error message explaining why not. <parameter>errbuf</> + with an explanatory error message. <parameter>errbuf</> must be a char array of size <parameter>errbufsize</> (the recommended size is 256 bytes). </para> @@ -4049,7 +4200,7 @@ typedef struct { </variablelist> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqrequestcancel"> <term> <function>PQrequestCancel</function> <indexterm> @@ -4059,16 +4210,16 @@ typedef struct { <listitem> <para> - Requests that the server abandon processing of the current - command. - <synopsis> - int PQrequestCancel(PGconn *conn); - </synopsis> + <function>PQrequestCancel</function> is a deprecated variant of + <function>PQcancel</function>. +<synopsis> +int PQrequestCancel(PGconn *conn); +</synopsis> </para> <para> - <function>PQrequestCancel</function> is a deprecated variant of - <function>PQcancel</function>. It operates directly on the + Requests that the server abandon processing of the current + command. It operates directly on the <structname>PGconn</> object, and in case of failure stores the error message in the <structname>PGconn</> object (whence it can be retrieved by <function>PQerrorMessage</function>). Although @@ -4109,24 +4260,26 @@ typedef struct { <para> The function <function>PQfn</function><indexterm><primary>PQfn</></> requests execution of a server function via the fast-path interface: - <synopsis> - PGresult *PQfn(PGconn *conn, - int fnid, - int *result_buf, - int *result_len, - int result_is_int, - const PQArgBlock *args, - int nargs); - - typedef struct { - int len; - int isint; - union { - int *ptr; - int integer; - } u; - } PQArgBlock; - </synopsis> +<synopsis> +PGresult *PQfn(PGconn *conn, + int fnid, + int *result_buf, + int *result_len, + int result_is_int, + const PQArgBlock *args, + int nargs); + +typedef struct +{ + int len; + int isint; + union + { + int *ptr; + int integer; + } u; +} PQArgBlock; +</synopsis> </para> <para> @@ -4204,15 +4357,16 @@ typedef struct { notification is returned from <function>PQnotifies</>, it is considered handled and will be removed from the list of notifications. - <synopsis> - PGnotify *PQnotifies(PGconn *conn); +<synopsis> +PGnotify *PQnotifies(PGconn *conn); - typedef struct pgNotify { - char *relname; /* notification channel name */ - int be_pid; /* process ID of notifying server process */ - char *extra; /* notification payload string */ - } PGnotify; - </synopsis> +typedef struct pgNotify +{ + char *relname; /* notification channel name */ + int be_pid; /* process ID of notifying server process */ + char *extra; /* notification payload string */ +} PGnotify; +</synopsis> After processing a <structname>PGnotify</structname> object returned by <function>PQnotifies</function>, be sure to free it with @@ -4318,7 +4472,7 @@ typedef struct { that are also used in connection with query results: <variablelist> - <varlistentry> + <varlistentry id="libpq-pqnfields-1"> <term> <function>PQnfields</function> <indexterm> @@ -4334,7 +4488,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqbinarytuples-1"> <term> <function>PQbinaryTuples</function> <indexterm> @@ -4353,7 +4507,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqfformat-1"> <term> <function>PQfformat</function> <indexterm> @@ -4394,7 +4548,7 @@ typedef struct { </para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqputcopydata"> <term> <function>PQputCopyData</function> <indexterm> @@ -4405,11 +4559,11 @@ typedef struct { <listitem> <para> Sends data to the server during <literal>COPY_IN</> state. - <synopsis> - int PQputCopyData(PGconn *conn, - const char *buffer, - int nbytes); - </synopsis> +<synopsis> +int PQputCopyData(PGconn *conn, + const char *buffer, + int nbytes); +</synopsis> </para> <para> @@ -4433,7 +4587,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqputcopyend"> <term> <function>PQputCopyEnd</function> <indexterm> @@ -4444,10 +4598,10 @@ typedef struct { <listitem> <para> Sends end-of-data indication to the server during <literal>COPY_IN</> state. - <synopsis> - int PQputCopyEnd(PGconn *conn, - const char *errormsg); - </synopsis> +<synopsis> +int PQputCopyEnd(PGconn *conn, + const char *errormsg); +</synopsis> </para> <para> @@ -4494,7 +4648,7 @@ typedef struct { </para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqgetcopydata"> <term> <function>PQgetCopyData</function> <indexterm> @@ -4505,11 +4659,11 @@ typedef struct { <listitem> <para> Receives data from the server during <literal>COPY_OUT</> state. - <synopsis> - int PQgetCopyData(PGconn *conn, - char **buffer, - int async); - </synopsis> +<synopsis> +int PQgetCopyData(PGconn *conn, + char **buffer, + int async); +</synopsis> </para> <para> @@ -4571,7 +4725,7 @@ typedef struct { </para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqgetline"> <term> <function>PQgetline</function> <indexterm> @@ -4583,11 +4737,11 @@ typedef struct { <para> Reads a newline-terminated line of characters (transmitted by the server) into a buffer string of size <parameter>length</>. - <synopsis> - int PQgetline(PGconn *conn, - char *buffer, - int length); - </synopsis> +<synopsis> +int PQgetline(PGconn *conn, + char *buffer, + int length); +</synopsis> </para> <para> @@ -4610,7 +4764,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqgetlineasync"> <term> <function>PQgetlineAsync</function> <indexterm> @@ -4622,11 +4776,11 @@ typedef struct { <para> Reads a row of <command>COPY</command> data (transmitted by the server) into a buffer without blocking. - <synopsis> - int PQgetlineAsync(PGconn *conn, - char *buffer, - int bufsize); - </synopsis> +<synopsis> +int PQgetlineAsync(PGconn *conn, + char *buffer, + int bufsize); +</synopsis> </para> <para> @@ -4669,7 +4823,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqputline"> <term> <function>PQputline</function> <indexterm> @@ -4681,10 +4835,10 @@ typedef struct { <para> Sends a null-terminated string to the server. Returns 0 if OK and <symbol>EOF</symbol> if unable to send the string. - <synopsis> - int PQputline(PGconn *conn, - const char *string); - </synopsis> +<synopsis> +int PQputline(PGconn *conn, + const char *string); +</synopsis> </para> <para> @@ -4710,7 +4864,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqputnbytes"> <term> <function>PQputnbytes</function> <indexterm> @@ -4722,11 +4876,11 @@ typedef struct { <para> Sends a non-null-terminated string to the server. Returns 0 if OK and <symbol>EOF</symbol> if unable to send the string. - <synopsis> - int PQputnbytes(PGconn *conn, - const char *buffer, - int nbytes); - </synopsis> +<synopsis> +int PQputnbytes(PGconn *conn, + const char *buffer, + int nbytes); +</synopsis> </para> <para> @@ -4737,7 +4891,7 @@ typedef struct { </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqendcopy"> <term> <function>PQendcopy</function> <indexterm> @@ -4748,9 +4902,9 @@ typedef struct { <listitem> <para> Synchronizes with the server. - <synopsis> - int PQendcopy(PGconn *conn); - </synopsis> +<synopsis> +int PQendcopy(PGconn *conn); +</synopsis> This function waits until the server has finished the copying. It should either be issued when the last string has been sent to the server using <function>PQputline</function> or when the @@ -4802,7 +4956,7 @@ typedef struct { </para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqclientencoding"> <term> <function>PQclientEncoding</function> <indexterm> @@ -4813,9 +4967,9 @@ typedef struct { <listitem> <para> Returns the client encoding. - <synopsis> - int PQclientEncoding(const PGconn *<replaceable>conn</replaceable>); - </synopsis> +<synopsis> +int PQclientEncoding(const PGconn *<replaceable>conn</replaceable>); +</synopsis> Note that it returns the encoding ID, not a symbolic string such as <literal>EUC_JP</literal>. To convert an encoding ID to an encoding name, you @@ -4828,7 +4982,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsetclientencoding"> <term> <function>PQsetClientEncoding</function> <indexterm> @@ -4839,9 +4993,9 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <listitem> <para> Sets the client encoding. - <synopsis> - int PQsetClientEncoding(PGconn *<replaceable>conn</replaceable>, const char *<replaceable>encoding</replaceable>); - </synopsis> +<synopsis> +int PQsetClientEncoding(PGconn *<replaceable>conn</replaceable>, const char *<replaceable>encoding</replaceable>); +</synopsis> <replaceable>conn</replaceable> is a connection to the server, and <replaceable>encoding</replaceable> is the encoding you want to @@ -4852,7 +5006,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqseterrorverbosity"> <term> <function>PQsetErrorVerbosity</function> <indexterm> @@ -4864,15 +5018,16 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <para> Determines the verbosity of messages returned by <function>PQerrorMessage</> and <function>PQresultErrorMessage</>. - <synopsis> - typedef enum { - PQERRORS_TERSE, - PQERRORS_DEFAULT, - PQERRORS_VERBOSE - } PGVerbosity; +<synopsis> +typedef enum +{ + PQERRORS_TERSE, + PQERRORS_DEFAULT, + PQERRORS_VERBOSE +} PGVerbosity; - PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity); - </synopsis> +PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity); +</synopsis> <function>PQsetErrorVerbosity</> sets the verbosity mode, returning the connection's previous setting. In <firstterm>TERSE</> mode, @@ -4887,7 +5042,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqtrace"> <term> <function>PQtrace</function> <indexterm> @@ -4898,9 +5053,9 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <listitem> <para> Enables tracing of the client/server communication to a debugging file stream. - <synopsis> - void PQtrace(PGconn *conn, FILE *stream); - </synopsis> +<synopsis> +void PQtrace(PGconn *conn, FILE *stream); +</synopsis> </para> <note> @@ -4917,7 +5072,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pquntrace"> <term> <function>PQuntrace</function> <indexterm> @@ -4928,9 +5083,9 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <listitem> <para> Disables tracing started by <function>PQtrace</function>. - <synopsis> - void PQuntrace(PGconn *conn); - </synopsis> +<synopsis> +void PQuntrace(PGconn *conn); +</synopsis> </para> </listitem> </varlistentry> @@ -4946,7 +5101,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqfreemem"> <term> <function>PQfreemem</function> <indexterm> @@ -4957,9 +5112,9 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <listitem> <para> Frees memory allocated by <application>libpq</>. - <synopsis> - void PQfreemem(void *ptr); - </synopsis> +<synopsis> +void PQfreemem(void *ptr); +</synopsis> </para> <para> @@ -4979,7 +5134,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqconninfofree"> <term> <function>PQconninfoFree</function> <indexterm> @@ -4991,9 +5146,9 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <para> Frees the data structures allocated by <function>PQconndefaults</> or <function>PQconninfoParse</>. - <synopsis> - void PQconninfoFree(PQconninfoOption *connOptions); - </synopsis> +<synopsis> +void PQconninfoFree(PQconninfoOption *connOptions); +</synopsis> </para> <para> @@ -5003,7 +5158,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqencryptpassword"> <term> <function>PQencryptPassword</function> <indexterm> @@ -5014,9 +5169,9 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <listitem> <para> Prepares the encrypted form of a <productname>PostgreSQL</> password. - <synopsis> - char * PQencryptPassword(const char *passwd, const char *user); - </synopsis> +<synopsis> +char * PQencryptPassword(const char *passwd, const char *user); +</synopsis> This function is intended to be used by client applications that wish to send commands like <literal>ALTER USER joe PASSWORD 'pwd'</>. It is good practice not to send the original cleartext @@ -5033,7 +5188,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqmakeemptypgresult"> <term> <function>PQmakeEmptyPGresult</function> <indexterm> @@ -5044,15 +5199,15 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <listitem> <para> Constructs an empty <structname>PGresult</structname> object with the given status. - <synopsis> - PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status); - </synopsis> +<synopsis> +PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status); +</synopsis> </para> <para> This is <application>libpq</>'s internal function to allocate and initialize an empty <structname>PGresult</structname> object. This - function returns NULL if memory could not be allocated. It is + function returns <symbol>NULL</> if memory could not be allocated. It is exported because some applications find it useful to generate result objects (particularly objects with error status) themselves. If <parameter>conn</parameter> is not null and <parameter>status</> @@ -5070,7 +5225,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqfireresultcreateevents"> <term> <function>PQfireResultCreateEvents</function> <indexterm> @@ -5084,14 +5239,14 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <structname>PGresult</structname> object. Returns non-zero for success, zero if any event procedure fails. - <synopsis> - int PQfireResultCreateEvents(PGconn *conn, PGresult *res); - </synopsis> +<synopsis> +int PQfireResultCreateEvents(PGconn *conn, PGresult *res); +</synopsis> </para> <para> The <literal>conn</> argument is passed through to event procedures - but not used directly. It can be <literal>NULL</> if the event + but not used directly. It can be <symbol>NULL</> if the event procedures won't use it. </para> @@ -5110,7 +5265,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqcopyresult"> <term> <function>PQcopyResult</function> <indexterm> @@ -5123,11 +5278,11 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); Makes a copy of a <structname>PGresult</structname> object. The copy is not linked to the source result in any way and <function>PQclear</function> must be called when the copy is no longer - needed. If the function fails, NULL is returned. + needed. If the function fails, <symbol>NULL</> is returned. - <synopsis> - PGresult *PQcopyResult(const PGresult *src, int flags); - </synopsis> +<synopsis> +PGresult *PQcopyResult(const PGresult *src, int flags); +</synopsis> </para> <para> @@ -5149,7 +5304,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsetresultattrs"> <term> <function>PQsetResultAttrs</function> <indexterm> @@ -5160,14 +5315,14 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <listitem> <para> Sets the attributes of a <structname>PGresult</structname> object. - <synopsis> - int PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs); - </synopsis> +<synopsis> +int PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs); +</synopsis> </para> <para> The provided <parameter>attDescs</parameter> are copied into the result. - If the <parameter>attDescs</parameter> pointer is NULL or + If the <parameter>attDescs</parameter> pointer is <symbol>NULL</> or <parameter>numAttributes</parameter> is less than one, the request is ignored and the function succeeds. If <parameter>res</parameter> already contains attributes, the function will fail. If the function @@ -5177,7 +5332,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsetvalue"> <term> <function>PQsetvalue</function> <indexterm> @@ -5188,9 +5343,9 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <listitem> <para> Sets a tuple field value of a <structname>PGresult</structname> object. - <synopsis> - int PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len); - </synopsis> +<synopsis> +int PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len); +</synopsis> </para> <para> @@ -5200,9 +5355,9 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); function can only grow the tuples array one tuple at a time. But any field of any existing tuple can be modified in any order. If a value at <parameter>field_num</parameter> already exists, it will be overwritten. - If <parameter>len</parameter> is <literal>-1</literal> or - <parameter>value</parameter> is <literal>NULL</literal>, the field value - will be set to an SQL <literal>NULL</literal>. The + If <parameter>len</parameter> is -1 or + <parameter>value</parameter> is <symbol>NULL</>, the field value + will be set to an SQL null value. The <parameter>value</parameter> is copied into the result's private storage, thus is no longer needed after the function returns. If the function fails, the return value is zero. If the @@ -5211,7 +5366,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqresultalloc"> <term> <function>PQresultAlloc</function> <indexterm> @@ -5222,21 +5377,65 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <listitem> <para> Allocate subsidiary storage for a <structname>PGresult</structname> object. - <synopsis> - void *PQresultAlloc(PGresult *res, size_t nBytes); - </synopsis> +<synopsis> +void *PQresultAlloc(PGresult *res, size_t nBytes); +</synopsis> </para> <para> Any memory allocated with this function will be freed when <parameter>res</parameter> is cleared. If the function fails, - the return value is <literal>NULL</literal>. The result is + the return value is <symbol>NULL</>. The result is guaranteed to be adequately aligned for any type of data, just as for <function>malloc</>. </para> </listitem> </varlistentry> + <varlistentry id="libpq-pqlibversion"> + <term> + <function>PQlibVersion</function> + <indexterm> + <primary>PQlibVersion</primary> + <seealso>PQserverVersion</seealso> + </indexterm> + </term> + + <listitem> + <para> + Return the version of <productname>libpq</> that is being used. +<synopsis> +int PQlibVersion(void); +</synopsis> + </para> + + <para> + The result of this function can be used to determine, at + run time, if specific functionality is available in the currently + loaded version of libpq. The function can be used, for example, + to determine which connection options are available for + <function>PQconnectdb</> or if the <literal>hex</> <type>bytea</> + output added in PostgreSQL 9.0 is supported. + </para> + + <para> + The number is formed by converting the major, minor, and revision + numbers into two-decimal-digit numbers and appending them together. + For example, version 9.1 will be returned as 90100, and version + 9.1.2 will be returned as 90102 (leading zeroes are not shown). + </para> + + <note> + <para> + This function appeared in <productname>PostgreSQL</> version 9.1, so + it cannot be used to detect required functionality in earlier + versions, since linking to it will create a link dependency + on version 9.1. + </para> + </note> + </listitem> + </varlistentry> + </variablelist> </sect1> @@ -5270,29 +5469,29 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <para> The function <function>PQsetNoticeReceiver</function> - <indexterm><primary>notice - receiver</></><indexterm><primary>PQsetNoticeReceiver</></> sets or + <indexterm><primary>notice receiver</></> + <indexterm><primary>PQsetNoticeReceiver</></> sets or examines the current notice receiver for a connection object. Similarly, <function>PQsetNoticeProcessor</function> - <indexterm><primary>notice - processor</></><indexterm><primary>PQsetNoticeProcessor</></> sets or + <indexterm><primary>notice processor</></> + <indexterm><primary>PQsetNoticeProcessor</></> sets or examines the current notice processor. - <synopsis> - typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res); +<synopsis> +typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res); - PQnoticeReceiver - PQsetNoticeReceiver(PGconn *conn, - PQnoticeReceiver proc, - void *arg); +PQnoticeReceiver +PQsetNoticeReceiver(PGconn *conn, + PQnoticeReceiver proc, + void *arg); - typedef void (*PQnoticeProcessor) (void *arg, const char *message); +typedef void (*PQnoticeProcessor) (void *arg, const char *message); - PQnoticeProcessor - PQsetNoticeProcessor(PGconn *conn, - PQnoticeProcessor proc, - void *arg); - </synopsis> +PQnoticeProcessor +PQsetNoticeProcessor(PGconn *conn, + PQnoticeProcessor proc, + void *arg); +</synopsis> Each of these functions returns the previous notice receiver or processor function pointer, and sets the new value. If you supply a @@ -5329,7 +5528,7 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>); <para> The default notice processor is simply: - <programlisting> +<programlisting> static void defaultNoticeProcessor(void *arg, const char *message) { @@ -5373,7 +5572,7 @@ defaultNoticeProcessor(void *arg, const char *message) life of the <structname>PGconn</> and all <structname>PGresult</>s generated from it; so if used, it must point to long-lived data. In addition there is an <firstterm>instance data</> pointer, which starts - out NULL in every <structname>PGconn</> and <structname>PGresult</>. + out <symbol>NULL</> in every <structname>PGconn</> and <structname>PGresult</>. This pointer can be manipulated using the <function>PQinstanceData</function>, <function>PQsetInstanceData</function>, @@ -5398,7 +5597,7 @@ defaultNoticeProcessor(void *arg, const char *message) </para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pgevt-register"> <term><literal>PGEVT_REGISTER</literal></term> <listitem> <para> @@ -5408,12 +5607,12 @@ defaultNoticeProcessor(void *arg, const char *message) register event will be fired per event handler per connection. If the event procedure fails, the registration is aborted. - <synopsis> +<synopsis> typedef struct { PGconn *conn; } PGEventRegister; - </synopsis> +</synopsis> When a <literal>PGEVT_REGISTER</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a @@ -5428,7 +5627,7 @@ typedef struct </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgevt-connreset"> <term><literal>PGEVT_CONNRESET</literal></term> <listitem> <para> @@ -5441,12 +5640,12 @@ typedef struct <function>PQresetPoll</function> will return <literal>PGRES_POLLING_FAILED</literal>. - <synopsis> +<synopsis> typedef struct { PGconn *conn; } PGEventConnReset; - </synopsis> +</synopsis> When a <literal>PGEVT_CONNRESET</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a @@ -5461,7 +5660,7 @@ typedef struct </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgevt-conndestroy"> <term><literal>PGEVT_CONNDESTROY</literal></term> <listitem> <para> @@ -5471,12 +5670,12 @@ typedef struct ability to manage this memory. Failure to clean up will lead to memory leaks. - <synopsis> +<synopsis> typedef struct { PGconn *conn; } PGEventConnDestroy; - </synopsis> +</synopsis> When a <literal>PGEVT_CONNDESTROY</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a @@ -5490,7 +5689,7 @@ typedef struct </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgevt-resultcreate"> <term><literal>PGEVT_RESULTCREATE</literal></term> <listitem> <para> @@ -5499,13 +5698,13 @@ typedef struct <function>PQgetResult</function>. This event will only be fired after the result has been created successfully. - <synopsis> +<synopsis> typedef struct { PGconn *conn; PGresult *result; } PGEventResultCreate; - </synopsis> +</synopsis> When a <literal>PGEVT_RESULTCREATE</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a @@ -5522,7 +5721,7 @@ typedef struct </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgevt-resultcopy"> <term><literal>PGEVT_RESULTCOPY</literal></term> <listitem> <para> @@ -5533,13 +5732,13 @@ typedef struct or <literal>PGEVT_RESULTCOPY</literal> event for the source result will receive <literal>PGEVT_RESULTCOPY</literal> events. - <synopsis> +<synopsis> typedef struct { const PGresult *src; PGresult *dest; } PGEventResultCopy; - </synopsis> +</synopsis> When a <literal>PGEVT_RESULTCOPY</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a @@ -5557,7 +5756,7 @@ typedef struct </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pgevt-resultdestroy"> <term><literal>PGEVT_RESULTDESTROY</literal></term> <listitem> <para> @@ -5567,12 +5766,12 @@ typedef struct ability to manage this memory. Failure to clean up will lead to memory leaks. - <synopsis> +<synopsis> typedef struct { PGresult *result; } PGEventResultDestroy; - </synopsis> +</synopsis> When a <literal>PGEVT_RESULTDESTROY</literal> event is received, the <parameter>evtInfo</parameter> pointer should be cast to a @@ -5592,7 +5791,7 @@ typedef struct <title>Event Callback Procedure</title> <variablelist> - <varlistentry> + <varlistentry id="libpq-pgeventproc"> <term> <literal>PGEventProc</literal> <indexterm> @@ -5606,9 +5805,9 @@ typedef struct event procedure, that is, the user callback function that receives events from libpq. The signature of an event procedure must be - <synopsis> +<synopsis> int eventproc(PGEventId evtId, void *evtInfo, void *passThrough) - </synopsis> +</synopsis> The <parameter>evtId</parameter> parameter indicates which <literal>PGEVT</literal> event occurred. The @@ -5647,7 +5846,7 @@ int eventproc(PGEventId evtId, void *evtInfo, void *passThrough) <title>Event Support Functions</title> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqregistereventproc"> <term> <function>PQregisterEventProc</function> <indexterm> @@ -5659,10 +5858,10 @@ int eventproc(PGEventId evtId, void *evtInfo, void *passThrough) <para> Registers an event callback procedure with libpq. - <synopsis> - int PQregisterEventProc(PGconn *conn, PGEventProc proc, - const char *name, void *passThrough); - </synopsis> +<synopsis> +int PQregisterEventProc(PGconn *conn, PGEventProc proc, + const char *name, void *passThrough); +</synopsis> </para> <para> @@ -5678,16 +5877,16 @@ int eventproc(PGEventId evtId, void *evtInfo, void *passThrough) event is fired. Its memory address is also used to lookup <literal>instanceData</literal>. The <parameter>name</parameter> argument is used to refer to the event procedure in error messages. - This value cannot be NULL or a zero-length string. The name string is + This value cannot be <symbol>NULL</> or a zero-length string. The name string is copied into the <structname>PGconn</>, so what is passed need not be long-lived. The <parameter>passThrough</parameter> pointer is passed to the <parameter>proc</parameter> whenever an event occurs. This - argument can be NULL. + argument can be <symbol>NULL</>. </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqsetinstancedata"> <term> <function>PQsetInstanceData</function> <indexterm> @@ -5696,18 +5895,20 @@ int eventproc(PGEventId evtId, void *evtInfo, void *passThrough) </term> <listitem> <para> - Sets the conn's instanceData for proc to data. This returns non-zero - for success and zero for failure. (Failure is only possible if - the proc has not been properly registered in the conn.) + Sets the connection <parameter>conn</>'s <literal>instanceData</> + for procedure <parameter>proc</> to <parameter>data</>. This + returns non-zero for success and zero for failure. (Failure is + only possible if <parameter>proc</> has not been properly + registered in <parameter>conn</>.) - <synopsis> - int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data); - </synopsis> +<synopsis> +int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqinstancedata"> <term> <function>PQinstanceData</function> <indexterm> @@ -5716,17 +5917,19 @@ int eventproc(PGEventId evtId, void *evtInfo, void *passThrough) </term> <listitem> <para> - Returns the conn's instanceData associated with proc, or NULL - if there is none. + Returns the + connection <parameter>conn</>'s <literal>instanceData</literal> + associated with procedure <parameter>proc</>, + or <symbol>NULL</symbol> if there is none. - <synopsis> - void *PQinstanceData(const PGconn *conn, PGEventProc proc); - </synopsis> +<synopsis> +void *PQinstanceData(const PGconn *conn, PGEventProc proc); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqresultsetinstancedata"> <term> <function>PQresultSetInstanceData</function> <indexterm> @@ -5735,18 +5938,20 @@ int eventproc(PGEventId evtId, void *evtInfo, void *passThrough) </term> <listitem> <para> - Sets the result's instanceData for proc to data. This returns non-zero - for success and zero for failure. (Failure is only possible if the - proc has not been properly registered in the result.) + Sets the result's <literal>instanceData</> + for <parameter>proc</> to <parameter>data</>. This returns + non-zero for success and zero for failure. (Failure is only + possible if <parameter>proc</> has not been properly registered + in the result.) - <synopsis> - int PQresultSetInstanceData(PGresult *res, PGEventProc proc, void *data); - </synopsis> +<synopsis> +int PQresultSetInstanceData(PGresult *res, PGEventProc proc, void *data); +</synopsis> </para> </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqresultinstancedata"> <term> <function>PQresultInstanceData</function> <indexterm> @@ -5755,12 +5960,12 @@ int eventproc(PGEventId evtId, void *evtInfo, void *passThrough) </term> <listitem> <para> - Returns the result's instanceData associated with proc, or NULL + Returns the result's <literal>instanceData</> associated with <parameter>proc</>, or <symbol>NULL</> if there is none. - <synopsis> - void *PQresultInstanceData(const PGresult *res, PGEventProc proc); - </synopsis> +<synopsis> +void *PQresultInstanceData(const PGresult *res, PGEventProc proc); +</synopsis> </para> </listitem> </varlistentry> @@ -5775,7 +5980,7 @@ int eventproc(PGEventId evtId, void *evtInfo, void *passThrough) libpq connections and results. </para> - <programlisting> +<programlisting> <![CDATA[ /* required header for libpq events (note: includes libpq-fe.h) */ #include <libpq-events.h> @@ -6138,6 +6343,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) <listitem> <para> <indexterm> + <primary><envar>PGREQUIREPEER</envar></primary> + </indexterm> + <envar>PGREQUIREPEER</envar> behaves the same as the <xref + linkend="libpq-connect-requirepeer"> connection parameter. + </para> + </listitem> + + <listitem> + <para> + <indexterm> <primary><envar>PGKRBSRVNAME</envar></primary> </indexterm> <envar>PGKRBSRVNAME</envar> behaves the same as the <xref @@ -6164,13 +6379,23 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) linkend="libpq-connect-connect-timeout"> connection parameter. </para> </listitem> + + <listitem> + <para> + <indexterm> + <primary><envar>PGCLIENTENCODING</envar></primary> + </indexterm> + <envar>PGCLIENTENCODING</envar> behaves the same as the <xref + linkend="libpq-connect-client-encoding"> connection parameter. + </para> + </listitem> </itemizedlist> </para> <para> The following environment variables can be used to specify default behavior for each <productname>PostgreSQL</productname> session. (See - also the <xref linkend="sql-alteruser"> + also the <xref linkend="sql-alterrole"> and <xref linkend="sql-alterdatabase"> commands for ways to set default behavior on a per-user or per-database basis.) @@ -6200,17 +6425,6 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) <listitem> <para> <indexterm> - <primary><envar>PGCLIENTENCODING</envar></primary> - </indexterm> - <envar>PGCLIENTENCODING</envar> sets the default client character - set encoding. (Equivalent to <literal>SET client_encoding TO - ...</literal>.) - </para> - </listitem> - - <listitem> - <para> - <indexterm> <primary><envar>PGGEQO</envar></primary> </indexterm> <envar>PGGEQO</envar> sets the default mode for the genetic query @@ -6277,9 +6491,9 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) <para> This file should contain lines of the following format: - <synopsis> - <replaceable>hostname</replaceable>:<replaceable>port</replaceable>:<replaceable>database</replaceable>:<replaceable>username</replaceable>:<replaceable>password</replaceable> - </synopsis> +<synopsis> +<replaceable>hostname</replaceable>:<replaceable>port</replaceable>:<replaceable>database</replaceable>:<replaceable>username</replaceable>:<replaceable>password</replaceable> +</synopsis> Each of the first four fields can be a literal value, or <literal>*</literal>, which matches anything. The password field from the first line that matches the current connection parameters will be @@ -6291,6 +6505,8 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) or the default socket directory) connections coming from the local machine. In a standby server, a database name of <literal>replication</> matches streaming replication connections made to the master server. + The <literal>database</> field is of limited usefulness because + users have the same password for all databases in the same cluster. </para> <para> @@ -6382,9 +6598,9 @@ user=admin <literal>keyword = value</literal> pairs which will be used to set connection options. The URL must conform to RFC 1959 and be of the form - <synopsis> - ldap://[<replaceable>hostname</replaceable>[:<replaceable>port</replaceable>]]/<replaceable>search_base</replaceable>?<replaceable>attribute</replaceable>?<replaceable>search_scope</replaceable>?<replaceable>filter</replaceable> - </synopsis> +<synopsis> +ldap://[<replaceable>hostname</replaceable>[:<replaceable>port</replaceable>]]/<replaceable>search_base</replaceable>?<replaceable>attribute</replaceable>?<replaceable>search_scope</replaceable>?<replaceable>filter</replaceable> +</synopsis> where <replaceable>hostname</replaceable> defaults to <literal>localhost</literal> and <replaceable>port</replaceable> defaults to 389. @@ -6402,36 +6618,36 @@ user=admin <para> A sample LDAP entry that has been created with the LDIF file - <synopsis> - version:1 - dn:cn=mydatabase,dc=mycompany,dc=com - changetype:add - objectclass:top - objectclass:groupOfUniqueNames - cn:mydatabase - uniqueMember:host=dbserver.mycompany.com - uniqueMember:port=5439 - uniqueMember:dbname=mydb - uniqueMember:user=mydb_user - uniqueMember:sslmode=require - </synopsis> +<programlisting> +version:1 +dn:cn=mydatabase,dc=mycompany,dc=com +changetype:add +objectclass:top +objectclass:groupOfUniqueNames +cn:mydatabase +uniqueMember:host=dbserver.mycompany.com +uniqueMember:port=5439 +uniqueMember:dbname=mydb +uniqueMember:user=mydb_user +uniqueMember:sslmode=require +</programlisting> might be queried with the following LDAP URL: - <synopsis> - ldap://ldap.mycompany.com/dc=mycompany,dc=com?uniqueMember?one?(cn=mydatabase) - </synopsis> +<programlisting> +ldap://ldap.mycompany.com/dc=mycompany,dc=com?uniqueMember?one?(cn=mydatabase) +</programlisting> </para> <para> You can also mix regular service file entries with LDAP lookups. A complete example for a stanza in <filename>pg_service.conf</filename> would be: - <synopsis> - # only host and port are stored in LDAP, specify dbname and user explicitly - [customerdb] - dbname=customer - user=appuser - ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*) - </synopsis> +<programlisting> +# only host and port are stored in LDAP, specify dbname and user explicitly +[customerdb] +dbname=customer +user=appuser +ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*) +</programlisting> </para> </sect1> @@ -6462,7 +6678,7 @@ user=admin </para> <sect2 id="libq-ssl-certificates"> - <title>Certificate verification</title> + <title>Client Verification of Server Certificates</title> <para> By default, <productname>PostgreSQL</> will not perform any verification of @@ -6477,7 +6693,7 @@ user=admin libpq will verify that the server is trustworthy by checking the certificate chain up to a trusted certificate authority (<acronym>CA</>). If <literal>sslmode</> is set to <literal>verify-full</>, - libpq will <emphasis>also</> verify that the server hostname matches its + libpq will <emphasis>also</> verify that the server host name matches its certificate. The SSL connection will fail if the server certificate cannot be verified. <literal>verify-full</> is recommended in most security-sensitive environments. @@ -6485,11 +6701,11 @@ user=admin <para> In <literal>verify-full</> mode, the <literal>cn</> (Common Name) attribute - of the certificate is matched against the hostname. If the <literal>cn</> + of the certificate is matched against the host name. If the <literal>cn</> attribute starts with an asterisk (<literal>*</>), it will be treated as a wildcard, and will match all characters <emphasis>except</> a dot (<literal>.</>). This means the certificate will not match subdomains. - If the connection is made using an IP address instead of a hostname, the + If the connection is made using an IP address instead of a host name, the IP address will be matched (without doing any DNS lookups). </para> @@ -6517,7 +6733,7 @@ user=admin </sect2> <sect2 id="libpq-ssl-clientcert"> - <title>Client certificates</title> + <title>Client Certificates</title> <para> If the server requests a trusted client certificate, @@ -6559,36 +6775,29 @@ user=admin </sect2> <sect2 id="libpq-ssl-protection"> - <title>Protection provided in different modes</title> + <title>Protection Provided in Different Modes</title> <para> The different values for the <literal>sslmode</> parameter provide different levels of protection. SSL can provide protection against three types of attacks: - </para> - <table id="libpq-ssl-protect-attacks"> - <title>SSL attacks</title> - <tgroup cols="2"> - <thead> - <row> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>Eavesdropping</entry> - <entry>If a third party can examine the network traffic between the + <variablelist> + <varlistentry> + <term>Eavesdropping</term> + <listitem> + <para>If a third party can examine the network traffic between the client and the server, it can read both connection information (including - the username and password) and the data that is passed. <acronym>SSL</> + the user name and password) and the data that is passed. <acronym>SSL</> uses encryption to prevent this. - </entry> - </row> + </para> + </listitem> + </varlistentry> - <row> - <entry>Man in the middle (<acronym>MITM</>)</entry> - <entry>If a third party can modify the data while passing between the + <varlistentry> + <term>Man in the middle (<acronym>MITM</>)</term> + <listitem> + <para>If a third party can modify the data while passing between the client and server, it can pretend to be the server and therefore see and modify data <emphasis>even if it is encrypted</>. The third party can then forward the connection information and data to the original server, @@ -6597,21 +6806,23 @@ user=admin to a different server than intended. There are also several other attack methods that can accomplish this. <acronym>SSL</> uses certificate verification to prevent this, by authenticating the server to the client. - </entry> - </row> + </para> + </listitem> + </varlistentry> - <row> - <entry>Impersonation</entry> - <entry>If a third party can pretend to be an authorized client, it can + <varlistentry> + <term>Impersonation</term> + <listitem> + <para>If a third party can pretend to be an authorized client, it can simply access data it should not have access to. Typically this can happen through insecure password management. <acronym>SSL</> uses client certificates to prevent this, by making sure that only holders of valid certificates can access the server. - </entry> - </row> - </tbody> - </tgroup> - </table> + </para> + </listitem> + </varlistentry> + </variablelist> + </para> <para> For a connection to be known secure, SSL usage must be configured @@ -6636,13 +6847,13 @@ user=admin <para> All <acronym>SSL</> options carry overhead in the form of encryption and key-exchange, so there is a tradeoff that has to be made between performance - and security. The following table illustrates the risks the different - <literal>sslmode</> values protect against, and what statement they make - about security and overhead: + and security. <xref linkend="libpq-ssl-sslmode-statements"> + illustrates the risks the different <literal>sslmode</> values + protect against, and what statement they make about security and overhead. </para> <table id="libpq-ssl-sslmode-statements"> - <title>SSL mode descriptions</title> + <title>SSL Mode Descriptions</title> <tgroup cols="4"> <thead> <row> @@ -6727,13 +6938,19 @@ user=admin The default value for <literal>sslmode</> is <literal>prefer</>. As is shown in the table, this makes no sense from a security point of view, and it only promises performance overhead if possible. It is only provided as the default - for backwards compatibility, and is not recommended in secure deployments. + for backward compatibility, and is not recommended in secure deployments. </para> </sect2> <sect2 id="libpq-ssl-fileusage"> - <title>SSL File Usage</title> + <title>SSL Client File Usage</title> + + <para> + <xref linkend="libpq-ssl-file-usage"> summarizes the files that are + relevant to the SSL setup on the client. + </para> + <table id="libpq-ssl-file-usage"> <title>Libpq/Client SSL File Usage</title> <tgroup cols="3"> @@ -6779,7 +6996,7 @@ user=admin </sect2> <sect2 id="libpq-ssl-initialize"> - <title>SSL library initialization</title> + <title>SSL Library Initialization</title> <para> If your application initializes <literal>libssl</> and/or @@ -6797,7 +7014,7 @@ user=admin <para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqinitopenssl"> <term> <function>PQinitOpenSSL</function> <indexterm> @@ -6808,9 +7025,9 @@ user=admin <listitem> <para> Allows applications to select which security libraries to initialize. - <synopsis> - void PQinitOpenSSL(int do_ssl, int do_crypto); - </synopsis> +<synopsis> +void PQinitOpenSSL(int do_ssl, int do_crypto); +</synopsis> </para> <para> @@ -6833,7 +7050,7 @@ user=admin </listitem> </varlistentry> - <varlistentry> + <varlistentry id="libpq-pqinitssl"> <term> <function>PQinitSSL</function> <indexterm> @@ -6844,9 +7061,9 @@ user=admin <listitem> <para> Allows applications to select which security libraries to initialize. - <synopsis> - void PQinitSSL(int do_ssl); - </synopsis> +<synopsis> +void PQinitSSL(int do_ssl); +</synopsis> </para> <para> @@ -6892,7 +7109,7 @@ user=admin </para> <variablelist> - <varlistentry> + <varlistentry id="libpq-pqisthreadsafe"> <term> <function>PQisthreadsafe</function> <indexterm> @@ -6904,9 +7121,9 @@ user=admin <para> Returns the thread safety status of the <application>libpq</application> library. - <synopsis> - int PQisthreadsafe(); - </synopsis> +<synopsis> +int PQisthreadsafe(); +</synopsis> </para> <para> @@ -7355,7 +7572,7 @@ main(int argc, char **argv) </example> <example id="libpq-example-3"> - <title><application>libpq</application> Example Program 3</> + <title><application>libpq</application> Example Program 3</title> <programlisting> <![CDATA[ diff --git a/doc/src/sgml/lo.sgml b/doc/src/sgml/lo.sgml index f8ef48af01..3d56ba3f70 100644 --- a/doc/src/sgml/lo.sgml +++ b/doc/src/sgml/lo.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/lo.sgml,v 1.3 2007/12/06 04:12:10 tgl Exp $ --> +<!-- doc/src/sgml/lo.sgml --> -<sect1 id="lo"> +<sect1 id="lo" xreflabel="lo"> <title>lo</title> <indexterm zone="lo"> @@ -66,12 +66,12 @@ Here's a simple example of usage: </para> - <programlisting> - CREATE TABLE image (title TEXT, raster lo); +<programlisting> +CREATE TABLE image (title TEXT, raster lo); - CREATE TRIGGER t_raster BEFORE UPDATE OR DELETE ON image - FOR EACH ROW EXECUTE PROCEDURE lo_manage(raster); - </programlisting> +CREATE TRIGGER t_raster BEFORE UPDATE OR DELETE ON image + FOR EACH ROW EXECUTE PROCEDURE lo_manage(raster); +</programlisting> <para> For each column that will contain unique references to large objects, @@ -99,7 +99,7 @@ <para> If you already have, or suspect you have, orphaned large objects, see the - <filename>contrib/vacuumlo</> module (<xref linkend="vacuumlo">) to help + <xref linkend="vacuumlo"> module to help you clean them up. It's a good idea to run <application>vacuumlo</> occasionally as a back-stop to the <function>lo_manage</> trigger. </para> diff --git a/doc/src/sgml/lobj.sgml b/doc/src/sgml/lobj.sgml index ea7d1c8dce..291409fde0 100644 --- a/doc/src/sgml/lobj.sgml +++ b/doc/src/sgml/lobj.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/lobj.sgml,v 1.53 2010/04/03 07:22:55 petere Exp $ --> +<!-- doc/src/sgml/lobj.sgml --> <chapter id="largeObjects"> <title>Large Objects</title> @@ -42,7 +42,7 @@ This makes the large object facility partially obsolete. One remaining advantage of the large object facility is that it allows values up to 2 GB in size, whereas <acronym>TOAST</acronym>ed fields can be at - most 1 GB. Also, large objects can be randomly modified using a read/write + most 1 GB. Also, large objects can be randomly modified using a read/write API that is more efficient than performing such operations using <acronym>TOAST</acronym>. </para> @@ -64,11 +64,11 @@ As of <productname>PostgreSQL</> 9.0, large objects have an owner and a set of access permissions, which can be managed using <xref linkend="sql-grant"> and - <xref linkend="sql-revoke">. + <xref linkend="sql-revoke">. For compatibility with prior releases, see <xref linkend="guc-lo-compat-privileges">. <literal>SELECT</literal> privileges are required to read a large - object, and + object, and <literal>UPDATE</literal> privileges are required to write to or truncate it. Only the large object owner (or the database superuser) can unlink, comment @@ -99,7 +99,7 @@ <application>libpq</application> library. </para> - <sect2> + <sect2 id="lo-create"> <title>Creating a Large Object</title> <para> @@ -108,13 +108,13 @@ Oid lo_creat(PGconn *conn, int mode); </synopsis> <indexterm><primary>lo_creat</></> - creates a new large object. + creates a new large object. The return value is the OID that was assigned to the new large object, or <symbol>InvalidOid</symbol> (zero) on failure. <replaceable class="parameter">mode</replaceable> is unused and ignored as of <productname>PostgreSQL</productname> 8.1; however, for - backwards compatibility with earlier releases it is best to + backward compatibility with earlier releases it is best to set it to <symbol>INV_READ</symbol>, <symbol>INV_WRITE</symbol>, or <symbol>INV_READ</symbol> <literal>|</> <symbol>INV_WRITE</symbol>. (These symbolic constants are defined @@ -158,7 +158,7 @@ inv_oid = lo_create(conn, desired_oid); </para> </sect2> - <sect2> + <sect2 id="lo-import"> <title>Importing a Large Object</title> <para> @@ -167,7 +167,7 @@ inv_oid = lo_create(conn, desired_oid); Oid lo_import(PGconn *conn, const char *filename); </synopsis> <indexterm><primary>lo_import</></> - <replaceable class="parameter">filename</replaceable> + <replaceable class="parameter">filename</replaceable> specifies the operating system name of the file to be imported as a large object. The return value is the OID that was assigned to the new large object, @@ -200,7 +200,7 @@ Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId); </para> </sect2> - <sect2> + <sect2 id="lo-export"> <title>Exporting a Large Object</title> <para> @@ -218,7 +218,7 @@ int lo_export(PGconn *conn, Oid lobjId, const char *filename); </para> </sect2> - <sect2> + <sect2 id="lo-open"> <title>Opening an Existing Large Object</title> <para> @@ -238,7 +238,7 @@ int lo_open(PGconn *conn, Oid lobjId, int mode); descriptor for later use in <function>lo_read</function>, <function>lo_write</function>, <function>lo_lseek</function>, <function>lo_tell</function>, and <function>lo_close</function>. - The descriptor is only valid for + The descriptor is only valid for the duration of the current transaction. On failure, -1 is returned. </para> @@ -256,7 +256,7 @@ int lo_open(PGconn *conn, Oid lobjId, int mode); from a descriptor opened with <symbol>INV_WRITE</symbol> returns data that reflects all writes of other committed transactions as well as writes of the current transaction. This is similar to the behavior - of <literal>SERIALIZABLE</> versus <literal>READ COMMITTED</> transaction + of <literal>REPEATABLE READ</> versus <literal>READ COMMITTED</> transaction modes for ordinary SQL <command>SELECT</> commands. </para> @@ -268,7 +268,7 @@ inv_fd = lo_open(conn, inv_oid, INV_READ|INV_WRITE); </para> </sect2> -<sect2> +<sect2 id="lo-write"> <title>Writing Data to a Large Object</title> <para> @@ -286,7 +286,7 @@ int lo_write(PGconn *conn, int fd, const char *buf, size_t len); </para> </sect2> -<sect2> +<sect2 id="lo-read"> <title>Reading Data from a Large Object</title> <para> @@ -304,7 +304,7 @@ int lo_read(PGconn *conn, int fd, char *buf, size_t len); </para> </sect2> -<sect2> +<sect2 id="lo-seek"> <title>Seeking in a Large Object</title> <para> @@ -324,7 +324,7 @@ int lo_lseek(PGconn *conn, int fd, int offset, int whence); </para> </sect2> -<sect2> +<sect2 id="lo-tell"> <title>Obtaining the Seek Position of a Large Object</title> <para> @@ -338,7 +338,7 @@ int lo_tell(PGconn *conn, int fd); </para> </sect2> -<sect2> +<sect2 id="lo-truncate"> <title>Truncating a Large Object</title> <para> @@ -370,7 +370,7 @@ int lo_truncate(PGcon *conn, int fd, size_t len); </para> </sect2> -<sect2> +<sect2 id="lo-close"> <title>Closing a Large Object Descriptor</title> <para> @@ -390,7 +390,7 @@ int lo_close(PGconn *conn, int fd); </para> </sect2> - <sect2> + <sect2 id="lo-unlink"> <title>Removing a Large Object</title> <para> @@ -407,7 +407,7 @@ int lo_unlink(PGconn *conn, Oid lobjId); </sect1> <sect1 id="lo-funcs"> -<title>Server-Side Functions</title> +<title>Server-side Functions</title> <para> There are server-side functions callable from SQL that correspond to @@ -462,9 +462,9 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image <title>Example Program</title> <para> - <xref linkend="lo-example"> is a sample program which shows how the large object + <xref linkend="lo-example"> is a sample program which shows how the large object interface - in <application>libpq</> can be used. Parts of the program are + in <application>libpq</> can be used. Parts of the program are commented out but are left in the source for the reader's benefit. This program can also be found in <filename>src/test/examples/testlo.c</filename> in the source distribution. diff --git a/doc/src/sgml/ltree.sgml b/doc/src/sgml/ltree.sgml index 77cd6c073c..0a91cd79d1 100644 --- a/doc/src/sgml/ltree.sgml +++ b/doc/src/sgml/ltree.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/ltree.sgml,v 1.4 2010/03/17 17:12:31 petere Exp $ --> +<!-- doc/src/sgml/ltree.sgml --> -<sect1 id="ltree"> +<sect1 id="ltree" xreflabel="ltree"> <title>ltree</title> <indexterm zone="ltree"> @@ -42,7 +42,7 @@ </para> <para> - The <filename>ltree</> module provides several datatypes: + The <filename>ltree</> module provides several data types: </para> <itemizedlist> @@ -58,32 +58,32 @@ for matching <type>ltree</> values. A simple word matches that label within a path. A star symbol (<literal>*</>) matches zero or more labels. For example: - <programlisting> +<synopsis> foo <lineannotation>Match the exact label path <literal>foo</></lineannotation> *.foo.* <lineannotation>Match any label path containing the label <literal>foo</></lineannotation> *.foo <lineannotation>Match any label path whose last label is <literal>foo</></lineannotation> - </programlisting> +</synopsis> </para> <para> Star symbols can also be quantified to restrict how many labels they can match: - <programlisting> +<synopsis> *{<replaceable>n</>} <lineannotation>Match exactly <replaceable>n</> labels</lineannotation> *{<replaceable>n</>,} <lineannotation>Match at least <replaceable>n</> labels</lineannotation> *{<replaceable>n</>,<replaceable>m</>} <lineannotation>Match at least <replaceable>n</> but not more than <replaceable>m</> labels</lineannotation> *{,<replaceable>m</>} <lineannotation>Match at most <replaceable>m</> labels — same as </lineannotation> *{0,<replaceable>m</>} - </programlisting> +</synopsis> </para> <para> There are several modifiers that can be put at the end of a non-star label in <type>lquery</> to make it match more than just the exact match: - <programlisting> +<synopsis> @ <lineannotation>Match case-insensitively, for example <literal>a@</> matches <literal>A</></lineannotation> * <lineannotation>Match any label with this prefix, for example <literal>foo*</> matches <literal>foobar</></lineannotation> % <lineannotation>Match initial underscore-separated words</lineannotation> - </programlisting> +</synopsis> The behavior of <literal>%</> is a bit complicated. It tries to match words rather than the entire label. For example <literal>foo_bar%</> matches <literal>foo_bar_baz</> but not @@ -102,10 +102,10 @@ foo <lineannotation>Match the exact label path <literal>foo</></lineanno <para> Here's an annotated example of <type>lquery</type>: - <programlisting> - Top.*{0,2}.sport*@.!football|tennis.Russ*|Spain - a. b. c. d. e. - </programlisting> +<programlisting> +Top.*{0,2}.sport*@.!football|tennis.Russ*|Spain +a. b. c. d. e. +</programlisting> This query will match any label path that: </para> <orderedlist numeration='loweralpha'> @@ -154,9 +154,9 @@ foo <lineannotation>Match the exact label path <literal>foo</></lineanno <para> Here's an example <type>ltxtquery</type>: - <programlisting> - Europe & Russia*@ & !Transportation - </programlisting> +<programlisting> +Europe & Russia*@ & !Transportation +</programlisting> This will match paths that contain the label <literal>Europe</literal> and any label beginning with <literal>Russia</literal> (case-insensitive), but not paths containing the label <literal>Transportation</literal>. @@ -182,8 +182,8 @@ foo <lineannotation>Match the exact label path <literal>foo</></lineanno <literal>=</>, <literal><></literal>, <literal><</>, <literal>></>, <literal><=</>, <literal>>=</>. Comparison sorts in the order of a tree traversal, with the children - of a node sorted by label text. In addition, there are the following - specialized operators: + of a node sorted by label text. In addition, the specialized + operators shown in <xref linkend="ltree-op-table"> are available. </para> <table id="ltree-op-table"> @@ -362,7 +362,7 @@ foo <lineannotation>Match the exact label path <literal>foo</></lineanno </para> <para> - The following functions are available: + The available functions are shown in <xref linkend="ltree-func-table">. </para> <table id="ltree-func-table"> @@ -504,9 +504,9 @@ foo <lineannotation>Match the exact label path <literal>foo</></lineanno <para> Example of creating such an index: </para> - <programlisting> - CREATE INDEX path_gist_idx ON test USING GIST (path); - </programlisting> +<programlisting> +CREATE INDEX path_gist_idx ON test USING GIST (path); +</programlisting> </listitem> <listitem> <para> @@ -517,9 +517,9 @@ foo <lineannotation>Match the exact label path <literal>foo</></lineanno <para> Example of creating such an index: </para> - <programlisting> - CREATE INDEX path_gist_idx ON test USING GIST (array_path); - </programlisting> +<programlisting> +CREATE INDEX path_gist_idx ON test USING GIST (array_path); +</programlisting> <para> Note: This index type is lossy. </para> @@ -535,7 +535,7 @@ foo <lineannotation>Match the exact label path <literal>foo</></lineanno <filename>contrib/ltree/ltreetest.sql</> in the source distribution): </para> - <programlisting> +<programlisting> CREATE TABLE test (path ltree); INSERT INTO test VALUES ('Top'); INSERT INTO test VALUES ('Top.Science'); @@ -552,31 +552,29 @@ INSERT INTO test VALUES ('Top.Collections.Pictures.Astronomy.Galaxies'); INSERT INTO test VALUES ('Top.Collections.Pictures.Astronomy.Astronauts'); CREATE INDEX path_gist_idx ON test USING gist(path); CREATE INDEX path_idx ON test USING btree(path); - </programlisting> +</programlisting> <para> Now, we have a table <structname>test</> populated with data describing the hierarchy shown below: </para> - <programlisting> - Top - / | \ - Science Hobbies Collections - / | \ - Astronomy Amateurs_Astronomy Pictures - / \ | - Astrophysics Cosmology Astronomy - / | \ - Galaxies Stars Astronauts - </programlisting> +<literallayout class="monospaced"> + Top + / | \ + Science Hobbies Collections + / | \ + Astronomy Amateurs_Astronomy Pictures + / \ | +Astrophysics Cosmology Astronomy + / | \ + Galaxies Stars Astronauts +</literallayout> <para> We can do inheritance: - </para> - - <programlisting> -ltreetest=# select path from test where path <@ 'Top.Science'; +<screen> +ltreetest=> SELECT path FROM test WHERE path <@ 'Top.Science'; path ------------------------------------ Top.Science @@ -584,14 +582,13 @@ ltreetest=# select path from test where path <@ 'Top.Science'; Top.Science.Astronomy.Astrophysics Top.Science.Astronomy.Cosmology (4 rows) - </programlisting> +</screen> + </para> <para> Here are some examples of path matching: - </para> - - <programlisting> -ltreetest=# select path from test where path ~ '*.Astronomy.*'; +<screen> +ltreetest=> SELECT path FROM test WHERE path ~ '*.Astronomy.*'; path ----------------------------------------------- Top.Science.Astronomy @@ -603,20 +600,20 @@ ltreetest=# select path from test where path ~ '*.Astronomy.*'; Top.Collections.Pictures.Astronomy.Astronauts (7 rows) -ltreetest=# select path from test where path ~ '*.!pictures@.*.Astronomy.*'; +ltreetest=> SELECT path FROM test WHERE path ~ '*.!pictures@.*.Astronomy.*'; path ------------------------------------ Top.Science.Astronomy Top.Science.Astronomy.Astrophysics Top.Science.Astronomy.Cosmology (3 rows) - </programlisting> +</screen> + </para> <para> Here are some examples of full text search: - </para> - <programlisting> -ltreetest=# select path from test where path @ 'Astro*% & !pictures@'; +<screen> +ltreetest=> SELECT path FROM test WHERE path @ 'Astro*% & !pictures@'; path ------------------------------------ Top.Science.Astronomy @@ -625,45 +622,46 @@ ltreetest=# select path from test where path @ 'Astro*% & !pictures@'; Top.Hobbies.Amateurs_Astronomy (4 rows) -ltreetest=# select path from test where path @ 'Astro* & !pictures@'; +ltreetest=> SELECT path FROM test WHERE path @ 'Astro* & !pictures@'; path ------------------------------------ Top.Science.Astronomy Top.Science.Astronomy.Astrophysics Top.Science.Astronomy.Cosmology (3 rows) - </programlisting> +</screen> + </para> <para> Path construction using functions: - </para> - <programlisting> -ltreetest=# select subpath(path,0,2)||'Space'||subpath(path,2) from test where path <@ 'Top.Science.Astronomy'; +<screen> +ltreetest=> SELECT subpath(path,0,2)||'Space'||subpath(path,2) FROM test WHERE path <@ 'Top.Science.Astronomy'; ?column? ------------------------------------------ Top.Science.Space.Astronomy Top.Science.Space.Astronomy.Astrophysics Top.Science.Space.Astronomy.Cosmology (3 rows) - </programlisting> +</screen> + </para> <para> We could simplify this by creating a SQL function that inserts a label at a specified position in a path: - </para> - <programlisting> +<screen> CREATE FUNCTION ins_label(ltree, int, text) RETURNS ltree -AS 'select subpath($1,0,$2) || $3 || subpath($1,$2);' -LANGUAGE SQL IMMUTABLE; + AS 'select subpath($1,0,$2) || $3 || subpath($1,$2);' + LANGUAGE SQL IMMUTABLE; -ltreetest=# select ins_label(path,2,'Space') from test where path <@ 'Top.Science.Astronomy'; +ltreetest=> SELECT ins_label(path,2,'Space') FROM test WHERE path <@ 'Top.Science.Astronomy'; ins_label ------------------------------------------ Top.Science.Space.Astronomy Top.Science.Space.Astronomy.Astrophysics Top.Science.Space.Astronomy.Cosmology (3 rows) - </programlisting> +</screen> + </para> </sect2> <sect2> diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml index 8f7fb6d346..03cc6c987a 100644 --- a/doc/src/sgml/maintenance.sgml +++ b/doc/src/sgml/maintenance.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/maintenance.sgml,v 1.105 2010/05/26 23:55:51 momjian Exp $ --> +<!-- doc/src/sgml/maintenance.sgml --> <chapter id="maintenance"> <title>Routine Database Maintenance Tasks</title> @@ -638,7 +638,7 @@ vacuum threshold = vacuum base threshold + vacuum scale factor * number of tuple <programlisting> analyze threshold = analyze base threshold + analyze scale factor * number of tuples </programlisting> - is compared to the total number of tuples inserted or updated + is compared to the total number of tuples inserted, updated, or deleted since the last <command>ANALYZE</command>. </para> @@ -670,13 +670,13 @@ analyze threshold = analyze base threshold + analyze scale factor * number of tu autovacuum will only touch the table if it must do so to prevent transaction ID wraparound. Another two parameters, - <literal>autovacuum_vacuum_cost_delay</literal> and - <literal>autovacuum_vacuum_cost_limit</literal>, are used to set + <varname>autovacuum_vacuum_cost_delay</> and + <varname>autovacuum_vacuum_cost_limit</>, are used to set table-specific values for the cost-based vacuum delay feature (see <xref linkend="runtime-config-resource-vacuum-cost">). - <literal>autovacuum_freeze_min_age</literal>, - <literal>autovacuum_freeze_max_age</literal> and - <literal>autovacuum_freeze_table_age</literal> are used to set + <varname>autovacuum_freeze_min_age</>, + <varname>autovacuum_freeze_max_age</> and + <varname>autovacuum_freeze_table_age</> are used to set values for <xref linkend="guc-vacuum-freeze-min-age">, <xref linkend="guc-autovacuum-freeze-max-age"> and <xref linkend="guc-vacuum-freeze-table-age"> respectively. @@ -764,7 +764,7 @@ analyze threshold = analyze base threshold + analyze scale factor * number of tu A better approach is to send the server's <systemitem>stderr</> output to some type of log rotation program. There is a built-in log rotation facility, which you can use by - setting the configuration parameter <literal>logging_collector</> to + setting the configuration parameter <varname>logging_collector</> to <literal>true</> in <filename>postgresql.conf</>. The control parameters for this program are described in <xref linkend="runtime-config-logging-where">. You can also use this approach @@ -794,7 +794,7 @@ pg_ctl start | rotatelogs /var/log/pgsql_log 86400 Another production-grade approach to managing log output is to send it to <application>syslog</> and let <application>syslog</> deal with file rotation. To do this, set the - configuration parameter <literal>log_destination</> to <literal>syslog</> + configuration parameter <varname>log_destination</> to <literal>syslog</> (to log to <application>syslog</> only) in <filename>postgresql.conf</>. Then you can send a <literal>SIGHUP</literal> signal to the <application>syslog</> daemon whenever you want to force it diff --git a/doc/src/sgml/manage-ag.sgml b/doc/src/sgml/manage-ag.sgml index e2321d125e..2b11293208 100644 --- a/doc/src/sgml/manage-ag.sgml +++ b/doc/src/sgml/manage-ag.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/manage-ag.sgml,v 2.62 2010/04/03 07:22:55 petere Exp $ --> +<!-- doc/src/sgml/manage-ag.sgml --> <chapter id="managing-databases"> <title>Managing Databases</title> @@ -78,6 +78,8 @@ SELECT datname FROM pg_database; <sect1 id="manage-ag-createdb"> <title>Creating a Database</title> + <indexterm><primary>CREATE DATABASE</></> + <para> In order to create a database, the <productname>PostgreSQL</> server must be up and running (see <xref @@ -86,8 +88,7 @@ SELECT datname FROM pg_database; <para> Databases are created with the SQL command - <xref linkend="sql-createdatabase">:<indexterm><primary>CREATE - DATABASE</></> + <xref linkend="sql-createdatabase">: <synopsis> CREATE DATABASE <replaceable>name</>; </synopsis> diff --git a/doc/src/sgml/mk_feature_tables.pl b/doc/src/sgml/mk_feature_tables.pl index 5dad68b809..7c78e0e3aa 100644 --- a/doc/src/sgml/mk_feature_tables.pl +++ b/doc/src/sgml/mk_feature_tables.pl @@ -1,6 +1,6 @@ # /usr/bin/perl -w -# $PostgreSQL: pgsql/doc/src/sgml/mk_feature_tables.pl,v 2.3 2008/10/18 00:35:32 petere Exp $ +# doc/src/sgml/mk_feature_tables.pl my $yesno = $ARGV[0]; diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 7a9f843d22..553c16873f 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/monitoring.sgml,v 1.80 2010/04/26 19:56:55 tgl Exp $ --> +<!-- doc/src/sgml/monitoring.sgml --> <chapter id="monitoring"> <title>Monitoring Database Activity</title> @@ -34,7 +34,7 @@ </para> <sect1 id="monitoring-ps"> - <title>Standard Unix Tools</Title> + <title>Standard Unix Tools</title> <indexterm zone="monitoring-ps"> <primary>ps</primary> @@ -106,7 +106,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </sect1> <sect1 id="monitoring-stats"> - <title>The Statistics Collector</Title> + <title>The Statistics Collector</title> <indexterm zone="monitoring-stats"> <primary>statistics</primary> @@ -117,19 +117,19 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re is a subsystem that supports collection and reporting of information about server activity. Presently, the collector can count accesses to tables and indexes in both disk-block and individual-row terms. It also tracks - the total number of rows in each table, and the last vacuum and analyze times - for each table. It can also count calls to user-defined functions and - the total time spent in each one. + the total number of rows in each table, and information about vacuum and + analyze actions for each table. It can also count calls to user-defined + functions and the total time spent in each one. </para> <para> <productname>PostgreSQL</productname> also supports reporting of the exact - command currently being executed by other server processes. This is an - facility independent of the collector process. + command currently being executed by other server processes. This + facility is independent of the collector process. </para> <sect2 id="monitoring-stats-setup"> - <title>Statistics Collection Configuration</Title> + <title>Statistics Collection Configuration</title> <para> Since collection of statistics adds some overhead to query execution, @@ -165,8 +165,8 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </para> <para> - The statistics collector communicates with the backends needing - information (including autovacuum) through temporary files. + The statistics collector transmits the collected + information to backends (including autovacuum) through temporary files. These files are stored in the <filename>pg_stat_tmp</filename> subdirectory. When the postmaster shuts down, a permanent copy of the statistics data is stored in the <filename>global</filename> subdirectory. For increased @@ -177,7 +177,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </sect2> <sect2 id="monitoring-stats-views"> - <title>Viewing Collected Statistics</Title> + <title>Viewing Collected Statistics</title> <para> Several predefined views, listed in <xref @@ -219,6 +219,16 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re statistical information will cause a new snapshot to be fetched. </para> + <para> + A transaction can also see its own statistics (as yet untransmitted to the + collector) in the views <structname>pg_stat_xact_all_tables</>, + <structname>pg_stat_xact_sys_tables</>, + <structname>pg_stat_xact_user_tables</>, and + <structname>pg_stat_xact_user_functions</>, or via these views' underlying + functions. These numbers do not act as stated above; instead they update + continuously throughout the transaction. + </para> + <table id="monitoring-stats-views-table"> <title>Standard Statistics Views</title> @@ -232,46 +242,84 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re <tbody> <row> - <entry><structname>pg_stat_activity</></entry> + <entry><structname>pg_stat_activity</><indexterm><primary>pg_stat_activity</primary></indexterm></entry> <entry>One row per server process, showing database OID, database name, process <acronym>ID</>, user OID, user name, application name, - client's address and port number, times at which the server process, - current transaction, and current query began execution, process's waiting - status, and text of the current query. + client's address, host name (if available), and port number, times at + which the server process, current transaction, and current query began + execution, process's waiting status, and text of the current query. The columns that report data on the current query are available unless the parameter <varname>track_activities</varname> has been turned off. Furthermore, these columns are only visible if the user examining the view is a superuser or the same as the user owning the process - being reported on. + being reported on. The client's host name will be available only if + <xref linkend="guc-log-hostname"> is set or if the user's host name + needed to be looked up during <filename>pg_hba.conf</filename> + processing. </entry> </row> <row> - <entry><structname>pg_stat_bgwriter</></entry> + <entry><structname>pg_stat_bgwriter</><indexterm><primary>pg_stat_bgwriter</primary></indexterm></entry> <entry>One row only, showing cluster-wide statistics from the background writer: number of scheduled checkpoints, requested checkpoints, buffers written by checkpoints and cleaning scans, and the number of times the background writer stopped a cleaning scan because it had written too many buffers. Also includes statistics about the shared buffer pool, including buffers written - by backends (that is, not by the background writer) and total buffers - allocated. + by backends (that is, not by the background writer), how many times + those backends had to execute their own fsync calls (normally the + background writer handles those even when the backend does its own + write), total buffers allocated, and time of last statistics reset. </entry> </row> <row> - <entry><structname>pg_stat_database</></entry> + <entry><structname>pg_stat_database</><indexterm><primary>pg_stat_database</primary></indexterm></entry> <entry>One row per database, showing database OID, database name, number of active server processes connected to that database, number of transactions committed and rolled back in that database, total disk blocks read, total buffer hits (i.e., block read requests avoided by finding the block already in buffer cache), - number of rows returned, fetched, inserted, updated and deleted. + number of rows returned, fetched, inserted, updated and deleted, the + total number of queries cancelled due to conflict with recovery (on + standby servers), and time of last statistics reset. + </entry> + </row> + + <row> + <entry><structname>pg_stat_database_conflicts</><indexterm><primary>pg_stat_database_conflicts</primary></indexterm></entry> + <entry>One row per database, showing database OID, database name and + the number of queries that have been cancelled in this database due to + dropped tablespaces, lock timeouts, old snapshots, pinned buffers and + deadlocks. Will only contain information on standby servers, since + conflicts do not occur on master servers. + </entry> + </row> + + <row> + <entry><structname>pg_stat_replication</><indexterm><primary>pg_stat_replication</primary></indexterm></entry> + <entry>One row per WAL sender process, showing process <acronym>ID</>, + user OID, user name, application name, client's address, host name + (if available) and port number, time at which the server process began + execution, and the current WAL sender state and transaction log + location. In addition, the standby reports the last transaction log + position it received and wrote, the last position it flushed to disk, + and the last position it replayed, and this information is also + displayed here. If the standby's application names matches one of the + settings in <varname>synchronous_standby_names</> then the sync_priority + is shown here also, that is the order in which standbys will become + the synchronous standby. The columns detailing what exactly the connection + is doing are only visible if the user examining the view is a superuser. + The client's host name will be available only if + <xref linkend="guc-log-hostname"> is set or if the user's host name + needed to be looked up during <filename>pg_hba.conf</filename> + processing. </entry> </row> <row> - <entry><structname>pg_stat_all_tables</></entry> + <entry><structname>pg_stat_all_tables</><indexterm><primary>pg_stat_all_tables</primary></indexterm></entry> <entry>For each table in the current database (including TOAST tables), the table OID, schema and table name, number of sequential scans initiated, number of live rows fetched by sequential @@ -280,27 +328,52 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re scans, numbers of row insertions, updates, and deletions, number of row updates that were HOT (i.e., no separate index update), numbers of live and dead rows, - the last time the table was vacuumed manually, + the last time the table was non-<option>FULL</> vacuumed manually, the last time it was vacuumed by the autovacuum daemon, the last time it was analyzed manually, - and the last time it was analyzed by the autovacuum daemon. + the last time it was analyzed by the autovacuum daemon, + number of times it has been non-<option>FULL</> vacuumed manually, + number of times it has been vacuumed by the autovacuum daemon, + number of times it has been analyzed manually, + and the number of times it has been analyzed by the autovacuum daemon. </entry> </row> <row> - <entry><structname>pg_stat_sys_tables</></entry> + <entry><structname>pg_stat_sys_tables</><indexterm><primary>pg_stat_sys_tables</primary></indexterm></entry> <entry>Same as <structname>pg_stat_all_tables</>, except that only system tables are shown.</entry> </row> <row> - <entry><structname>pg_stat_user_tables</></entry> + <entry><structname>pg_stat_user_tables</><indexterm><primary>pg_stat_user_tables</primary></indexterm></entry> <entry>Same as <structname>pg_stat_all_tables</>, except that only user tables are shown.</entry> </row> <row> - <entry><structname>pg_stat_all_indexes</></entry> + <entry><structname>pg_stat_xact_all_tables</><indexterm><primary>pg_stat_xact_all_tables</primary></indexterm></entry> + <entry>Similar to <structname>pg_stat_all_tables</>, but counts actions + taken so far within the current transaction (which are <emphasis>not</> + yet included in <structname>pg_stat_all_tables</> and related views). + The columns for numbers of live and dead rows and vacuum and + analyze actions are not present in this view.</entry> + </row> + + <row> + <entry><structname>pg_stat_xact_sys_tables</><indexterm><primary>pg_stat_xact_sys_tables</primary></indexterm></entry> + <entry>Same as <structname>pg_stat_xact_all_tables</>, except that only + system tables are shown.</entry> + </row> + + <row> + <entry><structname>pg_stat_xact_user_tables</><indexterm><primary>pg_stat_xact_user_tables</primary></indexterm></entry> + <entry>Same as <structname>pg_stat_xact_all_tables</>, except that only + user tables are shown.</entry> + </row> + + <row> + <entry><structname>pg_stat_all_indexes</><indexterm><primary>pg_stat_all_indexes</primary></indexterm></entry> <entry>For each index in the current database, the table and index OID, schema, table and index name, number of index scans initiated on that index, number of @@ -310,19 +383,19 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><structname>pg_stat_sys_indexes</></entry> + <entry><structname>pg_stat_sys_indexes</><indexterm><primary>pg_stat_sys_indexes</primary></indexterm></entry> <entry>Same as <structname>pg_stat_all_indexes</>, except that only indexes on system tables are shown.</entry> </row> <row> - <entry><structname>pg_stat_user_indexes</></entry> + <entry><structname>pg_stat_user_indexes</><indexterm><primary>pg_stat_user_indexes</primary></indexterm></entry> <entry>Same as <structname>pg_stat_all_indexes</>, except that only indexes on user tables are shown.</entry> </row> <row> - <entry><structname>pg_statio_all_tables</></entry> + <entry><structname>pg_statio_all_tables</><indexterm><primary>pg_statio_all_tables</primary></indexterm></entry> <entry>For each table in the current database (including TOAST tables), the table OID, schema and table name, number of disk blocks read from that table, number of buffer hits, numbers of @@ -334,19 +407,19 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><structname>pg_statio_sys_tables</></entry> + <entry><structname>pg_statio_sys_tables</><indexterm><primary>pg_statio_sys_tables</primary></indexterm></entry> <entry>Same as <structname>pg_statio_all_tables</>, except that only system tables are shown.</entry> </row> <row> - <entry><structname>pg_statio_user_tables</></entry> + <entry><structname>pg_statio_user_tables</><indexterm><primary>pg_statio_user_tables</primary></indexterm></entry> <entry>Same as <structname>pg_statio_all_tables</>, except that only user tables are shown.</entry> </row> <row> - <entry><structname>pg_statio_all_indexes</></entry> + <entry><structname>pg_statio_all_indexes</><indexterm><primary>pg_statio_all_indexes</primary></indexterm></entry> <entry>For each index in the current database, the table and index OID, schema, table and index name, numbers of disk blocks read and buffer hits in that index. @@ -354,19 +427,19 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><structname>pg_statio_sys_indexes</></entry> + <entry><structname>pg_statio_sys_indexes</><indexterm><primary>pg_statio_sys_indexes</primary></indexterm></entry> <entry>Same as <structname>pg_statio_all_indexes</>, except that only indexes on system tables are shown.</entry> </row> <row> - <entry><structname>pg_statio_user_indexes</></entry> + <entry><structname>pg_statio_user_indexes</><indexterm><primary>pg_statio_user_indexes</primary></indexterm></entry> <entry>Same as <structname>pg_statio_all_indexes</>, except that only indexes on user tables are shown.</entry> </row> <row> - <entry><structname>pg_statio_all_sequences</></entry> + <entry><structname>pg_statio_all_sequences</><indexterm><primary>pg_statio_all_sequences</primary></indexterm></entry> <entry>For each sequence object in the current database, the sequence OID, schema and sequence name, numbers of disk blocks read and buffer hits in that sequence. @@ -374,20 +447,20 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><structname>pg_statio_sys_sequences</></entry> + <entry><structname>pg_statio_sys_sequences</><indexterm><primary>pg_statio_sys_sequences</primary></indexterm></entry> <entry>Same as <structname>pg_statio_all_sequences</>, except that only system sequences are shown. (Presently, no system sequences are defined, so this view is always empty.)</entry> </row> <row> - <entry><structname>pg_statio_user_sequences</></entry> + <entry><structname>pg_statio_user_sequences</><indexterm><primary>pg_statio_user_sequences</primary></indexterm></entry> <entry>Same as <structname>pg_statio_all_sequences</>, except that only user sequences are shown.</entry> </row> <row> - <entry><structname>pg_stat_user_functions</></entry> + <entry><structname>pg_stat_user_functions</><indexterm><primary>pg_stat_user_functions</primary></indexterm></entry> <entry>For all tracked functions, function OID, schema, name, number of calls, total time, and self time. Self time is the amount of time spent in the function itself, total time includes the @@ -395,6 +468,13 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </entry> </row> + <row> + <entry><structname>pg_stat_xact_user_functions</><indexterm><primary>pg_stat_xact_user_functions</primary></indexterm></entry> + <entry>Similar to <structname>pg_stat_user_functions</>, but counts only + calls during the current transaction (which are <emphasis>not</> + yet included in <structname>pg_stat_user_functions</>).</entry> + </row> + </tbody> </tgroup> </table> @@ -405,7 +485,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </para> <para> - Beginning in <productname>PostgreSQL</productname> 8.1, indexes can be + Indexes can be used either directly or via <quote>bitmap scans</>. In a bitmap scan the output of several indexes can be combined via AND or OR rules; so it is difficult to associate individual heap row fetches @@ -556,6 +636,59 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> + <entry><literal><function>pg_stat_get_db_conflict_tablespace</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of queries cancelled because of recovery conflict with dropped tablespaces in database + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_db_conflict_lock</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of queries cancelled because of recovery conflict with locks in database + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_db_conflict_snapshot</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of queries cancelled because of recovery conflict with old snapshots in database + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_db_conflict_bufferpin</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of queries cancelled because of recovery conflict with pinned buffers in database + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_db_conflict_startup_deadlock</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of queries cancelled because of recovery conflict with deadlocks in database + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_db_stat_reset_time</function>(<type>oid</type>)</literal></entry> + <entry><type>timestamptz</type></entry> + <entry> + Time of the last statistics reset for the database. Initialized to the + system time during the first connection to each database. The reset time + is updated when you call <function>pg_stat_reset</function> on the + database, as well as upon execution of + <function>pg_stat_reset_single_table_counters</function> against any + table or index in it. + </entry> + </row> + + <row> <entry><literal><function>pg_stat_get_numscans</function>(<type>oid</type>)</literal></entry> <entry><type>bigint</type></entry> <entry> @@ -651,7 +784,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re <entry><literal><function>pg_stat_get_last_vacuum_time</function>(<type>oid</type>)</literal></entry> <entry><type>timestamptz</type></entry> <entry> - Time of the last vacuum initiated by the user on this table + Time of the last non-<option>FULL</option> vacuum initiated by the user on this table </entry> </row> @@ -681,8 +814,116 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> + <entry><literal><function>pg_stat_get_vacuum_count</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + The number of times this table has been non-<option>FULL</> vacuumed manually + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_autovacuum_count</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + The number of times this table has been vacuumed by the autovacuum daemon + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_analyze_count</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + The number of times this table has been analyzed manually + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_autoanalyze_count</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + The number of times this table has been analyzed by the autovacuum daemon + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_xact_numscans</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of sequential scans done when argument is a table, + or number of index scans done when argument is an index, in the current transaction + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_xact_tuples_returned</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of rows read by sequential scans when argument is a table, + or number of index entries returned when argument is an index, in the current transaction + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_xact_tuples_fetched</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of table rows fetched by bitmap scans when argument is a table, + or table rows fetched by simple index scans using the index + when argument is an index, in the current transaction + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_xact_tuples_inserted</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of rows inserted into table, in the current transaction + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_xact_tuples_updated</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of rows updated in table (includes HOT updates), in the current transaction + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_xact_tuples_deleted</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of rows deleted from table, in the current transaction + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_xact_tuples_hot_updated</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of rows HOT-updated in table, in the current transaction + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_xact_blocks_fetched</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of disk block fetch requests for table or index, in the current transaction + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_xact_blocks_hit</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of disk block requests found in cache for table or index, in the current transaction + </entry> + </row> + + <row> <!-- See also the entry for this in func.sgml --> - <entry><literal><function>pg_backend_pid</function>()</literal></entry> + <entry><literal><function>pg_backend_pid()</function></literal></entry> <entry><type>integer</type></entry> <entry> Process ID of the server process attached to the current session @@ -693,7 +934,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re <entry><literal><function>pg_stat_get_activity</function>(<type>integer</type>)</literal></entry> <entry><type>setof record</type></entry> <entry> - Returns a record of information about the backend with the specified pid, or + Returns a record of information about the backend with the specified PID, or one record for each active backend in the system if <symbol>NULL</symbol> is specified. The fields returned are a subset of those in the <structname>pg_stat_activity</structname> view. @@ -727,7 +968,34 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><literal><function>pg_stat_get_backend_idset</function>()</literal></entry> + <entry><literal><function>pg_stat_get_xact_function_calls</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Number of times the function has been called, in the current transaction. + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_xact_function_time</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Total wall clock time spent in the function, in microseconds, in the + current transaction. Includes the time spent in functions called by + this one. + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_xact_function_self_time</function>(<type>oid</type>)</literal></entry> + <entry><type>bigint</type></entry> + <entry> + Time spent in only this function, in the current transaction. Time + spent in called functions is excluded. + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_backend_idset()</function></literal></entry> <entry><type>setof integer</type></entry> <entry> Set of currently active server process numbers (from 1 to the @@ -838,7 +1106,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><literal><function>pg_stat_get_bgwriter_timed_checkpoints</function>()</literal></entry> + <entry><literal><function>pg_stat_get_bgwriter_timed_checkpoints()</function></literal></entry> <entry><type>bigint</type></entry> <entry> Number of times the background writer has started timed checkpoints @@ -847,7 +1115,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><literal><function>pg_stat_get_bgwriter_requested_checkpoints</function>()</literal></entry> + <entry><literal><function>pg_stat_get_bgwriter_requested_checkpoints()</function></literal></entry> <entry><type>bigint</type></entry> <entry> Number of times the background writer has started checkpoints based @@ -858,7 +1126,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><literal><function>pg_stat_get_bgwriter_buf_written_checkpoints</function>()</literal></entry> + <entry><literal><function>pg_stat_get_bgwriter_buf_written_checkpoints()</function></literal></entry> <entry><type>bigint</type></entry> <entry> Number of buffers written by the background writer during checkpoints @@ -866,7 +1134,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><literal><function>pg_stat_get_bgwriter_buf_written_clean</function>()</literal></entry> + <entry><literal><function>pg_stat_get_bgwriter_buf_written_clean()</function></literal></entry> <entry><type>bigint</type></entry> <entry> Number of buffers written by the background writer for routine cleaning of @@ -875,7 +1143,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><literal><function>pg_stat_get_bgwriter_maxwritten_clean</function>()</literal></entry> + <entry><literal><function>pg_stat_get_bgwriter_maxwritten_clean()</function></literal></entry> <entry><type>bigint</type></entry> <entry> Number of times the background writer has stopped its cleaning scan because @@ -885,7 +1153,17 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><literal><function>pg_stat_get_buf_written_backend</function>()</literal></entry> + <entry><literal><function>pg_stat_get_bgwriter_stat_reset_time()</function></literal></entry> + <entry><type>timestamptz</type></entry> + <entry> + Time of the last statistics reset for the background writer, updated + when executing <function>pg_stat_reset_shared('bgwriter')</function> + on the database cluster. + </entry> + </row> + + <row> + <entry><literal><function>pg_stat_get_buf_written_backend()</function></literal></entry> <entry><type>bigint</type></entry> <entry> Number of buffers written by backends because they needed @@ -894,7 +1172,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><literal><function>pg_stat_get_buf_alloc</function>()</literal></entry> + <entry><literal><function>pg_stat_get_buf_alloc()</function></literal></entry> <entry><type>bigint</type></entry> <entry> Total number of buffer allocations @@ -902,7 +1180,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><literal><function>pg_stat_clear_snapshot</function>()</literal></entry> + <entry><literal><function>pg_stat_clear_snapshot()</function></literal></entry> <entry><type>void</type></entry> <entry> Discard the current statistics snapshot @@ -910,7 +1188,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re </row> <row> - <entry><literal><function>pg_stat_reset</function>()</literal></entry> + <entry><literal><function>pg_stat_reset()</function></literal></entry> <entry><type>void</type></entry> <entry> Reset all statistics counters for the current database to zero @@ -1079,9 +1357,10 @@ SELECT pg_stat_get_backend_pid(s.backendid) AS procpid, <para> A number of standard probes are provided in the source code, - as shown in <xref linkend="dtrace-probe-point-table">. - More can certainly be added to enhance <productname>PostgreSQL</>'s - observability. + as shown in <xref linkend="dtrace-probe-point-table">; + <xref linkend="typedefs-table"> + shows the types used in the probes. More probes can certainly be + added to enhance <productname>PostgreSQL</>'s observability. </para> <table id="dtrace-probe-point-table"> @@ -1295,26 +1574,28 @@ SELECT pg_stat_get_backend_pid(s.backendid) AS procpid, </row> <row> <entry>buffer-read-start</entry> - <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid, bool, bool)</entry> + <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid, int, bool)</entry> <entry>Probe that fires when a buffer read is started. arg0 and arg1 contain the fork and block numbers of the page (but arg1 will be -1 if this is a relation extension request). arg2, arg3, and arg4 contain the tablespace, database, and relation OIDs identifying the relation. - arg5 is true for a local buffer, false for a shared buffer. + arg5 is the ID of the backend which created the temporary relation for a + local buffer, or InvalidBackendId (-1) for a shared buffer. arg6 is true for a relation extension request, false for normal read.</entry> </row> <row> <entry>buffer-read-done</entry> - <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid, bool, bool, bool)</entry> + <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid, int, bool, bool)</entry> <entry>Probe that fires when a buffer read is complete. arg0 and arg1 contain the fork and block numbers of the page (if this is a relation extension request, arg1 now contains the block number of the newly added block). arg2, arg3, and arg4 contain the tablespace, database, and relation OIDs identifying the relation. - arg5 is true for a local buffer, false for a shared buffer. + arg5 is the ID of the backend which created the temporary relation for a + local buffer, or InvalidBackendId (-1) for a shared buffer. arg6 is true for a relation extension request, false for normal read. arg7 is true if the buffer was found in the pool, false if not.</entry> @@ -1380,38 +1661,46 @@ SELECT pg_stat_get_backend_pid(s.backendid) AS procpid, </row> <row> <entry>smgr-md-read-start</entry> - <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid)</entry> + <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid, int)</entry> <entry>Probe that fires when beginning to read a block from a relation. arg0 and arg1 contain the fork and block numbers of the page. arg2, arg3, and arg4 contain the tablespace, database, and relation OIDs - identifying the relation.</entry> + identifying the relation. + arg5 is the ID of the backend which created the temporary relation for a + local buffer, or InvalidBackendId (-1) for a shared buffer.</entry> </row> <row> <entry>smgr-md-read-done</entry> - <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid, int, int)</entry> + <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid, int, int, int)</entry> <entry>Probe that fires when a block read is complete. arg0 and arg1 contain the fork and block numbers of the page. arg2, arg3, and arg4 contain the tablespace, database, and relation OIDs identifying the relation. - arg5 is the number of bytes actually read, while arg6 is the number + arg5 is the ID of the backend which created the temporary relation for a + local buffer, or InvalidBackendId (-1) for a shared buffer. + arg6 is the number of bytes actually read, while arg7 is the number requested (if these are different it indicates trouble).</entry> </row> <row> <entry>smgr-md-write-start</entry> - <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid)</entry> + <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid, int)</entry> <entry>Probe that fires when beginning to write a block to a relation. arg0 and arg1 contain the fork and block numbers of the page. arg2, arg3, and arg4 contain the tablespace, database, and relation OIDs - identifying the relation.</entry> + identifying the relation. + arg5 is the ID of the backend which created the temporary relation for a + local buffer, or InvalidBackendId (-1) for a shared buffer.</entry> </row> <row> <entry>smgr-md-write-done</entry> - <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid, int, int)</entry> + <entry>(ForkNumber, BlockNumber, Oid, Oid, Oid, int, int, int)</entry> <entry>Probe that fires when a block write is complete. arg0 and arg1 contain the fork and block numbers of the page. arg2, arg3, and arg4 contain the tablespace, database, and relation OIDs identifying the relation. - arg5 is the number of bytes actually written, while arg6 is the number + arg5 is the ID of the backend which created the temporary relation for a + local buffer, or InvalidBackendId (-1) for a shared buffer. + arg6 is the number of bytes actually written, while arg7 is the number requested (if these are different it indicates trouble).</entry> </row> <row> @@ -1680,7 +1969,7 @@ Total time (ns) 2312105013 <para> Add the probe definition to <filename>src/backend/utils/probes.d</>: <programlisting> - probe transaction__start(LocalTransactionId); +probe transaction__start(LocalTransactionId); </programlisting> Note the use of the double underline in the probe name. In a DTrace script using the probe, the double underline needs to be replaced with a @@ -1698,7 +1987,7 @@ Total time (ns) 2312105013 in the source code. In this case, it looks like the following: <programlisting> - TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId); +TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId); </programlisting> </para> </step> @@ -1748,8 +2037,8 @@ Total time (ns) 2312105013 is actually enabled: <programlisting> - if (TRACE_POSTGRESQL_TRANSACTION_START_ENABLED()) - TRACE_POSTGRESQL_TRANSACTION_START(some_function(...)); +if (TRACE_POSTGRESQL_TRANSACTION_START_ENABLED()) + TRACE_POSTGRESQL_TRANSACTION_START(some_function(...)); </programlisting> Each trace macro has a corresponding <literal>ENABLED</> macro. diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml index 341351e46f..e688176acb 100644 --- a/doc/src/sgml/mvcc.sgml +++ b/doc/src/sgml/mvcc.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/mvcc.sgml,v 2.75 2010/05/03 15:35:30 alvherre Exp $ --> +<!-- doc/src/sgml/mvcc.sgml --> <chapter id="mvcc"> <title>Concurrency Control</title> @@ -21,14 +21,26 @@ <title>Introduction</title> <indexterm> + <primary>Multiversion Concurrency Control</primary> + </indexterm> + + <indexterm> <primary>MVCC</primary> </indexterm> + <indexterm> + <primary>Serializable Snapshot Isolation</primary> + </indexterm> + + <indexterm> + <primary>SSI</primary> + </indexterm> + <para> - <productname>PostgreSQL</productname> provides a rich set of tools + <productname>PostgreSQL</productname> provides a rich set of tools for developers to manage concurrent access to data. Internally, - data consistency is maintained by using a multiversion - model (Multiversion Concurrency Control, <acronym>MVCC</acronym>). + data consistency is maintained by using a multiversion + model (Multiversion Concurrency Control, <acronym>MVCC</acronym>). This means that while querying a database each transaction sees a snapshot of data (a <firstterm>database version</firstterm>) as it was some @@ -37,8 +49,8 @@ could be caused by (other) concurrent transaction updates on the same data rows, providing <firstterm>transaction isolation</firstterm> for each database session. <acronym>MVCC</acronym>, by eschewing - explicit locking methodologies of traditional database systems, - minimizes lock contention in order to allow for reasonable + the locking methodologies of traditional database systems, + minimizes lock contention in order to allow for reasonable performance in multiuser environments. </para> @@ -48,12 +60,17 @@ <acronym>MVCC</acronym> locks acquired for querying (reading) data do not conflict with locks acquired for writing data, and so reading never blocks writing and writing never blocks reading. + <productname>PostgreSQL</productname> maintains this guarantee + even when providing the strictest level of transaction + isolation through the use of an innovative <firstterm>Serializable + Snapshot Isolation</firstterm> (<acronym>SSI</acronym>) level. </para> <para> Table- and row-level locking facilities are also available in - <productname>PostgreSQL</productname> for applications that cannot - adapt easily to <acronym>MVCC</acronym> behavior. However, proper + <productname>PostgreSQL</productname> for applications which don't + generally need full transaction isolation and prefer to explicitly + manage particular points of conflict. However, proper use of <acronym>MVCC</acronym> will generally provide better performance than locks. In addition, application-defined advisory locks provide a mechanism for acquiring locks that are not tied @@ -70,9 +87,21 @@ <para> The <acronym>SQL</acronym> standard defines four levels of - transaction isolation in terms of three phenomena that must be - prevented between concurrent transactions. These undesirable - phenomena are: + transaction isolation. The most strict is Serializable, + which is defined by the standard in a paragraph which says that any + concurrent execution of a set of Serializable transactions is guaranteed + to produce the same effect as running them one at a time in some order. + The other three levels are defined in terms of phenomena, resulting from + interaction between concurrent transactions, which must not occur at + each level. The standard notes that due to the definition of + Serializable, none of these phenomena are possible at that level. (This + is hardly surprising -- if the effect of the transactions must be + consistent with having been run one at a time, how could you see any + phenomena caused by interactions?) + </para> + + <para> + The phenomena which are prohibited are various levels are: <variablelist> <varlistentry> @@ -211,15 +240,16 @@ <para> In <productname>PostgreSQL</productname>, you can request any of the four standard transaction isolation levels. But internally, there are - only two distinct isolation levels, which correspond to the levels Read - Committed and Serializable. When you select the level Read - Uncommitted you really get Read Committed, and when you select - Repeatable Read you really get Serializable, so the actual + only three distinct isolation levels, which correspond to the levels Read + Committed, Repeatable Read, and Serializable. When you select the level Read + Uncommitted you really get Read Committed, and phantom reads are not possible + in the <productname>PostgreSQL</productname> implementation of Repeatable + Read, so the actual isolation level might be stricter than what you select. This is permitted by the SQL standard: the four isolation levels only define which phenomena must not happen, they do not define which phenomena must happen. The reason that <productname>PostgreSQL</> - only provides two isolation levels is that this is the only + only provides three isolation levels is that this is the only sensible way to map the standard isolation levels to the multiversion concurrency control architecture. The behavior of the available isolation levels is detailed in the following subsections. @@ -238,6 +268,10 @@ <secondary>read committed</secondary> </indexterm> + <indexterm> + <primary>read committed</primary> + </indexterm> + <para> <firstterm>Read Committed</firstterm> is the default isolation level in <productname>PostgreSQL</productname>. When a transaction @@ -345,39 +379,46 @@ COMMIT; </para> </sect2> - <sect2 id="xact-serializable"> - <title>Serializable Isolation Level</title> + <sect2 id="xact-repeatable-read"> + <title>Repeatable Read Isolation Level</title> <indexterm> <primary>transaction isolation level</primary> - <secondary>serializable</secondary> + <secondary>repeatable read</secondary> + </indexterm> + + <indexterm> + <primary>repeatable read</primary> </indexterm> <para> - The <firstterm>Serializable</firstterm> isolation level provides the strictest transaction - isolation. This level emulates serial transaction execution, - as if transactions had been executed one after another, serially, - rather than concurrently. However, applications using this level must - be prepared to retry transactions due to serialization failures. + The <firstterm>Repeatable Read</firstterm> isolation level only sees + data committed before the transaction began; it never sees either + uncommitted data or changes committed during transaction execution + by concurrent transactions. (However, the query does see the + effects of previous updates executed within its own transaction, + even though they are not yet committed.) This is a stronger + guarantee than is required by the <acronym>SQL</acronym> standard + for this isolation level, and prevents all of the phenomena described + in <xref linkend="mvcc-isolevel-table">. As mentioned above, this is + specifically allowed by the standard, which only describes the + <emphasis>minimum</emphasis> protections each isolation level must + provide. </para> <para> - When a transaction is using the serializable level, - a <command>SELECT</command> query only sees data committed before the - transaction began; it never sees either uncommitted data or changes - committed - during transaction execution by concurrent transactions. (However, - the query does see the effects of previous updates - executed within its own transaction, even though they are not yet - committed.) This is different from Read Committed in that - a query in a serializable transaction - sees a snapshot as of the start of the <emphasis>transaction</>, - not as of the start + This level is different from Read Committed in that a query in a + repeatable read transaction sees a snapshot as of the start of the + <emphasis>transaction</>, not as of the start of the current query within the transaction. Thus, successive <command>SELECT</command> commands within a <emphasis>single</> transaction see the same data, i.e., they do not see changes made by other transactions that committed after their own transaction started. - (This behavior can be ideal for reporting applications.) + </para> + + <para> + Applications using this level must be prepared to retry transactions + due to serialization failures. </para> <para> @@ -386,22 +427,21 @@ COMMIT; behave the same as <command>SELECT</command> in terms of searching for target rows: they will only find target rows that were committed as of the transaction start time. However, such a - target - row might have already been updated (or deleted or locked) by + target row might have already been updated (or deleted or locked) by another concurrent transaction by the time it is found. In this case, the - serializable transaction will wait for the first updating transaction to commit or + repeatable read transaction will wait for the first updating transaction to commit or roll back (if it is still in progress). If the first updater rolls back, - then its effects are negated and the serializable transaction can proceed + then its effects are negated and the repeatable read transaction can proceed with updating the originally found row. But if the first updater commits (and actually updated or deleted the row, not just locked it) - then the serializable transaction will be rolled back with the message + then the repeatable read transaction will be rolled back with the message <screen> ERROR: could not serialize access due to concurrent update </screen> - because a serializable transaction cannot modify or lock rows changed by - other transactions after the serializable transaction began. + because a repeatable read transaction cannot modify or lock rows changed by + other transactions after the repeatable read transaction began. </para> <para> @@ -419,39 +459,70 @@ ERROR: could not serialize access due to concurrent update </para> <para> - The Serializable mode provides a rigorous guarantee that each - transaction sees a wholly consistent view of the database. However, - the application has to be prepared to retry transactions when concurrent - updates make it impossible to sustain the illusion of serial execution. - Since the cost of redoing complex transactions can be significant, - serializable mode is recommended only when updating transactions contain logic - sufficiently complex that they might give wrong answers in Read - Committed mode. Most commonly, Serializable mode is necessary when - a transaction executes several successive commands that must see - identical views of the database. + The Repeatable Read mode provides a rigorous guarantee that each + transaction sees a completely stable view of the database. However, + this view will not necessarily always be consistent with some serial + (one at a time) execution of concurrent transactions of the same level. + For example, even a read only transaction at this level may see a + control record updated to show that a batch has been completed but + <emphasis>not</emphasis> see one of the detail records which is logically + part of the batch because it read an earlier revision of the control + record. Attempts to enforce business rules by transactions running at + this isolation level are not likely to work correctly without careful use + of explicit locks to block conflicting transactions. </para> - <sect3 id="mvcc-serializability"> - <title>Serializable Isolation versus True Serializability</title> + <note> + <para> + Prior to <productname>PostgreSQL</productname> version 9.1, a request + for the Serializable transaction isolation level provided exactly the + same behavior described here. To retain the legacy Serializable + behavior, Repeatable Read should now be requested. + </para> + </note> + </sect2> + + <sect2 id="xact-serializable"> + <title>Serializable Isolation Level</title> + + <indexterm> + <primary>transaction isolation level</primary> + <secondary>serializable</secondary> + </indexterm> <indexterm> - <primary>serializability</primary> + <primary>serializable</primary> </indexterm> <indexterm> <primary>predicate locking</primary> </indexterm> + <indexterm> + <primary>serialization anomaly</primary> + </indexterm> + <para> - The intuitive meaning (and mathematical definition) of - <quote>serializable</> execution is that any two successfully committed - concurrent transactions will appear to have executed strictly serially, - one after the other — although which one appeared to occur first might - not be predictable in advance. It is important to realize that forbidding - the undesirable behaviors listed in <xref linkend="mvcc-isolevel-table"> - is not sufficient to guarantee true serializability, and in fact - <productname>PostgreSQL</productname>'s Serializable mode <emphasis>does - not guarantee serializable execution in this sense</>. As an example, + The <firstterm>Serializable</firstterm> isolation level provides the strictest transaction + isolation. This level emulates serial transaction execution, + as if transactions had been executed one after another, serially, + rather than concurrently. However, like the Repeatable Read level, + applications using this level must + be prepared to retry transactions due to serialization failures. + In fact, this isolation level works exactly the same as Repeatable + Read except that it monitors for conditions which could make + execution of a concurrent set of serializable transactions behave + in a manner inconsistent with all possible serial (one at a time) + executions of those transactions. This monitoring does not + introduce any blocking beyond that present in repeatable read, but + there is some overhead to the monitoring, and detection of the + conditions which could cause a + <firstterm>serialization anomaly</firstterm> will trigger a + <firstterm>serialization failure</firstterm>. + </para> + + <para> + As an example, consider a table <structname>mytab</>, initially containing: <screen> class | value @@ -472,48 +543,137 @@ SELECT SUM(value) FROM mytab WHERE class = 1; SELECT SUM(value) FROM mytab WHERE class = 2; </screen> and obtains the result 300, which it inserts in a new row with - <structfield>class</><literal> = 1</>. Then both transactions commit. None of - the listed undesirable behaviors have occurred, yet we have a result - that could not have occurred in either order serially. If A had + <structfield>class</><literal> = 1</>. Then both transactions try to commit. + If either transaction were running at the Repeatable Read isolation level, + both would be allowed to commit; but since there is no serial order of execution + consistent with the result, using Serializable transactions will allow one + transaction to commit and and will roll the other back with this message: + +<screen> +ERROR: could not serialize access due to read/write dependencies among transactions +</screen> + + This is because if A had executed before B, B would have computed the sum 330, not 300, and similarly the other order would have resulted in a different sum computed by A. </para> <para> - To guarantee true mathematical serializability, it is necessary for - a database system to enforce <firstterm>predicate locking</>, which - means that a transaction cannot insert or modify a row that would - have matched the <literal>WHERE</> condition of a query in another concurrent - transaction. For example, once transaction A has executed the query - <literal>SELECT ... WHERE class = 1</>, a predicate-locking system - would forbid transaction B from inserting any new row with class 1 - until A has committed. - <footnote> - <para> - Essentially, a predicate-locking system prevents phantom reads - by restricting what is written, whereas MVCC prevents them by - restricting what is read. - </para> - </footnote> - Such a locking system is complex to - implement and extremely expensive in execution, since every session must - be aware of the details of every query executed by every concurrent - transaction. And this large expense is mostly wasted, since in - practice most applications do not do the sorts of things that could - result in problems. (Certainly the example above is rather contrived - and unlikely to represent real software.) For these reasons, - <productname>PostgreSQL</productname> does not implement predicate - locking. + To guarantee true serializability <productname>PostgreSQL</productname> + uses <firstterm>predicate locking</>, which means that it keeps locks + which allow it to determine when a write would have had an impact on + the result of a previous read from a concurrent transaction, had it run + first. In <productname>PostgreSQL</productname> these locks do not + cause any blocking and therefore can <emphasis>not</> play any part in + causing a deadlock. They are used to identify and flag dependencies + among concurrent serializable transactions which in certain combinations + can lead to serialization anomalies. In contrast, a Read Committed or + Repeatable Read transaction which wants to ensure data consistency may + need to take out a lock on an entire table, which could block other + users attempting to use that table, or it may use <literal>SELECT FOR + UPDATE</literal> or <literal>SELECT FOR SHARE</literal> which not only + can block other transactions but cause disk access. + </para> + + <para> + Predicate locks in <productname>PostgreSQL</productname>, like in most + other database systems, are based on data actually accessed by a + transaction. These will show up in the + <link linkend="view-pg-locks"><structname>pg_locks</structname></link> + system view with a <literal>mode</> of <literal>SIReadLock</>. The + particular locks + acquired during execution of a query will depend on the plan used by + the query, and multiple finer-grained locks (e.g., tuple locks) may be + combined into fewer coarser-grained locks (e.g., page locks) during the + course of the transaction to prevent exhaustion of the memory used to + track the locks. A <literal>READ ONLY</> transaction may be able to + release its SIRead locks before completion, if it detects that no + conflicts can still occur which could lead to a serialization anomaly. + In fact, <literal>READ ONLY</> transactions will often be able to + establish that fact at startup and avoid taking any predicate locks. + If you explicitly request a <literal>SERIALIZABLE READ ONLY DEFERRABLE</> + transaction, it will block until it can establish this fact. (This is + the <emphasis>only</> case where Serializable transactions block but + Repeatable Read transactions don't.) On the other hand, SIRead locks + often need to be kept past transaction commit, until overlapping read + write transactions complete. </para> <para> - In cases where the possibility of non-serializable execution - is a real hazard, problems can be prevented by appropriate use of - explicit locking. Further discussion appears in the following - sections. + Consistent use of Serializable transactions can simplify development. + The guarantee that any set of concurrent serializable transactions will + have the same effect as if they were run one at a time means that if + you can demonstrate that a single transaction, as written, will do the + right thing when run by itself, you can have confidence that it will + do the right thing in any mix of serializable transactions, even without + any information about what those other transactions might do. It is + important that an environment which uses this technique have a + generalized way of handling serialization failures (which always return + with a SQLSTATE value of '40001'), because it will be very hard to + predict exactly which transactions might contribute to the read/write + dependencies and need to be rolled back to prevent serialization + anomalies. The monitoring of read/write dependencies has a cost, as does + the restart of transactions which are terminated with a serialization + failure, but balanced against the cost and blocking involved in use of + explicit locks and <literal>SELECT FOR UPDATE</> or <literal>SELECT FOR + SHARE</>, Serializable transactions are the best performance choice + for some environments. </para> - </sect3> + + <para> + For optimal performance when relying on Serializable transactions for + concurrency control, these issues should be considered: + + <itemizedlist> + <listitem> + <para> + Declare transactions as <literal>READ ONLY</> when possible. + </para> + </listitem> + <listitem> + <para> + Control the number of active connections, using a connection pool if + needed. This is always an important performance consideration, but + it can be particularly important in a busy system using Serializable + transactions. + </para> + </listitem> + <listitem> + <para> + Don't put more into a single transaction than needed for integrity + purposes. + </para> + </listitem> + <listitem> + <para> + Don't leave connections dangling <quote>idle in transaction</quote> + longer than necessary. + </para> + </listitem> + <listitem> + <para> + Eliminate explicit locks, <literal>SELECT FOR UPDATE</>, and + <literal>SELECT FOR SHARE</> where no longer needed due to the + protections automatically provided by Serializable transactions. + </para> + </listitem> + </itemizedlist> + </para> + + <warning> + <para> + Support for the Serializable transaction isolation level has not yet + been added to Hot Standby replication targets (described in + <xref linkend="hot-standby">). The strictest isolation level currently + supported in hot standby mode is Repeatable Read. While performing all + permanent database writes within Serializable transactions on the + master will ensure that all standbys will eventually reach a consistent + state, a Repeatable Read transaction run on the standby can sometimes + see a transient state which is inconsistent with any serial execution + of serializable transactions on the master. + </para> + </warning> </sect2> </sect1> @@ -532,7 +692,7 @@ SELECT SUM(value) FROM mytab WHERE class = 2; most <productname>PostgreSQL</productname> commands automatically acquire locks of appropriate modes to ensure that referenced tables are not dropped or modified in incompatible ways while the - command executes. (For example, <command>ALTER TABLE</> cannot safely be + command executes. (For example, <command>TRUNCATE</> cannot safely be executed concurrently with other operations on the same table, so it obtains an exclusive lock on the table to enforce that.) </para> @@ -546,7 +706,7 @@ SELECT SUM(value) FROM mytab WHERE class = 2; </para> <sect2 id="locking-tables"> - <title>Table-Level Locks</title> + <title>Table-level Locks</title> <indexterm zone="locking-tables"> <primary>LOCK</primary> @@ -578,7 +738,7 @@ SELECT SUM(value) FROM mytab WHERE class = 2; </para> <variablelist> - <title>Table-level lock modes</title> + <title>Table-level Lock Modes</title> <varlistentry> <term> <literal>ACCESS SHARE</literal> @@ -656,7 +816,8 @@ SELECT SUM(value) FROM mytab WHERE class = 2; <para> Acquired by <command>VACUUM</command> (without <option>FULL</option>), - <command>ANALYZE</>, and <command>CREATE INDEX CONCURRENTLY</>. + <command>ANALYZE</>, <command>CREATE INDEX CONCURRENTLY</>, and + some forms of <command>ALTER TABLE</command>. </para> </listitem> </varlistentry> @@ -692,11 +853,14 @@ SELECT SUM(value) FROM mytab WHERE class = 2; <literal>SHARE</literal>, <literal>SHARE ROW EXCLUSIVE</literal>, <literal>EXCLUSIVE</literal>, and <literal>ACCESS EXCLUSIVE</literal> lock modes. + This mode protects a table against concurrent data changes, and + is self-exclusive so that only one session can hold it at a time. </para> <para> - This lock mode is not automatically acquired by any - <productname>PostgreSQL</productname> command. + Acquired by <command>CREATE TRIGGER</command>, + <command>CREATE RULE</command> (except for <literal>ON SELECT</> + rules) and some forms of <command>ALTER TABLE</command>. </para> </listitem> </varlistentry> @@ -718,9 +882,8 @@ SELECT SUM(value) FROM mytab WHERE class = 2; </para> <para> - This lock mode is not automatically acquired on user tables by any - <productname>PostgreSQL</productname> command. However it is - acquired on certain system catalogs in some operations. + This lock mode is not automatically acquired on tables by any + <productname>PostgreSQL</productname> command. </para> </listitem> </varlistentry> @@ -742,11 +905,12 @@ SELECT SUM(value) FROM mytab WHERE class = 2; </para> <para> - Acquired by the <command>ALTER TABLE</command>, <command>DROP - TABLE</command>, <command>TRUNCATE</command>, <command>REINDEX</command>, + Acquired by the <command>DROP TABLE</command>, + <command>TRUNCATE</command>, <command>REINDEX</command>, <command>CLUSTER</command>, and <command>VACUUM FULL</command> - commands. This is also the default lock mode for <command>LOCK - TABLE</command> statements that do not specify a mode explicitly. + commands, and some forms of <command>ALTER TABLE</>. + This is also the default lock mode for <command>LOCK TABLE</command> + statements that do not specify a mode explicitly. </para> </listitem> </varlistentry> @@ -773,7 +937,7 @@ SELECT SUM(value) FROM mytab WHERE class = 2; <table tocentry="1" id="table-lock-compatibility"> - <title> Conflicting lock modes</title> + <title> Conflicting Lock Modes</title> <tgroup cols="9"> <colspec colnum="2" colname="lockst"> <colspec colnum="9" colname="lockend"> @@ -889,7 +1053,7 @@ SELECT SUM(value) FROM mytab WHERE class = 2; </sect2> <sect2 id="locking-rows"> - <title>Row-Level Locks</title> + <title>Row-level Locks</title> <para> In addition to table-level locks, there are row-level locks, which @@ -1035,19 +1199,28 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222; called <firstterm>advisory locks</>, because the system does not enforce their use — it is up to the application to use them correctly. Advisory locks can be useful for locking strategies - that are an awkward fit for the MVCC model. Once acquired, an - advisory lock is held until explicitly released or the session ends. - Unlike standard locks, advisory locks do not - honor transaction semantics: a lock acquired during a - transaction that is later rolled back will still be held following the + that are an awkward fit for the MVCC model.</para> + + <para> + There are two different types of advisory locks in + <productname>PostgreSQL</productname>: session level and transaction level. + Once acquired, a session level advisory lock is held until explicitly + released or the session ends. Unlike standard locks, session level + advisory locks do not honor transaction semantics: a lock acquired during + a transaction that is later rolled back will still be held following the rollback, and likewise an unlock is effective even if the calling - transaction fails later. The same lock can be acquired multiple times by - its owning process: for each lock request there must be a corresponding - unlock request before the lock is actually released. (If a session - already holds a given lock, additional requests will always succeed, even - if other sessions are awaiting the lock.) Like all locks in - <productname>PostgreSQL</productname>, a complete list of advisory - locks currently held by any session can be found in the + transaction fails later. The same session level lock can be acquired + multiple times by its owning process: for each lock request there must be + a corresponding unlock request before the lock is actually released. (If a + session already holds a given lock, additional requests will always succeed, + even if other sessions are awaiting the lock.) Transaction level locks on + the other hand behave more like regular locks; they are automatically + released at the end of the transaction, and can not be explicitly unlocked. + Session and transaction level locks share the same lock space, which means + that a transaction level lock will prevent another session from obtaining + a session level lock on that same resource and vice versa. + Like all locks in <productname>PostgreSQL</productname>, a complete list of + advisory locks currently held by any session can be found in the <link linkend="view-pg-locks"><structname>pg_locks</structname></link> system view. </para> @@ -1069,7 +1242,7 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222; strategies typical of so called <quote>flat file</> data management systems. While a flag stored in a table could be used for the same purpose, - advisory locks are faster, avoid MVCC bloat, and are automatically + advisory locks are faster, avoid MVCC bloat, and can be automatically cleaned up by the server at the end of the session. In certain cases using this advisory locking method, especially in queries involving explicit ordering and <literal>LIMIT</> clauses, care must be @@ -1105,80 +1278,148 @@ SELECT pg_advisory_lock(q.id) FROM <title>Data Consistency Checks at the Application Level</title> <para> - Because readers in <productname>PostgreSQL</productname> - do not lock data, regardless of - transaction isolation level, data read by one transaction can be - overwritten by another concurrent transaction. In other words, - if a row is returned by <command>SELECT</command> it doesn't mean that - the row is still current at the instant it is returned (i.e., sometime - after the current query began). The row might have been modified or - deleted by an already-committed transaction that committed after - the <command>SELECT</command> started. - Even if the row is still valid <quote>now</>, it could be changed or - deleted - before the current transaction does a commit or rollback. + It is very difficult to enforce business rules regarding data integrity + using Read Committed transactions because the view of the data is + shifting with each statement, and even a single statement may not + restrict itself to the statement's snapshot if a write conflict occurs. </para> <para> - Another way to think about it is that each - transaction sees a snapshot of the database contents, and concurrently - executing transactions might very well see different snapshots. So the - whole concept of <quote>now</quote> is somewhat ill-defined anyway. - This is not normally - a big problem if the client applications are isolated from each other, - but if the clients can communicate via channels outside the database - then serious confusion might ensue. + While a Repeatable Read transaction has a stable view of the data + throughout its execution, there is a subtle issue with using + <acronym>MVCC</acronym> snapshots for data consistency checks, involving + something known as <firstterm>read/write conflicts</firstterm>. + If one transaction writes data and a concurrent transaction attempts + to read the same data (whether before or after the write), it cannot + see the work of the other transaction. The reader then appears to have + executed first regardless of which started first or which committed + first. If that is as far as it goes, there is no problem, but + if the reader also writes data which is read by a concurrent transaction + there is now a transaction which appears to have run before either of + the previously mentioned transactions. If the transaction which appears + to have executed last actually commits first, it is very easy for a + cycle to appear in a graph of the order of execution of the transactions. + When such a cycle appears, integrity checks will not work correctly + without some help. </para> <para> - To ensure the current validity of a row and protect it against - concurrent updates one must use <command>SELECT FOR UPDATE</command>, - <command>SELECT FOR SHARE</command>, or an appropriate <command>LOCK - TABLE</command> statement. (<command>SELECT FOR UPDATE</command> - and <command>SELECT FOR SHARE</command> lock just the - returned rows against concurrent updates, while <command>LOCK - TABLE</command> locks the whole table.) This should be taken into - account when porting applications to - <productname>PostgreSQL</productname> from other environments. + As mentioned in <xref linkend="xact-serializable">, Serializable + transactions are just Repeatable Read transactions which add + non-blocking monitoring for dangerous patterns of read/write conflicts. + When a pattern is detected which could cause a cycle in the apparent + order of execution, one of the transactions involved is rolled back to + break the cycle. </para> - <para> - Global validity checks require extra thought under <acronym>MVCC</acronym>. - For example, a banking application might wish to check that the sum of - all credits in one table equals the sum of debits in another table, - when both tables are being actively updated. Comparing the results of two - successive <literal>SELECT sum(...)</literal> commands will not work reliably in - Read Committed mode, since the second query will likely include the results - of transactions not counted by the first. Doing the two sums in a - single serializable transaction will give an accurate picture of only the - effects of transactions that committed before the serializable transaction - started — but one might legitimately wonder whether the answer is still - relevant by the time it is delivered. If the serializable transaction - itself applied some changes before trying to make the consistency check, - the usefulness of the check becomes even more debatable, since now it - includes some but not all post-transaction-start changes. In such cases - a careful person might wish to lock all tables needed for the check, - in order to get an indisputable picture of current reality. A - <literal>SHARE</> mode (or higher) lock guarantees that there are no - uncommitted changes in the locked table, other than those of the current - transaction. - </para> + <sect2 id="serializable-consistency"> + <title>Enforcing Consistency With Serializable Transactions</title> - <para> - Note also that if one is relying on explicit locking to prevent concurrent - changes, one should either use Read Committed mode, or in Serializable - mode be careful to obtain - locks before performing queries. A lock obtained by a - serializable transaction guarantees that no other transactions modifying - the table are still running, but if the snapshot seen by the - transaction predates obtaining the lock, it might predate some now-committed - changes in the table. A serializable transaction's snapshot is actually - frozen at the start of its first query or data-modification command - (<literal>SELECT</>, <literal>INSERT</>, - <literal>UPDATE</>, or <literal>DELETE</>), so - it is possible to obtain locks explicitly before the snapshot is - frozen. - </para> + <para> + If the Serializable transaction isolation level is used for all writes + and for all reads which need a consistent view of the data, no other + effort is required to ensure consistency. Software from other + environments which is written to use serializable transactions to + ensure consistency should <quote>just work</quote> in this regard in + <productname>PostgreSQL</productname>. + </para> + + <para> + When using this technique, it will avoid creating an unnecessary burden + for application programmers if the application software goes through a + framework which automatically retries transactions which are rolled + back with a serialization failure. It may be a good idea to set + <literal>default_transaction_isolation</> to <literal>serializable</>. + It would also be wise to take some action to ensure that no other + transaction isolation level is used, either inadvertently or to + subvert integrity checks, through checks of the transaction isolation + level in triggers. + </para> + + <para> + See <xref linkend="xact-serializable"> for performance suggestions. + </para> + + <warning> + <para> + This level of integrity protection using Serializable transactions + does not yet extend to hot standby mode (<xref linkend="hot-standby">). + Because of that, those using hot standby may want to use Repeatable + Read and explicit locking.on the master. + </para> + </warning> + </sect2> + + <sect2 id="non-serializable-consistency"> + <title>Enforcing Consistency With Explicit Blocking Locks</title> + + <para> + When non-serializable writes are possible, + to ensure the current validity of a row and protect it against + concurrent updates one must use <command>SELECT FOR UPDATE</command>, + <command>SELECT FOR SHARE</command>, or an appropriate <command>LOCK + TABLE</command> statement. (<command>SELECT FOR UPDATE</command> + and <command>SELECT FOR SHARE</command> lock just the + returned rows against concurrent updates, while <command>LOCK + TABLE</command> locks the whole table.) This should be taken into + account when porting applications to + <productname>PostgreSQL</productname> from other environments. + </para> + + <para> + Also of note to those converting from other environments is the fact + that <command>SELECT FOR UPDATE</command> does not ensure that a + concurrent transaction will not update or delete a selected row. + To do that in <productname>PostgreSQL</productname> you must actually + update the row, even if no values need to be changed. + <command>SELECT FOR UPDATE</command> <emphasis>temporarily blocks</emphasis> + other transactions from acquiring the same lock or executing an + <command>UPDATE</command> or <command>DELETE</command> which would + affect the locked row, but once the transaction holding this lock + commits or rolls back, a blocked transaction will proceed with the + conflicting operation unless an actual <command>UPDATE</command> of + the row was performed while the lock was held. + </para> + + <para> + Global validity checks require extra thought under + non-serializable <acronym>MVCC</acronym>. + For example, a banking application might wish to check that the sum of + all credits in one table equals the sum of debits in another table, + when both tables are being actively updated. Comparing the results of two + successive <literal>SELECT sum(...)</literal> commands will not work reliably in + Read Committed mode, since the second query will likely include the results + of transactions not counted by the first. Doing the two sums in a + single repeatable read transaction will give an accurate picture of only the + effects of transactions that committed before the repeatable read transaction + started — but one might legitimately wonder whether the answer is still + relevant by the time it is delivered. If the repeatable read transaction + itself applied some changes before trying to make the consistency check, + the usefulness of the check becomes even more debatable, since now it + includes some but not all post-transaction-start changes. In such cases + a careful person might wish to lock all tables needed for the check, + in order to get an indisputable picture of current reality. A + <literal>SHARE</> mode (or higher) lock guarantees that there are no + uncommitted changes in the locked table, other than those of the current + transaction. + </para> + + <para> + Note also that if one is relying on explicit locking to prevent concurrent + changes, one should either use Read Committed mode, or in Repeatable Read + mode be careful to obtain + locks before performing queries. A lock obtained by a + repeatable read transaction guarantees that no other transactions modifying + the table are still running, but if the snapshot seen by the + transaction predates obtaining the lock, it might predate some now-committed + changes in the table. A repeatable read transaction's snapshot is actually + frozen at the start of its first query or data-modification command + (<literal>SELECT</>, <literal>INSERT</>, + <literal>UPDATE</>, or <literal>DELETE</>), so + it is possible to obtain locks explicitly before the snapshot is + frozen. + </para> + </sect2> </sect1> <sect1 id="locking-indexes"> diff --git a/doc/src/sgml/nls.sgml b/doc/src/sgml/nls.sgml index da8902a584..778bb4b044 100644 --- a/doc/src/sgml/nls.sgml +++ b/doc/src/sgml/nls.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/nls.sgml,v 1.19 2010/03/17 17:12:31 petere Exp $ --> +<!-- doc/src/sgml/nls.sgml --> <chapter id="nls"> <chapterinfo> @@ -46,7 +46,7 @@ <filename>msgmerge</filename>, respectively, in a GNU-compatible implementation. Later, we will try to arrange it so that if you use a packaged source distribution, you won't need - <filename>xgettext</filename>. (If working from CVS, you will still need + <filename>xgettext</filename>. (If working from Git, you will still need it.) <application>GNU Gettext 0.10.36</application> or later is currently recommended. </para> @@ -138,7 +138,7 @@ msgstr "another translated" </sect2> <sect2> - <title>Creating and maintaining message catalogs</title> + <title>Creating and Maintaining Message Catalogs</title> <para> OK, so how does one create a <quote>blank</quote> message @@ -206,7 +206,7 @@ gmake update-po </sect2> <sect2> - <title>Editing the PO files</title> + <title>Editing the PO Files</title> <para> The PO files can be edited with a regular text editor. The @@ -313,7 +313,7 @@ msgstr "Die Datei %2$s hat %1$u Zeichen." </para> <procedure> - <title>Adding NLS support to a program</title> + <title>Adding NLS Support to a Program</title> <step> <para> @@ -440,7 +440,7 @@ fprintf(stderr, gettext("panic level %d\n"), lvl); </sect2> <sect2 id="nls-guidelines"> - <title>Message-writing guidelines</title> + <title>Message-writing Guidelines</title> <para> Here are some guidelines for writing messages that are easily diff --git a/doc/src/sgml/notation.sgml b/doc/src/sgml/notation.sgml index 7620156b07..48a82ca376 100644 --- a/doc/src/sgml/notation.sgml +++ b/doc/src/sgml/notation.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/notation.sgml,v 1.27 2006/03/10 19:10:48 momjian Exp $ --> +<!-- doc/src/sgml/notation.sgml --> <sect1 id="notation"> <title>Conventions</title> diff --git a/doc/src/sgml/oid2name.sgml b/doc/src/sgml/oid2name.sgml index 5e793ce199..3e4fe24a49 100644 --- a/doc/src/sgml/oid2name.sgml +++ b/doc/src/sgml/oid2name.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/oid2name.sgml,v 1.8 2010/05/25 15:55:28 momjian Exp $ --> +<!-- doc/src/sgml/oid2name.sgml --> -<sect1 id="oid2name"> +<sect1 id="oid2name" xreflabel="oid2name"> <title>oid2name</title> <indexterm zone="oid2name"> @@ -105,7 +105,7 @@ <varlistentry> <term><option>-U</option> <replaceable>username</></term> - <listitem><para>username to connect as</para></listitem> + <listitem><para>user name to connect as</para></listitem> </varlistentry> <varlistentry> @@ -122,8 +122,8 @@ using <option>-o</>, <option>-f</> and/or <option>-t</>. <option>-o</> takes an OID, <option>-f</> takes a filenode, - and <option>-t</> takes a tablename (actually, it's a LIKE - pattern, so you can use things like <option>foo%</>). + and <option>-t</> takes a table name (actually, it's a <literal>LIKE</> + pattern, so you can use things like <literal>foo%</>). You can use as many of these options as you like, and the listing will include all objects matched by any of the options. But note that these options can only @@ -147,7 +147,7 @@ <sect2> <title>Examples</title> - <programlisting> +<screen> $ # what's in this database server, anyway? $ oid2name All databases: @@ -264,7 +264,7 @@ From database "alvherre": Filenode Table Name ---------------------- 155156 foo - </programlisting> +</screen> </sect2> <sect2> diff --git a/doc/src/sgml/pageinspect.sgml b/doc/src/sgml/pageinspect.sgml index a81989a2a3..acbb05bc9c 100644 --- a/doc/src/sgml/pageinspect.sgml +++ b/doc/src/sgml/pageinspect.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pageinspect.sgml,v 1.6 2009/06/08 16:22:44 tgl Exp $ --> +<!-- doc/src/sgml/pageinspect.sgml --> -<sect1 id="pageinspect"> +<sect1 id="pageinspect" xreflabel="pageinspect"> <title>pageinspect</title> <indexterm zone="pageinspect"> @@ -62,15 +62,12 @@ <para> A page image obtained with <function>get_raw_page</function> should be passed as argument. For example: - </para> - <programlisting> +<screen> test=# SELECT * FROM page_header(get_raw_page('pg_class', 0)); lsn | tli | flags | lower | upper | special | pagesize | version | prune_xid -----------+-----+-------+-------+-------+---------+----------+---------+----------- 0/24A1B50 | 1 | 1 | 232 | 368 | 8192 | 8192 | 4 | 0 - </programlisting> - - <para> +</screen> The returned columns correspond to the fields in the <structname>PageHeaderData</> struct. See <filename>src/include/storage/bufpage.h</> for details. @@ -93,11 +90,9 @@ test=# SELECT * FROM page_header(get_raw_page('pg_class', 0)); <para> A heap page image obtained with <function>get_raw_page</function> should be passed as argument. For example: - </para> - <programlisting> +<screen> test=# SELECT * FROM heap_page_items(get_raw_page('pg_class', 0)); - </programlisting> - <para> +</screen> See <filename>src/include/storage/itemid.h</> and <filename>src/include/access/htup.h</> for explanations of the fields returned. @@ -112,10 +107,9 @@ test=# SELECT * FROM heap_page_items(get_raw_page('pg_class', 0)); <listitem> <para> - <function>bt_metap</function> returns information about a btree + <function>bt_metap</function> returns information about a B-tree index's metapage. For example: - </para> - <programlisting> +<screen> test=# SELECT * FROM bt_metap('pg_cast_oid_index'); -[ RECORD 1 ]----- magic | 340322 @@ -124,7 +118,8 @@ root | 1 level | 0 fastroot | 1 fastlevel | 0 - </programlisting> +</screen> + </para> </listitem> </varlistentry> @@ -136,9 +131,8 @@ fastlevel | 0 <listitem> <para> <function>bt_page_stats</function> returns summary information about - single pages of btree indexes. For example: - </para> - <programlisting> + single pages of B-tree indexes. For example: +<screen> test=# SELECT * FROM bt_page_stats('pg_cast_oid_index', 1); -[ RECORD 1 ]-+----- blkno | 1 @@ -152,7 +146,8 @@ btpo_prev | 0 btpo_next | 0 btpo | 0 btpo_flags | 3 - </programlisting> +</screen> + </para> </listitem> </varlistentry> @@ -164,9 +159,8 @@ btpo_flags | 3 <listitem> <para> <function>bt_page_items</function> returns detailed information about - all of the items on a btree index page. For example: - </para> - <programlisting> + all of the items on a B-tree index page. For example: +<screen> test=# SELECT * FROM bt_page_items('pg_cast_oid_index', 1); itemoffset | ctid | itemlen | nulls | vars | data ------------+---------+---------+-------+------+------------- @@ -178,7 +172,8 @@ test=# SELECT * FROM bt_page_items('pg_cast_oid_index', 1); 6 | (0,6) | 12 | f | f | 28 27 00 00 7 | (0,7) | 12 | f | f | 29 27 00 00 8 | (0,8) | 12 | f | f | 2a 27 00 00 - </programlisting> +</screen> + </para> </listitem> </varlistentry> @@ -190,7 +185,7 @@ test=# SELECT * FROM bt_page_items('pg_cast_oid_index', 1); <listitem> <para> <function>fsm_page_contents</function> shows the internal node structure - of a FSM page. The output is a multi-line string, with one line per + of a FSM page. The output is a multiline string, with one line per node in the binary tree within the page. Only those nodes that are not zero are printed. The so-called "next" pointer, which points to the next slot to be returned from the page, is also printed. diff --git a/doc/src/sgml/passwordcheck.sgml b/doc/src/sgml/passwordcheck.sgml index 2da1f52650..0050e65824 100644 --- a/doc/src/sgml/passwordcheck.sgml +++ b/doc/src/sgml/passwordcheck.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/passwordcheck.sgml,v 1.2 2010/04/03 07:22:55 petere Exp $ --> +<!-- doc/src/sgml/passwordcheck.sgml --> -<sect1 id="passwordcheck"> +<sect1 id="passwordcheck" xreflabel="passwordcheck"> <title>passwordcheck</title> <indexterm zone="passwordcheck"> diff --git a/doc/src/sgml/perform.sgml b/doc/src/sgml/perform.sgml index b69813cedb..2d115fa26e 100644 --- a/doc/src/sgml/perform.sgml +++ b/doc/src/sgml/perform.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/perform.sgml,v 1.82 2010/06/28 22:46:11 momjian Exp $ --> +<!-- doc/src/sgml/perform.sgml --> <chapter id="performance-tips"> <title>Performance Tips</title> @@ -316,7 +316,7 @@ WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2; -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..2.37 rows=106 width=0) Index Cond: (unique1 < 100) -> Index Scan using tenk2_unique2 on tenk2 t2 (cost=0.00..3.01 rows=1 width=244) - Index Cond: (t2.unique2 = t1.unique2) + Index Cond: (unique2 = t1.unique2) </programlisting> </para> @@ -329,7 +329,7 @@ WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2; so it doesn't affect the row count of the outer scan. For the inner (lower) scan, the <literal>unique2</> value of the current outer-scan row is plugged into the inner index scan to produce an index condition like - <literal>t2.unique2 = <replaceable>constant</replaceable></literal>. + <literal>unique2 = <replaceable>constant</replaceable></literal>. So we get the same inner-scan plan and costs that we'd get from, say, <literal>EXPLAIN SELECT * FROM tenk2 WHERE unique2 = 42</literal>. The costs of the loop node are then set on the basis of the cost of the outer @@ -405,7 +405,7 @@ WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2; -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..2.37 rows=106 width=0) (actual time=0.546..0.546 rows=100 loops=1) Index Cond: (unique1 < 100) -> Index Scan using tenk2_unique2 on tenk2 t2 (cost=0.00..3.01 rows=1 width=244) (actual time=0.067..0.078 rows=1 loops=100) - Index Cond: (t2.unique2 = t1.unique2) + Index Cond: (unique2 = t1.unique2) Total runtime: 14.452 ms </screen> @@ -430,18 +430,30 @@ WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2; <para> The <literal>Total runtime</literal> shown by <command>EXPLAIN - ANALYZE</command> includes executor start-up and shut-down time, as well - as time spent processing the result rows. It does not include parsing, - rewriting, or planning time. For a <command>SELECT</> query, the total - run time will normally be just a little larger than the total time - reported for the top-level plan node. For <command>INSERT</>, - <command>UPDATE</>, and <command>DELETE</> commands, the total run time - might be considerably larger, because it includes the time spent processing - the result rows. For these commands, the time for the top plan node is - essentially the time spent locating the old rows and/or computing - the new ones, but it doesn't include the time spent applying the changes. - Time spent firing triggers, if any, is also outside the top plan node, - and is shown separately for each trigger. + ANALYZE</command> includes executor start-up and shut-down time, but not + parsing, rewriting, or planning time. For <command>INSERT</>, + <command>UPDATE</>, and <command>DELETE</> commands, the time spent + applying the table changes is charged to a top-level Insert, Update, + or Delete plan node. (The plan nodes underneath this node represent + the work of locating the old rows and/or computing the new ones.) + Time spent executing <literal>BEFORE</> triggers, if any, is charged to + the related Insert, Update, or Delete node, although time spent executing + <literal>AFTER</> triggers is not. The time spent in each trigger + (either <literal>BEFORE</> or <literal>AFTER</>) is also shown separately + and is included in total run time. + Note, however, that deferred constraint triggers will not be executed + until end of transaction and are thus not shown by + <command>EXPLAIN ANALYZE</command>. + </para> + + <para> + There are two significant ways in which run times measured by + <command>EXPLAIN ANALYZE</command> can deviate from normal execution of + the same query. First, since no output rows are delivered to the client, + network transmission costs and I/O formatting costs are not included. + Second, the overhead added by <command>EXPLAIN ANALYZE</command> can be + significant, especially on machines with slow <function>gettimeofday()</> + kernel calls. </para> <para> @@ -937,7 +949,7 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse; </sect2> <sect2 id="populate-pitr"> - <title>Disable WAL archival and streaming replication</title> + <title>Disable WAL Archival and Streaming Replication</title> <para> When loading large amounts of data into an installation that uses @@ -1086,7 +1098,7 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse; <para> You can get the effect of disabling foreign keys by using the <option>--disable-triggers</> option — but realize that - that eliminates, rather than just postponing, foreign key + that eliminates, rather than just postpones, foreign key validation, and so it is possible to insert bad data if you use it. </para> </footnote> @@ -1118,9 +1130,10 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse; so if your site does not require such a guarantee, <productname>PostgreSQL</productname> can be configured to run much faster. The following are configuration changes you can make - to improve performance in such cases; they do not invalidate - commit guarantees related to database crashes, only abrupt operating - system stoppage, except as mentioned below: + to improve performance in such cases. Except as noted below, durability + is still guaranteed in case of a crash of the database software; + only abrupt operating system stoppage creates a risk of data loss + or corruption when these settings are used. <itemizedlist> <listitem> @@ -1159,7 +1172,8 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse; <para> Turn off <xref linkend="guc-synchronous-commit">; there might be no need to write the <acronym>WAL</acronym> to disk on every - commit. This does affect database crash transaction durability. + commit. This setting does risk transaction loss (though not data + corruption) in case of a crash of the <emphasis>database</> alone. </para> </listitem> </itemizedlist> diff --git a/doc/src/sgml/pgarchivecleanup.sgml b/doc/src/sgml/pgarchivecleanup.sgml index 7a839ba5f0..ddffa321f6 100644 --- a/doc/src/sgml/pgarchivecleanup.sgml +++ b/doc/src/sgml/pgarchivecleanup.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pgarchivecleanup.sgml,v 1.1 2010/06/14 17:25:24 sriggs Exp $ --> +<!-- doc/src/sgml/pgarchivecleanup.sgml --> -<sect1 id="pgarchivecleanup"> +<sect1 id="pgarchivecleanup" xreflabel="pg_archivecleanup"> <title>pg_archivecleanup</title> <indexterm zone="pgarchivecleanup"> @@ -8,10 +8,11 @@ </indexterm> <para> - <application>pg_archivecleanup</> is designed to cleanup an archive when used - as an <literal>archive_cleanup_command</literal> when running with - <literal>standby_mode = on</literal>. <application>pg_archivecleanup</> can - also be used as a standalone program to clean WAL file archives. + <application>pg_archivecleanup</> is designed to be used as an + <literal>archive_cleanup_command</literal> to clean up WAL file archives when + running as a standby server (see <xref linkend="warm-standby">). + <application>pg_archivecleanup</> can also be used as a standalone program to + clean WAL file archives. </para> <para> @@ -38,47 +39,42 @@ To configure a standby server to use <application>pg_archivecleanup</>, put this into its <filename>recovery.conf</filename> configuration file: +<programlisting> +archive_cleanup_command = 'pg_archivecleanup <replaceable>archivelocation</> %r' +</programlisting> + where <replaceable>archivelocation</> is the directory from which WAL segment + files should be removed. </para> - <programlisting> -archive_cleanup_command = 'pg_archivecleanup <replaceable>archiveDir</> %r' - </programlisting> <para> - where <replaceable>archiveDir</> is the directory from which WAL segment - files should be restored. - </para> - <para> - When used within <literal>archive_cleanup_command</literal>, - all WAL files logically preceding the value of the <literal>%r</> - will be removed <replaceable>archivelocation</>. This minimizes - the number of files that need to be retained, while preserving - crash-restart capability. Use of this parameter is appropriate if the - <replaceable>archivelocation</> is a transient staging area for this - particular standby server, but <emphasis>not</> when the - <replaceable>archivelocation</> is intended as a long-term WAL archive area. + When used within <xref linkend="archive-cleanup-command">, all WAL files + logically preceding the value of the <literal>%r</> argument will be removed + from <replaceable>archivelocation</>. This minimizes the number of files + that need to be retained, while preserving crash-restart capability. Use of + this parameter is appropriate if the <replaceable>archivelocation</> is a + transient staging area for this particular standby server, but + <emphasis>not</> when the <replaceable>archivelocation</> is intended as a + long-term WAL archive area, or when multiple standby servers are recovering + from the same archive location. </para> <para> The full syntax of <application>pg_archivecleanup</>'s command line is - </para> - <synopsis> +<synopsis> pg_archivecleanup <optional> <replaceable>option</> ... </optional> <replaceable>archivelocation</> <replaceable>restartwalfile</> - </synopsis> - <para> - When used as a standalone program all WAL files logically preceding the +</synopsis> + When used as a standalone program all WAL files logically preceding the <literal>restartwalfile</> will be removed <replaceable>archivelocation</>. - In this mode, if you specify a .backup filename, then only the file prefix + In this mode, if you specify a <filename>.backup</> file name, then only the file prefix will be used as the <literal>restartwalfile</>. This allows you to remove all WAL files archived prior to a specific base backup without error. For example, the following example will remove all files older than - WAL filename 000000010000003700000010: - </para> - <programlisting> + WAL file name <filename>000000010000003700000010</>: +<programlisting> pg_archivecleanup -d archive 000000010000003700000010.00000020.backup -pg_archivecleanup: keep WAL files 000000010000003700000010 and later -pg_archivecleanup: removing "archive/00000001000000370000000F" -pg_archivecleanup: removing "archive/00000001000000370000000E" - </programlisting> - <para> +pg_archivecleanup: keep WAL file "archive/000000010000003700000010" and later +pg_archivecleanup: removing file "archive/00000001000000370000000F" +pg_archivecleanup: removing file "archive/00000001000000370000000E" +</programlisting> <application>pg_archivecleanup</application> assumes that <replaceable>archivelocation</> is a directory readable and writable by the server-owning user. @@ -110,21 +106,19 @@ pg_archivecleanup: removing "archive/00000001000000370000000E" <sect2> <title>Examples</title> - <para>On Linux or Unix systems, you might use:</para> - - <programlisting> -archive_cleanup_command = 'pg_archivecleanup -d .../archive %r 2>>cleanup.log' - </programlisting> - <para> + <para>On Linux or Unix systems, you might use: +<programlisting> +archive_cleanup_command = 'pg_archivecleanup -d /mnt/standby/archive %r 2>>cleanup.log' +</programlisting> where the archive directory is physically located on the standby server, - so that the <literal>archive_command</> is accessing it across NFS, + so that the <varname>archive_command</> is accessing it across NFS, but the files are local to the standby. This will: </para> <itemizedlist> <listitem> <para> - produce debugging output in <filename>standby.log</> + produce debugging output in <filename>cleanup.log</> </para> </listitem> <listitem> @@ -137,7 +131,7 @@ archive_cleanup_command = 'pg_archivecleanup -d .../archive %r 2>>cleanup.log' </sect2> <sect2> - <title>Supported server versions</title> + <title>Supported Server Versions</title> <para> <application>pg_archivecleanup</application> is designed to work with diff --git a/doc/src/sgml/pgbench.sgml b/doc/src/sgml/pgbench.sgml index bc0cd9c0c2..e7b78605ec 100644 --- a/doc/src/sgml/pgbench.sgml +++ b/doc/src/sgml/pgbench.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pgbench.sgml,v 1.16 2010/05/25 15:55:28 momjian Exp $ --> +<!-- doc/src/sgml/pgbench.sgml --> -<sect1 id="pgbench"> +<sect1 id="pgbench" xreflabel="pgbench"> <title>pgbench</title> <indexterm zone="pgbench"> @@ -22,7 +22,7 @@ <para> Typical output from pgbench looks like: - <programlisting> +<screen> transaction type: TPC-B (sort of) scaling factor: 10 query mode: simple @@ -32,13 +32,15 @@ number of transactions per client: 1000 number of transactions actually processed: 10000/10000 tps = 85.184871 (including connections establishing) tps = 85.296346 (excluding connections establishing) - </programlisting> +</screen> The first six lines report some of the most important parameter settings. The next line reports the number of transactions completed and intended (the latter being just the product of number of clients and number of transactions per client); these will be equal unless the run - failed before completion. The last two lines report the TPS rate, + failed before completion. (In <literal>-T</> mode, only the actual + number of transactions is printed.) + The last two lines report the number of transactions per second, figured with and without counting the time to start database sessions. </para> @@ -53,9 +55,9 @@ tps = 85.296346 (excluding connections establishing) step, but will instead need to do whatever setup your test needs.) Initialization looks like: - <programlisting> +<programlisting> pgbench -i <optional> <replaceable>other-options</> </optional> <replaceable>dbname</> - </programlisting> +</programlisting> where <replaceable>dbname</> is the name of the already-created database to test in. (You may also need <literal>-h</>, @@ -77,16 +79,14 @@ pgbench -i <optional> <replaceable>other-options</> </optional> <replaceable>dbn <para> At the default <quote>scale factor</> of 1, the tables initially contain this many rows: - </para> - <programlisting> +<screen> table # of rows --------------------------------- pgbench_branches 1 pgbench_tellers 10 pgbench_accounts 100000 pgbench_history 0 - </programlisting> - <para> +</screen> You can (and, for most purposes, probably should) increase the number of rows by using the <literal>-s</> (scale factor) option. The <literal>-F</> (fillfactor) option might also be used at this point. @@ -96,9 +96,9 @@ pgbench_history 0 Once you have done the necessary setup, you can run your benchmark with a command that doesn't include <literal>-i</>, that is - <programlisting> +<programlisting> pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> - </programlisting> +</programlisting> In nearly all cases, you'll need some options to make a useful test. The most important options are <literal>-c</> (number of clients), @@ -128,22 +128,22 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> <variablelist> <varlistentry> - <term><option>-F</option> <replaceable>fillfactor</></term> + <term><option>-i</option></term> <listitem> <para> - Create the <structname>pgbench_accounts</>, - <structname>pgbench_tellers</> and - <structname>pgbench_branches</> tables with the given fillfactor. - Default is 100. + Required to invoke initialization mode. </para> </listitem> </varlistentry> <varlistentry> - <term><option>-i</option></term> + <term><option>-F</option> <replaceable>fillfactor</></term> <listitem> <para> - Required to invoke initialization mode. + Create the <structname>pgbench_accounts</>, + <structname>pgbench_tellers</> and + <structname>pgbench_branches</> tables with the given fillfactor. + Default is 100. </para> </listitem> </varlistentry> @@ -242,7 +242,7 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> <term><option>-l</option></term> <listitem> <para> - Write the time taken by each transaction to a logfile. + Write the time taken by each transaction to a log file. See below for details. </para> </listitem> @@ -297,6 +297,17 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> </varlistentry> <varlistentry> + <term><option>-r</option></term> + <listitem> + <para> + Report the average per-statement latency (execution time from the + perspective of the client) of each command after the benchmark + finishes. See below for details. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><option>-s</option> <replaceable>scale_factor</></term> <listitem> <para> @@ -369,7 +380,7 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> <term><option>-h</option> <replaceable>hostname</></term> <listitem> <para> - The database server's hostname + The database server's host name </para> </listitem> </varlistentry> @@ -387,7 +398,7 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> <term><option>-U</option> <replaceable>login</></term> <listitem> <para> - The username to connect as + The user name to connect as </para> </listitem> </varlistentry> @@ -398,7 +409,7 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> </sect2> <sect2> - <title>What is the <quote>transaction</> actually performed in pgbench?</title> + <title>What is the <quote>Transaction</> Actually Performed in pgbench?</title> <para> The default transaction script issues seven commands per transaction: @@ -436,7 +447,7 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> </para> <para> - The format of a script file is one SQL command per line; multi-line + The format of a script file is one SQL command per line; multiline SQL commands are not supported. Empty lines and lines beginning with <literal>--</> are ignored. Script file lines can also be <quote>meta commands</>, which are interpreted by <application>pgbench</> @@ -478,9 +489,9 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> <para> Example: - <programlisting> +<programlisting> \set ntellers 10 * :scale - </programlisting> +</programlisting> </para> </listitem> </varlistentry> @@ -501,9 +512,9 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> <para> Example: - <programlisting> +<programlisting> \setrandom aid 1 :naccounts - </programlisting> +</programlisting> </para> </listitem> </varlistentry> @@ -525,9 +536,9 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> <para> Example: - <programlisting> +<programlisting> \sleep 10 ms - </programlisting> +</programlisting> </para> </listitem> </varlistentry> @@ -554,9 +565,9 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> <para> Example: - <programlisting> +<programlisting> \setshell variable_to_be_assigned command literal_argument :variable ::literal_starting_with_colon - </programlisting> +</programlisting> </para> </listitem> </varlistentry> @@ -573,9 +584,9 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> <para> Example: - <programlisting> +<programlisting> \shell command literal_argument :variable ::literal_starting_with_colon - </programlisting> +</programlisting> </para> </listitem> </varlistentry> @@ -585,7 +596,7 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> As an example, the full definition of the built-in TPC-B-like transaction is: - <programlisting> +<programlisting> \set nbranches :scale \set ntellers 10 * :scale \set naccounts 100000 * :scale @@ -600,7 +611,7 @@ UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid; UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid; INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP); END; - </programlisting> +</programlisting> This script allows each iteration of the transaction to reference different, randomly-chosen rows. (This example also shows why it's @@ -611,16 +622,16 @@ END; </sect2> <sect2> - <title>Per-transaction logging</title> + <title>Per-Transaction Logging</title> <para> With the <literal>-l</> option, <application>pgbench</> writes the time - taken by each transaction to a logfile. The logfile will be named + taken by each transaction to a log file. The log file will be named <filename>pgbench_log.<replaceable>nnn</></filename>, where <replaceable>nnn</> is the PID of the pgbench process. If the <literal>-j</> option is 2 or higher, creating multiple worker threads, each will have its own log file. The first worker will use the - same name for its log file as in the standard single worker case. + same name for its log file as in the standard single worker case. The additional log files for the other workers will be named <filename>pgbench_log.<replaceable>nnn</>.<replaceable>mmm</></filename>, where <replaceable>mmm</> is a sequential number for each worker starting @@ -630,11 +641,11 @@ END; <para> The format of the log is: - <programlisting> - <replaceable>client_id</> <replaceable>transaction_no</> <replaceable>time</> <replaceable>file_no</> <replaceable>time_epoch</> <replaceable>time_us</> - </programlisting> +<synopsis> +<replaceable>client_id</> <replaceable>transaction_no</> <replaceable>time</> <replaceable>file_no</> <replaceable>time_epoch</> <replaceable>time_us</> +</synopsis> - where <replaceable>time</> is the elapsed transaction time in microseconds, + where <replaceable>time</> is the total elapsed transaction time in microseconds, <replaceable>file_no</> identifies which script file was used (useful when multiple scripts were specified with <literal>-f</>), and <replaceable>time_epoch</>/<replaceable>time_us</> are a @@ -646,12 +657,68 @@ END; <para> Here are example outputs: - <programlisting> +<screen> 0 199 2241 0 1175850568 995598 0 200 2465 0 1175850568 998079 0 201 2513 0 1175850569 608 0 202 2038 0 1175850569 2663 - </programlisting> +</screen> + </para> + </sect2> + + <sect2> + <title>Per-Statement Latencies</title> + + <para> + With the <literal>-r</> option, <application>pgbench</> collects + the elapsed transaction time of each statement executed by every + client. It then reports an average of those values, referred to + as the latency for each statement, after the benchmark has finished. + </para> + + <para> + For the default script, the output will look similar to this: +<screen> +starting vacuum...end. +transaction type: TPC-B (sort of) +scaling factor: 1 +query mode: simple +number of clients: 10 +number of threads: 1 +number of transactions per client: 1000 +number of transactions actually processed: 10000/10000 +tps = 618.764555 (including connections establishing) +tps = 622.977698 (excluding connections establishing) +statement latencies in milliseconds: + 0.004386 \set nbranches 1 * :scale + 0.001343 \set ntellers 10 * :scale + 0.001212 \set naccounts 100000 * :scale + 0.001310 \setrandom aid 1 :naccounts + 0.001073 \setrandom bid 1 :nbranches + 0.001005 \setrandom tid 1 :ntellers + 0.001078 \setrandom delta -5000 5000 + 0.326152 BEGIN; + 0.603376 UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid; + 0.454643 SELECT abalance FROM pgbench_accounts WHERE aid = :aid; + 5.528491 UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid; + 7.335435 UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid; + 0.371851 INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP); + 1.212976 END; +</screen> + </para> + + <para> + If multiple script files are specified, the averages are reported + separately for each script file. + </para> + + <para> + Note that collecting the additional timing information needed for + per-statement latency computation adds some overhead. This will slow + average execution speed and lower the computed TPS. The amount + of slowdown varies significantly depending on platform and hardware. + Comparing average TPS values with and without latency reporting enabled + is a good way to measure if the timing overhead is significant. </para> </sect2> diff --git a/doc/src/sgml/pgbuffercache.sgml b/doc/src/sgml/pgbuffercache.sgml index 3ea74ec507..1d7d95f9d7 100644 --- a/doc/src/sgml/pgbuffercache.sgml +++ b/doc/src/sgml/pgbuffercache.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pgbuffercache.sgml,v 2.6 2010/02/07 20:48:09 tgl Exp $ --> +<!-- doc/src/sgml/pgbuffercache.sgml --> -<sect1 id="pgbuffercache"> +<sect1 id="pgbuffercache" xreflabel="pg_buffercache"> <title>pg_buffercache</title> <indexterm zone="pgbuffercache"> @@ -25,7 +25,7 @@ </para> <sect2> - <title>The <structname>pg_buffercache</structname> view</title> + <title>The <structname>pg_buffercache</structname> View</title> <para> The definitions of the columns exposed by the view are shown in <xref linkend="pgbuffercache-columns">. @@ -132,31 +132,32 @@ </sect2> <sect2> - <title>Sample output</title> - - <programlisting> - regression=# SELECT c.relname, count(*) AS buffers - FROM pg_buffercache b INNER JOIN pg_class c - ON b.relfilenode = pg_relation_filenode(c.oid) AND - b.reldatabase IN (0, (SELECT oid FROM pg_database - WHERE datname = current_database())) - GROUP BY c.relname - ORDER BY 2 DESC - LIMIT 10; - relname | buffers - ---------------------------------+--------- - tenk2 | 345 - tenk1 | 141 - pg_proc | 46 - pg_class | 45 - pg_attribute | 43 - pg_class_relname_nsp_index | 30 - pg_proc_proname_args_nsp_index | 28 - pg_attribute_relid_attnam_index | 26 - pg_depend | 22 - pg_depend_reference_index | 20 - (10 rows) - </programlisting> + <title>Sample Output</title> + +<screen> +regression=# SELECT c.relname, count(*) AS buffers + FROM pg_buffercache b INNER JOIN pg_class c + ON b.relfilenode = pg_relation_filenode(c.oid) AND + b.reldatabase IN (0, (SELECT oid FROM pg_database + WHERE datname = current_database())) + GROUP BY c.relname + ORDER BY 2 DESC + LIMIT 10; + + relname | buffers +---------------------------------+--------- + tenk2 | 345 + tenk1 | 141 + pg_proc | 46 + pg_class | 45 + pg_attribute | 43 + pg_class_relname_nsp_index | 30 + pg_proc_proname_args_nsp_index | 28 + pg_attribute_relid_attnam_index | 26 + pg_depend | 22 + pg_depend_reference_index | 20 +(10 rows) +</screen> </sect2> <sect2> diff --git a/doc/src/sgml/pgcrypto.sgml b/doc/src/sgml/pgcrypto.sgml index 64be7cc73d..6b78f2c1c6 100644 --- a/doc/src/sgml/pgcrypto.sgml +++ b/doc/src/sgml/pgcrypto.sgml @@ -1,27 +1,32 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pgcrypto.sgml,v 1.9 2010/06/29 22:29:14 momjian Exp $ --> +<!-- doc/src/sgml/pgcrypto.sgml --> -<sect1 id="pgcrypto"> +<sect1 id="pgcrypto" xreflabel="pgcrypto"> <title>pgcrypto</title> <indexterm zone="pgcrypto"> <primary>pgcrypto</primary> </indexterm> + <indexterm zone="pgcrypto"> + <primary>encryption</primary> + <secondary>for specific columns</secondary> + </indexterm> + <para> The <filename>pgcrypto</> module provides cryptographic functions for <productname>PostgreSQL</>. </para> <sect2> - <title>General hashing functions</title> + <title>General Hashing Functions</title> <sect3> <title><function>digest()</function></title> - <synopsis> - digest(data text, type text) returns bytea - digest(data bytea, type text) returns bytea - </synopsis> +<synopsis> +digest(data text, type text) returns bytea +digest(data bytea, type text) returns bytea +</synopsis> <para> Computes a binary hash of the given <parameter>data</>. @@ -37,21 +42,21 @@ <para> If you want the digest as a hexadecimal string, use <function>encode()</> on the result. For example: +<programlisting> +CREATE OR REPLACE FUNCTION sha1(bytea) returns text AS $$ + SELECT encode(digest($1, 'sha1'), 'hex') +$$ LANGUAGE SQL STRICT IMMUTABLE; +</programlisting> </para> - <programlisting> - CREATE OR REPLACE FUNCTION sha1(bytea) returns text AS $$ - SELECT encode(digest($1, 'sha1'), 'hex') - $$ LANGUAGE SQL STRICT IMMUTABLE; - </programlisting> </sect3> <sect3> <title><function>hmac()</function></title> - <synopsis> - hmac(data text, key text, type text) returns bytea - hmac(data bytea, key text, type text) returns bytea - </synopsis> +<synopsis> +hmac(data text, key text, type text) returns bytea +hmac(data bytea, key text, type text) returns bytea +</synopsis> <para> Calculates hashed MAC for <parameter>data</> with key <parameter>key</>. @@ -72,7 +77,7 @@ </sect2> <sect2> - <title>Password hashing functions</title> + <title>Password Hashing Functions</title> <para> The functions <function>crypt()</> and <function>gen_salt()</> @@ -115,15 +120,20 @@ </listitem> </orderedlist> - <table> - <title>Supported algorithms for <function>crypt()</></title> + <para> + <xref linkend="pgcrypto-crypt-algorithms"> lists the algorithms + supported by the <function>crypt()</function> function. + </para> + + <table id="pgcrypto-crypt-algorithms"> + <title>Supported Algorithms for <function>crypt()</></title> <tgroup cols="5"> <thead> <row> <entry>Algorithm</entry> - <entry>Max password length</entry> + <entry>Max Password Length</entry> <entry>Adaptive?</entry> - <entry>Salt bits</entry> + <entry>Salt Bits</entry> <entry>Description</entry> </row> </thead> @@ -163,9 +173,9 @@ <sect3> <title><function>crypt()</></title> - <synopsis> - crypt(password text, salt text) returns text - </synopsis> +<synopsis> +crypt(password text, salt text) returns text +</synopsis> <para> Calculates a crypt(3)-style hash of <parameter>password</>. @@ -176,17 +186,15 @@ </para> <para> Example of setting a new password: +<programlisting> +UPDATE ... SET pswhash = crypt('new password', gen_salt('md5')); +</programlisting> </para> - <programlisting> - UPDATE ... SET pswhash = crypt('new password', gen_salt('md5')); - </programlisting> <para> Example of authentication: - </para> - <programlisting> - SELECT pswhash = crypt('entered password', pswhash) FROM ... ; - </programlisting> - <para> +<programlisting> +SELECT pswhash = crypt('entered password', pswhash) FROM ... ; +</programlisting> This returns <literal>true</> if the entered password is correct. </para> </sect3> @@ -194,9 +202,9 @@ <sect3> <title><function>gen_salt()</></title> - <synopsis> - gen_salt(type text [, iter_count integer ]) returns text - </synopsis> +<synopsis> +gen_salt(type text [, iter_count integer ]) returns text +</synopsis> <para> Generates a new random salt string for use in <function>crypt()</>. @@ -222,7 +230,7 @@ </para> <table id="pgcrypto-icfc-table"> - <title>Iteration counts for <function>crypt()</></title> + <title>Iteration Counts for <function>crypt()</></title> <tgroup cols="4"> <thead> <row> @@ -275,7 +283,7 @@ </para> <table id="pgcrypto-hash-speed-table"> - <title>Hash algorithm speeds</title> + <title>Hash Algorithm Speeds</title> <tgroup cols="4"> <thead> <row> @@ -390,7 +398,7 @@ </sect2> <sect2> - <title>PGP encryption functions</title> + <title>PGP Encryption Functions</title> <para> The functions here implement the encryption part of the OpenPGP (RFC 4880) @@ -489,10 +497,10 @@ <sect3> <title><function>pgp_sym_encrypt()</function></title> - <synopsis> - pgp_sym_encrypt(data text, psw text [, options text ]) returns bytea - pgp_sym_encrypt_bytea(data bytea, psw text [, options text ]) returns bytea - </synopsis> +<synopsis> +pgp_sym_encrypt(data text, psw text [, options text ]) returns bytea +pgp_sym_encrypt_bytea(data bytea, psw text [, options text ]) returns bytea +</synopsis> <para> Encrypt <parameter>data</> with a symmetric PGP key <parameter>psw</>. The <parameter>options</> parameter can contain option settings, @@ -503,15 +511,15 @@ <sect3> <title><function>pgp_sym_decrypt()</function></title> - <synopsis> - pgp_sym_decrypt(msg bytea, psw text [, options text ]) returns text - pgp_sym_decrypt_bytea(msg bytea, psw text [, options text ]) returns bytea - </synopsis> +<synopsis> +pgp_sym_decrypt(msg bytea, psw text [, options text ]) returns text +pgp_sym_decrypt_bytea(msg bytea, psw text [, options text ]) returns bytea +</synopsis> <para> Decrypt a symmetric-key-encrypted PGP message. </para> <para> - Decrypting bytea data with <function>pgp_sym_decrypt</> is disallowed. + Decrypting <type>bytea</> data with <function>pgp_sym_decrypt</> is disallowed. This is to avoid outputting invalid character data. Decrypting originally textual data with <function>pgp_sym_decrypt_bytea</> is fine. </para> @@ -524,10 +532,10 @@ <sect3> <title><function>pgp_pub_encrypt()</function></title> - <synopsis> - pgp_pub_encrypt(data text, key bytea [, options text ]) returns bytea - pgp_pub_encrypt_bytea(data bytea, key bytea [, options text ]) returns bytea - </synopsis> +<synopsis> +pgp_pub_encrypt(data text, key bytea [, options text ]) returns bytea +pgp_pub_encrypt_bytea(data bytea, key bytea [, options text ]) returns bytea +</synopsis> <para> Encrypt <parameter>data</> with a public PGP key <parameter>key</>. Giving this function a secret key will produce a error. @@ -541,10 +549,10 @@ <sect3> <title><function>pgp_pub_decrypt()</function></title> - <synopsis> - pgp_pub_decrypt(msg bytea, key bytea [, psw text [, options text ]]) returns text - pgp_pub_decrypt_bytea(msg bytea, key bytea [, psw text [, options text ]]) returns bytea - </synopsis> +<synopsis> +pgp_pub_decrypt(msg bytea, key bytea [, psw text [, options text ]]) returns text +pgp_pub_decrypt_bytea(msg bytea, key bytea [, psw text [, options text ]]) returns bytea +</synopsis> <para> Decrypt a public-key-encrypted message. <parameter>key</> must be the secret key corresponding to the public key that was used to encrypt. @@ -553,7 +561,7 @@ options, you need to give an empty password. </para> <para> - Decrypting bytea data with <function>pgp_pub_decrypt</> is disallowed. + Decrypting <type>bytea</> data with <function>pgp_pub_decrypt</> is disallowed. This is to avoid outputting invalid character data. Decrypting originally textual data with <function>pgp_pub_decrypt_bytea</> is fine. </para> @@ -566,9 +574,9 @@ <sect3> <title><function>pgp_key_id()</function></title> - <synopsis> - pgp_key_id(bytea) returns text - </synopsis> +<synopsis> +pgp_key_id(bytea) returns text +</synopsis> <para> <function>pgp_key_id</> extracts the key ID of a PGP public or secret key. Or it gives the key ID that was used for encrypting the data, if given @@ -608,27 +616,27 @@ <sect3> <title><function>armor()</function>, <function>dearmor()</function></title> - <synopsis> - armor(data bytea) returns text - dearmor(data text) returns bytea - </synopsis> +<synopsis> +armor(data bytea) returns text +dearmor(data text) returns bytea +</synopsis> <para> - These functions wrap/unwrap binary data into PGP Ascii Armor format, + These functions wrap/unwrap binary data into PGP ASCII-armor format, which is basically Base64 with CRC and additional formatting. </para> </sect3> <sect3> - <title>Options for PGP functions</title> + <title>Options for PGP Functions</title> <para> Options are named to be similar to GnuPG. An option's value should be given after an equal sign; separate options from each other with commas. For example: +<programlisting> +pgp_sym_encrypt(data, psw, 'compress-algo=1, cipher-algo=aes256') +</programlisting> </para> - <programlisting> - pgp_sym_encrypt(data, psw, 'compress-algo=1, cipher-algo=aes256') - </programlisting> <para> All of the options except <literal>convert-crlf</literal> apply only to @@ -648,11 +656,11 @@ <para> Which cipher algorithm to use. </para> - <programlisting> - Values: bf, aes128, aes192, aes256 (OpenSSL-only: <literal>3des</literal>, <literal>cast5</literal>) - Default: aes128 - Applies to: pgp_sym_encrypt, pgp_pub_encrypt - </programlisting> +<literallayout> +Values: bf, aes128, aes192, aes256 (OpenSSL-only: <literal>3des</literal>, <literal>cast5</literal>) +Default: aes128 +Applies to: pgp_sym_encrypt, pgp_pub_encrypt +</literallayout> </sect4> <sect4> @@ -662,14 +670,14 @@ Which compression algorithm to use. Only available if <productname>PostgreSQL</productname> was built with zlib. </para> - <programlisting> - Values: - 0 - no compression - 1 - ZIP compression - 2 - ZLIB compression (= ZIP plus meta-data and block CRCs) - Default: 0 - Applies to: pgp_sym_encrypt, pgp_pub_encrypt - </programlisting> +<literallayout> +Values: + 0 - no compression + 1 - ZIP compression + 2 - ZLIB compression (= ZIP plus meta-data and block CRCs) +Default: 0 +Applies to: pgp_sym_encrypt, pgp_pub_encrypt +</literallayout> </sect4> <sect4> @@ -679,11 +687,11 @@ How much to compress. Higher levels compress smaller but are slower. 0 disables compression. </para> - <programlisting> - Values: 0, 1-9 - Default: 6 - Applies to: pgp_sym_encrypt, pgp_pub_encrypt - </programlisting> +<literallayout> +Values: 0, 1-9 +Default: 6 +Applies to: pgp_sym_encrypt, pgp_pub_encrypt +</literallayout> </sect4> <sect4> @@ -696,11 +704,11 @@ <literal>\r\n</literal> line-feeds. Use this to get fully RFC-compliant behavior. </para> - <programlisting> - Values: 0, 1 - Default: 0 - Applies to: pgp_sym_encrypt, pgp_pub_encrypt, pgp_sym_decrypt, pgp_pub_decrypt - </programlisting> +<literallayout> +Values: 0, 1 +Default: 0 +Applies to: pgp_sym_encrypt, pgp_pub_encrypt, pgp_sym_decrypt, pgp_pub_decrypt +</literallayout> </sect4> <sect4> @@ -712,11 +720,11 @@ the addition of SHA-1 protected packets to RFC 4880. Recent gnupg.org and pgp.com software supports it fine. </para> - <programlisting> - Values: 0, 1 - Default: 0 - Applies to: pgp_sym_encrypt, pgp_pub_encrypt - </programlisting> +<literallayout> +Values: 0, 1 +Default: 0 +Applies to: pgp_sym_encrypt, pgp_pub_encrypt +</literallayout> </sect4> <sect4> @@ -727,11 +735,11 @@ session key; this is for symmetric-key encryption, which by default uses the S2K key directly. </para> - <programlisting> - Values: 0, 1 - Default: 0 - Applies to: pgp_sym_encrypt - </programlisting> +<literallayout> +Values: 0, 1 +Default: 0 +Applies to: pgp_sym_encrypt +</literallayout> </sect4> <sect4> @@ -740,14 +748,14 @@ <para> Which S2K algorithm to use. </para> - <programlisting> - Values: - 0 - Without salt. Dangerous! - 1 - With salt but with fixed iteration count. - 3 - Variable iteration count. - Default: 3 - Applies to: pgp_sym_encrypt - </programlisting> +<literallayout> +Values: + 0 - Without salt. Dangerous! + 1 - With salt but with fixed iteration count. + 3 - Variable iteration count. +Default: 3 +Applies to: pgp_sym_encrypt +</literallayout> </sect4> <sect4> @@ -756,11 +764,11 @@ <para> Which digest algorithm to use in S2K calculation. </para> - <programlisting> - Values: md5, sha1 - Default: sha1 - Applies to: pgp_sym_encrypt - </programlisting> +<literallayout> +Values: md5, sha1 +Default: sha1 +Applies to: pgp_sym_encrypt +</literallayout> </sect4> <sect4> @@ -769,11 +777,11 @@ <para> Which cipher to use for encrypting separate session key. </para> - <programlisting> - Values: bf, aes, aes128, aes192, aes256 - Default: use cipher-algo - Applies to: pgp_sym_encrypt - </programlisting> +<literallayout> +Values: bf, aes, aes128, aes192, aes256 +Default: use cipher-algo +Applies to: pgp_sym_encrypt +</literallayout> </sect4> <sect4> @@ -785,23 +793,23 @@ be done, but the message will be tagged as UTF-8. Without this option it will not be. </para> - <programlisting> - Values: 0, 1 - Default: 0 - Applies to: pgp_sym_encrypt, pgp_pub_encrypt - </programlisting> +<literallayout> +Values: 0, 1 +Default: 0 +Applies to: pgp_sym_encrypt, pgp_pub_encrypt +</literallayout> </sect4> </sect3> <sect3> - <title>Generating PGP keys with GnuPG</title> + <title>Generating PGP Keys with GnuPG</title> <para> To generate a new key: +<programlisting> +gpg --gen-key +</programlisting> </para> - <programlisting> - gpg --gen-key - </programlisting> <para> The preferred key type is <quote>DSA and Elgamal</>. </para> @@ -812,22 +820,22 @@ </para> <para> To list keys: +<programlisting> +gpg --list-secret-keys +</programlisting> </para> - <programlisting> - gpg --list-secret-keys - </programlisting> <para> - To export a public key in ascii-armor format: + To export a public key in ASCII-armor format: +<programlisting> +gpg -a --export KEYID > public.key +</programlisting> </para> - <programlisting> - gpg -a --export KEYID > public.key - </programlisting> <para> - To export a secret key in ascii-armor format: + To export a secret key in ASCII-armor format: +<programlisting> +gpg -a --export-secret-keys KEYID > secret.key +</programlisting> </para> - <programlisting> - gpg -a --export-secret-keys KEYID > secret.key - </programlisting> <para> You need to use <function>dearmor()</> on these keys before giving them to the PGP functions. Or if you can handle binary data, you can drop @@ -842,7 +850,7 @@ </sect3> <sect3> - <title>Limitations of PGP code</title> + <title>Limitations of PGP Code</title> <itemizedlist> <listitem> @@ -870,7 +878,7 @@ </sect2> <sect2> - <title>Raw encryption functions</title> + <title>Raw Encryption Functions</title> <para> These functions only run a cipher over data; they don't have any advanced @@ -905,34 +913,29 @@ encryption functions is discouraged. </para> - <synopsis> - encrypt(data bytea, key bytea, type text) returns bytea - decrypt(data bytea, key bytea, type text) returns bytea +<synopsis> +encrypt(data bytea, key bytea, type text) returns bytea +decrypt(data bytea, key bytea, type text) returns bytea - encrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea - decrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea - </synopsis> +encrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea +decrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea +</synopsis> <para> Encrypt/decrypt data using the cipher method specified by <parameter>type</parameter>. The syntax of the <parameter>type</parameter> string is: - </para> - <synopsis> - <replaceable>algorithm</> <optional> <literal>-</> <replaceable>mode</> </optional> <optional> <literal>/pad:</> <replaceable>padding</> </optional> - </synopsis> - - <para> +<synopsis> +<replaceable>algorithm</> <optional> <literal>-</> <replaceable>mode</> </optional> <optional> <literal>/pad:</> <replaceable>padding</> </optional> +</synopsis> where <replaceable>algorithm</> is one of: - </para> + <itemizedlist> <listitem><para><literal>bf</literal> — Blowfish</para></listitem> <listitem><para><literal>aes</literal> — AES (Rijndael-128)</para></listitem> </itemizedlist> - <para> and <replaceable>mode</> is one of: - </para> <itemizedlist> <listitem> <para> @@ -946,9 +949,7 @@ </para> </listitem> </itemizedlist> - <para> and <replaceable>padding</> is one of: - </para> <itemizedlist> <listitem> <para> @@ -961,13 +962,14 @@ </para> </listitem> </itemizedlist> + </para> <para> So, for example, these are equivalent: +<programlisting> +encrypt(data, 'fooz', 'bf') +encrypt(data, 'fooz', 'bf-cbc/pad:pkcs') +</programlisting> </para> - <programlisting> - encrypt(data, 'fooz', 'bf') - encrypt(data, 'fooz', 'bf-cbc/pad:pkcs') - </programlisting> <para> In <function>encrypt_iv</> and <function>decrypt_iv</>, the <parameter>iv</> parameter is the initial value for the CBC mode; @@ -978,11 +980,11 @@ </sect2> <sect2> - <title>Random-data functions</title> + <title>Random-Data Functions</title> - <synopsis> - gen_random_bytes(count integer) returns bytea - </synopsis> +<synopsis> +gen_random_bytes(count integer) returns bytea +</synopsis> <para> Returns <parameter>count</> cryptographically strong random bytes. At most 1024 bytes can be extracted at a time. This is to avoid @@ -1015,7 +1017,7 @@ </para> <table id="pgcrypto-with-without-openssl"> - <title>Summary of functionality with and without OpenSSL</title> + <title>Summary of Functionality with and without OpenSSL</title> <tgroup cols="3"> <thead> <row> @@ -1107,7 +1109,7 @@ </sect3> <sect3> - <title>NULL handling</title> + <title>NULL Handling</title> <para> As is standard in SQL, all functions return NULL, if any of the arguments @@ -1116,7 +1118,7 @@ </sect3> <sect3> - <title>Security limitations</title> + <title>Security Limitations</title> <para> All <filename>pgcrypto</> functions run inside the database server. @@ -1140,7 +1142,7 @@ </sect3> <sect3> - <title>Useful reading</title> + <title>Useful Reading</title> <itemizedlist> <listitem> @@ -1171,7 +1173,7 @@ </sect3> <sect3> - <title>Technical references</title> + <title>Technical References</title> <itemizedlist> <listitem> @@ -1204,7 +1206,7 @@ </listitem> <listitem> <para><ulink url="http://jlcooke.ca/random/"></ulink></para> - <para>Jean-Luc Cooke Fortuna-based /dev/random driver for Linux.</para> + <para>Jean-Luc Cooke Fortuna-based <filename>/dev/random</> driver for Linux.</para> </listitem> <listitem> <para><ulink url="http://research.cyber.ee/~lipmaa/crypto/"></ulink></para> diff --git a/doc/src/sgml/pgfreespacemap.sgml b/doc/src/sgml/pgfreespacemap.sgml index 31d3b836a3..51f772a397 100644 --- a/doc/src/sgml/pgfreespacemap.sgml +++ b/doc/src/sgml/pgfreespacemap.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pgfreespacemap.sgml,v 2.6 2010/04/23 23:21:43 rhaas Exp $ --> +<!-- doc/src/sgml/pgfreespacemap.sgml --> -<sect1 id="pgfreespacemap"> +<sect1 id="pgfreespacemap" xreflabel="pg_freespacemap"> <title>pg_freespacemap</title> <indexterm zone="pgfreespacemap"> @@ -33,7 +33,6 @@ <para> Returns the amount of free space on the page of the relation, specified by <literal>blkno</>, according to the FSM. - (blkno). </para> </listitem> </varlistentry> @@ -56,7 +55,7 @@ <para> The values stored in the free space map are not exact. They're rounded - to precision of 1/256th of BLCKSZ (32 bytes with default BLCKSZ), and + to precision of 1/256th of <symbol>BLCKSZ</> (32 bytes with default <symbol>BLCKSZ</>), and they're not kept fully up-to-date as tuples are inserted and updated. </para> @@ -73,9 +72,9 @@ </sect2> <sect2> - <title>Sample output</title> + <title>Sample Output</title> - <programlisting> +<screen> postgres=# SELECT * FROM pg_freespace('foo'); blkno | avail -------+------- @@ -106,8 +105,7 @@ postgres=# SELECT * FROM pg_freespace('foo', 7); -------------- 1216 (1 row) - - </programlisting> +</screen> </sect2> <sect2> diff --git a/doc/src/sgml/pgrowlocks.sgml b/doc/src/sgml/pgrowlocks.sgml index f2f58dbd3c..db1cf5e863 100644 --- a/doc/src/sgml/pgrowlocks.sgml +++ b/doc/src/sgml/pgrowlocks.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pgrowlocks.sgml,v 1.5 2009/05/18 11:08:24 petere Exp $ --> +<!-- doc/src/sgml/pgrowlocks.sgml --> -<sect1 id="pgrowlocks"> +<sect1 id="pgrowlocks" xreflabel="pgrowlocks"> <title>pgrowlocks</title> <indexterm zone="pgrowlocks"> @@ -26,7 +26,7 @@ pgrowlocks(text) returns setof record </para> <table id="pgrowlocks-columns"> - <title><function>pgrowlocks</> output columns</title> + <title><function>pgrowlocks</> Output Columns</title> <tgroup cols="3"> <thead> @@ -101,10 +101,10 @@ pgrowlocks(text) returns setof record rows. If you want to take a look at the row contents at the same time, you could do something like this: - <programlisting> +<programlisting> SELECT * FROM accounts AS a, pgrowlocks('accounts') AS p WHERE p.locked_row = a.ctid; - </programlisting> +</programlisting> Be aware however that (as of <productname>PostgreSQL</> 8.3) such a query will be very inefficient. @@ -112,9 +112,9 @@ SELECT * FROM accounts AS a, pgrowlocks('accounts') AS p </sect2> <sect2> - <title>Sample output</title> + <title>Sample Output</title> - <programlisting> +<screen> test=# SELECT * FROM pgrowlocks('t1'); locked_row | lock_type | locker | multi | xids | pids ------------+-----------+--------+-------+-----------+--------------- @@ -123,7 +123,7 @@ test=# SELECT * FROM pgrowlocks('t1'); (0,3) | Exclusive | 804 | f | {804} | {29066} (0,4) | Exclusive | 804 | f | {804} | {29066} (4 rows) - </programlisting> +</screen> </sect2> <sect2> diff --git a/doc/src/sgml/pgstandby.sgml b/doc/src/sgml/pgstandby.sgml index 2a4e03185f..e698cb73e6 100644 --- a/doc/src/sgml/pgstandby.sgml +++ b/doc/src/sgml/pgstandby.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pgstandby.sgml,v 2.11 2010/05/25 15:55:28 momjian Exp $ --> +<!-- doc/src/sgml/pgstandby.sgml --> -<sect1 id="pgstandby"> +<sect1 id="pgstandby" xreflabel="pg_standby"> <title>pg_standby</title> <indexterm zone="pgstandby"> @@ -15,7 +15,7 @@ <para> <application>pg_standby</> is designed to be a waiting - <literal>restore_command</literal>, which is needed to turn a standard + <varname>restore_command</>, which is needed to turn a standard archive recovery into a warm standby operation. Other configuration is required as well, all of which is described in the main server manual (see <xref linkend="warm-standby">). @@ -50,22 +50,18 @@ To configure a standby server to use <application>pg_standby</>, put this into its <filename>recovery.conf</filename> configuration file: - </para> - <programlisting> +<programlisting> restore_command = 'pg_standby <replaceable>archiveDir</> %f %p %r' - </programlisting> - <para> +</programlisting> where <replaceable>archiveDir</> is the directory from which WAL segment files should be restored. </para> <para> The full syntax of <application>pg_standby</>'s command line is - </para> - <synopsis> +<synopsis> pg_standby <optional> <replaceable>option</> ... </optional> <replaceable>archivelocation</> <replaceable>nextwalfile</> <replaceable>xlogfilepath</> <optional> <replaceable>restartwalfile</> </optional> - </synopsis> - <para> - When used within <literal>restore_command</literal>, the <literal>%f</> and +</synopsis> + When used within <varname>restore_command</>, the <literal>%f</> and <literal>%p</> macros should be specified for <replaceable>nextwalfile</> and <replaceable>xlogfilepath</> respectively, to provide the actual file and path required for the restore. @@ -206,7 +202,7 @@ pg_standby <optional> <replaceable>option</> ... </optional> <replaceable>archiv <listitem> <para> Specify a trigger file whose presence should cause failover. - It is recommended that you use a structured filename to + It is recommended that you use a structured file name to avoid confusion as to which server is being triggered when multiple servers exist on the same system; for example <filename>/tmp/pgsql.trigger.5432</>. @@ -235,21 +231,19 @@ pg_standby <optional> <replaceable>option</> ... </optional> <replaceable>archiv <sect2> <title>Examples</title> - <para>On Linux or Unix systems, you might use:</para> + <para>On Linux or Unix systems, you might use: - <programlisting> +<programlisting> archive_command = 'cp %p .../archive/%f' restore_command = 'pg_standby -d -s 2 -t /tmp/pgsql.trigger.5442 .../archive %f %p %r 2>>standby.log' recovery_end_command = 'rm -f /tmp/pgsql.trigger.5442' - </programlisting> - <para> +</programlisting> where the archive directory is physically located on the standby server, - so that the <literal>archive_command</> is accessing it across NFS, + so that the <varname>archive_command</> is accessing it across NFS, but the files are local to the standby (enabling use of <literal>ln</>). This will: - </para> <itemizedlist> <listitem> <para> @@ -279,22 +273,21 @@ recovery_end_command = 'rm -f /tmp/pgsql.trigger.5442' </para> </listitem> </itemizedlist> + </para> - <para>On Windows, you might use:</para> + <para>On Windows, you might use: - <programlisting> +<programlisting> archive_command = 'copy %p ...\\archive\\%f' restore_command = 'pg_standby -d -s 5 -t C:\pgsql.trigger.5442 ...\archive %f %p %r 2>>standby.log' recovery_end_command = 'del C:\pgsql.trigger.5442' - </programlisting> - <para> +</programlisting> Note that backslashes need to be doubled in the - <literal>archive_command</>, but <emphasis>not</emphasis> in the - <literal>restore_command</> or <literal>recovery_end_command</>. + <varname>archive_command</>, but <emphasis>not</emphasis> in the + <varname>restore_command</> or <varname>recovery_end_command</>. This will: - </para> <itemizedlist> <listitem> <para> @@ -329,10 +322,11 @@ recovery_end_command = 'del C:\pgsql.trigger.5442' </para> </listitem> </itemizedlist> + </para> <para> The <literal>copy</> command on Windows sets the final file size - before the file is completely copied, which would ordinarly confuse + before the file is completely copied, which would ordinarily confuse <application>pg_standby</application>. Therefore <application>pg_standby</application> waits <literal>sleeptime</> seconds once it sees the proper file size. GNUWin32's <literal>cp</> @@ -348,7 +342,7 @@ recovery_end_command = 'del C:\pgsql.trigger.5442' </sect2> <sect2> - <title>Supported server versions</title> + <title>Supported Server Versions</title> <para> <application>pg_standby</application> is designed to work with @@ -363,7 +357,7 @@ recovery_end_command = 'del C:\pgsql.trigger.5442' </para> <para> <productname>PostgreSQL</> 8.4 provides the - <literal>recovery_end_command</literal> option. Without this option + <varname>recovery_end_command</> option. Without this option a leftover trigger file can be hazardous. </para> </sect2> diff --git a/doc/src/sgml/pgstatstatements.sgml b/doc/src/sgml/pgstatstatements.sgml index 3bd3d60d76..52268c545d 100644 --- a/doc/src/sgml/pgstatstatements.sgml +++ b/doc/src/sgml/pgstatstatements.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pgstatstatements.sgml,v 1.6 2010/01/08 00:38:20 itagaki Exp $ --> +<!-- doc/src/sgml/pgstatstatements.sgml --> -<sect1 id="pgstatstatements"> +<sect1 id="pgstatstatements" xreflabel="pg_stat_statements"> <title>pg_stat_statements</title> <indexterm zone="pgstatstatements"> @@ -20,7 +20,7 @@ </para> <sect2> - <title>The <structname>pg_stat_statements</structname> view</title> + <title>The <structname>pg_stat_statements</structname> View</title> <para> The statistics gathered by the module are made available via a system view @@ -31,7 +31,7 @@ </para> <table id="pgstatstatements-columns"> - <title><structname>pg_stat_statements</> columns</title> + <title><structname>pg_stat_statements</> Columns</title> <tgroup cols="4"> <thead> @@ -148,7 +148,7 @@ <para> This view, and the function <function>pg_stat_statements_reset</>, are available only in databases they have been specifically installed into - by running the <filename>pg_stat_statements.sql</> install script. + by installing the <literal>pg_stat_statements</> extension. However, statistics are tracked across all databases of the server whenever the <filename>pg_stat_statements</filename> module is loaded into the server, regardless of presence of the view. @@ -190,7 +190,7 @@ </sect2> <sect2> - <title>Configuration parameters</title> + <title>Configuration Parameters</title> <variablelist> <varlistentry> @@ -279,22 +279,22 @@ <filename>postgresql.conf</> file, you will need to add <literal>pg_stat_statements</> to <xref linkend="guc-custom-variable-classes">. Typical usage might be: - </para> - <programlisting> +<programlisting> # postgresql.conf shared_preload_libraries = 'pg_stat_statements' custom_variable_classes = 'pg_stat_statements' pg_stat_statements.max = 10000 pg_stat_statements.track = all - </programlisting> +</programlisting> + </para> </sect2> <sect2> - <title>Sample output</title> + <title>Sample Output</title> - <programlisting> +<screen> bench=# SELECT pg_stat_statements_reset(); $ pgbench -i bench @@ -334,7 +334,7 @@ calls | 1 total_time | 0.08142 rows | 0 hit_percent | 34.4947735191637631 - </programlisting> +</screen> </sect2> <sect2> diff --git a/doc/src/sgml/pgstattuple.sgml b/doc/src/sgml/pgstattuple.sgml index c50a777bc5..a55b35cb3f 100644 --- a/doc/src/sgml/pgstattuple.sgml +++ b/doc/src/sgml/pgstattuple.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pgstattuple.sgml,v 1.5 2009/05/18 11:08:24 petere Exp $ --> +<!-- doc/src/sgml/pgstattuple.sgml --> -<sect1 id="pgstattuple"> +<sect1 id="pgstattuple" xreflabel="pgstattuple"> <title>pgstattuple</title> <indexterm zone="pgstattuple"> @@ -45,7 +45,7 @@ free_percent | 1.95 </para> <table id="pgstattuple-columns"> - <title><function>pgstattuple</function> output columns</title> + <title><function>pgstattuple</function> Output Columns</title> <tgroup cols="3"> <thead> <row> @@ -140,9 +140,8 @@ free_percent | 1.95 <listitem> <para> <function>pgstatindex</function> returns a record showing information - about a btree index. For example: - </para> - <programlisting> + about a B-tree index. For example: +<programlisting> test=> SELECT * FROM pgstatindex('pg_cast_oid_index'); -[ RECORD 1 ]------+------ version | 2 @@ -155,14 +154,13 @@ empty_pages | 0 deleted_pages | 0 avg_leaf_density | 50.27 leaf_fragmentation | 0 - </programlisting> +</programlisting> + </para> <para> The output columns are: - </para> - <table> - <title><function>pgstatindex</function> output columns</title> + <informaltable> <tgroup cols="3"> <thead> <row> @@ -176,7 +174,7 @@ leaf_fragmentation | 0 <row> <entry><structfield>version</structfield></entry> <entry><type>integer</type></entry> - <entry>Btree version number</entry> + <entry>B-tree version number</entry> </row> <row> @@ -235,7 +233,8 @@ leaf_fragmentation | 0 </tbody> </tgroup> - </table> + </informaltable> + </para> <para> As with <function>pgstattuple</>, the results are accumulated diff --git a/doc/src/sgml/pgtestfsync.sgml b/doc/src/sgml/pgtestfsync.sgml new file mode 100644 index 0000000000..2889059c82 --- /dev/null +++ b/doc/src/sgml/pgtestfsync.sgml @@ -0,0 +1,74 @@ +<!-- doc/src/sgml/pgtestfsync.sgml --> + +<sect1 id="pgtestfsync" xreflabel="pg_test_fsync"> + <title>pg_test_fsync</title> + + <indexterm zone="pgtestfsync"> + <primary>pg_test_fsync</primary> + </indexterm> + + <para> + <application>pg_test_fsync</> is intended to give you a reasonable + idea of what the fastest <xref linkend="guc-wal-sync-method"> is on your + specific system, + as well as supplying diagnostic information in the event of an + identified I/O problem. However, differences shown by pg_test_fsync + might not make any difference in real database throughput, especially + since many database servers are not speed-limited by their transaction + logs. + </para> + + <sect2> + <title>Usage</title> + +<synopsis> +pg_test_fsync [options] +</synopsis> + + <para> + <application>pg_test_fsync</application> accepts the following + command-line options: + + <variablelist> + + <varlistentry> + <term><option>-f</option></term> + <term><option>--filename</option></term> + <listitem> + <para> + Specifies the file name to write test data in. + This file should be in the same file system that the + <filename>pg_xlog</> directory is or will be placed in. + (<filename>pg_xlog</> contains the <acronym>WAL</> files.) + The default is <filename>pg_test_fsync.out</> in the current + directory. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-o</option></term> + <term><option>--ops-per-test</option></term> + <listitem> + <para> + Specifies the number of operations per test. The more operations + per test, the greater the test's accuracy, but the longer it takes + to run. The default is 2000. + </para> + </listitem> + </varlistentry> + + </variablelist> + </para> + + </sect2> + + <sect2> + <title>Author</title> + + <para> + Bruce Momjian <email>bruce@momjian.us</email> + </para> + </sect2> + +</sect1> diff --git a/doc/src/sgml/pgtrgm.sgml b/doc/src/sgml/pgtrgm.sgml index 5b630f203d..18f0f3eba0 100644 --- a/doc/src/sgml/pgtrgm.sgml +++ b/doc/src/sgml/pgtrgm.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pgtrgm.sgml,v 2.2 2007/12/10 05:32:51 tgl Exp $ --> +<!-- doc/src/sgml/pgtrgm.sgml --> -<sect1 id="pgtrgm"> +<sect1 id="pgtrgm" xreflabel="pg_trgm"> <title>pg_trgm</title> <indexterm zone="pgtrgm"> @@ -43,8 +43,14 @@ <sect2> <title>Functions and Operators</title> + <para> + The functions provided by the <filename>pg_trgm</filename> module + are shown in <xref linkend="pgtrgm-func-table">, the operators + in <xref linkend="pgtrgm-op-table">. + </para> + <table id="pgtrgm-func-table"> - <title><filename>pg_trgm</filename> functions</title> + <title><filename>pg_trgm</filename> Functions</title> <tgroup cols="3"> <thead> <row> @@ -97,7 +103,7 @@ </table> <table id="pgtrgm-op-table"> - <title><filename>pg_trgm</filename> operators</title> + <title><filename>pg_trgm</filename> Operators</title> <tgroup cols="3"> <thead> <row> @@ -117,6 +123,14 @@ <function>set_limit</>. </entry> </row> + <row> + <entry><type>text</> <literal><-></literal> <type>text</></entry> + <entry><type>real</type></entry> + <entry> + Returns the <quote>distance</> between the arguments, that is + one minus the <function>similarity()</> value. + </entry> + </row> </tbody> </tgroup> </table> @@ -129,34 +143,34 @@ The <filename>pg_trgm</filename> module provides GiST and GIN index operator classes that allow you to create an index over a text column for the purpose of very fast similarity searches. These index types support - the <literal>%</> similarity operator (and no other operators, so you may - want a regular btree index too). + the above-described similarity operators, and additionally support + trigram-based index searches for <literal>LIKE</> and <literal>ILIKE</> + queries. (These indexes do not support equality nor simple comparison + operators, so you may need a regular B-tree index too.) </para> <para> Example: - <programlisting> +<programlisting> CREATE TABLE test_trgm (t text); CREATE INDEX trgm_idx ON test_trgm USING gist (t gist_trgm_ops); - </programlisting> +</programlisting> or - <programlisting> +<programlisting> CREATE INDEX trgm_idx ON test_trgm USING gin (t gin_trgm_ops); - </programlisting> +</programlisting> </para> <para> At this point, you will have an index on the <structfield>t</> column that you can use for similarity searching. A typical query is - </para> - <programlisting> +<programlisting> SELECT t, similarity(t, '<replaceable>word</>') AS sml FROM test_trgm WHERE t % '<replaceable>word</>' ORDER BY sml DESC, t; - </programlisting> - <para> +</programlisting> This will return all values in the text column that are sufficiently similar to <replaceable>word</>, sorted from best match to worst. The index will be used to make this a fast operation even over very large data @@ -164,6 +178,30 @@ SELECT t, similarity(t, '<replaceable>word</>') AS sml </para> <para> + A variant of the above query is +<programlisting> +SELECT t, t <-> '<replaceable>word</>' AS dist + FROM test_trgm + ORDER BY dist LIMIT 10; +</programlisting> + This can be implemented quite efficiently by GiST indexes, but not + by GIN indexes. It will usually beat the first formulation when only + a small number of the closest matches is wanted. + </para> + + <para> + Beginning in <productname>PostgreSQL</> 9.1, these index types also support + index searches for <literal>LIKE</> and <literal>ILIKE</>, for example +<programlisting> +SELECT * FROM test_trgm WHERE t LIKE '%foo%bar'; +</programlisting> + The index search works by extracting trigrams from the search string + and then looking these up in the index. The more trigrams in the search + string, the more effective the index search is. Unlike B-tree based + searches, the search string need not be left-anchored. + </para> + + <para> The choice between GiST and GIN indexing depends on the relative performance characteristics of GiST and GIN, which are discussed elsewhere. As a rule of thumb, a GIN index is faster to search than a GiST index, but @@ -185,14 +223,12 @@ SELECT t, similarity(t, '<replaceable>word</>') AS sml <para> The first step is to generate an auxiliary table containing all the unique words in the documents: - </para> - <programlisting> +<programlisting> CREATE TABLE words AS SELECT word FROM ts_stat('SELECT to_tsvector(''simple'', bodytext) FROM documents'); - </programlisting> +</programlisting> - <para> where <structname>documents</> is a table that has a text field <structfield>bodytext</> that we wish to search. The reason for using the <literal>simple</> configuration with the <function>to_tsvector</> @@ -202,13 +238,11 @@ CREATE TABLE words AS SELECT word FROM <para> Next, create a trigram index on the word column: - </para> - <programlisting> +<programlisting> CREATE INDEX words_idx ON words USING gin(word gin_trgm_ops); - </programlisting> +</programlisting> - <para> Now, a <command>SELECT</command> query similar to the previous example can be used to suggest spellings for misspelled words in user search terms. A useful extra test is to require that the selected words are also of diff --git a/doc/src/sgml/pgupgrade.sgml b/doc/src/sgml/pgupgrade.sgml index 69ff9dba1b..8bd5f74178 100644 --- a/doc/src/sgml/pgupgrade.sgml +++ b/doc/src/sgml/pgupgrade.sgml @@ -1,6 +1,6 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pgupgrade.sgml,v 1.12 2010/05/25 15:55:28 momjian Exp $ --> +<!-- doc/src/sgml/pgupgrade.sgml --> -<sect1 id="pgupgrade"> +<sect1 id="pgupgrade" xreflabel="pg_upgrade"> <title>pg_upgrade</title> <indexterm zone="pgupgrade"> @@ -8,21 +8,32 @@ </indexterm> <para> - <application>pg_upgrade</> (formerly called pg_migrator) allows data - stored in <productname>PostgreSQL</> data files to be migrated to a later <productname>PostgreSQL</> + <application>pg_upgrade</> (formerly called <application>pg_migrator</>) allows data + stored in <productname>PostgreSQL</> data files to be upgraded to a later <productname>PostgreSQL</> major version without the data dump/reload typically required for major version upgrades, e.g. from 8.4.7 to the current major release - of <productname>PostgreSQL</>. It is not required for minor version upgrades, e.g - 9.0.1 -> 9.0.4. + of <productname>PostgreSQL</>. It is not required for minor version upgrades, e.g. from + 9.0.1 to 9.0.4. </para> <para> - <application>pg_upgrade</> works because, though new features are - regularly added to Postgres major releases, the internal data storage - format rarely changes. <application>pg_upgrade</> does its best to + Major PostgreSQL releases regularly add new features that often + change the layout of the system tables, but the internal data storage + format rarely changes. <application>pg_upgrade</> uses this fact + to perform rapid upgrades by creating new system tables and simply + reusing the old user data files. If a future major release ever + changes the data storage format in a way that makes the old data + format unreadable, <application>pg_upgrade</> will not be usable + for such upgrades. (The community will attempt to avoid such + situations.) + </para> + + <para> + <application>pg_upgrade</> does its best to make sure the old and new clusters are binary-compatible, e.g. by - checking for compatible compile-time settings. It is important that - any external modules are also binary compatibile, though this cannot + checking for compatible compile-time settings, including 32/64-bit + binaries. It is important that + any external modules are also binary compatible, though this cannot be checked by <application>pg_upgrade</>. </para> @@ -47,14 +58,16 @@ <varlistentry> <term><option>-b</option> <replaceable>old_bindir</></term> - <term><option>--old-bindir</option> <replaceable>OLDBINDIR</></term> - <listitem><para>specify the old cluster executable directory</para></listitem> + <term><option>--old-bindir=</option><replaceable>old_bindir</></term> + <listitem><para>the old cluster executable directory; + environment variable <envar>OLDBINDIR</></para></listitem> </varlistentry> <varlistentry> <term><option>-B</option> <replaceable>new_bindir</></term> - <term><option>--new-bindir</option> <replaceable>NEWBINDIR</></term> - <listitem><para>specify the new cluster executable directory</para></listitem> + <term><option>--new-bindir=</option><replaceable>new_bindir</></term> + <listitem><para>the new cluster executable directory; + environment variable <envar>NEWBINDIR</></para></listitem> </varlistentry> <varlistentry> @@ -65,14 +78,16 @@ <varlistentry> <term><option>-d</option> <replaceable>old_datadir</></term> - <term><option>--old-datadir</option> <replaceable>OLDDATADIR</></term> - <listitem><para>specify the old cluster data directory</para></listitem> + <term><option>--old-datadir=</option><replaceable>old_datadir</></term> + <listitem><para>the old cluster data directory; environment + variable <envar>OLDDATADIR</></para></listitem> </varlistentry> <varlistentry> <term><option>-D</option> <replaceable>new_datadir</></term> - <term><option>--new-datadir</option> <replaceable>NEWDATADIR</></term> - <listitem><para>specify the new cluster data directory</para></listitem> + <term><option>--new-datadir=</option><replaceable>new_datadir</></term> + <listitem><para>the new cluster data directory; environment + variable <envar>NEWDATADIR</></para></listitem> </varlistentry> <varlistentry> @@ -83,7 +98,7 @@ <varlistentry> <term><option>-G</option> <replaceable>debug_filename</></term> - <term><option>--debugfile</option> <replaceable>DEBUGFILENAME</></term> + <term><option>--debugfile=</option><replaceable>debug_filename</></term> <listitem><para>output debugging activity to file</para></listitem> </varlistentry> @@ -95,26 +110,29 @@ <varlistentry> <term><option>-l</option> <replaceable>log_filename</></term> - <term><option>--logfile</option> <replaceable>LOGFILENAME</></term> + <term><option>--logfile=</option><replaceable>log_filename</></term> <listitem><para>log session activity to file</para></listitem> </varlistentry> <varlistentry> - <term><option>-p</option> <replaceable>old_portnum</></term> - <term><option>--old-port</option> <replaceable>portnum</></term> - <listitem><para>specify the old cluster port number</para></listitem> + <term><option>-p</option> <replaceable>old_port_number</></term> + <term><option>--old-port=</option><replaceable>old_portnum</></term> + <listitem><para>the old cluster port number; environment + variable <envar>PGPORT</></para></listitem> </varlistentry> <varlistentry> - <term><option>-P</option> <replaceable>new_portnum</></term> - <term><option>--new-port</option> <replaceable>portnum</></term> - <listitem><para>specify the new cluster port number</para></listitem> + <term><option>-P</option> <replaceable>new_port_number</></term> + <term><option>--new-port=</option><replaceable>new_portnum</></term> + <listitem><para>the new cluster port number; environment + variable <envar>PGPORT</></para></listitem> </varlistentry> <varlistentry> - <term><option>-u</option> <replaceable>username</></term> - <term><option>--user</option> <replaceable>username</></term> - <listitem><para>clusters superuser</para></listitem> + <term><option>-u</option> <replaceable>user_name</></term> + <term><option>--user=</option><replaceable>user_name</></term> + <listitem><para>cluster's super user name; environment + variable <envar>PGUSER</></para></listitem> </varlistentry> <varlistentry> @@ -144,172 +162,155 @@ <sect2> <title>Upgrade Steps</title> - <orderedlist> - <listitem> - <para> - Optionally move the old cluster - </para> - + <procedure> + <step performance="optional"> + <title>Optionally move the old cluster</title> + <para> If you are using a version-specific installation directory, e.g. - /opt/PostgreSQL/8.4, you do not need to move the old cluster. The - one-click installers all use version-specific install directories. + <filename>/opt/PostgreSQL/8.4</>, you do not need to move the old cluster. The + one-click installers all use version-specific installation directories. </para> - - <para> + + <para> If your installation directory is not version-specific, e.g. - /usr/local/pgsql, it is necessary to move the current PostgreSQL install + <filename>/usr/local/pgsql</>, it is necessary to move the current PostgreSQL install directory so it does not interfere with the new <productname>PostgreSQL</> installation. Once the current <productname>PostgreSQL</> server is shut down, it is safe to rename the - PostgreSQL install directory; assuming the old directory is - /usr/local/pgsql, you can do: - + PostgreSQL installation directory; assuming the old directory is + <filename>/usr/local/pgsql</>, you can do: + <programlisting> mv /usr/local/pgsql /usr/local/pgsql.old </programlisting> to rename the directory. </para> - - </listitem> - - <listitem> - <para> - For source installs, build the new version - </para> - + </step> + + <step> + <title>For source installs, build the new version</title> + <para> - Build the new PostgreSQL source with configure flags that are compatible + Build the new PostgreSQL source with <command>configure</> flags that are compatible with the old cluster. <application>pg_upgrade</> will check <command>pg_controldata</> to make sure all settings are compatible before starting the upgrade. </para> - </listitem> - - <listitem> - <para> - Install the new PostgreSQL binaries - </para> - + </step> + + <step> + <title>Install the new PostgreSQL binaries</title> + <para> Install the new server's binaries and support files. You can use the same port numbers for both clusters, typically 5432, because the old and new clusters will not be running at the same time. </para> - + <para> For source installs, if you wish to install the new server in a custom - location, use 'prefix': - + location, use the <literal>prefix</literal> variable: + <programlisting> gmake prefix=/usr/local/pgsql.new install </programlisting> </para> - </listitem> - - <listitem> - <para> - Install <application>pg_upgrade</> and - <application>pg_upgrade_support</> in the new PostgreSQL cluster - </para> - </listitem> - - <listitem> + </step> + + <step> + <title>Install pg_upgrade and pg_upgrade_support</title> + <para> - Initialize the new PostgreSQL cluster + Install the <application>pg_upgrade</> binary and + <application>pg_upgrade_support</> library in the new PostgreSQL cluster. </para> - + </step> + + <step> + <title>Initialize the new PostgreSQL cluster</title> + <para> - Initialize the new cluster <xref - linkend="app-initdb">,<indexterm><primary>initdb</></>. - Again, use compatible initdb + Initialize the new cluster using <command>initdb</command>. + Again, use compatible <command>initdb</command> flags that match the old cluster. Many prebuilt installers do this step automatically. There is no need to start the new cluster. </para> - - </listitem> - - <listitem> - <para> - Install custom shared object files (or DLLs) - </para> - + </step> + + <step> + <title>Install custom shared object files</title> + <para> Install any custom shared object files (or DLLs) used by the old cluster - into the new cluster, e.g. pgcrypto.so, whether they are from /contrib + into the new cluster, e.g. <filename>pgcrypto.so</filename>, whether they are from <filename>contrib</filename> or some other source. Do not install the schema definitions, e.g. - pgcrypto.sql --- these will be migrated from the old cluster. - </para> - </listitem> - - <listitem> - <para> - Adjust authentication + <filename>pgcrypto.sql</>, because these will be upgraded from the old cluster. </para> - + </step> + + <step> + <title>Adjust authentication</title> + <para> - pg_upgrade will connect to the old and new servers several times, + <command>pg_upgrade</> will connect to the old and new servers several times, so you might want to set authentication to <literal>trust</> in <filename>pg_hba.conf</>, or if using <literal>md5</> authentication, use a <filename>~/.pgpass</> file (see <xref linkend="libpq-pgpass">) to avoid being prompted repeatedly for a password. </para> - </listitem> - - <listitem> - <para> - Stop both servers - </para> - + </step> + + <step> + <title>Stop both servers</title> + <para> - Make sure both database servers are stopped using on Unix, e.g.: - + Make sure both database servers are stopped using, on Unix, e.g.: + <programlisting> -pg_ctl --pgdata /opt/PostgreSQL/8.4 stop -pg_ctl --pgdata /opt/PostgreSQL/9.0 stop +pg_ctl -D /opt/PostgreSQL/8.4 stop +pg_ctl -D /opt/PostgreSQL/9.0 stop </programlisting> - - or on Windows - + + or on Windows, using the proper service names: + <programlisting> NET STOP postgresql-8.4 NET STOP postgresql-9.0 </programlisting> - + or - + <programlisting> NET STOP pgsql-8.3 (<productname>PostgreSQL</> 8.3 and older used a different service name) </programlisting> </para> - </listitem> - - <listitem> - <para> - Run <application>pg_upgrade</> - </para> - + </step> + + <step> + <title>Run <application>pg_upgrade</></title> + <para> - Always run the <application>pg_upgrade</> binary in the new server, not the old one. + Always run the <application>pg_upgrade</> binary of the new server, not the old one. <application>pg_upgrade</> requires the specification of the old and new cluster's - <varname>PGDATA</> and executable (/bin) directories. You can also specify separate + data and executable (<filename>bin</>) directories. You can also specify separate user and port values, and whether you want the data linked instead of - copied (the default). If you use linking, the migration will be much + copied (the default). If you use linking, the upgrade will be much faster (no data copying), but you will no longer be able to access your old cluster once you start the new cluster after the upgrade. See - pg_upgrade --help for a full list of options. + <literal>pg_upgrade --help</> for a full list of options. </para> - + <para> For Windows users, you must be logged into an administrative account, and - then start a shell as the 'postgres' user and set the proper path: - + then start a shell as the <literal>postgres</> user and set the proper path: + <programlisting> RUNAS /USER:postgres "CMD.EXE" SET PATH=%PATH%;C:\Program Files\PostgreSQL\9.0\bin; </programlisting> - + and then run <application>pg_upgrade</> with quoted directories, e.g.: - + <programlisting> pg_upgrade.exe --old-datadir "C:/Program Files/PostgreSQL/8.4/data" @@ -317,61 +318,58 @@ pg_upgrade.exe --old-bindir "C:/Program Files/PostgreSQL/8.4/bin" --new-bindir "C:/Program Files/PostgreSQL/9.0/bin" </programlisting> - - Once started, pg_upgrade will verify the two clusters are compatible - and then do the migration. You can use pg_upgrade <option>--check</> + + Once started, <command>pg_upgrade</> will verify the two clusters are compatible + and then do the upgrade. You can use <command>pg_upgrade --check</> to perform only the checks, even if the old server is still - running. pg_upgrade <option>--check</> will also outline any - manual adjustments you will need to make after the migration. + running. <command>pg_upgrade --check</> will also outline any + manual adjustments you will need to make after the upgrade. + <command>pg_upgrade</> requires write permission in the current directory. </para> - + <para> - Obviously, no one should be accessing the clusters during the migration. + Obviously, no one should be accessing the clusters during the upgrade. </para> - + <para> - If an error occurs while restoring the database schema, pg_upgrade will - exit and you will have to revert to the old cluster as outlined in step - #15 below. To try pg_upgrade again, you will need to modify the old + If an error occurs while restoring the database schema, <command>pg_upgrade</> will + exit and you will have to revert to the old cluster as outlined in <xref linkend="pgupgrade-step-revert"> + below. To try <command>pg_upgrade</command> again, you will need to modify the old cluster so the pg_upgrade schema restore succeeds. If the problem is a - /contrib module, you might need to uninstall the /contrib module from - the old cluster and install it in the new cluster after the migration, + contrib module, you might need to uninstall the contrib module from + the old cluster and install it in the new cluster after the upgrade, assuming the module is not being used to store user data. </para> - </listitem> - - <listitem> - <para> - Restore <filename>pg_hba.conf</> - </para> - + </step> + + <step> + <title>Restore <filename>pg_hba.conf</></title> + <para> If you modified <filename>pg_hba.conf</> to use <literal>trust</>, restore its original authentication settings. </para> - </listitem> - - <listitem> - <para> - Post-Migration processing - </para> - + </step> + + <step> + <title>Post-Upgrade processing</title> + <para> - If any post-migration processing is required, pg_upgrade will issue + If any post-upgrade processing is required, pg_upgrade will issue warnings as it completes. It will also generate script files that must be run by the administrator. The script files will connect to each - database that needs post-migration processing. Each script should be + database that needs post-upgrade processing. Each script should be run using: - + <programlisting> psql --username postgres --file script.sql postgres </programlisting> - + The scripts can be run in any order and can be deleted once they have been run. </para> - <caution> + <caution> <para> In general it is unsafe to access tables referenced in rebuild scripts until the rebuild scripts have run to completion; doing so could yield @@ -379,81 +377,86 @@ psql --username postgres --file script.sql postgres scripts can be accessed immediately. </para> </caution> - </listitem> - - <listitem> - <para> - Statistics - </para> - <caution> + </step> + + <step> + <title>Statistics</title> + <para> - Because optimizer statistics are not transferred by pg_upgrade, you will + Because optimizer statistics are not transferred by <command>pg_upgrade</>, you will be instructed to run a command to regenerate that information at the end - of the migration. + of the upgrade. </para> - </caution> - </listitem> - - <listitem> - <para> - Delete old cluster - </para> - + </step> + + <step> + <title>Delete old cluster</title> + <para> Once you are satisfied with the upgrade, you can delete the old cluster's data directories by running the script mentioned when - pg_upgrade completes. You will need to manually delete the old install - directories, e.g. /bin, /share. - </para> - </listitem> - - <listitem> - <para> - Reverting to old cluster - </para> - - <para> - If, after running pg_upgrade, you wish to revert to the old cluster, - there are several options. - </para> - - <para> - If you ran pg_upgrade with <option>--check</>, no modifications - were made to the old cluster and you can re-use it anytime. - </para> - - <para> - If you ran pg_upgrade with <option>--link</>, the data files - are shared between the old and new cluster. If you started - the new cluster, the new server has written to those shared - files and it is unsafe to use the old cluster. - </para> - - <para> - If you ran pg_upgrade <emphasis>without</>_ <option>--link</> - or did not start the new server, the old cluster was not - modified except that an <literal>.old</> suffix was appended - to <filename>$PGDATA/global/pg_control</> and perhaps tablespace - directories. To reuse the old cluster, remove the ".old" - suffix from <filename>$PGDATA/global/pg_control</>. and, if - migrating to 8.4 or earlier, remove the tablespace directories - created by the migration and remove the ".old" suffix from - the tablespace directory names; then you can restart the old - cluster. - </para> - - </listitem> - </orderedlist> - - </sect2> - - <sect2> - <title>Limitations in migrating <emphasis>from</> PostgreSQL 8.3</title> - + <command>pg_upgrade</command> completes. You can also delete the + old installation directories + (e.g. <filename>bin</>, <filename>share</>). + </para> + </step> + + <step id="pgupgrade-step-revert" performance="optional"> + <title>Reverting to old cluster</title> + + <para> + If, after running <command>pg_upgrade</command>, you wish to revert to the old cluster, + there are several options: + + <itemizedlist> + <listitem> + <para> + If you ran <command>pg_upgrade</command> + with <option>--check</>, no modifications were made to the old + cluster and you can re-use it anytime. + </para> + </listitem> + + <listitem> + <para> + If you ran <command>pg_upgrade</command> + with <option>--link</>, the data files are shared between the + old and new cluster. If you started the new cluster, the new + server has written to those shared files and it is unsafe to + use the old cluster. + </para> + </listitem> + + <listitem> + <para> + If you + ran <command>pg_upgrade</command> <emphasis>without</> <option>--link</> + or did not start the new server, the old cluster was not + modified except that an <literal>.old</> suffix was appended + to <filename>$PGDATA/global/pg_control</> and perhaps + tablespace directories. To reuse the old cluster, remove + the <filename>.old</> suffix + from <filename>$PGDATA/global/pg_control</>. and, if upgrading + to 8.4 or earlier, remove the tablespace directories created + by the upgrade and remove the <filename>.old</> suffix from + the tablespace directory names; then you can restart the old + cluster. + </para> + </listitem> + </itemizedlist> + </para> + </step> + </procedure> + + </sect2> + + <sect2> + <title>Limitations in Upgrading <emphasis>from</> PostgreSQL 8.3</title> + <para> Upgrading from PostgreSQL 8.3 has additional restrictions not present when upgrading from later PostgreSQL releases. For example, - pg_upgrade will not work for a migration from 8.3 if a user column + pg_upgrade will not work for upgrading from 8.3 if a user column is defined as: <itemizedlist> <listitem> @@ -470,26 +473,26 @@ psql --username postgres --file script.sql postgres </para> <para> - You must drop any such columns and migrate them manually. + You must drop any such columns and upgrade them manually. </para> - + <para> pg_upgrade will require a table rebuild if: <itemizedlist> <listitem> <para> - a user column is of data type tsvector + a user column is of data type <type>tsvector</type> </para> </listitem> </itemizedlist> </para> - + <para> pg_upgrade will require a reindex if: <itemizedlist> <listitem> <para> - an index is of type hash or gin + an index is of type hash or GIN </para> </listitem> <listitem> @@ -499,14 +502,14 @@ psql --username postgres --file script.sql postgres </listitem> </itemizedlist> </para> - + <para> Also, the default datetime storage format changed to integer after <productname>PostgreSQL</> 8.3. pg_upgrade will check that the datetime storage format used by the old and new clusters match. Make sure your new cluster is built with the configure flag <option>--disable-integer-datetimes</>. </para> - + <para> For Windows users, note that due to different integer datetimes settings used by the one-click installer and the MSI installer, it is only @@ -514,29 +517,42 @@ psql --username postgres --file script.sql postgres version 8.4 or later of the one-click distribution. It is not possible to upgrade from the MSI installer to the one-click installer. </para> - - <para> - All failure, rebuild, and reindex cases will be reported by <application>pg_upgrade</> - if they affect your installation; post-migration scripts to rebuild - tables and indexes will be automatically generated. + + </sect2> + + <sect2> + <title>Notes</title> + + <para> + <application>pg_upgrade</> does not support upgrading of databases + containing these <type>reg*</> OID-referencing system data types: + <type>regproc</>, <type>regprocedure</>, <type>regoper</>, + <type>regoperator</>, <type>regclass</>, <type>regconfig</>, and + <type>regdictionary</>. (<type>regtype</> can be upgraded.) + </para> + + <para> + All failure, rebuild, and reindex cases will be reported by + <application>pg_upgrade</> if they affect your installation; + post-upgrade scripts to rebuild tables and indexes will be + generated automatically. </para> - + <para> For deployment testing, create a schema-only copy of the old cluster, - insert dummy data, and migrate that. + insert dummy data, and upgrade that. </para> - - <para> + + <para> If you want to use link mode and you don't want your old cluster to be modified when the new cluster is started, make a copy of the - old cluster and migrate that with link mode. To make a valid copy - of the old cluster, use <application>rsync</> to create a dirty + old cluster and upgrade that with link mode. To make a valid copy + of the old cluster, use <command>rsync</> to create a dirty copy of the old cluster while the server is running, then shut down - the old server and run rsync again to update the copy with any + the old server and run <command>rsync</> again to update the copy with any changes to make it consistent. </para> - + </sect2> - + </sect1> - diff --git a/doc/src/sgml/planstats.sgml b/doc/src/sgml/planstats.sgml index 1d6e52afd9..e7171ffb9b 100644 --- a/doc/src/sgml/planstats.sgml +++ b/doc/src/sgml/planstats.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/planstats.sgml,v 1.9 2007/12/28 21:03:31 tgl Exp $ --> +<!-- doc/src/sgml/planstats.sgml --> <chapter id="planner-stats-details"> <title>How the Planner Uses Statistics</title> @@ -353,7 +353,7 @@ WHERE t1.unique1 < 50 AND t1.unique2 = t2.unique2; -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..4.63 rows=50 width=0) Index Cond: (unique1 < 50) -> Index Scan using tenk2_unique2 on tenk2 t2 (cost=0.00..6.27 rows=1 width=244) - Index Cond: (t2.unique2 = t1.unique2) + Index Cond: (unique2 = t1.unique2) </programlisting> The restriction on <structname>tenk1</structname>, @@ -428,7 +428,7 @@ rows = (outer_cardinality * inner_cardinality) * selectivity the unmodified size of <structname>tenk2</>. It might appear from inspection of the <command>EXPLAIN</> output that the estimate of join rows comes from 50 * 1, that is, the number of outer rows times - the estimated number of rows obtained by each inner indexscan on + the estimated number of rows obtained by each inner index scan on <structname>tenk2</>. But this is not the case: the join relation size is estimated before any particular join plan has been considered. If everything is working well then the two ways of estimating the join diff --git a/doc/src/sgml/plhandler.sgml b/doc/src/sgml/plhandler.sgml index 8be93ac1ac..20021bce65 100644 --- a/doc/src/sgml/plhandler.sgml +++ b/doc/src/sgml/plhandler.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/plhandler.sgml,v 1.11 2010/06/08 20:12:59 rhaas Exp $ --> +<!-- doc/src/sgml/plhandler.sgml --> <chapter id="plhandler"> <title>Writing A Procedural Language Handler</title> @@ -217,6 +217,15 @@ CREATE LANGUAGE plsample </para> <para> + It's recommended that you wrap all these function declarations, + as well as the <command>CREATE LANGUAGE</> command itself, into + an <firstterm>extension</> so that a simple <command>CREATE EXTENSION</> + command is sufficient to install the language. See + <xref linkend="extend-extensions"> for information about writing + extensions. + </para> + + <para> The procedural languages included in the standard distribution are good references when trying to write your own language handler. Look into the <filename>src/pl</> subdirectory of the source tree. diff --git a/doc/src/sgml/plperl.sgml b/doc/src/sgml/plperl.sgml index 2d5a6d94a0..b957757da6 100644 --- a/doc/src/sgml/plperl.sgml +++ b/doc/src/sgml/plperl.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.86 2010/07/08 21:35:33 petere Exp $ --> +<!-- doc/src/sgml/plperl.sgml --> <chapter id="plperl"> <title>PL/Perl - Perl Procedural Language</title> @@ -27,6 +27,7 @@ <para> To install PL/Perl in a particular database, use + <literal>CREATE EXTENSION plperl</>, or from the shell command line use <literal>createlang plperl <replaceable>dbname</></literal>. </para> @@ -41,7 +42,7 @@ <para> Users of source packages must specially enable the build of PL/Perl during the installation process. (Refer to <xref - linkend="install-short"> for more information.) Users of + linkend="installation"> for more information.) Users of binary packages might find PL/Perl in a separate subpackage. </para> </note> @@ -101,7 +102,7 @@ $$ LANGUAGE plperl; most convenient to use dollar quoting (see <xref linkend="sql-syntax-dollar-quoting">) for the string constant. If you choose to use escape string syntax <literal>E''</>, - you must double the single quote marks (<literal>'</>) and backslashes + you must double any single quote marks (<literal>'</>) and backslashes (<literal>\</>) used in the body of the function (see <xref linkend="sql-syntax-strings">). </para> @@ -125,6 +126,14 @@ $$ LANGUAGE plperl; </programlisting> </para> + <note> + <para> + Arguments will be converted from the database's encoding to UTF-8 + for use inside PL/Perl, and then converted from UTF-8 back to the + database encoding upon return. + </para> + </note> + <para> If an SQL null value<indexterm><primary>null value</><secondary sortas="PL/Perl">in PL/Perl</></indexterm> is passed to a function, @@ -191,6 +200,42 @@ select returns_array(); </para> <para> + Perl passes <productname>PostgreSQL</productname> arrays as a blessed + PostgreSQL::InServer::ARRAY object. This object may be treated as an array + reference or a string, allowing for backward compatibility with Perl + code written for <productname>PostgreSQL</productname> versions below 9.1 to + run. For example: + +<programlisting> +CREATE OR REPLACE FUNCTION concat_array_elements(text[]) RETURNS TEXT AS $$ + my $arg = shift; + my $result = ""; + return undef if (!defined $arg); + + # as an array reference + for (@$arg) { + $result .= $_; + } + + # also works as a string + $result .= $arg; + + return $result; +$$ LANGUAGE plperl; + +SELECT concat_array_elements(ARRAY['PL','/','Perl']); +</programlisting> + + <note> + <para> + Multi-dimensional arrays are represented as references to + lower-dimensional arrays of references in a way common to every Perl + programmer. + </para> + </note> + </para> + + <para> Composite-type arguments are passed to the function as references to hashes. The keys of the hash are the attribute names of the composite type. Here is an example: @@ -286,8 +331,8 @@ SELECT * FROM perl_set(); </para> <para> - If you wish to use the <literal>strict</> pragma with your code you - have a few options. For temporary global use you can <command>SET</> + If you wish to use the <literal>strict</> pragma with your code you + have a few options. For temporary global use you can <command>SET</> <literal>plperl.use_strict</literal> to true. This will affect subsequent compilations of <application>PL/Perl</> functions, but not functions already compiled in the current session. @@ -445,9 +490,9 @@ SELECT * FROM test_munge(); </varlistentry> <varlistentry> - <term><literal><function>spi_query</>(<replaceable>command</replaceable>)</literal></term> - <term><literal><function>spi_fetchrow</>(<replaceable>cursor</replaceable>)</literal></term> - <term><literal><function>spi_cursor_close</>(<replaceable>cursor</replaceable>)</literal></term> + <term><literal><function>spi_query(<replaceable>command</replaceable>)</function></literal></term> + <term><literal><function>spi_fetchrow(<replaceable>cursor</replaceable>)</function></literal></term> + <term><literal><function>spi_cursor_close(<replaceable>cursor</replaceable>)</function></literal></term> <listitem> <para> @@ -503,10 +548,10 @@ SELECT * from lotsa_md5(500); </varlistentry> <varlistentry> - <term><literal><function>spi_prepare</>(<replaceable>command</replaceable>, <replaceable>argument types</replaceable>)</literal></term> - <term><literal><function>spi_query_prepared</>(<replaceable>plan</replaceable>, <replaceable>arguments</replaceable>)</literal></term> - <term><literal><function>spi_exec_prepared</>(<replaceable>plan</replaceable> [, <replaceable>attributes</replaceable>], <replaceable>arguments</replaceable>)</literal></term> - <term><literal><function>spi_freeplan</>(<replaceable>plan</replaceable>)</literal></term> + <term><literal><function>spi_prepare(<replaceable>command</replaceable>, <replaceable>argument types</replaceable>)</function></literal></term> + <term><literal><function>spi_query_prepared(<replaceable>plan</replaceable>, <replaceable>arguments</replaceable>)</function></literal></term> + <term><literal><function>spi_exec_prepared(<replaceable>plan</replaceable> [, <replaceable>attributes</replaceable>], <replaceable>arguments</replaceable>)</function></literal></term> + <term><literal><function>spi_freeplan(<replaceable>plan</replaceable>)</function></literal></term> <listitem> <para> @@ -523,17 +568,14 @@ $plan = spi_prepare('SELECT * FROM test WHERE id > $1 AND name = $2', by <literal>spi_exec_query</literal>, or in <literal>spi_query_prepared</literal> which returns a cursor exactly as <literal>spi_query</literal> does, which can be later passed to <literal>spi_fetchrow</literal>. The optional second parameter to <literal>spi_exec_prepared</literal> is a hash reference of attributes; - the only attribute currently supported is <literal>limit</literal>, which sets the maximum number of rows returned by a query. + the only attribute currently supported is <literal>limit</literal>, which sets the maximum number of rows returned by a query. </para> <para> The advantage of prepared queries is that is it possible to use one prepared plan for more than one query execution. After the plan is not needed anymore, it can be freed with <literal>spi_freeplan</literal>: - </para> - - <para> - <programlisting> +<programlisting> CREATE OR REPLACE FUNCTION init() RETURNS VOID AS $$ $_SHARED{my_plan} = spi_prepare('SELECT (now() + $1)::date AS now', 'INTERVAL'); @@ -558,10 +600,7 @@ SELECT done(); add_time | add_time | add_time ------------+------------+------------ 2005-12-10 | 2005-12-11 | 2005-12-12 - </programlisting> - </para> - - <para> +</programlisting> Note that the parameter subscript in <literal>spi_prepare</literal> is defined via $1, $2, $3, etc, so avoid declaring query strings in double quotes that might easily lead to hard-to-catch bugs. @@ -569,15 +608,12 @@ SELECT done(); <para> Another example illustrates usage of an optional parameter in <literal>spi_exec_prepared</literal>: - </para> - - <para> - <programlisting> +<programlisting> CREATE TABLE hosts AS SELECT id, ('192.168.1.'||id)::inet AS address FROM generate_series(1,3) AS id; CREATE OR REPLACE FUNCTION init_hosts_query() RETURNS VOID AS $$ - $_SHARED{plan} = spi_prepare('SELECT * FROM hosts + $_SHARED{plan} = spi_prepare('SELECT * FROM hosts WHERE address << $1', 'inet'); $$ LANGUAGE plperl; @@ -603,7 +639,7 @@ SELECT release_hosts_query(); (1,192.168.1.1) (2,192.168.1.2) (2 rows) - </programlisting> +</programlisting> </para> </listitem> </varlistentry> @@ -611,7 +647,7 @@ SELECT release_hosts_query(); </sect2> <sect2 id="plperl-utility-functions"> - <title>Utility functions in PL/Perl</title> + <title>Utility Functions in PL/Perl</title> <variablelist> <varlistentry> @@ -620,7 +656,7 @@ SELECT release_hosts_query(); <secondary>in PL/Perl</secondary> </indexterm> - <term><literal><function>elog</>(<replaceable>level</replaceable>, <replaceable>msg</replaceable>)</literal></term> + <term><literal><function>elog(<replaceable>level</replaceable>, <replaceable>msg</replaceable>)</function></literal></term> <listitem> <para> Emit a log or error message. Possible levels are @@ -649,7 +685,7 @@ SELECT release_hosts_query(); <secondary>in PL/Perl</secondary> </indexterm> - <term><literal><function>quote_literal</>(<replaceable>string</replaceable>)</literal></term> + <term><literal><function>quote_literal(<replaceable>string</replaceable>)</function></literal></term> <listitem> <para> Return the given string suitably quoted to be used as a string literal in an SQL @@ -666,7 +702,7 @@ SELECT release_hosts_query(); <secondary>in PL/Perl</secondary> </indexterm> - <term><literal><function>quote_nullable</>(<replaceable>string</replaceable>)</literal></term> + <term><literal><function>quote_nullable(<replaceable>string</replaceable>)</function></literal></term> <listitem> <para> Return the given string suitably quoted to be used as a string literal in an SQL @@ -682,7 +718,7 @@ SELECT release_hosts_query(); <secondary>in PL/Perl</secondary> </indexterm> - <term><literal><function>quote_ident</>(<replaceable>string</replaceable>)</literal></term> + <term><literal><function>quote_ident(<replaceable>string</replaceable>)</function></literal></term> <listitem> <para> Return the given string suitably quoted to be used as an identifier in @@ -699,11 +735,11 @@ SELECT release_hosts_query(); <secondary>in PL/Perl</secondary> </indexterm> - <term><literal><function>decode_bytea</>(<replaceable>string</replaceable>)</literal></term> + <term><literal><function>decode_bytea(<replaceable>string</replaceable>)</function></literal></term> <listitem> <para> Return the unescaped binary data represented by the contents of the given string, - which should be bytea encoded. + which should be <type>bytea</type> encoded. </para> </listitem> </varlistentry> @@ -714,10 +750,10 @@ SELECT release_hosts_query(); <secondary>in PL/Perl</secondary> </indexterm> - <term><literal><function>encode_bytea</>(<replaceable>string</replaceable>)</literal></term> + <term><literal><function>encode_bytea(<replaceable>string</replaceable>)</function></literal></term> <listitem> <para> - Return the bytea encoded form of the binary data contents of the given string. + Return the <type>bytea</type> encoded form of the binary data contents of the given string. </para> </listitem> </varlistentry> @@ -728,8 +764,8 @@ SELECT release_hosts_query(); <secondary>in PL/Perl</secondary> </indexterm> - <term><literal><function>encode_array_literal</>(<replaceable>array</replaceable>)</literal></term> - <term><literal><function>encode_array_literal</>(<replaceable>array</replaceable>, <replaceable>delimiter</replaceable>)</literal></term> + <term><literal><function>encode_array_literal(<replaceable>array</replaceable>)</function></literal></term> + <term><literal><function>encode_array_literal(<replaceable>array</replaceable>, <replaceable>delimiter</replaceable>)</function></literal></term> <listitem> <para> Returns the contents of the referenced array as a string in array literal format @@ -743,11 +779,27 @@ SELECT release_hosts_query(); <varlistentry> <indexterm> + <primary>encode_typed_literal</primary> + <secondary>in PL/Perl</secondary> + </indexterm> + + <term><literal><function>encode_typed_literal(<replaceable>value</replaceable>, <replaceable>typename</replaceable>)</function></literal></term> + <listitem> + <para> + Converts a Perl variable to the value of the data type passed as a + second argument and returns a string representation of this value. + Correctly handles nested arrays and values of composite types. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <indexterm> <primary>encode_array_constructor</primary> <secondary>in PL/Perl</secondary> </indexterm> - <term><literal><function>encode_array_constructor</>(<replaceable>array</replaceable>)</literal></term> + <term><literal><function>encode_array_constructor(<replaceable>array</replaceable>)</function></literal></term> <listitem> <para> Returns the contents of the referenced array as a string in array constructor format @@ -765,7 +817,7 @@ SELECT release_hosts_query(); <secondary>in PL/Perl</secondary> </indexterm> - <term><literal><function>looks_like_number</>(<replaceable>string</replaceable>)</literal></term> + <term><literal><function>looks_like_number(<replaceable>string</replaceable>)</function></literal></term> <listitem> <para> Returns a true value if the content of the given string looks like a @@ -776,8 +828,24 @@ SELECT release_hosts_query(); </listitem> </varlistentry> + <varlistentry> + <indexterm> + <primary>is_array_ref</primary> + <secondary>in PL/Perl</secondary> + </indexterm> + + <term><literal><function>is_array_ref(<replaceable>argument</replaceable>)</function></literal></term> + <listitem> + <para> + Returns a true value if the given argument may be treated as an + array reference, that is, if ref of the argument is <literal>ARRAY</> or + <literal>PostgreSQL::InServer::ARRAY</>. Returns false otherwise. + </para> + </listitem> + </varlistentry> + </variablelist> - </sect2> + </sect2> </sect1> <sect1 id="plperl-global"> @@ -838,10 +906,20 @@ $$ LANGUAGE plperl; </para> <para> - The <varname>%_SHARED</varname> variable and other global state within - the language are public data, available to all PL/Perl functions within a - session. Use with care, especially in situations that involve use of - multiple roles or <literal>SECURITY DEFINER</> functions. + For security reasons, PL/Perl executes functions called by any one SQL role + in a separate Perl interpreter for that role. This prevents accidental or + malicious interference by one user with the behavior of another user's + PL/Perl functions. Each such interpreter has its own value of the + <varname>%_SHARED</varname> variable and other global state. Thus, two + PL/Perl functions will share the same value of <varname>%_SHARED</varname> + if and only if they are executed by the same SQL role. In an application + wherein a single session executes code under multiple SQL roles (via + <literal>SECURITY DEFINER</> functions, use of <command>SET ROLE</>, etc) + you may need to take explicit steps to ensure that PL/Perl functions can + share data via <varname>%_SHARED</varname>. To do that, make sure that + functions that should communicate are owned by the same user, and mark + them <literal>SECURITY DEFINER</>. You must of course take care that + such functions can't be used to do anything unintended. </para> </sect1> @@ -890,8 +968,7 @@ $$ LANGUAGE plperl; mail. To handle these cases, PL/Perl can also be installed as an <quote>untrusted</> language (usually called <application>PL/PerlU</application><indexterm><primary>PL/PerlU</></indexterm>). - In this case the full Perl language is available. If the - <command>createlang</command> program is used to install the + In this case the full Perl language is available. When installing the language, the language name <literal>plperlu</literal> will select the untrusted PL/Perl variant. </para> @@ -917,22 +994,31 @@ $$ LANGUAGE plperl; </para> <note> - <para> - For security reasons, to stop a leak of privileged operations from - <application>PL/PerlU</> to <application>PL/Perl</>, these two languages - have to run in separate instances of the Perl interpreter. If your - Perl installation has been appropriately compiled, this is not a problem. - However, not all installations are compiled with the requisite flags. - If <productname>PostgreSQL</> detects that this is the case then it will - not start a second interpreter, but instead create an error. In - consequence, in such an installation, you cannot use both - <application>PL/PerlU</> and <application>PL/Perl</> in the same backend - process. The remedy for this is to obtain a Perl installation configured - with the appropriate flags, namely either <literal>usemultiplicity</> - or <literal>useithreads</>. <literal>usemultiplicity</> is preferred - unless you actually need to use threads. For more details, see the - <citerefentry><refentrytitle>perlembed</></citerefentry> man page. - </para> + <para> + While <application>PL/Perl</> functions run in a separate Perl + interpreter for each SQL role, all <application>PL/PerlU</> functions + executed in a given session run in a single Perl interpreter (which is + not any of the ones used for <application>PL/Perl</> functions). + This allows <application>PL/PerlU</> functions to share data freely, + but no communication can occur between <application>PL/Perl</> and + <application>PL/PerlU</> functions. + </para> + </note> + + <note> + <para> + Perl cannot support multiple interpreters within one process unless + it was built with the appropriate flags, namely either + <literal>usemultiplicity</> or <literal>useithreads</>. + (<literal>usemultiplicity</> is preferred unless you actually need + to use threads. For more details, see the + <citerefentry><refentrytitle>perlembed</></citerefentry> man page.) + If <application>PL/Perl</> is used with a copy of Perl that was not built + this way, then it is only possible to have one Perl interpreter per + session, and so any one session can only execute either + <application>PL/PerlU</> functions, or <application>PL/Perl</> functions + that are all called by the same SQL role. + </para> </note> </sect1> @@ -989,7 +1075,9 @@ $$ LANGUAGE plperl; <term><literal>$_TD->{when}</literal></term> <listitem> <para> - When the trigger was called: <literal>BEFORE</literal>, <literal>AFTER</literal>, or <literal>UNKNOWN</literal> + When the trigger was called: <literal>BEFORE</literal>, + <literal>AFTER</literal>, <literal>INSTEAD OF</literal>, or + <literal>UNKNOWN</literal> </para> </listitem> </varlistentry> @@ -1146,12 +1234,13 @@ CREATE TRIGGER test_valid_id_trig </indexterm> <listitem> <para> - Specifies Perl code to be executed when a Perl interpreter is first initialized - and before it is specialized for use by <literal>plperl</> or <literal>plperlu</>. - The SPI functions are not available when this code is executed. - If the code fails with an error it will abort the initialization of the interpreter - and propagate out to the calling query, causing the current transaction - or subtransaction to be aborted. + Specifies Perl code to be executed when a Perl interpreter is first + initialized, before it is specialized for use by <literal>plperl</> or + <literal>plperlu</>. + The SPI functions are not available when this code is executed. + If the code fails with an error it will abort the initialization of + the interpreter and propagate out to the calling query, causing the + current transaction or subtransaction to be aborted. </para> <para> The Perl code is limited to a single string. Longer code can be placed @@ -1171,12 +1260,24 @@ DO 'elog(WARNING, join ", ", sort keys %INC)' language plperl; </programlisting> </para> <para> - Initialization will happen in the postmaster if the plperl library is included - in <literal>shared_preload_libraries</> (see <xref linkend="guc-shared-preload-libraries">), - in which case extra consideration should be given to the risk of destabilizing the postmaster. + Initialization will happen in the postmaster if the plperl library is + included in <xref linkend="guc-shared-preload-libraries">, in which + case extra consideration should be given to the risk of destabilizing + the postmaster. The principal reason for making use of this feature + is that Perl modules loaded by <literal>plperl.on_init</> need be + loaded only at postmaster start, and will be instantly available + without loading overhead in individual database sessions. However, + keep in mind that the overhead is avoided only for the first Perl + interpreter used by a database session — either PL/PerlU, or + PL/Perl for the first SQL role that calls a PL/Perl function. Any + additional Perl interpreters created in a database session will have + to execute <literal>plperl.on_init</> afresh. Also, on Windows there + will be no savings whatsoever from preloading, since the Perl + interpreter created in the postmaster process does not propagate to + child processes. </para> <para> - This parameter can only be set in the postgresql.conf file or on the server command line. + This parameter can only be set in the <filename>postgresql.conf</filename> file or on the server command line. </para> </listitem> </varlistentry> @@ -1192,41 +1293,30 @@ DO 'elog(WARNING, join ", ", sort keys %INC)' language plperl; </indexterm> <listitem> <para> - These parameters specify Perl code to be executed when the - <literal>plperl</>, or <literal>plperlu</> language is first used in a - session. Changes to these parameters after the corresponding language - has been used will have no effect. - The SPI functions are not available when this code is executed. - Only superusers can change these settings. - The Perl code in <literal>plperl.on_plperl_init</> can only perform trusted operations. - </para> - <para> - The effect of setting these parameters is very similar to executing a - <literal>DO</> command with the Perl code before any other use of the - language. The parameters are useful when you want to execute the Perl - code automatically on every connection, or when a connection is not - interactive. The parameters can be used by non-superusers by having a - superuser execute an <literal>ALTER USER ... SET ...</> command. - For example: -<programlisting> -ALTER USER joe SET plperl.on_plperl_init = '$_SHARED{debug} = 1'; -</programlisting> + These parameters specify Perl code to be executed when a Perl + interpreter is specialized for <literal>plperl</> or + <literal>plperlu</> respectively. This will happen when a PL/Perl or + PL/PerlU function is first executed in a database session, or when + an additional interpreter has to be created because the other language + is called or a PL/Perl function is called by a new SQL role. This + follows any initialization done by <literal>plperl.on_init</>. + The SPI functions are not available when this code is executed. + The Perl code in <literal>plperl.on_plperl_init</> is executed after + <quote>locking down</> the interpreter, and thus it can only perform + trusted operations. </para> <para> - If the code fails with an error it will abort the initialization and - propagate out to the calling query, causing the current transaction or - subtransaction to be aborted. Any changes within Perl won't be undone. - If the language is used again the initialization will be repeated. + If the code fails with an error it will abort the initialization and + propagate out to the calling query, causing the current transaction or + subtransaction to be aborted. Any actions already done within Perl + won't be undone; however, that interpreter won't be used again. + If the language is used again the initialization will be attempted + again within a fresh Perl interpreter. </para> <para> - The difference between these two settings and the - <literal>plperl.on_init</> setting is that these can be used for - settings specific to the trusted or untrusted language variant, such - as setting values in the <varname>%_SHARED</> variable. By contrast, - <literal>plperl.on_init</> is more useful for doing things like - setting the library search path for <productname>Perl</> or - loading Perl modules that don't interact directly with - <productname>PostgreSQL</>. + Only superusers can change these settings. Although these settings + can be changed within a session, such changes will not affect Perl + interpreters that have already been used to execute functions. </para> </listitem> </varlistentry> @@ -1238,8 +1328,9 @@ ALTER USER joe SET plperl.on_plperl_init = '$_SHARED{debug} = 1'; </indexterm> <listitem> <para> - When set true subsequent compilations of PL/Perl functions have the <literal>strict</> pragma enabled. - This parameter does not affect functions already compiled in the current session. + When set true subsequent compilations of PL/Perl functions will have + the <literal>strict</> pragma enabled. This parameter does not affect + functions already compiled in the current session. </para> </listitem> </varlistentry> @@ -1288,8 +1379,8 @@ ALTER USER joe SET plperl.on_plperl_init = '$_SHARED{debug} = 1'; <para> When a session ends normally, not due to a fatal error, any <literal>END</> blocks that have been defined are executed. - Currently no other actions are performed. Specifically, - file handles are not automatically flushed and objects are + Currently no other actions are performed. Specifically, + file handles are not automatically flushed and objects are not automatically destroyed. </para> </listitem> diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index 1ed946d10e..eea6ec58e3 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.154 2010/06/29 22:29:14 momjian Exp $ --> +<!-- doc/src/sgml/plpgsql.sgml --> <chapter id="plpgsql"> <title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title> @@ -328,15 +328,17 @@ arow RECORD; <para> The general syntax of a variable declaration is: <synopsis> -<replaceable>name</replaceable> <optional> CONSTANT </optional> <replaceable>type</replaceable> <optional> NOT NULL </optional> <optional> { DEFAULT | := } <replaceable>expression</replaceable> </optional>; +<replaceable>name</replaceable> <optional> CONSTANT </optional> <replaceable>type</replaceable> <optional> COLLATE <replaceable>collation_name</replaceable> </optional> <optional> NOT NULL </optional> <optional> { DEFAULT | := } <replaceable>expression</replaceable> </optional>; </synopsis> The <literal>DEFAULT</> clause, if given, specifies the initial value assigned to the variable when the block is entered. If the <literal>DEFAULT</> clause is not given then the variable is initialized to the <acronym>SQL</acronym> null value. The <literal>CONSTANT</> option prevents the variable from being - assigned to, so that its value will remain constant for the duration of - the block. + assigned to after initialization, so that its value will remain constant + for the duration of the block. + The <literal>COLLATE</> option specifies a collation to use for the + variable (see <xref linkend="plpgsql-declaration-collation">). If <literal>NOT NULL</> is specified, an assignment of a null value results in a run-time error. All variables declared as <literal>NOT NULL</> @@ -706,6 +708,99 @@ SELECT merge_fields(t.*) FROM table1 t WHERE ... ; structure on-the-fly. </para> </sect2> + + <sect2 id="plpgsql-declaration-collation"> + <title>Collation of <application>PL/pgSQL</application> Variables</title> + + <indexterm> + <primary>collation</> + <secondary>in PL/pgSQL</> + </indexterm> + + <para> + When a <application>PL/pgSQL</application> function has one or more + parameters of collatable data types, a collation is identified for each + function call depending on the collations assigned to the actual + arguments, as described in <xref linkend="collation">. If a collation is + successfully identified (i.e., there are no conflicts of implicit + collations among the arguments) then all the collatable parameters are + treated as having that collation implicitly. This will affect the + behavior of collation-sensitive operations within the function. + For example, consider + +<programlisting> +CREATE FUNCTION less_than(a text, b text) RETURNS boolean AS $$ +BEGIN + RETURN a < b; +END; +$$ LANGUAGE plpgsql; + +SELECT less_than(text_field_1, text_field_2) FROM table1; +SELECT less_than(text_field_1, text_field_2 COLLATE "C") FROM table1; +</programlisting> + + The first use of <function>less_than</> will use the common collation + of <structfield>text_field_1</> and <structfield>text_field_2</> for + the comparison, while the second use will use <literal>C</> collation. + </para> + + <para> + Furthermore, the identified collation is also assumed as the collation of + any local variables that are of collatable types. Thus this function + would not work any differently if it were written as + +<programlisting> +CREATE FUNCTION less_than(a text, b text) RETURNS boolean AS $$ +DECLARE + local_a text := a; + local_b text := b; +BEGIN + RETURN local_a < local_b; +END; +$$ LANGUAGE plpgsql; +</programlisting> + </para> + + <para> + If there are no parameters of collatable data types, or no common + collation can be identified for them, then parameters and local variables + use the default collation of their data type (which is usually the + database's default collation, but could be different for variables of + domain types). + </para> + + <para> + A local variable of a collatable data type can have a different collation + associated with it by including the <literal>COLLATE</> option in its + declaration, for example + +<programlisting> +DECLARE + local_a text COLLATE "en_US"; +</programlisting> + + This option overrides the collation that would otherwise be + given to the variable according to the rules above. + </para> + + <para> + Also, of course explicit <literal>COLLATE</> clauses can be written inside + a function if it is desired to force a particular collation to be used in + a particular operation. For example, + +<programlisting> +CREATE FUNCTION less_than_c(a text, b text) RETURNS boolean AS $$ +BEGIN + RETURN a < b COLLATE "C"; +END; +$$ LANGUAGE plpgsql; +</programlisting> + + This overrides the collations associated with the table columns, + parameters, or local variables used in the expression, just as would + happen in a plain SQL command. + </para> + </sect2> </sect1> <sect1 id="plpgsql-expressions"> @@ -874,7 +969,7 @@ PERFORM create_mv('cs_session_page_requests_mv', my_query); </sect2> <sect2 id="plpgsql-statements-sql-onerow"> - <title>Executing a Query with a Single-Row Result</title> + <title>Executing a Query with a Single-row Result</title> <indexterm zone="plpgsql-statements-sql-onerow"> <primary>SELECT INTO</primary> @@ -1135,21 +1230,26 @@ EXECUTE 'SELECT count(*) FROM ' </note> <example id="plpgsql-quote-literal-example"> - <title>Quoting values in dynamic queries</title> + <title>Quoting Values In Dynamic Queries</title> <indexterm> <primary>quote_ident</primary> - <secondary>use in PL/PgSQL</secondary> + <secondary>use in PL/pgSQL</secondary> </indexterm> <indexterm> <primary>quote_literal</primary> - <secondary>use in PL/PgSQL</secondary> + <secondary>use in PL/pgSQL</secondary> </indexterm> <indexterm> <primary>quote_nullable</primary> - <secondary>use in PL/PgSQL</secondary> + <secondary>use in PL/pgSQL</secondary> + </indexterm> + + <indexterm> + <primary>format</primary> + <secondary>use in PL/pgSQL</secondary> </indexterm> <para> @@ -1217,14 +1317,14 @@ EXECUTE 'UPDATE tbl SET ' As always, care must be taken to ensure that null values in a query do not deliver unintended results. For example the <literal>WHERE</> clause <programlisting> - 'WHERE key = ' || quote_nullable(keyvalue) +'WHERE key = ' || quote_nullable(keyvalue) </programlisting> will never succeed if <literal>keyvalue</> is null, because the result of using the equality operator <literal>=</> with a null operand is always null. If you wish null to work like an ordinary key value, you would need to rewrite the above as <programlisting> - 'WHERE key IS NOT DISTINCT FROM ' || quote_nullable(keyvalue) +'WHERE key IS NOT DISTINCT FROM ' || quote_nullable(keyvalue) </programlisting> (At present, <literal>IS NOT DISTINCT FROM</> is handled much less efficiently than <literal>=</>, so don't do this unless you must. @@ -1250,6 +1350,24 @@ EXECUTE 'UPDATE tbl SET ' <emphasis>must</> use <function>quote_literal</>, <function>quote_nullable</>, or <function>quote_ident</>, as appropriate. </para> + + <para> + Dynamic SQL statements can also be safely constructed using the + <function>format</function> function (see <xref + linkend="functions-string">). For example: +<programlisting> +EXECUTE format('UPDATE tbl SET %I = %L WHERE key = %L', colname, newvalue, keyvalue); +</programlisting> + The <function>format</function> function can be used in conjunction with + the <literal>USING</literal> clause: +<programlisting> +EXECUTE format('UPDATE tbl SET %I = $1 WHERE key = $2', colname) + USING newvalue, keyvalue; +</programlisting> + This form is more efficient, because the parameters + <literal>newvalue</literal> and <literal>keyvalue</literal> are not + converted to text. + </para> </example> <para> @@ -1333,25 +1451,21 @@ GET DIAGNOSTICS integer_var = ROW_COUNT; true if it successfully repositions the cursor, false otherwise. </para> </listitem> - <listitem> <para> - A <command>FOR</> statement sets <literal>FOUND</literal> true - if it iterates one or more times, else false. This applies to - all four variants of the <command>FOR</> statement (integer - <command>FOR</> loops, record-set <command>FOR</> loops, - dynamic record-set <command>FOR</> loops, and cursor - <command>FOR</> loops). + A <command>FOR</> or <command>FOREACH</> statement sets + <literal>FOUND</literal> true + if it iterates one or more times, else false. <literal>FOUND</literal> is set this way when the - <command>FOR</> loop exits; inside the execution of the loop, + loop exits; inside the execution of the loop, <literal>FOUND</literal> is not modified by the - <command>FOR</> statement, although it might be changed by the + loop statement, although it might be changed by the execution of other statements within the loop body. </para> </listitem> <listitem> <para> - A <command>RETURN QUERY</command> and <command>RETURN QUERY + <command>RETURN QUERY</command> and <command>RETURN QUERY EXECUTE</command> statements set <literal>FOUND</literal> true if the query returns at least one row, false if no row is returned. @@ -1391,20 +1505,20 @@ NULL; <para> For example, the following two fragments of code are equivalent: <programlisting> - BEGIN - y := x / 0; - EXCEPTION - WHEN division_by_zero THEN - NULL; -- ignore the error - END; +BEGIN + y := x / 0; +EXCEPTION + WHEN division_by_zero THEN + NULL; -- ignore the error +END; </programlisting> <programlisting> - BEGIN - y := x / 0; - EXCEPTION - WHEN division_by_zero THEN -- ignore the error - END; +BEGIN + y := x / 0; +EXCEPTION + WHEN division_by_zero THEN -- ignore the error +END; </programlisting> Which is preferable is a matter of taste. </para> @@ -1492,11 +1606,11 @@ RETURN <replaceable>expression</replaceable>; <title><command>RETURN NEXT</> and <command>RETURN QUERY</command></title> <indexterm> <primary>RETURN NEXT</primary> - <secondary>in PL/PgSQL</secondary> + <secondary>in PL/pgSQL</secondary> </indexterm> <indexterm> <primary>RETURN QUERY</primary> - <secondary>in PL/PgSQL</secondary> + <secondary>in PL/pgSQL</secondary> </indexterm> <synopsis> @@ -1842,7 +1956,7 @@ END CASE; <para> The searched form of <command>CASE</> provides conditional execution - based on truth of boolean expressions. Each <literal>WHEN</> clause's + based on truth of Boolean expressions. Each <literal>WHEN</> clause's <replaceable>boolean-expression</replaceable> is evaluated in turn, until one is found that yields <literal>true</>. Then the corresponding <replaceable>statements</replaceable> are executed, and @@ -1887,9 +2001,9 @@ END CASE; <para> With the <literal>LOOP</>, <literal>EXIT</>, - <literal>CONTINUE</>, <literal>WHILE</>, and <literal>FOR</> - statements, you can arrange for your <application>PL/pgSQL</> - function to repeat a series of commands. + <literal>CONTINUE</>, <literal>WHILE</>, <literal>FOR</>, + and <literal>FOREACH</> statements, you can arrange for your + <application>PL/pgSQL</> function to repeat a series of commands. </para> <sect3> @@ -2071,7 +2185,7 @@ END LOOP; </sect3> <sect3 id="plpgsql-integer-for"> - <title><literal>FOR</> (integer variant)</title> + <title><literal>FOR</> (Integer Variant)</title> <synopsis> <optional> <<<replaceable>label</replaceable>>> </optional> @@ -2150,21 +2264,20 @@ CREATE FUNCTION cs_refresh_mviews() RETURNS integer AS $$ DECLARE mviews RECORD; BEGIN - PERFORM cs_log('Refreshing materialized views...'); + RAISE NOTICE 'Refreshing materialized views...'; FOR mviews IN SELECT * FROM cs_materialized_views ORDER BY sort_key LOOP -- Now "mviews" has one record from cs_materialized_views - PERFORM cs_log('Refreshing materialized view ' - || quote_ident(mviews.mv_name) || ' ...'); + RAISE NOTICE 'Refreshing materialized view %s ...', quote_ident(mviews.mv_name); EXECUTE 'TRUNCATE TABLE ' || quote_ident(mviews.mv_name); EXECUTE 'INSERT INTO ' - || quote_ident(mviews.mv_name) || ' ' + || quote_ident(mviews.mv_name) || ' ' || mviews.mv_query; END LOOP; - PERFORM cs_log('Done refreshing materialized views.'); + RAISE NOTICE 'Done refreshing materialized views.'; RETURN 1; END; $$ LANGUAGE plpgsql; @@ -2215,12 +2328,96 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>; </para> </sect2> + <sect2 id="plpgsql-foreach-array"> + <title>Looping Through Arrays</title> + + <para> + The <literal>FOREACH</> loop is much like a <literal>FOR</> loop, + but instead of iterating through the rows returned by a SQL query, + it iterates through the elements of an array value. + (In general, <literal>FOREACH</> is meant for looping through + components of a composite-valued expression; variants for looping + through composites besides arrays may be added in future.) + The <literal>FOREACH</> statement to loop over an array is: + +<synopsis> +<optional> <<<replaceable>label</replaceable>>> </optional> +FOREACH <replaceable>target</replaceable> <optional> SLICE <replaceable>number</replaceable> </optional> IN ARRAY <replaceable>expression</replaceable> LOOP + <replaceable>statements</replaceable> +END LOOP <optional> <replaceable>label</replaceable> </optional>; +</synopsis> + </para> + + <para> + Without <literal>SLICE</>, or if <literal>SLICE 0</> is specified, + the loop iterates through individual elements of the array produced + by evaluating the <replaceable>expression</replaceable>. + The <replaceable>target</replaceable> variable is assigned each + element value in sequence, and the loop body is executed for each element. + Here is an example of looping through the elements of an integer + array: + +<programlisting> +CREATE FUNCTION sum(int[]) RETURNS int8 AS $$ +DECLARE + s int8 := 0; + x int; +BEGIN + FOREACH x IN ARRAY $1 + LOOP + s := s + x; + END LOOP; + RETURN s; +END; +$$ LANGUAGE plpgsql; +</programlisting> + + The elements are visited in storage order, regardless of the number of + array dimensions. Although the <replaceable>target</replaceable> is + usually just a single variable, it can be a list of variables when + looping through an array of composite values (records). In that case, + for each array element, the variables are assigned from successive + columns of the composite value. + </para> + + <para> + With a positive <literal>SLICE</> value, <literal>FOREACH</> + iterates through slices of the array rather than single elements. + The <literal>SLICE</> value must be an integer constant not larger + than the number of dimensions of the array. The + <replaceable>target</replaceable> variable must be an array, + and it receives successive slices of the array value, where each slice + is of the number of dimensions specified by <literal>SLICE</>. + Here is an example of iterating through one-dimensional slices: + +<programlisting> +CREATE FUNCTION scan_rows(int[]) RETURNS void AS $$ +DECLARE + x int[]; +BEGIN + FOREACH x SLICE 1 IN ARRAY $1 + LOOP + RAISE NOTICE 'row = %', x; + END LOOP; +END; +$$ LANGUAGE plpgsql; + +SELECT scan_rows(ARRAY[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]); + +NOTICE: row = {1,2,3} +NOTICE: row = {4,5,6} +NOTICE: row = {7,8,9} +NOTICE: row = {10,11,12} +</programlisting> + </para> + </sect2> + <sect2 id="plpgsql-error-trapping"> <title>Trapping Errors</title> <indexterm> <primary>exceptions</primary> - <secondary>in PL/PgSQL</secondary> + <secondary>in PL/pgSQL</secondary> </indexterm> <para> @@ -2275,8 +2472,8 @@ END; not case-sensitive. Also, an error condition can be specified by <literal>SQLSTATE</> code; for example these are equivalent: <programlisting> - WHEN division_by_zero THEN ... - WHEN SQLSTATE '22012' THEN ... +WHEN division_by_zero THEN ... +WHEN SQLSTATE '22012' THEN ... </programlisting> </para> @@ -2295,16 +2492,16 @@ END; As an example, consider this fragment: <programlisting> - INSERT INTO mytab(firstname, lastname) VALUES('Tom', 'Jones'); - BEGIN - UPDATE mytab SET firstname = 'Joe' WHERE lastname = 'Jones'; - x := x + 1; - y := x / 0; - EXCEPTION - WHEN division_by_zero THEN - RAISE NOTICE 'caught division_by_zero'; - RETURN x; - END; +INSERT INTO mytab(firstname, lastname) VALUES('Tom', 'Jones'); +BEGIN + UPDATE mytab SET firstname = 'Joe' WHERE lastname = 'Jones'; + x := x + 1; + y := x / 0; +EXCEPTION + WHEN division_by_zero THEN + RAISE NOTICE 'caught division_by_zero'; + RETURN x; +END; </programlisting> When control reaches the assignment to <literal>y</>, it will @@ -2361,7 +2558,7 @@ BEGIN INSERT INTO db(a,b) VALUES (key, data); RETURN; EXCEPTION WHEN unique_violation THEN - -- do nothing, and loop to try the UPDATE again + -- Do nothing, and loop to try the UPDATE again. END; END LOOP; END; @@ -2371,7 +2568,9 @@ LANGUAGE plpgsql; SELECT merge_db(1, 'david'); SELECT merge_db(1, 'dennis'); </programlisting> - + This example assumes the <literal>unique_violation</> error is caused by + the <command>INSERT</>, and not by an <command>INSERT</> trigger function + on the table. </para> </example> </sect2> @@ -2523,7 +2722,7 @@ OPEN <replaceable>unbound_cursorvar</replaceable> <optional> <optional> NO </opt <para> An example: <programlisting> -OPEN curs1 FOR EXECUTE 'SELECT * FROM ' || quote_ident(tabname) +OPEN curs1 FOR EXECUTE 'SELECT * FROM ' || quote_ident(tabname) || ' WHERE col1 = $1' USING keyvalue; </programlisting> In this example, the table name is inserted into the query textually, @@ -2898,7 +3097,7 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>; <indexterm> <primary>reporting errors</primary> - <secondary>in PL/PgSQL</secondary> + <secondary>in PL/pgSQL</secondary> </indexterm> <para> @@ -3012,10 +3211,21 @@ RAISE unique_violation USING MESSAGE = 'Duplicate user ID: ' || user_id; The last variant of <command>RAISE</> has no parameters at all. This form can only be used inside a <literal>BEGIN</> block's <literal>EXCEPTION</> clause; - it causes the error currently being handled to be re-thrown to the - next enclosing block. + it causes the error currently being handled to be re-thrown. </para> + <note> + <para> + Before <productname>PostgreSQL</> 9.1, <command>RAISE</> without + parameters was interpreted as re-throwing the error from the block + containing the active exception handler. Thus an <literal>EXCEPTION</> + clause nested within that handler could not catch it, even if the + <command>RAISE</> was within the nested <literal>EXCEPTION</> clause's + block. This was deemed surprising as well as being incompatible with + Oracle's PL/SQL. + </para> + </note> + <para> If no condition name nor SQLSTATE is specified in a <command>RAISE EXCEPTION</command> command, the default is to use @@ -3101,9 +3311,9 @@ RAISE unique_violation USING MESSAGE = 'Duplicate user ID: ' || user_id; <term><varname>TG_WHEN</varname></term> <listitem> <para> - Data type <type>text</type>; a string of either - <literal>BEFORE</literal> or <literal>AFTER</literal> - depending on the trigger's definition. + Data type <type>text</type>; a string of + <literal>BEFORE</literal>, <literal>AFTER</literal>, or + <literal>INSTEAD OF</literal>, depending on the trigger's definition. </para> </listitem> </varlistentry> @@ -3223,8 +3433,25 @@ RAISE unique_violation USING MESSAGE = 'Duplicate user ID: ' || user_id; effect, but it has to be nonnull to allow the trigger action to proceed. Note that <varname>NEW</varname> is null in <command>DELETE</command> triggers, so returning that is - usually not sensible. A useful idiom in <command>DELETE</command> - triggers might be to return <varname>OLD</varname>. + usually not sensible. The usual idiom in <command>DELETE</command> + triggers is to return <varname>OLD</varname>. + </para> + + <para> + <literal>INSTEAD OF</> triggers (which are always row-level triggers, + and may only be used on views) can return null to signal that they did + not perform any updates, and that the rest of the operation for this + row should be skipped (i.e., subsequent triggers are not fired, and the + row is not counted in the rows-affected status for the surrounding + <command>INSERT</>/<command>UPDATE</>/<command>DELETE</>). + Otherwise a nonnull value should be returned, to signal + that the trigger performed the requested operation. For + <command>INSERT</> and <command>UPDATE</> operations, the return value + should be <varname>NEW</>, which the trigger function may modify to + support <command>INSERT RETURNING</> and <command>UPDATE RETURNING</> + (this will also affect the row value passed to any subsequent triggers). + For <command>DELETE</> operations, the return value should be + <varname>OLD</>. </para> <para> @@ -3344,6 +3571,85 @@ AFTER INSERT OR UPDATE OR DELETE ON emp </example> <para> + A variation of the previous example uses a view joining the main table + to the audit table, to show when each entry was last modified. This + approach still records the full audit trail of changes to the table, + but also presents a simplified view of the audit trail, showing just + the last modified timestamp derived from the audit trail for each entry. + <xref linkend="plpgsql-view-trigger-audit-example"> shows an example + of an audit trigger on a view in <application>PL/pgSQL</application>. + </para> + + <example id="plpgsql-view-trigger-audit-example"> + <title>A <application>PL/pgSQL</application> View Trigger Procedure For Auditing</title> + + <para> + This example uses a trigger on the view to make it updatable, and + ensure that any insert, update or delete of a row in the view is + recorded (i.e., audited) in the <literal>emp_audit</literal> table. The current time + and user name are recorded, together with the type of operation + performed, and the view displays the last modified time of each row. + </para> + +<programlisting> +CREATE TABLE emp ( + empname text PRIMARY KEY, + salary integer +); + +CREATE TABLE emp_audit( + operation char(1) NOT NULL, + userid text NOT NULL, + empname text NOT NULL, + salary integer, + stamp timestamp NOT NULL +); + +CREATE VIEW emp_view AS + SELECT e.empname, + e.salary, + max(ea.stamp) AS last_updated + FROM emp e + LEFT JOIN emp_audit ea ON ea.empname = e.empname + GROUP BY 1, 2; + +CREATE OR REPLACE FUNCTION update_emp_view() RETURNS TRIGGER AS $$ + BEGIN + -- + -- Perform the required operation on emp, and create a row in emp_audit + -- to reflect the change made to emp. + -- + IF (TG_OP = 'DELETE') THEN + DELETE FROM emp WHERE empname = OLD.empname; + IF NOT FOUND THEN RETURN NULL; END IF; + + OLD.last_updated = now(); + INSERT INTO emp_audit VALUES('D', user, OLD.*); + RETURN OLD; + ELSIF (TG_OP = 'UPDATE') THEN + UPDATE emp SET salary = NEW.salary WHERE empname = OLD.empname; + IF NOT FOUND THEN RETURN NULL; END IF; + + NEW.last_updated = now(); + INSERT INTO emp_audit VALUES('U', user, NEW.*); + RETURN NEW; + ELSIF (TG_OP = 'INSERT') THEN + INSERT INTO emp VALUES(NEW.empname, NEW.salary); + + NEW.last_updated = now(); + INSERT INTO emp_audit VALUES('I', user, NEW.*); + RETURN NEW; + END IF; + END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER emp_audit +INSTEAD OF INSERT OR UPDATE OR DELETE ON emp_view + FOR EACH ROW EXECUTE PROCEDURE update_emp_view(); +</programlisting> + </example> + + <para> One use of triggers is to maintain a summary table of another table. The resulting summary can be used in place of the original table for certain queries — often with vastly reduced run @@ -3519,7 +3825,7 @@ SELECT * FROM sales_summary_bytime; column reference is syntactically allowed. As an extreme case, consider this example of poor programming style: <programlisting> - INSERT INTO foo (foo) VALUES (foo); +INSERT INTO foo (foo) VALUES (foo); </programlisting> The first occurrence of <literal>foo</> must syntactically be a table name, so it will not be substituted, even if the function has a variable @@ -3542,7 +3848,7 @@ SELECT * FROM sales_summary_bytime; tables: is a given name meant to refer to a table column, or a variable? Let's change the previous example to <programlisting> - INSERT INTO dest (col) SELECT foo + bar FROM src; +INSERT INTO dest (col) SELECT foo + bar FROM src; </programlisting> Here, <literal>dest</> and <literal>src</> must be table names, and <literal>col</> must be a column of <literal>dest</>, but <literal>foo</> @@ -3575,12 +3881,12 @@ SELECT * FROM sales_summary_bytime; declare it in a labeled block and use the block's label (see <xref linkend="plpgsql-structure">). For example, <programlisting> - <<block>> - DECLARE - foo int; - BEGIN - foo := ...; - INSERT INTO dest (col) SELECT block.foo + bar FROM src; +<<block>> +DECLARE + foo int; +BEGIN + foo := ...; + INSERT INTO dest (col) SELECT block.foo + bar FROM src; </programlisting> Here <literal>block.foo</> means the variable even if there is a column <literal>foo</> in <literal>src</>. Function parameters, as well as @@ -3697,13 +4003,16 @@ $$ LANGUAGE plpgsql; </para> <para> + <indexterm> + <primary>preparing a query</> + <secondary>in PL/pgSQL</> + </indexterm> As each expression and <acronym>SQL</acronym> command is first executed in the function, the <application>PL/pgSQL</> interpreter creates a prepared execution plan (using the <acronym>SPI</acronym> manager's <function>SPI_prepare</function> - and <function>SPI_saveplan</function> - functions).<indexterm><primary>preparing a query</><secondary>in - PL/pgSQL</></> Subsequent visits to that expression or command + and <function>SPI_saveplan</function> functions). + Subsequent visits to that expression or command reuse the prepared plan. Thus, a function with conditional code that contains many statements for which execution plans might be required will only prepare and save those plans that are really @@ -4279,7 +4588,7 @@ show errors; <programlisting> CREATE OR REPLACE FUNCTION cs_update_referrer_type_proc() RETURNS void AS $func$ DECLARE - CURSOR referrer_keys IS + referrer_keys CURSOR IS SELECT * FROM cs_referrer_keys ORDER BY try_order; func_body text; @@ -4591,17 +4900,17 @@ $$ LANGUAGE plpgsql; is equivalent to what you'd get in Oracle with: <programlisting> - BEGIN - SAVEPOINT s1; +BEGIN + SAVEPOINT s1; + ... code here ... +EXCEPTION + WHEN ... THEN + ROLLBACK TO s1; ... code here ... - EXCEPTION - WHEN ... THEN - ROLLBACK TO s1; - ... code here ... - WHEN ... THEN - ROLLBACK TO s1; - ... code here ... - END; + WHEN ... THEN + ROLLBACK TO s1; + ... code here ... +END; </programlisting> If you are translating an Oracle procedure that uses diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml index c76012db40..eda2bbf34c 100644 --- a/doc/src/sgml/plpython.sgml +++ b/doc/src/sgml/plpython.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.51 2010/07/08 18:42:12 petere Exp $ --> +<!-- doc/src/sgml/plpython.sgml --> <chapter id="plpython"> <title>PL/Python - Python Procedural Language</title> @@ -14,6 +14,7 @@ <para> To install PL/Python in a particular database, use + <literal>CREATE EXTENSION plpythonu</>, or from the shell command line use <literal>createlang plpythonu <replaceable>dbname</></literal> (but see also <xref linkend="plpython-python23">). </para> @@ -93,6 +94,17 @@ whether PL/Python for Python 2 or Python 3 or both are available. </para> + <tip> + <para> + The built variant depends on which Python version was found during + the installation or which version was explicitly set using + the <envar>PYTHON</envar> environment variable; + see <xref linkend="install-procedure">. To make both variants of + PL/Python available in one installation, the source tree has to be + configured and built twice. + </para> + </tip> + <para> This results in the following usage and migration strategy: @@ -136,8 +148,9 @@ <listitem> <para> Daredevils, who want to build a Python-3-only operating system - environment, can change the build scripts to - make <literal>plpythonu</literal> be equivalent + environment, can change the contents of + <link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link> + to make <literal>plpythonu</literal> be equivalent to <literal>plpython3u</literal>, keeping in mind that this would make their installation incompatible with most of the rest of the world. @@ -148,7 +161,7 @@ <para> See also the - document <ulink url="http://docs.python.org/dev/3.0/whatsnew/3.0.html">What's + document <ulink url="http://docs.python.org/py3k/whatsnew/3.0.html">What's New In Python 3.0</ulink> for more information about porting to Python 3. </para> @@ -343,7 +356,7 @@ $$ LANGUAGE plpythonu; <para> When the PostgreSQL return type is <type>bytea</type>, the return value will be converted to a string (Python 2) or bytes - (Python 3) using the respective Python builtins, with the + (Python 3) using the respective Python built-ins, with the result being converted <type>bytea</type>. </para> </listitem> @@ -352,7 +365,7 @@ $$ LANGUAGE plpythonu; <para> For all other PostgreSQL return types, the returned Python value is converted to a string using the Python - builtin <literal>str</literal>, and the result is passed to the + built-in <literal>str</literal>, and the result is passed to the input function of the PostgreSQL data type. </para> @@ -379,27 +392,16 @@ $$ LANGUAGE plpythonu; return type and the Python data type of the actual return object are not flagged; the value will be converted in any case. </para> - - <tip> - <para> - <application>PL/Python</application> functions cannot return - either type <type>RECORD</type> or <type>SETOF RECORD</type>. A - workaround is to write a <application>PL/pgSQL</application> - function that creates a temporary table, have it call the - <application>PL/Python</application> function to fill the table, - and then have the <application>PL/pgSQL</application> function - return the generic <type>RECORD</type> from the temporary table. - </para> - </tip> </sect2> <sect2> <title>Null, None</title> <para> If an SQL null value<indexterm><primary>null value</primary><secondary - sortas="PL/Python">PL/Python</secondary></indexterm> is passed to a + sortas="PL/Python">in PL/Python</secondary></indexterm> is passed to a function, the argument value will appear as <symbol>None</symbol> in - Python. The above function definition will return the wrong answer for null + Python. For example, the function definition of <function>pymax</function> + shown in <xref linkend="plpython-funcs"> will return the wrong answer for null inputs. We could add <literal>STRICT</literal> to the function definition to make <productname>PostgreSQL</productname> do something more reasonable: if a null value is passed, the function will not be called at all, @@ -582,10 +584,21 @@ $$ LANGUAGE plpythonu; </varlistentry> </variablelist> </para> + + <para> + Functions with <literal>OUT</literal> parameters are also supported. For example: +<programlisting> +CREATE FUNCTION multiout_simple(OUT i integer, OUT j integer) AS $$ +return (1, 2) +$$ LANGUAGE plpythonu; + +SELECT * FROM multiout_simple(); +</programlisting> + </para> </sect2> <sect2> - <title>Set-Returning Functions</title> + <title>Set-returning Functions</title> <para> A <application>PL/Python</application> function can also return sets of scalar or composite types. There are several ways to achieve this because @@ -598,7 +611,7 @@ CREATE TYPE greeting AS ( who text ); </programlisting> - + A set result can be returned from a: <variablelist> @@ -681,6 +694,19 @@ $$ LANGUAGE plpythonu; </varlistentry> </variablelist> </para> + + <para> + Set-returning functions with <literal>OUT</literal> parameters + (using <literal>RETURNS SETOF record</literal>) are also + supported. For example: +<programlisting> +CREATE FUNCTION multiout_simple_setof(n integer, OUT integer, OUT integer) RETURNS SETOF record AS $$ +return [(1, 2)] * n +$$ LANGUAGE plpythonu; + +SELECT * FROM multiout_simple_setof(3); +</programlisting> + </para> </sect2> </sect1> @@ -691,8 +717,8 @@ $$ LANGUAGE plpythonu; data between function calls. This variable is private static data. The global dictionary <varname>GD</varname> is public data, available to all Python functions within a session. Use with - care.<indexterm><primary>global data</><secondary>in - PL/Python</></indexterm> + care.<indexterm><primary>global data</> + <secondary>in PL/Python</></indexterm> </para> <para> @@ -740,8 +766,7 @@ $$ LANGUAGE plpythonu; <para> contains the event as a string: <literal>INSERT</>, <literal>UPDATE</>, - <literal>DELETE</>, <literal>TRUNCATE</>, - or <literal>UNKNOWN</>. + <literal>DELETE</>, or <literal>TRUNCATE</>. </para> </listitem> </varlistentry> @@ -750,8 +775,8 @@ $$ LANGUAGE plpythonu; <term><literal>TD["when"]</></term> <listitem> <para> - contains one of <literal>BEFORE</>, <literal>AFTER</>, - or <literal>UNKNOWN</>. + contains one of <literal>BEFORE</>, <literal>AFTER</>, or + <literal>INSTEAD OF</>. </para> </listitem> </varlistentry> @@ -760,8 +785,7 @@ $$ LANGUAGE plpythonu; <term><literal>TD["level"]</></term> <listitem> <para> - contains one of <literal>ROW</>, - <literal>STATEMENT</>, or <literal>UNKNOWN</>. + contains <literal>ROW</> or <literal>STATEMENT</>. </para> </listitem> </varlistentry> @@ -827,12 +851,14 @@ $$ LANGUAGE plpythonu; </para> <para> - If <literal>TD["when"]</literal> is <literal>BEFORE</> and + If <literal>TD["when"]</literal> is <literal>BEFORE</> or + <literal>INSTEAD OF</> and <literal>TD["level"]</literal> is <literal>ROW</>, you can return <literal>None</literal> or <literal>"OK"</literal> from the Python function to indicate the row is unmodified, - <literal>"SKIP"</> to abort the event, or <literal>"MODIFY"</> to - indicate you've modified the row. + <literal>"SKIP"</> to abort the event, or if <literal>TD["event"]</> + is <command>INSERT</> or <command>UPDATE</> you can return + <literal>"MODIFY"</> to indicate you've modified the new row. Otherwise the return value is ignored. </para> </sect1> @@ -847,6 +873,9 @@ $$ LANGUAGE plpythonu; <literal>plpy.<replaceable>foo</replaceable></literal>. </para> + <sect2> + <title>Database Access Functions</title> + <para> The <literal>plpy</literal> module provides two functions called <function>execute</function> and @@ -926,6 +955,210 @@ CREATE FUNCTION usesavedplan() RETURNS trigger AS $$ $$ LANGUAGE plpythonu; </programlisting> </para> + + </sect2> + + <sect2 id="plpython-trapping"> + <title>Trapping Errors</title> + + <para> + Functions accessing the database might encounter errors, which + will cause them to abort and raise an exception. Both + <function>plpy.execute</function> and + <function>plpy.prepare</function> can raise an instance of a subclass of + <literal>plpy.SPIError</literal>, which by default will terminate + the function. This error can be handled just like any other + Python exception, by using the <literal>try/except</literal> + construct. For example: +<programlisting> +CREATE FUNCTION try_adding_joe() RETURNS text AS $$ + try: + plpy.execute("INSERT INTO users(username) VALUES ('joe')") + except plpy.SPIError: + return "something went wrong" + else: + return "Joe added" +$$ LANGUAGE plpythonu; +</programlisting> + </para> + + <para> + The actual class of the exception being raised corresponds to the + specific condition that caused the error. Refer + to <xref linkend="errcodes-table"> for a list of possible + conditions. The module + <literal>plpy.spiexceptions</literal> defines an exception class + for each <productname>PostgreSQL</productname> condition, deriving + their names from the condition name. For + instance, <literal>division_by_zero</literal> + becomes <literal>DivisionByZero</literal>, <literal>unique_violation</literal> + becomes <literal>UniqueViolation</literal>, <literal>fdw_error</literal> + becomes <literal>FdwError</literal>, and so on. Each of these + exception classes inherits from <literal>SPIError</literal>. This + separation makes it easier to handle specific errors, for + instance: +<programlisting> +CREATE FUNCTION insert_fraction(numerator int, denominator int) RETURNS text AS $$ +from plpy import spiexceptions +try: + plan = plpy.prepare("INSERT INTO fractions (frac) VALUES ($1 / $2)", ["int", "int"]) + plpy.execute(plan, [numerator, denominator]) +except spiexceptions.DivisionByZero: + return "denominator cannot equal zero" +except spiexceptions.UniqueViolation: + return "already have that fraction" +except plpy.SPIError, e: + return "other error, SQLSTATE %s" % e.sqlstate +else: + return "fraction inserted" +$$ LANGUAGE plpythonu; +</programlisting> + Note that because all exceptions from + the <literal>plpy.spiexceptions</literal> module inherit + from <literal>SPIError</literal>, an <literal>except</literal> + clause handling it will catch any database access error. + </para> + + <para> + As an alternative way of handling different error conditions, you + can catch the <literal>SPIError</literal> exception and determine + the specific error condition inside the <literal>except</literal> + block by looking at the <literal>sqlstate</literal> attribute of + the exception object. This attribute is a string value containing + the <quote>SQLSTATE</quote> error code. This approach provides + approximately the same functionality + </para> + </sect2> + </sect1> + + <sect1 id="plpython-subtransaction"> + <title>Explicit Subtransactions</title> + + <para> + Recovering from errors caused by database access as described in + <xref linkend="plpython-trapping"> can lead to an undesirable + situation where some operations succeed before one of them fails, + and after recovering from that error the data is left in an + inconsistent state. PL/Python offers a solution to this problem in + the form of explicit subtransactions. + </para> + + <sect2> + <title>Subtransaction Context Managers</title> + + <para> + Consider a function that implements a transfer between two + accounts: +<programlisting> +CREATE FUNCTION transfer_funds() RETURNS void AS $$ +try: + plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'") + plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'") +except plpy.SPIError, e: + result = "error transferring funds: %s" % e.args +else: + result = "funds transferred correctly" +plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"]) +plpy.execute(plan, [result]) +$$ LANGUAGE plpythonu; +</programlisting> + If the second <literal>UPDATE</literal> statement results in an + exception being raised, this function will report the error, but + the result of the first <literal>UPDATE</literal> will + nevertheless be committed. In other words, the funds will be + withdrawn from Joe's account, but will not be transferred to + Mary's account. + </para> + + <para> + To avoid such issues, you can wrap your + <literal>plpy.execute</literal> calls in an explicit + subtransaction. The <literal>plpy</literal> module provides a + helper object to manage explicit subtransactions that gets created + with the <literal>plpy.subtransaction()</literal> function. + Objects created by this function implement the + <ulink url="http://docs.python.org/library/stdtypes.html#context-manager-types"> + context manager interface</ulink>. Using explicit subtransactions + we can rewrite our function as: +<programlisting> +CREATE FUNCTION transfer_funds2() RETURNS void AS $$ +try: + with plpy.subtransaction(): + plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'") + plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'") +except plpy.SPIError, e: + result = "error transferring funds: %s" % e.args +else: + result = "funds transferred correctly" +plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"]) +plpy.execute(plan, [result]) +$$ LANGUAGE plpythonu; +</programlisting> + Note that the use of <literal>try/catch</literal> is still + required. Otherwise the exception would propagate to the top of + the Python stack and would cause the whole function to abort with + a <productname>PostgreSQL</productname> error, so that the + <literal>operations</literal> table would not have any row + inserted into it. The subtransaction context manager does not + trap errors, it only assures that all database operations executed + inside its scope will be atomically committed or rolled back. A + rollback of the subtransaction block occurs on any kind of + exception exit, not only ones caused by errors originating from + database access. A regular Python exception raised inside an + explicit subtransaction block would also cause the subtransaction + to be rolled back. + </para> + </sect2> + + <sect2> + <title>Older Python Versions</title> + + <para> + Context managers syntax using the <literal>with</literal> keyword + is available by default in Python 2.6. If using PL/Python with an + older Python version, it is still possible to use explicit + subtransactions, although not as transparently. You can call the + subtransaction manager's <literal>__enter__</literal> and + <literal>__exit__</literal> functions using the + <literal>enter</literal> and <literal>exit</literal> convenience + aliases. The example function that transfers funds could be + written as: +<programlisting> +CREATE FUNCTION transfer_funds_old() RETURNS void AS $$ +try: + subxact = plpy.subtransaction() + subxact.enter() + try: + plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'") + plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'") + except: + import sys + subxact.exit(*sys.exc_info()) + raise + else: + subxact.exit(None, None, None) +except plpy.SPIError, e: + result = "error transferring funds: %s" % e.args +else: + result = "funds transferred correctly" + +plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"]) +plpy.execute(plan, [result]) +$$ LANGUAGE plpythonu; +</programlisting> + </para> + + <note> + <para> + Although context managers were implemented in Python 2.5, to use + the <literal>with</literal> syntax in that version you need to + use a <ulink + url="http://docs.python.org/release/2.5/ref/future.html">future + statement</ulink>. Because of implementation details, however, + you cannot use future statements in PL/Python functions. + </para> + </note> + </sect2> </sect1> <sect1 id="plpython-util"> @@ -943,8 +1176,8 @@ $$ LANGUAGE plpythonu; <function>plpy.fatal</function> actually raise a Python exception which, if uncaught, propagates out to the calling query, causing the current transaction or subtransaction to be aborted. - <literal>raise plpy.ERROR(<replaceable>msg</>)</literal> and - <literal>raise plpy.FATAL(<replaceable>msg</>)</literal> are + <literal>raise plpy.Error(<replaceable>msg</>)</literal> and + <literal>raise plpy.Fatal(<replaceable>msg</>)</literal> are equivalent to calling <function>plpy.error</function> and <function>plpy.fatal</function>, respectively. @@ -956,6 +1189,83 @@ $$ LANGUAGE plpythonu; <xref linkend="guc-client-min-messages"> configuration variables. See <xref linkend="runtime-config"> for more information. </para> + + <para> + Another set of utility functions are + <literal>plpy.quote_literal(<replaceable>string</>)</literal>, + <literal>plpy.quote_nullable(<replaceable>string</>)</literal>, and + <literal>plpy.quote_ident(<replaceable>string</>)</literal>. They + are equivalent to the built-in quoting functions described in <xref + linkend="functions-string">. They are useful when constructing + ad-hoc queries. A PL/Python equivalent of dynamic SQL from <xref + linkend="plpgsql-quote-literal-example"> would be: +<programlisting> +plpy.execute("UPDATE tbl SET %s = %s WHERE key = %s" % ( + plpy.quote_ident(colname), + plpy.quote_nullable(newvalue), + plpy.quote_literal(keyvalue))) +</programlisting> + </para> </sect1> + <sect1 id="plpython-envar"> + <title>Environment Variables</title> + + <para> + Some of the environment variables that are accepted by the Python + interpreter can also be used to affect PL/Python behavior. They + would need to be set in the environment of the main PostgreSQL + server process, for example in a start script. The available + environment variables depend on the version of Python; see the + Python documentation for details. At the time of this writing, the + following environment variables have an affect on PL/Python, + assuming an adequate Python version: + <itemizedlist> + <listitem> + <para><envar>PYTHONHOME</envar></para> + </listitem> + + <listitem> + <para><envar>PYTHONPATH</envar></para> + </listitem> + + <listitem> + <para><envar>PYTHONY2K</envar></para> + </listitem> + + <listitem> + <para><envar>PYTHONOPTIMIZE</envar></para> + </listitem> + + <listitem> + <para><envar>PYTHONDEBUG</envar></para> + </listitem> + + <listitem> + <para><envar>PYTHONVERBOSE</envar></para> + </listitem> + + <listitem> + <para><envar>PYTHONCASEOK</envar></para> + </listitem> + + <listitem> + <para><envar>PYTHONDONTWRITEBYTECODE</envar></para> + </listitem> + + <listitem> + <para><envar>PYTHONIOENCODING</envar></para> + </listitem> + + <listitem> + <para><envar>PYTHONUSERBASE</envar></para> + </listitem> + </itemizedlist> + + (It appears to be a Python implementation detail beyond the control + of PL/Python that some of the environment variables listed on + the <command>python</command> man page are only effective in a + command-line interpreter and not an embedded Python interpreter.) + </para> + </sect1> </chapter> diff --git a/doc/src/sgml/pltcl.sgml b/doc/src/sgml/pltcl.sgml index 5a425a8cb4..9f252e97ca 100644 --- a/doc/src/sgml/pltcl.sgml +++ b/doc/src/sgml/pltcl.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.50 2010/05/13 18:29:12 tgl Exp $ --> +<!-- doc/src/sgml/pltcl.sgml --> <chapter id="pltcl"> <title>PL/Tcl - Tcl Procedural Language</title> @@ -66,6 +66,7 @@ directory if Tcl support is specified in the configuration step of the installation procedure. To install <application>PL/Tcl</> and/or <application>PL/TclU</> in a particular database, use the + <command>CREATE EXTENSION</> command or the <command>createlang</command> program, for example <literal>createlang pltcl <replaceable>dbname</></literal> or <literal>createlang pltclu <replaceable>dbname</></literal>. @@ -214,14 +215,36 @@ $$ LANGUAGE pltcl; Sometimes it is useful to have some global data that is held between two calls to a function or is shared between different functions. - This is easily done since - all PL/Tcl functions executed in one session share the same - safe Tcl interpreter. So, any global Tcl variable is accessible to - all PL/Tcl function calls and will persist for the duration of the - SQL session. (Note that <application>PL/TclU</> functions likewise share - global data, but they are in a different Tcl interpreter and cannot - communicate with PL/Tcl functions.) + This is easily done in PL/Tcl, but there are some restrictions that + must be understood. </para> + + <para> + For security reasons, PL/Tcl executes functions called by any one SQL + role in a separate Tcl interpreter for that role. This prevents + accidental or malicious interference by one user with the behavior of + another user's PL/Tcl functions. Each such interpreter will have its own + values for any <quote>global</> Tcl variables. Thus, two PL/Tcl + functions will share the same global variables if and only if they are + executed by the same SQL role. In an application wherein a single + session executes code under multiple SQL roles (via <literal>SECURITY + DEFINER</> functions, use of <command>SET ROLE</>, etc) you may need to + take explicit steps to ensure that PL/Tcl functions can share data. To + do that, make sure that functions that should communicate are owned by + the same user, and mark them <literal>SECURITY DEFINER</>. You must of + course take care that such functions can't be used to do anything + unintended. + </para> + + <para> + All PL/TclU functions used in a session execute in the same Tcl + interpreter, which of course is distinct from the interpreter(s) + used for PL/Tcl functions. So global data is automatically shared + between PL/TclU functions. This is not considered a security risk + because all PL/TclU functions execute at the same trust level, + namely that of a database superuser. + </para> + <para> To help protect PL/Tcl functions from unintentionally interfering with each other, a global @@ -231,7 +254,9 @@ $$ LANGUAGE pltcl; <literal>GD</> be used for persistent private data of a function. Use regular Tcl global variables only for values that you specifically intend to be shared among - multiple functions. + multiple functions. (Note that the <literal>GD</> arrays are only + global within a particular interpreter, so they do not bypass the + security restrictions mentioned above.) </para> <para> @@ -278,7 +303,7 @@ $$ LANGUAGE pltcl; If the command is a <command>SELECT</> statement and no <replaceable>loop-body</> script is given, then only the first row of results are stored into Tcl variables; remaining rows, if any, are ignored. No storing occurs - if the + if the query returns no rows. (This case can be detected by checking the result of <function>spi_exec</function>.) For example: <programlisting> @@ -319,8 +344,8 @@ spi_exec -array C "SELECT * FROM pg_class" { <para> Prepares and saves a query plan for later execution. The saved plan will be retained for the life of the current - session.<indexterm><primary>preparing a query</><secondary>in - PL/Tcl</></> + session.<indexterm><primary>preparing a query</> + <secondary>in PL/Tcl</></> </para> <para> The query can use parameters, that is, placeholders for @@ -567,8 +592,8 @@ SELECT 'doesn''t' AS ret <term><varname>$TG_when</varname></term> <listitem> <para> - The string <literal>BEFORE</> or <literal>AFTER</> depending on the - type of trigger event. + The string <literal>BEFORE</>, <literal>AFTER</>, or + <literal>INSTEAD OF</>, depending on the type of trigger event. </para> </listitem> </varlistentry> @@ -641,10 +666,14 @@ SELECT 'doesn''t' AS ret the operation (<command>INSERT</>/<command>UPDATE</>/<command>DELETE</>) that fired the trigger will proceed normally. <literal>SKIP</> tells the trigger manager to silently suppress the operation for this row. If a list is returned, it tells PL/Tcl to - return a modified row to the trigger manager that will be inserted - instead of the one given in <varname>$NEW</>. (This works for <command>INSERT</> and <command>UPDATE</> - only.) Needless to say that all this is only meaningful when the trigger - is <literal>BEFORE</> and <command>FOR EACH ROW</>; otherwise the return value is ignored. + return a modified row to the trigger manager. This is only meaningful + for row-level <literal>BEFORE</> <command>INSERT</> or <command>UPDATE</> + triggers for which the modified row will be inserted instead of the one + given in <varname>$NEW</>; or for row-level <literal>INSTEAD OF</> + <command>INSERT</> or <command>UPDATE</> triggers where the returned row + is used to support <command>INSERT RETURNING</> and + <command>UPDATE RETURNING</> commands. The return value is ignored for + other types of triggers. </para> <para> @@ -683,7 +712,7 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab </sect1> <sect1 id="pltcl-unknown"> - <title>Modules and the <function>unknown</> command</title> + <title>Modules and the <function>unknown</> Command</title> <para> PL/Tcl has support for autoloading Tcl code when used. It recognizes a special table, <literal>pltcl_modules</>, which @@ -691,8 +720,8 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab exists, the module <literal>unknown</> is fetched from the table and loaded into the Tcl interpreter immediately before the first execution of a PL/Tcl function in a database session. (This - happens separately for PL/Tcl and PL/TclU, if both are used, - because separate interpreters are used for the two languages.) + happens separately for each Tcl interpreter, if more than one is + used in a session; see <xref linkend="pltcl-global">.) </para> <para> While the <literal>unknown</> module could actually contain any @@ -735,7 +764,7 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab different function definitions as long as the number of arguments or their types differ. Tcl, however, requires all procedure names to be distinct. PL/Tcl deals with this by making the internal Tcl procedure names contain - the object + the object ID of the function from the system table <structname>pg_proc</> as part of their name. Thus, <productname>PostgreSQL</productname> functions with the same name and different argument types will be different Tcl procedures, too. This diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index 3f2a6e0efc..ac1da22be8 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -1,13 +1,13 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/postgres.sgml,v 1.91 2010/02/22 11:47:30 heikki Exp $ --> +<!-- doc/src/sgml/postgres.sgml --> <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.2//EN" [ -<!entity % version SYSTEM "version.sgml"> +<!ENTITY % version SYSTEM "version.sgml"> %version; -<!entity % filelist SYSTEM "filelist.sgml"> +<!ENTITY % filelist SYSTEM "filelist.sgml"> %filelist; -<!entity reference SYSTEM "reference.sgml"> +<!ENTITY reference SYSTEM "reference.sgml"> ]> @@ -238,6 +238,7 @@ &sources; &nls; &plhandler; + &fdwhandler; &geqo; &indexam; &gist; @@ -258,7 +259,7 @@ &release; &contrib; &external-projects; - &cvs; + &sourcerepo; &docguide; &acronyms; diff --git a/doc/src/sgml/problems.sgml b/doc/src/sgml/problems.sgml index 886d24757b..3f79c6ef90 100644 --- a/doc/src/sgml/problems.sgml +++ b/doc/src/sgml/problems.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/problems.sgml,v 2.30 2009/04/27 16:27:36 momjian Exp $ --> +<!-- doc/src/sgml/problems.sgml --> <sect1 id="bug-reporting"> <title>Bug Reporting Guidelines</title> @@ -8,7 +8,7 @@ hear about it. Your bug reports play an important part in making <productname>PostgreSQL</productname> more reliable because even the utmost care cannot guarantee that every part of - <productname>PostgreSQL</productname> + <productname>PostgreSQL</productname> will work on every platform under every circumstance. </para> @@ -78,7 +78,7 @@ </listitem> </itemizedlist> - Here <quote>program</quote> refers to any executable, not only the backend server. + Here <quote>program</quote> refers to any executable, not only the backend process. </para> <para> @@ -97,7 +97,7 @@ </sect2> <sect2> - <title>What to report</title> + <title>What to Report</title> <para> The most important thing to remember about bug reporting is to state all @@ -228,8 +228,8 @@ If the function or the options do not exist then your version is more than old enough to warrant an upgrade. If you run a prepackaged version, such as RPMs, say so, including any - subversion the package might have. If you are talking about a CVS - snapshot, mention that, including its date and time. + subversion the package might have. If you are talking about a Git + snapshot, mention that, including the commit hash. </para> <para> @@ -280,9 +280,9 @@ When writing a bug report, please avoid confusing terminology. The software package in total is called <quote>PostgreSQL</quote>, sometimes <quote>Postgres</quote> for short. If you - are specifically talking about the backend server, mention that, do not + are specifically talking about the backend process, mention that, do not just say <quote>PostgreSQL crashes</quote>. A crash of a single - backend server process is quite different from crash of the parent + backend process is quite different from crash of the parent <quote>postgres</> process; please don't say <quote>the server crashed</> when you mean a single backend process went down, nor vice versa. Also, client programs such as the interactive frontend <quote><application>psql</application></quote> @@ -292,7 +292,7 @@ </sect2> <sect2> - <title>Where to report bugs</title> + <title>Where to Report Bugs</title> <para> In general, send bug reports to the bug report mailing list at @@ -301,7 +301,7 @@ message, perhaps parts of the error message. </para> - <para> + <para> Another method is to fill in the bug report web-form available at the project's <ulink url="http://www.postgresql.org/">web site</ulink>. @@ -316,7 +316,7 @@ reported privately to <email>security@postgresql.org</email>. </para> - <para> + <para> Do not send bug reports to any of the user mailing lists, such as <email>pgsql-sql@postgresql.org</email> or <email>pgsql-general@postgresql.org</email>. diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml index dc165f7253..d3de330916 100644 --- a/doc/src/sgml/protocol.sgml +++ b/doc/src/sgml/protocol.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/protocol.sgml,v 1.89 2010/06/07 02:01:08 itagaki Exp $ --> +<!-- doc/src/sgml/protocol.sgml --> <chapter id="protocol"> <title>Frontend/Backend Protocol</title> @@ -210,7 +210,7 @@ </para> <sect2> - <title>Start-Up</title> + <title>Start-up</title> <para> To begin a session, a frontend opens a connection to the server and sends @@ -314,6 +314,8 @@ the credential message.) If the credential is acceptable, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. + (This message type is only issued by pre-9.1 servers. It may + eventually be removed from the protocol specification.) </para> </listitem> </varlistentry> @@ -1033,12 +1035,25 @@ </para> <para> - The CopyInResponse and CopyOutResponse messages include fields that - inform the frontend of the number of columns per row and the format - codes being used for each column. (As of the present implementation, - all columns in a given <command>COPY</> operation will use the same - format, but the message design does not assume this.) + There is another Copy-related mode called Copy-both, which allows + high-speed bulk data transfer to <emphasis>and</> from the server. + Copy-both mode is initiated when a backend in walsender mode + executes a <command>START_REPLICATION</command> statement. The + backend sends a CopyBothResponse message to the frontend. Both + the backend and the frontend may then send CopyData messages + until the connection is terminated. See <xref + linkend="protocol-replication">. </para> + + <para> + The CopyInResponse, CopyOutResponse and CopyBothResponse messages + include fields that inform the frontend of the number of columns + per row and the format codes being used for each column. (As of + the present implementation, all columns in a given <command>COPY</> + operation will use the same format, but the message design does not + assume this.) + </para> + </sect2> <sect2 id="protocol-async"> @@ -1079,27 +1094,27 @@ <para> At present there is a hard-wired set of parameters for which ParameterStatus will be generated: they are - <literal>server_version</>, - <literal>server_encoding</>, - <literal>client_encoding</>, - <literal>application_name</>, - <literal>is_superuser</>, - <literal>session_authorization</>, - <literal>DateStyle</>, - <literal>IntervalStyle</>, - <literal>TimeZone</>, - <literal>integer_datetimes</>, and - <literal>standard_conforming_strings</>. - (<literal>server_encoding</>, <literal>TimeZone</>, and - <literal>integer_datetimes</> were not reported by releases before 8.0; - <literal>standard_conforming_strings</> was not reported by releases + <varname>server_version</>, + <varname>server_encoding</>, + <varname>client_encoding</>, + <varname>application_name</>, + <varname>is_superuser</>, + <varname>session_authorization</>, + <varname>DateStyle</>, + <varname>IntervalStyle</>, + <varname>TimeZone</>, + <varname>integer_datetimes</>, and + <varname>standard_conforming_strings</>. + (<varname>server_encoding</>, <varname>TimeZone</>, and + <varname>integer_datetimes</> were not reported by releases before 8.0; + <varname>standard_conforming_strings</> was not reported by releases before 8.1; - <literal>IntervalStyle</> was not reported by releases before 8.4; - <literal>application_name</> was not reported by releases before 9.0.) + <varname>IntervalStyle</> was not reported by releases before 8.4; + <varname>application_name</> was not reported by releases before 9.0.) Note that - <literal>server_version</>, - <literal>server_encoding</> and - <literal>integer_datetimes</> + <varname>server_version</>, + <varname>server_encoding</> and + <varname>integer_datetimes</> are pseudo-parameters that cannot change after startup. This set might change in the future, or even become configurable. Accordingly, a frontend should simply ignore ParameterStatus for @@ -1302,7 +1317,7 @@ The commands accepted in walsender mode are: <listitem> <para> Requests the server to identify itself. Server replies with a result - set of a single row, containing two fields: + set of a single row, containing three fields: </para> <para> @@ -1331,6 +1346,19 @@ The commands accepted in walsender mode are: </para> </listitem> </varlistentry> + + <varlistentry> + <term> + xlogpos + </term> + <listitem> + <para> + Current xlog write location. Useful to get a known location in the + transaction log where streaming can start. + </para> + </listitem> + </varlistentry> + </variablelist> </para> </listitem> @@ -1344,7 +1372,7 @@ The commands accepted in walsender mode are: WAL position <replaceable>XXX</>/<replaceable>XXX</>. The server can reply with an error, e.g. if the requested section of WAL has already been recycled. On success, server responds with a - CopyOutResponse message, and then starts to stream WAL to the frontend. + CopyBothResponse message, and then starts to stream WAL to the frontend. WAL will continue to be streamed until the connection is broken; no further commands will be accepted. </para> @@ -1443,6 +1471,294 @@ The commands accepted in walsender mode are: shutdown), it will send a CommandComplete message before exiting. This might not happen during an abnormal shutdown, of course. </para> + + <para> + The receiving process can send replies back to the sender at any time, + using one of the following message formats (also in the payload of a + CopyData message): + </para> + + <para> + <variablelist> + <varlistentry> + <term> + Standby status update (F) + </term> + <listitem> + <para> + <variablelist> + <varlistentry> + <term> + Byte1('r') + </term> + <listitem> + <para> + Identifies the message as a receiver status update. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + Byte8 + </term> + <listitem> + <para> + The location of the last WAL byte + 1 received and written to disk + in the standby, in XLogRecPtr format. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + Byte8 + </term> + <listitem> + <para> + The location of the last WAL byte + 1 flushed to disk in + the standby, in XLogRecPtr format. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + Byte8 + </term> + <listitem> + <para> + The location of the last WAL byte + 1 applied in the standby, in + XLogRecPtr format. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + Byte8 + </term> + <listitem> + <para> + The server's system clock at the time of transmission, + given in TimestampTz format. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <para> + <variablelist> + <varlistentry> + <term> + Hot Standby feedback message (F) + </term> + <listitem> + <para> + <variablelist> + <varlistentry> + <term> + Byte1('h') + </term> + <listitem> + <para> + Identifies the message as a Hot Standby feedback message. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + Byte8 + </term> + <listitem> + <para> + The server's system clock at the time of transmission, + given in TimestampTz format. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + Byte4 + </term> + <listitem> + <para> + The standby's current xmin. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + Byte4 + </term> + <listitem> + <para> + The standby's current epoch. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>BASE_BACKUP [<literal>LABEL</literal> <replaceable>'label'</replaceable>] [<literal>PROGRESS</literal>] [<literal>FAST</literal>] [<literal>WAL</literal>] [<literal>NOWAIT</literal>]</term> + <listitem> + <para> + Instructs the server to start streaming a base backup. + The system will automatically be put in backup mode before the backup + is started, and taken out of it when the backup is complete. The + following options are accepted: + <variablelist> + <varlistentry> + <term><literal>LABEL</literal> <replaceable>'label'</replaceable></term> + <listitem> + <para> + Sets the label of the backup. If none is specified, a backup label + of <literal>base backup</literal> will be used. The quoting rules + for the label are the same as a standard SQL string with + <xref linkend="guc-standard-conforming-strings"> turned on. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>PROGRESS</></term> + <listitem> + <para> + Request information required to generate a progress report. This will + send back an approximate size in the header of each tablespace, which + can be used to calculate how far along the stream is done. This is + calculated by enumerating all the file sizes once before the transfer + is even started, and may as such have a negative impact on the + performance - in particular it may take longer before the first data + is streamed. Since the database files can change during the backup, + the size is only approximate and may both grow and shrink between + the time of approximation and the sending of the actual files. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>FAST</></term> + <listitem> + <para> + Request a fast checkpoint. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>WAL</literal></term> + <listitem> + <para> + Include the necessary WAL segments in the backup. This will include + all the files between start and stop backup in the + <filename>pg_xlog</filename> directory of the base directory tar + file. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>NOWAIT</literal></term> + <listitem> + <para> + By default, the backup will wait until the last required xlog + segment has been archived, or emit a warning if log archiving is + not enabled. Specifying <literal>NOWAIT</literal> disables both + the waiting and the warning, leaving the client responsible for + ensuring the required log is available. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + <para> + When the backup is started, the server will first send two + ordinary result sets, followed by one or more CopyResponse + results. + </para> + <para> + The first ordinary result set contains the starting position of the + backup, given in XLogRecPtr format as a single column in a single row. + </para> + <para> + The second ordinary result set has one row for each tablespace. + The fields in this row are: + <variablelist> + <varlistentry> + <term>spcoid</term> + <listitem> + <para> + The oid of the tablespace, or <literal>NULL</> if it's the base + directory. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>spclocation</term> + <listitem> + <para> + The full path of the tablespace directory, or <literal>NULL</> + if it's the base directory. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>size</term> + <listitem> + <para> + The approximate size of the tablespace, if progress report has + been requested; otherwise it's <literal>NULL</>. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + <para> + After the second regular result set, one or more CopyResponse results + will be sent, one for PGDATA and one for each additional tablespace other + than <literal>pg_default</> and <literal>pg_global</>. The data in + the CopyResponse results will be a tar format (using ustar00 + extensions) dump of the tablespace contents. After the tar data is + complete, a final ordinary result set will be sent. + </para> + + <para> + The tar archive for the data directory and each tablespace will contain + all files in the directories, regardless of whether they are + <productname>PostgreSQL</> files or other files added to the same + directory. The only excluded files are: + <itemizedlist spacing="compact" mark="bullet"> + <listitem> + <para> + <filename>postmaster.pid</> + </para> + </listitem> + <listitem> + <para> + <filename>pg_xlog</>, including subdirectories. If the backup is run + with wal files included, a synthesized version of pg_xlog will be + included, but it will only contain the files necessary for the + backup to work, not the rest of the contents. + </para> + </listitem> + </itemizedlist> + Owner, group and file mode are set if the underlying filesystem on + the server supports it. + </para> + <para> + Once all tablespaces have been sent, a final regular result set will + be sent. This result set contains the end position of the + backup, given in XLogRecPtr format as a single column in a single row. + </para> </listitem> </varlistentry> </variablelist> @@ -2696,6 +3012,79 @@ CopyOutResponse (B) <varlistentry> <term> +CopyBothResponse (B) +</term> +<listitem> +<para> + +<variablelist> +<varlistentry> +<term> + Byte1('W') +</term> +<listitem> +<para> + Identifies the message as a Start Copy Both response. + This message is used only for Streaming Replication. +</para> +</listitem> +</varlistentry> +<varlistentry> +<term> + Int32 +</term> +<listitem> +<para> + Length of message contents in bytes, including self. +</para> +</listitem> +</varlistentry> +<varlistentry> +<term> + Int8 +</term> +<listitem> +<para> + 0 indicates the overall <command>COPY</command> format + is textual (rows separated by newlines, columns + separated by separator characters, etc). 1 indicates + the overall copy format is binary (similar to DataRow + format). See <xref linkend="sql-copy"> for more information. +</para> +</listitem> +</varlistentry> +<varlistentry> +<term> + Int16 +</term> +<listitem> +<para> + The number of columns in the data to be copied + (denoted <replaceable>N</> below). +</para> +</listitem> +</varlistentry> +<varlistentry> +<term> + Int16[<replaceable>N</>] +</term> +<listitem> +<para> + The format codes to be used for each column. + Each must presently be zero (text) or one (binary). + All must be zero if the overall copy format is textual. +</para> +</listitem> +</varlistentry> +</variablelist> + +</para> +</listitem> +</varlistentry> + + +<varlistentry> +<term> DataRow (B) </term> <listitem> diff --git a/doc/src/sgml/queries.sgml b/doc/src/sgml/queries.sgml index 26bc224384..b3cf39a39b 100644 --- a/doc/src/sgml/queries.sgml +++ b/doc/src/sgml/queries.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/queries.sgml,v 1.58 2010/07/03 02:57:46 rhaas Exp $ --> +<!-- doc/src/sgml/queries.sgml --> <chapter id="queries"> <title>Queries</title> @@ -472,7 +472,7 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r (1 row) </screen> This is because a restriction placed in the <literal>ON</> - clause is processed <emphasis>before</> the join, while + clause is processed <emphasis>before</> the join, while a restriction placed in the <literal>WHERE</> clause is processed <emphasis>after</> the join. </para> @@ -686,8 +686,9 @@ SELECT * AS t1(proname name, prosrc text) WHERE proname LIKE 'bytea%'; </programlisting> - The <literal>dblink</> function executes a remote query (see - <filename>contrib/dblink</>). It is declared to return + The <xref linkend="CONTRIB-DBLINK-FUNCTION"> function + (part of the <xref linkend="dblink"> module>) executes + a remote query. It is declared to return <type>record</> since it might be used for any kind of query. The actual column set must be specified in the calling query so that the parser knows, for example, what <literal>*</> should @@ -886,10 +887,7 @@ SELECT product_id, p.name, (sum(s.units) * p.price) AS sales In this example, the columns <literal>product_id</literal>, <literal>p.name</literal>, and <literal>p.price</literal> must be in the <literal>GROUP BY</> clause since they are referenced in - the query select list. (Depending on how the products - table is set up, name and price might be fully dependent on the - product ID, so the additional groupings could theoretically be - unnecessary, though this is not implemented.) The column + the query select list (but see below). The column <literal>s.units</> does not have to be in the <literal>GROUP BY</> list since it is only used in an aggregate expression (<literal>sum(...)</literal>), which represents the sales @@ -897,6 +895,18 @@ SELECT product_id, p.name, (sum(s.units) * p.price) AS sales all sales of the product. </para> + <indexterm><primary>functional dependency</primary></indexterm> + + <para> + If the products table is set up so that, say, + <literal>product_id</literal> is the primary key, then it would be + enough to group by <literal>product_id</literal> in the above example, + since name and price would be <firstterm>functionally + dependent</firstterm> on the product ID, and so there would be no + ambiguity about which name and price value to return for each product + ID group. + </para> + <para> In strict SQL, <literal>GROUP BY</> can only group by columns of the source table but <productname>PostgreSQL</productname> extends @@ -970,7 +980,7 @@ SELECT product_id, p.name, (sum(s.units) * (p.price - p.cost)) AS profit </sect2> <sect2 id="queries-window"> - <title>Window Function Processing</> + <title>Window Function Processing</title> <indexterm zone="queries-window"> <primary>window function</primary> @@ -1130,7 +1140,7 @@ SELECT a "value", b + c AS sum FROM ... <para> The naming of output columns here is different from that done in the <literal>FROM</> clause (see <xref - linkend="queries-table-aliases">). It is possible + linkend="queries-table-aliases">). It is possible to rename the same column twice, but the name assigned in the select list is the one that will be passed on. </para> @@ -1160,9 +1170,12 @@ SELECT DISTINCT <replaceable>select_list</replaceable> ... can be used to specify the default behavior of retaining all rows.) </para> + <indexterm> + <primary>null value</> + <secondary sortas="DISTINCT">in DISTINCT</> + </indexterm> + <para> - <indexterm><primary>null value</><secondary sortas="DISTINCT">in - DISTINCT</></indexterm> Obviously, two rows are considered distinct if they differ in at least one column value. Null values are considered equal in this comparison. @@ -1516,7 +1529,7 @@ SELECT <replaceable>select_list</replaceable> FROM <replaceable>table_expression <sect1 id="queries-with"> - <title><literal>WITH</literal> Queries</title> + <title><literal>WITH</literal> Queries (Common Table Expressions)</title> <indexterm zone="queries-with"> <primary>WITH</primary> @@ -1529,10 +1542,23 @@ SELECT <replaceable>select_list</replaceable> FROM <replaceable>table_expression </indexterm> <para> - <literal>WITH</> provides a way to write subqueries for use in a larger - <literal>SELECT</> query. The subqueries can be thought of as defining - temporary tables that exist just for this query. One use of this feature - is to break down complicated queries into simpler parts. An example is: + <literal>WITH</> provides a way to write auxiliary statements for use in a + larger query. These statements, which are often referred to as Common + Table Expressions or <acronym>CTE</acronym>s, can be thought of as defining + temporary tables that exist just for one query. Each auxiliary statement + in a <literal>WITH</> clause can be a <command>SELECT</>, + <command>INSERT</>, <command>UPDATE</>, or <command>DELETE</>; and the + <literal>WITH</> clause itself is attached to a primary statement that can + also be a <command>SELECT</>, <command>INSERT</>, <command>UPDATE</>, or + <command>DELETE</>. + </para> + + <sect2 id="queries-with-select"> + <title><command>SELECT</> in <literal>WITH</></title> + + <para> + The basic value of <command>SELECT</> in <literal>WITH</> is to + break down complicated queries into simpler parts. An example is: <programlisting> WITH regional_sales AS ( @@ -1554,8 +1580,13 @@ GROUP BY region, product; </programlisting> which displays per-product sales totals in only the top sales regions. + The <literal>WITH</> clause defines two auxiliary statements named + <structname>regional_sales</> and <structname>top_regions</>, + where the output of <structname>regional_sales</> is used in + <structname>top_regions</> and the output of <structname>top_regions</> + is used in the primary <command>SELECT</> query. This example could have been written without <literal>WITH</>, - but we'd have needed two levels of nested sub-SELECTs. It's a bit + but we'd have needed two levels of nested sub-<command>SELECT</command>s. It's a bit easier to follow this way. </para> @@ -1768,7 +1799,9 @@ SELECT n FROM t LIMIT 100; fetched by the parent query. Using this trick in production is not recommended, because other systems might work differently. Also, it usually won't work if you make the outer query sort the recursive query's - results or join them to some other table. + results or join them to some other table, because in such cases the + outer query will usually try to fetch all of the <literal>WITH</> query's + output anyway. </para> <para> @@ -1782,12 +1815,166 @@ SELECT n FROM t LIMIT 100; However, the other side of this coin is that the optimizer is less able to push restrictions from the parent query down into a <literal>WITH</> query than an ordinary sub-query. The <literal>WITH</> query will generally be - evaluated as stated, without suppression of rows that the parent query + evaluated as written, without suppression of rows that the parent query might discard afterwards. (But, as mentioned above, evaluation might stop early if the reference(s) to the query demand only a limited number of rows.) </para> + <para> + The examples above only show <literal>WITH</> being used with + <command>SELECT</>, but it can be attached in the same way to + <command>INSERT</>, <command>UPDATE</>, or <command>DELETE</>. + In each case it effectively provides temporary table(s) that can + be referred to in the main command. + </para> + </sect2> + + <sect2 id="queries-with-modifying"> + <title>Data-Modifying Statements in <literal>WITH</></title> + + <para> + You can use data-modifying statements (<command>INSERT</>, + <command>UPDATE</>, or <command>DELETE</>) in <literal>WITH</>. This + allows you to perform several different operations in the same query. + An example is: + +<programlisting> +WITH moved_rows AS ( + DELETE FROM products + WHERE + "date" >= '2010-10-01' AND + "date" < '2010-11-01' + RETURNING * +) +INSERT INTO products_log +SELECT * FROM moved_rows; +</programlisting> + + This query effectively moves rows from <structname>products</> to + <structname>products_log</>. The <command>DELETE</> in <literal>WITH</> + deletes the specified rows from <structname>products</>, returning their + contents by means of its <literal>RETURNING</> clause; and then the + primary query reads that output and inserts it into + <structname>products_log</>. + </para> |