⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xfunc.sgml

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 SGML
📖 第 1 页 / 共 5 页
字号:
         <entry><type>xid</type></entry>         <entry><type>TransactionId</type></entry>         <entry><filename>postgres.h</filename></entry>        </row>       </tbody>      </tgroup>     </table>    <para>     Now that we've gone over all of the possible structures     for base types, we can show some examples of real functions.    </para>   </sect2>   <sect2>    <title>Calling Conventions Version 0 for C-Language Functions</title>    <para>     We present the <quote>old style</quote> calling convention first &mdash; 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.    </para>    <para>     Here are some examples:<programlisting>#include "postgres.h"#include &lt;string.h&gt;/* by value */         intadd_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-&gt;x = pointx-&gt;x;    new_point-&gt;y = pointy-&gt;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));    VARATT_SIZEP(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);    VARATT_SIZEP(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;}</programlisting>    </para>    <para>     Supposing that the above code has been prepared in file     <filename>funcs.c</filename> and compiled into a shared object,     we could define the functions to <productname>PostgreSQL</productname>     with commands like this:     <programlisting>CREATE FUNCTION add_one(integer) RETURNS integer     AS '<replaceable>DIRECTORY</replaceable>/funcs', 'add_one'     LANGUAGE C STRICT;-- note overloading of SQL function name "add_one"CREATE FUNCTION add_one(double precision) RETURNS double precision     AS '<replaceable>DIRECTORY</replaceable>/funcs', 'add_one_float8'     LANGUAGE C STRICT;CREATE FUNCTION makepoint(point, point) RETURNS point     AS '<replaceable>DIRECTORY</replaceable>/funcs', 'makepoint'     LANGUAGE C STRICT;                         CREATE FUNCTION copytext(text) RETURNS text     AS '<replaceable>DIRECTORY</replaceable>/funcs', 'copytext'     LANGUAGE C STRICT;CREATE FUNCTION concat_text(text, text) RETURNS text     AS '<replaceable>DIRECTORY</replaceable>/funcs', 'concat_text'     LANGUAGE C STRICT;</programlisting>    </para>    <para>     Here, <replaceable>DIRECTORY</replaceable> stands for the     directory of the shared library file (for instance the     <productname>PostgreSQL</productname> tutorial directory, which     contains the code for the examples used in this section).     (Better style would be to use just <literal>'funcs'</> in the     <literal>AS</> clause, after having added     <replaceable>DIRECTORY</replaceable> to the search path.  In any     case, we may omit the system-specific extension for a shared     library, commonly <literal>.so</literal> or     <literal>.sl</literal>.)    </para>    <para>     Notice that we have specified the functions as <quote>strict</quote>,     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!)    </para>    <para>     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 <type>int</type> 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.    </para>   </sect2>   <sect2>    <title>Calling Conventions Version 1 for C-Language Functions</title>    <para>     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<programlisting>Datum funcname(PG_FUNCTION_ARGS)</programlisting>     In addition, the macro call<programlisting>PG_FUNCTION_INFO_V1(funcname);</programlisting>     must appear in the same source file.  (Conventionally. it's     written just before the function itself.)  This macro call is not     needed for <literal>internal</>-language functions, since     <productname>PostgreSQL</> assumes that all internal functions     use the version-1 convention.  It is, however, required for     dynamically-loaded functions.    </para>    <para>     In a version-1 function, each actual argument is fetched using a     <function>PG_GETARG_<replaceable>xxx</replaceable>()</function>     macro that corresponds to the argument's data type, and the     result is returned using a     <function>PG_RETURN_<replaceable>xxx</replaceable>()</function>     macro for the return type.     <function>PG_GETARG_<replaceable>xxx</replaceable>()</function>     takes as its argument the number of the function argument to     fetch, where the count starts at 0.     <function>PG_RETURN_<replaceable>xxx</replaceable>()</function>     takes as its argument the actual value to return.    </para>    <para>     Here we show the same functions as above, coded in version-1 style:<programlisting>#include "postgres.h"#include &lt;string.h&gt;#include "fmgr.h"/* by value */PG_FUNCTION_INFO_V1(add_one);         Datumadd_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);Datumadd_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);Datummakepoint(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-&gt;x = pointx-&gt;x;    new_point-&gt;y = pointy-&gt;y;           PG_RETURN_POINT_P(new_point);}/* by reference, variable length */PG_FUNCTION_INFO_V1(copytext);Datumcopytext(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));    VARATT_SIZEP(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);Datumconcat_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);    VARATT_SIZEP(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);}</programlisting>    </para>    <para>     The <command>CREATE FUNCTION</command> commands are the same as     for the version-0 equivalents.    </para>    <para>     At first glance, the version-1 coding conventions may 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 <function>add_one_float8</>, we no longer need to     be aware that <type>float8</type> is a pass-by-reference type.  Another     example is that the <literal>GETARG</> macros for variable-length types allow     for more efficient fetching of <quote>toasted</quote> (compressed or     out-of-line) values.    </para>    <para>     One big improvement in version-1 functions is better handling of null     inputs and results.  The macro <function>PG_ARGISNULL(<replaceable>n</>)</function>     allows a function to test whether each input is null.  (Of course, doing     this is only necessary in functions not declared <quote>strict</>.)     As with the     <function>PG_GETARG_<replaceable>xxx</replaceable>()</function> macros,     the input arguments are counted beginning at zero.  Note that one     should refrain from executing     <function>PG_GETARG_<replaceable>xxx</replaceable>()</function> until     one has verified that the argument isn't null.     To return a null result, execute <function>PG_RETURN_NULL()</function>;     this works in both strict and nonstrict functions.    </para>    <para>     Other options provided in the new-style interface are two     variants of the     <function>PG_GETARG_<replaceable>xxx</replaceable>()</function>     macros. The first of these,     <function>PG_GETARG_<replaceable>xxx</replaceable>_COPY()</function>,     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     <function>PG_GETARG_<replaceable>xxx</replaceable>_COPY()</function>     macros guarantees a writable result.)    The second variant consists of the    <function>PG_GETARG_<replaceable>xxx</replaceable>_SLICE()</function>    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    <quote>external</quote>. (The storage type of a column can be specified using    <literal>ALTER TABLE <replaceable>tablename</replaceable> ALTER    COLUMN <replaceable>colname</replaceable> SET STORAGE    <replaceable>storagetype</replaceable></literal>. <replaceable>storagetype</replaceable> is one of    <literal>plain</>, <literal>external</>, <literal>extended</literal>,     or <literal>main</>.)    </para>    <para>     Finally, the version-1 function call conventions make it possible     to return set results (<xref linkend="xfunc-c-return-set">) and     implement trigger functions (<xref linkend="triggers">) and     procedural-language call handlers (<xref     linkend="plhandler">).  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 <filename>src/backend/utils/fmgr/README</filename> in the     source distribution.    </para>   </sect2>   <sect2>    <title>Writing Code</title>    <para>     Before we turn to the more advanced topics, we should discuss     some coding rules for <productname>PostgreSQL</productname>     C-language functions.  While it may be possible to load functions     written in languages other than C into     <productname>PostgreSQL</productname>, 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.    </para>    <para>     The basic rules for writing and building C functions are as follows:     <itemizedlist>      <listitem>       <para>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -