diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-02-08 16:08:41 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-02-08 16:13:22 -0500 |
commit | d9572c4e3b474031060189050e14ef384b94e001 (patch) | |
tree | 07646762f4086b94a69b9fc215734d2bccade5db /doc/src | |
parent | 414c5a2ea65cbd38d79ffdf9b1fde7cc75c134e0 (diff) | |
download | postgresql-d9572c4e3b474031060189050e14ef384b94e001.tar.gz postgresql-d9572c4e3b474031060189050e14ef384b94e001.zip |
Core support for "extensions", which are packages of SQL objects.
This patch adds the server infrastructure to support extensions.
There is still one significant loose end, namely how to make it play nice
with pg_upgrade, so I am not yet committing the changes that would make
all the contrib modules depend on this feature.
In passing, fix a disturbingly large amount of breakage in
AlterObjectNamespace() and callers.
Dimitri Fontaine, reviewed by Anssi Kääriäinen,
Itagaki Takahiro, Tom Lane, and numerous others
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/acronyms.sgml | 2 | ||||
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 195 | ||||
-rw-r--r-- | doc/src/sgml/extend.sgml | 715 | ||||
-rw-r--r-- | doc/src/sgml/ref/allfiles.sgml | 3 | ||||
-rw-r--r-- | doc/src/sgml/ref/alter_extension.sgml | 98 | ||||
-rw-r--r-- | doc/src/sgml/ref/comment.sgml | 1 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_extension.sgml | 118 | ||||
-rw-r--r-- | doc/src/sgml/ref/drop_extension.sgml | 121 | ||||
-rw-r--r-- | doc/src/sgml/ref/psql-ref.sgml | 14 | ||||
-rw-r--r-- | doc/src/sgml/reference.sgml | 3 | ||||
-rw-r--r-- | doc/src/sgml/release-9.0.sgml | 5 | ||||
-rw-r--r-- | doc/src/sgml/xfunc.sgml | 331 |
12 files changed, 1296 insertions, 310 deletions
diff --git a/doc/src/sgml/acronyms.sgml b/doc/src/sgml/acronyms.sgml index d1ef489e366..8f6752f05d7 100644 --- a/doc/src/sgml/acronyms.sgml +++ b/doc/src/sgml/acronyms.sgml @@ -485,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> diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index f31662c2720..24aa22cbced 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -144,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> @@ -2680,6 +2685,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> @@ -2848,6 +2868,101 @@ </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 string for the extension, or <literal>NULL</> if none</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> + + <sect1 id="catalog-pg-foreign-data-wrapper"> <title><structname>pg_foreign_data_wrapper</structname></title> @@ -6192,6 +6307,11 @@ <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-cursors"><structname>pg_cursors</structname></link></entry> <entry>open cursors</entry> </row> @@ -6286,6 +6406,81 @@ </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. This view can only + be read by superusers. 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>version</structfield></entry> + <entry><type>text</type></entry> + <entry>Version string from the extension's control file</entry> + </row> + + <row> + <entry><structfield>installed</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>schema</structfield></entry> + <entry><type>name</type></entry> + <entry>Name of the schema where the extension is installed, + or <literal>NULL</literal> if not installed</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>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-cursors"> <title><structname>pg_cursors</structname></title> diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml index 2033ae21ba5..206eb6b9017 100644 --- a/doc/src/sgml/extend.sgml +++ b/doc/src/sgml/extend.sgml @@ -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> @@ -273,67 +278,701 @@ &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 datatype 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 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> + + <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/contrib</literal> directory. There + must also be a <acronym>SQL</> script file, which typically is + named after the extension with a suffix of <literal>.sql</>, and is also + placed in the <literal>SHAREDIR/contrib</literal> directory; but these + defaults can be overridden by the control file. + </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>script</varname> (<type>string</type>)</term> + <listitem> + <para> + The filename of the extension's <acronym>SQL</> script. + Defaults to the same name as the control file, but with the + <literal>.sql</literal> extension. Unless an absolute path is + given, the name is relative to the <literal>SHAREDIR/contrib</literal> + directory. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><varname>version</varname> (<type>string</type>)</term> + <listitem> + <para> + The version of the extension. Any string can be given. + </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. + </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>encoding</varname> (<type>string</type>)</term> + <listitem> + <para> + The character set encoding used by the script file. This should + be specified if the script file contains any non-ASCII characters. + Otherwise the script will be assumed to be in the encoding of the + database it is loaded into. + </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> + An extension's <acronym>SQL</> script file 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 file is implicitly executed within a transaction block. + </para> + + <para> + While the script file can contain any characters allowed by the specified + encoding, the control file should contain only plain ASCII, because there + is no way for <productname>PostgreSQL</> to know what encoding the + 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 <varname>comment</> parameter + in the control file, but instead use <command>COMMENT ON EXTENSION</> + within the 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 structures - (<acronym>POD</>). This is necessary because backend errors - generate a distant <function>longjmp()</> 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 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.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' +version = '0.1.2' +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.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 then 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_built = isbn_issn.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>MODULEDIR</varname></term> + <listitem> + <para> + subdirectory into which EXTENSION, DATA and DOCS files should be + installed (if not set, default is <literal>contrib</literal>) + </para> + </listitem> + </varlistentry> + + <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/$MODULEDIR</literal> + </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/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml index c44d11ef91b..ba85cae0837 100644 --- a/doc/src/sgml/ref/allfiles.sgml +++ b/doc/src/sgml/ref/allfiles.sgml @@ -11,6 +11,7 @@ Complete list of usable sgml source files in this directory. <!entity alterDatabase system "alter_database.sgml"> <!entity alterDefaultPrivileges system "alter_default_privileges.sgml"> <!entity alterDomain system "alter_domain.sgml"> +<!entity alterExtension system "alter_extension.sgml"> <!entity alterForeignDataWrapper system "alter_foreign_data_wrapper.sgml"> <!entity alterForeignTable system "alter_foreign_table.sgml"> <!entity alterFunction system "alter_function.sgml"> @@ -50,6 +51,7 @@ Complete list of usable sgml source files in this directory. <!entity createConversion system "create_conversion.sgml"> <!entity createDatabase system "create_database.sgml"> <!entity createDomain system "create_domain.sgml"> +<!entity createExtension system "create_extension.sgml"> <!entity createForeignDataWrapper system "create_foreign_data_wrapper.sgml"> <!entity createForeignTable system "create_foreign_table.sgml"> <!entity createFunction system "create_function.sgml"> @@ -86,6 +88,7 @@ Complete list of usable sgml source files in this directory. <!entity dropConversion system "drop_conversion.sgml"> <!entity dropDatabase system "drop_database.sgml"> <!entity dropDomain system "drop_domain.sgml"> +<!entity dropExtension system "drop_extension.sgml"> <!entity dropForeignDataWrapper system "drop_foreign_data_wrapper.sgml"> <!entity dropForeignTable system "drop_foreign_table.sgml"> <!entity dropFunction system "drop_function.sgml"> diff --git a/doc/src/sgml/ref/alter_extension.sgml b/doc/src/sgml/ref/alter_extension.sgml new file mode 100644 index 00000000000..1b29d274cd6 --- /dev/null +++ b/doc/src/sgml/ref/alter_extension.sgml @@ -0,0 +1,98 @@ +<!-- +doc/src/sgml/ref/alter_extension.sgml +PostgreSQL documentation +--> + +<refentry id="SQL-ALTEREXTENSION"> + <refmeta> + <refentrytitle>ALTER EXTENSION</refentrytitle> + <manvolnum>7</manvolnum> + <refmiscinfo>SQL - Language Statements</refmiscinfo> + </refmeta> + + <refnamediv> + <refname>ALTER EXTENSION</refname> + <refpurpose> + change the definition of an extension + </refpurpose> + </refnamediv> + + <indexterm zone="sql-alterextension"> + <primary>ALTER EXTENSION</primary> + </indexterm> + + <refsynopsisdiv> +<synopsis> +ALTER EXTENSION <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable> +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>ALTER EXTENSION</command> changes the definition of an existing extension. + Currently there is only one subform: + + <variablelist> + <varlistentry> + <term><literal>SET SCHEMA</literal></term> + <listitem> + <para> + This form moves the extension's objects into another schema. The + extension has to be <firstterm>relocatable</> for this command to + succeed. See <xref linkend="extend-extensions"> for details. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <para> + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">name</replaceable></term> + <listitem> + <para> + The name of an installed extension. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">new_schema</replaceable></term> + <listitem> + <para> + The new schema for the extension. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> + + <refsect1> + <title>Examples</title> + + <para> + To change the schema of the extension <literal>hstore</literal> + to <literal>utils</literal>: +<programlisting> +ALTER EXTENSION hstore SET SCHEMA utils; +</programlisting> + </para> + </refsect1> + + <refsect1 id="SQL-ALTEREXTENSION-see-also"> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="sql-createextension"></member> + <member><xref linkend="sql-dropextension"></member> + </simplelist> + </refsect1> +</refentry> diff --git a/doc/src/sgml/ref/comment.sgml b/doc/src/sgml/ref/comment.sgml index f1a1605df3c..e1fe0c16f9a 100644 --- a/doc/src/sgml/ref/comment.sgml +++ b/doc/src/sgml/ref/comment.sgml @@ -31,6 +31,7 @@ COMMENT ON CONVERSION <replaceable class="PARAMETER">object_name</replaceable> | DATABASE <replaceable class="PARAMETER">object_name</replaceable> | DOMAIN <replaceable class="PARAMETER">object_name</replaceable> | + EXTENSION <replaceable class="PARAMETER">object_name</replaceable> | FOREIGN TABLE <replaceable class="PARAMETER">object_name</replaceable> | FUNCTION <replaceable class="PARAMETER">function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) | INDEX <replaceable class="PARAMETER">object_name</replaceable> | diff --git a/doc/src/sgml/ref/create_extension.sgml b/doc/src/sgml/ref/create_extension.sgml new file mode 100644 index 00000000000..961cab3839e --- /dev/null +++ b/doc/src/sgml/ref/create_extension.sgml @@ -0,0 +1,118 @@ +<!-- +doc/src/sgml/ref/create_extension.sgml +PostgreSQL documentation +--> + +<refentry id="SQL-CREATEEXTENSION"> + <refmeta> + <refentrytitle>CREATE EXTENSION</refentrytitle> + <manvolnum>7</manvolnum> + <refmiscinfo>SQL - Language Statements</refmiscinfo> + </refmeta> + + <refnamediv> + <refname>CREATE EXTENSION</refname> + <refpurpose>install an extension</refpurpose> + </refnamediv> + + <indexterm zone="sql-createextension"> + <primary>CREATE EXTENSION</primary> + </indexterm> + + <refsynopsisdiv> +<synopsis> +CREATE EXTENSION <replaceable class="parameter">extension_name</replaceable> + [ WITH ] [ SCHEMA [=] <replaceable class="parameter">schema</replaceable> ] +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>CREATE EXTENSION</command> loads a new extension into the current + database. There must not be an extension of the same name already loaded. + </para> + + <para> + Loading an extension essentially amounts to running the extension's script + file. The script will typically create new <acronym>SQL</> objects such as + functions, data types, operators and index support methods. + <command>CREATE EXTENSION</command> additionally records the identities + of all the created objects, so that they can be dropped again if + <command>DROP EXTENSION</command> is issued. + </para> + + <para> + For information about writing new extensions, see + <xref linkend="extend-extensions">. + </para> + + <para> + Only superusers can execute <command>CREATE EXTENSION</command>. + </para> + + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class="parameter">extension_name</replaceable></term> + <listitem> + <para> + The name of the extension to be + installed. <productname>PostgreSQL</productname> will create the + extension using details from the file + <literal>SHAREDIR/contrib/</literal><replaceable class="parameter">extension</replaceable><literal>.control</literal>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="parameter">schema</replaceable></term> + <listitem> + <para> + The name of the schema in which to install the extension's + objects, given that the extension allows its contents to be + relocated. The named schema must already exist. + If not specified, and the extension's control file does not specify a + schema either, the current default object creation schema is used. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + + <para> + Install the <link linkend="hstore">hstore</link> extension into the + current database: +<programlisting> +CREATE EXTENSION hstore; +</programlisting> + </para> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>CREATE EXTENSION</command> is a <productname>PostgreSQL</> + extension. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="sql-alterextension"></member> + <member><xref linkend="sql-dropextension"></member> + </simplelist> + </refsect1> + +</refentry> diff --git a/doc/src/sgml/ref/drop_extension.sgml b/doc/src/sgml/ref/drop_extension.sgml new file mode 100644 index 00000000000..1e09ec4c7a7 --- /dev/null +++ b/doc/src/sgml/ref/drop_extension.sgml @@ -0,0 +1,121 @@ +<!-- +doc/src/sgml/ref/drop_extension.sgml +PostgreSQL documentation +--> + +<refentry id="SQL-DROPEXTENSION"> + <refmeta> + <refentrytitle>DROP EXTENSION</refentrytitle> + <manvolnum>7</manvolnum> + <refmiscinfo>SQL - Language Statements</refmiscinfo> + </refmeta> + + <refnamediv> + <refname>DROP EXTENSION</refname> + <refpurpose>remove an extension</refpurpose> + </refnamediv> + + <indexterm zone="sql-dropextension"> + <primary>DROP EXTENSION</primary> + </indexterm> + + <refsynopsisdiv> +<synopsis> +DROP EXTENSION [ IF EXISTS ] <replaceable class="PARAMETER">extension_name</replaceable> [, ...] [ CASCADE | RESTRICT ] +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>DROP EXTENSION</command> removes extensions from the database. + Dropping an extension causes its component objects to be dropped as well. + </para> + + <para> + An extension can only be dropped by a superuser. + </para> + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + + <varlistentry> + <term><literal>IF EXISTS</literal></term> + <listitem> + <para> + Do not throw an error if the extension does not exist. A notice is issued + in this case. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">extension_name</replaceable></term> + <listitem> + <para> + The name of an installed extension. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>CASCADE</literal></term> + <listitem> + <para> + Automatically drop objects that depend on the extension. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>RESTRICT</literal></term> + <listitem> + <para> + Refuse to drop the extension if any objects depend on it (other than + its own member objects and other extensions listed in the same + <command>DROP</> command). This is the default. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Examples</title> + + <para> + To remove the extension <literal>hstore</literal> from the current + database: +<programlisting> +DROP EXTENSION hstore; +</programlisting> + This command will fail if any of <literal>hstore</literal>'s objects + are in use in the database, for example if any tables have columns + of the <type>hstore</> type. Add the <literal>CASCADE</> option to + forcibly remove those dependent objects as well. + </para> + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + <command>DROP EXTENSION</command> is a <productname>PostgreSQL</> + extension. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="sql-createextension"></member> + <member><xref linkend="sql-alterextension"></member> + </simplelist> + </refsect1> + +</refentry> diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index eacae71cdc7..cdf1abfa956 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -1357,7 +1357,6 @@ testdb=> </listitem> </varlistentry> - <varlistentry> <term><literal>\du[+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term> <listitem> @@ -1371,6 +1370,19 @@ testdb=> </listitem> </varlistentry> + <varlistentry> + <term><literal>\dx[+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term> + <listitem> + <para> + Lists installed extensions. + If <replaceable class="parameter">pattern</replaceable> + is specified, only those extensions whose names match the pattern + are listed. + If the form <literal>\dx+</literal> is used, all the objects belonging + to each matching extension are listed. + </para> + </listitem> + </varlistentry> <varlistentry> <term><literal>\edit</> (or <literal>\e</>) <literal> <optional> <replaceable class="parameter">filename</> </optional> <optional> <replaceable class="parameter">line_number</> </optional> </literal></term> diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml index 6ee8e5bcff8..47cd01f58e2 100644 --- a/doc/src/sgml/reference.sgml +++ b/doc/src/sgml/reference.sgml @@ -39,6 +39,7 @@ &alterDatabase; &alterDefaultPrivileges; &alterDomain; + &alterExtension; &alterForeignDataWrapper; &alterForeignTable; &alterFunction; @@ -78,6 +79,7 @@ &createConversion; &createDatabase; &createDomain; + &createExtension; &createForeignDataWrapper; &createForeignTable; &createFunction; @@ -114,6 +116,7 @@ &dropConversion; &dropDatabase; &dropDomain; + &dropExtension; &dropForeignDataWrapper; &dropForeignTable; &dropFunction; diff --git a/doc/src/sgml/release-9.0.sgml b/doc/src/sgml/release-9.0.sgml index 2288f1b0e64..4902c058a96 100644 --- a/doc/src/sgml/release-9.0.sgml +++ b/doc/src/sgml/release-9.0.sgml @@ -3520,9 +3520,8 @@ if TG_OP = 'INSERT' and NEW.col1 = ... then <listitem> <para> - Add data and documentation installation location control to <link - linkend="xfunc-c-pgxs"><acronym>PGXS</></link> Makefiles - (Mark Cave-Ayland) + Add data and documentation installation location control to + <acronym>PGXS</> Makefiles (Mark Cave-Ayland) </para> </listitem> diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 4ad50ec0cb5..4f2c23fab7a 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -2392,273 +2392,6 @@ concat_text(PG_FUNCTION_ARGS) &dfunc; - <sect2 id="xfunc-c-pgxs"> - <title>Extension Building Infrastructure</title> - - <indexterm zone="xfunc-c-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. Note that this infrastructure is not - intended to be a universal build system framework that can be used - to build all software interfacing to <productname>PostgreSQL</>; - it simply automates common build rules for simple server extension - modules. For more complicated packages, you need to write your - own build system. - </para> - - <para> - To use the infrastructure for your extension, you must write a - simple makefile. In that 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, an - SQL script, and a documentation text file: -<programlisting> -MODULES = isbn_issn -DATA_built = isbn_issn.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 objects to be built from source files with same - stem (do not include suffix in this list) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><varname>MODULE_big</varname></term> - <listitem> - <para> - a shared object to build from multiple source files - (list object files in <varname>OBJS</varname>) - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><varname>PROGRAM</varname></term> - <listitem> - <para> - a binary 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>MODULEDIR</varname></term> - <listitem> - <para> - subdirectory into which DATA and DOCS files should be - installed (if not set, default is <literal>contrib</literal>) - </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 later <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 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, just like <literal>make - installcheck</literal> is used for the main - <productname>PostgreSQL</productname> server. For this to work you need - to have a subdirectory named <literal>sql/</literal> in your extension's - directory, within which you put one file for each group of tests you want - to run. The files should have extension <literal>.sql</literal>, which - should not be included in the <varname>REGRESS</varname> list in the - makefile. For each test there should be a file containing the expected - result in a subdirectory named <literal>expected/</literal>, with extension - <literal>.out</literal>. The tests are run by executing <literal>make - installcheck</literal>, and the resulting output will be compared to the - expected files. The differences will be written to the file - <literal>regression.diffs</literal> in <command>diff -c</command> format. - Note that trying to run a test which is missing the expected file will be - reported as <quote>trouble</quote>, so make sure you have all expected - files. - </para> - - <tip> - <para> - The easiest way of creating the expected files is creating empty files, - then carefully inspecting the result files after a test run (to be found - in the <literal>results/</literal> directory), and copying them to - <literal>expected/</literal> if they match what you want from the test. - </para> - - </tip> - </sect2> - - <sect2> <title>Composite-type Arguments</title> @@ -3385,4 +3118,68 @@ if (!ptr) </programlisting> </para> </sect2> + + <sect2 id="extend-Cpp"> + <title>Using C++ for Extensibility</title> + + <indexterm zone="extend-Cpp"> + <primary>C++</primary> + </indexterm> + + <para> + Although the <productname>PostgreSQL</productname> backend is written in + C, it is possible to write extensions in C++ if these guidelines are + followed: + + <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. Using C++ + <function>delete</> in such cases will fail. + </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 explicitly throw any + exceptions, because events like out-of-memory can 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()</>. + </para> + </listitem> + <listitem> + <para> + If calling backend functions from C++ code, be sure that the + C++ call stack contains only plain old data structures + (<acronym>POD</>). This is necessary because backend errors + generate a distant <function>longjmp()</> that does not properly + unroll a C++ call stack with non-POD objects. + </para> + </listitem> + </itemizedlist> + </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. + </para> + </sect2> + </sect1> |