📄 xfunc.sgml
字号:
that fails as well, the load will fail. </para> <para> The user ID the <productname>PostgreSQL</productname> 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 <systemitem>postgres</systemitem> user is a common mistake. </para> <para> In any case, the file name that is given in the <command>CREATE FUNCTION</command> command is recorded literally in the system catalogs, so if the file needs to be loaded again the same procedure is applied. </para> <note> <para> <productname>PostgreSQL</productname> will not compile a C function automatically. The object file must be compiled before it is referenced in a <command>CREATE FUNCTION</> command. See <xref linkend="dfunc"> for additional information. </para> </note> <para> 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, use the <xref linkend="sql-load" endterm="sql-load-title"> command or begin a fresh session. </para> <para> It is recommended to locate shared libraries either relative to <literal>$libdir</literal> or through the dynamic library path. This simplifies version upgrades if the new installation is at a different location. The actual directory that <literal>$libdir</literal> stands for can be found out with the command <literal>pg_config --pkglibdir</literal>. </para> <para> Before <productname>PostgreSQL</productname> release 7.2, only exact absolute paths to object files could be specified in <command>CREATE FUNCTION</>. This approach is now deprecated since it makes the function definition unnecessarily unportable. It's best to specify just the shared library name with no path nor extension, and let the search mechanism provide that information instead. </para> </sect2> <sect2 id="xfunc-c-basetype"> <title>Base Types in C-Language Functions</title> <indexterm zone="xfunc-c-basetype"> <primary>data type</primary> <secondary>internal organization</secondary> </indexterm> <para> To know how to write C-language functions, you need to know how <productname>PostgreSQL</productname> internally represents base data types and how they can be passed to and from functions. Internally, <productname>PostgreSQL</productname> regards a base type as a <quote>blob of memory</quote>. The user-defined functions that you define over a type in turn define the way that <productname>PostgreSQL</productname> can operate on it. That is, <productname>PostgreSQL</productname> will only store and retrieve the data from disk and use your user-defined functions to input, process, and output the data. </para> <para> Base types can have one of three internal formats: <itemizedlist> <listitem> <para> pass by value, fixed-length </para> </listitem> <listitem> <para> pass by reference, fixed-length </para> </listitem> <listitem> <para> pass by reference, variable-length </para> </listitem> </itemizedlist> </para> <para> By-value types can only be 1, 2, or 4 bytes in length (also 8 bytes, if <literal>sizeof(Datum)</literal> 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 <literal>long</literal> type is dangerous because it is 4 bytes on some machines and 8 bytes on others, whereas <type>int</type> type is 4 bytes on most Unix machines. A reasonable implementation of the <type>int4</type> type on Unix machines might be: <programlisting>/* 4-byte integer, passed by value */typedef int int4;</programlisting> </para> <para> On the other hand, fixed-length types of any size may be passed by-reference. For example, here is a sample implementation of a <productname>PostgreSQL</productname> type: <programlisting>/* 16-byte structure, passed by reference */typedef struct{ double x, y;} Point;</programlisting> Only pointers to such types can be used when passing them in and out of <productname>PostgreSQL</productname> functions. To return a value of such a type, allocate the right amount of memory with <literal>palloc</literal>, 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 <literal>palloc</literal> and just return the pointer to the input value.) </para> <para> Finally, all variable-length types must also be passed by reference. All variable-length types must begin with a length field of exactly 4 bytes, and 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. </para> <warning> <para> <emphasis>Never</> 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 may well point directly into a disk buffer. The sole exception to this rule is explained in <xref linkend="xaggr">. </para> </warning> <para> As an example, we can define the type <type>text</type> as follows:<programlisting>typedef struct { int4 length; char data[1];} text;</programlisting> 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>C</acronym>, we rely on the knowledge that the <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.) </para> <para> 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 <structname>text</> structure, we might use a code fragment like this:<programlisting>#include "postgres.h"...char buffer[40]; /* our source data */...text *destination = (text *) palloc(VARHDRSZ + 40);destination->length = VARHDRSZ + 40;memcpy(destination->data, buffer, 40);...</programlisting> <literal>VARHDRSZ</> is the same as <literal>sizeof(int4)</>, but it's considered good style to use the macro <literal>VARHDRSZ</> to refer to the size of the overhead for a variable-length type. </para> <para> <xref linkend="xfunc-c-type-table"> specifies which C type corresponds to which SQL type when writing a C-language function that uses a built-in type of <productname>PostgreSQL</>. The <quote>Defined In</quote> column gives the header file that needs to be included to get the type definition. (The actual definition may 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 <filename>postgres.h</filename> first in any source file, because it declares a number of things that you will need anyway. </para> <table tocentry="1" id="xfunc-c-type-table"> <title>Equivalent C Types for Built-In SQL Types</title> <tgroup cols="3"> <thead> <row> <entry> SQL Type </entry> <entry> C Type </entry> <entry> Defined In </entry> </row> </thead> <tbody> <row> <entry><type>abstime</type></entry> <entry><type>AbsoluteTime</type></entry> <entry><filename>utils/nabstime.h</filename></entry> </row> <row> <entry><type>boolean</type></entry> <entry><type>bool</type></entry> <entry><filename>postgres.h</filename> (maybe compiler built-in)</entry> </row> <row> <entry><type>box</type></entry> <entry><type>BOX*</type></entry> <entry><filename>utils/geo_decls.h</filename></entry> </row> <row> <entry><type>bytea</type></entry> <entry><type>bytea*</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>"char"</type></entry> <entry><type>char</type></entry> <entry>(compiler built-in)</entry> </row> <row> <entry><type>character</type></entry> <entry><type>BpChar*</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>cid</type></entry> <entry><type>CommandId</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>date</type></entry> <entry><type>DateADT</type></entry> <entry><filename>utils/date.h</filename></entry> </row> <row> <entry><type>smallint</type> (<type>int2</type>)</entry> <entry><type>int2</type> or <type>int16</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>int2vector</type></entry> <entry><type>int2vector*</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>integer</type> (<type>int4</type>)</entry> <entry><type>int4</type> or <type>int32</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>real</type> (<type>float4</type>)</entry> <entry><type>float4*</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>double precision</type> (<type>float8</type>)</entry> <entry><type>float8*</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>interval</type></entry> <entry><type>Interval*</type></entry> <entry><filename>utils/timestamp.h</filename></entry> </row> <row> <entry><type>lseg</type></entry> <entry><type>LSEG*</type></entry> <entry><filename>utils/geo_decls.h</filename></entry> </row> <row> <entry><type>name</type></entry> <entry><type>Name</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>oid</type></entry> <entry><type>Oid</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>oidvector</type></entry> <entry><type>oidvector*</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>path</type></entry> <entry><type>PATH*</type></entry> <entry><filename>utils/geo_decls.h</filename></entry> </row> <row> <entry><type>point</type></entry> <entry><type>POINT*</type></entry> <entry><filename>utils/geo_decls.h</filename></entry> </row> <row> <entry><type>regproc</type></entry> <entry><type>regproc</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>reltime</type></entry> <entry><type>RelativeTime</type></entry> <entry><filename>utils/nabstime.h</filename></entry> </row> <row> <entry><type>text</type></entry> <entry><type>text*</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row> <entry><type>tid</type></entry> <entry><type>ItemPointer</type></entry> <entry><filename>storage/itemptr.h</filename></entry> </row> <row> <entry><type>time</type></entry> <entry><type>TimeADT</type></entry> <entry><filename>utils/date.h</filename></entry> </row> <row> <entry><type>time with time zone</type></entry> <entry><type>TimeTzADT</type></entry> <entry><filename>utils/date.h</filename></entry> </row> <row> <entry><type>timestamp</type></entry> <entry><type>Timestamp*</type></entry> <entry><filename>utils/timestamp.h</filename></entry> </row> <row> <entry><type>tinterval</type></entry> <entry><type>TimeInterval</type></entry> <entry><filename>utils/nabstime.h</filename></entry> </row> <row> <entry><type>varchar</type></entry> <entry><type>VarChar*</type></entry> <entry><filename>postgres.h</filename></entry> </row> <row>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -