Fix SPI documentation for new handling of ExecutorRun's count parameter.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 24 Jan 2013 23:34:08 +0000 (18:34 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 24 Jan 2013 23:34:08 +0000 (18:34 -0500)
Since 9.0, the count parameter has only limited the number of tuples
actually returned by the executor.  It doesn't affect the behavior of
INSERT/UPDATE/DELETE unless RETURNING is specified, because without
RETURNING, the ModifyTable plan node doesn't return control to execMain.c
for each tuple.  And we only check the limit at the top level.

While this behavioral change was unintentional at the time, discussion of
bug #6572 led us to the conclusion that we prefer the new behavior anyway,
and so we should just adjust the docs to match rather than change the code.
Accordingly, do that.  Back-patch as far as 9.0 so that the docs match the
code in each branch.

doc/src/sgml/spi.sgml
src/backend/executor/execMain.c

index 1b41cb40b3c5f309e6a12ac2e971142d240dab4b..7a61802eb22325f49d322016826f3248ac8dc1bb 100644 (file)
@@ -316,13 +316,24 @@ int SPI_execute(const char * <parameter>command</parameter>, bool <parameter>rea
   <para>
    If <parameter>count</parameter> is zero then the command is executed
    for all rows that it applies to.  If <parameter>count</parameter>
-   is greater than 0, then the number of rows for which the command
-   will be executed is restricted (much like a
-   <literal>LIMIT</literal> clause). For example:
+   is greater than zero, then no more than <parameter>count</parameter> rows
+   will be retrieved; execution stops when the count is reached, much like
+   adding a <literal>LIMIT</literal> clause to the query. For example,
+<programlisting>
+SPI_execute("SELECT * FROM foo", true, 5);
+</programlisting>
+   will retrieve at most 5 rows from the table.  Note that such a limit
+   is only effective when the command actually returns rows.  For example,
 <programlisting>
 SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);
 </programlisting>
-   will allow at most 5 rows to be inserted into the table.
+   inserts all rows from <structname>bar</>, ignoring the
+   <parameter>count</parameter> parameter.  However, with
+<programlisting>
+SPI_execute("INSERT INTO foo SELECT * FROM bar RETURNING *", false, 5);
+</programlisting>
+   at most 5 rows would be inserted, since execution would stop after the
+   fifth <literal>RETURNING</> result row is retrieved.
   </para>
 
   <para>
@@ -331,7 +342,8 @@ SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);
    whole string will be parsed and planned before execution begins.
    <function>SPI_execute</function> returns the
    result for the command executed last.  The <parameter>count</parameter>
-   limit applies to each command separately, but it is not applied to
+   limit applies to each command separately (even though only the last
+   result will actually be returned).  The limit is not applied to any
    hidden commands generated by rules.
   </para>
 
@@ -432,7 +444,8 @@ typedef struct
     <term><literal>long <parameter>count</parameter></literal></term>
     <listitem>
      <para>
-      maximum number of rows to process or return
+      maximum number of rows to return,
+      or <literal>0</> for no limit
      </para>
     </listitem>
    </varlistentry>
@@ -608,15 +621,12 @@ typedef struct
   <title>Notes</title>
 
   <para>
-   The functions <function>SPI_execute</function>,
-   <function>SPI_exec</function>,
-   <function>SPI_execute_plan</function>, and
-   <function>SPI_execp</function> change both
+   All SPI query-execution functions set both
    <varname>SPI_processed</varname> and
    <varname>SPI_tuptable</varname> (just the pointer, not the contents
    of the structure).  Save these two global variables into local
    procedure variables if you need to access the result table of
-   <function>SPI_execute</function> or a related function
+   <function>SPI_execute</function> or another query-execution function
    across later calls.
   </para>
  </refsect1>
@@ -671,7 +681,8 @@ int SPI_exec(const char * <parameter>command</parameter>, long <parameter>count<
     <term><literal>long <parameter>count</parameter></literal></term>
     <listitem>
      <para>
-      maximum number of rows to process or return
+      maximum number of rows to return,
+      or <literal>0</> for no limit
      </para>
     </listitem>
    </varlistentry>
@@ -808,7 +819,8 @@ int SPI_execute_with_args(const char *<parameter>command</parameter>,
     <term><literal>long <parameter>count</parameter></literal></term>
     <listitem>
      <para>
-      maximum number of rows to process or return
+      maximum number of rows to return,
+      or <literal>0</> for no limit
      </para>
     </listitem>
    </varlistentry>
@@ -1424,7 +1436,8 @@ int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>
     <term><literal>long <parameter>count</parameter></literal></term>
     <listitem>
      <para>
-      maximum number of rows to process or return
+      maximum number of rows to return,
+      or <literal>0</> for no limit
      </para>
     </listitem>
    </varlistentry>
@@ -1541,7 +1554,8 @@ int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
     <term><literal>long <parameter>count</parameter></literal></term>
     <listitem>
      <para>
-      maximum number of rows to process or return
+      maximum number of rows to return,
+      or <literal>0</> for no limit
      </para>
     </listitem>
    </varlistentry>
@@ -1641,7 +1655,8 @@ int SPI_execp(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values<
     <term><literal>long <parameter>count</parameter></literal></term>
     <listitem>
      <para>
-      maximum number of rows to process or return
+      maximum number of rows to return,
+      or <literal>0</> for no limit
      </para>
     </listitem>
    </varlistentry>
index 8a43db7d6ab139911cdff78bbe0e9ab520d03886..5139c3b8e50eafdc23055c26ef4831421535649d 100644 (file)
@@ -239,7 +239,9 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
  *             we retrieve up to 'count' tuples in the specified direction.
  *
  *             Note: count = 0 is interpreted as no portal limit, i.e., run to
- *             completion.
+ *             completion.  Also note that the count limit is only applied to
+ *             retrieved tuples, not for instance to those inserted/updated/deleted
+ *             by a ModifyTable plan node.
  *
  *             There is no return value, but output tuples (if any) are sent to
  *             the destination receiver specified in the QueryDesc; and the number
@@ -1395,7 +1397,7 @@ ExecEndPlan(PlanState *planstate, EState *estate)
 /* ----------------------------------------------------------------
  *             ExecutePlan
  *
- *             Processes the query plan until we have processed 'numberTuples' tuples,
+ *             Processes the query plan until we have retrieved 'numberTuples' tuples,
  *             moving in the specified direction.
  *
  *             Runs to completion if numberTuples is 0