Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2011-09-16 04:42:53 +0000
committerTom Lane2011-09-16 04:43:52 +0000
commite6faf910d75027bdce7cd0f2033db4e912592bcc (patch)
treeb5fdc2340cc1cdf27dd473e23a09cb2953b5053c /doc/src/sgml
parent09e98a3e170ecdeb25a0e1afe81bdbeeeaf21f48 (diff)
Redesign the plancache mechanism for more flexibility and efficiency.
Rewrite plancache.c so that a "cached plan" (which is rather a misnomer at this point) can support generation of custom, parameter-value-dependent plans, and can make an intelligent choice between using custom plans and the traditional generic-plan approach. The specific choice algorithm implemented here can probably be improved in future, but this commit is all about getting the mechanism in place, not the policy. In addition, restructure the API to greatly reduce the amount of extraneous data copying needed. The main compromise needed to make that possible was to split the initial creation of a CachedPlanSource into two steps. It's worth noting in particular that SPI_saveplan is now deprecated in favor of SPI_keepplan, which accomplishes the same end result with zero data copying, and no need to then spend even more cycles throwing away the original SPIPlan. The risk of long-term memory leaks while manipulating SPIPlans has also been greatly reduced. Most of this improvement is based on use of the recently-added MemoryContextSetParent primitive.
Diffstat (limited to 'doc/src/sgml')
-rw-r--r--doc/src/sgml/plpgsql.sgml119
-rw-r--r--doc/src/sgml/protocol.sgml50
-rw-r--r--doc/src/sgml/ref/prepare.sgml44
-rw-r--r--doc/src/sgml/spi.sgml237
4 files changed, 256 insertions, 194 deletions
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index d9b4e615e09..84fb012d1f3 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -839,12 +839,10 @@ PREPARE <replaceable>statement_name</>(integer, integer) AS SELECT $1 &lt; $2;
and then this prepared statement is <command>EXECUTE</>d for each
execution of the <command>IF</> statement, with the current values
of the <application>PL/pgSQL</application> variables supplied as
- parameter values.
- The query plan prepared in this way is saved for the life of the database
- connection, as described in
- <xref linkend="plpgsql-plan-caching">. Normally these details are
+ parameter values. Normally these details are
not important to a <application>PL/pgSQL</application> user, but
they are useful to know when trying to diagnose a problem.
+ More information appears in <xref linkend="plpgsql-plan-caching">.
</para>
</sect1>
@@ -919,10 +917,9 @@ my_record.user_id := 20;
<para>
When executing a SQL command in this way,
- <application>PL/pgSQL</application> plans the command just once
- and re-uses the plan on subsequent executions, for the life of
- the database connection. The implications of this are discussed
- in detail in <xref linkend="plpgsql-plan-caching">.
+ <application>PL/pgSQL</application> may cache and re-use the execution
+ plan for the command, as discussed in
+ <xref linkend="plpgsql-plan-caching">.
</para>
<para>
@@ -1137,8 +1134,8 @@ EXECUTE <replaceable class="command">command-string</replaceable> <optional> INT
<para>
Also, there is no plan caching for commands executed via
- <command>EXECUTE</command>. Instead, the
- command is prepared each time the statement is run. Thus the command
+ <command>EXECUTE</command>. Instead, the command is always planned
+ each time the statement is run. Thus the command
string can be dynamically created within the function to perform
actions on different tables and columns.
</para>
@@ -1206,11 +1203,11 @@ EXECUTE 'SELECT count(*) FROM '
The important difference is that <command>EXECUTE</> will re-plan
the command on each execution, generating a plan that is specific
to the current parameter values; whereas
- <application>PL/pgSQL</application> normally creates a generic plan
- and caches it for re-use. In situations where the best plan depends
- strongly on the parameter values, <command>EXECUTE</> can be
- significantly faster; while when the plan is not sensitive to parameter
- values, re-planning will be a waste.
+ <application>PL/pgSQL</application> may otherwise create a generic plan
+ and cache it for re-use. In situations where the best plan depends
+ strongly on the parameter values, it can be helpful to use
+ <command>EXECUTE</> to positively ensure that a generic plan is not
+ selected.
</para>
<para>
@@ -4103,17 +4100,14 @@ $$ LANGUAGE plpgsql;
</indexterm>
As each expression and <acronym>SQL</acronym> command is first
executed in the function, the <application>PL/pgSQL</> interpreter
- creates a prepared execution plan (using the
- <acronym>SPI</acronym> manager's <function>SPI_prepare</function>
- and <function>SPI_saveplan</function> functions).
+ parses and analyzes the command to create a prepared statement,
+ using the <acronym>SPI</acronym> manager's
+ <function>SPI_prepare</function> function.
Subsequent visits to that expression or command
- reuse the prepared plan. Thus, a function with conditional code
- that contains many statements for which execution plans might be
- required will only prepare and save those plans that are really
- used during the lifetime of the database connection. This can
- substantially reduce the total amount of time required to parse
- and generate execution plans for the statements in a
- <application>PL/pgSQL</> function. A disadvantage is that errors
+ reuse the prepared statement. Thus, a function with conditional code
+ paths that are seldom visited will never incur the overhead of
+ analyzing those commands that are never executed within the current
+ session. A disadvantage is that errors
in a specific expression or command cannot be detected until that
part of the function is reached in execution. (Trivial syntax
errors will be detected during the initial parsing pass, but
@@ -4121,46 +4115,31 @@ $$ LANGUAGE plpgsql;
</para>
<para>
- A saved plan will be re-planned automatically if there is any schema
- change to any table used in the query, or if any user-defined function
- used in the query is redefined. This makes the re-use of prepared plans
- transparent in most cases, but there are corner cases where a stale plan
- might be re-used. An example is that dropping and re-creating a
- user-defined operator won't affect already-cached plans; they'll continue
- to call the original operator's underlying function, if that has not been
- changed. When necessary, the cache can be flushed by starting a fresh
- database session.
+ <application>PL/pgSQL</> (or more precisely, the SPI manager) can
+ furthermore attempt to cache the execution plan associated with any
+ particular prepared statement. If a cached plan is not used, then
+ a fresh execution plan is generated on each visit to the statement,
+ and the current parameter values (that is, <application>PL/pgSQL</>
+ variable values) can be used to optimize the selected plan. If the
+ statement has no parameters, or is executed many times, the SPI manager
+ will consider creating a <firstterm>generic</> plan that is not dependent
+ on specific parameter values, and caching that for re-use. Typically
+ this will happen only if the execution plan is not very sensitive to
+ the values of the <application>PL/pgSQL</> variables referenced in it.
+ If it is, generating a plan each time is a net win.
</para>
<para>
- Because <application>PL/pgSQL</application> saves execution plans
- in this way, SQL commands that appear directly in a
+ Because <application>PL/pgSQL</application> saves prepared statements
+ and sometimes execution plans in this way,
+ SQL commands that appear directly in a
<application>PL/pgSQL</application> function must refer to the
same tables and columns on every execution; that is, you cannot use
a parameter as the name of a table or column in an SQL command. To get
around this restriction, you can construct dynamic commands using
the <application>PL/pgSQL</application> <command>EXECUTE</command>
- statement &mdash; at the price of constructing a new execution plan on
- every execution.
- </para>
-
- <para>
- Another important point is that the prepared plans are parameterized
- to allow the values of <application>PL/pgSQL</application> variables
- to change from one use to the next, as discussed in detail above.
- Sometimes this means that a plan is less efficient than it would be
- if generated for a specific variable value. As an example, consider
-<programlisting>
-SELECT * INTO myrec FROM dictionary WHERE word LIKE search_term;
-</programlisting>
- where <literal>search_term</> is a <application>PL/pgSQL</application>
- variable. The cached plan for this query will never use an index on
- <structfield>word</>, since the planner cannot assume that the
- <literal>LIKE</> pattern will be left-anchored at run time. To use
- an index the query must be planned with a specific constant
- <literal>LIKE</> pattern provided. This is another situation where
- <command>EXECUTE</command> can be used to force a new plan to be
- generated for each execution.
+ statement &mdash; at the price of performing new parse analysis and
+ constructing a new execution plan on every execution.
</para>
<para>
@@ -4168,14 +4147,14 @@ SELECT * INTO myrec FROM dictionary WHERE word LIKE search_term;
connection. When fields of a record variable are used in
expressions or statements, the data types of the fields must not
change from one call of the function to the next, since each
- expression will be planned using the data type that is present
+ expression will be analyzed using the data type that is present
when the expression is first reached. <command>EXECUTE</command> can be
used to get around this problem when necessary.
</para>
<para>
If the same function is used as a trigger for more than one table,
- <application>PL/pgSQL</application> prepares and caches plans
+ <application>PL/pgSQL</application> prepares and caches statements
independently for each such table &mdash; that is, there is a cache
for each trigger function and table combination, not just for each
function. This alleviates some of the problems with varying
@@ -4186,14 +4165,14 @@ SELECT * INTO myrec FROM dictionary WHERE word LIKE search_term;
<para>
Likewise, functions having polymorphic argument types have a separate
- plan cache for each combination of actual argument types they have been
- invoked for, so that data type differences do not cause unexpected
+ statement cache for each combination of actual argument types they have
+ been invoked for, so that data type differences do not cause unexpected
failures.
</para>
<para>
- Plan caching can sometimes have surprising effects on the interpretation
- of time-sensitive values. For example there
+ Statement caching can sometimes have surprising effects on the
+ interpretation of time-sensitive values. For example there
is a difference between what these two functions do:
<programlisting>
@@ -4221,15 +4200,17 @@ $$ LANGUAGE plpgsql;
<para>
In the case of <function>logfunc1</function>, the
<productname>PostgreSQL</productname> main parser knows when
- preparing the plan for the <command>INSERT</command> that the
+ analyzing the <command>INSERT</command> that the
string <literal>'now'</literal> should be interpreted as
<type>timestamp</type>, because the target column of
<classname>logtable</classname> is of that type. Thus,
- <literal>'now'</literal> will be converted to a constant when the
- <command>INSERT</command> is planned, and then used in all
+ <literal>'now'</literal> will be converted to a <type>timestamp</type>
+ constant when the
+ <command>INSERT</command> is analyzed, and then used in all
invocations of <function>logfunc1</function> during the lifetime
of the session. Needless to say, this isn't what the programmer
- wanted.
+ wanted. A better idea is to use the <literal>now()</> or
+ <literal>current_timestamp</> function.
</para>
<para>
@@ -4243,7 +4224,9 @@ $$ LANGUAGE plpgsql;
string to the <type>timestamp</type> type by calling the
<function>text_out</function> and <function>timestamp_in</function>
functions for the conversion. So, the computed time stamp is updated
- on each execution as the programmer expects.
+ on each execution as the programmer expects. Even though this
+ happens to work as expected, it's not terribly efficient, so
+ use of the <literal>now()</> function would still be a better idea.
</para>
</sect2>
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 508991bcc2b..19c9686fff4 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -125,9 +125,8 @@
into multiple steps. The state retained between steps is represented
by two types of objects: <firstterm>prepared statements</> and
<firstterm>portals</>. A prepared statement represents the result of
- parsing, semantic analysis, and (optionally) planning of a textual query
- string.
- A prepared statement is not necessarily ready to execute, because it might
+ parsing and semantic analysis of a textual query string.
+ A prepared statement is not in itself ready to execute, because it might
lack specific values for <firstterm>parameters</>. A portal represents
a ready-to-execute or already-partially-executed statement, with any
missing parameter values filled in. (For <command>SELECT</> statements,
@@ -692,7 +691,7 @@
the unnamed statement as destination is issued. (Note that a simple
Query message also destroys the unnamed statement.) Named prepared
statements must be explicitly closed before they can be redefined by
- a Parse message, but this is not required for the unnamed statement.
+ another Parse message, but this is not required for the unnamed statement.
Named prepared statements can also be created and accessed at the SQL
command level, using <command>PREPARE</> and <command>EXECUTE</>.
</para>
@@ -722,44 +721,23 @@
</note>
<para>
- Query planning for named prepared-statement objects occurs when the Parse
- message is processed. If a query will be repeatedly executed with
- different parameters, it might be beneficial to send a single Parse message
- containing a parameterized query, followed by multiple Bind
- and Execute messages. This will avoid replanning the query on each
- execution.
+ Query planning typically occurs when the Bind message is processed.
+ If the prepared statement has no parameters, or is executed repeatedly,
+ the server might save the created plan and re-use it during subsequent
+ Bind messages for the same prepared statement. However, it will do so
+ only if it finds that a generic plan can be created that is not much
+ less efficient than a plan that depends on the specific parameter values
+ supplied. This happens transparently so far as the protocol is concerned.
</para>
<para>
- The unnamed prepared statement is likewise planned during Parse processing
- if the Parse message defines no parameters. But if there are parameters,
- query planning occurs every time Bind parameters are supplied. This allows the
- planner to make use of the actual values of the parameters provided by
- each Bind message, rather than use generic estimates.
- </para>
-
- <note>
- <para>
- Query plans generated from a parameterized query might be less
- efficient than query plans generated from an equivalent query with actual
- parameter values substituted. The query planner cannot make decisions
- based on actual parameter values (for example, index selectivity) when
- planning a parameterized query assigned to a named prepared-statement
- object. This possible penalty is avoided when using the unnamed
- statement, since it is not planned until actual parameter values are
- available. The cost is that planning must occur afresh for each Bind,
- even if the query stays the same.
- </para>
- </note>
-
- <para>
If successfully created, a named portal object lasts till the end of the
current transaction, unless explicitly destroyed. An unnamed portal is
destroyed at the end of the transaction, or as soon as the next Bind
statement specifying the unnamed portal as destination is issued. (Note
that a simple Query message also destroys the unnamed portal.) Named
- portals must be explicitly closed before they can be redefined by a Bind
- message, but this is not required for the unnamed portal.
+ portals must be explicitly closed before they can be redefined by another
+ Bind message, but this is not required for the unnamed portal.
Named portals can also be created and accessed at the SQL
command level, using <command>DECLARE CURSOR</> and <command>FETCH</>.
</para>
@@ -1280,7 +1258,9 @@
The frontend should also be prepared to handle an ErrorMessage
response to SSLRequest from the server. This would only occur if
the server predates the addition of <acronym>SSL</acronym> support
- to <productname>PostgreSQL</>. In this case the connection must
+ to <productname>PostgreSQL</>. (Such servers are now very ancient,
+ and likely do not exist in the wild anymore.)
+ In this case the connection must
be closed, but the frontend might choose to open a fresh connection
and proceed without requesting <acronym>SSL</acronym>.
</para>
diff --git a/doc/src/sgml/ref/prepare.sgml b/doc/src/sgml/ref/prepare.sgml
index 6f18a97ca59..8466a63c580 100644
--- a/doc/src/sgml/ref/prepare.sgml
+++ b/doc/src/sgml/ref/prepare.sgml
@@ -37,11 +37,11 @@ PREPARE <replaceable class="PARAMETER">name</replaceable> [ ( <replaceable class
<command>PREPARE</command> creates a prepared statement. A prepared
statement is a server-side object that can be used to optimize
performance. When the <command>PREPARE</command> statement is
- executed, the specified statement is parsed, rewritten, and
- planned. When an <command>EXECUTE</command> command is subsequently
- issued, the prepared statement need only be executed. Thus, the
- parsing, rewriting, and planning stages are only performed once,
- instead of every time the statement is executed.
+ executed, the specified statement is parsed, analyzed, and rewritten.
+ When an <command>EXECUTE</command> command is subsequently
+ issued, the prepared statement is planned and executed. This division
+ of labor avoids repetitive parse analysis work, while allowing
+ the execution plan to depend on the specific parameter values supplied.
</para>
<para>
@@ -65,7 +65,7 @@ PREPARE <replaceable class="PARAMETER">name</replaceable> [ ( <replaceable class
forgotten, so it must be recreated before being used again. This
also means that a single prepared statement cannot be used by
multiple simultaneous database clients; however, each client can create
- their own prepared statement to use. The prepared statement can be
+ their own prepared statement to use. Prepared statements can be
manually cleaned up using the <xref linkend="sql-deallocate"> command.
</para>
@@ -127,20 +127,22 @@ PREPARE <replaceable class="PARAMETER">name</replaceable> [ ( <replaceable class
<title>Notes</title>
<para>
- In some situations, the query plan produced for a prepared
- statement will be inferior to the query plan that would have been
- chosen if the statement had been submitted and executed
- normally. This is because when the statement is planned and the
- planner attempts to determine the optimal query plan, the actual
- values of any parameters specified in the statement are
- unavailable. <productname>PostgreSQL</productname> collects
- statistics on the distribution of data in the table, and can use
- constant values in a statement to make guesses about the likely
- result of executing the statement. Since this data is unavailable
- when planning prepared statements with parameters, the chosen plan
- might be suboptimal. To examine the query plan
- <productname>PostgreSQL</productname> has chosen for a prepared
- statement, use <xref linkend="sql-explain">.
+ If a prepared statement is executed enough times, the server may eventually
+ decide to save and re-use a generic plan rather than re-planning each time.
+ This will occur immediately if the prepared statement has no parameters;
+ otherwise it occurs only if the generic plan appears to be not much more
+ expensive than a plan that depends on specific parameter values.
+ Typically, a generic plan will be selected only if the query's performance
+ is estimated to be fairly insensitive to the specific parameter values
+ supplied.
+ </para>
+
+ <para>
+ To examine the query plan <productname>PostgreSQL</productname> is using
+ for a prepared statement, use <xref linkend="sql-explain">.
+ If a generic plan is in use, it will contain parameter symbols
+ <literal>$<replaceable>n</></literal>, while a custom plan will have the
+ current actual parameter values substituted into it.
</para>
<para>
@@ -151,7 +153,7 @@ PREPARE <replaceable class="PARAMETER">name</replaceable> [ ( <replaceable class
</para>
<para>
- You can see all available prepared statements of a session by querying the
+ You can see all prepared statements available in the session by querying the
<link linkend="view-pg-prepared-statements"><structname>pg_prepared_statements</structname></link>
system view.
</para>
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index 1b41cb40b3c..7162fdb7aa3 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -733,7 +733,8 @@ int SPI_execute_with_args(const char *<parameter>command</parameter>,
<para>
Similar results can be achieved with <function>SPI_prepare</> followed by
<function>SPI_execute_plan</function>; however, when using this function
- the query plan is customized to the specific parameter values provided.
+ the query plan is always customized to the specific parameter values
+ provided.
For one-time query execution, this function should be preferred.
If the same command is to be executed with many different parameters,
either method might be faster, depending on the cost of re-planning
@@ -840,7 +841,7 @@ int SPI_execute_with_args(const char *<parameter>command</parameter>,
<refnamediv>
<refname>SPI_prepare</refname>
- <refpurpose>prepare a plan for a command, without executing it yet</refpurpose>
+ <refpurpose>prepare a statement, without executing it yet</refpurpose>
</refnamediv>
<indexterm><primary>SPI_prepare</primary></indexterm>
@@ -855,17 +856,22 @@ SPIPlanPtr SPI_prepare(const char * <parameter>command</parameter>, int <paramet
<title>Description</title>
<para>
- <function>SPI_prepare</function> creates and returns an execution
- plan for the specified command, but doesn't execute the command.
- This function should only be called from a connected procedure.
+ <function>SPI_prepare</function> creates and returns a prepared
+ statement for the specified command, but doesn't execute the command.
+ The prepared statement can later be executed repeatedly using
+ <function>SPI_execute_plan</function>.
</para>
<para>
When the same or a similar command is to be executed repeatedly, it
- might be advantageous to perform the planning only once.
- <function>SPI_prepare</function> converts a command string into an
- execution plan that can be executed repeatedly using
- <function>SPI_execute_plan</function>.
+ is generally advantageous to perform parse analysis only once, and
+ might furthermore be advantageous to re-use an execution plan for the
+ command.
+ <function>SPI_prepare</function> converts a command string into a
+ prepared statement that encapsulates the results of parse analysis.
+ The prepared statement also provides a place for caching an execution plan
+ if it is found that generating a custom plan for each execution is not
+ helpful.
</para>
<para>
@@ -878,11 +884,11 @@ SPIPlanPtr SPI_prepare(const char * <parameter>command</parameter>, int <paramet
</para>
<para>
- The plan returned by <function>SPI_prepare</function> can be used
+ The statement returned by <function>SPI_prepare</function> can be used
only in the current invocation of the procedure, since
- <function>SPI_finish</function> frees memory allocated for a plan.
- But a plan can be saved for longer using the function
- <function>SPI_saveplan</function>.
+ <function>SPI_finish</function> frees memory allocated for such a
+ statement. But the statement can be saved for longer using the functions
+ <function>SPI_keepplan</function> or <function>SPI_saveplan</function>.
</para>
</refsect1>
@@ -925,7 +931,8 @@ SPIPlanPtr SPI_prepare(const char * <parameter>command</parameter>, int <paramet
<para>
<function>SPI_prepare</function> returns a non-null pointer to an
- execution plan. On error, <symbol>NULL</symbol> will be returned,
+ <type>SPIPlan</>, which is an opaque struct representing a prepared
+ statement. On error, <symbol>NULL</symbol> will be returned,
and <varname>SPI_result</varname> will be set to one of the same
error codes used by <function>SPI_execute</function>, except that
it is set to <symbol>SPI_ERROR_ARGUMENT</symbol> if
@@ -939,6 +946,26 @@ SPIPlanPtr SPI_prepare(const char * <parameter>command</parameter>, int <paramet
<title>Notes</title>
<para>
+ If no parameters are defined, a generic plan will be created at the
+ first use of <function>SPI_execute_plan</function>, and used for all
+ subsequent executions as well. If there are parameters, the first few uses
+ of <function>SPI_execute_plan</function> will generate custom plans
+ that are specific to the supplied parameter values. After enough uses
+ of the same prepared statement, <function>SPI_execute_plan</function> will
+ build a generic plan, and if that is not too much more expensive than the
+ custom plans, it will start using the generic plan instead of re-planning
+ each time. If this default behavior is unsuitable, you can alter it by
+ passing the <literal>CURSOR_OPT_GENERIC_PLAN</> or
+ <literal>CURSOR_OPT_CUSTOM_PLAN</> flag to
+ <function>SPI_prepare_cursor</function>, to force use of generic or custom
+ plans respectively.
+ </para>
+
+ <para>
+ This function should only be called from a connected procedure.
+ </para>
+
+ <para>
<type>SPIPlanPtr</> is declared as a pointer to an opaque struct type in
<filename>spi.h</>. It is unwise to try to access its contents
directly, as that makes your code much more likely to break in
@@ -946,10 +973,8 @@ SPIPlanPtr SPI_prepare(const char * <parameter>command</parameter>, int <paramet
</para>
<para>
- There is a disadvantage to using parameters: since the planner does
- not know the values that will be supplied for the parameters, it
- might make worse planning choices than it would make for a normal
- command with all constants visible.
+ The name <type>SPIPlanPtr</> is somewhat historical, since the data
+ structure no longer necessarily contains an execution plan.
</para>
</refsect1>
</refentry>
@@ -964,7 +989,7 @@ SPIPlanPtr SPI_prepare(const char * <parameter>command</parameter>, int <paramet
<refnamediv>
<refname>SPI_prepare_cursor</refname>
- <refpurpose>prepare a plan for a command, without executing it yet</refpurpose>
+ <refpurpose>prepare a statement, without executing it yet</refpurpose>
</refnamediv>
<indexterm><primary>SPI_prepare_cursor</primary></indexterm>
@@ -1047,8 +1072,10 @@ SPIPlanPtr SPI_prepare_cursor(const char * <parameter>command</parameter>, int <
<para>
Useful bits to set in <parameter>cursorOptions</> include
<symbol>CURSOR_OPT_SCROLL</symbol>,
- <symbol>CURSOR_OPT_NO_SCROLL</symbol>, and
- <symbol>CURSOR_OPT_FAST_PLAN</symbol>. Note in particular that
+ <symbol>CURSOR_OPT_NO_SCROLL</symbol>,
+ <symbol>CURSOR_OPT_FAST_PLAN</symbol>,
+ <symbol>CURSOR_OPT_GENERIC_PLAN</symbol>, and
+ <symbol>CURSOR_OPT_CUSTOM_PLAN</symbol>. Note in particular that
<symbol>CURSOR_OPT_HOLD</symbol> is ignored.
</para>
</refsect1>
@@ -1064,7 +1091,7 @@ SPIPlanPtr SPI_prepare_cursor(const char * <parameter>command</parameter>, int <
<refnamediv>
<refname>SPI_prepare_params</refname>
- <refpurpose>prepare a plan for a command, without executing it yet</refpurpose>
+ <refpurpose>prepare a statement, without executing it yet</refpurpose>
</refnamediv>
<indexterm><primary>SPI_prepare_params</primary></indexterm>
@@ -1082,8 +1109,8 @@ SPIPlanPtr SPI_prepare_params(const char * <parameter>command</parameter>,
<title>Description</title>
<para>
- <function>SPI_prepare_params</function> creates and returns an execution
- plan for the specified command, but doesn't execute the command.
+ <function>SPI_prepare_params</function> creates and returns a prepared
+ statement for the specified command, but doesn't execute the command.
This function is equivalent to <function>SPI_prepare_cursor</function>,
with the addition that the caller can specify parser hook functions
to control the parsing of external parameter references.
@@ -1152,7 +1179,7 @@ SPIPlanPtr SPI_prepare_params(const char * <parameter>command</parameter>,
<refnamediv>
<refname>SPI_getargcount</refname>
- <refpurpose>return the number of arguments needed by a plan
+ <refpurpose>return the number of arguments needed by a statement
prepared by <function>SPI_prepare</function></refpurpose>
</refnamediv>
@@ -1169,7 +1196,7 @@ int SPI_getargcount(SPIPlanPtr <parameter>plan</parameter>)
<para>
<function>SPI_getargcount</function> returns the number of arguments needed
- to execute a plan prepared by <function>SPI_prepare</function>.
+ to execute a statement prepared by <function>SPI_prepare</function>.
</para>
</refsect1>
@@ -1181,7 +1208,7 @@ int SPI_getargcount(SPIPlanPtr <parameter>plan</parameter>)
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
<listitem>
<para>
- execution plan (returned by <function>SPI_prepare</function>)
+ prepared statement (returned by <function>SPI_prepare</function>)
</para>
</listitem>
</varlistentry>
@@ -1210,7 +1237,7 @@ int SPI_getargcount(SPIPlanPtr <parameter>plan</parameter>)
<refnamediv>
<refname>SPI_getargtypeid</refname>
<refpurpose>return the data type OID for an argument of
- a plan prepared by <function>SPI_prepare</function></refpurpose>
+ a statement prepared by <function>SPI_prepare</function></refpurpose>
</refnamediv>
<indexterm><primary>SPI_getargtypeid</primary></indexterm>
@@ -1226,7 +1253,7 @@ Oid SPI_getargtypeid(SPIPlanPtr <parameter>plan</parameter>, int <parameter>argI
<para>
<function>SPI_getargtypeid</function> returns the OID representing the type
- for the <parameter>argIndex</parameter>'th argument of a plan prepared by
+ for the <parameter>argIndex</parameter>'th argument of a statement prepared by
<function>SPI_prepare</function>. First argument is at index zero.
</para>
</refsect1>
@@ -1239,7 +1266,7 @@ Oid SPI_getargtypeid(SPIPlanPtr <parameter>plan</parameter>, int <parameter>argI
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
<listitem>
<para>
- execution plan (returned by <function>SPI_prepare</function>)
+ prepared statement (returned by <function>SPI_prepare</function>)
</para>
</listitem>
</varlistentry>
@@ -1279,7 +1306,7 @@ Oid SPI_getargtypeid(SPIPlanPtr <parameter>plan</parameter>, int <parameter>argI
<refnamediv>
<refname>SPI_is_cursor_plan</refname>
- <refpurpose>return <symbol>true</symbol> if a plan
+ <refpurpose>return <symbol>true</symbol> if a statement
prepared by <function>SPI_prepare</function> can be used with
<function>SPI_cursor_open</function></refpurpose>
</refnamediv>
@@ -1297,7 +1324,7 @@ bool SPI_is_cursor_plan(SPIPlanPtr <parameter>plan</parameter>)
<para>
<function>SPI_is_cursor_plan</function> returns <symbol>true</symbol>
- if a plan prepared by <function>SPI_prepare</function> can be passed
+ if a statement prepared by <function>SPI_prepare</function> can be passed
as an argument to <function>SPI_cursor_open</function>, or
<symbol>false</symbol> if that is not the case. The criteria are that the
<parameter>plan</parameter> represents one single command and that this
@@ -1316,7 +1343,7 @@ bool SPI_is_cursor_plan(SPIPlanPtr <parameter>plan</parameter>)
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
<listitem>
<para>
- execution plan (returned by <function>SPI_prepare</function>)
+ prepared statement (returned by <function>SPI_prepare</function>)
</para>
</listitem>
</varlistentry>
@@ -1348,7 +1375,7 @@ bool SPI_is_cursor_plan(SPIPlanPtr <parameter>plan</parameter>)
<refnamediv>
<refname>SPI_execute_plan</refname>
- <refpurpose>execute a plan prepared by <function>SPI_prepare</function></refpurpose>
+ <refpurpose>execute a statement prepared by <function>SPI_prepare</function></refpurpose>
</refnamediv>
<indexterm><primary>SPI_execute_plan</primary></indexterm>
@@ -1364,8 +1391,9 @@ int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>
<title>Description</title>
<para>
- <function>SPI_execute_plan</function> executes a plan prepared by
- <function>SPI_prepare</function>. <parameter>read_only</parameter> and
+ <function>SPI_execute_plan</function> executes a statement prepared by
+ <function>SPI_prepare</function> or one of its siblings.
+ <parameter>read_only</parameter> and
<parameter>count</parameter> have the same interpretation as in
<function>SPI_execute</function>.
</para>
@@ -1379,7 +1407,7 @@ int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
<listitem>
<para>
- execution plan (returned by <function>SPI_prepare</function>)
+ prepared statement (returned by <function>SPI_prepare</function>)
</para>
</listitem>
</varlistentry>
@@ -1389,7 +1417,7 @@ int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>
<listitem>
<para>
An array of actual parameter values. Must have same length as the
- plan's number of arguments.
+ statement's number of arguments.
</para>
</listitem>
</varlistentry>
@@ -1399,7 +1427,7 @@ int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>
<listitem>
<para>
An array describing which parameters are null. Must have same length as
- the plan's number of arguments.
+ the statement's number of arguments.
<literal>n</literal> indicates a null value (entry in
<parameter>values</> will be ignored); a space indicates a
nonnull value (entry in <parameter>values</> is valid).
@@ -1479,7 +1507,7 @@ int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>
<refnamediv>
<refname>SPI_execute_plan_with_paramlist</refname>
- <refpurpose>execute a plan prepared by <function>SPI_prepare</function></refpurpose>
+ <refpurpose>execute a statement prepared by <function>SPI_prepare</function></refpurpose>
</refnamediv>
<indexterm><primary>SPI_execute_plan_with_paramlist</primary></indexterm>
@@ -1497,7 +1525,7 @@ int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
<title>Description</title>
<para>
- <function>SPI_execute_plan_with_paramlist</function> executes a plan
+ <function>SPI_execute_plan_with_paramlist</function> executes a statement
prepared by <function>SPI_prepare</function>.
This function is equivalent to <function>SPI_execute_plan</function>
except that information about the parameter values to be passed to the
@@ -1516,7 +1544,7 @@ int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
<listitem>
<para>
- execution plan (returned by <function>SPI_prepare</function>)
+ prepared statement (returned by <function>SPI_prepare</function>)
</para>
</listitem>
</varlistentry>
@@ -1573,7 +1601,7 @@ int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
<refnamediv>
<refname>SPI_execp</refname>
- <refpurpose>execute a plan in read/write mode</refpurpose>
+ <refpurpose>execute a statement in read/write mode</refpurpose>
</refnamediv>
<indexterm><primary>SPI_execp</primary></indexterm>
@@ -1603,7 +1631,7 @@ int SPI_execp(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values<
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
<listitem>
<para>
- execution plan (returned by <function>SPI_prepare</function>)
+ prepared statement (returned by <function>SPI_prepare</function>)
</para>
</listitem>
</varlistentry>
@@ -1613,7 +1641,7 @@ int SPI_execp(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values<
<listitem>
<para>
An array of actual parameter values. Must have same length as the
- plan's number of arguments.
+ statement's number of arguments.
</para>
</listitem>
</varlistentry>
@@ -1623,7 +1651,7 @@ int SPI_execp(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values<
<listitem>
<para>
An array describing which parameters are null. Must have same length as
- the plan's number of arguments.
+ the statement's number of arguments.
<literal>n</literal> indicates a null value (entry in
<parameter>values</> will be ignored); a space indicates a
nonnull value (entry in <parameter>values</> is valid).
@@ -1673,7 +1701,7 @@ int SPI_execp(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values<
<refnamediv>
<refname>SPI_cursor_open</refname>
- <refpurpose>set up a cursor using a plan created with <function>SPI_prepare</function></refpurpose>
+ <refpurpose>set up a cursor using a statement created with <function>SPI_prepare</function></refpurpose>
</refnamediv>
<indexterm><primary>SPI_cursor_open</primary></indexterm>
@@ -1691,14 +1719,14 @@ Portal SPI_cursor_open(const char * <parameter>name</parameter>, SPIPlanPtr <par
<para>
<function>SPI_cursor_open</function> sets up a cursor (internally,
- a portal) that will execute a plan prepared by
+ a portal) that will execute a statement prepared by
<function>SPI_prepare</function>. The parameters have the same
meanings as the corresponding parameters to
<function>SPI_execute_plan</function>.
</para>
<para>
- Using a cursor instead of executing the plan directly has two
+ Using a cursor instead of executing the statement directly has two
benefits. First, the result rows can be retrieved a few at a time,
avoiding memory overrun for queries that return many rows. Second,
a portal can outlive the current procedure (it can, in fact, live
@@ -1731,7 +1759,7 @@ Portal SPI_cursor_open(const char * <parameter>name</parameter>, SPIPlanPtr <par
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
<listitem>
<para>
- execution plan (returned by <function>SPI_prepare</function>)
+ prepared statement (returned by <function>SPI_prepare</function>)
</para>
</listitem>
</varlistentry>
@@ -1741,7 +1769,7 @@ Portal SPI_cursor_open(const char * <parameter>name</parameter>, SPIPlanPtr <par
<listitem>
<para>
An array of actual parameter values. Must have same length as the
- plan's number of arguments.
+ statement's number of arguments.
</para>
</listitem>
</varlistentry>
@@ -1751,7 +1779,7 @@ Portal SPI_cursor_open(const char * <parameter>name</parameter>, SPIPlanPtr <par
<listitem>
<para>
An array describing which parameters are null. Must have same length as
- the plan's number of arguments.
+ the statement's number of arguments.
<literal>n</literal> indicates a null value (entry in
<parameter>values</> will be ignored); a space indicates a
nonnull value (entry in <parameter>values</> is valid).
@@ -1958,7 +1986,7 @@ Portal SPI_cursor_open_with_paramlist(const char *<parameter>name</parameter>,
<para>
<function>SPI_cursor_open_with_paramlist</function> sets up a cursor
- (internally, a portal) that will execute a plan prepared by
+ (internally, a portal) that will execute a statement prepared by
<function>SPI_prepare</function>.
This function is equivalent to <function>SPI_cursor_open</function>
except that information about the parameter values to be passed to the
@@ -1992,7 +2020,7 @@ Portal SPI_cursor_open_with_paramlist(const char *<parameter>name</parameter>,
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
<listitem>
<para>
- execution plan (returned by <function>SPI_prepare</function>)
+ prepared statement (returned by <function>SPI_prepare</function>)
</para>
</listitem>
</varlistentry>
@@ -2495,6 +2523,75 @@ void SPI_cursor_close(Portal <parameter>portal</parameter>)
<!-- *********************************************** -->
+<refentry id="spi-spi-keepplan">
+ <refmeta>
+ <refentrytitle>SPI_keepplan</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>SPI_keepplan</refname>
+ <refpurpose>save a prepared statement</refpurpose>
+ </refnamediv>
+
+ <indexterm><primary>SPI_keepplan</primary></indexterm>
+
+ <refsynopsisdiv>
+<synopsis>
+int SPI_keepplan(SPIPlanPtr <parameter>plan</parameter>)
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <function>SPI_keepplan</function> saves a passed statement (prepared by
+ <function>SPI_prepare</function>) so that it will not be freed
+ by <function>SPI_finish</function> nor by the transaction manager.
+ This gives you the ability to reuse prepared statements in the subsequent
+ invocations of your procedure in the current session.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Arguments</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
+ <listitem>
+ <para>
+ the prepared statement to be saved
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>
+ 0 on success;
+ <symbol>SPI_ERROR_ARGUMENT</symbol> if <parameter>plan</parameter>
+ is <symbol>NULL</symbol> or invalid
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Notes</title>
+
+ <para>
+ The passed-in statement is relocated to permanent storage by means
+ of pointer adjustment (no data copying is required). If you later
+ wish to delete it, use <function>SPI_freeplan</function> on it.
+ </para>
+ </refsect1>
+</refentry>
+
+<!-- *********************************************** -->
+
<refentry id="spi-spi-saveplan">
<refmeta>
<refentrytitle>SPI_saveplan</refentrytitle>
@@ -2503,7 +2600,7 @@ void SPI_cursor_close(Portal <parameter>portal</parameter>)
<refnamediv>
<refname>SPI_saveplan</refname>
- <refpurpose>save a plan</refpurpose>
+ <refpurpose>save a prepared statement</refpurpose>
</refnamediv>
<indexterm><primary>SPI_saveplan</primary></indexterm>
@@ -2518,11 +2615,11 @@ SPIPlanPtr SPI_saveplan(SPIPlanPtr <parameter>plan</parameter>)
<title>Description</title>
<para>
- <function>SPI_saveplan</function> saves a passed plan (prepared by
- <function>SPI_prepare</function>) in memory that will not be freed
+ <function>SPI_saveplan</function> copies a passed statement (prepared by
+ <function>SPI_prepare</function>) into memory that will not be freed
by <function>SPI_finish</function> nor by the transaction manager,
- and returns a pointer to the saved plan. This gives you the
- ability to reuse prepared plans in the subsequent invocations of
+ and returns a pointer to the copied statement. This gives you the
+ ability to reuse prepared statements in the subsequent invocations of
your procedure in the current session.
</para>
</refsect1>
@@ -2535,7 +2632,7 @@ SPIPlanPtr SPI_saveplan(SPIPlanPtr <parameter>plan</parameter>)
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
<listitem>
<para>
- the plan to be saved
+ the prepared statement to be saved
</para>
</listitem>
</varlistentry>
@@ -2546,7 +2643,7 @@ SPIPlanPtr SPI_saveplan(SPIPlanPtr <parameter>plan</parameter>)
<title>Return Value</title>
<para>
- Pointer to the saved plan; <symbol>NULL</symbol> if unsuccessful.
+ Pointer to the copied statement; or <symbol>NULL</symbol> if unsuccessful.
On error, <varname>SPI_result</varname> is set thus:
<variablelist>
@@ -2575,16 +2672,15 @@ SPIPlanPtr SPI_saveplan(SPIPlanPtr <parameter>plan</parameter>)
<title>Notes</title>
<para>
- The passed-in plan is not freed, so you might wish to do
+ The originally passed-in statement is not freed, so you might wish to do
<function>SPI_freeplan</function> on it to avoid leaking memory
until <function>SPI_finish</>.
</para>
<para>
- If one of the objects (a table, function, etc.) referenced by the
- prepared plan is dropped or redefined, then future executions of
- <function>SPI_execute_plan</function> may fail or return different
- results than the plan initially indicates.
+ In most cases, <function>SPI_keepplan</function> is preferred to this
+ function, since it accomplishes largely the same result without needing
+ to physically copy the prepared statement's data structures.
</para>
</refsect1>
</refentry>
@@ -3809,7 +3905,7 @@ void SPI_freetuptable(SPITupleTable * <parameter>tuptable</parameter>)
<refnamediv>
<refname>SPI_freeplan</refname>
- <refpurpose>free a previously saved plan</refpurpose>
+ <refpurpose>free a previously saved prepared statement</refpurpose>
</refnamediv>
<indexterm><primary>SPI_freeplan</primary></indexterm>
@@ -3824,9 +3920,9 @@ int SPI_freeplan(SPIPlanPtr <parameter>plan</parameter>)
<title>Description</title>
<para>
- <function>SPI_freeplan</function> releases a command execution plan
+ <function>SPI_freeplan</function> releases a prepared statement
previously returned by <function>SPI_prepare</function> or saved by
- <function>SPI_saveplan</function>.
+ <function>SPI_keepplan</function> or <function>SPI_saveplan</function>.
</para>
</refsect1>
@@ -3838,7 +3934,7 @@ int SPI_freeplan(SPIPlanPtr <parameter>plan</parameter>)
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
<listitem>
<para>
- pointer to plan to free
+ pointer to statement to free
</para>
</listitem>
</varlistentry>
@@ -3849,6 +3945,7 @@ int SPI_freeplan(SPIPlanPtr <parameter>plan</parameter>)
<title>Return Value</title>
<para>
+ 0 on success;
<symbol>SPI_ERROR_ARGUMENT</symbol> if <parameter>plan</parameter>
is <symbol>NULL</symbol> or invalid
</para>