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

📄 spi.sgml

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 SGML
📖 第 1 页 / 共 5 页
字号:
<!--$PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.43.2.1 2005/12/07 15:39:32 tgl Exp $--><chapter id="spi"> <title>Server Programming Interface</title> <indexterm zone="spi">  <primary>SPI</primary> </indexterm> <para>  The <firstterm>Server Programming Interface</firstterm>  (<acronym>SPI</acronym>) gives writers of user-defined  <acronym>C</acronym> functions the ability to run  <acronym>SQL</acronym> commands inside their functions.  <acronym>SPI</acronym> is a set of  interface functions to simplify access to the parser, planner,  optimizer, and executor. <acronym>SPI</acronym> also does some  memory management. </para> <note>  <para>   The available procedural languages provide various means to   execute SQL commands from procedures.  Most of these facilities are   based on SPI, so this documentation might be of use for users   of those languages as well.  </para> </note> <para>  To avoid misunderstanding we'll use the term <quote>function</quote>  when we speak of <acronym>SPI</acronym> interface functions and  <quote>procedure</quote> for a user-defined C-function that is  using <acronym>SPI</acronym>. </para> <para>  Note that if a command invoked via SPI fails, then control will not be  returned to your procedure.  Rather, the  transaction or subtransaction in which your procedure executes will be  rolled back.  (This may seem surprising given that the SPI functions mostly  have documented error-return conventions.  Those conventions only apply  for errors detected within the SPI functions themselves, however.)  It is possible to recover control after an error by establishing your own  subtransaction surrounding SPI calls that might fail.  This is not currently  documented because the mechanisms required are still in flux. </para> <para>  <acronym>SPI</acronym> functions return a nonnegative result on  success (either via a returned integer value or in the global  variable <varname>SPI_result</varname>, as described below).  On  error, a negative result or <symbol>NULL</symbol> will be returned. </para> <para>  Source code files that use SPI must include the header file  <filename>executor/spi.h</filename>. </para><sect1 id="spi-interface"> <title>Interface Functions</title> <refentry id="spi-spi-connect">  <refmeta>   <refentrytitle>SPI_connect</refentrytitle>  </refmeta>  <refnamediv>   <refname>SPI_connect</refname>   <refpurpose>connect a procedure to the SPI manager</refpurpose> </refnamediv> <indexterm><primary>SPI_connect</primary></indexterm> <refsynopsisdiv><synopsis>int SPI_connect(void)</synopsis> </refsynopsisdiv> <refsect1>  <title>Description</title>  <para>   <function>SPI_connect</function> opens a connection from a   procedure invocation to the SPI manager.  You must call this   function if you want to execute commands through SPI.  Some utility   SPI functions may be called from unconnected procedures.  </para>  <para>   If your procedure is already connected,   <function>SPI_connect</function> will return the error code   <returnvalue>SPI_ERROR_CONNECT</returnvalue>.  This could happen if   a procedure that has called <function>SPI_connect</function>   directly calls another procedure that calls   <function>SPI_connect</function>.  While recursive calls to the   <acronym>SPI</acronym> manager are permitted when an SQL command   called through SPI invokes another function that uses   <acronym>SPI</acronym>, directly nested calls to   <function>SPI_connect</function> and   <function>SPI_finish</function> are forbidden.   (But see <function>SPI_push</function> and <function>SPI_pop</function>.)  </para> </refsect1> <refsect1>  <title>Return Value</title>  <variablelist>   <varlistentry>    <term><symbol>SPI_OK_CONNECT</symbol></term>    <listitem>     <para>      on success     </para>    </listitem>   </varlistentry>   <varlistentry>    <term><symbol>SPI_ERROR_CONNECT</symbol></term>    <listitem>     <para>      on error     </para>    </listitem>   </varlistentry>  </variablelist> </refsect1></refentry><!-- *********************************************** --><refentry id="spi-spi-finish"> <refmeta>  <refentrytitle>SPI_finish</refentrytitle> </refmeta> <refnamediv>  <refname>SPI_finish</refname>  <refpurpose>disconnect a procedure from the SPI manager</refpurpose> </refnamediv> <indexterm><primary>SPI_finish</primary></indexterm> <refsynopsisdiv><synopsis>int SPI_finish(void)</synopsis> </refsynopsisdiv> <refsect1>  <title>Description</title>  <para>   <function>SPI_finish</function> closes an existing connection to   the SPI manager.  You must call this function after completing the   SPI operations needed during your procedure's current invocation.   You do not need to worry about making this happen, however, if you   abort the transaction via <literal>elog(ERROR)</literal>.  In that   case SPI will clean itself up automatically.  </para>  <para>   If <function>SPI_finish</function> is called without having a valid   connection, it will return <symbol>SPI_ERROR_UNCONNECTED</symbol>.   There is no fundamental problem with this; it means that the SPI   manager has nothing to do.  </para> </refsect1> <refsect1>  <title>Return Value</title>  <variablelist>   <varlistentry>    <term><symbol>SPI_OK_FINISH</symbol></term>    <listitem>     <para>      if properly disconnected     </para>    </listitem>   </varlistentry>   <varlistentry>    <term><symbol>SPI_ERROR_UNCONNECTED</symbol></term>    <listitem>     <para>      if called from an unconnected procedure     </para>    </listitem>   </varlistentry>  </variablelist> </refsect1></refentry><!-- *********************************************** --><refentry id="spi-spi-push"> <refmeta>  <refentrytitle>SPI_push</refentrytitle> </refmeta> <refnamediv>  <refname>SPI_push</refname>  <refpurpose>push SPI stack to allow recursive SPI usage</refpurpose> </refnamediv> <indexterm><primary>SPI_push</primary></indexterm> <refsynopsisdiv><synopsis>void SPI_push(void)</synopsis> </refsynopsisdiv> <refsect1>  <title>Description</title>  <para>   <function>SPI_push</function> should be called before executing another   procedure that might itself wish to use SPI.   After <function>SPI_push</function>, SPI is no longer in a   <quote>connected</> state, and SPI function calls will be rejected unless   a fresh <function>SPI_connect</function> is done.  This ensures a clean   separation between your procedure's SPI state and that of another procedure   you call.  After the other procedure returns, call   <function>SPI_pop</function> to restore access to your own SPI state.  </para>  <para>   Note that <function>SPI_execute</function> and related functions   automatically do the equivalent of <function>SPI_push</function> before   passing control back to the SQL execution engine, so it is not necessary   for you to worry about this when using those functions.   Only when you are directly calling arbitrary code that might contain   <function>SPI_connect</function> calls do you need to issue   <function>SPI_push</function> and <function>SPI_pop</function>.  </para> </refsect1></refentry><!-- *********************************************** --><refentry id="spi-spi-pop"> <refmeta>  <refentrytitle>SPI_pop</refentrytitle> </refmeta> <refnamediv>  <refname>SPI_pop</refname>  <refpurpose>pop SPI stack to return from recursive SPI usage</refpurpose> </refnamediv> <indexterm><primary>SPI_pop</primary></indexterm> <refsynopsisdiv><synopsis>void SPI_pop(void)</synopsis> </refsynopsisdiv> <refsect1>  <title>Description</title>  <para>   <function>SPI_pop</function> pops the previous environment from the    SPI call stack.  See <function>SPI_push</function>.  </para> </refsect1></refentry><!-- *********************************************** --><refentry id="spi-spi-execute"> <refmeta>  <refentrytitle>SPI_execute</refentrytitle> </refmeta> <refnamediv>  <refname>SPI_execute</refname>  <refpurpose>execute a command</refpurpose> </refnamediv> <indexterm><primary>SPI_execute</primary></indexterm> <refsynopsisdiv><synopsis>int SPI_execute(const char * <parameter>command</parameter>, bool <parameter>read_only</parameter>, long <parameter>count</parameter>)</synopsis> </refsynopsisdiv> <refsect1>  <title>Description</title>  <para>   <function>SPI_execute</function> executes the specified SQL command   for <parameter>count</parameter> rows.  If <parameter>read_only</parameter>   is <literal>true</>, the command must be read-only, and execution overhead   is somewhat reduced.  </para>  <para>   This function may only be called from a connected procedure.  </para>  <para>   If <parameter>count</parameter> is zero then the command is executed   for all rows that it applies to.  If <parameter>count</parameter>   is greater than 0, then the number of rows for which the command   will be executed is restricted (much like a   <literal>LIMIT</literal> clause). For example,<programlisting>SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);</programlisting>   will allow at most 5 rows to be inserted into the table.  </para>  <para>   You may pass multiple commands in one string.   <function>SPI_execute</function> returns the   result for the command executed last.  The <parameter>count</parameter>   limit applies to each command separately, but it is not applied to   hidden commands generated by rules.  </para>  <para>   When <parameter>read_only</parameter> is <literal>false</>,   <function>SPI_execute</function> increments the command   counter and computes a new <firstterm>snapshot</> before executing each   command in the string.  The snapshot does not actually change if the   current transaction isolation level is <literal>SERIALIZABLE</>, but in   <literal>READ COMMITTED</> mode the snapshot update allows each command to   see the results of newly committed transactions from other sessions.   This is essential for consistent behavior when the commands are modifying   the database.  </para>  <para>   When <parameter>read_only</parameter> is <literal>true</>,   <function>SPI_execute</function> does not update either the snapshot   or the command counter, and it allows only plain <command>SELECT</>   commands to appear in the command string.  The commands are executed   using the snapshot previously established for the surrounding query.   This execution mode is somewhat faster than the read/write mode due   to eliminating per-command overhead.  It also allows genuinely   <firstterm>stable</> functions to be built: since successive executions   will all use the same snapshot, there will be no change in the results.  </para>  <para>   It is generally unwise to mix read-only and read-write commands within   a single function using SPI; that could result in very confusing behavior,   since the read-only queries would not see the results of any database   updates done by the read-write queries.  </para>  <para>   The actual number of rows for which the (last) command was executed   is returned in the global variable <varname>SPI_processed</varname>   (unless the return value of the function is   <symbol>SPI_OK_UTILITY</symbol>).  If the return value of the   function is <symbol>SPI_OK_SELECT</symbol> then you may use the   global pointer <literal>SPITupleTable *SPI_tuptable</literal> to   access the result rows.  </para>  <para>   The structure <structname>SPITupleTable</structname> is defined   thus:<programlisting>typedef struct{    MemoryContext tuptabcxt;    /* memory context of result table */    uint32      alloced;        /* number of alloced vals */    uint32      free;           /* number of free vals */    TupleDesc   tupdesc;        /* row descriptor */    HeapTuple  *vals;           /* rows */} SPITupleTable;</programlisting>   <structfield>vals</> is an array of pointers to rows.  (The number   of valid entries is given by <varname>SPI_processed</varname>.)   <structfield>tupdesc</> is a row descriptor which you may pass to   SPI functions dealing with rows.  <structfield>tuptabcxt</>,   <structfield>alloced</>, and <structfield>free</> are internal   fields not intended for use by SPI callers.  </para>  <para>   <function>SPI_finish</function> frees all   <structname>SPITupleTable</>s allocated during the current   procedure.  You can free a particular result table earlier, if you   are done with it, by calling <function>SPI_freetuptable</function>.  </para> </refsect1> <refsect1>  <title>Arguments</title>  <variablelist>   <varlistentry>    <term><literal>const char * <parameter>command</parameter></literal></term>    <listitem>     <para>      string containing command to execute     </para>    </listitem>   </varlistentry>   <varlistentry>    <term><literal>bool <parameter>read_only</parameter></literal></term>    <listitem>     <para>      <literal>true</> for read-only execution     </para>    </listitem>   </varlistentry>   <varlistentry>    <term><literal>long <parameter>count</parameter></literal></term>    <listitem>     <para>      maximum number of rows to process or return     </para>    </listitem>   </varlistentry>  </variablelist> </refsect1> <refsect1>  <title>Return Value</title>  <para>   If the execution of the command was successful then one of the   following (nonnegative) values will be returned:   <variablelist>    <varlistentry>     <term><symbol>SPI_OK_SELECT</symbol></term>     <listitem>      <para>       if a <command>SELECT</command> (but not <command>SELECT       INTO</>) was executed      </para>     </listitem>    </varlistentry>    <varlistentry>     <term><symbol>SPI_OK_SELINTO</symbol></term>     <listitem>      <para>       if a <command>SELECT INTO</command> was executed      </para>     </listitem>    </varlistentry>    <varlistentry>     <term><symbol>SPI_OK_DELETE</symbol></term>     <listitem>      <para>       if a <command>DELETE</command> was executed      </para>     </listitem>    </varlistentry>    <varlistentry>     <term><symbol>SPI_OK_INSERT</symbol></term>     <listitem>      <para>       if an <command>INSERT</command> was executed      </para>     </listitem>    </varlistentry>    <varlistentry>     <term><symbol>SPI_OK_UPDATE</symbol></term>     <listitem>      <para>       if an <command>UPDATE</command> was executed      </para>     </listitem>    </varlistentry>    <varlistentry>

⌨️ 快捷键说明

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