Expose more cursor-related functionality in SPI: specifically, allow
access to the planner's cursor-related planning options, and provide new FETCH/MOVE routines that allow access to the full power of those commands. Small refactoring of planner(), pg_plan_query(), and pg_plan_queries() APIs to make it convenient to pass the planning options down from SPI. This is the core-code portion of Pavel Stehule's patch for scrollable cursor support in plpgsql; I'll review and apply the plpgsql changes separately.
This commit is contained in:
parent
fa92d21a48
commit
66888f7424
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.55 2007/03/25 23:27:59 tgl Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.56 2007/04/16 01:14:55 tgl Exp $ -->
|
||||||
|
|
||||||
<chapter id="spi">
|
<chapter id="spi">
|
||||||
<title>Server Programming Interface</title>
|
<title>Server Programming Interface</title>
|
||||||
@ -799,6 +799,104 @@ SPIPlanPtr SPI_prepare(const char * <parameter>command</parameter>, int <paramet
|
|||||||
|
|
||||||
<!-- *********************************************** -->
|
<!-- *********************************************** -->
|
||||||
|
|
||||||
|
<refentry id="spi-spi-prepare-cursor">
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>SPI_prepare_cursor</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>SPI_prepare_cursor</refname>
|
||||||
|
<refpurpose>prepare a plan for a command, without executing it yet</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<indexterm><primary>SPI_prepare_cursor</primary></indexterm>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<synopsis>
|
||||||
|
SPIPlanPtr SPI_prepare_cursor(const char * <parameter>command</parameter>, int <parameter>nargs</parameter>, Oid * <parameter>argtypes</parameter>, int <parameter>cursorOptions</parameter>)
|
||||||
|
</synopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<function>SPI_prepare_cursor</function> is identical to
|
||||||
|
<function>SPI_prepare</function>, except that it also allows specification
|
||||||
|
of the planner's <quote>cursor options</> parameter. This is a bitmask
|
||||||
|
having the values shown in <filename>nodes/parsenodes.h</filename>
|
||||||
|
for the <structfield>options</> field of <structname>DeclareCursorStmt</>.
|
||||||
|
<function>SPI_prepare</function> always takes these options as zero.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Arguments</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>const char * <parameter>command</parameter></literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
command string
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>int <parameter>nargs</parameter></literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
number of input parameters (<literal>$1</>, <literal>$2</>, etc.)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>Oid * <parameter>argtypes</parameter></literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
pointer to an array containing the <acronym>OID</acronym>s of
|
||||||
|
the data types of the parameters
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>int <parameter>cursorOptions</parameter></literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
integer bitmask of cursor options; zero produces default behavior
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Return Value</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<function>SPI_prepare_cursor</function> has the same return conventions as
|
||||||
|
<function>SPI_prepare</function>.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Notes</title>
|
||||||
|
|
||||||
|
<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_HOLD</symbol> is ignored.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
|
|
||||||
|
<!-- *********************************************** -->
|
||||||
|
|
||||||
<refentry id="spi-spi-getargcount">
|
<refentry id="spi-spi-getargcount">
|
||||||
<refmeta>
|
<refmeta>
|
||||||
<refentrytitle>SPI_getargcount</refentrytitle>
|
<refentrytitle>SPI_getargcount</refentrytitle>
|
||||||
@ -1430,7 +1528,9 @@ void SPI_cursor_fetch(Portal <parameter>portal</parameter>, bool <parameter>forw
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
<function>SPI_cursor_fetch</function> fetches some rows from a
|
<function>SPI_cursor_fetch</function> fetches some rows from a
|
||||||
cursor. This is equivalent to the SQL command <command>FETCH</>.
|
cursor. This is equivalent to a subset of the SQL command
|
||||||
|
<command>FETCH</> (see <function>SPI_scroll_cursor_fetch</function>
|
||||||
|
for more functionality).
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@ -1476,6 +1576,15 @@ void SPI_cursor_fetch(Portal <parameter>portal</parameter>, bool <parameter>forw
|
|||||||
<function>SPI_execute</function> if successful.
|
<function>SPI_execute</function> if successful.
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Notes</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Fetching backward may fail if the cursor's plan was not created
|
||||||
|
with the <symbol>CURSOR_OPT_SCROLL</symbol> option.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|
||||||
<!-- *********************************************** -->
|
<!-- *********************************************** -->
|
||||||
@ -1503,8 +1612,9 @@ void SPI_cursor_move(Portal <parameter>portal</parameter>, bool <parameter>forwa
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
<function>SPI_cursor_move</function> skips over some number of rows
|
<function>SPI_cursor_move</function> skips over some number of rows
|
||||||
in a cursor. This is equivalent to the SQL command
|
in a cursor. This is equivalent to a subset of the SQL command
|
||||||
<command>MOVE</>.
|
<command>MOVE</> (see <function>SPI_scroll_cursor_move</function>
|
||||||
|
for more functionality).
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@ -1540,6 +1650,210 @@ void SPI_cursor_move(Portal <parameter>portal</parameter>, bool <parameter>forwa
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Notes</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Moving backward may fail if the cursor's plan was not created
|
||||||
|
with the <symbol>CURSOR_OPT_SCROLL</symbol> option.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
|
|
||||||
|
<!-- *********************************************** -->
|
||||||
|
|
||||||
|
<refentry id="spi-spi-scroll-cursor-fetch">
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>SPI_scroll_cursor_fetch</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>SPI_scroll_cursor_fetch</refname>
|
||||||
|
<refpurpose>fetch some rows from a cursor</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<indexterm><primary>SPI_scroll_cursor_fetch</primary></indexterm>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<synopsis>
|
||||||
|
void SPI_scroll_cursor_fetch(Portal <parameter>portal</parameter>, FetchDirection <parameter>direction</parameter>, long <parameter>count</parameter>)
|
||||||
|
</synopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<function>SPI_scroll_cursor_fetch</function> fetches some rows from a
|
||||||
|
cursor. This is equivalent to the SQL command <command>FETCH</>.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Arguments</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>Portal <parameter>portal</parameter></literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
portal containing the cursor
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>FetchDirection <parameter>direction</parameter></literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
one of <symbol>FETCH_FORWARD</symbol>,
|
||||||
|
<symbol>FETCH_BACKWARD</symbol>,
|
||||||
|
<symbol>FETCH_ABSOLUTE</symbol> or
|
||||||
|
<symbol>FETCH_RELATIVE</symbol>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>long <parameter>count</parameter></literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
number of rows to fetch for
|
||||||
|
<symbol>FETCH_FORWARD</symbol> or
|
||||||
|
<symbol>FETCH_BACKWARD</symbol>; absolute row number to fetch for
|
||||||
|
<symbol>FETCH_ABSOLUTE</symbol>; or relative row number to fetch for
|
||||||
|
<symbol>FETCH_RELATIVE</symbol>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Return Value</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<varname>SPI_processed</varname> and
|
||||||
|
<varname>SPI_tuptable</varname> are set as in
|
||||||
|
<function>SPI_execute</function> if successful.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Notes</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
See the SQL <xref linkend="sql-fetch" endterm="sql-fetch-title"> command
|
||||||
|
for details of the interpretation of the
|
||||||
|
<parameter>direction</parameter> and
|
||||||
|
<parameter>count</parameter> parameters.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Direction values other than <symbol>FETCH_FORWARD</symbol>
|
||||||
|
may fail if the cursor's plan was not created
|
||||||
|
with the <symbol>CURSOR_OPT_SCROLL</symbol> option.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
|
|
||||||
|
<!-- *********************************************** -->
|
||||||
|
|
||||||
|
<refentry id="spi-spi-scroll-cursor-move">
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>SPI_scroll_cursor_move</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>SPI_scroll_cursor_move</refname>
|
||||||
|
<refpurpose>move a cursor</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<indexterm><primary>SPI_scroll_cursor_move</primary></indexterm>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<synopsis>
|
||||||
|
void SPI_scroll_cursor_move(Portal <parameter>portal</parameter>, FetchDirection <parameter>direction</parameter>, long <parameter>count</parameter>)
|
||||||
|
</synopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<function>SPI_scroll_cursor_move</function> skips over some number of rows
|
||||||
|
in a cursor. This is equivalent to the SQL command
|
||||||
|
<command>MOVE</>.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Arguments</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>Portal <parameter>portal</parameter></literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
portal containing the cursor
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>FetchDirection <parameter>direction</parameter></literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
one of <symbol>FETCH_FORWARD</symbol>,
|
||||||
|
<symbol>FETCH_BACKWARD</symbol>,
|
||||||
|
<symbol>FETCH_ABSOLUTE</symbol> or
|
||||||
|
<symbol>FETCH_RELATIVE</symbol>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>long <parameter>count</parameter></literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
number of rows to move for
|
||||||
|
<symbol>FETCH_FORWARD</symbol> or
|
||||||
|
<symbol>FETCH_BACKWARD</symbol>; absolute row number to move to for
|
||||||
|
<symbol>FETCH_ABSOLUTE</symbol>; or relative row number to move to for
|
||||||
|
<symbol>FETCH_RELATIVE</symbol>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Return Value</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<varname>SPI_processed</varname> and
|
||||||
|
<varname>SPI_tuptable</varname> are set as in
|
||||||
|
<function>SPI_execute</function> if successful.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Notes</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
See the SQL <xref linkend="sql-fetch" endterm="sql-fetch-title"> command
|
||||||
|
for details of the interpretation of the
|
||||||
|
<parameter>direction</parameter> and
|
||||||
|
<parameter>count</parameter> parameters.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Direction values other than <symbol>FETCH_FORWARD</symbol>
|
||||||
|
may fail if the cursor's plan was not created
|
||||||
|
with the <symbol>CURSOR_OPT_SCROLL</symbol> option.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|
||||||
<!-- *********************************************** -->
|
<!-- *********************************************** -->
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.279 2007/03/29 00:15:38 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.280 2007/04/16 01:14:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1023,7 +1023,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
|
|||||||
errmsg("COPY (SELECT INTO) is not supported")));
|
errmsg("COPY (SELECT INTO) is not supported")));
|
||||||
|
|
||||||
/* plan the query */
|
/* plan the query */
|
||||||
plan = planner(query, false, 0, NULL);
|
plan = planner(query, 0, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update snapshot command ID to ensure this query sees results of any
|
* Update snapshot command ID to ensure this query sees results of any
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.160 2007/03/13 00:33:39 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.161 2007/04/16 01:14:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -42,7 +42,7 @@ typedef struct ExplainState
|
|||||||
List *rtable; /* range table */
|
List *rtable; /* range table */
|
||||||
} ExplainState;
|
} ExplainState;
|
||||||
|
|
||||||
static void ExplainOneQuery(Query *query, bool isCursor, int cursorOptions,
|
static void ExplainOneQuery(Query *query, int cursorOptions,
|
||||||
ExplainStmt *stmt, const char *queryString,
|
ExplainStmt *stmt, const char *queryString,
|
||||||
ParamListInfo params, TupOutputState *tstate);
|
ParamListInfo params, TupOutputState *tstate);
|
||||||
static double elapsed_time(instr_time *starttime);
|
static double elapsed_time(instr_time *starttime);
|
||||||
@ -102,7 +102,7 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
|
|||||||
/* Explain every plan */
|
/* Explain every plan */
|
||||||
foreach(l, rewritten)
|
foreach(l, rewritten)
|
||||||
{
|
{
|
||||||
ExplainOneQuery((Query *) lfirst(l), false, 0,
|
ExplainOneQuery((Query *) lfirst(l), 0,
|
||||||
stmt, queryString, params, tstate);
|
stmt, queryString, params, tstate);
|
||||||
/* put a blank line between plans */
|
/* put a blank line between plans */
|
||||||
if (lnext(l) != NULL)
|
if (lnext(l) != NULL)
|
||||||
@ -134,7 +134,7 @@ ExplainResultDesc(ExplainStmt *stmt)
|
|||||||
* print out the execution plan for one Query
|
* print out the execution plan for one Query
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ExplainOneQuery(Query *query, bool isCursor, int cursorOptions,
|
ExplainOneQuery(Query *query, int cursorOptions,
|
||||||
ExplainStmt *stmt, const char *queryString,
|
ExplainStmt *stmt, const char *queryString,
|
||||||
ParamListInfo params, TupOutputState *tstate)
|
ParamListInfo params, TupOutputState *tstate)
|
||||||
{
|
{
|
||||||
@ -150,7 +150,7 @@ ExplainOneQuery(Query *query, bool isCursor, int cursorOptions,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* plan the query */
|
/* plan the query */
|
||||||
plan = planner(query, isCursor, cursorOptions, params);
|
plan = planner(query, cursorOptions, params);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update snapshot command ID to ensure this query sees results of any
|
* Update snapshot command ID to ensure this query sees results of any
|
||||||
@ -229,7 +229,7 @@ ExplainOneUtility(Node *utilityStmt, ExplainStmt *stmt,
|
|||||||
/* do not actually execute the underlying query! */
|
/* do not actually execute the underlying query! */
|
||||||
memcpy(&newstmt, stmt, sizeof(ExplainStmt));
|
memcpy(&newstmt, stmt, sizeof(ExplainStmt));
|
||||||
newstmt.analyze = false;
|
newstmt.analyze = false;
|
||||||
ExplainOneQuery(query, true, dcstmt->options, &newstmt,
|
ExplainOneQuery(query, dcstmt->options, &newstmt,
|
||||||
queryString, params, tstate);
|
queryString, params, tstate);
|
||||||
}
|
}
|
||||||
else if (IsA(utilityStmt, ExecuteStmt))
|
else if (IsA(utilityStmt, ExecuteStmt))
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.63 2007/04/12 06:53:46 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.64 2007/04/16 01:14:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -111,7 +111,7 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params,
|
|||||||
errdetail("Cursors must be READ ONLY.")));
|
errdetail("Cursors must be READ ONLY.")));
|
||||||
|
|
||||||
/* plan the query */
|
/* plan the query */
|
||||||
plan = planner(query, true, stmt->options, params);
|
plan = planner(query, stmt->options, params);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a portal and copy the plan into its memory context.
|
* Create a portal and copy the plan into its memory context.
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* Copyright (c) 2002-2007, PostgreSQL Global Development Group
|
* Copyright (c) 2002-2007, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.71 2007/04/12 06:53:46 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.72 2007/04/16 01:14:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -160,7 +160,7 @@ PrepareQuery(PrepareStmt *stmt, const char *queryString)
|
|||||||
query_list = QueryRewrite(query);
|
query_list = QueryRewrite(query);
|
||||||
|
|
||||||
/* Generate plans for queries. Snapshot is already set. */
|
/* Generate plans for queries. Snapshot is already set. */
|
||||||
plan_list = pg_plan_queries(query_list, NULL, false);
|
plan_list = pg_plan_queries(query_list, 0, NULL, false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save the results.
|
* Save the results.
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.114 2007/04/02 18:49:29 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.115 2007/04/16 01:14:56 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -115,7 +115,7 @@ init_execution_state(List *queryTree_list, bool readonly_func)
|
|||||||
if (queryTree->commandType == CMD_UTILITY)
|
if (queryTree->commandType == CMD_UTILITY)
|
||||||
stmt = queryTree->utilityStmt;
|
stmt = queryTree->utilityStmt;
|
||||||
else
|
else
|
||||||
stmt = (Node *) pg_plan_query(queryTree, NULL);
|
stmt = (Node *) pg_plan_query(queryTree, 0, NULL);
|
||||||
|
|
||||||
/* Precheck all commands for validity in a function */
|
/* Precheck all commands for validity in a function */
|
||||||
if (IsA(stmt, TransactionStmt))
|
if (IsA(stmt, TransactionStmt))
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.175 2007/03/25 23:42:43 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.176 2007/04/16 01:14:56 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -34,7 +34,8 @@ static int _SPI_stack_depth = 0; /* allocated size of _SPI_stack */
|
|||||||
static int _SPI_connected = -1;
|
static int _SPI_connected = -1;
|
||||||
static int _SPI_curid = -1;
|
static int _SPI_curid = -1;
|
||||||
|
|
||||||
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan);
|
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan,
|
||||||
|
int cursorOptions);
|
||||||
|
|
||||||
static int _SPI_execute_plan(SPIPlanPtr plan,
|
static int _SPI_execute_plan(SPIPlanPtr plan,
|
||||||
Datum *Values, const char *Nulls,
|
Datum *Values, const char *Nulls,
|
||||||
@ -45,8 +46,9 @@ static int _SPI_pquery(QueryDesc *queryDesc, long tcount);
|
|||||||
|
|
||||||
static void _SPI_error_callback(void *arg);
|
static void _SPI_error_callback(void *arg);
|
||||||
|
|
||||||
static void _SPI_cursor_operation(Portal portal, bool forward, long count,
|
static void _SPI_cursor_operation(Portal portal,
|
||||||
DestReceiver *dest);
|
FetchDirection direction, long count,
|
||||||
|
DestReceiver *dest);
|
||||||
|
|
||||||
static SPIPlanPtr _SPI_copy_plan(SPIPlanPtr plan, MemoryContext parentcxt);
|
static SPIPlanPtr _SPI_copy_plan(SPIPlanPtr plan, MemoryContext parentcxt);
|
||||||
static SPIPlanPtr _SPI_save_plan(SPIPlanPtr plan);
|
static SPIPlanPtr _SPI_save_plan(SPIPlanPtr plan);
|
||||||
@ -310,7 +312,7 @@ SPI_execute(const char *src, bool read_only, long tcount)
|
|||||||
memset(&plan, 0, sizeof(_SPI_plan));
|
memset(&plan, 0, sizeof(_SPI_plan));
|
||||||
plan.magic = _SPI_PLAN_MAGIC;
|
plan.magic = _SPI_PLAN_MAGIC;
|
||||||
|
|
||||||
_SPI_prepare_plan(src, &plan);
|
_SPI_prepare_plan(src, &plan, 0);
|
||||||
|
|
||||||
res = _SPI_execute_plan(&plan, NULL, NULL,
|
res = _SPI_execute_plan(&plan, NULL, NULL,
|
||||||
InvalidSnapshot, InvalidSnapshot,
|
InvalidSnapshot, InvalidSnapshot,
|
||||||
@ -398,6 +400,13 @@ SPI_execute_snapshot(SPIPlanPtr plan,
|
|||||||
|
|
||||||
SPIPlanPtr
|
SPIPlanPtr
|
||||||
SPI_prepare(const char *src, int nargs, Oid *argtypes)
|
SPI_prepare(const char *src, int nargs, Oid *argtypes)
|
||||||
|
{
|
||||||
|
return SPI_prepare_cursor(src, nargs, argtypes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIPlanPtr
|
||||||
|
SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
|
||||||
|
int cursorOptions)
|
||||||
{
|
{
|
||||||
_SPI_plan plan;
|
_SPI_plan plan;
|
||||||
SPIPlanPtr result;
|
SPIPlanPtr result;
|
||||||
@ -417,7 +426,7 @@ SPI_prepare(const char *src, int nargs, Oid *argtypes)
|
|||||||
plan.nargs = nargs;
|
plan.nargs = nargs;
|
||||||
plan.argtypes = argtypes;
|
plan.argtypes = argtypes;
|
||||||
|
|
||||||
_SPI_prepare_plan(src, &plan);
|
_SPI_prepare_plan(src, &plan, cursorOptions);
|
||||||
|
|
||||||
/* copy plan to procedure context */
|
/* copy plan to procedure context */
|
||||||
result = _SPI_copy_plan(&plan, _SPI_current->procCxt);
|
result = _SPI_copy_plan(&plan, _SPI_current->procCxt);
|
||||||
@ -1032,7 +1041,8 @@ SPI_cursor_find(const char *name)
|
|||||||
void
|
void
|
||||||
SPI_cursor_fetch(Portal portal, bool forward, long count)
|
SPI_cursor_fetch(Portal portal, bool forward, long count)
|
||||||
{
|
{
|
||||||
_SPI_cursor_operation(portal, forward, count,
|
_SPI_cursor_operation(portal,
|
||||||
|
forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
|
||||||
CreateDestReceiver(DestSPI, NULL));
|
CreateDestReceiver(DestSPI, NULL));
|
||||||
/* we know that the DestSPI receiver doesn't need a destroy call */
|
/* we know that the DestSPI receiver doesn't need a destroy call */
|
||||||
}
|
}
|
||||||
@ -1046,7 +1056,36 @@ SPI_cursor_fetch(Portal portal, bool forward, long count)
|
|||||||
void
|
void
|
||||||
SPI_cursor_move(Portal portal, bool forward, long count)
|
SPI_cursor_move(Portal portal, bool forward, long count)
|
||||||
{
|
{
|
||||||
_SPI_cursor_operation(portal, forward, count, None_Receiver);
|
_SPI_cursor_operation(portal,
|
||||||
|
forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
|
||||||
|
None_Receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SPI_scroll_cursor_fetch()
|
||||||
|
*
|
||||||
|
* Fetch rows in a scrollable cursor
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count)
|
||||||
|
{
|
||||||
|
_SPI_cursor_operation(portal,
|
||||||
|
direction, count,
|
||||||
|
CreateDestReceiver(DestSPI, NULL));
|
||||||
|
/* we know that the DestSPI receiver doesn't need a destroy call */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SPI_scroll_cursor_move()
|
||||||
|
*
|
||||||
|
* Move in a scrollable cursor
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
SPI_scroll_cursor_move(Portal portal, FetchDirection direction, long count)
|
||||||
|
{
|
||||||
|
_SPI_cursor_operation(portal, direction, count, None_Receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1299,7 +1338,7 @@ spi_printtup(TupleTableSlot *slot, DestReceiver *self)
|
|||||||
* and need to be copied somewhere to survive.
|
* and need to be copied somewhere to survive.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
_SPI_prepare_plan(const char *src, SPIPlanPtr plan)
|
_SPI_prepare_plan(const char *src, SPIPlanPtr plan, int cursorOptions)
|
||||||
{
|
{
|
||||||
List *raw_parsetree_list;
|
List *raw_parsetree_list;
|
||||||
List *plancache_list;
|
List *plancache_list;
|
||||||
@ -1345,7 +1384,7 @@ _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
|
|||||||
/* Need a copyObject here to keep parser from modifying raw tree */
|
/* Need a copyObject here to keep parser from modifying raw tree */
|
||||||
stmt_list = pg_analyze_and_rewrite(copyObject(parsetree),
|
stmt_list = pg_analyze_and_rewrite(copyObject(parsetree),
|
||||||
src, argtypes, nargs);
|
src, argtypes, nargs);
|
||||||
stmt_list = pg_plan_queries(stmt_list, NULL, false);
|
stmt_list = pg_plan_queries(stmt_list, cursorOptions, NULL, false);
|
||||||
|
|
||||||
plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
|
plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
|
||||||
cplan = (CachedPlan *) palloc0(sizeof(CachedPlan));
|
cplan = (CachedPlan *) palloc0(sizeof(CachedPlan));
|
||||||
@ -1739,7 +1778,7 @@ _SPI_error_callback(void *arg)
|
|||||||
* Do a FETCH or MOVE in a cursor
|
* Do a FETCH or MOVE in a cursor
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
_SPI_cursor_operation(Portal portal, bool forward, long count,
|
_SPI_cursor_operation(Portal portal, FetchDirection direction, long count,
|
||||||
DestReceiver *dest)
|
DestReceiver *dest)
|
||||||
{
|
{
|
||||||
long nfetched;
|
long nfetched;
|
||||||
@ -1760,7 +1799,7 @@ _SPI_cursor_operation(Portal portal, bool forward, long count,
|
|||||||
|
|
||||||
/* Run the cursor */
|
/* Run the cursor */
|
||||||
nfetched = PortalRunFetch(portal,
|
nfetched = PortalRunFetch(portal,
|
||||||
forward ? FETCH_FORWARD : FETCH_BACKWARD,
|
direction,
|
||||||
count,
|
count,
|
||||||
dest);
|
dest);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.216 2007/02/27 01:11:25 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.217 2007/04/16 01:14:56 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -80,8 +80,7 @@ static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist);
|
|||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
PlannedStmt *
|
PlannedStmt *
|
||||||
planner(Query *parse, bool isCursor, int cursorOptions,
|
planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
|
||||||
ParamListInfo boundParams)
|
|
||||||
{
|
{
|
||||||
PlannedStmt *result;
|
PlannedStmt *result;
|
||||||
PlannerGlobal *glob;
|
PlannerGlobal *glob;
|
||||||
@ -107,7 +106,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
|
|||||||
glob->finalrtable = NIL;
|
glob->finalrtable = NIL;
|
||||||
|
|
||||||
/* Determine what fraction of the plan is likely to be scanned */
|
/* Determine what fraction of the plan is likely to be scanned */
|
||||||
if (isCursor)
|
if (cursorOptions & CURSOR_OPT_FAST_PLAN)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We have no real idea how many tuples the user will ultimately FETCH
|
* We have no real idea how many tuples the user will ultimately FETCH
|
||||||
@ -130,7 +129,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
|
|||||||
* If creating a plan for a scrollable cursor, make sure it can run
|
* If creating a plan for a scrollable cursor, make sure it can run
|
||||||
* backwards on demand. Add a Material node at the top at need.
|
* backwards on demand. Add a Material node at the top at need.
|
||||||
*/
|
*/
|
||||||
if (isCursor && (cursorOptions & CURSOR_OPT_SCROLL))
|
if (cursorOptions & CURSOR_OPT_SCROLL)
|
||||||
{
|
{
|
||||||
if (!ExecSupportsBackwardScan(top_plan))
|
if (!ExecSupportsBackwardScan(top_plan))
|
||||||
top_plan = materialize_finished_plan(top_plan);
|
top_plan = materialize_finished_plan(top_plan);
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.588 2007/04/12 06:53:46 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.589 2007/04/16 01:14:56 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -279,9 +279,9 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
|
|||||||
%type <boolean> opt_freeze opt_default opt_recheck
|
%type <boolean> opt_freeze opt_default opt_recheck
|
||||||
%type <defelt> opt_binary opt_oids copy_delimiter
|
%type <defelt> opt_binary opt_oids copy_delimiter
|
||||||
|
|
||||||
%type <boolean> copy_from opt_hold
|
%type <boolean> copy_from
|
||||||
|
|
||||||
%type <ival> opt_column event cursor_options
|
%type <ival> opt_column event cursor_options opt_hold
|
||||||
%type <objtype> reindex_type drop_type comment_type
|
%type <objtype> reindex_type drop_type comment_type
|
||||||
|
|
||||||
%type <node> fetch_direction select_limit_value select_offset_value
|
%type <node> fetch_direction select_limit_value select_offset_value
|
||||||
@ -5821,10 +5821,9 @@ DeclareCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt
|
|||||||
{
|
{
|
||||||
DeclareCursorStmt *n = makeNode(DeclareCursorStmt);
|
DeclareCursorStmt *n = makeNode(DeclareCursorStmt);
|
||||||
n->portalname = $2;
|
n->portalname = $2;
|
||||||
n->options = $3;
|
/* currently we always set FAST_PLAN option */
|
||||||
|
n->options = $3 | $5 | CURSOR_OPT_FAST_PLAN;
|
||||||
n->query = $7;
|
n->query = $7;
|
||||||
if ($5)
|
|
||||||
n->options |= CURSOR_OPT_HOLD;
|
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -5836,9 +5835,9 @@ cursor_options: /*EMPTY*/ { $$ = 0; }
|
|||||||
| cursor_options INSENSITIVE { $$ = $1 | CURSOR_OPT_INSENSITIVE; }
|
| cursor_options INSENSITIVE { $$ = $1 | CURSOR_OPT_INSENSITIVE; }
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_hold: /* EMPTY */ { $$ = FALSE; }
|
opt_hold: /* EMPTY */ { $$ = 0; }
|
||||||
| WITH HOLD { $$ = TRUE; }
|
| WITH HOLD { $$ = CURSOR_OPT_HOLD; }
|
||||||
| WITHOUT HOLD { $$ = FALSE; }
|
| WITHOUT HOLD { $$ = 0; }
|
||||||
;
|
;
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.530 2007/03/29 19:10:10 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.531 2007/04/16 01:14:57 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* this is the "main" module of the postgres backend and
|
* this is the "main" module of the postgres backend and
|
||||||
@ -656,9 +656,12 @@ pg_rewrite_queries(List *querytree_list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Generate a plan for a single already-rewritten query. */
|
/*
|
||||||
|
* Generate a plan for a single already-rewritten query.
|
||||||
|
* This is a thin wrapper around planner() and takes the same parameters.
|
||||||
|
*/
|
||||||
PlannedStmt *
|
PlannedStmt *
|
||||||
pg_plan_query(Query *querytree, ParamListInfo boundParams)
|
pg_plan_query(Query *querytree, int cursorOptions, ParamListInfo boundParams)
|
||||||
{
|
{
|
||||||
PlannedStmt *plan;
|
PlannedStmt *plan;
|
||||||
|
|
||||||
@ -670,7 +673,7 @@ pg_plan_query(Query *querytree, ParamListInfo boundParams)
|
|||||||
ResetUsage();
|
ResetUsage();
|
||||||
|
|
||||||
/* call the optimizer */
|
/* call the optimizer */
|
||||||
plan = planner(querytree, false, 0, boundParams);
|
plan = planner(querytree, cursorOptions, boundParams);
|
||||||
|
|
||||||
if (log_planner_stats)
|
if (log_planner_stats)
|
||||||
ShowUsage("PLANNER STATISTICS");
|
ShowUsage("PLANNER STATISTICS");
|
||||||
@ -718,7 +721,7 @@ pg_plan_query(Query *querytree, ParamListInfo boundParams)
|
|||||||
* list. Utility statements are simply represented by their statement nodes.
|
* list. Utility statements are simply represented by their statement nodes.
|
||||||
*/
|
*/
|
||||||
List *
|
List *
|
||||||
pg_plan_queries(List *querytrees, ParamListInfo boundParams,
|
pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams,
|
||||||
bool needSnapshot)
|
bool needSnapshot)
|
||||||
{
|
{
|
||||||
List *stmt_list = NIL;
|
List *stmt_list = NIL;
|
||||||
@ -741,7 +744,7 @@ pg_plan_queries(List *querytrees, ParamListInfo boundParams,
|
|||||||
ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
|
ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
|
||||||
needSnapshot = false;
|
needSnapshot = false;
|
||||||
}
|
}
|
||||||
stmt = (Node *) pg_plan_query(query, boundParams);
|
stmt = (Node *) pg_plan_query(query, cursorOptions, boundParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt_list = lappend(stmt_list, stmt);
|
stmt_list = lappend(stmt_list, stmt);
|
||||||
@ -892,7 +895,7 @@ exec_simple_query(const char *query_string)
|
|||||||
querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
|
querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
|
|
||||||
plantree_list = pg_plan_queries(querytree_list, NULL, true);
|
plantree_list = pg_plan_queries(querytree_list, 0, NULL, true);
|
||||||
|
|
||||||
/* If we got a cancel signal in analysis or planning, quit */
|
/* If we got a cancel signal in analysis or planning, quit */
|
||||||
CHECK_FOR_INTERRUPTS();
|
CHECK_FOR_INTERRUPTS();
|
||||||
@ -1207,7 +1210,7 @@ exec_parse_message(const char *query_string, /* string to execute */
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stmt_list = pg_plan_queries(querytree_list, NULL, true);
|
stmt_list = pg_plan_queries(querytree_list, 0, NULL, true);
|
||||||
fully_planned = true;
|
fully_planned = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1621,7 +1624,7 @@ exec_bind_message(StringInfo input_message)
|
|||||||
*/
|
*/
|
||||||
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
|
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
|
||||||
query_list = copyObject(cplan->stmt_list);
|
query_list = copyObject(cplan->stmt_list);
|
||||||
plan_list = pg_plan_queries(query_list, params, true);
|
plan_list = pg_plan_queries(query_list, 0, params, true);
|
||||||
MemoryContextSwitchTo(oldContext);
|
MemoryContextSwitchTo(oldContext);
|
||||||
|
|
||||||
/* We no longer need the cached plan refcount ... */
|
/* We no longer need the cached plan refcount ... */
|
||||||
|
9
src/backend/utils/cache/plancache.c
vendored
9
src/backend/utils/cache/plancache.c
vendored
@ -33,7 +33,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.6 2007/04/12 06:53:47 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.7 2007/04/16 01:14:57 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -458,10 +458,13 @@ RevalidateCachedPlan(CachedPlanSource *plansource, bool useResOwner)
|
|||||||
if (plansource->fully_planned)
|
if (plansource->fully_planned)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Generate plans for queries. Assume snapshot is not set yet
|
* Generate plans for queries. We don't need any boundParams, and
|
||||||
|
* currently we don't need to worry about cursor options because
|
||||||
|
* cursor plans are never saved in the plancache (that might have
|
||||||
|
* to change someday). Also, assume snapshot is not set yet
|
||||||
* (XXX this may be wasteful, won't all callers have done that?)
|
* (XXX this may be wasteful, won't all callers have done that?)
|
||||||
*/
|
*/
|
||||||
slist = pg_plan_queries(slist, NULL, true);
|
slist = pg_plan_queries(slist, 0, NULL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.60 2007/03/25 23:27:59 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.61 2007/04/16 01:14:57 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -20,8 +20,8 @@
|
|||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are not needed by this file, but used by other programs
|
* Most of these are not needed by this file, but may be used by
|
||||||
* using SPI
|
* user-written code that uses SPI
|
||||||
*/
|
*/
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
#include "access/xact.h"
|
#include "access/xact.h"
|
||||||
@ -32,6 +32,7 @@
|
|||||||
#include "executor/executor.h"
|
#include "executor/executor.h"
|
||||||
#include "nodes/execnodes.h"
|
#include "nodes/execnodes.h"
|
||||||
#include "nodes/params.h"
|
#include "nodes/params.h"
|
||||||
|
#include "nodes/parsenodes.h"
|
||||||
#include "nodes/plannodes.h"
|
#include "nodes/plannodes.h"
|
||||||
#include "nodes/primnodes.h"
|
#include "nodes/primnodes.h"
|
||||||
#include "nodes/relation.h"
|
#include "nodes/relation.h"
|
||||||
@ -105,6 +106,8 @@ extern int SPI_execute_snapshot(SPIPlanPtr plan,
|
|||||||
Snapshot crosscheck_snapshot,
|
Snapshot crosscheck_snapshot,
|
||||||
bool read_only, long tcount);
|
bool read_only, long tcount);
|
||||||
extern SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes);
|
extern SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes);
|
||||||
|
extern SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
|
||||||
|
int cursorOptions);
|
||||||
extern SPIPlanPtr SPI_saveplan(SPIPlanPtr plan);
|
extern SPIPlanPtr SPI_saveplan(SPIPlanPtr plan);
|
||||||
extern int SPI_freeplan(SPIPlanPtr plan);
|
extern int SPI_freeplan(SPIPlanPtr plan);
|
||||||
|
|
||||||
@ -136,6 +139,8 @@ extern Portal SPI_cursor_open(const char *name, SPIPlanPtr plan,
|
|||||||
extern Portal SPI_cursor_find(const char *name);
|
extern Portal SPI_cursor_find(const char *name);
|
||||||
extern void SPI_cursor_fetch(Portal portal, bool forward, long count);
|
extern void SPI_cursor_fetch(Portal portal, bool forward, long count);
|
||||||
extern void SPI_cursor_move(Portal portal, bool forward, long count);
|
extern void SPI_cursor_move(Portal portal, bool forward, long count);
|
||||||
|
extern void SPI_scroll_cursor_fetch(Portal, FetchDirection direction, long count);
|
||||||
|
extern void SPI_scroll_cursor_move(Portal, FetchDirection direction, long count);
|
||||||
extern void SPI_cursor_close(Portal portal);
|
extern void SPI_cursor_close(Portal portal);
|
||||||
|
|
||||||
extern void AtEOXact_SPI(bool isCommit);
|
extern void AtEOXact_SPI(bool isCommit);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.345 2007/04/12 06:53:48 neilc Exp $
|
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.346 2007/04/16 01:14:57 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1429,11 +1429,12 @@ typedef struct CommentStmt
|
|||||||
* Declare Cursor Statement
|
* Declare Cursor Statement
|
||||||
* ----------------------
|
* ----------------------
|
||||||
*/
|
*/
|
||||||
#define CURSOR_OPT_BINARY 0x0001
|
#define CURSOR_OPT_BINARY 0x0001 /* BINARY */
|
||||||
#define CURSOR_OPT_SCROLL 0x0002
|
#define CURSOR_OPT_SCROLL 0x0002 /* SCROLL explicitly given */
|
||||||
#define CURSOR_OPT_NO_SCROLL 0x0004
|
#define CURSOR_OPT_NO_SCROLL 0x0004 /* NO SCROLL explicitly given */
|
||||||
#define CURSOR_OPT_INSENSITIVE 0x0008
|
#define CURSOR_OPT_INSENSITIVE 0x0008 /* INSENSITIVE (unimplemented) */
|
||||||
#define CURSOR_OPT_HOLD 0x0010
|
#define CURSOR_OPT_HOLD 0x0010 /* WITH HOLD */
|
||||||
|
#define CURSOR_OPT_FAST_PLAN 0x0020 /* prefer fast-start plan */
|
||||||
|
|
||||||
typedef struct DeclareCursorStmt
|
typedef struct DeclareCursorStmt
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.38 2007/02/20 17:32:17 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.39 2007/04/16 01:14:58 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -18,7 +18,7 @@
|
|||||||
#include "nodes/relation.h"
|
#include "nodes/relation.h"
|
||||||
|
|
||||||
|
|
||||||
extern PlannedStmt *planner(Query *parse, bool isCursor, int cursorOptions,
|
extern PlannedStmt *planner(Query *parse, int cursorOptions,
|
||||||
ParamListInfo boundParams);
|
ParamListInfo boundParams);
|
||||||
extern Plan *subquery_planner(PlannerGlobal *glob, Query *parse,
|
extern Plan *subquery_planner(PlannerGlobal *glob, Query *parse,
|
||||||
Index level, double tuple_fraction,
|
Index level, double tuple_fraction,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.88 2007/03/07 13:35:03 alvherre Exp $
|
* $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.89 2007/04/16 01:14:58 tgl Exp $
|
||||||
*
|
*
|
||||||
* OLD COMMENTS
|
* OLD COMMENTS
|
||||||
* This file was created so that other c files could get the two
|
* This file was created so that other c files could get the two
|
||||||
@ -49,9 +49,10 @@ extern List *pg_parse_and_rewrite(const char *query_string,
|
|||||||
extern List *pg_parse_query(const char *query_string);
|
extern List *pg_parse_query(const char *query_string);
|
||||||
extern List *pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
|
extern List *pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
|
||||||
Oid *paramTypes, int numParams);
|
Oid *paramTypes, int numParams);
|
||||||
extern PlannedStmt *pg_plan_query(Query *querytree, ParamListInfo boundParams);
|
extern PlannedStmt *pg_plan_query(Query *querytree, int cursorOptions,
|
||||||
extern List *pg_plan_queries(List *querytrees, ParamListInfo boundParams,
|
ParamListInfo boundParams);
|
||||||
bool needSnapshot);
|
extern List *pg_plan_queries(List *querytrees, int cursorOptions,
|
||||||
|
ParamListInfo boundParams, bool needSnapshot);
|
||||||
|
|
||||||
extern bool assign_max_stack_depth(int newval, bool doit, GucSource source);
|
extern bool assign_max_stack_depth(int newval, bool doit, GucSource source);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user