]> granicus.if.org Git - postgresql/blob - doc/src/sgml/spi.sgml
Overhaul SPI documentation: bring it into some semblance of agreement
[postgresql] / doc / src / sgml / spi.sgml
1 <!--
2 $Header: /cvsroot/pgsql/doc/src/sgml/spi.sgml,v 1.19 2001/11/14 22:26:02 tgl Exp $
3 -->
4
5 <Chapter id="spi">
6 <DocInfo>
7 <AuthorGroup>
8 <Author>
9 <FirstName>Vadim</FirstName>
10 <Surname>Mikheev</Surname>
11 </Author>
12 </AuthorGroup>
13 <Date>Transcribed 1998-01-16</Date>
14 </DocInfo>
15
16 <Title>Server Programming Interface</Title>
17
18 <Para>
19 The <FirstTerm>Server Programming Interface</FirstTerm> 
20 (<Acronym>SPI</Acronym>) gives users the
21 ability to run <Acronym>SQL</Acronym> queries inside user-defined 
22 <Acronym>C</Acronym> functions.
23 </Para>
24
25 <note>
26 <para>
27 The available Procedural Languages (<Acronym>PL</Acronym>) give an alternate
28 means to build functions that can execute queries.
29 </para>
30 </note>
31
32 <Para>
33 In fact, <Acronym>SPI</Acronym> is just a set of native interface functions
34 to simplify access to the Parser, Planner, Optimizer and Executor. 
35 <Acronym>SPI</Acronym> also does some memory management.
36 </Para>
37
38 <Para>
39 To avoid misunderstanding we'll use <FirstTerm>function</FirstTerm> 
40 to mean <Acronym>SPI</Acronym> interface functions and 
41 <FirstTerm>procedure</FirstTerm> for user-defined C-functions 
42 using <Acronym>SPI</Acronym>.
43 </Para>
44
45 <Para>
46 Procedures which use <Acronym>SPI</Acronym> are called by the
47 Executor.  The <Acronym>SPI</Acronym> calls recursively invoke the
48 Executor in turn to run queries.  When the Executor is invoked
49 recursively, it may itself call procedures which may make
50 <Acronym>SPI</Acronym> calls.
51 </Para>
52
53 <Para>
54 Note that if during execution of a query from a procedure the transaction is
55 aborted, then control will not be returned to your procedure. Rather, all work
56 will be rolled back and the server will wait for the next command from the
57 client.  This will probably be changed in future versions.
58 </Para>
59
60 <Para>
61 A related restriction is the inability to execute BEGIN, END and ABORT
62 (transaction control statements).  This will also be
63 changed in the future.
64 </Para>
65
66 <Para>
67 If successful, <Acronym>SPI</Acronym> functions return a non-negative result (either via
68 a returned integer value or in SPI_result global variable, as described below).
69 On error, a negative or NULL result will be returned.
70 </Para>
71
72 <Sect1 id="spi-interface">
73 <Title>Interface Functions</Title>
74
75 <REFENTRY ID="SPI-SPICONNECT">
76 <REFMETA>
77 <REFENTRYTITLE>SPI_connect</REFENTRYTITLE>
78 <REFMISCINFO>SPI - Connection Management</REFMISCINFO>
79 </REFMETA>
80 <REFNAMEDIV>
81 <REFNAME>SPI_connect
82 </REFNAME>
83 <REFPURPOSE>
84    Connects your procedure to the SPI manager.
85 </REFPURPOSE>
86 <INDEXTERM ID="IX-SPI-SPICONNECT-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
87 <INDEXTERM ID="IX-SPI-SPICONNECT-2"><PRIMARY>SPI_connect</PRIMARY></INDEXTERM>
88 </REFNAMEDIV>
89 <REFSYNOPSISDIV>
90 <REFSYNOPSISDIVINFO>
91 <DATE>1997-12-24</DATE>
92 </REFSYNOPSISDIVINFO>
93 <SYNOPSIS>
94 int SPI_connect(void)
95 </SYNOPSIS>
96
97 <REFSECT2 ID="R2-SPI-SPICONNECT-1">
98 <REFSECT2INFO>
99 <DATE>1997-12-24</DATE>
100 </REFSECT2INFO>
101 <TITLE>Inputs
102 </TITLE>
103 <PARA>None
104 </PARA>
105 </REFSECT2>
106
107 <REFSECT2 ID="R2-SPI-SPICONNECT-2">
108 <REFSECT2INFO>
109 <DATE>1997-12-24</DATE>
110 </REFSECT2INFO>
111 <TITLE>Outputs
112 </TITLE>
113 <VARIABLELIST>
114 <VARLISTENTRY>
115 <TERM>int
116 </TERM>
117 <LISTITEM>
118 <PARA>
119 Return status
120 <VARIABLELIST>
121 <VARLISTENTRY>
122 <TERM><ReturnValue>SPI_OK_CONNECT</ReturnValue>
123 </TERM>
124 <LISTITEM>
125 <PARA>
126    if connected
127 </PARA>
128 </LISTITEM>
129 </VARLISTENTRY>
130 <VARLISTENTRY>
131 <TERM><ReturnValue>SPI_ERROR_CONNECT</ReturnValue>
132 </TERM>
133 <LISTITEM>
134 <PARA>
135    if not connected
136 </PARA>
137 </LISTITEM>
138 </VARLISTENTRY>
139 </VARIABLELIST>
140 </para>
141 </LISTITEM>
142 </VARLISTENTRY>
143 </VARIABLELIST>
144 </REFSECT2>
145 </REFSYNOPSISDIV>
146
147 <REFSECT1 ID="R1-SPI-SPICONNECT-1">
148 <REFSECT1INFO>
149 <DATE>1997-12-24</DATE>
150 </REFSECT1INFO>
151 <TITLE>Description
152 </TITLE>
153 <PARA>
154 <FUNCTION>SPI_connect</FUNCTION> opens a connection from a procedure
155 invocation to the SPI manager.
156    You must call this function if you will need to execute queries. Some
157    utility SPI functions may be called from un-connected procedures.
158 </PARA>
159 <PARA>
160    If your procedure is already connected,
161    <Function>SPI_connect</Function> will return an
162    <ReturnValue>SPI_ERROR_CONNECT</ReturnValue> error.  Note that this
163    may happen if a procedure which has called
164    <Function>SPI_connect</Function> directly calls another procedure
165    which itself calls <Function>SPI_connect</Function>.  While
166    recursive calls to the <Acronym>SPI</Acronym> manager are permitted
167    when an <Acronym>SPI</Acronym> query invokes another function which
168    uses <Acronym>SPI</Acronym>, directly nested calls to
169    <Function>SPI_connect</Function> and
170    <Function>SPI_finish</Function> are forbidden.
171 </PARA>
172 </REFSECT1>
173 <REFSECT1 ID="R1-SPI-SPICONNECT-2">
174 <TITLE>Usage
175 </TITLE>
176 <PARA>
177 <!--
178 XXX thomas 1997-12-24
179 -->
180 </PARA>
181 </REFSECT1>
182 <REFSECT1 ID="R1-SPI-SPICONNECT-3">
183 <TITLE>Algorithm
184 </TITLE>
185 <PARA><FUNCTION>SPI_connect</FUNCTION> performs the following:
186   Initializes the SPI internal
187    structures for query execution and memory management.
188 </PARA>
189 </REFSECT1>
190 <!--
191 <REFSECT1 ID="R1-SPI-SPICONNECT-4">
192 <TITLE>Structures
193 </TITLE>
194 <PARA>None
195 </PARA>
196 </REFSECT1>
197 -->
198 </REFENTRY>
199
200 <!-- *********************************************** -->
201 <!-- *********************************************** -->
202 <!-- *********************************************** -->
203
204 <REFENTRY ID="SPI-SPIFINISH">
205 <REFMETA>
206 <REFENTRYTITLE>SPI_finish</REFENTRYTITLE>
207 <REFMISCINFO>SPI - Connection Management</REFMISCINFO>
208 </REFMETA>
209 <REFNAMEDIV>
210 <REFNAME>SPI_finish
211 </REFNAME>
212 <REFPURPOSE>
213    Disconnects your procedure from the SPI manager.
214 </REFPURPOSE>
215 <INDEXTERM ID="IX-SPI-SPIFINISH-1"><PRIMARY>SPI</PRIMARY><SECONDARY>disconnecting</SECONDARY></INDEXTERM>
216 <INDEXTERM ID="IX-SPI-SPIFINISH-2"><PRIMARY>SPI_finish</PRIMARY></INDEXTERM>
217 </REFNAMEDIV>
218 <REFSYNOPSISDIV>
219 <REFSYNOPSISDIVINFO>
220 <DATE>1997-12-24</DATE>
221 </REFSYNOPSISDIVINFO>
222 <SYNOPSIS>
223 SPI_finish(void)
224 </SYNOPSIS>
225
226 <REFSECT2 ID="R2-SPI-SPIFINISH-1">
227 <REFSECT2INFO>
228 <DATE>1997-12-24</DATE>
229 </REFSECT2INFO>
230 <TITLE>Inputs
231 </TITLE>
232 <PARA>None
233 </PARA>
234 </REFSECT2>
235
236 <REFSECT2 ID="R2-SPI-SPIFINISH-2">
237 <REFSECT2INFO>
238 <DATE>1997-12-24</DATE>
239 </REFSECT2INFO>
240 <TITLE>Outputs
241 </TITLE>
242 <VARIABLELIST>
243 <VARLISTENTRY>
244 <TERM>int
245 </TERM>
246 <LISTITEM>
247 <PARA>
248 <SimpleList>
249 <Member>
250 <ReturnValue>SPI_OK_FINISH</ReturnValue>
251    if properly disconnected
252 </Member>
253 <Member>
254 <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue>
255    if called from an un-connected procedure
256 </Member>
257 </SimpleList>
258 </PARA>
259 </LISTITEM>
260 </VARLISTENTRY>
261 </VARIABLELIST>
262 </REFSECT2>
263 </REFSYNOPSISDIV>
264
265 <REFSECT1 ID="R1-SPI-SPIFINISH-1">
266 <REFSECT1INFO>
267 <DATE>1997-12-24</DATE>
268 </REFSECT1INFO>
269 <TITLE>Description
270 </TITLE>
271 <PARA>
272 <FUNCTION>SPI_finish</FUNCTION> closes an existing connection to the
273 SPI manager.
274    You must call this function after completing the SPI operations needed
275    during your procedure's current invocation.
276 </para>
277 <PARA>
278    You may get the error return <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if <Function>SPI_finish</Function> is
279    called without having a current valid connection.
280  There is no fundamental problem
281    with this; it means that nothing was done by the SPI manager.
282 </PARA>
283 </REFSECT1>
284 <REFSECT1 ID="R1-SPI-SPIFINISH-2">
285 <TITLE>Usage
286 </TITLE>
287 <PARA>
288    <Function>SPI_finish</Function> <Emphasis>must</Emphasis> be called as a final step by a connected procedure,
289  or you may get
290    unpredictable results!  However, you do not need to worry about making
291 this happen if the transaction is aborted via elog(ERROR).  In that case
292 SPI will clean itself up.
293
294 </PARA>
295 </REFSECT1>
296 <REFSECT1 ID="R1-SPI-SPIFINISH-3">
297 <TITLE>Algorithm
298 </TITLE>
299 <PARA><FUNCTION>SPI_finish</FUNCTION> performs the following:
300    Disconnects your procedure from the SPI manager and frees all memory
301    allocations made by your procedure via <Function>palloc</Function> since
302  the <Function>SPI_connect</Function>. 
303    These allocations can't be used any more! See Memory management.
304 </PARA>
305 </REFSECT1>
306 <!--
307 <REFSECT1 ID="R1-SPI-SPIFINISH-4">
308 <TITLE>Structures
309 </TITLE>
310 <PARA>None
311 </PARA>
312 </REFSECT1>
313 -->
314 </REFENTRY>
315
316 <!-- *********************************************** -->
317 <!-- *********************************************** -->
318 <!-- *********************************************** -->
319
320 <REFENTRY ID="SPI-SPIEXEC">
321 <REFMETA>
322 <REFENTRYTITLE>SPI_exec</REFENTRYTITLE>
323 <REFMISCINFO>SPI - Connection Management</REFMISCINFO>
324 </REFMETA>
325 <REFNAMEDIV>
326 <REFNAME>SPI_exec
327 </REFNAME>
328 <REFPURPOSE>
329    Creates an execution plan (parser+planner+optimizer) and executes a query.
330 </REFPURPOSE>
331 <INDEXTERM ID="IX-SPI-SPIEXEC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>executing</SECONDARY></INDEXTERM>
332 <INDEXTERM ID="IX-SPI-SPIEXEC-2"><PRIMARY>SPI_exec</PRIMARY></INDEXTERM>
333 </REFNAMEDIV>
334 <REFSYNOPSISDIV>
335 <REFSYNOPSISDIVINFO>
336 <DATE>1997-12-24</DATE>
337 </REFSYNOPSISDIVINFO>
338 <SYNOPSIS>
339 SPI_exec(<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>)
340 </SYNOPSIS>
341
342 <REFSECT2 ID="R2-SPI-SPIEXEC-1">
343 <REFSECT2INFO>
344 <DATE>1997-12-24</DATE>
345 </REFSECT2INFO>
346 <TITLE>Inputs
347 </TITLE>
348 <VARIABLELIST>
349 <VARLISTENTRY>
350 <TERM>
351 char *<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>
352 </TERM>
353 <LISTITEM>
354 <PARA>
355 String containing query plan
356 </PARA>
357 </LISTITEM>
358 </VARLISTENTRY>
359 <VARLISTENTRY>
360 <TERM>
361 int <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>
362 </TERM>
363 <LISTITEM>
364 <PARA>
365 Maximum number of tuples to return
366 </PARA>
367 </LISTITEM>
368 </VARLISTENTRY>
369 </VARIABLELIST>
370 </REFSECT2>
371
372 <REFSECT2 ID="R2-SPI-SPIEXEC-2">
373 <REFSECT2INFO>
374 <DATE>1997-12-24</DATE>
375 </REFSECT2INFO>
376 <TITLE>Outputs
377 </TITLE>
378 <VARIABLELIST>
379 <VARLISTENTRY>
380 <TERM>int
381 </TERM>
382 <LISTITEM>
383 <PARA>
384 <SimpleList>
385 <Member>
386    <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if called from an un-connected procedure
387 </Member>
388 <Member>
389    <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> < 0.
390 </Member>
391 <Member>
392    <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is unconnected.
393 </Member>
394 <Member>
395    <ReturnValue>SPI_ERROR_COPY</ReturnValue> if COPY TO/FROM stdin.
396 </Member>
397 <Member>
398    <ReturnValue>SPI_ERROR_CURSOR</ReturnValue> if DECLARE/CLOSE CURSOR, FETCH.
399 </Member>
400 <Member>
401    <ReturnValue>SPI_ERROR_TRANSACTION</ReturnValue> if BEGIN/ABORT/END.
402 </Member>
403 <Member>
404    <ReturnValue>SPI_ERROR_OPUNKNOWN</ReturnValue> if type of query is unknown (this shouldn't occur).
405 </Member>
406 </SimpleList>
407 </para>
408 <Para>
409    If execution of your query was successful then one of the following
410    (non-negative) values will be returned:
411 <SimpleList>
412 <Member>
413    <ReturnValue>SPI_OK_UTILITY</ReturnValue> if some utility (e.g. CREATE TABLE ...) was executed
414 </Member>
415 <Member>
416    <ReturnValue>SPI_OK_SELECT</ReturnValue> if SELECT (but not SELECT ... INTO!) was executed
417 </Member>
418 <Member>
419    <ReturnValue>SPI_OK_SELINTO</ReturnValue> if SELECT ... INTO was executed
420 </Member>
421 <Member>
422    <ReturnValue>SPI_OK_INSERT</ReturnValue> if INSERT (or INSERT ... SELECT) was executed
423 </Member>
424 <Member>
425    <ReturnValue>SPI_OK_DELETE</ReturnValue> if DELETE was executed
426 </Member>
427 <Member>
428    <ReturnValue>SPI_OK_UPDATE</ReturnValue> if UPDATE was executed
429 </Member>
430 </SimpleList>
431 </PARA>
432 </LISTITEM>
433 </VARLISTENTRY>
434 </VARIABLELIST>
435 </REFSECT2>
436 </REFSYNOPSISDIV>
437
438 <REFSECT1 ID="R1-SPI-SPIEXEC-1">
439 <REFSECT1INFO>
440 <DATE>1997-12-24</DATE>
441 </REFSECT1INFO>
442 <TITLE>Description
443 </TITLE>
444 <PARA>
445 <FUNCTION>SPI_exec</FUNCTION> creates an execution plan (parser+planner+optimizer)
446  and executes the query for <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> tuples.
447
448 </PARA>
449 </REFSECT1>
450 <REFSECT1 ID="R1-SPI-SPIEXEC-2">
451 <TITLE>Usage
452 </TITLE>
453 <PARA>
454   This should only be called from a connected procedure.
455    If <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> is zero then it executes the query for all tuples returned by the
456    query scan. Using <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> > 0 you may restrict the number of tuples for
457    which the query will be executed (much like a LIMIT clause). For example,
458
459 <ProgramListing>
460 SPI_exec ("INSERT INTO tab SELECT * FROM tab", 5);
461 </ProgramListing>
462
463 will allow at most 5 tuples to be inserted into table.
464
465    If execution of your query was successful then a non-negative value will be returned.
466
467 <Note>
468 <Para>
469 You may pass multiple queries in one string or query string may be
470    re-written by RULEs. <Function>SPI_exec</Function> returns the result for the last query
471    executed.
472 </Para>
473 </Note>
474 </para>
475 <Para>
476    The actual number of tuples for which the (last) query was executed is
477    returned in the global variable SPI_processed (if not <ReturnValue>SPI_OK_UTILITY</ReturnValue>).
478
479    If <ReturnValue>SPI_OK_SELECT</ReturnValue> is returned and SPI_processed &gt; 0 then you may use global
480    pointer SPITupleTable *SPI_tuptable to access the result tuples.
481 </Para>
482
483 <Para>
484    <Function>SPI_exec</Function> may return one of the following (negative) values:
485 <SimpleList>
486 <Member>
487    <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> < 0.
488 </Member>
489 <Member>
490    <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is unconnected.
491 </Member>
492 <Member>
493    <ReturnValue>SPI_ERROR_COPY</ReturnValue> if COPY TO/FROM stdin.
494 </Member>
495 <Member>
496    <ReturnValue>SPI_ERROR_CURSOR</ReturnValue> if DECLARE/CLOSE CURSOR, FETCH.
497 </Member>
498 <Member>
499    <ReturnValue>SPI_ERROR_TRANSACTION</ReturnValue> if BEGIN/ABORT/END.
500 </Member>
501 <Member>
502    <ReturnValue>SPI_ERROR_OPUNKNOWN</ReturnValue> if type of query is unknown (this shouldn't occur).
503 </Member>
504 </SimpleList>
505
506 </PARA>
507 </REFSECT1>
508 <!--
509 <REFSECT1 ID="R1-SPI-SPIEXEC-3">
510 <TITLE>Algorithm
511 </TITLE>
512 <PARA>
513 </PARA>
514 </REFSECT1>
515 -->
516 <REFSECT1 ID="R1-SPI-SPIEXEC-4">
517 <TITLE>Structures
518 </TITLE>
519 <Para>
520    If <ReturnValue>SPI_OK_SELECT</ReturnValue> is returned and SPI_processed &gt; 0 then you may use the global
521    pointer SPITupleTable *SPI_tuptable to access the selected tuples.
522 </Para>
523
524 <Para>
525    Structure SPITupleTable is defined in spi.h:
526 <ProgramListing>
527    typedef struct
528    {
529        MemoryContext tuptabcxt;    /* memory context of result table */
530        uint32      alloced;        /* # of alloced vals */
531        uint32      free;           /* # of free vals */
532        TupleDesc   tupdesc;        /* tuple descriptor */
533        HeapTuple  *vals;           /* tuples */
534    } SPITupleTable;
535 </ProgramListing>
536 </Para>
537
538 <Para>
539    vals is an array of pointers to tuples (the number of useful entries
540    is given by SPI_processed). TupleDesc tupdesc is
541    a tuple descriptor which you may pass to SPI functions dealing with
542    tuples.  tuptabcxt, alloced, and free are internal fields not intended
543    for use by SPI callers.
544 </Para>
545
546 <note>
547 <Para>
548    Functions <Function>SPI_exec</Function>, <Function>SPI_execp</Function> and
549    <Function>SPI_prepare</Function> change both SPI_processed and SPI_tuptable
550    (just the pointer, not the contents of the structure).
551    Save these two global variables into local procedure variables if you need
552    to access the result of one <Function>SPI_exec</Function> or
553    <Function>SPI_execp</Function> across later calls.
554 </Para>
555 </note>
556
557 <Para>
558    <Function>SPI_finish</Function> frees all SPITupleTables allocated during
559    the current procedure.  You can free a particular result table earlier,
560    if you are done with it, by calling <Function>SPI_freetuptable</Function>.
561 </Para>
562 </REFSECT1>
563 </REFENTRY>
564
565 <!-- *********************************************** -->
566 <!-- *********************************************** -->
567 <!-- *********************************************** -->
568
569 <REFENTRY ID="SPI-SPIPREPARE">
570 <REFMETA>
571 <REFENTRYTITLE>SPI_prepare</REFENTRYTITLE>
572 <REFMISCINFO>SPI - Plan Preparation</REFMISCINFO>
573 </REFMETA>
574 <REFNAMEDIV>
575 <REFNAME>SPI_prepare
576 </REFNAME>
577 <REFPURPOSE>
578    Prepares a plan for a query, without executing it yet
579 </REFPURPOSE>
580 <INDEXTERM ID="IX-SPI-SPIPREPARE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
581 <INDEXTERM ID="IX-SPI-SPIPREPARE-2"><PRIMARY>SPI_prepare</PRIMARY></INDEXTERM>
582 </REFNAMEDIV>
583 <REFSYNOPSISDIV>
584 <REFSYNOPSISDIVINFO>
585 <DATE>1997-12-24</DATE>
586 </REFSYNOPSISDIVINFO>
587 <SYNOPSIS>
588 SPI_prepare(<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">nargs</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">argtypes</REPLACEABLE>)
589 </SYNOPSIS>
590
591 <REFSECT2 ID="R2-SPI-SPIPREPARE-1">
592 <REFSECT2INFO>
593 <DATE>1997-12-24</DATE>
594 </REFSECT2INFO>
595 <TITLE>Inputs
596 </TITLE>
597 <VARIABLELIST>
598 <VARLISTENTRY>
599 <TERM>
600 <REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>
601 </TERM>
602 <LISTITEM>
603 <PARA>
604 Query string
605 </PARA>
606 </LISTITEM>
607 </VARLISTENTRY>
608 <VARLISTENTRY>
609 <TERM>
610 <REPLACEABLE CLASS="PARAMETER">nargs</REPLACEABLE>
611 </TERM>
612 <LISTITEM>
613 <PARA>
614 Number of input parameters ($1 ... $nargs - as in SQL-functions)
615 </PARA>
616 </LISTITEM>
617 </VARLISTENTRY>
618 <VARLISTENTRY>
619 <TERM>
620 <REPLACEABLE CLASS="PARAMETER">argtypes</REPLACEABLE>
621 </TERM>
622 <LISTITEM>
623 <PARA>
624 Pointer to array of type <Acronym>OID</Acronym>s for input parameter types
625 </PARA>
626 </LISTITEM>
627 </VARLISTENTRY>
628 </VARIABLELIST>
629 </REFSECT2>
630
631 <REFSECT2 ID="R2-SPI-SPIPREPARE-2">
632 <REFSECT2INFO>
633 <DATE>1997-12-24</DATE>
634 </REFSECT2INFO>
635 <TITLE>Outputs
636 </TITLE>
637 <VARIABLELIST>
638 <VARLISTENTRY>
639 <TERM>void *
640 </TERM>
641 <LISTITEM>
642 <PARA>
643 Pointer to an execution plan (parser+planner+optimizer)
644 </PARA>
645 </LISTITEM>
646 </VARLISTENTRY>
647 </VARIABLELIST>
648 </REFSECT2>
649 </REFSYNOPSISDIV>
650
651 <REFSECT1 ID="R1-SPI-SPIPREPARE-1">
652 <REFSECT1INFO>
653 <DATE>1997-12-24</DATE>
654 </REFSECT1INFO>
655 <TITLE>Description
656 </TITLE>
657 <PARA>
658 <FUNCTION>SPI_prepare</FUNCTION> 
659    creates and returns an execution plan (parser+planner+optimizer) but doesn't
660    execute the query. Should only be called from a connected procedure.
661
662 </PARA>
663 </REFSECT1>
664 <REFSECT1 ID="R1-SPI-SPIPREPARE-2">
665 <TITLE>Usage
666 </TITLE>
667 <Para>
668    When the same or similar query is to be executed repeatedly, it may
669    be advantageous to perform query planning only once.
670    <FUNCTION>SPI_prepare</FUNCTION> converts a query string into an execution
671    plan that can be passed repeatedly to <FUNCTION>SPI_execp</FUNCTION>.
672 </para>
673 <PARA>
674    A prepared query can be generalized by writing parameters ($1, $2, etc)
675    in place of what would be constants in a normal query.  The values of
676    the parameters are then specified when <FUNCTION>SPI_execp</FUNCTION>
677    is called.  This allows the prepared query to be used over a wider
678    range of situations than would be possible without parameters.
679 </para>
680 <note>
681 <PARA>
682    However, there is a disadvantage: since the planner does not know the
683    values that will be supplied for the parameters, it may make worse
684    query planning choices than it would make for a simple query with
685    all constants visible.
686 </para>
687 </note>
688 <PARA>
689    If the query uses parameters, their number and datatypes must be
690    specified in the call to <FUNCTION>SPI_prepare</FUNCTION>.
691 </para>
692 <Para>
693 The plan returned by <Function>SPI_prepare</Function> may be used only in current
694    invocation of the procedure since <Function>SPI_finish</Function> frees memory allocated for a plan. 
695    But see <Function>SPI_saveplan</Function> to save a plan for longer.
696 </para>
697 <Para>
698    If successful, a non-null pointer will be returned. Otherwise, you'll get
699    a NULL plan.  In both cases SPI_result will be set like the value returned
700    by SPI_exec, except that it is set to 
701    <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or nargs < 0 or nargs > 0 && argtypes
702    is NULL.
703
704 </PARA>
705 </REFSECT1>
706 <!--
707 <REFSECT1 ID="R1-SPI-SPIPREPARE-3">
708 <TITLE>Algorithm
709 </TITLE>
710 <PARA><FUNCTION>SPI_prepare</FUNCTION> performs the following:
711 TBD
712 </PARA>
713 </REFSECT1>
714 -->
715 <!--
716 <REFSECT1 ID="R1-SPI-SPIPREPARE-4">
717 <TITLE>Structures
718 </TITLE>
719 <PARA>None
720 </PARA>
721 </REFSECT1>
722 -->
723 </REFENTRY>
724
725 <!-- *********************************************** -->
726 <!-- *********************************************** -->
727 <!-- *********************************************** -->
728
729 <REFENTRY ID="SPI-SPIEXECP">
730 <REFMETA>
731 <REFENTRYTITLE>SPI_execp</REFENTRYTITLE>
732 <REFMISCINFO>SPI - Plan Execution</REFMISCINFO>
733 </REFMETA>
734 <REFNAMEDIV>
735 <REFNAME>SPI_execp
736 </REFNAME>
737 <REFPURPOSE>
738 Executes a plan from <Function>SPI_prepare</Function>
739 </REFPURPOSE>
740 <INDEXTERM ID="IX-SPI-SPIEXECP-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
741 <INDEXTERM ID="IX-SPI-SPIEXECP-2"><PRIMARY>SPI_execp</PRIMARY></INDEXTERM>
742 </REFNAMEDIV>
743 <REFSYNOPSISDIV>
744 <REFSYNOPSISDIVINFO>
745 <DATE>1997-12-24</DATE>
746 </REFSYNOPSISDIVINFO>
747 <SYNOPSIS>
748 SPI_execp(<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>,
749 <REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE>,
750 <REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>,
751 <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>)
752 </SYNOPSIS>
753
754 <REFSECT2 ID="R2-SPI-SPIEXECP-1">
755 <REFSECT2INFO>
756 <DATE>1997-12-24</DATE>
757 </REFSECT2INFO>
758 <TITLE>Inputs
759 </TITLE>
760 <VARIABLELIST>
761 <VARLISTENTRY>
762 <TERM>
763 void *<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>
764 </TERM>
765 <LISTITEM>
766 <PARA>
767 Execution plan
768 </PARA>
769 </LISTITEM>
770 </VARLISTENTRY>
771 <VARLISTENTRY>
772 <TERM>
773 Datum *<REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE>
774 </TERM>
775 <LISTITEM>
776 <PARA>
777 Actual parameter values
778 </PARA>
779 </LISTITEM>
780 </VARLISTENTRY>
781 <VARLISTENTRY>
782 <TERM>
783 char *<REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>
784 </TERM>
785 <LISTITEM>
786 <PARA>
787 Array describing which parameters are NULLs
788 <SimpleList>
789 <Member><literal>n</literal> indicates NULL (values[] entry ignored)</Member>
790 <Member>space indicates not NULL (values[] entry is valid)</Member>
791 </SimpleList>
792 </PARA>
793 </LISTITEM>
794 </VARLISTENTRY>
795 <VARLISTENTRY>
796 <TERM>
797 int <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>
798 </TERM>
799 <LISTITEM>
800 <PARA>
801 Number of tuples for which plan is to be executed
802 </PARA>
803 </LISTITEM>
804 </VARLISTENTRY>
805 </VARIABLELIST>
806 </REFSECT2>
807
808 <REFSECT2 ID="R2-SPI-SPIEXECP-2">
809 <REFSECT2INFO>
810 <DATE>1997-12-24</DATE>
811 </REFSECT2INFO>
812 <TITLE>Outputs
813 </TITLE>
814 <VARIABLELIST>
815 <VARLISTENTRY>
816 <TERM>int
817 </TERM>
818 <LISTITEM>
819 <PARA>
820    Returns the same value as <Function>SPI_exec</Function> as well as
821 <SimpleList>
822 <Member>
823  <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue>
824  if <REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>
825  is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> &lt; 0
826 </Member>
827 <Member>
828    <ReturnValue>SPI_ERROR_PARAM</ReturnValue>
829  if <REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE>
830  is NULL
831  and <REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>
832  was prepared with some parameters.
833 </Member>
834 </SimpleList>
835 </para>
836 </LISTITEM>
837 </VARLISTENTRY>
838 <VARLISTENTRY>
839 <TERM>SPI_tuptable
840 </TERM>
841 <LISTITEM>
842 <PARA>
843 initialized as in
844    <Function>SPI_exec</Function> if successful
845 </PARA>
846 </LISTITEM>
847 </VARLISTENTRY>
848 <VARLISTENTRY>
849 <TERM>SPI_processed
850 </TERM>
851 <LISTITEM>
852 <PARA>
853 initialized as in
854    <Function>SPI_exec</Function> if successful
855 </para>
856 </listitem>
857 </VARLISTENTRY>
858 </VARIABLELIST>
859 </REFSECT2>
860 </REFSYNOPSISDIV>
861
862 <REFSECT1 ID="R1-SPI-SPIEXECP-1">
863 <REFSECT1INFO>
864 <DATE>1997-12-24</DATE>
865 </REFSECT1INFO>
866 <TITLE>Description
867 </TITLE>
868 <PARA>
869 <FUNCTION>SPI_execp</FUNCTION> 
870    executes a plan prepared by <Function>SPI_prepare</Function>.
871    <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> has the same
872    interpretation as in <Function>SPI_exec</Function>.
873 </para>
874 </REFSECT1>
875 <REFSECT1 ID="R1-SPI-SPIEXECP-2">
876 <TITLE>Usage
877 </TITLE>
878 <Para>
879    If <REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>
880 is NULL then 
881    <Function>SPI_execp</Function> 
882 assumes that all parameters (if any) are NOT NULL.
883
884 <Note>
885 <Para>
886    If one of the objects (a relation, function, etc.) referenced by the prepared
887    plan is dropped during your session (by your backend or another process) then the
888    results of <Function>SPI_execp</Function> for this plan will be unpredictable.
889 </Para>
890 </Note>
891
892 </PARA>
893 </REFSECT1>
894 <!--
895 <REFSECT1 ID="R1-SPI-SPIEXECP-3">
896 <TITLE>Algorithm
897 </TITLE>
898 <PARA><FUNCTION>SPI_execp</FUNCTION> performs the following:
899 TBD
900 </PARA>
901 </REFSECT1>
902 -->
903 <!--
904 <REFSECT1 ID="R1-SPI-SPIEXECP-4">
905 <TITLE>Structures
906 </TITLE>
907 <PARA>None
908 </PARA>
909 </REFSECT1>
910 -->
911 </REFENTRY>
912
913 <!-- *********************************************** -->
914 <!-- *********************************************** -->
915 <!-- *********************************************** -->
916
917 <REFENTRY ID="SPI-SPICURSOR-OPEN">
918 <REFMETA>
919 <REFENTRYTITLE>SPI_cursor_open</REFENTRYTITLE>
920 <REFMISCINFO>SPI - Cursor Support</REFMISCINFO>
921 </REFMETA>
922 <REFNAMEDIV>
923 <REFNAME>SPI_cursor_open
924 </REFNAME>
925 <REFPURPOSE>
926 Sets up a cursor using a plan created with <Function>SPI_prepare</Function>
927 </REFPURPOSE>
928 <INDEXTERM ID="IX-SPI-SPICURSOR-OPEN-1"><PRIMARY>SPI</PRIMARY><SECONDARY>cursors</SECONDARY></INDEXTERM>
929 <INDEXTERM ID="IX-SPI-SPICURSOR-OPEN-2"><PRIMARY>SPI_cursor_open</PRIMARY></INDEXTERM>
930 </REFNAMEDIV>
931 <REFSYNOPSISDIV>
932 <REFSYNOPSISDIVINFO>
933 <DATE>2001-11-14</DATE>
934 </REFSYNOPSISDIVINFO>
935 <SYNOPSIS>
936 SPI_cursor_open(<REPLACEABLE CLASS="PARAMETER">name</REPLACEABLE>,
937 <REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>,
938 <REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE>,
939 <REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>)
940 </SYNOPSIS>
941
942 <REFSECT2 ID="R2-SPI-SPICURSOR-OPEN-1">
943 <REFSECT2INFO>
944 <DATE>2001-11-14</DATE>
945 </REFSECT2INFO>
946 <TITLE>Inputs
947 </TITLE>
948 <VARIABLELIST>
949 <VARLISTENTRY>
950 <TERM>
951 char *<REPLACEABLE CLASS="PARAMETER">name</REPLACEABLE>
952 </TERM>
953 <LISTITEM>
954 <PARA>
955 Name for portal, or NULL to let the system select a name
956 </PARA>
957 </LISTITEM>
958 </VARLISTENTRY>
959 <VARLISTENTRY>
960 <TERM>
961 void *<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>
962 </TERM>
963 <LISTITEM>
964 <PARA>
965 Execution plan
966 </PARA>
967 </LISTITEM>
968 </VARLISTENTRY>
969 <VARLISTENTRY>
970 <TERM>
971 Datum *<REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE>
972 </TERM>
973 <LISTITEM>
974 <PARA>
975 Actual parameter values
976 </PARA>
977 </LISTITEM>
978 </VARLISTENTRY>
979 <VARLISTENTRY>
980 <TERM>
981 char *<REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>
982 </TERM>
983 <LISTITEM>
984 <PARA>
985 Array describing which parameters are NULLs
986 <SimpleList>
987 <Member><literal>n</literal> indicates NULL (values[] entry ignored)</Member>
988 <Member>space indicates not NULL (values[] entry is valid)</Member>
989 </SimpleList>
990 </PARA>
991 </LISTITEM>
992 </VARLISTENTRY>
993 </VARIABLELIST>
994 </REFSECT2>
995
996 <REFSECT2 ID="R2-SPI-SPICURSOR-OPEN-2">
997 <REFSECT2INFO>
998 <DATE>2001-11-14</DATE>
999 </REFSECT2INFO>
1000 <TITLE>Outputs
1001 </TITLE>
1002 <VARIABLELIST>
1003 <VARLISTENTRY>
1004 <TERM>Portal
1005 </TERM>
1006 <LISTITEM>
1007 <PARA>
1008    Pointer to Portal containing cursor, or NULL on error
1009 </para>
1010 </LISTITEM>
1011 </VARLISTENTRY>
1012 </VARIABLELIST>
1013 </REFSECT2>
1014 </REFSYNOPSISDIV>
1015
1016 <REFSECT1 ID="R1-SPI-SPICURSOR-OPEN-1">
1017 <REFSECT1INFO>
1018 <DATE>2001-11-14</DATE>
1019 </REFSECT1INFO>
1020 <TITLE>Description
1021 </TITLE>
1022 <PARA>
1023 <FUNCTION>SPI_cursor_open</FUNCTION> 
1024    sets up a cursor (internally, a Portal) that will execute a plan
1025    prepared by <Function>SPI_prepare</Function>.
1026 </para>
1027 <para>
1028    Using a cursor instead of executing the plan directly has two
1029    benefits.  First, the result rows can be retrieved a few at a time,
1030    avoiding memory overrun for queries that return many rows.  Second,
1031    a Portal can outlive the current procedure (it can, in fact, live to
1032    the end of the current transaction).  Returning the portal name to
1033    the procedure's caller provides a way of returning a rowset result.
1034 </para>
1035 </REFSECT1>
1036 <REFSECT1 ID="R1-SPI-SPICURSOR-OPEN-2">
1037 <TITLE>Usage
1038 </TITLE>
1039 <Para>
1040    If <REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>
1041 is NULL then 
1042    <Function>SPI_cursor_open</Function> 
1043 assumes that all parameters (if any) are NOT NULL.
1044 </PARA>
1045 </REFSECT1>
1046 <!--
1047 <REFSECT1 ID="R1-SPI-SPICURSOR-OPEN-3">
1048 <TITLE>Algorithm
1049 </TITLE>
1050 <PARA><FUNCTION>SPI_cursor_open</FUNCTION> performs the following:
1051 TBD
1052 </PARA>
1053 </REFSECT1>
1054 -->
1055 </REFENTRY>
1056
1057 <!-- *********************************************** -->
1058 <!-- *********************************************** -->
1059 <!-- *********************************************** -->
1060
1061 <REFENTRY ID="SPI-SPICURSOR-FIND">
1062 <REFMETA>
1063 <REFENTRYTITLE>SPI_cursor_find</REFENTRYTITLE>
1064 <REFMISCINFO>SPI - Cursor Support</REFMISCINFO>
1065 </REFMETA>
1066 <REFNAMEDIV>
1067 <REFNAME>SPI_cursor_find
1068 </REFNAME>
1069 <REFPURPOSE>
1070 Finds an existing cursor (Portal) by name
1071 </REFPURPOSE>
1072 <INDEXTERM ID="IX-SPI-SPICURSOR-FIND-1"><PRIMARY>SPI</PRIMARY><SECONDARY>cursors</SECONDARY></INDEXTERM>
1073 <INDEXTERM ID="IX-SPI-SPICURSOR-FIND-2"><PRIMARY>SPI_cursor_find</PRIMARY></INDEXTERM>
1074 </REFNAMEDIV>
1075 <REFSYNOPSISDIV>
1076 <REFSYNOPSISDIVINFO>
1077 <DATE>2001-11-14</DATE>
1078 </REFSYNOPSISDIVINFO>
1079 <SYNOPSIS>
1080 SPI_cursor_find(<REPLACEABLE CLASS="PARAMETER">name</REPLACEABLE>)
1081 </SYNOPSIS>
1082
1083 <REFSECT2 ID="R2-SPI-SPICURSOR-FIND-1">
1084 <REFSECT2INFO>
1085 <DATE>2001-11-14</DATE>
1086 </REFSECT2INFO>
1087 <TITLE>Inputs
1088 </TITLE>
1089 <VARIABLELIST>
1090 <VARLISTENTRY>
1091 <TERM>
1092 char *<REPLACEABLE CLASS="PARAMETER">name</REPLACEABLE>
1093 </TERM>
1094 <LISTITEM>
1095 <PARA>
1096 Name of portal
1097 </PARA>
1098 </LISTITEM>
1099 </VARLISTENTRY>
1100 </VARIABLELIST>
1101 </REFSECT2>
1102
1103 <REFSECT2 ID="R2-SPI-SPICURSOR-FIND-2">
1104 <REFSECT2INFO>
1105 <DATE>2001-11-14</DATE>
1106 </REFSECT2INFO>
1107 <TITLE>Outputs
1108 </TITLE>
1109 <VARIABLELIST>
1110 <VARLISTENTRY>
1111 <TERM>Portal
1112 </TERM>
1113 <LISTITEM>
1114 <PARA>
1115    Pointer to Portal with given name, or NULL if not found
1116 </para>
1117 </LISTITEM>
1118 </VARLISTENTRY>
1119 </VARIABLELIST>
1120 </REFSECT2>
1121 </REFSYNOPSISDIV>
1122
1123 <REFSECT1 ID="R1-SPI-SPICURSOR-FIND-1">
1124 <REFSECT1INFO>
1125 <DATE>2001-11-14</DATE>
1126 </REFSECT1INFO>
1127 <TITLE>Description
1128 </TITLE>
1129 <PARA>
1130 <FUNCTION>SPI_cursor_find</FUNCTION> 
1131    finds a pre-existing Portal by name.  This is primarily useful
1132    to resolve a cursor name returned as text by some other function.
1133 </para>
1134 </REFSECT1>
1135 <!--
1136 <REFSECT1 ID="R1-SPI-SPICURSOR-FIND-2">
1137 <TITLE>Usage
1138 </TITLE>
1139 <Para>
1140 </PARA>
1141 </REFSECT1>
1142 -->
1143 <!--
1144 <REFSECT1 ID="R1-SPI-SPICURSOR-FIND-3">
1145 <TITLE>Algorithm
1146 </TITLE>
1147 <PARA><FUNCTION>SPI_cursor_find</FUNCTION> performs the following:
1148 TBD
1149 </PARA>
1150 </REFSECT1>
1151 -->
1152 </REFENTRY>
1153
1154 <!-- *********************************************** -->
1155 <!-- *********************************************** -->
1156 <!-- *********************************************** -->
1157
1158 <REFENTRY ID="SPI-SPICURSOR-FETCH">
1159 <REFMETA>
1160 <REFENTRYTITLE>SPI_cursor_fetch</REFENTRYTITLE>
1161 <REFMISCINFO>SPI - Cursor Support</REFMISCINFO>
1162 </REFMETA>
1163 <REFNAMEDIV>
1164 <REFNAME>SPI_cursor_fetch
1165 </REFNAME>
1166 <REFPURPOSE>
1167 Fetches some rows from a cursor
1168 </REFPURPOSE>
1169 <INDEXTERM ID="IX-SPI-SPICURSOR-FETCH-1"><PRIMARY>SPI</PRIMARY><SECONDARY>cursors</SECONDARY></INDEXTERM>
1170 <INDEXTERM ID="IX-SPI-SPICURSOR-FETCH-2"><PRIMARY>SPI_cursor_fetch</PRIMARY></INDEXTERM>
1171 </REFNAMEDIV>
1172 <REFSYNOPSISDIV>
1173 <REFSYNOPSISDIVINFO>
1174 <DATE>2001-11-14</DATE>
1175 </REFSYNOPSISDIVINFO>
1176 <SYNOPSIS>
1177 SPI_cursor_fetch(<REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE>,
1178 <REPLACEABLE CLASS="PARAMETER">forward</REPLACEABLE>,
1179 <REPLACEABLE CLASS="PARAMETER">count</REPLACEABLE>)
1180 </SYNOPSIS>
1181
1182 <REFSECT2 ID="R2-SPI-SPICURSOR-FETCH-1">
1183 <REFSECT2INFO>
1184 <DATE>2001-11-14</DATE>
1185 </REFSECT2INFO>
1186 <TITLE>Inputs
1187 </TITLE>
1188 <VARIABLELIST>
1189 <VARLISTENTRY>
1190 <TERM>
1191 Portal <REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE>
1192 </TERM>
1193 <LISTITEM>
1194 <PARA>
1195 Portal containing cursor
1196 </PARA>
1197 </LISTITEM>
1198 </VARLISTENTRY>
1199 <VARLISTENTRY>
1200 <TERM>
1201 bool <REPLACEABLE CLASS="PARAMETER">forward</REPLACEABLE>
1202 </TERM>
1203 <LISTITEM>
1204 <PARA>
1205 True for fetch forward, false for fetch backward
1206 </PARA>
1207 </LISTITEM>
1208 </VARLISTENTRY>
1209 <VARLISTENTRY>
1210 <TERM>
1211 int <REPLACEABLE CLASS="PARAMETER">count</REPLACEABLE>
1212 </TERM>
1213 <LISTITEM>
1214 <PARA>
1215 Maximum number of rows to fetch
1216 </PARA>
1217 </LISTITEM>
1218 </VARLISTENTRY>
1219 </VARIABLELIST>
1220 </REFSECT2>
1221
1222 <REFSECT2 ID="R2-SPI-SPICURSOR-FETCH-2">
1223 <REFSECT2INFO>
1224 <DATE>2001-11-14</DATE>
1225 </REFSECT2INFO>
1226 <TITLE>Outputs
1227 </TITLE>
1228 <VARIABLELIST>
1229 <VARLISTENTRY>
1230 <TERM>SPI_tuptable
1231 </TERM>
1232 <LISTITEM>
1233 <PARA>
1234 initialized as in
1235    <Function>SPI_exec</Function> if successful
1236 </PARA>
1237 </LISTITEM>
1238 </VARLISTENTRY>
1239 <VARLISTENTRY>
1240 <TERM>SPI_processed
1241 </TERM>
1242 <LISTITEM>
1243 <PARA>
1244 initialized as in
1245    <Function>SPI_exec</Function> if successful
1246 </para>
1247 </listitem>
1248 </VARLISTENTRY>
1249 </VARIABLELIST>
1250 </REFSECT2>
1251 </REFSYNOPSISDIV>
1252
1253 <REFSECT1 ID="R1-SPI-SPICURSOR-FETCH-1">
1254 <REFSECT1INFO>
1255 <DATE>2001-11-14</DATE>
1256 </REFSECT1INFO>
1257 <TITLE>Description
1258 </TITLE>
1259 <PARA>
1260 <FUNCTION>SPI_cursor_fetch</FUNCTION> 
1261    fetches some (more) rows from a cursor.  This is equivalent to the
1262    SQL command <command>FETCH</>.
1263 </para>
1264 </REFSECT1>
1265 <!--
1266 <REFSECT1 ID="R1-SPI-SPICURSOR-FETCH-2">
1267 <TITLE>Usage
1268 </TITLE>
1269 <Para>
1270 </PARA>
1271 </REFSECT1>
1272 -->
1273 <!--
1274 <REFSECT1 ID="R1-SPI-SPICURSOR-FETCH-3">
1275 <TITLE>Algorithm
1276 </TITLE>
1277 <PARA><FUNCTION>SPI_cursor_fetch</FUNCTION> performs the following:
1278 TBD
1279 </PARA>
1280 </REFSECT1>
1281 -->
1282 </REFENTRY>
1283
1284 <!-- *********************************************** -->
1285 <!-- *********************************************** -->
1286 <!-- *********************************************** -->
1287
1288 <REFENTRY ID="SPI-SPICURSOR-MOVE">
1289 <REFMETA>
1290 <REFENTRYTITLE>SPI_cursor_move</REFENTRYTITLE>
1291 <REFMISCINFO>SPI - Cursor Support</REFMISCINFO>
1292 </REFMETA>
1293 <REFNAMEDIV>
1294 <REFNAME>SPI_cursor_move
1295 </REFNAME>
1296 <REFPURPOSE>
1297 Moves a cursor
1298 </REFPURPOSE>
1299 <INDEXTERM ID="IX-SPI-SPICURSOR-MOVE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>cursors</SECONDARY></INDEXTERM>
1300 <INDEXTERM ID="IX-SPI-SPICURSOR-MOVE-2"><PRIMARY>SPI_cursor_move</PRIMARY></INDEXTERM>
1301 </REFNAMEDIV>
1302 <REFSYNOPSISDIV>
1303 <REFSYNOPSISDIVINFO>
1304 <DATE>2001-11-14</DATE>
1305 </REFSYNOPSISDIVINFO>
1306 <SYNOPSIS>
1307 SPI_cursor_move(<REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE>,
1308 <REPLACEABLE CLASS="PARAMETER">forward</REPLACEABLE>,
1309 <REPLACEABLE CLASS="PARAMETER">count</REPLACEABLE>)
1310 </SYNOPSIS>
1311
1312 <REFSECT2 ID="R2-SPI-SPICURSOR-MOVE-1">
1313 <REFSECT2INFO>
1314 <DATE>2001-11-14</DATE>
1315 </REFSECT2INFO>
1316 <TITLE>Inputs
1317 </TITLE>
1318 <VARIABLELIST>
1319 <VARLISTENTRY>
1320 <TERM>
1321 Portal <REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE>
1322 </TERM>
1323 <LISTITEM>
1324 <PARA>
1325 Portal containing cursor
1326 </PARA>
1327 </LISTITEM>
1328 </VARLISTENTRY>
1329 <VARLISTENTRY>
1330 <TERM>
1331 bool <REPLACEABLE CLASS="PARAMETER">forward</REPLACEABLE>
1332 </TERM>
1333 <LISTITEM>
1334 <PARA>
1335 True for move forward, false for move backward
1336 </PARA>
1337 </LISTITEM>
1338 </VARLISTENTRY>
1339 <VARLISTENTRY>
1340 <TERM>
1341 int <REPLACEABLE CLASS="PARAMETER">count</REPLACEABLE>
1342 </TERM>
1343 <LISTITEM>
1344 <PARA>
1345 Maximum number of rows to move
1346 </PARA>
1347 </LISTITEM>
1348 </VARLISTENTRY>
1349 </VARIABLELIST>
1350 </REFSECT2>
1351
1352 <REFSECT2 ID="R2-SPI-SPICURSOR-MOVE-2">
1353 <REFSECT2INFO>
1354 <DATE>2001-11-14</DATE>
1355 </REFSECT2INFO>
1356 <TITLE>Outputs
1357 </TITLE>
1358 <VARIABLELIST>
1359 <VARLISTENTRY>
1360 <TERM>None
1361 </TERM>
1362 <LISTITEM>
1363 <PARA>
1364 </PARA>
1365 </LISTITEM>
1366 </VARLISTENTRY>
1367 </VARIABLELIST>
1368 </REFSECT2>
1369 </REFSYNOPSISDIV>
1370
1371 <REFSECT1 ID="R1-SPI-SPICURSOR-MOVE-1">
1372 <REFSECT1INFO>
1373 <DATE>2001-11-14</DATE>
1374 </REFSECT1INFO>
1375 <TITLE>Description
1376 </TITLE>
1377 <PARA>
1378 <FUNCTION>SPI_cursor_move</FUNCTION> 
1379    skips over some number of rows in a cursor.  This is equivalent to the
1380    SQL command <command>MOVE</>.
1381 </para>
1382 </REFSECT1>
1383 <!--
1384 <REFSECT1 ID="R1-SPI-SPICURSOR-MOVE-2">
1385 <TITLE>Usage
1386 </TITLE>
1387 <Para>
1388 </PARA>
1389 </REFSECT1>
1390 -->
1391 <!--
1392 <REFSECT1 ID="R1-SPI-SPICURSOR-MOVE-3">
1393 <TITLE>Algorithm
1394 </TITLE>
1395 <PARA><FUNCTION>SPI_cursor_move</FUNCTION> performs the following:
1396 TBD
1397 </PARA>
1398 </REFSECT1>
1399 -->
1400 </REFENTRY>
1401
1402 <!-- *********************************************** -->
1403 <!-- *********************************************** -->
1404 <!-- *********************************************** -->
1405
1406 <REFENTRY ID="SPI-SPICURSOR-CLOSE">
1407 <REFMETA>
1408 <REFENTRYTITLE>SPI_cursor_close</REFENTRYTITLE>
1409 <REFMISCINFO>SPI - Cursor Support</REFMISCINFO>
1410 </REFMETA>
1411 <REFNAMEDIV>
1412 <REFNAME>SPI_cursor_close
1413 </REFNAME>
1414 <REFPURPOSE>
1415 Closes a cursor
1416 </REFPURPOSE>
1417 <INDEXTERM ID="IX-SPI-SPICURSOR-CLOSE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>cursors</SECONDARY></INDEXTERM>
1418 <INDEXTERM ID="IX-SPI-SPICURSOR-CLOSE-2"><PRIMARY>SPI_cursor_close</PRIMARY></INDEXTERM>
1419 </REFNAMEDIV>
1420 <REFSYNOPSISDIV>
1421 <REFSYNOPSISDIVINFO>
1422 <DATE>2001-11-14</DATE>
1423 </REFSYNOPSISDIVINFO>
1424 <SYNOPSIS>
1425 SPI_cursor_close(<REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE>)
1426 </SYNOPSIS>
1427
1428 <REFSECT2 ID="R2-SPI-SPICURSOR-CLOSE-1">
1429 <REFSECT2INFO>
1430 <DATE>2001-11-14</DATE>
1431 </REFSECT2INFO>
1432 <TITLE>Inputs
1433 </TITLE>
1434 <VARIABLELIST>
1435 <VARLISTENTRY>
1436 <TERM>
1437 Portal <REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE>
1438 </TERM>
1439 <LISTITEM>
1440 <PARA>
1441 Portal containing cursor
1442 </PARA>
1443 </LISTITEM>
1444 </VARLISTENTRY>
1445 </VARIABLELIST>
1446 </REFSECT2>
1447
1448 <REFSECT2 ID="R2-SPI-SPICURSOR-CLOSE-2">
1449 <REFSECT2INFO>
1450 <DATE>2001-11-14</DATE>
1451 </REFSECT2INFO>
1452 <TITLE>Outputs
1453 </TITLE>
1454 <VARIABLELIST>
1455 <VARLISTENTRY>
1456 <TERM>None
1457 </TERM>
1458 <LISTITEM>
1459 <PARA>
1460 </PARA>
1461 </LISTITEM>
1462 </VARLISTENTRY>
1463 </VARIABLELIST>
1464 </REFSECT2>
1465 </REFSYNOPSISDIV>
1466
1467 <REFSECT1 ID="R1-SPI-SPICURSOR-CLOSE-1">
1468 <REFSECT1INFO>
1469 <DATE>2001-11-14</DATE>
1470 </REFSECT1INFO>
1471 <TITLE>Description
1472 </TITLE>
1473 <PARA>
1474 <FUNCTION>SPI_cursor_close</FUNCTION> 
1475    closes a previously created cursor and releases its Portal storage.
1476 </para>
1477 </REFSECT1>
1478 <REFSECT1 ID="R1-SPI-SPICURSOR-CLOSE-2">
1479 <TITLE>Usage
1480 </TITLE>
1481 <Para>
1482    All open cursors are closed implicitly at transaction end.
1483    <FUNCTION>SPI_cursor_close</FUNCTION> need only be invoked if
1484    it is desirable to release resources sooner.
1485 </PARA>
1486 </REFSECT1>
1487 <!--
1488 <REFSECT1 ID="R1-SPI-SPICURSOR-CLOSE-3">
1489 <TITLE>Algorithm
1490 </TITLE>
1491 <PARA><FUNCTION>SPI_cursor_close</FUNCTION> performs the following:
1492 TBD
1493 </PARA>
1494 </REFSECT1>
1495 -->
1496 </REFENTRY>
1497
1498 <!-- *********************************************** -->
1499 <!-- *********************************************** -->
1500 <!-- *********************************************** -->
1501
1502 <REFENTRY ID="SPI-SPISAVEPLAN">
1503 <REFMETA>
1504 <REFENTRYTITLE>SPI_saveplan</REFENTRYTITLE>
1505 <REFMISCINFO>SPI - Plan Storage</REFMISCINFO>
1506 </REFMETA>
1507 <REFNAMEDIV>
1508 <REFNAME>SPI_saveplan
1509 </REFNAME>
1510 <REFPURPOSE>
1511    Saves a passed plan
1512 </REFPURPOSE>
1513 <INDEXTERM ID="IX-SPI-SPISAVEPLAN-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
1514 <INDEXTERM ID="IX-SPI-SPISAVEPLAN-2"><PRIMARY>SPI_saveplan</PRIMARY></INDEXTERM>
1515 </REFNAMEDIV>
1516 <REFSYNOPSISDIV>
1517 <REFSYNOPSISDIVINFO>
1518 <DATE>1997-12-24</DATE>
1519 </REFSYNOPSISDIVINFO>
1520 <SYNOPSIS>
1521 SPI_saveplan(<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>)
1522 </SYNOPSIS>
1523
1524 <REFSECT2 ID="R2-SPI-SPISAVEPLAN-1">
1525 <REFSECT2INFO>
1526 <DATE>1997-12-24</DATE>
1527 </REFSECT2INFO>
1528 <TITLE>Inputs
1529 </TITLE>
1530 <VARIABLELIST>
1531 <VARLISTENTRY>
1532 <TERM>
1533 void *<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>
1534 </TERM>
1535 <LISTITEM>
1536 <PARA>
1537 Passed plan
1538 </PARA>
1539 </LISTITEM>
1540 </VARLISTENTRY>
1541 </VARIABLELIST>
1542 </REFSECT2>
1543
1544 <REFSECT2 ID="R2-SPI-SPISAVEPLAN-2">
1545 <REFSECT2INFO>
1546 <DATE>1997-12-24</DATE>
1547 </REFSECT2INFO>
1548 <TITLE>Outputs
1549 </TITLE>
1550 <VARIABLELIST>
1551 <VARLISTENTRY>
1552 <TERM>void *
1553 </TERM>
1554 <LISTITEM>
1555 <PARA>
1556 Execution plan location. NULL if unsuccessful.
1557 </PARA>
1558 </LISTITEM>
1559 </VARLISTENTRY>
1560 <VARLISTENTRY>
1561 <TERM>SPI_result
1562 </TERM>
1563 <LISTITEM>
1564 <PARA>
1565 <SimpleList>
1566 <Member>
1567    <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if plan is NULL
1568 </Member>
1569 <Member>
1570    <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is un-connected
1571 </Member>
1572 </SimpleList>
1573 </PARA>
1574 </LISTITEM>
1575 </VARLISTENTRY>
1576 </VARIABLELIST>
1577 </REFSECT2>
1578 </REFSYNOPSISDIV>
1579
1580 <REFSECT1 ID="R1-SPI-SPISAVEPLAN-1">
1581 <REFSECT1INFO>
1582 <DATE>1997-12-24</DATE>
1583 </REFSECT1INFO>
1584 <TITLE>Description
1585 </TITLE>
1586 <PARA>
1587 <FUNCTION>SPI_saveplan</FUNCTION> 
1588    stores a plan prepared by <Function>SPI_prepare</Function> in safe memory
1589    protected from freeing by <Function>SPI_finish</Function> or the transaction manager.
1590 </para>
1591 <Para>
1592    In the current version of <ProductName>Postgres</ProductName> there is no ability to
1593  store prepared plans in the system
1594    catalog and fetch them from there for execution. This will be implemented
1595    in future versions.
1596
1597    As an alternative, there is the ability to reuse prepared plans in the
1598    subsequent invocations of your procedure in the current session.
1599    Use <Function>SPI_execp</Function> to execute this saved plan.
1600 </PARA>
1601 </REFSECT1>
1602 <REFSECT1 ID="R1-SPI-SPISAVEPLAN-2">
1603 <TITLE>Usage
1604 </TITLE>
1605 <Para>
1606    <Function>SPI_saveplan</Function> saves a passed plan (prepared by <Function>SPI_prepare</Function>) in memory
1607    protected from freeing by <Function>SPI_finish</Function> and by the transaction manager and
1608    returns a pointer to the saved plan.  You may save the pointer returned in
1609    a local variable.  Always check if this pointer is NULL or not either when
1610    preparing a plan or using an already prepared plan in SPI_execp (see below).
1611
1612 <Note>
1613 <Para>
1614    If one of the objects (a relation, function, etc.) referenced by the prepared
1615    plan is dropped during your session (by your backend or another process) then the
1616    results of <Function>SPI_execp</Function> for this plan will be unpredictable.
1617 </Para>
1618 </Note>
1619
1620 </PARA>
1621 </REFSECT1>
1622 <!--
1623 <REFSECT1 ID="R1-SPI-SPISAVEPLAN-3">
1624 <TITLE>Algorithm
1625 </TITLE>
1626 <PARA><FUNCTION>SPI_saveplan</FUNCTION> performs the following:
1627 TBD
1628 </PARA>
1629 </REFSECT1>
1630 -->
1631 <!--
1632 <REFSECT1 ID="R1-SPI-SPISAVEPLAN-4">
1633 <TITLE>Structures
1634 </TITLE>
1635 <PARA>None
1636 </PARA>
1637 </REFSECT1>
1638 -->
1639 </REFENTRY>
1640
1641 </Sect1>
1642
1643 <Sect1 id="spi-interface-support">
1644 <Title>Interface Support Functions</Title>
1645
1646 <Para>
1647 The functions described here provide convenient interfaces for extracting
1648 information from tuple sets returned by <function>SPI_exec</> and other
1649 SPI interface functions.
1650 </Para>
1651
1652 <Para>
1653 All functions described in this section may be used by both connected and
1654 unconnected procedures.
1655 </Para>
1656
1657 <!-- *********************************************** -->
1658 <!-- *********************************************** -->
1659 <!-- *********************************************** -->
1660
1661 <REFENTRY ID="SPI-SPIFNUMBER">
1662 <REFMETA>
1663 <REFENTRYTITLE>SPI_fnumber</REFENTRYTITLE>
1664 <REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
1665 </REFMETA>
1666 <REFNAMEDIV>
1667 <REFNAME>SPI_fnumber
1668 </REFNAME>
1669 <REFPURPOSE>
1670 Finds the attribute number for specified attribute name
1671 </REFPURPOSE>
1672 <INDEXTERM ID="IX-SPI-SPIFNUMBER-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
1673 <INDEXTERM ID="IX-SPI-SPIFNUMBER-2"><PRIMARY>SPI_fnumber</PRIMARY></INDEXTERM>
1674 </REFNAMEDIV>
1675 <REFSYNOPSISDIV>
1676 <REFSYNOPSISDIVINFO>
1677 <DATE>1997-12-24</DATE>
1678 </REFSYNOPSISDIVINFO>
1679 <SYNOPSIS>
1680 SPI_fnumber(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fname</REPLACEABLE>)
1681 </SYNOPSIS>
1682
1683 <REFSECT2 ID="R2-SPI-SPIFNUMBER-1">
1684 <REFSECT2INFO>
1685 <DATE>1997-12-24</DATE>
1686 </REFSECT2INFO>
1687 <TITLE>Inputs
1688 </TITLE>
1689 <VARIABLELIST>
1690 <VARLISTENTRY>
1691 <TERM>
1692 TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
1693 </TERM>
1694 <LISTITEM>
1695 <PARA>
1696 Input tuple description
1697 </PARA>
1698 </LISTITEM>
1699 </VARLISTENTRY>
1700 <VARLISTENTRY>
1701 <TERM>
1702 char * <REPLACEABLE CLASS="PARAMETER">fname</REPLACEABLE>
1703 </TERM>
1704 <LISTITEM>
1705 <PARA>
1706 Field name
1707 </PARA>
1708 </LISTITEM>
1709 </VARLISTENTRY>
1710 </VARIABLELIST>
1711 </REFSECT2>
1712
1713 <REFSECT2 ID="R2-SPI-SPIFNUMBER-2">
1714 <REFSECT2INFO>
1715 <DATE>1997-12-24</DATE>
1716 </REFSECT2INFO>
1717 <TITLE>Outputs
1718 </TITLE>
1719 <VARIABLELIST>
1720 <VARLISTENTRY>
1721 <TERM>
1722 int
1723 </TERM>
1724 <LISTITEM>
1725 <PARA>
1726 Attribute number
1727 <SimpleList>
1728 <Member>
1729 Valid one-based index number of attribute
1730 </Member>
1731 <Member>
1732 <ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> if the named attribute is not found
1733 </Member>
1734 </SimpleList>
1735 </para>
1736 </LISTITEM>
1737 </VARLISTENTRY>
1738 </VARIABLELIST>
1739 </REFSECT2>
1740 </REFSYNOPSISDIV>
1741
1742 <REFSECT1 ID="R1-SPI-SPIFNUMBER-1">
1743 <REFSECT1INFO>
1744 <DATE>1997-12-24</DATE>
1745 </REFSECT1INFO>
1746 <TITLE>Description
1747 </TITLE>
1748 <PARA>
1749 <FUNCTION>SPI_fnumber</FUNCTION> 
1750    returns the attribute number for the attribute with name in fname.
1751 </PARA>
1752 </REFSECT1>
1753 <REFSECT1 ID="R1-SPI-SPIFNUMBER-2">
1754 <TITLE>Usage
1755 </TITLE>
1756 <Para>
1757 Attribute numbers are 1 based.
1758 </Para>
1759 <Para>
1760 If the given fname refers to a system attribute (eg, <literal>oid</>)
1761 then the appropriate negative attribute number will be returned.
1762 The caller should be careful to test for exact equality to 
1763 <ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> to detect error;
1764 testing for result &lt;= 0 is not correct unless system attributes
1765 should be rejected.
1766 </Para>
1767 </REFSECT1>
1768 <!--
1769 <REFSECT1 ID="R1-SPI-SPIFNUMBER-3">
1770 <TITLE>Algorithm
1771 </TITLE>
1772 <PARA>
1773 </PARA>
1774 </REFSECT1>
1775 -->
1776 <!--
1777 <REFSECT1 ID="R1-SPI-SPIFNUMBER-4">
1778 <TITLE>Structures
1779 </TITLE>
1780 <PARA>None
1781 </PARA>
1782 </REFSECT1>
1783 -->
1784 </REFENTRY>
1785
1786 <!-- *********************************************** -->
1787 <!-- *********************************************** -->
1788 <!-- *********************************************** -->
1789
1790 <REFENTRY ID="SPI-SPIFNAME">
1791 <REFMETA>
1792 <REFENTRYTITLE>SPI_fname</REFENTRYTITLE>
1793 <REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
1794 </REFMETA>
1795 <REFNAMEDIV>
1796 <REFNAME>SPI_fname
1797 </REFNAME>
1798 <REFPURPOSE>
1799 Finds the attribute name for the specified attribute number
1800 </REFPURPOSE>
1801 <INDEXTERM ID="IX-SPI-SPIFNAME-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
1802 <INDEXTERM ID="IX-SPI-SPIFNAME-2"><PRIMARY>SPI_fname</PRIMARY></INDEXTERM>
1803 </REFNAMEDIV>
1804 <REFSYNOPSISDIV>
1805 <REFSYNOPSISDIVINFO>
1806 <DATE>1997-12-24</DATE>
1807 </REFSYNOPSISDIVINFO>
1808 <SYNOPSIS>
1809 SPI_fname(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>)
1810 </SYNOPSIS>
1811
1812 <REFSECT2 ID="R2-SPI-SPIFNAME-1">
1813 <REFSECT2INFO>
1814 <DATE>1997-12-24</DATE>
1815 </REFSECT2INFO>
1816 <TITLE>Inputs
1817 </TITLE>
1818 <VARIABLELIST>
1819 <VARLISTENTRY>
1820 <TERM>
1821 TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
1822 </TERM>
1823 <LISTITEM>
1824 <PARA>
1825 Input tuple description
1826 </PARA>
1827 </LISTITEM>
1828 </VARLISTENTRY>
1829 <VARLISTENTRY>
1830 <TERM>
1831 int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>
1832 </TERM>
1833 <LISTITEM>
1834 <PARA>
1835 Attribute number
1836 </PARA>
1837 </LISTITEM>
1838 </VARLISTENTRY>
1839 </VARIABLELIST>
1840 </REFSECT2>
1841
1842 <REFSECT2 ID="R2-SPI-SPIFNAME-2">
1843 <REFSECT2INFO>
1844 <DATE>1997-12-24</DATE>
1845 </REFSECT2INFO>
1846 <TITLE>Outputs
1847 </TITLE>
1848 <VARIABLELIST>
1849 <VARLISTENTRY>
1850 <TERM>
1851 char *
1852 </TERM>
1853 <LISTITEM>
1854 <PARA>
1855 Attribute name
1856 <SimpleList>
1857 <Member>
1858 NULL if fnumber is out of range
1859 </Member>
1860 <Member>
1861 SPI_result set to
1862 <ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> on error
1863 </Member>
1864 </SimpleList>
1865 </para>
1866 </LISTITEM>
1867 </VARLISTENTRY>
1868 </VARIABLELIST>
1869 </REFSECT2>
1870 </REFSYNOPSISDIV>
1871
1872 <REFSECT1 ID="R1-SPI-SPIFNAME-1">
1873 <REFSECT1INFO>
1874 <DATE>1997-12-24</DATE>
1875 </REFSECT1INFO>
1876 <TITLE>Description
1877 </TITLE>
1878 <PARA>
1879 <FUNCTION>SPI_fname</FUNCTION> 
1880    returns the attribute name for the specified attribute.
1881 </PARA>
1882 </REFSECT1>
1883 <REFSECT1 ID="R1-SPI-SPIFNAME-2">
1884 <TITLE>Usage
1885 </TITLE>
1886 <Para>
1887 Attribute numbers are 1 based.
1888 </PARA>
1889 </REFSECT1>
1890 <REFSECT1 ID="R1-SPI-SPIFNAME-3">
1891 <TITLE>Algorithm
1892 </TITLE>
1893 <PARA>
1894 Returns a newly-allocated copy of the attribute name.
1895 (Use pfree() to release the copy when done with it.)
1896 </PARA>
1897 </REFSECT1>
1898 <!--
1899 <REFSECT1 ID="R1-SPI-SPIFNAME-4">
1900 <TITLE>Structures
1901 </TITLE>
1902 <PARA>None
1903 </PARA>
1904 </REFSECT1>
1905 -->
1906 </REFENTRY>
1907
1908 <!-- *********************************************** -->
1909 <!-- *********************************************** -->
1910 <!-- *********************************************** -->
1911
1912 <REFENTRY ID="SPI-SPIGETVALUE">
1913 <REFMETA>
1914 <REFENTRYTITLE>SPI_getvalue</REFENTRYTITLE>
1915 <REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
1916 </REFMETA>
1917 <REFNAMEDIV>
1918 <REFNAME>SPI_getvalue
1919 </REFNAME>
1920 <REFPURPOSE>
1921 Returns the string value of the specified attribute
1922 </REFPURPOSE>
1923 <INDEXTERM ID="IX-SPI-SPIGETVALUE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
1924 <INDEXTERM ID="IX-SPI-SPIGETVALUE-2"><PRIMARY>SPI_getvalue</PRIMARY></INDEXTERM>
1925 </REFNAMEDIV>
1926 <REFSYNOPSISDIV>
1927 <REFSYNOPSISDIVINFO>
1928 <DATE>1997-12-24</DATE>
1929 </REFSYNOPSISDIVINFO>
1930 <SYNOPSIS>
1931 SPI_getvalue(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>)
1932 </SYNOPSIS>
1933
1934 <REFSECT2 ID="R2-SPI-SPIGETVALUE-1">
1935 <REFSECT2INFO>
1936 <DATE>1997-12-24</DATE>
1937 </REFSECT2INFO>
1938 <TITLE>Inputs
1939 </TITLE>
1940 <VARIABLELIST>
1941 <VARLISTENTRY>
1942 <TERM>
1943 HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
1944 </TERM>
1945 <LISTITEM>
1946 <PARA>
1947 Input tuple to be examined
1948 </PARA>
1949 </LISTITEM>
1950 </VARLISTENTRY>
1951 <VARLISTENTRY>
1952 <TERM>
1953 TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
1954 </TERM>
1955 <LISTITEM>
1956 <PARA>
1957 Input tuple description
1958 </PARA>
1959 </LISTITEM>
1960 </VARLISTENTRY>
1961 <VARLISTENTRY>
1962 <TERM>
1963 int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>
1964 </TERM>
1965 <LISTITEM>
1966 <PARA>
1967 Attribute number
1968 </PARA>
1969 </LISTITEM>
1970 </VARLISTENTRY>
1971 </VARIABLELIST>
1972 </REFSECT2>
1973
1974 <REFSECT2 ID="R2-SPI-SPIGETVALUE-2">
1975 <REFSECT2INFO>
1976 <DATE>1997-12-24</DATE>
1977 </REFSECT2INFO>
1978 <TITLE>Outputs
1979 </TITLE>
1980 <VARIABLELIST>
1981 <VARLISTENTRY>
1982 <TERM>
1983 char *
1984 </TERM>
1985 <LISTITEM>
1986 <PARA>
1987 Attribute value or NULL if
1988 <SimpleList>
1989 <Member>
1990 attribute is NULL
1991 </Member>
1992 <Member>
1993 fnumber is out of range
1994 (SPI_result set to
1995 <ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue>)
1996 </Member>
1997 <Member>
1998 no output function available
1999 (SPI_result set to
2000 <ReturnValue>SPI_ERROR_NOOUTFUNC</ReturnValue>)
2001 </Member>
2002 </SimpleList>
2003 </para>
2004 </LISTITEM>
2005 </VARLISTENTRY>
2006 </VARIABLELIST>
2007 </REFSECT2>
2008 </REFSYNOPSISDIV>
2009
2010 <REFSECT1 ID="R1-SPI-SPIGETVALUE-1">
2011 <REFSECT1INFO>
2012 <DATE>1997-12-24</DATE>
2013 </REFSECT1INFO>
2014 <TITLE>Description
2015 </TITLE>
2016 <PARA>
2017 <FUNCTION>SPI_getvalue</FUNCTION> 
2018    returns an external (string) representation of the value of the specified attribute.
2019 </PARA>
2020 </REFSECT1>
2021 <REFSECT1 ID="R1-SPI-SPIGETVALUE-2">
2022 <TITLE>Usage
2023 </TITLE>
2024 <Para>
2025 Attribute numbers are 1 based.
2026 </PARA>
2027 </REFSECT1>
2028 <REFSECT1 ID="R1-SPI-SPIGETVALUE-3">
2029 <TITLE>Algorithm
2030 </TITLE>
2031 <PARA>
2032 The result is returned as a palloc'd string.
2033 (Use pfree() to release the string when done with it.)
2034 </PARA>
2035 </REFSECT1>
2036 <!--
2037 <REFSECT1 ID="R1-SPI-SPIGETVALUE-4">
2038 <TITLE>Structures
2039 </TITLE>
2040 <PARA>None
2041 </PARA>
2042 </REFSECT1>
2043 -->
2044 </REFENTRY>
2045
2046 <!-- *********************************************** -->
2047 <!-- *********************************************** -->
2048 <!-- *********************************************** -->
2049
2050 <REFENTRY ID="SPI-SPIGETBINVAL">
2051 <REFMETA>
2052 <REFENTRYTITLE>SPI_getbinval</REFENTRYTITLE>
2053 <REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
2054 </REFMETA>
2055 <REFNAMEDIV>
2056 <REFNAME>SPI_getbinval
2057 </REFNAME>
2058 <REFPURPOSE>
2059 Returns the binary value of the specified attribute
2060 </REFPURPOSE>
2061 <INDEXTERM ID="IX-SPI-SPIGETBINVAL-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
2062 <INDEXTERM ID="IX-SPI-SPIGETBINVAL-2"><PRIMARY>SPI_getbinval</PRIMARY></INDEXTERM>
2063 </REFNAMEDIV>
2064 <REFSYNOPSISDIV>
2065 <REFSYNOPSISDIVINFO>
2066 <DATE>1997-12-24</DATE>
2067 </REFSYNOPSISDIVINFO>
2068 <SYNOPSIS>
2069 SPI_getbinval(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">isnull</REPLACEABLE>)
2070 </SYNOPSIS>
2071
2072 <REFSECT2 ID="R2-SPI-SPIGETBINVAL-1">
2073 <REFSECT2INFO>
2074 <DATE>1997-12-24</DATE>
2075 </REFSECT2INFO>
2076 <TITLE>Inputs
2077 </TITLE>
2078 <VARIABLELIST>
2079 <VARLISTENTRY>
2080 <TERM>
2081 HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
2082 </TERM>
2083 <LISTITEM>
2084 <PARA>
2085 Input tuple to be examined
2086 </PARA>
2087 </LISTITEM>
2088 </VARLISTENTRY>
2089 <VARLISTENTRY>
2090 <TERM>
2091 TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
2092 </TERM>
2093 <LISTITEM>
2094 <PARA>
2095 Input tuple description
2096 </PARA>
2097 </LISTITEM>
2098 </VARLISTENTRY>
2099 <VARLISTENTRY>
2100 <TERM>
2101 int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>
2102 </TERM>
2103 <LISTITEM>
2104 <PARA>
2105 Attribute number
2106 </PARA>
2107 </LISTITEM>
2108 </VARLISTENTRY>
2109 </VARIABLELIST>
2110 </REFSECT2>
2111
2112 <REFSECT2 ID="R2-SPI-SPIGETBINVAL-2">
2113 <REFSECT2INFO>
2114 <DATE>1997-12-24</DATE>
2115 </REFSECT2INFO>
2116 <TITLE>Outputs
2117 </TITLE>
2118 <VARIABLELIST>
2119 <VARLISTENTRY>
2120 <TERM>
2121 Datum
2122 </TERM>
2123 <LISTITEM>
2124 <PARA>
2125 Attribute binary value
2126 </PARA>
2127 </LISTITEM>
2128 </VARLISTENTRY>
2129 <VARLISTENTRY>
2130 <TERM>
2131 bool * <REPLACEABLE CLASS="PARAMETER">isnull</REPLACEABLE>
2132 </TERM>
2133 <LISTITEM>
2134 <PARA>
2135 flag for null value in attribute
2136 </PARA>
2137 </LISTITEM>
2138 </VARLISTENTRY>
2139 <VARLISTENTRY>
2140 <TERM>
2141 SPI_result
2142 </TERM>
2143 <LISTITEM>
2144 <PARA>
2145 <SimpleList>
2146 <Member>
2147 <ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue>
2148 </Member>
2149 </SimpleList>
2150 </PARA>
2151 </LISTITEM>
2152 </VARLISTENTRY>
2153 </VARIABLELIST>
2154 </REFSECT2>
2155 </REFSYNOPSISDIV>
2156
2157 <REFSECT1 ID="R1-SPI-SPIGETBINVAL-1">
2158 <REFSECT1INFO>
2159 <DATE>1997-12-24</DATE>
2160 </REFSECT1INFO>
2161 <TITLE>Description
2162 </TITLE>
2163 <PARA>
2164 <FUNCTION>SPI_getbinval</FUNCTION> 
2165    returns the specified attribute's value in internal form (as a Datum).
2166 </PARA>
2167 </REFSECT1>
2168 <REFSECT1 ID="R1-SPI-SPIGETBINVAL-2">
2169 <TITLE>Usage
2170 </TITLE>
2171 <Para>
2172 Attribute numbers are 1 based.
2173 </PARA>
2174 </REFSECT1>
2175 <REFSECT1 ID="R1-SPI-SPIGETBINVAL-3">
2176 <TITLE>Algorithm
2177 </TITLE>
2178 <PARA>
2179 Does not allocate new space for the datum.  In the case of a pass-by-
2180 reference datatype, the Datum will be a pointer into the given tuple.
2181 </PARA>
2182 </REFSECT1>
2183 <!--
2184 <REFSECT1 ID="R1-SPI-SPIGETBINVAL-4">
2185 <TITLE>Structures
2186 </TITLE>
2187 <PARA>None
2188 </PARA>
2189 </REFSECT1>
2190 -->
2191 </REFENTRY>
2192
2193 <!-- *********************************************** -->
2194 <!-- *********************************************** -->
2195 <!-- *********************************************** -->
2196
2197 <REFENTRY ID="SPI-SPIGETTYPE">
2198 <REFMETA>
2199 <REFENTRYTITLE>SPI_gettype</REFENTRYTITLE>
2200 <REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
2201 </REFMETA>
2202 <REFNAMEDIV>
2203 <REFNAME>SPI_gettype
2204 </REFNAME>
2205 <REFPURPOSE>
2206 Returns the type name of the specified attribute
2207 </REFPURPOSE>
2208 <INDEXTERM ID="IX-SPI-SPIGETTYPE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
2209 <INDEXTERM ID="IX-SPI-SPIGETTYPE-2"><PRIMARY>SPI_gettype</PRIMARY></INDEXTERM>
2210 </REFNAMEDIV>
2211 <REFSYNOPSISDIV>
2212 <REFSYNOPSISDIVINFO>
2213 <DATE>1997-12-24</DATE>
2214 </REFSYNOPSISDIVINFO>
2215 <SYNOPSIS>
2216 SPI_gettype(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>)
2217 </SYNOPSIS>
2218
2219 <REFSECT2 ID="R2-SPI-SPIGETTYPE-1">
2220 <REFSECT2INFO>
2221 <DATE>1997-12-24</DATE>
2222 </REFSECT2INFO>
2223 <TITLE>Inputs
2224 </TITLE>
2225 <VARIABLELIST>
2226 <VARLISTENTRY>
2227 <TERM>
2228 TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
2229 </TERM>
2230 <LISTITEM>
2231 <PARA>
2232 Input tuple description
2233 </PARA>
2234 </LISTITEM>
2235 </VARLISTENTRY>
2236 <VARLISTENTRY>
2237 <TERM>
2238 int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>
2239 </TERM>
2240 <LISTITEM>
2241 <PARA>
2242 Attribute number
2243 </PARA>
2244 </LISTITEM>
2245 </VARLISTENTRY>
2246 </VARIABLELIST>
2247 </REFSECT2>
2248
2249 <REFSECT2 ID="R2-SPI-SPIGETTYPE-2">
2250 <REFSECT2INFO>
2251 <DATE>1997-12-24</DATE>
2252 </REFSECT2INFO>
2253 <TITLE>Outputs
2254 </TITLE>
2255 <VARIABLELIST>
2256 <VARLISTENTRY>
2257 <TERM>
2258 char *
2259 </TERM>
2260 <LISTITEM>
2261 <PARA>
2262 The type name for the specified attribute number
2263 </PARA>
2264 </LISTITEM>
2265 </VARLISTENTRY>
2266 <VARLISTENTRY>
2267 <TERM>
2268 SPI_result
2269 </TERM>
2270 <LISTITEM>
2271 <PARA>
2272 <SimpleList>
2273 <Member>
2274 <ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue>
2275 </Member>
2276 </SimpleList>
2277 </PARA>
2278 </LISTITEM>
2279 </VARLISTENTRY>
2280 </VARIABLELIST>
2281 </REFSECT2>
2282 </REFSYNOPSISDIV>
2283
2284 <REFSECT1 ID="R1-SPI-SPIGETTYPE-1">
2285 <REFSECT1INFO>
2286 <DATE>1997-12-24</DATE>
2287 </REFSECT1INFO>
2288 <TITLE>Description
2289 </TITLE>
2290 <PARA>
2291 <FUNCTION>SPI_gettype</FUNCTION> 
2292    returns a copy of the type name for the specified attribute,
2293    or NULL on error.
2294 </PARA>
2295 </REFSECT1>
2296 <REFSECT1 ID="R1-SPI-SPIGETTYPE-2">
2297 <TITLE>Usage
2298 </TITLE>
2299 <Para>
2300 Attribute numbers are 1 based.
2301 </PARA>
2302 </REFSECT1>
2303 <REFSECT1 ID="R1-SPI-SPIGETTYPE-3">
2304 <TITLE>Algorithm
2305 </TITLE>
2306 <PARA>
2307 Returns a newly-allocated copy of the type name.
2308 (Use pfree() to release the copy when done with it.)
2309 </PARA>
2310 </REFSECT1>
2311 <!--
2312 <REFSECT1 ID="R1-SPI-SPIGETTYPE-4">
2313 <TITLE>Structures
2314 </TITLE>
2315 <PARA>None
2316 </PARA>
2317 </REFSECT1>
2318 -->
2319 </REFENTRY>
2320
2321 <!-- *********************************************** -->
2322 <!-- *********************************************** -->
2323 <!-- *********************************************** -->
2324
2325 <REFENTRY ID="SPI-SPIGETTYPEID">
2326 <REFMETA>
2327 <REFENTRYTITLE>SPI_gettypeid</REFENTRYTITLE>
2328 <REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
2329 </REFMETA>
2330 <REFNAMEDIV>
2331 <REFNAME>SPI_gettypeid
2332 </REFNAME>
2333 <REFPURPOSE>
2334 Returns the type <Acronym>OID</Acronym> of the specified attribute
2335 </REFPURPOSE>
2336 <INDEXTERM ID="IX-SPI-SPIGETTYPEID-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
2337 <INDEXTERM ID="IX-SPI-SPIGETTYPEID-2"><PRIMARY>SPI_gettypeid</PRIMARY></INDEXTERM>
2338 </REFNAMEDIV>
2339 <REFSYNOPSISDIV>
2340 <REFSYNOPSISDIVINFO>
2341 <DATE>1997-12-24</DATE>
2342 </REFSYNOPSISDIVINFO>
2343 <SYNOPSIS>
2344 SPI_gettypeid(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>)
2345 </SYNOPSIS>
2346
2347 <REFSECT2 ID="R2-SPI-SPIGETTYPEID-1">
2348 <REFSECT2INFO>
2349 <DATE>1997-12-24</DATE>
2350 </REFSECT2INFO>
2351 <TITLE>Inputs
2352 </TITLE>
2353 <VARIABLELIST>
2354 <VARLISTENTRY>
2355 <TERM>
2356 TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
2357 </TERM>
2358 <LISTITEM>
2359 <PARA>
2360 Input tuple description
2361 </PARA>
2362 </LISTITEM>
2363 </VARLISTENTRY>
2364 <VARLISTENTRY>
2365 <TERM>
2366 int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>
2367 </TERM>
2368 <LISTITEM>
2369 <PARA>
2370 Attribute number
2371 </PARA>
2372 </LISTITEM>
2373 </VARLISTENTRY>
2374 </VARIABLELIST>
2375 </REFSECT2>
2376
2377 <REFSECT2 ID="R2-SPI-SPIGETTYPEID-2">
2378 <REFSECT2INFO>
2379 <DATE>1997-12-24</DATE>
2380 </REFSECT2INFO>
2381 <TITLE>Outputs
2382 </TITLE>
2383 <VARIABLELIST>
2384 <VARLISTENTRY>
2385 <TERM>
2386 <Acronym>OID</Acronym>
2387 </TERM>
2388 <LISTITEM>
2389 <PARA>
2390 The type <Acronym>OID</Acronym> for the specified attribute number
2391 </PARA>
2392 </LISTITEM>
2393 </VARLISTENTRY>
2394 <VARLISTENTRY>
2395 <TERM>
2396 SPI_result
2397 </TERM>
2398 <LISTITEM>
2399 <PARA>
2400 <SimpleList>
2401 <Member>
2402 <ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue>
2403 </Member>
2404 </SimpleList>
2405 </PARA>
2406 </LISTITEM>
2407 </VARLISTENTRY>
2408 </VARIABLELIST>
2409 </REFSECT2>
2410 </REFSYNOPSISDIV>
2411
2412 <REFSECT1 ID="R1-SPI-SPIGETTYPEID-1">
2413 <REFSECT1INFO>
2414 <DATE>1997-12-24</DATE>
2415 </REFSECT1INFO>
2416 <TITLE>Description
2417 </TITLE>
2418 <PARA>
2419 <FUNCTION>SPI_gettypeid</FUNCTION> 
2420    returns the type <Acronym>OID</Acronym> for the specified attribute.
2421 </PARA>
2422 </REFSECT1>
2423 <REFSECT1 ID="R1-SPI-SPIGETTYPEID-2">
2424 <TITLE>Usage
2425 </TITLE>
2426 <Para>
2427 Attribute numbers are 1 based.
2428 </PARA>
2429 </REFSECT1>
2430 <!--
2431 <REFSECT1 ID="R1-SPI-SPIGETTYPEID-3">
2432 <TITLE>Algorithm
2433 </TITLE>
2434 <PARA>
2435 TBD
2436 </PARA>
2437 </REFSECT1>
2438 -->
2439 <!--
2440 <REFSECT1 ID="R1-SPI-SPIGETTYPEID-4">
2441 <TITLE>Structures
2442 </TITLE>
2443 <PARA>None
2444 </PARA>
2445 </REFSECT1>
2446 -->
2447 </REFENTRY>
2448
2449 <!-- *********************************************** -->
2450 <!-- *********************************************** -->
2451 <!-- *********************************************** -->
2452
2453 <REFENTRY ID="SPI-SPIGETRELNAME">
2454 <REFMETA>
2455 <REFENTRYTITLE>SPI_getrelname</REFENTRYTITLE>
2456 <REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
2457 </REFMETA>
2458 <REFNAMEDIV>
2459 <REFNAME>SPI_getrelname
2460 </REFNAME>
2461 <REFPURPOSE>
2462 Returns the name of the specified relation
2463 </REFPURPOSE>
2464 <INDEXTERM ID="IX-SPI-SPIGETRELNAME-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
2465 <INDEXTERM ID="IX-SPI-SPIGETRELNAME-2"><PRIMARY>SPI_getrelname</PRIMARY></INDEXTERM>
2466 </REFNAMEDIV>
2467 <REFSYNOPSISDIV>
2468 <REFSYNOPSISDIVINFO>
2469 <DATE>1997-12-24</DATE>
2470 </REFSYNOPSISDIVINFO>
2471 <SYNOPSIS>
2472 SPI_getrelname(<REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>)
2473 </SYNOPSIS>
2474
2475 <REFSECT2 ID="R2-SPI-SPIGETRELNAME-1">
2476 <REFSECT2INFO>
2477 <DATE>1997-12-24</DATE>
2478 </REFSECT2INFO>
2479 <TITLE>Inputs
2480 </TITLE>
2481 <VARIABLELIST>
2482 <VARLISTENTRY>
2483 <TERM>
2484 Relation <REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>
2485 </TERM>
2486 <LISTITEM>
2487 <PARA>
2488 Input relation
2489 </PARA>
2490 </LISTITEM>
2491 </VARLISTENTRY>
2492 </VARIABLELIST>
2493 </REFSECT2>
2494
2495 <REFSECT2 ID="R2-SPI-SPIGETRELNAME-2">
2496 <REFSECT2INFO>
2497 <DATE>1997-12-24</DATE>
2498 </REFSECT2INFO>
2499 <TITLE>Outputs
2500 </TITLE>
2501 <VARIABLELIST>
2502 <VARLISTENTRY>
2503 <TERM>
2504 char *
2505 </TERM>
2506 <LISTITEM>
2507 <PARA>
2508 The name of the specified relation
2509 </PARA>
2510 </LISTITEM>
2511 </VARLISTENTRY>
2512 </VARIABLELIST>
2513 </REFSECT2>
2514 </REFSYNOPSISDIV>
2515
2516 <REFSECT1 ID="R1-SPI-SPIGETRELNAME-1">
2517 <REFSECT1INFO>
2518 <DATE>1997-12-24</DATE>
2519 </REFSECT1INFO>
2520 <TITLE>Description
2521 </TITLE>
2522 <PARA>
2523 <FUNCTION>SPI_getrelname</FUNCTION> 
2524    returns the name of the specified relation.
2525 </PARA>
2526 </REFSECT1>
2527 <!--
2528 <REFSECT1 ID="R1-SPI-SPIGETRELNAME-2">
2529 <TITLE>Usage
2530 </TITLE>
2531 <Para>
2532 TBD
2533 </PARA>
2534 </REFSECT1>
2535 -->
2536 <REFSECT1 ID="R1-SPI-SPIGETRELNAME-3">
2537 <TITLE>Algorithm
2538 </TITLE>
2539 <PARA>
2540 Returns a newly-allocated copy of the rel name.
2541 (Use pfree() to release the copy when done with it.)
2542 </PARA>
2543 </REFSECT1>
2544 <!--
2545 <REFSECT1 ID="R1-SPI-SPIGETRELNAME-4">
2546 <TITLE>Structures
2547 </TITLE>
2548 <PARA>None
2549 </PARA>
2550 </REFSECT1>
2551 -->
2552 </REFENTRY>
2553
2554 </Sect1>
2555
2556 <Sect1 id="spi-memory">
2557 <Title>Memory Management</Title>
2558
2559 <Para>
2560 <ProductName>Postgres</ProductName> allocates memory within memory
2561 <firstterm>contexts</firstterm>, which provide a convenient method of
2562 managing allocations made in many different places that need to live
2563 for differing amounts of time.  Destroying a context releases all the
2564 memory that was allocated in it.  Thus, it is not necessary to keep track
2565 of individual objects to avoid memory leaks --- only a relatively small number
2566 of contexts have to be managed.  <Function>palloc</Function> and related
2567 functions allocate memory from the <quote>current</> context.
2568 </Para>
2569 <Para>
2570 <Function>SPI_connect</Function> creates a new memory context and makes
2571 it current.  <Function>SPI_finish</Function> restores the previous
2572 current memory context and destroys the context created by
2573 <Function>SPI_connect</Function>.  These actions ensure that transient
2574 memory allocations made inside your procedure are reclaimed at procedure
2575 exit, avoiding memory leakage.
2576 </Para>
2577 <Para>
2578 However, if your procedure needs to return an allocated memory object
2579 (such as a value of a pass-by-reference datatype), you can't allocate
2580 the return object using <Function>palloc</Function>, at least not while
2581 you are connected to SPI.  If you try, the object will be deallocated
2582 during <Function>SPI_finish</Function>, and your procedure will not
2583 work reliably!
2584 </Para>
2585 <Para>
2586 To solve this problem, use <Function>SPI_palloc</Function> to allocate
2587 your return object.  <Function>SPI_palloc</Function> allocates space
2588 from <quote>upper Executor</> memory --- that is, the memory context
2589 that was current when <Function>SPI_connect</Function> was called,
2590 which is precisely the right context for return values of your procedure.
2591 </Para>
2592 <Para>
2593 If called while not connected to SPI, <Function>SPI_palloc</Function>
2594 acts the same as plain <Function>palloc</Function>.
2595 </Para>
2596 <Para>
2597    Before a procedure connects to the SPI manager, the current memory context
2598 is the upper Executor context, so all allocations made by the procedure via
2599 <Function>palloc</Function> or by SPI utility functions are
2600 made in this context.
2601 </Para>
2602 <Para>
2603    After <Function>SPI_connect</Function> is called, the current context is
2604    the procedure's private context made by <Function>SPI_connect</Function>.
2605    All allocations made via
2606 <Function>palloc</Function>/<Function>repalloc</Function> or by SPI utility
2607 functions (except for <Function>SPI_copytuple</Function>,
2608 <Function>SPI_copytupledesc</Function>,
2609 <Function>SPI_copytupleintoslot</Function>,
2610 <Function>SPI_modifytuple</Function>,
2611 and <Function>SPI_palloc</Function>) are
2612 made in this context.
2613 </Para>
2614 <Para>
2615 When a procedure disconnects from the SPI manager (via
2616 <Function>SPI_finish</Function>) the
2617 current context is restored to the upper Executor context, and all allocations
2618 made in the procedure memory context are freed and can't be used any more!
2619 </Para>
2620
2621 <Para>
2622 All functions described in this section may be used by both connected and
2623 unconnected procedures.  In an unconnected procedure, they act the same
2624 as the underlying ordinary backend functions (<function>palloc</> etc).
2625 </Para>
2626
2627 <!-- *********************************************** -->
2628 <!-- *********************************************** -->
2629 <!-- *********************************************** -->
2630
2631 <REFENTRY ID="SPI-SPICOPYTUPLE">
2632 <REFMETA>
2633 <REFENTRYTITLE>SPI_copytuple</REFENTRYTITLE>
2634 <REFMISCINFO>SPI - Tuple Copy</REFMISCINFO>
2635 </REFMETA>
2636 <REFNAMEDIV>
2637 <REFNAME>SPI_copytuple
2638 </REFNAME>
2639 <REFPURPOSE>
2640 Makes copy of tuple in upper Executor context
2641 </REFPURPOSE>
2642 <INDEXTERM ID="IX-SPI-SPICOPYTUPLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>copying tuples</SECONDARY></INDEXTERM>
2643 <INDEXTERM ID="IX-SPI-SPICOPYTUPLE-2"><PRIMARY>SPI_copytuple</PRIMARY></INDEXTERM>
2644 </REFNAMEDIV>
2645 <REFSYNOPSISDIV>
2646 <REFSYNOPSISDIVINFO>
2647 <DATE>1997-12-24</DATE>
2648 </REFSYNOPSISDIVINFO>
2649 <SYNOPSIS>
2650 SPI_copytuple(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>)
2651 </SYNOPSIS>
2652
2653 <REFSECT2 ID="R2-SPI-SPICOPYTUPLE-1">
2654 <REFSECT2INFO>
2655 <DATE>1997-12-24</DATE>
2656 </REFSECT2INFO>
2657 <TITLE>Inputs
2658 </TITLE>
2659 <VARIABLELIST>
2660 <VARLISTENTRY>
2661 <TERM>
2662 HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
2663 </TERM>
2664 <LISTITEM>
2665 <PARA>
2666 Input tuple to be copied
2667 </PARA>
2668 </LISTITEM>
2669 </VARLISTENTRY>
2670 </VARIABLELIST>
2671 </REFSECT2>
2672
2673 <REFSECT2 ID="R2-SPI-SPICOPYTUPLE-2">
2674 <REFSECT2INFO>
2675 <DATE>1997-12-24</DATE>
2676 </REFSECT2INFO>
2677 <TITLE>Outputs
2678 </TITLE>
2679 <VARIABLELIST>
2680 <VARLISTENTRY>
2681 <TERM>
2682 HeapTuple
2683 </TERM>
2684 <LISTITEM>
2685 <PARA>
2686 Copied tuple
2687 <SimpleList>
2688 <Member>
2689  <ReturnValue>non-NULL</ReturnValue>
2690  if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
2691  is not NULL and the copy was successful
2692 </Member>
2693 <Member>
2694    <ReturnValue>NULL</ReturnValue>
2695  only if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
2696  is NULL
2697 </Member>
2698 </SimpleList>
2699 </para>
2700 </LISTITEM>
2701 </VARLISTENTRY>
2702 </VARIABLELIST>
2703 </REFSECT2>
2704 </REFSYNOPSISDIV>
2705
2706 <REFSECT1 ID="R1-SPI-SPICOPYTUPLE-1">
2707 <REFSECT1INFO>
2708 <DATE>1997-12-24</DATE>
2709 </REFSECT1INFO>
2710 <TITLE>Description
2711 </TITLE>
2712 <PARA>
2713 <FUNCTION>SPI_copytuple</FUNCTION> 
2714    makes a copy of tuple in upper Executor context.
2715 </PARA>
2716 </REFSECT1>
2717 <REFSECT1 ID="R1-SPI-SPICOPYTUPLE-2">
2718 <TITLE>Usage
2719 </TITLE>
2720 <Para>
2721 TBD
2722 </PARA>
2723 </REFSECT1>
2724 <!--
2725 <REFSECT1 ID="R1-SPI-SPICOPYTUPLE-3">
2726 <TITLE>Algorithm
2727 </TITLE>
2728 <PARA>
2729 </PARA>
2730 </REFSECT1>
2731 -->
2732 <!--
2733 <REFSECT1 ID="R1-SPI-SPICOPYTUPLE-4">
2734 <TITLE>Structures
2735 </TITLE>
2736 <PARA>None
2737 </PARA>
2738 </REFSECT1>
2739 -->
2740 </REFENTRY>
2741
2742 <!-- *********************************************** -->
2743 <!-- *********************************************** -->
2744 <!-- *********************************************** -->
2745
2746 <REFENTRY ID="SPI-SPICOPYTUPLEDESC">
2747 <REFMETA>
2748 <REFENTRYTITLE>SPI_copytupledesc</REFENTRYTITLE>
2749 <REFMISCINFO>SPI - Tuple Descriptor Copy</REFMISCINFO>
2750 </REFMETA>
2751 <REFNAMEDIV>
2752 <REFNAME>SPI_copytupledesc
2753 </REFNAME>
2754 <REFPURPOSE>
2755 Makes copy of tuple descriptor in upper Executor context
2756 </REFPURPOSE>
2757 <INDEXTERM ID="IX-SPI-SPICOPYTUPLEDESC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>copying tuple descriptors</SECONDARY></INDEXTERM>
2758 <INDEXTERM ID="IX-SPI-SPICOPYTUPLEDESC-2"><PRIMARY>SPI_copytupledesc</PRIMARY></INDEXTERM>
2759 </REFNAMEDIV>
2760 <REFSYNOPSISDIV>
2761 <REFSYNOPSISDIVINFO>
2762 <DATE>2001-08-02</DATE>
2763 </REFSYNOPSISDIVINFO>
2764 <SYNOPSIS>
2765 SPI_copytupledesc(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>)
2766 </SYNOPSIS>
2767
2768 <REFSECT2 ID="R2-SPI-SPICOPYTUPLEDESC-1">
2769 <REFSECT2INFO>
2770 <DATE>2001-08-02</DATE>
2771 </REFSECT2INFO>
2772 <TITLE>Inputs
2773 </TITLE>
2774 <VARIABLELIST>
2775 <VARLISTENTRY>
2776 <TERM>
2777 TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
2778 </TERM>
2779 <LISTITEM>
2780 <PARA>
2781 Input tuple descriptor to be copied
2782 </PARA>
2783 </LISTITEM>
2784 </VARLISTENTRY>
2785 </VARIABLELIST>
2786 </REFSECT2>
2787
2788 <REFSECT2 ID="R2-SPI-SPICOPYTUPLEDESC-2">
2789 <REFSECT2INFO>
2790 <DATE>2001-08-02</DATE>
2791 </REFSECT2INFO>
2792 <TITLE>Outputs
2793 </TITLE>
2794 <VARIABLELIST>
2795 <VARLISTENTRY>
2796 <TERM>
2797 TupleDesc
2798 </TERM>
2799 <LISTITEM>
2800 <PARA>
2801 Copied tuple descriptor
2802 <SimpleList>
2803 <Member>
2804  <ReturnValue>non-NULL</ReturnValue>
2805  if <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
2806  is not NULL and the copy was successful
2807 </Member>
2808 <Member>
2809    <ReturnValue>NULL</ReturnValue>
2810  only if <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
2811  is NULL
2812 </Member>
2813 </SimpleList>
2814 </para>
2815 </LISTITEM>
2816 </VARLISTENTRY>
2817 </VARIABLELIST>
2818 </REFSECT2>
2819 </REFSYNOPSISDIV>
2820
2821 <REFSECT1 ID="R1-SPI-SPICOPYTUPLEDESC-1">
2822 <REFSECT1INFO>
2823 <DATE>2001-08-02</DATE>
2824 </REFSECT1INFO>
2825 <TITLE>Description
2826 </TITLE>
2827 <PARA>
2828 <FUNCTION>SPI_copytupledesc</FUNCTION> 
2829    makes a copy of tupdesc in upper Executor context.
2830 </PARA>
2831 </REFSECT1>
2832 <REFSECT1 ID="R1-SPI-SPICOPYTUPLEDESC-2">
2833 <TITLE>Usage
2834 </TITLE>
2835 <Para>
2836 TBD
2837 </PARA>
2838 </REFSECT1>
2839 <!--
2840 <REFSECT1 ID="R1-SPI-SPICOPYTUPLEDESC-3">
2841 <TITLE>Algorithm
2842 </TITLE>
2843 <PARA>
2844 </PARA>
2845 </REFSECT1>
2846 -->
2847 <!--
2848 <REFSECT1 ID="R1-SPI-SPICOPYTUPLEDESC-4">
2849 <TITLE>Structures
2850 </TITLE>
2851 <PARA>None
2852 </PARA>
2853 </REFSECT1>
2854 -->
2855 </REFENTRY>
2856
2857 <!-- *********************************************** -->
2858 <!-- *********************************************** -->
2859 <!-- *********************************************** -->
2860
2861 <REFENTRY ID="SPI-SPICOPYTUPLEINTOSLOT">
2862 <REFMETA>
2863 <REFENTRYTITLE>SPI_copytupleintoslot</REFENTRYTITLE>
2864 <REFMISCINFO>SPI - Tuple and Descriptor Copy</REFMISCINFO>
2865 </REFMETA>
2866 <REFNAMEDIV>
2867 <REFNAME>SPI_copytupleintoslot
2868 </REFNAME>
2869 <REFPURPOSE>
2870 Makes copy of tuple and descriptor in upper Executor context
2871 </REFPURPOSE>
2872 <INDEXTERM ID="IX-SPI-SPICOPYTUPLEINTOSLOT-1"><PRIMARY>SPI</PRIMARY><SECONDARY>copying tuples</SECONDARY></INDEXTERM>
2873 <INDEXTERM ID="IX-SPI-SPICOPYTUPLEINTOSLOT-2"><PRIMARY>SPI_copytupleintoslot</PRIMARY></INDEXTERM>
2874 </REFNAMEDIV>
2875 <REFSYNOPSISDIV>
2876 <REFSYNOPSISDIVINFO>
2877 <DATE>1997-12-24</DATE>
2878 </REFSYNOPSISDIVINFO>
2879 <SYNOPSIS>
2880 SPI_copytupleintoslot(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>)
2881 </SYNOPSIS>
2882
2883 <REFSECT2 ID="R2-SPI-SPICOPYTUPLEINTOSLOT-1">
2884 <REFSECT2INFO>
2885 <DATE>1997-12-24</DATE>
2886 </REFSECT2INFO>
2887 <TITLE>Inputs
2888 </TITLE>
2889 <VARIABLELIST>
2890 <VARLISTENTRY>
2891 <TERM>
2892 HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
2893 </TERM>
2894 <LISTITEM>
2895 <PARA>
2896 Input tuple to be copied
2897 </PARA>
2898 </LISTITEM>
2899 </VARLISTENTRY>
2900 <VARLISTENTRY>
2901 <TERM>
2902 TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
2903 </TERM>
2904 <LISTITEM>
2905 <PARA>
2906 Input tuple descriptor to be copied
2907 </PARA>
2908 </LISTITEM>
2909 </VARLISTENTRY>
2910 </VARIABLELIST>
2911 </REFSECT2>
2912
2913 <REFSECT2 ID="R2-SPI-SPICOPYTUPLEINTOSLOT-2">
2914 <REFSECT2INFO>
2915 <DATE>1997-12-24</DATE>
2916 </REFSECT2INFO>
2917 <TITLE>Outputs
2918 </TITLE>
2919 <VARIABLELIST>
2920 <VARLISTENTRY>
2921 <TERM>
2922 TupleTableSlot *
2923 </TERM>
2924 <LISTITEM>
2925 <PARA>
2926 Tuple slot containing copied tuple and descriptor
2927 <SimpleList>
2928 <Member>
2929  <ReturnValue>non-NULL</ReturnValue>
2930  if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
2931  and <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
2932  are not NULL and the copy was successful
2933 </Member>
2934 <Member>
2935    <ReturnValue>NULL</ReturnValue>
2936  only if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
2937  or <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
2938  is NULL
2939 </Member>
2940 </SimpleList>
2941 </para>
2942 </LISTITEM>
2943 </VARLISTENTRY>
2944 </VARIABLELIST>
2945 </REFSECT2>
2946 </REFSYNOPSISDIV>
2947
2948 <REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-1">
2949 <REFSECT1INFO>
2950 <DATE>1997-12-24</DATE>
2951 </REFSECT1INFO>
2952 <TITLE>Description
2953 </TITLE>
2954 <PARA>
2955 <FUNCTION>SPI_copytupleintoslot</FUNCTION> 
2956    makes a copy of tuple in upper Executor context, returning it in the
2957    form of a filled-in TupleTableSlot.
2958 </PARA>
2959 </REFSECT1>
2960 <REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-2">
2961 <TITLE>Usage
2962 </TITLE>
2963 <Para>
2964 TBD
2965 </PARA>
2966 </REFSECT1>
2967 <!--
2968 <REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-3">
2969 <TITLE>Algorithm
2970 </TITLE>
2971 <PARA>
2972 </PARA>
2973 </REFSECT1>
2974 -->
2975 <!--
2976 <REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-4">
2977 <TITLE>Structures
2978 </TITLE>
2979 <PARA>None
2980 </PARA>
2981 </REFSECT1>
2982 -->
2983 </REFENTRY>
2984
2985 <!-- *********************************************** -->
2986 <!-- *********************************************** -->
2987 <!-- *********************************************** -->
2988
2989 <REFENTRY ID="SPI-SPIMODIFYTUPLE">
2990 <REFMETA>
2991 <REFENTRYTITLE>SPI_modifytuple</REFENTRYTITLE>
2992 <REFMISCINFO>SPI - Tuple Modify</REFMISCINFO>
2993 </REFMETA>
2994 <REFNAMEDIV>
2995 <REFNAME>SPI_modifytuple
2996 </REFNAME>
2997 <REFPURPOSE>
2998 Creates a tuple by replacing selected fields of a given tuple
2999 </REFPURPOSE>
3000 <INDEXTERM ID="IX-SPI-SPIMODIFYTUPLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>modifying tuples</SECONDARY></INDEXTERM>
3001 <INDEXTERM ID="IX-SPI-SPIMODIFYTUPLE-2"><PRIMARY>SPI_modifytuple</PRIMARY></INDEXTERM>
3002 </REFNAMEDIV>
3003 <REFSYNOPSISDIV>
3004 <REFSYNOPSISDIVINFO>
3005 <DATE>1997-12-24</DATE>
3006 </REFSYNOPSISDIVINFO>
3007 <SYNOPSIS>
3008 SPI_modifytuple(<REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">nattrs</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">attnum</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">Values</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">Nulls</REPLACEABLE>)
3009 </SYNOPSIS>
3010
3011 <REFSECT2 ID="R2-SPI-SPIMODIFYTUPLE-1">
3012 <REFSECT2INFO>
3013 <DATE>1997-12-24</DATE>
3014 </REFSECT2INFO>
3015 <TITLE>Inputs
3016 </TITLE>
3017 <VARIABLELIST>
3018 <VARLISTENTRY>
3019 <TERM>
3020 Relation <REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>
3021 </TERM>
3022 <LISTITEM>
3023 <PARA>
3024 Used only as source of tuple descriptor for tuple.  (Passing a relation
3025 rather than a tuple descriptor is a misfeature.)
3026 </PARA>
3027 </LISTITEM>
3028 </VARLISTENTRY>
3029 <VARLISTENTRY>
3030 <TERM>
3031 HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
3032 </TERM>
3033 <LISTITEM>
3034 <PARA>
3035 Input tuple to be modified
3036 </PARA>
3037 </LISTITEM>
3038 </VARLISTENTRY>
3039 <VARLISTENTRY>
3040 <TERM>
3041 int <REPLACEABLE CLASS="PARAMETER">nattrs</REPLACEABLE>
3042 </TERM>
3043 <LISTITEM>
3044 <PARA>
3045 Number of attribute numbers in attnum array
3046 </PARA>
3047 </LISTITEM>
3048 </VARLISTENTRY>
3049 <VARLISTENTRY>
3050 <TERM>
3051 int * <REPLACEABLE CLASS="PARAMETER">attnum</REPLACEABLE>
3052 </TERM>
3053 <LISTITEM>
3054 <PARA>
3055 Array of numbers of the attributes that are to be changed
3056 </PARA>
3057 </LISTITEM>
3058 </VARLISTENTRY>
3059 <VARLISTENTRY>
3060 <TERM>
3061 Datum * <REPLACEABLE CLASS="PARAMETER">Values</REPLACEABLE>
3062 </TERM>
3063 <LISTITEM>
3064 <PARA>
3065 New values for the attributes specified
3066 </PARA>
3067 </LISTITEM>
3068 </VARLISTENTRY>
3069 <VARLISTENTRY>
3070 <TERM>
3071 char * <REPLACEABLE CLASS="PARAMETER">Nulls</REPLACEABLE>
3072 </TERM>
3073 <LISTITEM>
3074 <PARA>
3075 Which new values are NULL, if any
3076 </PARA>
3077 </LISTITEM>
3078 </VARLISTENTRY>
3079 </VARIABLELIST>
3080 </REFSECT2>
3081
3082 <REFSECT2 ID="R2-SPI-SPIMODIFYTUPLE-2">
3083 <REFSECT2INFO>
3084 <DATE>1997-12-24</DATE>
3085 </REFSECT2INFO>
3086 <TITLE>Outputs
3087 </TITLE>
3088 <VARIABLELIST>
3089 <VARLISTENTRY>
3090 <TERM>
3091 HeapTuple
3092 </TERM>
3093 <LISTITEM>
3094 <PARA>
3095 New tuple with modifications
3096 <SimpleList>
3097 <Member>
3098  <ReturnValue>non-NULL</ReturnValue>
3099  if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
3100  is not NULL and the modify was successful
3101 </Member>
3102 <Member>
3103    <ReturnValue>NULL</ReturnValue>
3104  only if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
3105  is NULL
3106 </Member>
3107 </SimpleList>
3108 </para>
3109 </LISTITEM>
3110 </VARLISTENTRY>
3111 <VARLISTENTRY>
3112 <TERM>
3113 SPI_result
3114 </TERM>
3115 <LISTITEM>
3116 <PARA>
3117 <SimpleList>
3118 <Member>
3119    <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if rel is NULL or tuple is NULL or natts &lt;= 0 or
3120    attnum is NULL or Values is NULL.
3121 </Member>
3122 <Member>
3123    <ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> if there is an invalid 
3124    attribute number in attnum (attnum &lt;= 0 or &gt; number of
3125    attributes in tuple)
3126 </Member>
3127 </SimpleList>
3128 </para>
3129 </LISTITEM>
3130 </VARLISTENTRY>
3131 </VARIABLELIST>
3132 </REFSECT2>
3133 </REFSYNOPSISDIV>
3134
3135 <REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-1">
3136 <REFSECT1INFO>
3137 <DATE>1997-12-24</DATE>
3138 </REFSECT1INFO>
3139 <TITLE>Description
3140 </TITLE>
3141 <PARA>
3142 <FUNCTION>SPI_modifytuple</FUNCTION> 
3143 creates a new tuple by substituting new values for selected attributes,
3144 copying the original tuple's attributes at other positions.  The input
3145 tuple is not modified.
3146 </PARA>
3147 </REFSECT1>
3148 <REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-2">
3149 <TITLE>Usage
3150 </TITLE>
3151 <Para>
3152 If successful, a pointer to the new tuple is returned. The new tuple is
3153 allocated in upper Executor context.
3154 </PARA>
3155 </REFSECT1>
3156 <!--
3157 <REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-3">
3158 <TITLE>Algorithm
3159 </TITLE>
3160 <PARA>
3161 </PARA>
3162 </REFSECT1>
3163 -->
3164 <!--
3165 <REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-4">
3166 <TITLE>Structures
3167 </TITLE>
3168 <PARA>None
3169 </PARA>
3170 </REFSECT1>
3171 -->
3172 </REFENTRY>
3173
3174 <!-- *********************************************** -->
3175 <!-- *********************************************** -->
3176 <!-- *********************************************** -->
3177
3178 <REFENTRY ID="SPI-SPIPALLOC">
3179 <REFMETA>
3180 <REFENTRYTITLE>SPI_palloc</REFENTRYTITLE>
3181 <REFMISCINFO>SPI - Memory Management</REFMISCINFO>
3182 </REFMETA>
3183 <REFNAMEDIV>
3184 <REFNAME>SPI_palloc
3185 </REFNAME>
3186 <REFPURPOSE>
3187 Allocates memory in upper Executor context
3188 </REFPURPOSE>
3189 <INDEXTERM ID="IX-SPI-SPIPALLOC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM>
3190 <INDEXTERM ID="IX-SPI-SPIPALLOC-2"><PRIMARY>SPI_palloc</PRIMARY></INDEXTERM>
3191 </REFNAMEDIV>
3192 <REFSYNOPSISDIV>
3193 <REFSYNOPSISDIVINFO>
3194 <DATE>1997-12-24</DATE>
3195 </REFSYNOPSISDIVINFO>
3196 <SYNOPSIS>
3197 SPI_palloc(<REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>)
3198 </SYNOPSIS>
3199
3200 <REFSECT2 ID="R2-SPI-SPIPALLOC-1">
3201 <REFSECT2INFO>
3202 <DATE>1997-12-24</DATE>
3203 </REFSECT2INFO>
3204 <TITLE>Inputs
3205 </TITLE>
3206 <VARIABLELIST>
3207 <VARLISTENTRY>
3208 <TERM>
3209 Size <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>
3210 </TERM>
3211 <LISTITEM>
3212 <PARA>
3213 Octet size of storage to allocate
3214 </PARA>
3215 </LISTITEM>
3216 </VARLISTENTRY>
3217 </VARIABLELIST>
3218 </REFSECT2>
3219
3220 <REFSECT2 ID="R2-SPI-SPIPALLOC-2">
3221 <REFSECT2INFO>
3222 <DATE>1997-12-24</DATE>
3223 </REFSECT2INFO>
3224 <TITLE>Outputs
3225 </TITLE>
3226 <VARIABLELIST>
3227 <VARLISTENTRY>
3228 <TERM>
3229 void *
3230 </TERM>
3231 <LISTITEM>
3232 <PARA>
3233 New storage space of specified size
3234 </PARA>
3235 </LISTITEM>
3236 </VARLISTENTRY>
3237 </VARIABLELIST>
3238 </REFSECT2>
3239 </REFSYNOPSISDIV>
3240
3241 <REFSECT1 ID="R1-SPI-SPIPALLOC-1">
3242 <REFSECT1INFO>
3243 <DATE>1997-12-24</DATE>
3244 </REFSECT1INFO>
3245 <TITLE>Description
3246 </TITLE>
3247 <PARA>
3248 <FUNCTION>SPI_palloc</FUNCTION> 
3249    allocates memory in upper Executor context.
3250 </PARA>
3251 </REFSECT1>
3252 <REFSECT1 ID="R1-SPI-SPIPALLOC-2">
3253 <TITLE>Usage
3254 </TITLE>
3255 <Para>
3256 TBD
3257 </PARA>
3258 </REFSECT1>
3259 <!--
3260 <REFSECT1 ID="R1-SPI-SPIPALLOC-3">
3261 <TITLE>Algorithm
3262 </TITLE>
3263 <PARA>
3264 TBD
3265 </PARA>
3266 </REFSECT1>
3267 -->
3268 <!--
3269 <REFSECT1 ID="R1-SPI-SPIPALLOC-4">
3270 <TITLE>Structures
3271 </TITLE>
3272 <PARA>None
3273 </PARA>
3274 </REFSECT1>
3275 -->
3276 </REFENTRY>
3277
3278 <!-- *********************************************** -->
3279 <!-- *********************************************** -->
3280 <!-- *********************************************** -->
3281
3282 <REFENTRY ID="SPI-SPIREPALLOC">
3283 <REFMETA>
3284 <REFENTRYTITLE>SPI_repalloc</REFENTRYTITLE>
3285 <REFMISCINFO>SPI - Memory Management</REFMISCINFO>
3286 </REFMETA>
3287 <REFNAMEDIV>
3288 <REFNAME>SPI_repalloc
3289 </REFNAME>
3290 <REFPURPOSE>
3291 Re-allocates memory in upper Executor context
3292 </REFPURPOSE>
3293 <INDEXTERM ID="IX-SPI-SPIREPALLOC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM>
3294 <INDEXTERM ID="IX-SPI-SPIREPALLOC-2"><PRIMARY>SPI_repalloc</PRIMARY></INDEXTERM>
3295 </REFNAMEDIV>
3296 <REFSYNOPSISDIV>
3297 <REFSYNOPSISDIVINFO>
3298 <DATE>1997-12-24</DATE>
3299 </REFSYNOPSISDIVINFO>
3300 <SYNOPSIS>
3301 SPI_repalloc(<REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>)
3302 </SYNOPSIS>
3303
3304 <REFSECT2 ID="R2-SPI-SPIREPALLOC-1">
3305 <REFSECT2INFO>
3306 <DATE>1997-12-24</DATE>
3307 </REFSECT2INFO>
3308 <TITLE>Inputs
3309 </TITLE>
3310 <VARIABLELIST>
3311 <VARLISTENTRY>
3312 <TERM>
3313 void * <REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>
3314 </TERM>
3315 <LISTITEM>
3316 <PARA>
3317 Pointer to existing storage
3318 </PARA>
3319 </LISTITEM>
3320 </VARLISTENTRY>
3321 <VARLISTENTRY>
3322 <TERM>
3323 Size <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>
3324 </TERM>
3325 <LISTITEM>
3326 <PARA>
3327 Octet size of storage to allocate
3328 </PARA>
3329 </LISTITEM>
3330 </VARLISTENTRY>
3331 </VARIABLELIST>
3332 </REFSECT2>
3333
3334 <REFSECT2 ID="R2-SPI-SPIREPALLOC-2">
3335 <REFSECT2INFO>
3336 <DATE>1997-12-24</DATE>
3337 </REFSECT2INFO>
3338 <TITLE>Outputs
3339 </TITLE>
3340 <VARIABLELIST>
3341 <VARLISTENTRY>
3342 <TERM>
3343 void *
3344 </TERM>
3345 <LISTITEM>
3346 <PARA>
3347 New storage space of specified size with contents copied from existing area
3348 </PARA>
3349 </LISTITEM>
3350 </VARLISTENTRY>
3351 </VARIABLELIST>
3352 </REFSECT2>
3353 </REFSYNOPSISDIV>
3354
3355 <REFSECT1 ID="R1-SPI-SPIREPALLOC-1">
3356 <REFSECT1INFO>
3357 <DATE>1997-12-24</DATE>
3358 </REFSECT1INFO>
3359 <TITLE>Description
3360 </TITLE>
3361 <PARA>
3362 <FUNCTION>SPI_repalloc</FUNCTION> 
3363    re-allocates memory in upper Executor context.
3364 </PARA>
3365 </REFSECT1>
3366 <REFSECT1 ID="R1-SPI-SPIREPALLOC-2">
3367 <TITLE>Usage
3368 </TITLE>
3369 <Para>
3370 This function is no longer different from plain <FUNCTION>repalloc</FUNCTION>.
3371 It's kept just for backward compatibility of existing code.
3372 </PARA>
3373 </REFSECT1>
3374 <!--
3375 <REFSECT1 ID="R1-SPI-SPIREPALLOC-3">
3376 <TITLE>Algorithm
3377 </TITLE>
3378 <PARA>
3379 TBD
3380 </PARA>
3381 </REFSECT1>
3382 -->
3383 <!--
3384 <REFSECT1 ID="R1-SPI-SPIREPALLOC-4">
3385 <TITLE>Structures
3386 </TITLE>
3387 <PARA>None
3388 </PARA>
3389 </REFSECT1>
3390 -->
3391 </REFENTRY>
3392
3393 <!-- *********************************************** -->
3394 <!-- *********************************************** -->
3395 <!-- *********************************************** -->
3396
3397 <REFENTRY ID="SPI-SPIPFREE">
3398 <REFMETA>
3399 <REFENTRYTITLE>SPI_pfree</REFENTRYTITLE>
3400 <REFMISCINFO>SPI - Memory Management</REFMISCINFO>
3401 </REFMETA>
3402 <REFNAMEDIV>
3403 <REFNAME>SPI_pfree
3404 </REFNAME>
3405 <REFPURPOSE>
3406 Frees memory in upper Executor context
3407 </REFPURPOSE>
3408 <INDEXTERM ID="IX-SPI-SPIPFREE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM>
3409 <INDEXTERM ID="IX-SPI-SPIPFREE-2"><PRIMARY>SPI_pfree</PRIMARY></INDEXTERM>
3410 </REFNAMEDIV>
3411 <REFSYNOPSISDIV>
3412 <REFSYNOPSISDIVINFO>
3413 <DATE>1997-12-24</DATE>
3414 </REFSYNOPSISDIVINFO>
3415 <SYNOPSIS>
3416 SPI_pfree(<REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>)
3417 </SYNOPSIS>
3418
3419 <REFSECT2 ID="R2-SPI-SPIPFREE-1">
3420 <REFSECT2INFO>
3421 <DATE>1997-12-24</DATE>
3422 </REFSECT2INFO>
3423 <TITLE>Inputs
3424 </TITLE>
3425 <VARIABLELIST>
3426 <VARLISTENTRY>
3427 <TERM>
3428 void * <REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>
3429 </TERM>
3430 <LISTITEM>
3431 <PARA>
3432 Pointer to existing storage
3433 </PARA>
3434 </LISTITEM>
3435 </VARLISTENTRY>
3436 </VARIABLELIST>
3437 </REFSECT2>
3438
3439 <REFSECT2 ID="R2-SPI-SPIPFREE-2">
3440 <REFSECT2INFO>
3441 <DATE>1997-12-24</DATE>
3442 </REFSECT2INFO>
3443 <TITLE>Outputs
3444 </TITLE>
3445 <VARIABLELIST>
3446 <VARLISTENTRY>
3447 <TERM>
3448 None
3449 </TERM>
3450 <LISTITEM>
3451 <PARA>
3452 </PARA>
3453 </LISTITEM>
3454 </VARLISTENTRY>
3455 </VARIABLELIST>
3456 </REFSECT2>
3457 </REFSYNOPSISDIV>
3458
3459 <REFSECT1 ID="R1-SPI-SPIPFREE-1">
3460 <REFSECT1INFO>
3461 <DATE>1997-12-24</DATE>
3462 </REFSECT1INFO>
3463 <TITLE>Description
3464 </TITLE>
3465 <PARA>
3466 <FUNCTION>SPI_pfree</FUNCTION> 
3467    frees memory in upper Executor context.
3468 </PARA>
3469 </REFSECT1>
3470 <REFSECT1 ID="R1-SPI-SPIPFREE-2">
3471 <TITLE>Usage
3472 </TITLE>
3473 <Para>
3474 This function is no longer different from plain <FUNCTION>pfree</FUNCTION>.
3475 It's kept just for backward compatibility of existing code.
3476 </PARA>
3477 </REFSECT1>
3478 </REFENTRY>
3479
3480 <!-- *********************************************** -->
3481 <!-- *********************************************** -->
3482 <!-- *********************************************** -->
3483
3484 <REFENTRY ID="SPI-SPIFREETUPLE">
3485 <REFMETA>
3486 <REFENTRYTITLE>SPI_freetuple</REFENTRYTITLE>
3487 <REFMISCINFO>SPI - Memory Management</REFMISCINFO>
3488 </REFMETA>
3489 <REFNAMEDIV>
3490 <REFNAME>SPI_freetuple
3491 </REFNAME>
3492 <REFPURPOSE>
3493 Frees a tuple allocated in upper Executor context
3494 </REFPURPOSE>
3495 <INDEXTERM ID="IX-SPI-SPIFREETUPLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM>
3496 <INDEXTERM ID="IX-SPI-SPIFREETUPLE-2"><PRIMARY>SPI_freetuple</PRIMARY></INDEXTERM>
3497 </REFNAMEDIV>
3498 <REFSYNOPSISDIV>
3499 <REFSYNOPSISDIVINFO>
3500 <DATE>1997-12-24</DATE>
3501 </REFSYNOPSISDIVINFO>
3502 <SYNOPSIS>
3503 SPI_freetuple(<REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>)
3504 </SYNOPSIS>
3505
3506 <REFSECT2 ID="R2-SPI-SPIFREETUPLE-1">
3507 <REFSECT2INFO>
3508 <DATE>1997-12-24</DATE>
3509 </REFSECT2INFO>
3510 <TITLE>Inputs
3511 </TITLE>
3512 <VARIABLELIST>
3513 <VARLISTENTRY>
3514 <TERM>
3515 HeapTuple <REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>
3516 </TERM>
3517 <LISTITEM>
3518 <PARA>
3519 Pointer to allocated tuple
3520 </PARA>
3521 </LISTITEM>
3522 </VARLISTENTRY>
3523 </VARIABLELIST>
3524 </REFSECT2>
3525
3526 <REFSECT2 ID="R2-SPI-SPIFREETUPLE-2">
3527 <REFSECT2INFO>
3528 <DATE>1997-12-24</DATE>
3529 </REFSECT2INFO>
3530 <TITLE>Outputs
3531 </TITLE>
3532 <VARIABLELIST>
3533 <VARLISTENTRY>
3534 <TERM>
3535 None
3536 </TERM>
3537 <LISTITEM>
3538 <PARA>
3539 </PARA>
3540 </LISTITEM>
3541 </VARLISTENTRY>
3542 </VARIABLELIST>
3543 </REFSECT2>
3544 </REFSYNOPSISDIV>
3545
3546 <REFSECT1 ID="R1-SPI-SPIFREETUPLE-1">
3547 <REFSECT1INFO>
3548 <DATE>1997-12-24</DATE>
3549 </REFSECT1INFO>
3550 <TITLE>Description
3551 </TITLE>
3552 <PARA>
3553 <FUNCTION>SPI_freetuple</FUNCTION> 
3554    frees a tuple previously allocated in upper Executor context.
3555 </PARA>
3556 </REFSECT1>
3557 <REFSECT1 ID="R1-SPI-SPIFREETUPLE-2">
3558 <TITLE>Usage
3559 </TITLE>
3560 <Para>
3561 This function is no longer different from plain <FUNCTION>heap_freetuple</FUNCTION>.
3562 It's kept just for backward compatibility of existing code.
3563 </PARA>
3564 </REFSECT1>
3565 </REFENTRY>
3566
3567 <!-- *********************************************** -->
3568 <!-- *********************************************** -->
3569 <!-- *********************************************** -->
3570
3571 <REFENTRY ID="SPI-SPIFREETUPTABLE">
3572 <REFMETA>
3573 <REFENTRYTITLE>SPI_freetuptable</REFENTRYTITLE>
3574 <REFMISCINFO>SPI - Memory Management</REFMISCINFO>
3575 </REFMETA>
3576 <REFNAMEDIV>
3577 <REFNAME>SPI_freetuptable
3578 </REFNAME>
3579 <REFPURPOSE>
3580 Frees a tuple set created by <function>SPI_exec</> or similar function
3581 </REFPURPOSE>
3582 <INDEXTERM ID="IX-SPI-SPIFREETUPTABLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM>
3583 <INDEXTERM ID="IX-SPI-SPIFREETUPTABLE-2"><PRIMARY>SPI_freetuptable</PRIMARY></INDEXTERM>
3584 </REFNAMEDIV>
3585 <REFSYNOPSISDIV>
3586 <REFSYNOPSISDIVINFO>
3587 <DATE>2001-11-14</DATE>
3588 </REFSYNOPSISDIVINFO>
3589 <SYNOPSIS>
3590 SPI_freetuptable(<REPLACEABLE CLASS="PARAMETER">tuptable</REPLACEABLE>)
3591 </SYNOPSIS>
3592
3593 <REFSECT2 ID="R2-SPI-SPIFREETUPTABLE-1">
3594 <REFSECT2INFO>
3595 <DATE>2001-11-14</DATE>
3596 </REFSECT2INFO>
3597 <TITLE>Inputs
3598 </TITLE>
3599 <VARIABLELIST>
3600 <VARLISTENTRY>
3601 <TERM>
3602 SPITupleTable * <REPLACEABLE CLASS="PARAMETER">tuptable</REPLACEABLE>
3603 </TERM>
3604 <LISTITEM>
3605 <PARA>
3606 Pointer to tuple table
3607 </PARA>
3608 </LISTITEM>
3609 </VARLISTENTRY>
3610 </VARIABLELIST>
3611 </REFSECT2>
3612
3613 <REFSECT2 ID="R2-SPI-SPIFREETUPTABLE-2">
3614 <REFSECT2INFO>
3615 <DATE>2001-11-14</DATE>
3616 </REFSECT2INFO>
3617 <TITLE>Outputs
3618 </TITLE>
3619 <VARIABLELIST>
3620 <VARLISTENTRY>
3621 <TERM>
3622 None
3623 </TERM>
3624 <LISTITEM>
3625 <PARA>
3626 </PARA>
3627 </LISTITEM>
3628 </VARLISTENTRY>
3629 </VARIABLELIST>
3630 </REFSECT2>
3631 </REFSYNOPSISDIV>
3632
3633 <REFSECT1 ID="R1-SPI-SPIFREETUPTABLE-1">
3634 <REFSECT1INFO>
3635 <DATE>2001-11-14</DATE>
3636 </REFSECT1INFO>
3637 <TITLE>Description
3638 </TITLE>
3639 <PARA>
3640 <FUNCTION>SPI_freetuptable</FUNCTION> 
3641    frees a tuple set created by a prior SPI query function, such as
3642    <function>SPI_exec</>.
3643 </PARA>
3644 </REFSECT1>
3645 <REFSECT1 ID="R1-SPI-SPIFREETUPTABLE-2">
3646 <TITLE>Usage
3647 </TITLE>
3648 <Para>
3649 This function is useful if a SPI procedure needs to execute multiple
3650 queries and does not want to keep the results of earlier queries around
3651 until it ends.  Note that any unfreed tuple sets will be freed anyway
3652 at <function>SPI_finish</>.
3653 </PARA>
3654 </REFSECT1>
3655 </REFENTRY>
3656
3657 <!-- *********************************************** -->
3658 <!-- *********************************************** -->
3659 <!-- *********************************************** -->
3660
3661 <REFENTRY ID="SPI-SPIFREEPLAN">
3662 <REFMETA>
3663 <REFENTRYTITLE>SPI_freeplan</REFENTRYTITLE>
3664 <REFMISCINFO>SPI - Memory Management</REFMISCINFO>
3665 </REFMETA>
3666 <REFNAMEDIV>
3667 <REFNAME>SPI_freeplan
3668 </REFNAME>
3669 <REFPURPOSE>
3670    Releases a previously saved plan
3671 </REFPURPOSE>
3672 <INDEXTERM ID="IX-SPI-SPIFREEPLAN-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM>
3673 <INDEXTERM ID="IX-SPI-SPIFREEPLAN-2"><PRIMARY>SPI_freeplan</PRIMARY></INDEXTERM>
3674 </REFNAMEDIV>
3675 <REFSYNOPSISDIV>
3676 <REFSYNOPSISDIVINFO>
3677 <DATE>2001-11-14</DATE>
3678 </REFSYNOPSISDIVINFO>
3679 <SYNOPSIS>
3680 SPI_freeplan(<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>)
3681 </SYNOPSIS>
3682
3683 <REFSECT2 ID="R2-SPI-SPIFREEPLAN-1">
3684 <REFSECT2INFO>
3685 <DATE>2001-11-14</DATE>
3686 </REFSECT2INFO>
3687 <TITLE>Inputs
3688 </TITLE>
3689 <VARIABLELIST>
3690 <VARLISTENTRY>
3691 <TERM>
3692 void *<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>
3693 </TERM>
3694 <LISTITEM>
3695 <PARA>
3696 Passed plan
3697 </PARA>
3698 </LISTITEM>
3699 </VARLISTENTRY>
3700 </VARIABLELIST>
3701 </REFSECT2>
3702
3703 <REFSECT2 ID="R2-SPI-SPIFREEPLAN-2">
3704 <REFSECT2INFO>
3705 <DATE>2001-11-14</DATE>
3706 </REFSECT2INFO>
3707 <TITLE>Outputs
3708 </TITLE>
3709 <VARIABLELIST>
3710 <VARLISTENTRY>
3711 <TERM>int
3712 </TERM>
3713 <LISTITEM>
3714 <PARA>
3715 <SimpleList>
3716 <Member>
3717    <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if plan is NULL
3718 </Member>
3719 </SimpleList>
3720 </PARA>
3721 </LISTITEM>
3722 </VARLISTENTRY>
3723 </VARIABLELIST>
3724 </REFSECT2>
3725 </REFSYNOPSISDIV>
3726
3727 <REFSECT1 ID="R1-SPI-SPIFREEPLAN-1">
3728 <REFSECT1INFO>
3729 <DATE>2001-11-14</DATE>
3730 </REFSECT1INFO>
3731 <TITLE>Description
3732 </TITLE>
3733 <PARA>
3734 <FUNCTION>SPI_freeplan</FUNCTION> 
3735    releases a query plan previously returned by
3736    <Function>SPI_prepare</Function> or saved by
3737    <Function>SPI_saveplan</Function>.
3738 </para>
3739 </REFSECT1>
3740 </REFENTRY>
3741
3742 </Sect1>
3743
3744 <Sect1 id="spi-visibility">
3745 <Title>Visibility of Data Changes</Title>
3746
3747 <Para>
3748 <ProductName>Postgres</ProductName> data changes visibility rule: during a query execution, data
3749 changes made by the query itself (via SQL-function, SPI-function, triggers)
3750 are invisible to the query scan.  For example, in query
3751 <programlisting>
3752    INSERT INTO a SELECT * FROM a
3753 </programlisting>
3754    tuples inserted are invisible for SELECT's scan.  In effect, this
3755 duplicates the database table within itself (subject to unique index
3756 rules, of course) without recursing.
3757 </Para>
3758
3759 <Para>
3760    Changes made by query Q are visible to queries that are started after
3761 query Q, no matter whether they are started inside Q (during the execution
3762 of Q) or after Q is done.
3763 </Para>
3764 </Sect1>
3765
3766 <Sect1 id="spi-examples">
3767 <Title>Examples</Title>
3768
3769 <Para>
3770    This example of SPI usage demonstrates the visibility rule.
3771    There are more complex examples in src/test/regress/regress.c and
3772 in contrib/spi.
3773 </Para>
3774
3775 <Para>
3776    This is a very simple example of SPI usage. The procedure execq accepts
3777 an SQL-query in its first argument and tcount in its second, executes the
3778 query using SPI_exec and returns the number of tuples for which the query
3779 executed:
3780
3781 <ProgramListing>
3782 #include "executor/spi.h"   /* this is what you need to work with SPI */
3783
3784 int execq(text *sql, int cnt);
3785
3786 int
3787 execq(text *sql, int cnt)
3788 {
3789     char *query;
3790     int ret;
3791     int proc;
3792
3793     /* Convert given TEXT object to a C string */
3794     query = DatumGetCString(DirectFunctionCall1(textout,
3795                                                 PointerGetDatum(sql)));
3796
3797     SPI_connect();
3798     
3799     ret = SPI_exec(query, cnt);
3800     
3801     proc = SPI_processed;
3802     /*
3803      * If this is SELECT and some tuple(s) fetched -
3804      * returns tuples to the caller via elog (NOTICE).
3805      */
3806     if ( ret == SPI_OK_SELECT && SPI_processed > 0 )
3807     {
3808         TupleDesc tupdesc = SPI_tuptable->tupdesc;
3809         SPITupleTable *tuptable = SPI_tuptable;
3810         char buf[8192];
3811         int i,j;
3812         
3813         for (j = 0; j < proc; j++)
3814         {
3815             HeapTuple tuple = tuptable->vals[j];
3816             
3817             for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++)
3818                 sprintf(buf + strlen (buf), " %s%s",
3819                         SPI_getvalue(tuple, tupdesc, i),
3820                         (i == tupdesc->natts) ? " " : " |");
3821             elog (NOTICE, "EXECQ: %s", buf);
3822         }
3823     }
3824
3825     SPI_finish();
3826
3827     pfree(query);
3828
3829     return (proc);
3830 }
3831 </ProgramListing>
3832 </Para>
3833
3834 <Para>
3835    Now, compile and create the function:
3836
3837 <ProgramListing>
3838 CREATE FUNCTION execq (text, integer) RETURNS integer
3839     AS '...path_to_so'
3840     LANGUAGE C;
3841 </ProgramListing>
3842
3843 <ProgramListing>
3844 vac=> SELECT execq('CREATE TABLE a (x INTEGER)', 0);
3845 execq
3846 -----
3847     0
3848 (1 row)
3849
3850 vac=> INSERT INTO a VALUES (execq('INSERT INTO a VALUES (0)',0));
3851 INSERT 167631 1
3852 vac=> SELECT execq('SELECT * FROM a',0);
3853 NOTICE:EXECQ:  0 <<< inserted by execq
3854
3855 NOTICE:EXECQ:  1 <<< value returned by execq and inserted by upper INSERT
3856
3857 execq
3858 -----
3859     2
3860 (1 row)
3861
3862 vac=> SELECT execq('INSERT INTO a SELECT x + 2 FROM a',1);
3863 execq
3864 -----
3865     1
3866 (1 row)
3867
3868 vac=> SELECT execq('SELECT * FROM a', 10);
3869 NOTICE:EXECQ:  0 
3870
3871 NOTICE:EXECQ:  1 
3872
3873 NOTICE:EXECQ:  2 <<< 0 + 2, only one tuple inserted - as specified
3874
3875 execq
3876 -----
3877     3            <<< 10 is max value only, 3 is real # of tuples
3878 (1 row)
3879
3880 vac=> DELETE FROM a;
3881 DELETE 3
3882 vac=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1);
3883 INSERT 167712 1
3884 vac=> SELECT * FROM a;
3885 x
3886 -
3887 1                <<< no tuples in a (0) + 1
3888 (1 row)
3889
3890 vac=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1);
3891 NOTICE:EXECQ:  0 
3892 INSERT 167713 1
3893 vac=> SELECT * FROM a;
3894 x
3895 -
3896 1
3897 2                <<< there was single tuple in a + 1
3898 (2 rows)
3899
3900 --   This demonstrates data changes visibility rule:
3901
3902 vac=> INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a;
3903 NOTICE:EXECQ:  1 
3904 NOTICE:EXECQ:  2 
3905 NOTICE:EXECQ:  1 
3906 NOTICE:EXECQ:  2 
3907 NOTICE:EXECQ:  2 
3908 INSERT 0 2
3909 vac=> SELECT * FROM a;
3910 x
3911 -
3912 1
3913 2
3914 2                <<< 2 tuples * 1 (x in first tuple)
3915 6                <<< 3 tuples (2 + 1 just inserted) * 2 (x in second tuple)
3916 (4 rows)             ^^^^^^^^ 
3917                      tuples visible to execq() in different invocations
3918 </ProgramListing>
3919 </Para>
3920 </Sect1>
3921 </Chapter>