Submit
Path:
~
/
/
opt
/
alt
/
postgresql11
/
usr
/
share
/
doc
/
alt-postgresql11-9.2.24
/
html
/
File Content:
xfunc-c.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML ><HEAD ><TITLE >C-Language Functions</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK REV="MADE" HREF="mailto:pgsql-docs@postgresql.org"><LINK REL="HOME" TITLE="PostgreSQL 9.2.24 Documentation" HREF="index.html"><LINK REL="UP" TITLE="Extending SQL" HREF="extend.html"><LINK REL="PREVIOUS" TITLE="Internal Functions" HREF="xfunc-internal.html"><LINK REL="NEXT" TITLE="User-defined Aggregates" HREF="xaggr.html"><LINK REL="STYLESHEET" TYPE="text/css" HREF="stylesheet.css"><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1"><META NAME="creation" CONTENT="2017-11-06T22:43:11"></HEAD ><BODY CLASS="SECT1" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="5" ALIGN="center" VALIGN="bottom" ><A HREF="index.html" >PostgreSQL 9.2.24 Documentation</A ></TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="top" ><A TITLE="Internal Functions" HREF="xfunc-internal.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="10%" ALIGN="left" VALIGN="top" ><A HREF="extend.html" ACCESSKEY="U" >Up</A ></TD ><TD WIDTH="60%" ALIGN="center" VALIGN="bottom" >Chapter 35. Extending <ACRONYM CLASS="ACRONYM" >SQL</ACRONYM ></TD ><TD WIDTH="20%" ALIGN="right" VALIGN="top" ><A TITLE="User-defined Aggregates" HREF="xaggr.html" ACCESSKEY="N" >Next</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="SECT1" ><H1 CLASS="SECT1" ><A NAME="XFUNC-C" >35.9. C-Language Functions</A ></H1 ><P > User-defined functions can be written in C (or a language that can be made compatible with C, such as C++). Such functions are compiled into dynamically loadable objects (also called shared libraries) and are loaded by the server on demand. The dynamic loading feature is what distinguishes <SPAN CLASS="QUOTE" >"C language"</SPAN > functions from <SPAN CLASS="QUOTE" >"internal"</SPAN > functions — the actual coding conventions are essentially the same for both. (Hence, the standard internal function library is a rich source of coding examples for user-defined C functions.) </P ><P > Two different calling conventions are currently used for C functions. The newer <SPAN CLASS="QUOTE" >"version 1"</SPAN > calling convention is indicated by writing a <TT CLASS="LITERAL" >PG_FUNCTION_INFO_V1()</TT > macro call for the function, as illustrated below. Lack of such a macro indicates an old-style (<SPAN CLASS="QUOTE" >"version 0"</SPAN >) function. The language name specified in <TT CLASS="COMMAND" >CREATE FUNCTION</TT > is <TT CLASS="LITERAL" >C</TT > in either case. Old-style functions are now deprecated because of portability problems and lack of functionality, but they are still supported for compatibility reasons. </P ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="XFUNC-C-DYNLOAD" >35.9.1. Dynamic Loading</A ></H2 ><P > The first time a user-defined function in a particular loadable object file is called in a session, the dynamic loader loads that object file into memory so that the function can be called. The <TT CLASS="COMMAND" >CREATE FUNCTION</TT > for a user-defined C function must therefore specify two pieces of information for the function: the name of the loadable object file, and the C name (link symbol) of the specific function to call within that object file. If the C name is not explicitly specified then it is assumed to be the same as the SQL function name. </P ><P > The following algorithm is used to locate the shared object file based on the name given in the <TT CLASS="COMMAND" >CREATE FUNCTION</TT > command: <P ></P ></P><OL TYPE="1" ><LI ><P > If the name is an absolute path, the given file is loaded. </P ></LI ><LI ><P > If the name starts with the string <TT CLASS="LITERAL" >$libdir</TT >, that part is replaced by the <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > package library directory name, which is determined at build time. </P ></LI ><LI ><P > If the name does not contain a directory part, the file is searched for in the path specified by the configuration variable <A HREF="runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH" >dynamic_library_path</A >. </P ></LI ><LI ><P > Otherwise (the file was not found in the path, or it contains a non-absolute directory part), the dynamic loader will try to take the name as given, which will most likely fail. (It is unreliable to depend on the current working directory.) </P ></LI ></OL ><P> If this sequence does not work, the platform-specific shared library file name extension (often <TT CLASS="FILENAME" >.so</TT >) is appended to the given name and this sequence is tried again. If that fails as well, the load will fail. </P ><P > It is recommended to locate shared libraries either relative to <TT CLASS="LITERAL" >$libdir</TT > or through the dynamic library path. This simplifies version upgrades if the new installation is at a different location. The actual directory that <TT CLASS="LITERAL" >$libdir</TT > stands for can be found out with the command <TT CLASS="LITERAL" >pg_config --pkglibdir</TT >. </P ><P > The user ID the <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > server runs as must be able to traverse the path to the file you intend to load. Making the file or a higher-level directory not readable and/or not executable by the <SPAN CLASS="SYSTEMITEM" >postgres</SPAN > user is a common mistake. </P ><P > In any case, the file name that is given in the <TT CLASS="COMMAND" >CREATE FUNCTION</TT > command is recorded literally in the system catalogs, so if the file needs to be loaded again the same procedure is applied. </P ><DIV CLASS="NOTE" ><BLOCKQUOTE CLASS="NOTE" ><P ><B >Note: </B > <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > will not compile a C function automatically. The object file must be compiled before it is referenced in a <TT CLASS="COMMAND" >CREATE FUNCTION</TT > command. See <A HREF="xfunc-c.html#DFUNC" >Section 35.9.6</A > for additional information. </P ></BLOCKQUOTE ></DIV ><P > To ensure that a dynamically loaded object file is not loaded into an incompatible server, <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > checks that the file contains a <SPAN CLASS="QUOTE" >"magic block"</SPAN > with the appropriate contents. This allows the server to detect obvious incompatibilities, such as code compiled for a different major version of <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN >. A magic block is required as of <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > 8.2. To include a magic block, write this in one (and only one) of the module source files, after having included the header <TT CLASS="FILENAME" >fmgr.h</TT >: </P><PRE CLASS="PROGRAMLISTING" >#ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif</PRE ><P> The <TT CLASS="LITERAL" >#ifdef</TT > test can be omitted if the code doesn't need to compile against pre-8.2 <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > releases. </P ><P > After it is used for the first time, a dynamically loaded object file is retained in memory. Future calls in the same session to the function(s) in that file will only incur the small overhead of a symbol table lookup. If you need to force a reload of an object file, for example after recompiling it, begin a fresh session. </P ><P > Optionally, a dynamically loaded file can contain initialization and finalization functions. If the file includes a function named <CODE CLASS="FUNCTION" >_PG_init</CODE >, that function will be called immediately after loading the file. The function receives no parameters and should return void. If the file includes a function named <CODE CLASS="FUNCTION" >_PG_fini</CODE >, that function will be called immediately before unloading the file. Likewise, the function receives no parameters and should return void. Note that <CODE CLASS="FUNCTION" >_PG_fini</CODE > will only be called during an unload of the file, not during process termination. (Presently, unloads are disabled and will never occur, but this may change in the future.) </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="XFUNC-C-BASETYPE" >35.9.2. Base Types in C-Language Functions</A ></H2 ><P > To know how to write C-language functions, you need to know how <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > internally represents base data types and how they can be passed to and from functions. Internally, <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > regards a base type as a <SPAN CLASS="QUOTE" >"blob of memory"</SPAN >. The user-defined functions that you define over a type in turn define the way that <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > can operate on it. That is, <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > will only store and retrieve the data from disk and use your user-defined functions to input, process, and output the data. </P ><P > Base types can have one of three internal formats: <P ></P ></P><UL ><LI ><P > pass by value, fixed-length </P ></LI ><LI ><P > pass by reference, fixed-length </P ></LI ><LI ><P > pass by reference, variable-length </P ></LI ></UL ><P> </P ><P > By-value types can only be 1, 2, or 4 bytes in length (also 8 bytes, if <TT CLASS="LITERAL" >sizeof(Datum)</TT > is 8 on your machine). You should be careful to define your types such that they will be the same size (in bytes) on all architectures. For example, the <TT CLASS="LITERAL" >long</TT > type is dangerous because it is 4 bytes on some machines and 8 bytes on others, whereas <TT CLASS="TYPE" >int</TT > type is 4 bytes on most Unix machines. A reasonable implementation of the <TT CLASS="TYPE" >int4</TT > type on Unix machines might be: </P><PRE CLASS="PROGRAMLISTING" >/* 4-byte integer, passed by value */ typedef int int4;</PRE ><P> </P ><P > On the other hand, fixed-length types of any size can be passed by-reference. For example, here is a sample implementation of a <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > type: </P><PRE CLASS="PROGRAMLISTING" >/* 16-byte structure, passed by reference */ typedef struct { double x, y; } Point;</PRE ><P> Only pointers to such types can be used when passing them in and out of <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > functions. To return a value of such a type, allocate the right amount of memory with <TT CLASS="LITERAL" >palloc</TT >, fill in the allocated memory, and return a pointer to it. (Also, if you just want to return the same value as one of your input arguments that's of the same data type, you can skip the extra <TT CLASS="LITERAL" >palloc</TT > and just return the pointer to the input value.) </P ><P > Finally, all variable-length types must also be passed by reference. All variable-length types must begin with an opaque length field of exactly 4 bytes, which will be set by <TT CLASS="SYMBOL" >SET_VARSIZE</TT >; never set this field directly! All data to be stored within that type must be located in the memory immediately following that length field. The length field contains the total length of the structure, that is, it includes the size of the length field itself. </P ><P > Another important point is to avoid leaving any uninitialized bits within data type values; for example, take care to zero out any alignment padding bytes that might be present in structs. Without this, logically-equivalent constants of your data type might be seen as unequal by the planner, leading to inefficient (though not incorrect) plans. </P ><DIV CLASS="WARNING" ><P ></P ><TABLE CLASS="WARNING" BORDER="1" WIDTH="100%" ><TR ><TD ALIGN="CENTER" ><B >Warning</B ></TD ></TR ><TR ><TD ALIGN="LEFT" ><P > <SPAN CLASS="emphasis" ><I CLASS="EMPHASIS" >Never</I ></SPAN > modify the contents of a pass-by-reference input value. If you do so you are likely to corrupt on-disk data, since the pointer you are given might point directly into a disk buffer. The sole exception to this rule is explained in <A HREF="xaggr.html" >Section 35.10</A >. </P ></TD ></TR ></TABLE ></DIV ><P > As an example, we can define the type <TT CLASS="TYPE" >text</TT > as follows: </P><PRE CLASS="PROGRAMLISTING" >typedef struct { int4 length; char data[1]; } text;</PRE ><P> Obviously, the data field declared here is not long enough to hold all possible strings. Since it's impossible to declare a variable-size structure in <ACRONYM CLASS="ACRONYM" >C</ACRONYM >, we rely on the knowledge that the <ACRONYM CLASS="ACRONYM" >C</ACRONYM > compiler won't range-check array subscripts. We just allocate the necessary amount of space and then access the array as if it were declared the right length. (This is a common trick, which you can read about in many textbooks about C.) </P ><P > When manipulating variable-length types, we must be careful to allocate the correct amount of memory and set the length field correctly. For example, if we wanted to store 40 bytes in a <TT CLASS="STRUCTNAME" >text</TT > structure, we might use a code fragment like this: </P><PRE CLASS="PROGRAMLISTING" >#include "postgres.h" ... char buffer[40]; /* our source data */ ... text *destination = (text *) palloc(VARHDRSZ + 40); SET_VARSIZE(destination, VARHDRSZ + 40); memcpy(destination->data, buffer, 40); ...</PRE ><P> <TT CLASS="LITERAL" >VARHDRSZ</TT > is the same as <TT CLASS="LITERAL" >sizeof(int32)</TT >, but it's considered good style to use the macro <TT CLASS="LITERAL" >VARHDRSZ</TT > to refer to the size of the overhead for a variable-length type. Also, the length field <SPAN CLASS="emphasis" ><I CLASS="EMPHASIS" >must</I ></SPAN > be set using the <TT CLASS="LITERAL" >SET_VARSIZE</TT > macro, not by simple assignment. </P ><P > <A HREF="xfunc-c.html#XFUNC-C-TYPE-TABLE" >Table 35-1</A > specifies which C type corresponds to which SQL type when writing a C-language function that uses a built-in type of <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN >. The <SPAN CLASS="QUOTE" >"Defined In"</SPAN > column gives the header file that needs to be included to get the type definition. (The actual definition might be in a different file that is included by the listed file. It is recommended that users stick to the defined interface.) Note that you should always include <TT CLASS="FILENAME" >postgres.h</TT > first in any source file, because it declares a number of things that you will need anyway. </P ><DIV CLASS="TABLE" ><A NAME="XFUNC-C-TYPE-TABLE" ></A ><P ><B >Table 35-1. Equivalent C Types for Built-in SQL Types</B ></P ><TABLE BORDER="1" CLASS="CALSTABLE" ><COL><COL><COL><THEAD ><TR ><TH > SQL Type </TH ><TH > C Type </TH ><TH > Defined In </TH ></TR ></THEAD ><TBODY ><TR ><TD ><TT CLASS="TYPE" >abstime</TT ></TD ><TD ><TT CLASS="TYPE" >AbsoluteTime</TT ></TD ><TD ><TT CLASS="FILENAME" >utils/nabstime.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >boolean</TT ></TD ><TD ><TT CLASS="TYPE" >bool</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT > (maybe compiler built-in)</TD ></TR ><TR ><TD ><TT CLASS="TYPE" >box</TT ></TD ><TD ><TT CLASS="TYPE" >BOX*</TT ></TD ><TD ><TT CLASS="FILENAME" >utils/geo_decls.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >bytea</TT ></TD ><TD ><TT CLASS="TYPE" >bytea*</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >"char"</TT ></TD ><TD ><TT CLASS="TYPE" >char</TT ></TD ><TD >(compiler built-in)</TD ></TR ><TR ><TD ><TT CLASS="TYPE" >character</TT ></TD ><TD ><TT CLASS="TYPE" >BpChar*</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >cid</TT ></TD ><TD ><TT CLASS="TYPE" >CommandId</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >date</TT ></TD ><TD ><TT CLASS="TYPE" >DateADT</TT ></TD ><TD ><TT CLASS="FILENAME" >utils/date.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >smallint</TT > (<TT CLASS="TYPE" >int2</TT >)</TD ><TD ><TT CLASS="TYPE" >int2</TT > or <TT CLASS="TYPE" >int16</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >int2vector</TT ></TD ><TD ><TT CLASS="TYPE" >int2vector*</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >integer</TT > (<TT CLASS="TYPE" >int4</TT >)</TD ><TD ><TT CLASS="TYPE" >int4</TT > or <TT CLASS="TYPE" >int32</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >real</TT > (<TT CLASS="TYPE" >float4</TT >)</TD ><TD ><TT CLASS="TYPE" >float4*</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >double precision</TT > (<TT CLASS="TYPE" >float8</TT >)</TD ><TD ><TT CLASS="TYPE" >float8*</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >interval</TT ></TD ><TD ><TT CLASS="TYPE" >Interval*</TT ></TD ><TD ><TT CLASS="FILENAME" >datatype/timestamp.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >lseg</TT ></TD ><TD ><TT CLASS="TYPE" >LSEG*</TT ></TD ><TD ><TT CLASS="FILENAME" >utils/geo_decls.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >name</TT ></TD ><TD ><TT CLASS="TYPE" >Name</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >oid</TT ></TD ><TD ><TT CLASS="TYPE" >Oid</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >oidvector</TT ></TD ><TD ><TT CLASS="TYPE" >oidvector*</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >path</TT ></TD ><TD ><TT CLASS="TYPE" >PATH*</TT ></TD ><TD ><TT CLASS="FILENAME" >utils/geo_decls.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >point</TT ></TD ><TD ><TT CLASS="TYPE" >POINT*</TT ></TD ><TD ><TT CLASS="FILENAME" >utils/geo_decls.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >regproc</TT ></TD ><TD ><TT CLASS="TYPE" >regproc</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >reltime</TT ></TD ><TD ><TT CLASS="TYPE" >RelativeTime</TT ></TD ><TD ><TT CLASS="FILENAME" >utils/nabstime.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >text</TT ></TD ><TD ><TT CLASS="TYPE" >text*</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >tid</TT ></TD ><TD ><TT CLASS="TYPE" >ItemPointer</TT ></TD ><TD ><TT CLASS="FILENAME" >storage/itemptr.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >time</TT ></TD ><TD ><TT CLASS="TYPE" >TimeADT</TT ></TD ><TD ><TT CLASS="FILENAME" >utils/date.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >time with time zone</TT ></TD ><TD ><TT CLASS="TYPE" >TimeTzADT</TT ></TD ><TD ><TT CLASS="FILENAME" >utils/date.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >timestamp</TT ></TD ><TD ><TT CLASS="TYPE" >Timestamp*</TT ></TD ><TD ><TT CLASS="FILENAME" >datatype/timestamp.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >tinterval</TT ></TD ><TD ><TT CLASS="TYPE" >TimeInterval</TT ></TD ><TD ><TT CLASS="FILENAME" >utils/nabstime.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >varchar</TT ></TD ><TD ><TT CLASS="TYPE" >VarChar*</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ><TR ><TD ><TT CLASS="TYPE" >xid</TT ></TD ><TD ><TT CLASS="TYPE" >TransactionId</TT ></TD ><TD ><TT CLASS="FILENAME" >postgres.h</TT ></TD ></TR ></TBODY ></TABLE ></DIV ><P > Now that we've gone over all of the possible structures for base types, we can show some examples of real functions. </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="AEN53110" >35.9.3. Version 0 Calling Conventions</A ></H2 ><P > We present the <SPAN CLASS="QUOTE" >"old style"</SPAN > calling convention first — although this approach is now deprecated, it's easier to get a handle on initially. In the version-0 method, the arguments and result of the C function are just declared in normal C style, but being careful to use the C representation of each SQL data type as shown above. </P ><P > Here are some examples: </P><PRE CLASS="PROGRAMLISTING" >#include "postgres.h" #include <string.h> #include "utils/geo_decls.h" #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif /* by value */ int add_one(int arg) { return arg + 1; } /* by reference, fixed length */ float8 * add_one_float8(float8 *arg) { float8 *result = (float8 *) palloc(sizeof(float8)); *result = *arg + 1.0; return result; } Point * makepoint(Point *pointx, Point *pointy) { Point *new_point = (Point *) palloc(sizeof(Point)); new_point->x = pointx->x; new_point->y = pointy->y; return new_point; } /* by reference, variable length */ text * copytext(text *t) { /* * VARSIZE is the total size of the struct in bytes. */ text *new_t = (text *) palloc(VARSIZE(t)); SET_VARSIZE(new_t, VARSIZE(t)); /* * VARDATA is a pointer to the data region of the struct. */ memcpy((void *) VARDATA(new_t), /* destination */ (void *) VARDATA(t), /* source */ VARSIZE(t) - VARHDRSZ); /* how many bytes */ return new_t; } text * concat_text(text *arg1, text *arg2) { int32 new_text_size = VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ; text *new_text = (text *) palloc(new_text_size); SET_VARSIZE(new_text, new_text_size); memcpy(VARDATA(new_text), VARDATA(arg1), VARSIZE(arg1) - VARHDRSZ); memcpy(VARDATA(new_text) + (VARSIZE(arg1) - VARHDRSZ), VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ); return new_text; }</PRE ><P> </P ><P > Supposing that the above code has been prepared in file <TT CLASS="FILENAME" >funcs.c</TT > and compiled into a shared object, we could define the functions to <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > with commands like this: </P><PRE CLASS="PROGRAMLISTING" >CREATE FUNCTION add_one(integer) RETURNS integer AS '<TT CLASS="REPLACEABLE" ><I >DIRECTORY</I ></TT >/funcs', 'add_one' LANGUAGE C STRICT; -- note overloading of SQL function name "add_one" CREATE FUNCTION add_one(double precision) RETURNS double precision AS '<TT CLASS="REPLACEABLE" ><I >DIRECTORY</I ></TT >/funcs', 'add_one_float8' LANGUAGE C STRICT; CREATE FUNCTION makepoint(point, point) RETURNS point AS '<TT CLASS="REPLACEABLE" ><I >DIRECTORY</I ></TT >/funcs', 'makepoint' LANGUAGE C STRICT; CREATE FUNCTION copytext(text) RETURNS text AS '<TT CLASS="REPLACEABLE" ><I >DIRECTORY</I ></TT >/funcs', 'copytext' LANGUAGE C STRICT; CREATE FUNCTION concat_text(text, text) RETURNS text AS '<TT CLASS="REPLACEABLE" ><I >DIRECTORY</I ></TT >/funcs', 'concat_text' LANGUAGE C STRICT;</PRE ><P> </P ><P > Here, <TT CLASS="REPLACEABLE" ><I >DIRECTORY</I ></TT > stands for the directory of the shared library file (for instance the <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > tutorial directory, which contains the code for the examples used in this section). (Better style would be to use just <TT CLASS="LITERAL" >'funcs'</TT > in the <TT CLASS="LITERAL" >AS</TT > clause, after having added <TT CLASS="REPLACEABLE" ><I >DIRECTORY</I ></TT > to the search path. In any case, we can omit the system-specific extension for a shared library, commonly <TT CLASS="LITERAL" >.so</TT > or <TT CLASS="LITERAL" >.sl</TT >.) </P ><P > Notice that we have specified the functions as <SPAN CLASS="QUOTE" >"strict"</SPAN >, meaning that the system should automatically assume a null result if any input value is null. By doing this, we avoid having to check for null inputs in the function code. Without this, we'd have to check for null values explicitly, by checking for a null pointer for each pass-by-reference argument. (For pass-by-value arguments, we don't even have a way to check!) </P ><P > Although this calling convention is simple to use, it is not very portable; on some architectures there are problems with passing data types that are smaller than <TT CLASS="TYPE" >int</TT > this way. Also, there is no simple way to return a null result, nor to cope with null arguments in any way other than making the function strict. The version-1 convention, presented next, overcomes these objections. </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="AEN53137" >35.9.4. Version 1 Calling Conventions</A ></H2 ><P > The version-1 calling convention relies on macros to suppress most of the complexity of passing arguments and results. The C declaration of a version-1 function is always: </P><PRE CLASS="PROGRAMLISTING" >Datum funcname(PG_FUNCTION_ARGS)</PRE ><P> In addition, the macro call: </P><PRE CLASS="PROGRAMLISTING" >PG_FUNCTION_INFO_V1(funcname);</PRE ><P> must appear in the same source file. (Conventionally, it's written just before the function itself.) This macro call is not needed for <TT CLASS="LITERAL" >internal</TT >-language functions, since <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > assumes that all internal functions use the version-1 convention. It is, however, required for dynamically-loaded functions. </P ><P > In a version-1 function, each actual argument is fetched using a <CODE CLASS="FUNCTION" >PG_GETARG_<TT CLASS="REPLACEABLE" ><I >xxx</I ></TT >()</CODE > macro that corresponds to the argument's data type, and the result is returned using a <CODE CLASS="FUNCTION" >PG_RETURN_<TT CLASS="REPLACEABLE" ><I >xxx</I ></TT >()</CODE > macro for the return type. <CODE CLASS="FUNCTION" >PG_GETARG_<TT CLASS="REPLACEABLE" ><I >xxx</I ></TT >()</CODE > takes as its argument the number of the function argument to fetch, where the count starts at 0. <CODE CLASS="FUNCTION" >PG_RETURN_<TT CLASS="REPLACEABLE" ><I >xxx</I ></TT >()</CODE > takes as its argument the actual value to return. </P ><P > Here we show the same functions as above, coded in version-1 style: </P><PRE CLASS="PROGRAMLISTING" >#include "postgres.h" #include <string.h> #include "fmgr.h" #include "utils/geo_decls.h" #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif /* by value */ PG_FUNCTION_INFO_V1(add_one); Datum add_one(PG_FUNCTION_ARGS) { int32 arg = PG_GETARG_INT32(0); PG_RETURN_INT32(arg + 1); } /* by reference, fixed length */ PG_FUNCTION_INFO_V1(add_one_float8); Datum add_one_float8(PG_FUNCTION_ARGS) { /* The macros for FLOAT8 hide its pass-by-reference nature. */ float8 arg = PG_GETARG_FLOAT8(0); PG_RETURN_FLOAT8(arg + 1.0); } PG_FUNCTION_INFO_V1(makepoint); Datum makepoint(PG_FUNCTION_ARGS) { /* Here, the pass-by-reference nature of Point is not hidden. */ Point *pointx = PG_GETARG_POINT_P(0); Point *pointy = PG_GETARG_POINT_P(1); Point *new_point = (Point *) palloc(sizeof(Point)); new_point->x = pointx->x; new_point->y = pointy->y; PG_RETURN_POINT_P(new_point); } /* by reference, variable length */ PG_FUNCTION_INFO_V1(copytext); Datum copytext(PG_FUNCTION_ARGS) { text *t = PG_GETARG_TEXT_P(0); /* * VARSIZE is the total size of the struct in bytes. */ text *new_t = (text *) palloc(VARSIZE(t)); SET_VARSIZE(new_t, VARSIZE(t)); /* * VARDATA is a pointer to the data region of the struct. */ memcpy((void *) VARDATA(new_t), /* destination */ (void *) VARDATA(t), /* source */ VARSIZE(t) - VARHDRSZ); /* how many bytes */ PG_RETURN_TEXT_P(new_t); } PG_FUNCTION_INFO_V1(concat_text); Datum concat_text(PG_FUNCTION_ARGS) { text *arg1 = PG_GETARG_TEXT_P(0); text *arg2 = PG_GETARG_TEXT_P(1); int32 new_text_size = VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ; text *new_text = (text *) palloc(new_text_size); SET_VARSIZE(new_text, new_text_size); memcpy(VARDATA(new_text), VARDATA(arg1), VARSIZE(arg1) - VARHDRSZ); memcpy(VARDATA(new_text) + (VARSIZE(arg1) - VARHDRSZ), VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ); PG_RETURN_TEXT_P(new_text); }</PRE ><P> </P ><P > The <TT CLASS="COMMAND" >CREATE FUNCTION</TT > commands are the same as for the version-0 equivalents. </P ><P > At first glance, the version-1 coding conventions might appear to be just pointless obscurantism. They do, however, offer a number of improvements, because the macros can hide unnecessary detail. An example is that in coding <CODE CLASS="FUNCTION" >add_one_float8</CODE >, we no longer need to be aware that <TT CLASS="TYPE" >float8</TT > is a pass-by-reference type. Another example is that the <TT CLASS="LITERAL" >GETARG</TT > macros for variable-length types allow for more efficient fetching of <SPAN CLASS="QUOTE" >"toasted"</SPAN > (compressed or out-of-line) values. </P ><P > One big improvement in version-1 functions is better handling of null inputs and results. The macro <CODE CLASS="FUNCTION" >PG_ARGISNULL(<TT CLASS="REPLACEABLE" ><I >n</I ></TT >)</CODE > allows a function to test whether each input is null. (Of course, doing this is only necessary in functions not declared <SPAN CLASS="QUOTE" >"strict"</SPAN >.) As with the <CODE CLASS="FUNCTION" >PG_GETARG_<TT CLASS="REPLACEABLE" ><I >xxx</I ></TT >()</CODE > macros, the input arguments are counted beginning at zero. Note that one should refrain from executing <CODE CLASS="FUNCTION" >PG_GETARG_<TT CLASS="REPLACEABLE" ><I >xxx</I ></TT >()</CODE > until one has verified that the argument isn't null. To return a null result, execute <CODE CLASS="FUNCTION" >PG_RETURN_NULL()</CODE >; this works in both strict and nonstrict functions. </P ><P > Other options provided in the new-style interface are two variants of the <CODE CLASS="FUNCTION" >PG_GETARG_<TT CLASS="REPLACEABLE" ><I >xxx</I ></TT >()</CODE > macros. The first of these, <CODE CLASS="FUNCTION" >PG_GETARG_<TT CLASS="REPLACEABLE" ><I >xxx</I ></TT >_COPY()</CODE >, guarantees to return a copy of the specified argument that is safe for writing into. (The normal macros will sometimes return a pointer to a value that is physically stored in a table, which must not be written to. Using the <CODE CLASS="FUNCTION" >PG_GETARG_<TT CLASS="REPLACEABLE" ><I >xxx</I ></TT >_COPY()</CODE > macros guarantees a writable result.) The second variant consists of the <CODE CLASS="FUNCTION" >PG_GETARG_<TT CLASS="REPLACEABLE" ><I >xxx</I ></TT >_SLICE()</CODE > macros which take three arguments. The first is the number of the function argument (as above). The second and third are the offset and length of the segment to be returned. Offsets are counted from zero, and a negative length requests that the remainder of the value be returned. These macros provide more efficient access to parts of large values in the case where they have storage type <SPAN CLASS="QUOTE" >"external"</SPAN >. (The storage type of a column can be specified using <TT CLASS="LITERAL" >ALTER TABLE <TT CLASS="REPLACEABLE" ><I >tablename</I ></TT > ALTER COLUMN <TT CLASS="REPLACEABLE" ><I >colname</I ></TT > SET STORAGE <TT CLASS="REPLACEABLE" ><I >storagetype</I ></TT ></TT >. <TT CLASS="REPLACEABLE" ><I >storagetype</I ></TT > is one of <TT CLASS="LITERAL" >plain</TT >, <TT CLASS="LITERAL" >external</TT >, <TT CLASS="LITERAL" >extended</TT >, or <TT CLASS="LITERAL" >main</TT >.) </P ><P > Finally, the version-1 function call conventions make it possible to return set results (<A HREF="xfunc-c.html#XFUNC-C-RETURN-SET" >Section 35.9.9</A >) and implement trigger functions (<A HREF="triggers.html" >Chapter 36</A >) and procedural-language call handlers (<A HREF="plhandler.html" >Chapter 49</A >). Version-1 code is also more portable than version-0, because it does not break restrictions on function call protocol in the C standard. For more details see <TT CLASS="FILENAME" >src/backend/utils/fmgr/README</TT > in the source distribution. </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="AEN53195" >35.9.5. Writing Code</A ></H2 ><P > Before we turn to the more advanced topics, we should discuss some coding rules for <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > C-language functions. While it might be possible to load functions written in languages other than C into <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN >, this is usually difficult (when it is possible at all) because other languages, such as C++, FORTRAN, or Pascal often do not follow the same calling convention as C. That is, other languages do not pass argument and return values between functions in the same way. For this reason, we will assume that your C-language functions are actually written in C. </P ><P > The basic rules for writing and building C functions are as follows: <P ></P ></P><UL ><LI ><P > Use <TT CLASS="LITERAL" >pg_config --includedir-server</TT > to find out where the <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > server header files are installed on your system (or the system that your users will be running on). </P ></LI ><LI ><P > Compiling and linking your code so that it can be dynamically loaded into <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > always requires special flags. See <A HREF="xfunc-c.html#DFUNC" >Section 35.9.6</A > for a detailed explanation of how to do it for your particular operating system. </P ></LI ><LI ><P > Remember to define a <SPAN CLASS="QUOTE" >"magic block"</SPAN > for your shared library, as described in <A HREF="xfunc-c.html#XFUNC-C-DYNLOAD" >Section 35.9.1</A >. </P ></LI ><LI ><P > When allocating memory, use the <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > functions <CODE CLASS="FUNCTION" >palloc</CODE > and <CODE CLASS="FUNCTION" >pfree</CODE > instead of the corresponding C library functions <CODE CLASS="FUNCTION" >malloc</CODE > and <CODE CLASS="FUNCTION" >free</CODE >. The memory allocated by <CODE CLASS="FUNCTION" >palloc</CODE > will be freed automatically at the end of each transaction, preventing memory leaks. </P ></LI ><LI ><P > Always zero the bytes of your structures using <CODE CLASS="FUNCTION" >memset</CODE > (or allocate them with <CODE CLASS="FUNCTION" >palloc0</CODE > in the first place). Even if you assign to each field of your structure, there might be alignment padding (holes in the structure) that contain garbage values. Without this, it's difficult to support hash indexes or hash joins, as you must pick out only the significant bits of your data structure to compute a hash. The planner also sometimes relies on comparing constants via bitwise equality, so you can get undesirable planning results if logically-equivalent values aren't bitwise equal. </P ></LI ><LI ><P > Most of the internal <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > types are declared in <TT CLASS="FILENAME" >postgres.h</TT >, while the function manager interfaces (<TT CLASS="SYMBOL" >PG_FUNCTION_ARGS</TT >, etc.) are in <TT CLASS="FILENAME" >fmgr.h</TT >, so you will need to include at least these two files. For portability reasons it's best to include <TT CLASS="FILENAME" >postgres.h</TT > <SPAN CLASS="emphasis" ><I CLASS="EMPHASIS" >first</I ></SPAN >, before any other system or user header files. Including <TT CLASS="FILENAME" >postgres.h</TT > will also include <TT CLASS="FILENAME" >elog.h</TT > and <TT CLASS="FILENAME" >palloc.h</TT > for you. </P ></LI ><LI ><P > Symbol names defined within object files must not conflict with each other or with symbols defined in the <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > server executable. You will have to rename your functions or variables if you get error messages to this effect. </P ></LI ></UL ><P> </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="DFUNC" >35.9.6. Compiling and Linking Dynamically-loaded Functions</A ></H2 ><P > Before you are able to use your <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > extension functions written in C, they must be compiled and linked in a special way to produce a file that can be dynamically loaded by the server. To be precise, a <I CLASS="FIRSTTERM" >shared library</I > needs to be created. </P ><P > For information beyond what is contained in this section you should read the documentation of your operating system, in particular the manual pages for the C compiler, <TT CLASS="COMMAND" >cc</TT >, and the link editor, <TT CLASS="COMMAND" >ld</TT >. In addition, the <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > source code contains several working examples in the <TT CLASS="FILENAME" >contrib</TT > directory. If you rely on these examples you will make your modules dependent on the availability of the <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > source code, however. </P ><P > Creating shared libraries is generally analogous to linking executables: first the source files are compiled into object files, then the object files are linked together. The object files need to be created as <I CLASS="FIRSTTERM" >position-independent code</I > (<ACRONYM CLASS="ACRONYM" >PIC</ACRONYM >), which conceptually means that they can be placed at an arbitrary location in memory when they are loaded by the executable. (Object files intended for executables are usually not compiled that way.) The command to link a shared library contains special flags to distinguish it from linking an executable (at least in theory — on some systems the practice is much uglier). </P ><P > In the following examples we assume that your source code is in a file <TT CLASS="FILENAME" >foo.c</TT > and we will create a shared library <TT CLASS="FILENAME" >foo.so</TT >. The intermediate object file will be called <TT CLASS="FILENAME" >foo.o</TT > unless otherwise noted. A shared library can contain more than one object file, but we only use one here. </P ><P ></P ><DIV CLASS="VARIABLELIST" ><DL ><DT ><SPAN CLASS="SYSTEMITEM" >FreeBSD</SPAN ></DT ><DD ><P > The compiler flag to create <ACRONYM CLASS="ACRONYM" >PIC</ACRONYM > is <TT CLASS="OPTION" >-fPIC</TT >. To create shared libraries the compiler flag is <TT CLASS="OPTION" >-shared</TT >. </P><PRE CLASS="PROGRAMLISTING" >gcc -fPIC -c foo.c gcc -shared -o foo.so foo.o</PRE ><P> This is applicable as of version 3.0 of <SPAN CLASS="SYSTEMITEM" >FreeBSD</SPAN >. </P ></DD ><DT ><SPAN CLASS="SYSTEMITEM" >HP-UX</SPAN ></DT ><DD ><P > The compiler flag of the system compiler to create <ACRONYM CLASS="ACRONYM" >PIC</ACRONYM > is <TT CLASS="OPTION" >+z</TT >. When using <SPAN CLASS="APPLICATION" >GCC</SPAN > it's <TT CLASS="OPTION" >-fPIC</TT >. The linker flag for shared libraries is <TT CLASS="OPTION" >-b</TT >. So: </P><PRE CLASS="PROGRAMLISTING" >cc +z -c foo.c</PRE ><P> or: </P><PRE CLASS="PROGRAMLISTING" >gcc -fPIC -c foo.c</PRE ><P> and then: </P><PRE CLASS="PROGRAMLISTING" >ld -b -o foo.sl foo.o</PRE ><P> <SPAN CLASS="SYSTEMITEM" >HP-UX</SPAN > uses the extension <TT CLASS="FILENAME" >.sl</TT > for shared libraries, unlike most other systems. </P ></DD ><DT ><SPAN CLASS="SYSTEMITEM" >IRIX</SPAN ></DT ><DD ><P > <ACRONYM CLASS="ACRONYM" >PIC</ACRONYM > is the default, no special compiler options are necessary. The linker option to produce shared libraries is <TT CLASS="OPTION" >-shared</TT >. </P><PRE CLASS="PROGRAMLISTING" >cc -c foo.c ld -shared -o foo.so foo.o</PRE ><P> </P ></DD ><DT ><SPAN CLASS="SYSTEMITEM" >Linux</SPAN ></DT ><DD ><P > The compiler flag to create <ACRONYM CLASS="ACRONYM" >PIC</ACRONYM > is <TT CLASS="OPTION" >-fPIC</TT >. The compiler flag to create a shared library is <TT CLASS="OPTION" >-shared</TT >. A complete example looks like this: </P><PRE CLASS="PROGRAMLISTING" >cc -fPIC -c foo.c cc -shared -o foo.so foo.o</PRE ><P> </P ></DD ><DT ><SPAN CLASS="SYSTEMITEM" >Mac OS X</SPAN ></DT ><DD ><P > Here is an example. It assumes the developer tools are installed. </P><PRE CLASS="PROGRAMLISTING" >cc -c foo.c cc -bundle -flat_namespace -undefined suppress -o foo.so foo.o</PRE ><P> </P ></DD ><DT ><SPAN CLASS="SYSTEMITEM" >NetBSD</SPAN ></DT ><DD ><P > The compiler flag to create <ACRONYM CLASS="ACRONYM" >PIC</ACRONYM > is <TT CLASS="OPTION" >-fPIC</TT >. For <ACRONYM CLASS="ACRONYM" >ELF</ACRONYM > systems, the compiler with the flag <TT CLASS="OPTION" >-shared</TT > is used to link shared libraries. On the older non-ELF systems, <TT CLASS="LITERAL" >ld -Bshareable</TT > is used. </P><PRE CLASS="PROGRAMLISTING" >gcc -fPIC -c foo.c gcc -shared -o foo.so foo.o</PRE ><P> </P ></DD ><DT ><SPAN CLASS="SYSTEMITEM" >OpenBSD</SPAN ></DT ><DD ><P > The compiler flag to create <ACRONYM CLASS="ACRONYM" >PIC</ACRONYM > is <TT CLASS="OPTION" >-fPIC</TT >. <TT CLASS="LITERAL" >ld -Bshareable</TT > is used to link shared libraries. </P><PRE CLASS="PROGRAMLISTING" >gcc -fPIC -c foo.c ld -Bshareable -o foo.so foo.o</PRE ><P> </P ></DD ><DT ><SPAN CLASS="SYSTEMITEM" >Solaris</SPAN ></DT ><DD ><P > The compiler flag to create <ACRONYM CLASS="ACRONYM" >PIC</ACRONYM > is <TT CLASS="OPTION" >-KPIC</TT > with the Sun compiler and <TT CLASS="OPTION" >-fPIC</TT > with <SPAN CLASS="APPLICATION" >GCC</SPAN >. To link shared libraries, the compiler option is <TT CLASS="OPTION" >-G</TT > with either compiler or alternatively <TT CLASS="OPTION" >-shared</TT > with <SPAN CLASS="APPLICATION" >GCC</SPAN >. </P><PRE CLASS="PROGRAMLISTING" >cc -KPIC -c foo.c cc -G -o foo.so foo.o</PRE ><P> or </P><PRE CLASS="PROGRAMLISTING" >gcc -fPIC -c foo.c gcc -G -o foo.so foo.o</PRE ><P> </P ></DD ><DT ><SPAN CLASS="SYSTEMITEM" >Tru64 UNIX</SPAN ></DT ><DD ><P > <ACRONYM CLASS="ACRONYM" >PIC</ACRONYM > is the default, so the compilation command is the usual one. <TT CLASS="COMMAND" >ld</TT > with special options is used to do the linking. </P><PRE CLASS="PROGRAMLISTING" >cc -c foo.c ld -shared -expect_unresolved '*' -o foo.so foo.o</PRE ><P> The same procedure is used with GCC instead of the system compiler; no special options are required. </P ></DD ><DT ><SPAN CLASS="SYSTEMITEM" >UnixWare</SPAN ></DT ><DD ><P > The compiler flag to create <ACRONYM CLASS="ACRONYM" >PIC</ACRONYM > is <TT CLASS="OPTION" >-K PIC</TT > with the SCO compiler and <TT CLASS="OPTION" >-fpic</TT > with <SPAN CLASS="PRODUCTNAME" >GCC</SPAN >. To link shared libraries, the compiler option is <TT CLASS="OPTION" >-G</TT > with the SCO compiler and <TT CLASS="OPTION" >-shared</TT > with <SPAN CLASS="PRODUCTNAME" >GCC</SPAN >. </P><PRE CLASS="PROGRAMLISTING" >cc -K PIC -c foo.c cc -G -o foo.so foo.o</PRE ><P> or </P><PRE CLASS="PROGRAMLISTING" >gcc -fpic -c foo.c gcc -shared -o foo.so foo.o</PRE ><P> </P ></DD ></DL ></DIV ><DIV CLASS="TIP" ><BLOCKQUOTE CLASS="TIP" ><P ><B >Tip: </B > If this is too complicated for you, you should consider using <A HREF="http://www.gnu.org/software/libtool/" TARGET="_top" > <SPAN CLASS="PRODUCTNAME" >GNU Libtool</SPAN ></A >, which hides the platform differences behind a uniform interface. </P ></BLOCKQUOTE ></DIV ><P > The resulting shared library file can then be loaded into <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN >. When specifying the file name to the <TT CLASS="COMMAND" >CREATE FUNCTION</TT > command, one must give it the name of the shared library file, not the intermediate object file. Note that the system's standard shared-library extension (usually <TT CLASS="LITERAL" >.so</TT > or <TT CLASS="LITERAL" >.sl</TT >) can be omitted from the <TT CLASS="COMMAND" >CREATE FUNCTION</TT > command, and normally should be omitted for best portability. </P ><P > Refer back to <A HREF="xfunc-c.html#XFUNC-C-DYNLOAD" >Section 35.9.1</A > about where the server expects to find the shared library files. </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="AEN53419" >35.9.7. Composite-type Arguments</A ></H2 ><P > Composite types do not have a fixed layout like C structures. Instances of a composite type can contain null fields. In addition, composite types that are part of an inheritance hierarchy can have different fields than other members of the same inheritance hierarchy. Therefore, <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > provides a function interface for accessing fields of composite types from C. </P ><P > Suppose we want to write a function to answer the query: </P><PRE CLASS="PROGRAMLISTING" >SELECT name, c_overpaid(emp, 1500) AS overpaid FROM emp WHERE name = 'Bill' OR name = 'Sam';</PRE ><P> Using call conventions version 0, we can define <CODE CLASS="FUNCTION" >c_overpaid</CODE > as: </P><PRE CLASS="PROGRAMLISTING" >#include "postgres.h" #include "executor/executor.h" /* for GetAttributeByName() */ #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif bool c_overpaid(HeapTupleHeader t, /* the current row of emp */ int32 limit) { bool isnull; int32 salary; salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull)); if (isnull) return false; return salary > limit; }</PRE ><P> In version-1 coding, the above would look like this: </P><PRE CLASS="PROGRAMLISTING" >#include "postgres.h" #include "executor/executor.h" /* for GetAttributeByName() */ #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif PG_FUNCTION_INFO_V1(c_overpaid); Datum c_overpaid(PG_FUNCTION_ARGS) { HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(0); int32 limit = PG_GETARG_INT32(1); bool isnull; Datum salary; salary = GetAttributeByName(t, "salary", &isnull); if (isnull) PG_RETURN_BOOL(false); /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */ PG_RETURN_BOOL(DatumGetInt32(salary) > limit); }</PRE ><P> </P ><P > <CODE CLASS="FUNCTION" >GetAttributeByName</CODE > is the <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > system function that returns attributes out of the specified row. It has three arguments: the argument of type <TT CLASS="TYPE" >HeapTupleHeader</TT > passed into the function, the name of the desired attribute, and a return parameter that tells whether the attribute is null. <CODE CLASS="FUNCTION" >GetAttributeByName</CODE > returns a <TT CLASS="TYPE" >Datum</TT > value that you can convert to the proper data type by using the appropriate <CODE CLASS="FUNCTION" >DatumGet<TT CLASS="REPLACEABLE" ><I >XXX</I ></TT >()</CODE > macro. Note that the return value is meaningless if the null flag is set; always check the null flag before trying to do anything with the result. </P ><P > There is also <CODE CLASS="FUNCTION" >GetAttributeByNum</CODE >, which selects the target attribute by column number instead of name. </P ><P > The following command declares the function <CODE CLASS="FUNCTION" >c_overpaid</CODE > in SQL: </P><PRE CLASS="PROGRAMLISTING" >CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean AS '<TT CLASS="REPLACEABLE" ><I >DIRECTORY</I ></TT >/funcs', 'c_overpaid' LANGUAGE C STRICT;</PRE ><P> Notice we have used <TT CLASS="LITERAL" >STRICT</TT > so that we did not have to check whether the input arguments were NULL. </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="AEN53443" >35.9.8. Returning Rows (Composite Types)</A ></H2 ><P > To return a row or composite-type value from a C-language function, you can use a special API that provides macros and functions to hide most of the complexity of building composite data types. To use this API, the source file must include: </P><PRE CLASS="PROGRAMLISTING" >#include "funcapi.h"</PRE ><P> </P ><P > There are two ways you can build a composite data value (henceforth a <SPAN CLASS="QUOTE" >"tuple"</SPAN >): you can build it from an array of Datum values, or from an array of C strings that can be passed to the input conversion functions of the tuple's column data types. In either case, you first need to obtain or construct a <TT CLASS="STRUCTNAME" >TupleDesc</TT > descriptor for the tuple structure. When working with Datums, you pass the <TT CLASS="STRUCTNAME" >TupleDesc</TT > to <CODE CLASS="FUNCTION" >BlessTupleDesc</CODE >, and then call <CODE CLASS="FUNCTION" >heap_form_tuple</CODE > for each row. When working with C strings, you pass the <TT CLASS="STRUCTNAME" >TupleDesc</TT > to <CODE CLASS="FUNCTION" >TupleDescGetAttInMetadata</CODE >, and then call <CODE CLASS="FUNCTION" >BuildTupleFromCStrings</CODE > for each row. In the case of a function returning a set of tuples, the setup steps can all be done once during the first call of the function. </P ><P > Several helper functions are available for setting up the needed <TT CLASS="STRUCTNAME" >TupleDesc</TT >. The recommended way to do this in most functions returning composite values is to call: </P><PRE CLASS="PROGRAMLISTING" >TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)</PRE ><P> passing the same <TT CLASS="LITERAL" >fcinfo</TT > struct passed to the calling function itself. (This of course requires that you use the version-1 calling conventions.) <TT CLASS="VARNAME" >resultTypeId</TT > can be specified as <TT CLASS="LITERAL" >NULL</TT > or as the address of a local variable to receive the function's result type OID. <TT CLASS="VARNAME" >resultTupleDesc</TT > should be the address of a local <TT CLASS="STRUCTNAME" >TupleDesc</TT > variable. Check that the result is <TT CLASS="LITERAL" >TYPEFUNC_COMPOSITE</TT >; if so, <TT CLASS="VARNAME" >resultTupleDesc</TT > has been filled with the needed <TT CLASS="STRUCTNAME" >TupleDesc</TT >. (If it is not, you can report an error along the lines of <SPAN CLASS="QUOTE" >"function returning record called in context that cannot accept type record"</SPAN >.) </P ><DIV CLASS="TIP" ><BLOCKQUOTE CLASS="TIP" ><P ><B >Tip: </B > <CODE CLASS="FUNCTION" >get_call_result_type</CODE > can resolve the actual type of a polymorphic function result; so it is useful in functions that return scalar polymorphic results, not only functions that return composites. The <TT CLASS="VARNAME" >resultTypeId</TT > output is primarily useful for functions returning polymorphic scalars. </P ></BLOCKQUOTE ></DIV ><DIV CLASS="NOTE" ><BLOCKQUOTE CLASS="NOTE" ><P ><B >Note: </B > <CODE CLASS="FUNCTION" >get_call_result_type</CODE > has a sibling <CODE CLASS="FUNCTION" >get_expr_result_type</CODE >, which can be used to resolve the expected output type for a function call represented by an expression tree. This can be used when trying to determine the result type from outside the function itself. There is also <CODE CLASS="FUNCTION" >get_func_result_type</CODE >, which can be used when only the function's OID is available. However these functions are not able to deal with functions declared to return <TT CLASS="STRUCTNAME" >record</TT >, and <CODE CLASS="FUNCTION" >get_func_result_type</CODE > cannot resolve polymorphic types, so you should preferentially use <CODE CLASS="FUNCTION" >get_call_result_type</CODE >. </P ></BLOCKQUOTE ></DIV ><P > Older, now-deprecated functions for obtaining <TT CLASS="STRUCTNAME" >TupleDesc</TT >s are: </P><PRE CLASS="PROGRAMLISTING" >TupleDesc RelationNameGetTupleDesc(const char *relname)</PRE ><P> to get a <TT CLASS="STRUCTNAME" >TupleDesc</TT > for the row type of a named relation, and: </P><PRE CLASS="PROGRAMLISTING" >TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)</PRE ><P> to get a <TT CLASS="STRUCTNAME" >TupleDesc</TT > based on a type OID. This can be used to get a <TT CLASS="STRUCTNAME" >TupleDesc</TT > for a base or composite type. It will not work for a function that returns <TT CLASS="STRUCTNAME" >record</TT >, however, and it cannot resolve polymorphic types. </P ><P > Once you have a <TT CLASS="STRUCTNAME" >TupleDesc</TT >, call: </P><PRE CLASS="PROGRAMLISTING" >TupleDesc BlessTupleDesc(TupleDesc tupdesc)</PRE ><P> if you plan to work with Datums, or: </P><PRE CLASS="PROGRAMLISTING" >AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)</PRE ><P> if you plan to work with C strings. If you are writing a function returning set, you can save the results of these functions in the <TT CLASS="STRUCTNAME" >FuncCallContext</TT > structure — use the <TT CLASS="STRUCTFIELD" >tuple_desc</TT > or <TT CLASS="STRUCTFIELD" >attinmeta</TT > field respectively. </P ><P > When working with Datums, use: </P><PRE CLASS="PROGRAMLISTING" >HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)</PRE ><P> to build a <TT CLASS="STRUCTNAME" >HeapTuple</TT > given user data in Datum form. </P ><P > When working with C strings, use: </P><PRE CLASS="PROGRAMLISTING" >HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)</PRE ><P> to build a <TT CLASS="STRUCTNAME" >HeapTuple</TT > given user data in C string form. <TT CLASS="LITERAL" >values</TT > is an array of C strings, one for each attribute of the return row. Each C string should be in the form expected by the input function of the attribute data type. In order to return a null value for one of the attributes, the corresponding pointer in the <TT CLASS="PARAMETER" >values</TT > array should be set to <TT CLASS="SYMBOL" >NULL</TT >. This function will need to be called again for each row you return. </P ><P > Once you have built a tuple to return from your function, it must be converted into a <TT CLASS="TYPE" >Datum</TT >. Use: </P><PRE CLASS="PROGRAMLISTING" >HeapTupleGetDatum(HeapTuple tuple)</PRE ><P> to convert a <TT CLASS="STRUCTNAME" >HeapTuple</TT > into a valid Datum. This <TT CLASS="TYPE" >Datum</TT > can be returned directly if you intend to return just a single row, or it can be used as the current return value in a set-returning function. </P ><P > An example appears in the next section. </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="XFUNC-C-RETURN-SET" >35.9.9. Returning Sets</A ></H2 ><P > There is also a special API that provides support for returning sets (multiple rows) from a C-language function. A set-returning function must follow the version-1 calling conventions. Also, source files must include <TT CLASS="FILENAME" >funcapi.h</TT >, as above. </P ><P > A set-returning function (<ACRONYM CLASS="ACRONYM" >SRF</ACRONYM >) is called once for each item it returns. The <ACRONYM CLASS="ACRONYM" >SRF</ACRONYM > must therefore save enough state to remember what it was doing and return the next item on each call. The structure <TT CLASS="STRUCTNAME" >FuncCallContext</TT > is provided to help control this process. Within a function, <TT CLASS="LITERAL" >fcinfo->flinfo->fn_extra</TT > is used to hold a pointer to <TT CLASS="STRUCTNAME" >FuncCallContext</TT > across calls. </P><PRE CLASS="PROGRAMLISTING" >typedef struct { /* * Number of times we've been called before * * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and * incremented for you every time SRF_RETURN_NEXT() is called. */ uint32 call_cntr; /* * OPTIONAL maximum number of calls * * max_calls is here for convenience only and setting it is optional. * If not set, you must provide alternative means to know when the * function is done. */ uint32 max_calls; /* * OPTIONAL pointer to result slot * * This is obsolete and only present for backward compatibility, viz, * user-defined SRFs that use the deprecated TupleDescGetSlot(). */ TupleTableSlot *slot; /* * OPTIONAL pointer to miscellaneous user-provided context information * * user_fctx is for use as a pointer to your own data to retain * arbitrary context information between calls of your function. */ void *user_fctx; /* * OPTIONAL pointer to struct containing attribute type input metadata * * attinmeta is for use when returning tuples (i.e., composite data types) * and is not used when returning base data types. It is only needed * if you intend to use BuildTupleFromCStrings() to create the return * tuple. */ AttInMetadata *attinmeta; /* * memory context used for structures that must live for multiple calls * * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory * context for any memory that is to be reused across multiple calls * of the SRF. */ MemoryContext multi_call_memory_ctx; /* * OPTIONAL pointer to struct containing tuple description * * tuple_desc is for use when returning tuples (i.e., composite data types) * and is only needed if you are going to build the tuples with * heap_form_tuple() rather than with BuildTupleFromCStrings(). Note that * the TupleDesc pointer stored here should usually have been run through * BlessTupleDesc() first. */ TupleDesc tuple_desc; } FuncCallContext;</PRE ><P> </P ><P > An <ACRONYM CLASS="ACRONYM" >SRF</ACRONYM > uses several functions and macros that automatically manipulate the <TT CLASS="STRUCTNAME" >FuncCallContext</TT > structure (and expect to find it via <TT CLASS="LITERAL" >fn_extra</TT >). Use: </P><PRE CLASS="PROGRAMLISTING" >SRF_IS_FIRSTCALL()</PRE ><P> to determine if your function is being called for the first or a subsequent time. On the first call (only) use: </P><PRE CLASS="PROGRAMLISTING" >SRF_FIRSTCALL_INIT()</PRE ><P> to initialize the <TT CLASS="STRUCTNAME" >FuncCallContext</TT >. On every function call, including the first, use: </P><PRE CLASS="PROGRAMLISTING" >SRF_PERCALL_SETUP()</PRE ><P> to properly set up for using the <TT CLASS="STRUCTNAME" >FuncCallContext</TT > and clearing any previously returned data left over from the previous pass. </P ><P > If your function has data to return, use: </P><PRE CLASS="PROGRAMLISTING" >SRF_RETURN_NEXT(funcctx, result)</PRE ><P> to return it to the caller. (<TT CLASS="LITERAL" >result</TT > must be of type <TT CLASS="TYPE" >Datum</TT >, either a single value or a tuple prepared as described above.) Finally, when your function is finished returning data, use: </P><PRE CLASS="PROGRAMLISTING" >SRF_RETURN_DONE(funcctx)</PRE ><P> to clean up and end the <ACRONYM CLASS="ACRONYM" >SRF</ACRONYM >. </P ><P > The memory context that is current when the <ACRONYM CLASS="ACRONYM" >SRF</ACRONYM > is called is a transient context that will be cleared between calls. This means that you do not need to call <CODE CLASS="FUNCTION" >pfree</CODE > on everything you allocated using <CODE CLASS="FUNCTION" >palloc</CODE >; it will go away anyway. However, if you want to allocate any data structures to live across calls, you need to put them somewhere else. The memory context referenced by <TT CLASS="STRUCTFIELD" >multi_call_memory_ctx</TT > is a suitable location for any data that needs to survive until the <ACRONYM CLASS="ACRONYM" >SRF</ACRONYM > is finished running. In most cases, this means that you should switch into <TT CLASS="STRUCTFIELD" >multi_call_memory_ctx</TT > while doing the first-call setup. </P ><P > A complete pseudo-code example looks like the following: </P><PRE CLASS="PROGRAMLISTING" >Datum my_set_returning_function(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; Datum result; <TT CLASS="REPLACEABLE" ><I >further declarations as needed</I ></TT > if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /* One-time setup code appears here: */ <TT CLASS="REPLACEABLE" ><I >user code</I ></TT > <TT CLASS="REPLACEABLE" ><I >if returning composite</I ></TT > <TT CLASS="REPLACEABLE" ><I >build TupleDesc, and perhaps AttInMetadata</I ></TT > <TT CLASS="REPLACEABLE" ><I >endif returning composite</I ></TT > <TT CLASS="REPLACEABLE" ><I >user code</I ></TT > MemoryContextSwitchTo(oldcontext); } /* Each-time setup code appears here: */ <TT CLASS="REPLACEABLE" ><I >user code</I ></TT > funcctx = SRF_PERCALL_SETUP(); <TT CLASS="REPLACEABLE" ><I >user code</I ></TT > /* this is just one way we might test whether we are done: */ if (funcctx->call_cntr < funcctx->max_calls) { /* Here we want to return another item: */ <TT CLASS="REPLACEABLE" ><I >user code</I ></TT > <TT CLASS="REPLACEABLE" ><I >obtain result Datum</I ></TT > SRF_RETURN_NEXT(funcctx, result); } else { /* Here we are done returning items and just need to clean up: */ <TT CLASS="REPLACEABLE" ><I >user code</I ></TT > SRF_RETURN_DONE(funcctx); } }</PRE ><P> </P ><P > A complete example of a simple <ACRONYM CLASS="ACRONYM" >SRF</ACRONYM > returning a composite type looks like: </P><PRE CLASS="PROGRAMLISTING" >PG_FUNCTION_INFO_V1(retcomposite); Datum retcomposite(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; int call_cntr; int max_calls; TupleDesc tupdesc; AttInMetadata *attinmeta; /* stuff done only on the first call of the function */ if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); /* switch to memory context appropriate for multiple function calls */ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /* total number of tuples to be returned */ funcctx->max_calls = PG_GETARG_UINT32(0); /* Build a tuple descriptor for our result type */ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); /* * generate attribute metadata needed later to produce tuples from raw * C strings */ attinmeta = TupleDescGetAttInMetadata(tupdesc); funcctx->attinmeta = attinmeta; MemoryContextSwitchTo(oldcontext); } /* stuff done on every call of the function */ funcctx = SRF_PERCALL_SETUP(); call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; attinmeta = funcctx->attinmeta; if (call_cntr < max_calls) /* do when there is more left to send */ { char **values; HeapTuple tuple; Datum result; /* * Prepare a values array for building the returned tuple. * This should be an array of C strings which will * be processed later by the type input functions. */ values = (char **) palloc(3 * sizeof(char *)); values[0] = (char *) palloc(16 * sizeof(char)); values[1] = (char *) palloc(16 * sizeof(char)); values[2] = (char *) palloc(16 * sizeof(char)); snprintf(values[0], 16, "%d", 1 * PG_GETARG_INT32(1)); snprintf(values[1], 16, "%d", 2 * PG_GETARG_INT32(1)); snprintf(values[2], 16, "%d", 3 * PG_GETARG_INT32(1)); /* build a tuple */ tuple = BuildTupleFromCStrings(attinmeta, values); /* make the tuple into a datum */ result = HeapTupleGetDatum(tuple); /* clean up (this is not really necessary) */ pfree(values[0]); pfree(values[1]); pfree(values[2]); pfree(values); SRF_RETURN_NEXT(funcctx, result); } else /* do when there is no more left */ { SRF_RETURN_DONE(funcctx); } }</PRE ><P> One way to declare this function in SQL is: </P><PRE CLASS="PROGRAMLISTING" >CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer); CREATE OR REPLACE FUNCTION retcomposite(integer, integer) RETURNS SETOF __retcomposite AS '<TT CLASS="REPLACEABLE" ><I >filename</I ></TT >', 'retcomposite' LANGUAGE C IMMUTABLE STRICT;</PRE ><P> A different way is to use OUT parameters: </P><PRE CLASS="PROGRAMLISTING" >CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer, OUT f1 integer, OUT f2 integer, OUT f3 integer) RETURNS SETOF record AS '<TT CLASS="REPLACEABLE" ><I >filename</I ></TT >', 'retcomposite' LANGUAGE C IMMUTABLE STRICT;</PRE ><P> Notice that in this method the output type of the function is formally an anonymous <TT CLASS="STRUCTNAME" >record</TT > type. </P ><P > The directory <A HREF="tablefunc.html" >contrib/tablefunc</A > module in the source distribution contains more examples of set-returning functions. </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="AEN53566" >35.9.10. Polymorphic Arguments and Return Types</A ></H2 ><P > C-language functions can be declared to accept and return the polymorphic types <TT CLASS="TYPE" >anyelement</TT >, <TT CLASS="TYPE" >anyarray</TT >, <TT CLASS="TYPE" >anynonarray</TT >, <TT CLASS="TYPE" >anyenum</TT >, and <TT CLASS="TYPE" >anyrange</TT >. See <A HREF="extend-type-system.html#EXTEND-TYPES-POLYMORPHIC" >Section 35.2.5</A > for a more detailed explanation of polymorphic functions. When function arguments or return types are defined as polymorphic types, the function author cannot know in advance what data type it will be called with, or need to return. There are two routines provided in <TT CLASS="FILENAME" >fmgr.h</TT > to allow a version-1 C function to discover the actual data types of its arguments and the type it is expected to return. The routines are called <TT CLASS="LITERAL" >get_fn_expr_rettype(FmgrInfo *flinfo)</TT > and <TT CLASS="LITERAL" >get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</TT >. They return the result or argument type OID, or <TT CLASS="SYMBOL" >InvalidOid</TT > if the information is not available. The structure <TT CLASS="LITERAL" >flinfo</TT > is normally accessed as <TT CLASS="LITERAL" >fcinfo->flinfo</TT >. The parameter <TT CLASS="LITERAL" >argnum</TT > is zero based. <CODE CLASS="FUNCTION" >get_call_result_type</CODE > can also be used as an alternative to <CODE CLASS="FUNCTION" >get_fn_expr_rettype</CODE >. </P ><P > For example, suppose we want to write a function to accept a single element of any type, and return a one-dimensional array of that type: </P><PRE CLASS="PROGRAMLISTING" >PG_FUNCTION_INFO_V1(make_array); Datum make_array(PG_FUNCTION_ARGS) { ArrayType *result; Oid element_type = get_fn_expr_argtype(fcinfo->flinfo, 0); Datum element; bool isnull; int16 typlen; bool typbyval; char typalign; int ndims; int dims[MAXDIM]; int lbs[MAXDIM]; if (!OidIsValid(element_type)) elog(ERROR, "could not determine data type of input"); /* get the provided element, being careful in case it's NULL */ isnull = PG_ARGISNULL(0); if (isnull) element = (Datum) 0; else element = PG_GETARG_DATUM(0); /* we have one dimension */ ndims = 1; /* and one element */ dims[0] = 1; /* and lower bound is 1 */ lbs[0] = 1; /* get required info about the element type */ get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign); /* now build the array */ result = construct_md_array(&element, &isnull, ndims, dims, lbs, element_type, typlen, typbyval, typalign); PG_RETURN_ARRAYTYPE_P(result); }</PRE ><P> </P ><P > The following command declares the function <CODE CLASS="FUNCTION" >make_array</CODE > in SQL: </P><PRE CLASS="PROGRAMLISTING" >CREATE FUNCTION make_array(anyelement) RETURNS anyarray AS '<TT CLASS="REPLACEABLE" ><I >DIRECTORY</I ></TT >/funcs', 'make_array' LANGUAGE C IMMUTABLE;</PRE ><P> </P ><P > There is a variant of polymorphism that is only available to C-language functions: they can be declared to take parameters of type <TT CLASS="LITERAL" >"any"</TT >. (Note that this type name must be double-quoted, since it's also a SQL reserved word.) This works like <TT CLASS="TYPE" >anyelement</TT > except that it does not constrain different <TT CLASS="LITERAL" >"any"</TT > arguments to be the same type, nor do they help determine the function's result type. A C-language function can also declare its final parameter to be <TT CLASS="LITERAL" >VARIADIC "any"</TT >. This will match one or more actual arguments of any type (not necessarily the same type). These arguments will <SPAN CLASS="emphasis" ><I CLASS="EMPHASIS" >not</I ></SPAN > be gathered into an array as happens with normal variadic functions; they will just be passed to the function separately. The <CODE CLASS="FUNCTION" >PG_NARGS()</CODE > macro and the methods described above must be used to determine the number of actual arguments and their types when using this feature. </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="XFUNC-TRANSFORM-FUNCTIONS" >35.9.11. Transform Functions</A ></H2 ><P > Some function calls can be simplified during planning based on properties specific to the function. For example, <TT CLASS="LITERAL" >int4mul(n, 1)</TT > could be simplified to just <TT CLASS="LITERAL" >n</TT >. To define such function-specific optimizations, write a <I CLASS="FIRSTTERM" >transform function</I > and place its OID in the <TT CLASS="STRUCTFIELD" >protransform</TT > field of the primary function's <TT CLASS="STRUCTNAME" >pg_proc</TT > entry. The transform function must have the SQL signature <TT CLASS="LITERAL" >protransform(internal) RETURNS internal</TT >. The argument, actually <TT CLASS="TYPE" >FuncExpr *</TT >, is a dummy node representing a call to the primary function. If the transform function's study of the expression tree proves that a simplified expression tree can substitute for all possible concrete calls represented thereby, build and return that simplified expression. Otherwise, return a <TT CLASS="LITERAL" >NULL</TT > pointer (<SPAN CLASS="emphasis" ><I CLASS="EMPHASIS" >not</I ></SPAN > a SQL null). </P ><P > We make no guarantee that <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > will never call the primary function in cases that the transform function could simplify. Ensure rigorous equivalence between the simplified expression and an actual call to the primary function. </P ><P > Currently, this facility is not exposed to users at the SQL level because of security concerns, so it is only practical to use for optimizing built-in functions. </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="AEN53612" >35.9.12. Shared Memory and LWLocks</A ></H2 ><P > Add-ins can reserve LWLocks and an allocation of shared memory on server startup. The add-in's shared library must be preloaded by specifying it in <A HREF="runtime-config-resource.html#GUC-SHARED-PRELOAD-LIBRARIES" >shared_preload_libraries</A >. Shared memory is reserved by calling: </P><PRE CLASS="PROGRAMLISTING" >void RequestAddinShmemSpace(int size)</PRE ><P> from your <CODE CLASS="FUNCTION" >_PG_init</CODE > function. </P ><P > LWLocks are reserved by calling: </P><PRE CLASS="PROGRAMLISTING" >void RequestAddinLWLocks(int n)</PRE ><P> from <CODE CLASS="FUNCTION" >_PG_init</CODE >. </P ><P > To avoid possible race-conditions, each backend should use the LWLock <CODE CLASS="FUNCTION" >AddinShmemInitLock</CODE > when connecting to and initializing its allocation of shared memory, as shown here: </P><PRE CLASS="PROGRAMLISTING" >static mystruct *ptr = NULL; if (!ptr) { bool found; LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); ptr = ShmemInitStruct("my struct name", size, &found); if (!found) { initialize contents of shmem area; acquire any requested LWLocks using: ptr->mylockid = LWLockAssign(); } LWLockRelease(AddinShmemInitLock); }</PRE ><P> </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="EXTEND-CPP" >35.9.13. Using C++ for Extensibility</A ></H2 ><P > Although the <SPAN CLASS="PRODUCTNAME" >PostgreSQL</SPAN > backend is written in C, it is possible to write extensions in C++ if these guidelines are followed: <P ></P ></P><UL ><LI ><P > All functions accessed by the backend must present a C interface to the backend; these C functions can then call C++ functions. For example, <TT CLASS="LITERAL" >extern C</TT > 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. </P ></LI ><LI ><P > Free memory using the appropriate deallocation method. For example, most backend memory is allocated using <CODE CLASS="FUNCTION" >palloc()</CODE >, so use <CODE CLASS="FUNCTION" >pfree()</CODE > to free it. Using C++ <CODE CLASS="FUNCTION" >delete</CODE > in such cases will fail. </P ></LI ><LI ><P > Prevent exceptions from propagating into the C code (use a catch-all block at the top level of all <TT CLASS="LITERAL" >extern C</TT > 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 <TT CLASS="OPTION" >-fno-exceptions</TT > to eliminate exceptions entirely; in such cases, you must check for failures in your C++ code, e.g. check for NULL returned by <CODE CLASS="FUNCTION" >new()</CODE >. </P ></LI ><LI ><P > If calling backend functions from C++ code, be sure that the C++ call stack contains only plain old data structures (<ACRONYM CLASS="ACRONYM" >POD</ACRONYM >). This is necessary because backend errors generate a distant <CODE CLASS="FUNCTION" >longjmp()</CODE > that does not properly unroll a C++ call stack with non-POD objects. </P ></LI ></UL ><P> </P ><P > In summary, it is best to place C++ code behind a wall of <TT CLASS="LITERAL" >extern C</TT > functions that interface to the backend, and avoid exception, memory, and call stack leakage. </P ></DIV ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="xfunc-internal.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >Home</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="xaggr.html" ACCESSKEY="N" >Next</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >Internal Functions</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="extend.html" ACCESSKEY="U" >Up</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >User-defined Aggregates</TD ></TR ></TABLE ></DIV ></BODY ></HTML >
Submit
FILE
FOLDER
Name
Size
Permission
Action
LEGALNOTICE.html
2681 bytes
0644
acronyms.html
16284 bytes
0644
admin.html
12564 bytes
0644
adminpack.html
7889 bytes
0644
app-clusterdb.html
10602 bytes
0644
app-createdb.html
12856 bytes
0644
app-createlang.html
9907 bytes
0644
app-createuser.html
15640 bytes
0644
app-dropdb.html
9642 bytes
0644
app-droplang.html
9638 bytes
0644
app-dropuser.html
9596 bytes
0644
app-ecpg.html
8718 bytes
0644
app-initdb.html
15405 bytes
0644
app-pg-ctl.html
22459 bytes
0644
app-pg-dumpall.html
20706 bytes
0644
app-pgbasebackup.html
19833 bytes
0644
app-pgconfig.html
11093 bytes
0644
app-pgcontroldata.html
3979 bytes
0644
app-pgdump.html
43964 bytes
0644
app-pgreceivexlog.html
11057 bytes
0644
app-pgresetxlog.html
11566 bytes
0644
app-pgrestore.html
30269 bytes
0644
app-postgres.html
31828 bytes
0644
app-postmaster.html
3005 bytes
0644
app-psql.html
138871 bytes
0644
app-reindexdb.html
11281 bytes
0644
app-vacuumdb.html
12616 bytes
0644
appendixes.html
26329 bytes
0644
applevel-consistency.html
10315 bytes
0644
archive-recovery-settings.html
7338 bytes
0644
arrays.html
28079 bytes
0644
auth-delay.html
3780 bytes
0644
auth-methods.html
36202 bytes
0644
auth-pg-hba-conf.html
29759 bytes
0644
auth-username-maps.html
8597 bytes
0644
auto-explain.html
9887 bytes
0644
backup-dump.html
15927 bytes
0644
backup-file.html
7996 bytes
0644
backup.html
4485 bytes
0644
biblio.html
11549 bytes
0644
bki-commands.html
9646 bytes
0644
bki-example.html
3049 bytes
0644
bki-format.html
3463 bytes
0644
bki-structure.html
4320 bytes
0644
bki.html
4330 bytes
0644
bookindex.html
243165 bytes
0644
btree-gin.html
4600 bytes
0644
btree-gist.html
6884 bytes
0644
bug-reporting.html
18646 bytes
0644
catalog-pg-aggregate.html
5502 bytes
0644
catalog-pg-am.html
10547 bytes
0644
catalog-pg-amop.html
7593 bytes
0644
catalog-pg-amproc.html
4885 bytes
0644
catalog-pg-attrdef.html
4364 bytes
0644
catalog-pg-attribute.html
10287 bytes
0644
catalog-pg-auth-members.html
4255 bytes
0644
catalog-pg-authid.html
6815 bytes
0644
catalog-pg-cast.html
6955 bytes
0644
catalog-pg-class.html
12661 bytes
0644
catalog-pg-collation.html
5897 bytes
0644
catalog-pg-constraint.html
11579 bytes
0644
catalog-pg-conversion.html
4430 bytes
0644
catalog-pg-database.html
7027 bytes
0644
catalog-pg-db-role-setting.html
4068 bytes
0644
catalog-pg-default-acl.html
5267 bytes
0644
catalog-pg-depend.html
8635 bytes
0644
catalog-pg-description.html
4478 bytes
0644
catalog-pg-enum.html
4716 bytes
0644
catalog-pg-extension.html
5282 bytes
0644
catalog-pg-foreign-data-wrapper.html
4945 bytes
0644
catalog-pg-foreign-server.html
4688 bytes
0644
catalog-pg-foreign-table.html
4036 bytes
0644
catalog-pg-index.html
8868 bytes
0644
catalog-pg-inherits.html
3888 bytes
0644
catalog-pg-language.html
5952 bytes
0644
catalog-pg-largeobject-metadata.html
3630 bytes
0644
catalog-pg-largeobject.html
5154 bytes
0644
catalog-pg-namespace.html
3751 bytes
0644
catalog-pg-opclass.html
5863 bytes
0644
catalog-pg-operator.html
6645 bytes
0644
catalog-pg-opfamily.html
4811 bytes
0644
catalog-pg-pltemplate.html
5364 bytes
0644
catalog-pg-proc.html
13403 bytes
0644
catalog-pg-range.html
5182 bytes
0644
catalog-pg-rewrite.html
5391 bytes
0644
catalog-pg-seclabel.html
4515 bytes
0644
catalog-pg-shdepend.html
7043 bytes
0644
catalog-pg-shdescription.html
4247 bytes
0644
catalog-pg-shseclabel.html
4404 bytes
0644
catalog-pg-statistic.html
9538 bytes
0644
catalog-pg-tablespace.html
4158 bytes
0644
catalog-pg-trigger.html
8287 bytes
0644
catalog-pg-ts-config-map.html
4193 bytes
0644
catalog-pg-ts-config.html
4481 bytes
0644
catalog-pg-ts-dict.html
4716 bytes
0644
catalog-pg-ts-parser.html
5082 bytes
0644
catalog-pg-ts-template.html
4258 bytes
0644
catalog-pg-type.html
19905 bytes
0644
catalog-pg-user-mapping.html
3847 bytes
0644
catalogs-overview.html
10431 bytes
0644
catalogs.html
10387 bytes
0644
charset.html
4162 bytes
0644
chkpass.html
4391 bytes
0644
citext.html
11148 bytes
0644
client-authentication-problems.html
4224 bytes
0644
client-authentication.html
5914 bytes
0644
client-interfaces.html
13717 bytes
0644
collation.html
14222 bytes
0644
config-setting.html
11146 bytes
0644
connect-estab.html
4315 bytes
0644
continuous-archiving.html
49830 bytes
0644
contrib-dblink-build-sql-delete.html
5451 bytes
0644
contrib-dblink-build-sql-insert.html
6052 bytes
0644
contrib-dblink-build-sql-update.html
6281 bytes
0644
contrib-dblink-cancel-query.html
3820 bytes
0644
contrib-dblink-close.html
4650 bytes
0644
contrib-dblink-connect-u.html
4482 bytes
0644
contrib-dblink-connect.html
7325 bytes
0644
contrib-dblink-disconnect.html
3718 bytes
0644
contrib-dblink-error-message.html
3508 bytes
0644
contrib-dblink-exec.html
5466 bytes
0644
contrib-dblink-fetch.html
5979 bytes
0644
contrib-dblink-function.html
8630 bytes
0644
contrib-dblink-get-connections.html
3206 bytes
0644
contrib-dblink-get-notify.html
4168 bytes
0644
contrib-dblink-get-pkey.html
4498 bytes
0644
contrib-dblink-get-result.html
6959 bytes
0644
contrib-dblink-is-busy.html
3490 bytes
0644
contrib-dblink-open.html
5464 bytes
0644
contrib-dblink-send-query.html
4170 bytes
0644
contrib-prog-client.html
3434 bytes
0644
contrib-prog-server.html
3837 bytes
0644
contrib-prog.html
3320 bytes
0644
contrib-spi.html
11236 bytes
0644
contrib.html
8904 bytes
0644
creating-cluster.html
12465 bytes
0644
cube.html
15941 bytes
0644
database-roles.html
6092 bytes
0644
datatype-binary.html
12893 bytes
0644
datatype-bit.html
5096 bytes
0644
datatype-boolean.html
5267 bytes
0644
datatype-character.html
11893 bytes
0644
datatype-datetime.html
50763 bytes
0644
datatype-enum.html
6433 bytes
0644
datatype-geometric.html
12503 bytes
0644
datatype-json.html
3439 bytes
0644
datatype-money.html
5482 bytes
0644
datatype-net-types.html
10423 bytes
0644
datatype-numeric.html
22353 bytes
0644
datatype-oid.html
9686 bytes
0644
datatype-pseudo.html
7285 bytes
0644
datatype-textsearch.html
10033 bytes
0644
datatype-uuid.html
4560 bytes
0644
datatype-xml.html
11334 bytes
0644
datatype.html
16609 bytes
0644
datetime-appendix.html
3525 bytes
0644
datetime-config-files.html
8980 bytes
0644
datetime-input-rules.html
6763 bytes
0644
datetime-keywords.html
5096 bytes
0644
datetime-units-history.html
7634 bytes
0644
dblink.html
5322 bytes
0644
ddl-alter.html
10498 bytes
0644
ddl-basics.html
7816 bytes
0644
ddl-constraints.html
22790 bytes
0644
ddl-default.html
4540 bytes
0644
ddl-depend.html
6498 bytes
0644
ddl-foreign-data.html
4485 bytes
0644
ddl-inherit.html
15308 bytes
0644
ddl-others.html
3080 bytes
0644
ddl-partitioning.html
27763 bytes
0644
ddl-priv.html
6066 bytes
0644
ddl-schemas.html
18046 bytes
0644
ddl-system-columns.html
8049 bytes
0644
ddl.html
6382 bytes
0644
dict-int.html
4793 bytes
0644
dict-xsyn.html
6481 bytes
0644
different-replication-solutions.html
14793 bytes
0644
disk-full.html
3517 bytes
0644
disk-usage.html
5661 bytes
0644
diskusage.html
2668 bytes
0644
dml-delete.html
3565 bytes
0644
dml-insert.html
5801 bytes
0644
dml-returning.html
5104 bytes
0644
dml-update.html
5556 bytes
0644
dml.html
2944 bytes
0644
docguide-authoring.html
6757 bytes
0644
docguide-build.html
15280 bytes
0644
docguide-docbook.html
3853 bytes
0644
docguide-style.html
7429 bytes
0644
docguide-toolsets.html
20683 bytes
0644
docguide.html
3624 bytes
0644
dummy-seclabel.html
4358 bytes
0644
dynamic-trace.html
27234 bytes
0644
earthdistance.html
8806 bytes
0644
ecpg-commands.html
9527 bytes
0644
ecpg-concept.html
4979 bytes
0644
ecpg-connect.html
10826 bytes
0644
ecpg-cpp.html
9624 bytes
0644
ecpg-descriptors.html
34909 bytes
0644
ecpg-develop.html
7964 bytes
0644
ecpg-dynamic.html
6515 bytes
0644
ecpg-errors.html
25737 bytes
0644
ecpg-informix-compat.html
52760 bytes
0644
ecpg-library.html
5798 bytes
0644
ecpg-lo.html
5527 bytes
0644
ecpg-pgtypes.html
54457 bytes
0644
ecpg-preproc.html
8985 bytes
0644
ecpg-process.html
5386 bytes
0644
ecpg-sql-allocate-descriptor.html
3983 bytes
0644
ecpg-sql-commands.html
4698 bytes
0644
ecpg-sql-connect.html
9375 bytes
0644
ecpg-sql-deallocate-descriptor.html
3773 bytes
0644
ecpg-sql-declare.html
5397 bytes
0644
ecpg-sql-describe.html
4595 bytes
0644
ecpg-sql-disconnect.html
4733 bytes
0644
ecpg-sql-execute-immediate.html
3877 bytes
0644
ecpg-sql-get-descriptor.html
7709 bytes
0644
ecpg-sql-open.html
4642 bytes
0644
ecpg-sql-prepare.html
4177 bytes
0644
ecpg-sql-set-autocommit.html
3333 bytes
0644
ecpg-sql-set-connection.html
3929 bytes
0644
ecpg-sql-set-descriptor.html
5505 bytes
0644
ecpg-sql-type.html
5026 bytes
0644
ecpg-sql-var.html
3539 bytes
0644
ecpg-sql-whenever.html
4686 bytes
0644
ecpg-variables.html
40283 bytes
0644
ecpg.html
10344 bytes
0644
encryption-options.html
7495 bytes
0644
errcodes-appendix.html
36965 bytes
0644
error-message-reporting.html
14124 bytes
0644
error-style-guide.html
16769 bytes
0644
event-log-registration.html
4188 bytes
0644
executor.html
6612 bytes
0644
explicit-joins.html
11019 bytes
0644
explicit-locking.html
25073 bytes
0644
extend-extensions.html
32430 bytes
0644
extend-how.html
4552 bytes
0644
extend-pgxs.html
11761 bytes
0644
extend-type-system.html
10111 bytes
0644
extend.html
9982 bytes
0644
external-admin-tools.html
2722 bytes
0644
external-extensions.html
3263 bytes
0644
external-interfaces.html
5513 bytes
0644
external-pl.html
4670 bytes
0644
external-projects.html
3004 bytes
0644
fdw-callbacks.html
12905 bytes
0644
fdw-functions.html
4496 bytes
0644
fdw-helpers.html
5988 bytes
0644
fdw-planning.html
9845 bytes
0644
fdwhandler.html
3990 bytes
0644
features-sql-standard.html
39105 bytes
0644
features.html
7566 bytes
0644
file-fdw.html
7709 bytes
0644
functions-admin.html
50395 bytes
0644
functions-aggregate.html
21814 bytes
0644
functions-array.html
13521 bytes
0644
functions-binarystring.html
12588 bytes
0644
functions-bitstring.html
6786 bytes
0644
functions-comparison.html
10638 bytes
0644
functions-comparisons.html
13531 bytes
0644
functions-conditional.html
11007 bytes
0644
functions-datetime.html
48303 bytes
0644
functions-enum.html
5491 bytes
0644
functions-formatting.html
35401 bytes
0644
functions-geometry.html
20347 bytes
0644
functions-info.html
58658 bytes
0644
functions-json.html
3814 bytes
0644
functions-logical.html
4665 bytes
0644
functions-matching.html
75728 bytes
0644
functions-math.html
20401 bytes
0644
functions-net.html
13502 bytes
0644
functions-range.html
10857 bytes
0644
functions-sequence.html
12925 bytes
0644
functions-srf.html
8840 bytes
0644
functions-string.html
59052 bytes
0644
functions-subquery.html
16381 bytes
0644
functions-textsearch.html
20488 bytes
0644
functions-trigger.html
4548 bytes
0644
functions-window.html
12085 bytes
0644
functions-xml.html
32169 bytes
0644
functions.html
9939 bytes
0644
fuzzystrmatch.html
8061 bytes
0644
geqo-biblio.html
3459 bytes
0644
geqo-intro.html
4415 bytes
0644
geqo-intro2.html
5627 bytes
0644
geqo-pg-intro.html
8785 bytes
0644
geqo.html
3616 bytes
0644
gin-examples.html
3322 bytes
0644
gin-extensibility.html
14402 bytes
0644
gin-implementation.html
6564 bytes
0644
gin-intro.html
4662 bytes
0644
gin-limit.html
2817 bytes
0644
gin-tips.html
5713 bytes
0644
gin.html
2929 bytes
0644
gist-examples.html
3752 bytes
0644
gist-extensibility.html
24354 bytes
0644
gist-implementation.html
4101 bytes
0644
gist-intro.html
3616 bytes
0644
gist.html
2679 bytes
0644
git.html
4564 bytes
0644
high-availability.html
7698 bytes
0644
history.html
11918 bytes
0644
hot-standby.html
36045 bytes
0644
hstore.html
22629 bytes
0644
index-catalog.html
7996 bytes
0644
index-cost-estimation.html
9991 bytes
0644
index-functions.html
19114 bytes
0644
index-locking.html
8049 bytes
0644
index-scanning.html
10707 bytes
0644
index-unique-checks.html
9192 bytes
0644
index.html
8071 bytes
0644
indexam.html
5247 bytes
0644
indexes-bitmap-scans.html
6580 bytes
0644
indexes-collations.html
3640 bytes
0644
indexes-examine.html
7161 bytes
0644
indexes-expressional.html
4813 bytes
0644
indexes-intro.html
6313 bytes
0644
indexes-multicolumn.html
6298 bytes
0644
indexes-opclass.html
7336 bytes
0644
indexes-ordering.html
6480 bytes
0644
indexes-partial.html
11812 bytes
0644
indexes-types.html
10233 bytes
0644
indexes-unique.html
4002 bytes
0644
indexes.html
3619 bytes
0644
information-schema.html
11177 bytes
0644
infoschema-administrable-role-authorizations.html
3751 bytes
0644
infoschema-applicable-roles.html
3970 bytes
0644
infoschema-attributes.html
12807 bytes
0644
infoschema-character-sets.html
7050 bytes
0644
infoschema-check-constraint-routine-usage.html
4349 bytes
0644
infoschema-check-constraints.html
3876 bytes
0644
infoschema-collation-character-set-applicab.html
4425 bytes
0644
infoschema-collations.html
3885 bytes
0644
infoschema-column-domain-usage.html
4322 bytes
0644
infoschema-column-options.html
4109 bytes
0644
infoschema-column-privileges.html
5029 bytes
0644
infoschema-column-udt-usage.html
4583 bytes
0644
infoschema-columns.html
17625 bytes
0644
infoschema-constraint-column-usage.html
4873 bytes
0644
infoschema-constraint-table-usage.html
4774 bytes
0644
infoschema-data-type-privileges.html
5089 bytes
0644
infoschema-datatypes.html
4229 bytes
0644
infoschema-domain-constraints.html
4664 bytes
0644
infoschema-domain-udt-usage.html
4171 bytes
0644
infoschema-domains.html
11367 bytes
0644
infoschema-element-types.html
11374 bytes
0644
infoschema-enabled-roles.html
3780 bytes
0644
infoschema-foreign-data-wrapper-options.html
3910 bytes
0644
infoschema-foreign-data-wrappers.html
4227 bytes
0644
infoschema-foreign-server-options.html
3853 bytes
0644
infoschema-foreign-servers.html
4571 bytes
0644
infoschema-foreign-table-options.html
3974 bytes
0644
infoschema-foreign-tables.html
4072 bytes
0644
infoschema-information-schema-catalog-name.html
3357 bytes
0644
infoschema-key-column-usage.html
5185 bytes
0644
infoschema-parameters.html
10799 bytes
0644
infoschema-referential-constraints.html
5664 bytes
0644
infoschema-role-column-grants.html
5017 bytes
0644
infoschema-role-routine-grants.html
5360 bytes
0644
infoschema-role-table-grants.html
5427 bytes
0644
infoschema-role-udt-grants.html
4781 bytes
0644
infoschema-role-usage-grants.html
5010 bytes
0644
infoschema-routine-privileges.html
5032 bytes
0644
infoschema-routines.html
23052 bytes
0644
infoschema-schema.html
3180 bytes
0644
infoschema-schemata.html
4248 bytes
0644
infoschema-sequences.html
6111 bytes
0644
infoschema-sql-features.html
4708 bytes
0644
infoschema-sql-implementation-info.html
4503 bytes
0644
infoschema-sql-languages.html
5094 bytes
0644
infoschema-sql-packages.html
4178 bytes
0644
infoschema-sql-parts.html
4080 bytes
0644
infoschema-sql-sizing-profiles.html
4177 bytes
0644
infoschema-sql-sizing.html
4101 bytes
0644
infoschema-table-constraints.html
4914 bytes
0644
infoschema-table-privileges.html
5097 bytes
0644
infoschema-tables.html
5957 bytes
0644
infoschema-triggered-update-columns.html
4554 bytes
0644
infoschema-triggers.html
9447 bytes
0644
infoschema-udt-privileges.html
4509 bytes
0644
infoschema-usage-privileges.html
5512 bytes
0644
infoschema-user-defined-types.html
9753 bytes
0644
infoschema-user-mapping-options.html
4449 bytes
0644
infoschema-user-mappings.html
3833 bytes
0644
infoschema-view-column-usage.html
4728 bytes
0644
infoschema-view-routine-usage.html
4368 bytes
0644
infoschema-view-table-usage.html
4389 bytes
0644
infoschema-views.html
5529 bytes
0644
install-getsource.html
3574 bytes
0644
install-post.html
8076 bytes
0644
install-procedure.html
46527 bytes
0644
install-requirements.html
14481 bytes
0644
install-short.html
2870 bytes
0644
install-windows-full.html
19274 bytes
0644
install-windows-libpq.html
6283 bytes
0644
install-windows.html
6620 bytes
0644
installation-platform-notes.html
39380 bytes
0644
installation.html
4160 bytes
0644
intagg.html
6254 bytes
0644
intarray.html
13757 bytes
0644
internals.html
15638 bytes
0644
intro-whatis.html
4011 bytes
0644
isn.html
13356 bytes
0644
kernel-resources.html
37822 bytes
0644
largeobjects.html
4675 bytes
0644
libpq-async.html
21020 bytes
0644
libpq-build.html
6369 bytes
0644
libpq-cancel.html
6777 bytes
0644
libpq-connect.html
51248 bytes
0644
libpq-control.html
6280 bytes
0644
libpq-copy.html
22442 bytes
0644
libpq-envars.html
9820 bytes
0644
libpq-events.html
23093 bytes
0644
libpq-example.html
16024 bytes
0644
libpq-exec.html
64877 bytes
0644
libpq-fastpath.html
6124 bytes
0644
libpq-ldap.html
5506 bytes
0644
libpq-misc.html
13815 bytes
0644
libpq-notice-processing.html
6284 bytes
0644
libpq-notify.html
6715 bytes
0644
libpq-pgpass.html
4861 bytes
0644
libpq-pgservice.html
3905 bytes
0644
libpq-single-row-mode.html
6353 bytes
0644
libpq-ssl.html
19972 bytes
0644
libpq-status.html
17695 bytes
0644
libpq-threading.html
5544 bytes
0644
libpq.html
7918 bytes
0644
lo-examplesect.html
8696 bytes
0644
lo-funcs.html
4640 bytes
0644
lo-implementation.html
3353 bytes
0644
lo-interfaces.html
15155 bytes
0644
lo-intro.html
3206 bytes
0644
lo.html
6627 bytes
0644
locale.html
13691 bytes
0644
locking-indexes.html
4350 bytes
0644
log-shipping-alternative.html
11057 bytes
0644
logfile-maintenance.html
7143 bytes
0644
ltree.html
27295 bytes
0644
maintenance.html
5538 bytes
0644
manage-ag-config.html
3746 bytes
0644
manage-ag-createdb.html
6310 bytes
0644
manage-ag-dropdb.html
3605 bytes
0644
manage-ag-overview.html
5144 bytes
0644
manage-ag-tablespaces.html
9250 bytes
0644
manage-ag-templatedbs.html
8162 bytes
0644
managing-databases.html
3273 bytes
0644
monitoring-locks.html
3673 bytes
0644
monitoring-ps.html
6782 bytes
0644
monitoring-stats.html
58063 bytes
0644
monitoring.html
4458 bytes
0644
multibyte.html
31965 bytes
0644
mvcc-caveats.html
4077 bytes
0644
mvcc-intro.html
4552 bytes
0644
mvcc.html
4302 bytes
0644
nls-programmer.html
10078 bytes
0644
nls-translator.html
14522 bytes
0644
nls.html
3134 bytes
0644
non-durability.html
4484 bytes
0644
notation.html
4415 bytes
0644
oid2name.html
11962 bytes
0644
overview.html
4093 bytes
0644
pageinspect.html
8117 bytes
0644
parser-stage.html
8117 bytes
0644
passwordcheck.html
4788 bytes
0644
performance-tips.html
4501 bytes
0644
perm-functions.html
3338 bytes
0644
pgarchivecleanup.html
8999 bytes
0644
pgbench.html
30833 bytes
0644
pgbuffercache.html
7715 bytes
0644
pgcrypto.html
38804 bytes
0644
pgfreespacemap.html
5230 bytes
0644
pgrowlocks.html
6078 bytes
0644
pgstandby.html
15204 bytes
0644
pgstatstatements.html
16068 bytes
0644
pgstattuple.html
9449 bytes
0644
pgtestfsync.html
5254 bytes
0644
pgtesttiming.html
12476 bytes
0644
pgtrgm.html
12333 bytes
0644
pgupgrade.html
24737 bytes
0644
planner-optimizer.html
9396 bytes
0644
planner-stats-details.html
3276 bytes
0644
planner-stats-security.html
5556 bytes
0644
planner-stats.html
9058 bytes
0644
plhandler.html
13748 bytes
0644
plperl-builtins.html
18276 bytes
0644
plperl-data.html
2878 bytes
0644
plperl-funcs.html
13369 bytes
0644
plperl-global.html
5067 bytes
0644
plperl-triggers.html
6446 bytes
0644
plperl-trusted.html
6712 bytes
0644
plperl-under-the-hood.html
8991 bytes
0644
plperl.html
4930 bytes
0644
plpgsql-control-structures.html
46183 bytes
0644
plpgsql-cursors.html
25586 bytes
0644
plpgsql-declarations.html
21746 bytes
0644
plpgsql-development-tips.html
9511 bytes
0644
plpgsql-errors-and-messages.html
10094 bytes
0644
plpgsql-expressions.html
4662 bytes
0644
plpgsql-implementation.html
18043 bytes
0644
plpgsql-overview.html
9032 bytes
0644
plpgsql-porting.html
27094 bytes
0644
plpgsql-statements.html
32221 bytes
0644
plpgsql-structure.html
8329 bytes
0644
plpgsql-trigger.html
22322 bytes
0644
plpgsql.html
6965 bytes
0644
plpython-data.html
14648 bytes
0644
plpython-database.html
15413 bytes
0644
plpython-do.html
2771 bytes
0644
plpython-envar.html
3885 bytes
0644
plpython-funcs.html
5478 bytes
0644
plpython-python23.html
7207 bytes
0644
plpython-sharing.html
3032 bytes
0644
plpython-subtransaction.html
7888 bytes
0644
plpython-trigger.html
5069 bytes
0644
plpython-util.html
5104 bytes
0644
plpython.html
6067 bytes
0644
pltcl-data.html
2906 bytes
0644
pltcl-dbaccess.html
13902 bytes
0644
pltcl-functions.html
6177 bytes
0644
pltcl-global.html
5066 bytes
0644
pltcl-overview.html
5288 bytes
0644
pltcl-procnames.html
3222 bytes
0644
pltcl-trigger.html
9452 bytes
0644
pltcl-unknown.html
5075 bytes
0644
pltcl.html
3400 bytes
0644
populate.html
17114 bytes
0644
postgres-user.html
3314 bytes
0644
preface.html
5070 bytes
0644
preventing-server-spoofing.html
4604 bytes
0644
protocol-changes.html
6650 bytes
0644
protocol-error-fields.html
6131 bytes
0644
protocol-flow.html
46202 bytes
0644
protocol-message-formats.html
40844 bytes
0644
protocol-message-types.html
4933 bytes
0644
protocol-overview.html
9670 bytes
0644
protocol-replication.html
14666 bytes
0644
protocol.html
5652 bytes
0644
queries-limit.html
5335 bytes
0644
queries-order.html
7369 bytes
0644
queries-overview.html
5068 bytes
0644
queries-select-lists.html
9308 bytes
0644
queries-table-expressions.html
39874 bytes
0644
queries-union.html
5114 bytes
0644
queries-values.html
4930 bytes
0644
queries-with.html
20880 bytes
0644
queries.html
4418 bytes
0644
query-path.html
5470 bytes
0644
querytree.html
11136 bytes
0644
rangetypes.html
22735 bytes
0644
recovery-config.html
3550 bytes
0644
recovery-target-settings.html
7762 bytes
0644
reference-client.html
6102 bytes
0644
reference-server.html
3964 bytes
0644
reference.html
23162 bytes
0644
regress-coverage.html
3325 bytes
0644
regress-evaluation.html
12487 bytes
0644
regress-run.html
13710 bytes
0644
regress-variant.html
7177 bytes
0644
regress.html
4277 bytes
0644
release-0-01.html
2555 bytes
0644
release-0-02.html
4292 bytes
0644
release-0-03.html
7798 bytes
0644
release-1-0.html
4229 bytes
0644
release-1-01.html
9346 bytes
0644
release-1-02.html
6489 bytes
0644
release-1-09.html
2525 bytes
0644
release-6-0.html
7920 bytes
0644
release-6-1-1.html
3719 bytes
0644
release-6-1.html
9025 bytes
0644
release-6-2-1.html
4405 bytes
0644
release-6-2.html
8883 bytes
0644
release-6-3-1.html
4444 bytes
0644
release-6-3-2.html
4157 bytes
0644
release-6-3.html
16311 bytes
0644
release-6-4-1.html
4061 bytes
0644
release-6-4-2.html
2908 bytes
0644
release-6-4.html
14732 bytes
0644
release-6-5-1.html
3842 bytes
0644
release-6-5-2.html
4102 bytes
0644
release-6-5-3.html
3053 bytes
0644
release-6-5.html
17387 bytes
0644
release-7-0-1.html
3920 bytes
0644
release-7-0-2.html
2887 bytes
0644
release-7-0-3.html
4656 bytes
0644
release-7-0.html
23104 bytes
0644
release-7-1-1.html
3262 bytes
0644
release-7-1-2.html
2975 bytes
0644
release-7-1-3.html
3139 bytes
0644
release-7-1.html
13017 bytes
0644
release-7-2-1.html
4011 bytes
0644
release-7-2-2.html
3793 bytes
0644
release-7-2-3.html
3364 bytes
0644
release-7-2-4.html
3587 bytes
0644
release-7-2-5.html
3746 bytes
0644
release-7-2-6.html
3624 bytes
0644
release-7-2-7.html
3726 bytes
0644
release-7-2-8.html
3948 bytes
0644
release-7-2.html
27098 bytes
0644
release-7-3-1.html
4168 bytes
0644
release-7-3-10.html
7493 bytes
0644
release-7-3-11.html
4111 bytes
0644
release-7-3-12.html
3527 bytes
0644
release-7-3-13.html
4618 bytes
0644
release-7-3-14.html
3931 bytes
0644
release-7-3-15.html
6315 bytes
0644
release-7-3-16.html
3424 bytes
0644
release-7-3-17.html
3550 bytes
0644
release-7-3-18.html
3647 bytes
0644
release-7-3-19.html
3686 bytes
0644
release-7-3-2.html
5205 bytes
0644
release-7-3-20.html
3524 bytes
0644
release-7-3-21.html
6216 bytes
0644
release-7-3-3.html
10290 bytes
0644
release-7-3-4.html
3502 bytes
0644
release-7-3-5.html
4493 bytes
0644
release-7-3-6.html
4428 bytes
0644
release-7-3-7.html
3352 bytes
0644
release-7-3-8.html
3571 bytes
0644
release-7-3-9.html
4079 bytes
0644
release-7-3.html
33053 bytes
0644
release-7-4-1.html
7116 bytes
0644
release-7-4-10.html
3806 bytes
0644
release-7-4-11.html
4857 bytes
0644
release-7-4-12.html
4221 bytes
0644
release-7-4-13.html
6961 bytes
0644
release-7-4-14.html
3673 bytes
0644
release-7-4-15.html
4270 bytes
0644
release-7-4-16.html
3972 bytes
0644
release-7-4-17.html
4013 bytes
0644
release-7-4-18.html
3927 bytes
0644
release-7-4-19.html
7242 bytes
0644
release-7-4-2.html
8260 bytes
0644
release-7-4-20.html
6605 bytes
0644
release-7-4-21.html
3922 bytes
0644
release-7-4-22.html
4071 bytes
0644
release-7-4-23.html
4423 bytes
0644
release-7-4-24.html
4289 bytes
0644
release-7-4-25.html
4506 bytes
0644
release-7-4-26.html
5455 bytes
0644
release-7-4-27.html
5164 bytes
0644
release-7-4-28.html
5629 bytes
0644
release-7-4-29.html
6960 bytes
0644
release-7-4-3.html
4615 bytes
0644
release-7-4-30.html
6211 bytes
0644
release-7-4-4.html
4085 bytes
0644
release-7-4-5.html
3194 bytes
0644
release-7-4-6.html
4731 bytes
0644
release-7-4-7.html
4274 bytes
0644
release-7-4-8.html
10156 bytes
0644
release-7-4-9.html
5118 bytes
0644
release-7-4.html
57378 bytes
0644
release-8-0-1.html
4744 bytes
0644
release-8-0-10.html
4751 bytes
0644
release-8-0-11.html
3969 bytes
0644
release-8-0-12.html
3134 bytes
0644
release-8-0-13.html
4118 bytes
0644
release-8-0-14.html
4518 bytes
0644
release-8-0-15.html
9101 bytes
0644
release-8-0-16.html
8946 bytes
0644
release-8-0-17.html
3920 bytes
0644
release-8-0-18.html
5579 bytes
0644
release-8-0-19.html
4976 bytes
0644
release-8-0-2.html
9566 bytes
0644
release-8-0-20.html
4312 bytes
0644
release-8-0-21.html
4504 bytes
0644
release-8-0-22.html
6440 bytes
0644
release-8-0-23.html
6023 bytes
0644
release-8-0-24.html
7002 bytes
0644
release-8-0-25.html
7427 bytes
0644
release-8-0-26.html
8026 bytes
0644
release-8-0-3.html
7425 bytes
0644
release-8-0-4.html
6680 bytes
0644
release-8-0-5.html
4816 bytes
0644
release-8-0-6.html
5694 bytes
0644
release-8-0-7.html
5909 bytes
0644
release-8-0-8.html
7225 bytes
0644
release-8-0-9.html
4306 bytes
0644
release-8-0.html
66818 bytes
0644
release-8-1-1.html
5459 bytes
0644
release-8-1-10.html
4781 bytes
0644
release-8-1-11.html
9946 bytes
0644
release-8-1-12.html
9341 bytes
0644
release-8-1-13.html
4292 bytes
0644
release-8-1-14.html
6901 bytes
0644
release-8-1-15.html
6274 bytes
0644
release-8-1-16.html
5278 bytes
0644
release-8-1-17.html
6035 bytes
0644
release-8-1-18.html
6442 bytes
0644
release-8-1-19.html
6612 bytes
0644
release-8-1-2.html
6335 bytes
0644
release-8-1-20.html
7298 bytes
0644
release-8-1-21.html
7213 bytes
0644
release-8-1-22.html
8324 bytes
0644
release-8-1-23.html
7933 bytes
0644
release-8-1-3.html
7026 bytes
0644
release-8-1-4.html
8873 bytes
0644
release-8-1-5.html
5479 bytes
0644
release-8-1-6.html
5337 bytes
0644
release-8-1-7.html
4558 bytes
0644
release-8-1-8.html
3116 bytes
0644
release-8-1-9.html
4388 bytes
0644
release-8-1.html
62113 bytes
0644
release-8-2-1.html
5065 bytes
0644
release-8-2-10.html
8180 bytes
0644
release-8-2-11.html
7147 bytes
0644
release-8-2-12.html
6748 bytes
0644
release-8-2-13.html
7348 bytes
0644
release-8-2-14.html
7876 bytes
0644
release-8-2-15.html
8155 bytes
0644
release-8-2-16.html
9293 bytes
0644
release-8-2-17.html
8214 bytes
0644
release-8-2-18.html
10277 bytes
0644
release-8-2-19.html
8589 bytes
0644
release-8-2-2.html
5802 bytes
0644
release-8-2-20.html
6244 bytes
0644
release-8-2-21.html
5593 bytes
0644
release-8-2-22.html
9617 bytes
0644
release-8-2-23.html
9559 bytes
0644
release-8-2-3.html
3095 bytes
0644
release-8-2-4.html
5428 bytes
0644
release-8-2-5.html
5995 bytes
0644
release-8-2-6.html
10551 bytes
0644
release-8-2-7.html
9311 bytes
0644
release-8-2-8.html
7521 bytes
0644
release-8-2-9.html
4281 bytes
0644
release-8-2.html
69398 bytes
0644
release-8-3-1.html
10585 bytes
0644
release-8-3-10.html
10725 bytes
0644
release-8-3-11.html
8963 bytes
0644
release-8-3-12.html
12119 bytes
0644
release-8-3-13.html
9506 bytes
0644
release-8-3-14.html
6242 bytes
0644
release-8-3-15.html
6381 bytes
0644
release-8-3-16.html
11015 bytes
0644
release-8-3-17.html
10590 bytes
0644
release-8-3-18.html
11265 bytes
0644
release-8-3-19.html
8466 bytes
0644
release-8-3-2.html
12203 bytes
0644
release-8-3-20.html
9251 bytes
0644
release-8-3-21.html
5034 bytes
0644
release-8-3-22.html
10585 bytes
0644
release-8-3-23.html
6284 bytes
0644
release-8-3-3.html
4275 bytes
0644
release-8-3-4.html
11273 bytes
0644
release-8-3-5.html
8689 bytes
0644
release-8-3-6.html
9197 bytes
0644
release-8-3-7.html
9729 bytes
0644
release-8-3-8.html
9260 bytes
0644
release-8-3-9.html
10206 bytes
0644
release-8-3.html
69773 bytes
0644
release-8-4-1.html
9563 bytes
0644
release-8-4-10.html
11932 bytes
0644
release-8-4-11.html
13787 bytes
0644
release-8-4-12.html
9987 bytes
0644
release-8-4-13.html
9714 bytes
0644
release-8-4-14.html
5117 bytes
0644
release-8-4-15.html
10626 bytes
0644
release-8-4-16.html
7329 bytes
0644
release-8-4-17.html
9572 bytes
0644
release-8-4-18.html
7048 bytes
0644
release-8-4-19.html
7780 bytes
0644
release-8-4-2.html
15697 bytes
0644
release-8-4-20.html
16258 bytes
0644
release-8-4-21.html
5450 bytes
0644
release-8-4-22.html
11306 bytes
0644
release-8-4-3.html
13928 bytes
0644
release-8-4-4.html
10736 bytes
0644
release-8-4-5.html
15933 bytes
0644
release-8-4-6.html
10430 bytes
0644
release-8-4-7.html
6220 bytes
0644
release-8-4-8.html
8850 bytes
0644
release-8-4-9.html
14528 bytes
0644
release-8-4.html
87976 bytes
0644
release-9-0-1.html
5946 bytes
0644
release-9-0-10.html
5693 bytes
0644
release-9-0-11.html
12666 bytes
0644
release-9-0-12.html
8824 bytes
0644
release-9-0-13.html
11671 bytes
0644
release-9-0-14.html
8759 bytes
0644
release-9-0-15.html
9147 bytes
0644
release-9-0-16.html
17408 bytes
0644
release-9-0-17.html
6335 bytes
0644
release-9-0-18.html
11879 bytes
0644
release-9-0-19.html
26610 bytes
0644
release-9-0-2.html
13636 bytes
0644
release-9-0-20.html
15836 bytes
0644
release-9-0-21.html
5166 bytes
0644
release-9-0-22.html
4321 bytes
0644
release-9-0-23.html
16158 bytes
0644
release-9-0-3.html
7256 bytes
0644
release-9-0-4.html
11345 bytes
0644
release-9-0-5.html
17915 bytes
0644
release-9-0-6.html
13426 bytes
0644
release-9-0-7.html
18091 bytes
0644
release-9-0-8.html
10993 bytes
0644
release-9-0-9.html
11743 bytes
0644
release-9-0.html
96127 bytes
0644
release-9-1-1.html
3670 bytes
0644
release-9-1-10.html
10352 bytes
0644
release-9-1-11.html
9584 bytes
0644
release-9-1-12.html
18554 bytes
0644
release-9-1-13.html
6685 bytes
0644
release-9-1-14.html
13036 bytes
0644
release-9-1-15.html
28969 bytes
0644
release-9-1-16.html
19119 bytes
0644
release-9-1-17.html
4947 bytes
0644
release-9-1-18.html
4102 bytes
0644
release-9-1-19.html
17617 bytes
0644
release-9-1-2.html
21571 bytes
0644
release-9-1-20.html
17541 bytes
0644
release-9-1-21.html
7601 bytes
0644
release-9-1-22.html
7258 bytes
0644
release-9-1-23.html
12653 bytes
0644
release-9-1-24.html
8731 bytes
0644
release-9-1-3.html
21153 bytes
0644
release-9-1-4.html
16018 bytes
0644
release-9-1-5.html
14042 bytes
0644
release-9-1-6.html
9521 bytes
0644
release-9-1-7.html
14941 bytes
0644
release-9-1-8.html
10154 bytes
0644
release-9-1-9.html
12679 bytes
0644
release-9-1.html
78963 bytes
0644
release-9-2-1.html
7111 bytes
0644
release-9-2-10.html
32368 bytes
0644
release-9-2-11.html
20298 bytes
0644
release-9-2-12.html
5130 bytes
0644
release-9-2-13.html
4102 bytes
0644
release-9-2-14.html
18386 bytes
0644
release-9-2-15.html
18605 bytes
0644
release-9-2-16.html
7598 bytes
0644
release-9-2-17.html
8195 bytes
0644
release-9-2-18.html
12718 bytes
0644
release-9-2-19.html
10514 bytes
0644
release-9-2-2.html
23001 bytes
0644
release-9-2-20.html
13332 bytes
0644
release-9-2-21.html
14198 bytes
0644
release-9-2-22.html
15865 bytes
0644
release-9-2-23.html
8126 bytes
0644
release-9-2-24.html
7877 bytes
0644
release-9-2-3.html
13373 bytes
0644
release-9-2-4.html
14800 bytes
0644
release-9-2-5.html
12005 bytes
0644
release-9-2-6.html
11684 bytes
0644
release-9-2-7.html
20022 bytes
0644
release-9-2-8.html
7375 bytes
0644
release-9-2-9.html
15615 bytes
0644
release-9-2.html
79519 bytes
0644
release.html
22882 bytes
0644
resources.html
4226 bytes
0644
role-attributes.html
7855 bytes
0644
role-membership.html
8390 bytes
0644
role-removal.html
5303 bytes
0644
routine-reindex.html
3628 bytes
0644
routine-vacuuming.html
38023 bytes
0644
row-estimation-examples.html
20767 bytes
0644
rowtypes.html
23412 bytes
0644
rule-system.html
4117 bytes
0644
rules-privileges.html
11663 bytes
0644
rules-status.html
4512 bytes
0644
rules-triggers.html
9476 bytes
0644
rules-update.html
32615 bytes
0644
rules-views.html
26888 bytes
0644
rules.html
4948 bytes
0644
runtime-config-autovacuum.html
10974 bytes
0644
runtime-config-client.html
32815 bytes
0644
runtime-config-compatible.html
14827 bytes
0644
runtime-config-connection.html
23478 bytes
0644
runtime-config-custom.html
3548 bytes
0644
runtime-config-developer.html
14070 bytes
0644
runtime-config-error-handling.html
3570 bytes
0644
runtime-config-file-locations.html
6977 bytes
0644
runtime-config-locks.html
7634 bytes
0644
runtime-config-logging.html
45446 bytes
0644
runtime-config-preset.html
8710 bytes
0644
runtime-config-query.html
24950 bytes
0644
runtime-config-replication.html
18294 bytes
0644
runtime-config-resource.html
27901 bytes
0644
runtime-config-short.html
6683 bytes
0644
runtime-config-statistics.html
8616 bytes
0644
runtime-config-wal.html
27093 bytes
0644
runtime-config.html
8249 bytes
0644
runtime.html
5241 bytes
0644
seg.html
15470 bytes
0644
sepgsql.html
30829 bytes
0644
server-programming.html
9618 bytes
0644
server-shutdown.html
6469 bytes
0644
server-start.html
14217 bytes
0644
source-format.html
5133 bytes
0644
source.html
4071 bytes
0644
sourcerepo.html
3411 bytes
0644
spgist-examples.html
2703 bytes
0644
spgist-extensibility.html
31282 bytes
0644
spgist-implementation.html
8098 bytes
0644
spgist-intro.html
4323 bytes
0644
spgist.html
2966 bytes
0644
spi-examples.html
6217 bytes
0644
spi-interface-support.html
3770 bytes
0644
spi-interface.html
5998 bytes
0644
spi-memory.html
7089 bytes
0644
spi-realloc.html
3627 bytes
0644
spi-spi-connect.html
4052 bytes
0644
spi-spi-copytuple.html
3453 bytes
0644
spi-spi-cursor-close.html
3336 bytes
0644
spi-spi-cursor-fetch.html
4110 bytes
0644
spi-spi-cursor-find.html
3464 bytes
0644
spi-spi-cursor-move.html
3890 bytes
0644
spi-spi-cursor-open-with-args.html
6178 bytes
0644
spi-spi-cursor-open-with-paramlist.html
5035 bytes
0644
spi-spi-cursor-open.html
5732 bytes
0644
spi-spi-exec.html
3591 bytes
0644
spi-spi-execp.html
4866 bytes
0644
spi-spi-execute-plan-with-paramlist.html
4893 bytes
0644
spi-spi-execute-plan.html
5901 bytes
0644
spi-spi-execute-with-args.html
6221 bytes
0644
spi-spi-execute.html
12598 bytes
0644
spi-spi-finish.html
3655 bytes
0644
spi-spi-fname.html
3767 bytes
0644
spi-spi-fnumber.html
3936 bytes
0644
spi-spi-freeplan.html
3505 bytes
0644
spi-spi-freetuple.html
3277 bytes
0644
spi-spi-freetupletable.html
3628 bytes
0644
spi-spi-getargcount.html
3698 bytes
0644
spi-spi-getargtypeid.html
4141 bytes
0644
spi-spi-getbinval.html
4287 bytes
0644
spi-spi-getnspname.html
3467 bytes
0644
spi-spi-getrelname.html
3351 bytes
0644
spi-spi-gettype.html
3714 bytes
0644
spi-spi-gettypeid.html
3718 bytes
0644
spi-spi-getvalue.html
4166 bytes
0644
spi-spi-is-cursor-plan.html
4560 bytes
0644
spi-spi-keepplan.html
3884 bytes
0644
spi-spi-modifytuple.html
5631 bytes
0644
spi-spi-palloc.html
3157 bytes
0644
spi-spi-pfree.html
3275 bytes
0644
spi-spi-pop.html
2743 bytes
0644
spi-spi-prepare-cursor.html
5055 bytes
0644
spi-spi-prepare-params.html
4412 bytes
0644
spi-spi-prepare.html
7661 bytes
0644
spi-spi-push.html
3737 bytes
0644
spi-spi-returntuple.html
4097 bytes
0644
spi-spi-saveplan.html
4576 bytes
0644
spi-spi-scroll-cursor-fetch.html
4809 bytes
0644
spi-spi-scroll-cursor-move.html
4899 bytes
0644
spi-visibility.html
4152 bytes
0644
spi.html
10843 bytes
0644
sql-abort.html
4177 bytes
0644
sql-alteraggregate.html
6111 bytes
0644
sql-altercollation.html
5084 bytes
0644
sql-alterconversion.html
5170 bytes
0644
sql-alterdatabase.html
8778 bytes
0644
sql-alterdefaultprivileges.html
9407 bytes
0644
sql-alterdomain.html
11113 bytes
0644
sql-alterextension.html
11745 bytes
0644
sql-alterforeigndatawrapper.html
7378 bytes
0644
sql-alterforeigntable.html
12707 bytes
0644
sql-alterfunction.html
12845 bytes
0644
sql-altergroup.html
5239 bytes
0644
sql-alterindex.html
7655 bytes
0644
sql-alterlanguage.html
4022 bytes
0644
sql-alterlargeobject.html
3730 bytes
0644
sql-alteropclass.html
5114 bytes
0644
sql-alteroperator.html
5435 bytes
0644
sql-alteropfamily.html
13564 bytes
0644
sql-alterrole.html
13028 bytes
0644
sql-alterschema.html
4314 bytes
0644
sql-altersequence.html
13031 bytes
0644
sql-alterserver.html
5928 bytes
0644
sql-altertable.html
43543 bytes
0644
sql-altertablespace.html
5866 bytes
0644
sql-altertrigger.html
4647 bytes
0644
sql-altertsconfig.html
8126 bytes
0644
sql-altertsdictionary.html
6539 bytes
0644
sql-altertsparser.html
4257 bytes
0644
sql-altertstemplate.html
4223 bytes
0644
sql-altertype.html
11193 bytes
0644
sql-alteruser.html
4720 bytes
0644
sql-alterusermapping.html
5714 bytes
0644
sql-alterview.html
6969 bytes
0644
sql-analyze.html
10674 bytes
0644
sql-begin.html
6695 bytes
0644
sql-checkpoint.html
3758 bytes
0644
sql-close.html
4984 bytes
0644
sql-cluster.html
9404 bytes
0644
sql-commands.html
18810 bytes
0644
sql-comment.html
13799 bytes
0644
sql-commit-prepared.html
4516 bytes
0644
sql-commit.html
3992 bytes
0644
sql-copy.html
37443 bytes
0644
sql-createaggregate.html
13829 bytes
0644
sql-createcast.html
19632 bytes
0644
sql-createcollation.html
6739 bytes
0644
sql-createconversion.html
6538 bytes
0644
sql-createdatabase.html
12133 bytes
0644
sql-createdomain.html
8544 bytes
0644
sql-createextension.html
9083 bytes
0644
sql-createforeigndatawrapper.html
8059 bytes
0644
sql-createforeigntable.html
7718 bytes
0644
sql-createfunction.html
31076 bytes
0644
sql-creategroup.html
4012 bytes
0644
sql-createindex.html
25934 bytes
0644
sql-createlanguage.html
14888 bytes
0644
sql-createopclass.html
12676 bytes
0644
sql-createoperator.html
10688 bytes
0644
sql-createopfamily.html
5626 bytes
0644
sql-createrole.html
19325 bytes
0644
sql-createrule.html
12656 bytes
0644
sql-createschema.html
8319 bytes
0644
sql-createsequence.html
13862 bytes
0644
sql-createserver.html
6251 bytes
0644
sql-createtable.html
59172 bytes
0644
sql-createtableas.html
12772 bytes
0644
sql-createtablespace.html
6104 bytes
0644
sql-createtrigger.html
23175 bytes
0644
sql-createtsconfig.html
5352 bytes
0644
sql-createtsdictionary.html
5533 bytes
0644
sql-createtsparser.html
5947 bytes
0644
sql-createtstemplate.html
5437 bytes
0644
sql-createtype.html
39460 bytes
0644
sql-createuser.html
4524 bytes
0644
sql-createusermapping.html
5503 bytes
0644
sql-createview.html
10556 bytes
0644
sql-deallocate.html
3785 bytes
0644
sql-declare.html
15400 bytes
0644
sql-delete.html
11777 bytes
0644
sql-discard.html
4309 bytes
0644
sql-do.html
5204 bytes
0644
sql-drop-owned.html
5058 bytes
0644
sql-dropaggregate.html
4561 bytes
0644
sql-dropcast.html
4344 bytes
0644
sql-dropcollation.html
4409 bytes
0644
sql-dropconversion.html
4437 bytes
0644
sql-dropdatabase.html
4344 bytes
0644
sql-dropdomain.html
4257 bytes
0644
sql-dropextension.html
4785 bytes
0644
sql-dropforeigndatawrapper.html
4526 bytes
0644
sql-dropforeigntable.html
4560 bytes
0644
sql-dropfunction.html
5838 bytes
0644
sql-dropgroup.html
3047 bytes
0644
sql-dropindex.html
5182 bytes
0644
sql-droplanguage.html
4841 bytes
0644
sql-dropopclass.html
5678 bytes
0644
sql-dropoperator.html
5222 bytes
0644
sql-dropopfamily.html
5279 bytes
0644
sql-droprole.html
5158 bytes
0644
sql-droprule.html
4151 bytes
0644
sql-dropschema.html
4529 bytes
0644
sql-dropsequence.html
4367 bytes
0644
sql-dropserver.html
4265 bytes
0644
sql-droptable.html
5028 bytes
0644
sql-droptablespace.html
4585 bytes
0644
sql-droptrigger.html
4711 bytes
0644
sql-droptsconfig.html
4772 bytes
0644
sql-droptsdictionary.html
4689 bytes
0644
sql-droptsparser.html
4595 bytes
0644
sql-droptstemplate.html
4567 bytes
0644
sql-droptype.html
4463 bytes
0644
sql-dropuser.html
3181 bytes
0644
sql-dropusermapping.html
4679 bytes
0644
sql-dropview.html
4262 bytes
0644
sql-end.html
4157 bytes
0644
sql-execute.html
5073 bytes
0644
sql-explain.html
17094 bytes
0644
sql-expressions.html
47801 bytes
0644
sql-fetch.html
14251 bytes
0644
sql-grant.html
29245 bytes
0644
sql-insert.html
12860 bytes
0644
sql-keywords-appendix.html
106534 bytes
0644
sql-listen.html
5903 bytes
0644
sql-load.html
4207 bytes
0644
sql-lock.html
11869 bytes
0644
sql-move.html
4984 bytes
0644
sql-notify.html
10948 bytes
0644
sql-prepare-transaction.html
8640 bytes
0644
sql-prepare.html
9181 bytes
0644
sql-reassign-owned.html
5344 bytes
0644
sql-reindex.html
11103 bytes
0644
sql-release-savepoint.html
5005 bytes
0644
sql-reset.html
4993 bytes
0644
sql-revoke.html
14879 bytes
0644
sql-rollback-prepared.html
4627 bytes
0644
sql-rollback-to.html
6401 bytes
0644
sql-rollback.html
3996 bytes
0644
sql-savepoint.html
5605 bytes
0644
sql-security-label.html
8879 bytes
0644
sql-select.html
79544 bytes
0644
sql-selectinto.html
7634 bytes
0644
sql-set-constraints.html
7068 bytes
0644
sql-set-role.html
6915 bytes
0644
sql-set-session-authorization.html
6062 bytes
0644
sql-set-transaction.html
12696 bytes
0644
sql-set.html
12057 bytes
0644
sql-show.html
6851 bytes
0644
sql-start-transaction.html
4983 bytes
0644
sql-syntax-calling-funcs.html
8080 bytes
0644
sql-syntax-lexical.html
43370 bytes
0644
sql-syntax.html
5430 bytes
0644
sql-truncate.html
9364 bytes
0644
sql-unlisten.html
4923 bytes
0644
sql-update.html
15669 bytes
0644
sql-vacuum.html
10669 bytes
0644
sql-values.html
10640 bytes
0644
sql.html
13569 bytes
0644
ssh-tunnels.html
6263 bytes
0644
ssl-tcp.html
13477 bytes
0644
sslinfo.html
7594 bytes
0644
standby-settings.html
5427 bytes
0644
storage-file-layout.html
12936 bytes
0644
storage-fsm.html
3821 bytes
0644
storage-init.html
2760 bytes
0644
storage-page-layout.html
13891 bytes
0644
storage-toast.html
11478 bytes
0644
storage-vm.html
3540 bytes
0644
storage.html
2952 bytes
0644
stylesheet.css
1538 bytes
0644
supported-platforms.html
5042 bytes
0644
tablefunc.html
32193 bytes
0644
tcn.html
4974 bytes
0644
test-parser.html
4530 bytes
0644
textsearch-configuration.html
6257 bytes
0644
textsearch-controls.html
26966 bytes
0644
textsearch-debugging.html
17227 bytes
0644
textsearch-dictionaries.html
31261 bytes
0644
textsearch-features.html
21310 bytes
0644
textsearch-indexes.html
7387 bytes
0644
textsearch-intro.html
18453 bytes
0644
textsearch-limitations.html
3859 bytes
0644
textsearch-migration.html
5034 bytes
0644
textsearch-parsers.html
9210 bytes
0644
textsearch-psql.html
9345 bytes
0644
textsearch-tables.html
9750 bytes
0644
textsearch.html
5878 bytes
0644
transaction-iso.html
27240 bytes
0644
trigger-datachanges.html
5072 bytes
0644
trigger-definition.html
15507 bytes
0644
trigger-example.html
7749 bytes
0644
trigger-interface.html
10719 bytes
0644
triggers.html
3798 bytes
0644
tsearch2.html
9950 bytes
0644
tutorial-accessdb.html
7040 bytes
0644
tutorial-advanced-intro.html
3341 bytes
0644
tutorial-advanced.html
2856 bytes
0644
tutorial-agg.html
7594 bytes
0644
tutorial-arch.html
4852 bytes
0644
tutorial-concepts.html
3839 bytes
0644
tutorial-conclusion.html
2849 bytes
0644
tutorial-createdb.html
9200 bytes
0644
tutorial-delete.html
3517 bytes
0644
tutorial-fk.html
4422 bytes
0644
tutorial-inheritance.html
6137 bytes
0644
tutorial-install.html
4522 bytes
0644
tutorial-join.html
9685 bytes
0644
tutorial-populate.html
4839 bytes
0644
tutorial-select.html
8033 bytes
0644
tutorial-sql-intro.html
4904 bytes
0644
tutorial-sql.html
3060 bytes
0644
tutorial-start.html
2629 bytes
0644
tutorial-table.html
5704 bytes
0644
tutorial-transactions.html
9948 bytes
0644
tutorial-update.html
3159 bytes
0644
tutorial-views.html
3375 bytes
0644
tutorial-window.html
12481 bytes
0644
tutorial.html
5209 bytes
0644
typeconv-func.html
12170 bytes
0644
typeconv-oper.html
14907 bytes
0644
typeconv-overview.html
8301 bytes
0644
typeconv-query.html
5450 bytes
0644
typeconv-union-case.html
6612 bytes
0644
typeconv.html
3721 bytes
0644
unaccent.html
6742 bytes
0644
unsupported-features-sql-standard.html
35115 bytes
0644
upgrading.html
12795 bytes
0644
user-manag.html
3983 bytes
0644
using-explain.html
41824 bytes
0644
uuid-ossp.html
7228 bytes
0644
vacuumlo.html
7548 bytes
0644
view-pg-available-extension-versions.html
4642 bytes
0644
view-pg-available-extensions.html
3944 bytes
0644
view-pg-cursors.html
5669 bytes
0644
view-pg-group.html
3897 bytes
0644
view-pg-indexes.html
4155 bytes
0644
view-pg-locks.html
14444 bytes
0644
view-pg-prepared-statements.html
5060 bytes
0644
view-pg-prepared-xacts.html
4912 bytes
0644
view-pg-roles.html
6073 bytes
0644
view-pg-rules.html
3999 bytes
0644
view-pg-seclabels.html
5123 bytes
0644
view-pg-settings.html
10600 bytes
0644
view-pg-shadow.html
5381 bytes
0644
view-pg-stats.html
8887 bytes
0644
view-pg-tables.html
4836 bytes
0644
view-pg-timezone-abbrevs.html
3860 bytes
0644
view-pg-timezone-names.html
4177 bytes
0644
view-pg-user-mappings.html
5165 bytes
0644
view-pg-user.html
4517 bytes
0644
view-pg-views.html
3853 bytes
0644
views-overview.html
6542 bytes
0644
wal-async-commit.html
9016 bytes
0644
wal-configuration.html
14960 bytes
0644
wal-internals.html
6151 bytes
0644
wal-intro.html
5534 bytes
0644
wal-reliability.html
11479 bytes
0644
wal.html
2928 bytes
0644
warm-standby-failover.html
6102 bytes
0644
warm-standby.html
34646 bytes
0644
xaggr.html
9902 bytes
0644
xfunc-c.html
78520 bytes
0644
xfunc-internal.html
4004 bytes
0644
xfunc-overload.html
5911 bytes
0644
xfunc-pl.html
2991 bytes
0644
xfunc-sql.html
38027 bytes
0644
xfunc-volatility.html
9839 bytes
0644
xfunc.html
4518 bytes
0644
xindex.html
44593 bytes
0644
xml2.html
16900 bytes
0644
xoper-optimization.html
23144 bytes
0644
xoper.html
4835 bytes
0644
xplang-install.html
11127 bytes
0644
xplang.html
4235 bytes
0644
xtypes.html
12114 bytes
0644
N4ST4R_ID | Naxtarrr