Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
28e82066
Commit
28e82066
authored
Aug 27, 2002
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PREPARE/EXECUTE statements. Patch by Neil Conway, some kibitzing
from Tom Lane.
parent
bc8f725a
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
1512 additions
and
55 deletions
+1512
-55
doc/src/sgml/ref/allfiles.sgml
doc/src/sgml/ref/allfiles.sgml
+4
-1
doc/src/sgml/ref/deallocate.sgml
doc/src/sgml/ref/deallocate.sgml
+137
-0
doc/src/sgml/ref/execute.sgml
doc/src/sgml/ref/execute.sgml
+132
-0
doc/src/sgml/ref/prepare.sgml
doc/src/sgml/ref/prepare.sgml
+209
-0
doc/src/sgml/reference.sgml
doc/src/sgml/reference.sgml
+5
-2
doc/src/sgml/release.sgml
doc/src/sgml/release.sgml
+2
-1
src/backend/commands/Makefile
src/backend/commands/Makefile
+2
-2
src/backend/commands/prepare.c
src/backend/commands/prepare.c
+407
-0
src/backend/nodes/copyfuncs.c
src/backend/nodes/copyfuncs.c
+45
-1
src/backend/nodes/equalfuncs.c
src/backend/nodes/equalfuncs.c
+47
-1
src/backend/parser/analyze.c
src/backend/parser/analyze.c
+139
-1
src/backend/parser/gram.y
src/backend/parser/gram.y
+84
-25
src/backend/parser/keywords.c
src/backend/parser/keywords.c
+3
-1
src/backend/parser/parser.c
src/backend/parser/parser.c
+35
-2
src/backend/tcop/postgres.c
src/backend/tcop/postgres.c
+14
-2
src/backend/tcop/utility.c
src/backend/tcop/utility.c
+16
-9
src/include/commands/prepare.h
src/include/commands/prepare.h
+29
-0
src/include/nodes/nodes.h
src/include/nodes/nodes.h
+4
-1
src/include/nodes/parsenodes.h
src/include/nodes/parsenodes.h
+39
-1
src/include/parser/gramparse.h
src/include/parser/gramparse.h
+4
-3
src/test/regress/expected/prepare.out
src/test/regress/expected/prepare.out
+107
-0
src/test/regress/parallel_schedule
src/test/regress/parallel_schedule
+1
-1
src/test/regress/serial_schedule
src/test/regress/serial_schedule
+2
-1
src/test/regress/sql/prepare.sql
src/test/regress/sql/prepare.sql
+45
-0
No files found.
doc/src/sgml/ref/allfiles.sgml
View file @
28e82066
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.4
7 2002/08/27 03:38:27 momjian
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.4
8 2002/08/27 04:55:07 tgl
Exp $
PostgreSQL documentation
Complete list of usable sgml source files in this directory.
-->
...
...
@@ -71,6 +71,7 @@ Complete list of usable sgml source files in this directory.
<!entity createType system "create_type.sgml">
<!entity createUser system "create_user.sgml">
<!entity createView system "create_view.sgml">
<!entity deallocate system "deallocate.sgml">
<!entity declare system "declare.sgml">
<!entity delete system "delete.sgml">
<!entity dropAggregate system "drop_aggregate.sgml">
...
...
@@ -93,6 +94,7 @@ Complete list of usable sgml source files in this directory.
<!entity dropUser system "drop_user.sgml">
<!entity dropView system "drop_view.sgml">
<!entity end system "end.sgml">
<!entity execute system "execute.sgml">
<!entity explain system "explain.sgml">
<!entity fetch system "fetch.sgml">
<!entity grant system "grant.sgml">
...
...
@@ -102,6 +104,7 @@ Complete list of usable sgml source files in this directory.
<!entity lock system "lock.sgml">
<!entity move system "move.sgml">
<!entity notify system "notify.sgml">
<!entity prepare system "prepare.sgml">
<!entity reindex system "reindex.sgml">
<!entity reset system "reset.sgml">
<!entity revoke system "revoke.sgml">
...
...
doc/src/sgml/ref/deallocate.sgml
0 → 100644
View file @
28e82066
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/deallocate.sgml,v 1.1 2002/08/27 04:55:07 tgl Exp $
PostgreSQL documentation
-->
<refentry id="SQL-DEALLOCATE">
<refmeta>
<refentrytitle id="sql-deallocate-title">DEALLOCATE</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>
DEALLOCATE
</refname>
<refpurpose>
remove a prepared query
</refpurpose>
</refnamediv>
<refsynopsisdiv>
<refsynopsisdivinfo>
<date>2002-08-12</date>
</refsynopsisdivinfo>
<synopsis>
DEALLOCATE [ PREPARE ] <replaceable class="PARAMETER">plan_name</replaceable>
</synopsis>
<refsect2 id="R2-SQL-DEALLOCATE-1">
<refsect2info>
<date>2002-08-12</date>
</refsect2info>
<title>
Inputs
</title>
<para>
<variablelist>
<varlistentry>
<term>PREPARE</term>
<listitem>
<para>
This keyword is ignored.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">plan_name</replaceable></term>
<listitem>
<para>
The name of the prepared query to remove.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect2>
<refsect2 id="R2-SQL-DEALLOCATE-2">
<refsect2info>
<date>2002-08-12</date>
</refsect2info>
<title>
Outputs
</title>
<para>
<variablelist>
<varlistentry>
<term><computeroutput>
<returnvalue>DEALLOCATE</returnvalue>
</computeroutput></term>
<listitem>
<para>
The prepared query was removed successfully.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect2>
</refsynopsisdiv>
<refsect1 id="R1-SQL-DEALLOCATE-1">
<refsect1info>
<date>2002-08-12</date>
</refsect1info>
<title>
Description
</title>
<para>
<command>DEALLOCATE</command> is used to remove a previously
prepared query. If you do not explicitly
<command>DEALLOCATE</command> a prepared query, it is removed when
the session ends.
</para>
<para>
For more information on prepared queries, see <xref
linkend="sql-prepare" endterm="sql-prepare-title">.
</para>
</refsect1>
<refsect1 id="R1-SQL-DEALLOCATE-2">
<title>
Compatibility
</title>
<refsect2 id="R2-SQL-DEALLOCATE-3">
<refsect2info>
<date>2002-08-12</date>
</refsect2info>
<title>
SQL92
</title>
<para>
SQL92 includes a <command>DEALLOCATE</command> statement, but it is
only for use in embedded SQL clients.
</para>
</refsect2>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"../reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:"/usr/lib/sgml/catalog"
sgml-local-ecat-files:nil
End:
-->
doc/src/sgml/ref/execute.sgml
0 → 100644
View file @
28e82066
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/execute.sgml,v 1.1 2002/08/27 04:55:07 tgl Exp $
PostgreSQL documentation
-->
<refentry id="SQL-EXECUTE">
<refmeta>
<refentrytitle id="sql-execute-title">EXECUTE</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>
EXECUTE
</refname>
<refpurpose>
execute a prepared query
</refpurpose>
</refnamediv>
<refsynopsisdiv>
<refsynopsisdivinfo>
<date>2002-08-12</date>
</refsynopsisdivinfo>
<synopsis>
EXECUTE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable class="PARAMETER">parameter</replaceable> [, ...] ) ]
</synopsis>
<refsect2 id="R2-SQL-EXECUTE-1">
<refsect2info>
<date>2002-08-12</date>
</refsect2info>
<title>
Inputs
</title>
<para>
<variablelist>
<varlistentry>
<term><replaceable class="PARAMETER">plan_name</replaceable></term>
<listitem>
<para>
The name of the prepared query to execute.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">parameter</replaceable></term>
<listitem>
<para>
The actual value of a parameter to the prepared query.
This must be an expression yielding a value of a type
compatible with
the data-type specified for this parameter position in the
<command>PREPARE</command> statement that created the prepared
query.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect2>
</refsynopsisdiv>
<refsect1 id="R1-SQL-EXECUTE-1">
<refsect1info>
<date>2002-08-12</date>
</refsect1info>
<title>
Description
</title>
<para>
<command>EXECUTE</command> is used to execute a previously prepared
query. Since prepared queries only exist for the duration of a
session, the prepared query must have been created by a
<command>PREPARE</command> statement executed earlier in the
current session.
</para>
<para>
If the <command>PREPARE</command> statement that created the query
specified some parameters, a compatible set of parameters must be
passed to the <command>EXECUTE</command> statement, or else an
error is raised. Note that (unlike functions) prepared queries are
not overloaded based on the type or number of their parameters: the
name of a prepared query must be unique within a database session.
</para>
<para>
For more information on the creation and usage of prepared queries,
see <xref linkend="sql-prepare" endterm="sql-prepare-title">.
</para>
</refsect1>
<refsect1 id="R1-SQL-EXECUTE-2">
<title>
Compatibility
</title>
<refsect2 id="R2-SQL-EXECUTE-2">
<refsect2info>
<date>2002-08-12</date>
</refsect2info>
<title>
SQL92
</title>
<para>
SQL92 includes an <command>EXECUTE</command> statement, but it is
only for use in embedded SQL clients. The
<command>EXECUTE</command> statement implemented by
<productname>PostgreSQL</productname> also uses a somewhat
different syntax.
</para>
</refsect2>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"../reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:"/usr/lib/sgml/catalog"
sgml-local-ecat-files:nil
End:
-->
doc/src/sgml/ref/prepare.sgml
0 → 100644
View file @
28e82066
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/prepare.sgml,v 1.1 2002/08/27 04:55:07 tgl Exp $
PostgreSQL documentation
-->
<refentry id="SQL-PREPARE">
<refmeta>
<refentrytitle id="sql-prepare-title">PREPARE</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>
PREPARE
</refname>
<refpurpose>
create a prepared query
</refpurpose>
</refnamediv>
<refsynopsisdiv>
<refsynopsisdivinfo>
<date>2002-08-12</date>
</refsynopsisdivinfo>
<synopsis>
PREPARE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable class="PARAMETER">datatype</replaceable> [, ...] ) ] AS <replaceable class="PARAMETER">query</replaceable>
</synopsis>
<refsect2 id="R2-SQL-PREPARE-1">
<refsect2info>
<date>2002-08-12</date>
</refsect2info>
<title>
Inputs
</title>
<para>
<variablelist>
<varlistentry>
<term><replaceable class="PARAMETER">plan_name</replaceable></term>
<listitem>
<para>
An arbitrary name given to this particular prepared query. It
must be unique within a single session, and is used to execute
or remove a previously prepared query.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">datatype</replaceable></term>
<listitem>
<para>
The data-type of a parameter to the prepared query.
To refer to the parameters in the prepared query itself,
use <literal>$1</literal>, <literal>$2</literal>, etc.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect2>
<refsect2 id="R2-SQL-PREPARE-2">
<refsect2info>
<date>2002-08-12</date>
</refsect2info>
<title>
Outputs
</title>
<para>
<variablelist>
<varlistentry>
<term><computeroutput>
<returnvalue>PREPARE</returnvalue>
</computeroutput></term>
<listitem>
<para>
The query has been prepared successfully.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect2>
</refsynopsisdiv>
<refsect1 id="R1-SQL-PREPARE-1">
<refsect1info>
<date>2002-08-12</date>
</refsect1info>
<title>
Description
</title>
<para>
<command>PREPARE</command> creates a prepared query. A prepared
query is a server-side object that can be used to optimize
performance. When the <command>PREPARE</command> statement is
executed, the specified query is parsed, rewritten, and
planned. When a subsequent <command>EXECUTE</command> statement is
issued, the prepared query need only be executed. Thus, the
parsing, rewriting, and planning stages are only performed once,
instead of every time the query is executed.
</para>
<para>
Prepared queries can take parameters: values that are
substituted into the query when it is executed. To specify the
parameters to a prepared query, include a list of data-types with
the <command>PREPARE</command> statement. In the query itself, you
can refer to the parameters by position using
<literal>$1</literal>, <literal>$2</literal>, etc. When executing
the query, specify the actual values for these parameters in the
<command>EXECUTE</command> statement -- refer to <xref
linkend="sql-execute" endterm="sql-execute-title">
for more information.
</para>
<para>
Prepared queries are stored locally (in the current backend), and
only exist for the duration of the current database session. When
the client exits, the prepared query is forgotten, and so it must be
re-created before being used again. This also means that a single
prepared query cannot be used by multiple simultaneous database
clients; however, each client can create their own prepared query
to use.
</para>
<para>
Prepared queries have the largest performance advantage when a
single backend is being used to execute a large number of similar
queries. The performance difference will be particularly
significant if the queries are complex to plan or rewrite. For
example, if the query involves a join of many tables or requires
the application of several rules. If the query is relatively simple
to plan and rewrite but relatively expensive to execute, the
performance advantage of prepared queries will be less noticeable.
</para>
<refsect2 id="R2-SQL-PREPARE-3">
<refsect2info>
<date>2002-08-12</date>
</refsect2info>
<title>
Notes
</title>
<para>
In some situations, the query plan produced by
<productname>PostgreSQL</productname> for a prepared query may be
inferior to the plan produced if the query were submitted and
executed normally. This is because when the query is planned (and
the optimizer attempts to determine the optimal query plan), the
actual values of any parameters specified in the query are
unavailable. <productname>PostgreSQL</productname> collects
statistics on the distribution of data in the table, and can use
constant values in a query to make guesses about the likely
result of executing the query. Since this data is unavailable when
planning prepared queries with parameters, the chosen plan may be
sub-optimal.
</para>
<para>
For more information on query planning and the statistics
collected by <productname>PostgreSQL</productname> for query
optimization purposes, see the <xref linkend="sql-analyze"
endterm="sql-analyze-title"> documentation.
</para>
</refsect2>
</refsect1>
<refsect1 id="R1-SQL-PREPARE-3">
<title>
Compatibility
</title>
<refsect2 id="R2-SQL-PREPARE-4">
<refsect2info>
<date>2002-08-12</date>
</refsect2info>
<title>
SQL92
</title>
<para>
SQL92 includes a <command>PREPARE</command> statement, but it is
only for use in embedded SQL clients. The
<command>PREPARE</command> statement implemented by
<productname>PostgreSQL</productname> also uses a somewhat
different syntax.
</para>
</refsect2>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"../reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:"/usr/lib/sgml/catalog"
sgml-local-ecat-files:nil
End:
-->
doc/src/sgml/reference.sgml
View file @
28e82066
<!-- reference.sgml
$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.3
6 2002/08/27 03:38:27 momjian
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.3
7 2002/08/27 04:55:07 tgl
Exp $
PostgreSQL Reference Manual
-->
...
...
@@ -80,6 +80,7 @@ PostgreSQL Reference Manual
&createType;
&createUser;
&createView;
&deallocate;
&declare;
&delete;
&dropAggregate;
...
...
@@ -98,10 +99,11 @@ PostgreSQL Reference Manual
&dropSequence;
&dropTable;
&dropTrigger;
&dropType
&dropType
;
&dropUser;
&dropView;
&end;
&execute;
&explain;
&fetch;
&grant;
...
...
@@ -111,6 +113,7 @@ PostgreSQL Reference Manual
&lock;
&move;
¬ify;
&prepare;
&reindex;
&reset;
&revoke;
...
...
doc/src/sgml/release.sgml
View file @
28e82066
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.15
1 2002/08/25 14:34:24 momjian
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.15
2 2002/08/27 04:55:07 tgl
Exp $
-->
<appendix id="release">
...
...
@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
worries about funny characters.
-->
<literallayout><![CDATA[
PREPARE statement allows caching query plans for interactive statements
Type OPAQUE is now deprecated in favor of pseudo-types cstring, trigger, etc
Files larger than 2 GB are now supported (if supported by the operating system)
SERIAL no longer implies UNIQUE; specify explicitly if index is wanted
...
...
src/backend/commands/Makefile
View file @
28e82066
...
...
@@ -4,7 +4,7 @@
# Makefile for backend/commands
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.3
0 2002/07/29 22:14:10
tgl Exp $
# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.3
1 2002/08/27 04:55:07
tgl Exp $
#
#-------------------------------------------------------------------------
...
...
@@ -16,7 +16,7 @@ OBJS = aggregatecmds.o analyze.o async.o cluster.o comment.o \
conversioncmds.o copy.o
\
dbcommands.o define.o explain.o functioncmds.o
\
indexcmds.o lockcmds.o operatorcmds.o opclasscmds.o
\
portalcmds.o proclang.o
\
portalcmds.o pr
epare.o pr
oclang.o
\
schemacmds.o sequence.o tablecmds.o trigger.o typecmds.o user.o
\
vacuum.o vacuumlazy.o variable.o view.o
...
...
src/backend/commands/prepare.c
0 → 100644
View file @
28e82066
/*-------------------------------------------------------------------------
*
* prepare.c
* Prepareable SQL statements via PREPARE, EXECUTE and DEALLOCATE
*
* Copyright (c) 2002, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.1 2002/08/27 04:55:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "commands/prepare.h"
#include "executor/executor.h"
#include "utils/guc.h"
#include "optimizer/planner.h"
#include "rewrite/rewriteHandler.h"
#include "tcop/pquery.h"
#include "tcop/tcopprot.h"
#include "tcop/utility.h"
#include "utils/hsearch.h"
#include "utils/memutils.h"
#define HASH_KEY_LEN NAMEDATALEN
/* All the data we need to remember about a stored query */
typedef
struct
{
/* dynahash.c requires key to be first field */
char
key
[
HASH_KEY_LEN
];
List
*
query_list
;
/* list of queries */
List
*
plan_list
;
/* list of plans */
List
*
argtype_list
;
/* list of parameter type OIDs */
MemoryContext
context
;
/* context containing this query */
}
QueryHashEntry
;
/*
* The hash table in which prepared queries are stored. This is
* per-backend: query plans are not shared between backends.
* The keys for this hash table are the arguments to PREPARE
* and EXECUTE ("plan names"); the entries are QueryHashEntry structs.
*/
static
HTAB
*
prepared_queries
=
NULL
;
static
void
InitQueryHashTable
(
void
);
static
void
StoreQuery
(
const
char
*
stmt_name
,
List
*
query_list
,
List
*
plan_list
,
List
*
argtype_list
);
static
QueryHashEntry
*
FetchQuery
(
const
char
*
plan_name
);
static
void
RunQuery
(
QueryDesc
*
qdesc
,
EState
*
state
);
/*
* Implements the 'PREPARE' utility statement.
*/
void
PrepareQuery
(
PrepareStmt
*
stmt
)
{
List
*
plan_list
=
NIL
;
List
*
query_list
,
*
query_list_item
;
if
(
!
stmt
->
name
)
elog
(
ERROR
,
"No statement name given"
);
if
(
stmt
->
query
->
commandType
==
CMD_UTILITY
)
elog
(
ERROR
,
"Utility statements cannot be prepared"
);
/* Rewrite the query. The result could be 0, 1, or many queries. */
query_list
=
QueryRewrite
(
stmt
->
query
);
foreach
(
query_list_item
,
query_list
)
{
Query
*
query
=
(
Query
*
)
lfirst
(
query_list_item
);
Plan
*
plan
;
/* We can't generate plans for utility statements. */
if
(
query
->
commandType
==
CMD_UTILITY
)
plan
=
NULL
;
else
{
/* Call the query planner to generate a plan. */
plan
=
planner
(
query
);
}
plan_list
=
lappend
(
plan_list
,
plan
);
}
StoreQuery
(
stmt
->
name
,
query_list
,
plan_list
,
stmt
->
argtype_oids
);
}
/*
* Implements the 'EXECUTE' utility statement.
*/
void
ExecuteQuery
(
ExecuteStmt
*
stmt
,
CommandDest
outputDest
)
{
QueryHashEntry
*
entry
;
List
*
l
,
*
query_list
,
*
plan_list
;
ParamListInfo
paramLI
=
NULL
;
/* Look it up in the hash table */
entry
=
FetchQuery
(
stmt
->
name
);
/* Make working copies the executor can safely scribble on */
query_list
=
(
List
*
)
copyObject
(
entry
->
query_list
);
plan_list
=
(
List
*
)
copyObject
(
entry
->
plan_list
);
Assert
(
length
(
query_list
)
==
length
(
plan_list
));
/* Evaluate parameters, if any */
if
(
entry
->
argtype_list
!=
NIL
)
{
int
nargs
=
length
(
entry
->
argtype_list
);
int
i
=
0
;
ExprContext
*
econtext
=
MakeExprContext
(
NULL
,
CurrentMemoryContext
);
/* Parser should have caught this error, but check */
if
(
nargs
!=
length
(
stmt
->
params
))
elog
(
ERROR
,
"ExecuteQuery: wrong number of arguments"
);
paramLI
=
(
ParamListInfo
)
palloc
((
nargs
+
1
)
*
sizeof
(
ParamListInfoData
));
MemSet
(
paramLI
,
0
,
(
nargs
+
1
)
*
sizeof
(
ParamListInfoData
));
foreach
(
l
,
stmt
->
params
)
{
Node
*
n
=
lfirst
(
l
);
bool
isNull
;
paramLI
[
i
].
value
=
ExecEvalExprSwitchContext
(
n
,
econtext
,
&
isNull
,
NULL
);
paramLI
[
i
].
kind
=
PARAM_NUM
;
paramLI
[
i
].
id
=
i
+
1
;
paramLI
[
i
].
isnull
=
isNull
;
i
++
;
}
paramLI
[
i
].
kind
=
PARAM_INVALID
;
}
/* Execute each query */
foreach
(
l
,
query_list
)
{
Query
*
query
=
lfirst
(
l
);
Plan
*
plan
=
lfirst
(
plan_list
);
bool
is_last_query
;
plan_list
=
lnext
(
plan_list
);
is_last_query
=
(
plan_list
==
NIL
);
if
(
query
->
commandType
==
CMD_UTILITY
)
ProcessUtility
(
query
->
utilityStmt
,
outputDest
,
NULL
);
else
{
QueryDesc
*
qdesc
;
EState
*
state
;
if
(
Show_executor_stats
)
ResetUsage
();
qdesc
=
CreateQueryDesc
(
query
,
plan
,
outputDest
,
NULL
);
state
=
CreateExecutorState
();
state
->
es_param_list_info
=
paramLI
;
if
(
stmt
->
into
)
{
if
(
qdesc
->
operation
!=
CMD_SELECT
)
elog
(
ERROR
,
"INTO clause specified for non-SELECT query"
);
query
->
into
=
stmt
->
into
;
qdesc
->
dest
=
None
;
}
RunQuery
(
qdesc
,
state
);
if
(
Show_executor_stats
)
ShowUsage
(
"EXECUTOR STATISTICS"
);
}
/*
* If we're processing multiple queries, we need to increment
* the command counter between them. For the last query,
* there's no need to do this, it's done automatically.
*/
if
(
!
is_last_query
)
CommandCounterIncrement
();
}
/* No need to pfree memory, MemoryContext will be reset */
}
/*
* Initialize query hash table upon first use.
*/
static
void
InitQueryHashTable
(
void
)
{
HASHCTL
hash_ctl
;
MemSet
(
&
hash_ctl
,
0
,
sizeof
(
hash_ctl
));
hash_ctl
.
keysize
=
HASH_KEY_LEN
;
hash_ctl
.
entrysize
=
sizeof
(
QueryHashEntry
);
prepared_queries
=
hash_create
(
"Prepared Queries"
,
32
,
&
hash_ctl
,
HASH_ELEM
);
if
(
!
prepared_queries
)
elog
(
ERROR
,
"InitQueryHashTable: unable to create hash table"
);
}
/*
* Store all the data pertaining to a query in the hash table using
* the specified key. A copy of the data is made in a memory context belonging
* to the hash entry, so the caller can dispose of their copy.
*/
static
void
StoreQuery
(
const
char
*
stmt_name
,
List
*
query_list
,
List
*
plan_list
,
List
*
argtype_list
)
{
QueryHashEntry
*
entry
;
MemoryContext
oldcxt
,
entrycxt
;
char
key
[
HASH_KEY_LEN
];
bool
found
;
/* Initialize the hash table, if necessary */
if
(
!
prepared_queries
)
InitQueryHashTable
();
/* Check for pre-existing entry of same name */
/* See notes in FetchQuery */
MemSet
(
key
,
0
,
sizeof
(
key
));
strncpy
(
key
,
stmt_name
,
sizeof
(
key
));
hash_search
(
prepared_queries
,
key
,
HASH_FIND
,
&
found
);
if
(
found
)
elog
(
ERROR
,
"Prepared statement with name
\"
%s
\"
already exists"
,
stmt_name
);
/* Okay. Make a permanent memory context for the hashtable entry */
entrycxt
=
AllocSetContextCreate
(
TopMemoryContext
,
stmt_name
,
1024
,
1024
,
ALLOCSET_DEFAULT_MAXSIZE
);
oldcxt
=
MemoryContextSwitchTo
(
entrycxt
);
/*
* We need to copy the data so that it is stored in the correct
* memory context. Do this before making hashtable entry, so that
* an out-of-memory failure only wastes memory and doesn't leave us
* with an incomplete (ie corrupt) hashtable entry.
*/
query_list
=
(
List
*
)
copyObject
(
query_list
);
plan_list
=
(
List
*
)
copyObject
(
plan_list
);
argtype_list
=
listCopy
(
argtype_list
);
/* Now we can add entry to hash table */
entry
=
(
QueryHashEntry
*
)
hash_search
(
prepared_queries
,
key
,
HASH_ENTER
,
&
found
);
/* Shouldn't get a failure, nor duplicate entry */
if
(
!
entry
||
found
)
elog
(
ERROR
,
"Unable to store prepared statement
\"
%s
\"
!"
,
stmt_name
);
/* Fill in the hash table entry with copied data */
entry
->
query_list
=
query_list
;
entry
->
plan_list
=
plan_list
;
entry
->
argtype_list
=
argtype_list
;
entry
->
context
=
entrycxt
;
MemoryContextSwitchTo
(
oldcxt
);
}
/*
* Lookup an existing query in the hash table.
*/
static
QueryHashEntry
*
FetchQuery
(
const
char
*
plan_name
)
{
char
key
[
HASH_KEY_LEN
];
QueryHashEntry
*
entry
;
/*
* If the hash table hasn't been initialized, it can't be storing
* anything, therefore it couldn't possibly store our plan.
*/
if
(
!
prepared_queries
)
elog
(
ERROR
,
"Prepared statement with name
\"
%s
\"
does not exist"
,
plan_name
);
/*
* We can't just use the statement name as supplied by the user: the
* hash package is picky enough that it needs to be NULL-padded out
* to the appropriate length to work correctly.
*/
MemSet
(
key
,
0
,
sizeof
(
key
));
strncpy
(
key
,
plan_name
,
sizeof
(
key
));
entry
=
(
QueryHashEntry
*
)
hash_search
(
prepared_queries
,
key
,
HASH_FIND
,
NULL
);
if
(
!
entry
)
elog
(
ERROR
,
"Prepared statement with name
\"
%s
\"
does not exist"
,
plan_name
);
return
entry
;
}
/*
* Given a plan name, look up the stored plan (giving error if not found).
* If found, return the list of argument type OIDs.
*/
List
*
FetchQueryParams
(
const
char
*
plan_name
)
{
QueryHashEntry
*
entry
;
entry
=
FetchQuery
(
plan_name
);
return
entry
->
argtype_list
;
}
/*
* Actually execute a prepared query.
*/
static
void
RunQuery
(
QueryDesc
*
qdesc
,
EState
*
state
)
{
TupleDesc
tupdesc
;
tupdesc
=
ExecutorStart
(
qdesc
,
state
);
ExecutorRun
(
qdesc
,
state
,
state
->
es_direction
,
0L
);
ExecutorEnd
(
qdesc
,
state
);
}
/*
* Implements the 'DEALLOCATE' utility statement: deletes the
* specified plan from storage.
*
* The initial part of this routine is identical to FetchQuery(),
* but we repeat the coding because we need to use the key twice.
*/
void
DeallocateQuery
(
DeallocateStmt
*
stmt
)
{
char
key
[
HASH_KEY_LEN
];
QueryHashEntry
*
entry
;
/*
* If the hash table hasn't been initialized, it can't be storing
* anything, therefore it couldn't possibly store our plan.
*/
if
(
!
prepared_queries
)
elog
(
ERROR
,
"Prepared statement with name
\"
%s
\"
does not exist"
,
stmt
->
name
);
/*
* We can't just use the statement name as supplied by the user: the
* hash package is picky enough that it needs to be NULL-padded out
* to the appropriate length to work correctly.
*/
MemSet
(
key
,
0
,
sizeof
(
key
));
strncpy
(
key
,
stmt
->
name
,
sizeof
(
key
));
/*
* First lookup the entry, so we can release all the subsidiary memory
* it has allocated (when it's removed, hash_search() will return
* a dangling pointer, so it needs to be done prior to HASH_REMOVE).
* This requires an extra hash-table lookup, but DEALLOCATE
* isn't exactly a performance bottleneck.
*/
entry
=
(
QueryHashEntry
*
)
hash_search
(
prepared_queries
,
key
,
HASH_FIND
,
NULL
);
if
(
!
entry
)
elog
(
ERROR
,
"Prepared statement with name
\"
%s
\"
does not exist"
,
stmt
->
name
);
/* Flush the context holding the subsidiary data */
if
(
MemoryContextIsValid
(
entry
->
context
))
MemoryContextDelete
(
entry
->
context
);
/* Now we can remove the hash table entry */
hash_search
(
prepared_queries
,
key
,
HASH_REMOVE
,
NULL
);
}
src/backend/nodes/copyfuncs.c
View file @
28e82066
...
...
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.20
6 2002/08/26 17:53:5
7 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.20
7 2002/08/27 04:55:0
7 tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -2647,6 +2647,41 @@ _copyDropCastStmt(DropCastStmt *from)
return
newnode
;
}
static
PrepareStmt
*
_copyPrepareStmt
(
PrepareStmt
*
from
)
{
PrepareStmt
*
newnode
=
makeNode
(
PrepareStmt
);
newnode
->
name
=
pstrdup
(
from
->
name
);
Node_Copy
(
from
,
newnode
,
argtypes
);
newnode
->
argtype_oids
=
listCopy
(
from
->
argtype_oids
);
Node_Copy
(
from
,
newnode
,
query
);
return
newnode
;
}
static
ExecuteStmt
*
_copyExecuteStmt
(
ExecuteStmt
*
from
)
{
ExecuteStmt
*
newnode
=
makeNode
(
ExecuteStmt
);
newnode
->
name
=
pstrdup
(
from
->
name
);
Node_Copy
(
from
,
newnode
,
into
);
Node_Copy
(
from
,
newnode
,
params
);
return
newnode
;
}
static
DeallocateStmt
*
_copyDeallocateStmt
(
DeallocateStmt
*
from
)
{
DeallocateStmt
*
newnode
=
makeNode
(
DeallocateStmt
);
newnode
->
name
=
pstrdup
(
from
->
name
);
return
newnode
;
}
/* ****************************************************************
* pg_list.h copy functions
...
...
@@ -3079,6 +3114,15 @@ copyObject(void *from)
case
T_DropCastStmt
:
retval
=
_copyDropCastStmt
(
from
);
break
;
case
T_PrepareStmt
:
retval
=
_copyPrepareStmt
(
from
);
break
;
case
T_ExecuteStmt
:
retval
=
_copyExecuteStmt
(
from
);
break
;
case
T_DeallocateStmt
:
retval
=
_copyDeallocateStmt
(
from
);
break
;
case
T_A_Expr
:
retval
=
_copyAExpr
(
from
);
...
...
src/backend/nodes/equalfuncs.c
View file @
28e82066
...
...
@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.15
4 2002/08/26 17:53:5
7 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.15
5 2002/08/27 04:55:0
7 tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -1490,6 +1490,43 @@ _equalDropCastStmt(DropCastStmt *a, DropCastStmt *b)
return
true
;
}
static
bool
_equalPrepareStmt
(
PrepareStmt
*
a
,
PrepareStmt
*
b
)
{
if
(
!
equalstr
(
a
->
name
,
b
->
name
))
return
false
;
if
(
!
equal
(
a
->
argtypes
,
b
->
argtypes
))
return
false
;
if
(
!
equali
(
a
->
argtype_oids
,
b
->
argtype_oids
))
return
false
;
if
(
!
equal
(
a
->
query
,
b
->
query
))
return
false
;
return
true
;
}
static
bool
_equalExecuteStmt
(
ExecuteStmt
*
a
,
ExecuteStmt
*
b
)
{
if
(
!
equalstr
(
a
->
name
,
b
->
name
))
return
false
;
if
(
!
equal
(
a
->
into
,
b
->
into
))
return
false
;
if
(
!
equal
(
a
->
params
,
b
->
params
))
return
false
;
return
true
;
}
static
bool
_equalDeallocateStmt
(
DeallocateStmt
*
a
,
DeallocateStmt
*
b
)
{
if
(
!
equalstr
(
a
->
name
,
b
->
name
))
return
false
;
return
true
;
}
static
bool
_equalAExpr
(
A_Expr
*
a
,
A_Expr
*
b
)
{
...
...
@@ -2249,6 +2286,15 @@ equal(void *a, void *b)
case
T_DropCastStmt
:
retval
=
_equalDropCastStmt
(
a
,
b
);
break
;
case
T_PrepareStmt
:
retval
=
_equalPrepareStmt
(
a
,
b
);
break
;
case
T_ExecuteStmt
:
retval
=
_equalExecuteStmt
(
a
,
b
);
break
;
case
T_DeallocateStmt
:
retval
=
_equalDeallocateStmt
(
a
,
b
);
break
;
case
T_A_Expr
:
retval
=
_equalAExpr
(
a
,
b
);
...
...
src/backend/parser/analyze.c
View file @
28e82066
...
...
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.24
3 2002/08/27 03:56:34 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.24
4 2002/08/27 04:55:07 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -20,7 +20,10 @@
#include "catalog/namespace.h"
#include "catalog/pg_index.h"
#include "catalog/pg_type.h"
#include "commands/prepare.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "parser/analyze.h"
#include "parser/gramparse.h"
#include "parser/parsetree.h"
...
...
@@ -94,6 +97,8 @@ static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
static
Query
*
transformSetOperationStmt
(
ParseState
*
pstate
,
SelectStmt
*
stmt
);
static
Node
*
transformSetOperationTree
(
ParseState
*
pstate
,
SelectStmt
*
stmt
);
static
Query
*
transformUpdateStmt
(
ParseState
*
pstate
,
UpdateStmt
*
stmt
);
static
Query
*
transformPrepareStmt
(
ParseState
*
pstate
,
PrepareStmt
*
stmt
);
static
Query
*
transformExecuteStmt
(
ParseState
*
pstate
,
ExecuteStmt
*
stmt
);
static
Query
*
transformCreateStmt
(
ParseState
*
pstate
,
CreateStmt
*
stmt
,
List
**
extras_before
,
List
**
extras_after
);
static
Query
*
transformAlterTableStmt
(
ParseState
*
pstate
,
AlterTableStmt
*
stmt
,
...
...
@@ -277,6 +282,14 @@ transformStmt(ParseState *pstate, Node *parseTree,
extras_before
,
extras_after
);
break
;
case
T_PrepareStmt
:
result
=
transformPrepareStmt
(
pstate
,
(
PrepareStmt
*
)
parseTree
);
break
;
case
T_ExecuteStmt
:
result
=
transformExecuteStmt
(
pstate
,
(
ExecuteStmt
*
)
parseTree
);
break
;
/*
* Optimizable statements
*/
...
...
@@ -2454,6 +2467,131 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
return
qry
;
}
static
Query
*
transformPrepareStmt
(
ParseState
*
pstate
,
PrepareStmt
*
stmt
)
{
Query
*
result
=
makeNode
(
Query
);
List
*
extras_before
=
NIL
,
*
extras_after
=
NIL
;
List
*
argtype_oids
=
NIL
;
/* argtype OIDs in a list */
Oid
*
argtoids
=
NULL
;
/* as an array for parser_param_set */
int
nargs
;
result
->
commandType
=
CMD_UTILITY
;
result
->
utilityStmt
=
(
Node
*
)
stmt
;
/* Transform list of TypeNames to list (and array) of type OIDs */
nargs
=
length
(
stmt
->
argtypes
);
if
(
nargs
)
{
List
*
l
;
int
i
=
0
;
argtoids
=
(
Oid
*
)
palloc
(
nargs
*
sizeof
(
Oid
));
foreach
(
l
,
stmt
->
argtypes
)
{
TypeName
*
tn
=
lfirst
(
l
);
Oid
toid
=
typenameTypeId
(
tn
);
argtype_oids
=
lappendi
(
argtype_oids
,
toid
);
argtoids
[
i
++
]
=
toid
;
}
}
stmt
->
argtype_oids
=
argtype_oids
;
/*
* We need to adjust the parameters expected by the
* rest of the system, so that $1, ... $n are parsed properly.
*
* This is somewhat of a hack; however, the main parser interface
* only allows parameters to be specified when working with a
* raw query string, which is not helpful here.
*/
parser_param_set
(
argtoids
,
nargs
);
stmt
->
query
=
transformStmt
(
pstate
,
(
Node
*
)
stmt
->
query
,
&
extras_before
,
&
extras_after
);
/* Shouldn't get any extras, since grammar only allows OptimizableStmt */
if
(
extras_before
||
extras_after
)
elog
(
ERROR
,
"transformPrepareStmt: internal error"
);
/* Remove links to our local parameters */
parser_param_set
(
NULL
,
0
);
return
result
;
}
static
Query
*
transformExecuteStmt
(
ParseState
*
pstate
,
ExecuteStmt
*
stmt
)
{
Query
*
result
=
makeNode
(
Query
);
List
*
paramtypes
;
result
->
commandType
=
CMD_UTILITY
;
result
->
utilityStmt
=
(
Node
*
)
stmt
;
paramtypes
=
FetchQueryParams
(
stmt
->
name
);
if
(
stmt
->
params
||
paramtypes
)
{
int
nparams
=
length
(
stmt
->
params
);
int
nexpected
=
length
(
paramtypes
);
List
*
l
;
int
i
=
1
;
if
(
nparams
!=
nexpected
)
elog
(
ERROR
,
"Wrong number of parameters, expected %d but got %d"
,
nexpected
,
nparams
);
foreach
(
l
,
stmt
->
params
)
{
Node
*
expr
=
lfirst
(
l
);
Oid
expected_type_id
,
given_type_id
;
expr
=
transformExpr
(
pstate
,
expr
);
/* Cannot contain subselects or aggregates */
if
(
contain_subplans
(
expr
))
elog
(
ERROR
,
"Cannot use subselects in EXECUTE parameters"
);
if
(
contain_agg_clause
(
expr
))
elog
(
ERROR
,
"Cannot use aggregates in EXECUTE parameters"
);
given_type_id
=
exprType
(
expr
);
expected_type_id
=
(
Oid
)
lfirsti
(
paramtypes
);
if
(
given_type_id
!=
expected_type_id
)
{
expr
=
CoerceTargetExpr
(
pstate
,
expr
,
given_type_id
,
expected_type_id
,
-
1
,
false
);
if
(
!
expr
)
elog
(
ERROR
,
"Parameter $%d of type %s cannot be coerced into the expected type %s"
"
\n\t
You will need to rewrite or cast the expression"
,
i
,
format_type_be
(
given_type_id
),
format_type_be
(
expected_type_id
));
}
fix_opids
(
expr
);
lfirst
(
l
)
=
expr
;
paramtypes
=
lnext
(
paramtypes
);
i
++
;
}
}
return
result
;
}
/* exported so planner can check again after rewriting, query pullup, etc */
void
CheckSelectForUpdate
(
Query
*
qry
)
...
...
src/backend/parser/gram.y
View file @
28e82066
...
...
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.36
0 2002/08/19 15:08:47
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.36
1 2002/08/27 04:55:08
tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
...
...
@@ -68,8 +68,6 @@
extern List *parsetree; /* final parse result is delivered here */
static bool QueryIsRule = FALSE;
static Oid *param_type_info;
static int pfunc_num_args;
/*
* If you need access to certain yacc-generated variables and find that
...
...
@@ -149,7 +147,8 @@ static void doNegateFloat(Value *v);
SelectStmt, TransactionStmt, TruncateStmt,
UnlistenStmt, UpdateStmt, VacuumStmt,
VariableResetStmt, VariableSetStmt, VariableShowStmt,
ViewStmt, CheckPointStmt, CreateConversionStmt
ViewStmt, CheckPointStmt, CreateConversionStmt,
DeallocateStmt, PrepareStmt, ExecuteStmt
%type <node> select_no_parens, select_with_parens, select_clause,
simple_select
...
...
@@ -218,7 +217,8 @@ static void doNegateFloat(Value *v);
group_clause, TriggerFuncArgs, select_limit,
opt_select_limit, opclass_item_list, trans_options,
TableFuncElementList, OptTableFuncElementList,
convert_args
convert_args, prep_type_clause, prep_type_list,
execute_param_clause, execute_param_list
%type <range> into_clause, OptTempTableName
...
...
@@ -335,7 +335,7 @@ static void doNegateFloat(Value *v);
CREATEUSER, CROSS, CURRENT_DATE, CURRENT_TIME,
CURRENT_TIMESTAMP, CURRENT_USER, CURSOR, CYCLE,
DATABASE, DAY_P, DEC, DECIMAL, DECLARE, DEFAULT,
DATABASE, DAY_P, DE
ALLOCATE, DE
C, DECIMAL, DECLARE, DEFAULT,
DEFERRABLE, DEFERRED, DEFINER, DELETE_P, DELIMITER, DELIMITERS,
DESC, DISTINCT, DO, DOMAIN_P, DOUBLE, DROP,
...
...
@@ -371,7 +371,7 @@ static void doNegateFloat(Value *v);
ORDER, OUT_P, OUTER_P, OVERLAPS, OVERLAY, OWNER,
PARTIAL, PASSWORD, PATH_P, PENDANT, PLACING, POSITION,
PRECISION, PRIMARY, PRIOR, PRIVILEGES, PROCEDURE,
PRECISION, PR
EPARE, PR
IMARY, PRIOR, PRIVILEGES, PROCEDURE,
PROCEDURAL,
READ, REAL, RECHECK, REFERENCES, REINDEX, RELATIVE, RENAME, REPLACE,
...
...
@@ -490,6 +490,7 @@ stmt :
| CreateTrigStmt
| CreateUserStmt
| ClusterStmt
| DeallocateStmt
| DefineStmt
| DropStmt
| TruncateStmt
...
...
@@ -502,6 +503,7 @@ stmt :
| DropTrigStmt
| DropRuleStmt
| DropUserStmt
| ExecuteStmt
| ExplainStmt
| FetchStmt
| GrantStmt
...
...
@@ -510,6 +512,7 @@ stmt :
| UnlistenStmt
| LockStmt
| NotifyStmt
| PrepareStmt
| ReindexStmt
| RemoveAggrStmt
| RemoveOperStmt
...
...
@@ -3875,6 +3878,77 @@ ExplainStmt:
}
;
/*****************************************************************************
*
* QUERY:
* PREPARE <plan_name> [(args, ...)] AS <query>
*
*****************************************************************************/
PrepareStmt: PREPARE name prep_type_clause AS OptimizableStmt
{
PrepareStmt *n = makeNode(PrepareStmt);
n->name = $2;
n->argtypes = $3;
n->query = (Query *) $5;
$$ = (Node *) n;
}
;
prep_type_clause: '(' prep_type_list ')' { $$ = $2; }
| /* EMPTY */ { $$ = NIL; }
;
prep_type_list: Typename { $$ = makeList1($1); }
| prep_type_list ',' Typename
{ $$ = lappend($1, $3); }
;
/*****************************************************************************
*
* QUERY:
* EXECUTE <plan_name> [(params, ...)] [INTO ...]
*
*****************************************************************************/
ExecuteStmt: EXECUTE name execute_param_clause into_clause
{
ExecuteStmt *n = makeNode(ExecuteStmt);
n->name = $2;
n->params = $3;
n->into = $4;
$$ = (Node *) n;
}
;
execute_param_clause: '(' execute_param_list ')' { $$ = $2; }
| /* EMPTY */ { $$ = NIL; }
;
execute_param_list: a_expr { $$ = makeList1($1); }
| execute_param_list ',' a_expr { $$ = lappend($1, $3); }
;
/*****************************************************************************
*
* QUERY:
* DEALLOCATE [PREPARE] <plan_name>
*
*****************************************************************************/
DeallocateStmt: DEALLOCATE name
{
DeallocateStmt *n = makeNode(DeallocateStmt);
n->name = $2;
$$ = (Node *) n;
}
| DEALLOCATE PREPARE name
{
DeallocateStmt *n = makeNode(DeallocateStmt);
n->name = $3;
$$ = (Node *) n;
}
;
/*****************************************************************************
* *
...
...
@@ -6947,6 +7021,7 @@ unreserved_keyword:
| CYCLE
| DATABASE
| DAY_P
| DEALLOCATE
| DECLARE
| DEFERRED
| DEFINER
...
...
@@ -7019,6 +7094,7 @@ unreserved_keyword:
| PATH_P
| PENDANT
| PRECISION
| PREPARE
| PRIOR
| PRIVILEGES
| PROCEDURAL
...
...
@@ -7589,26 +7665,9 @@ SystemTypeName(char *name)
* Initialize to parse one query string
*/
void
parser_init(
Oid *typev, int nargs
)
parser_init(
void
)
{
QueryIsRule = FALSE;
/*
* Keep enough information around to fill out the type of param nodes
* used in postquel functions
*/
param_type_info = typev;
pfunc_num_args = nargs;
}
/* param_type()
* Fetch a parameter type previously passed to parser_init
*/
Oid
param_type(int t)
{
if ((t > pfunc_num_args) || (t <= 0))
return InvalidOid;
return param_type_info[t - 1];
}
/* exprIsNullConstant()
...
...
src/backend/parser/keywords.c
View file @
28e82066
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.12
5 2002/08/18 09:36:25 petere
Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.12
6 2002/08/27 04:55:09 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -96,6 +96,7 @@ static const ScanKeyword ScanKeywords[] = {
{
"cycle"
,
CYCLE
},
{
"database"
,
DATABASE
},
{
"day"
,
DAY_P
},
{
"deallocate"
,
DEALLOCATE
},
{
"dec"
,
DEC
},
{
"decimal"
,
DECIMAL
},
{
"declare"
,
DECLARE
},
...
...
@@ -229,6 +230,7 @@ static const ScanKeyword ScanKeywords[] = {
{
"placing"
,
PLACING
},
{
"position"
,
POSITION
},
{
"precision"
,
PRECISION
},
{
"prepare"
,
PREPARE
},
{
"primary"
,
PRIMARY
},
{
"prior"
,
PRIOR
},
{
"privileges"
,
PRIVILEGES
},
...
...
src/backend/parser/parser.c
View file @
28e82066
...
...
@@ -14,7 +14,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.5
3 2002/06/20 20:29:33 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.5
4 2002/08/27 04:55:11 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -30,6 +30,9 @@
List
*
parsetree
;
/* result of parsing is left here */
static
Oid
*
param_type_info
;
/* state for param_type() */
static
int
param_count
;
static
int
lookahead_token
;
/* one-token lookahead */
static
bool
have_lookahead
;
/* lookahead_token set? */
...
...
@@ -50,8 +53,9 @@ parser(StringInfo str, Oid *typev, int nargs)
have_lookahead
=
false
;
scanner_init
(
str
);
parser_init
(
typev
,
nargs
);
parser_init
();
parse_expr_init
();
parser_param_set
(
typev
,
nargs
);
yyresult
=
yyparse
();
...
...
@@ -65,6 +69,35 @@ parser(StringInfo str, Oid *typev, int nargs)
}
/*
* Save information needed to fill out the type of Param references ($n)
*
* This is used for SQL functions, PREPARE statements, etc. It's split
* out from parser() setup because PREPARE needs to change the info after
* the grammar runs and before parse analysis is done on the preparable
* query.
*/
void
parser_param_set
(
Oid
*
typev
,
int
nargs
)
{
param_type_info
=
typev
;
param_count
=
nargs
;
}
/*
* param_type()
*
* Fetch a parameter type previously passed to parser_param_set
*/
Oid
param_type
(
int
t
)
{
if
(
t
>
param_count
||
t
<=
0
)
return
InvalidOid
;
return
param_type_info
[
t
-
1
];
}
/*
* Intermediate filter between parser and base lexer (base_yylex in scan.l).
*
...
...
src/backend/tcop/postgres.c
View file @
28e82066
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.28
3 2002/08/17 15:12:07 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.28
4 2002/08/27 04:55:11 tgl
Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
...
...
@@ -1666,7 +1666,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if
(
!
IsUnderPostmaster
)
{
puts
(
"
\n
POSTGRES backend interactive interface "
);
puts
(
"$Revision: 1.28
3 $ $Date: 2002/08/17 15:12:07
$
\n
"
);
puts
(
"$Revision: 1.28
4 $ $Date: 2002/08/27 04:55:11
$
\n
"
);
}
/*
...
...
@@ -2406,6 +2406,18 @@ CreateCommandTag(Node *parsetree)
tag
=
"DROP OPERATOR CLASS"
;
break
;
case
T_PrepareStmt
:
tag
=
"PREPARE"
;
break
;
case
T_ExecuteStmt
:
tag
=
"EXECUTE"
;
break
;
case
T_DeallocateStmt
:
tag
=
"DEALLOCATE"
;
break
;
default:
elog
(
LOG
,
"CreateCommandTag: unknown parse node type %d"
,
nodeTag
(
parsetree
));
...
...
src/backend/tcop/utility.c
View file @
28e82066
...
...
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.17
2 2002/08/17 13:04:15 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.17
3 2002/08/27 04:55:11 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -30,6 +30,7 @@
#include "commands/explain.h"
#include "commands/lockcmds.h"
#include "commands/portalcmds.h"
#include "commands/prepare.h"
#include "commands/proclang.h"
#include "commands/schemacmds.h"
#include "commands/sequence.h"
...
...
@@ -379,6 +380,18 @@ ProcessUtility(Node *parsetree,
}
break
;
case
T_PrepareStmt
:
PrepareQuery
((
PrepareStmt
*
)
parsetree
);
break
;
case
T_ExecuteStmt
:
ExecuteQuery
((
ExecuteStmt
*
)
parsetree
,
dest
);
break
;
case
T_DeallocateStmt
:
DeallocateQuery
((
DeallocateStmt
*
)
parsetree
);
break
;
/*
* schema
*/
...
...
@@ -541,11 +554,7 @@ ProcessUtility(Node *parsetree,
case
T_GrantStmt
:
{
GrantStmt
*
stmt
=
(
GrantStmt
*
)
parsetree
;
ExecuteGrantStmt
(
stmt
);
}
ExecuteGrantStmt
((
GrantStmt
*
)
parsetree
);
break
;
/*
...
...
@@ -841,9 +850,7 @@ ProcessUtility(Node *parsetree,
break
;
case
T_CreateConversionStmt
:
{
CreateConversionCommand
((
CreateConversionStmt
*
)
parsetree
);
}
CreateConversionCommand
((
CreateConversionStmt
*
)
parsetree
);
break
;
case
T_CreateCastStmt
:
...
...
src/include/commands/prepare.h
0 → 100644
View file @
28e82066
/*-------------------------------------------------------------------------
*
* prepare.h
* PREPARE, EXECUTE and DEALLOCATE command prototypes
*
*
* Copyright (c) 2002, PostgreSQL Global Development Group
*
* $Id: prepare.h,v 1.1 2002/08/27 04:55:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PREPARE_H
#define PREPARE_H
#include "nodes/parsenodes.h"
#include "tcop/dest.h"
extern
void
PrepareQuery
(
PrepareStmt
*
stmt
);
extern
void
ExecuteQuery
(
ExecuteStmt
*
stmt
,
CommandDest
outputDest
);
extern
void
DeallocateQuery
(
DeallocateStmt
*
stmt
);
extern
List
*
FetchQueryParams
(
const
char
*
plan_name
);
#endif
/* PREPARE_H */
src/include/nodes/nodes.h
View file @
28e82066
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: nodes.h,v 1.11
6 2002/08/19 15:08:47
tgl Exp $
* $Id: nodes.h,v 1.11
7 2002/08/27 04:55:11
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -200,6 +200,9 @@ typedef enum NodeTag
T_DropCastStmt
,
T_CreateOpClassStmt
,
T_RemoveOpClassStmt
,
T_PrepareStmt
,
T_ExecuteStmt
,
T_DeallocateStmt
,
T_A_Expr
=
700
,
T_ColumnRef
,
...
...
src/include/nodes/parsenodes.h
View file @
28e82066
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: parsenodes.h,v 1.20
1 2002/08/19 15:08:47
tgl Exp $
* $Id: parsenodes.h,v 1.20
2 2002/08/27 04:55:12
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -1620,4 +1620,42 @@ typedef struct DropCastStmt
}
DropCastStmt
;
/* ----------------------
* PREPARE Statement
* ----------------------
*/
typedef
struct
PrepareStmt
{
NodeTag
type
;
char
*
name
;
/* Name of plan, arbitrary */
List
*
argtypes
;
/* Types of parameters (TypeNames) */
List
*
argtype_oids
;
/* Types of parameters (OIDs) */
Query
*
query
;
/* The query itself */
}
PrepareStmt
;
/* ----------------------
* EXECUTE Statement
* ----------------------
*/
typedef
struct
ExecuteStmt
{
NodeTag
type
;
char
*
name
;
/* The name of the plan to execute */
RangeVar
*
into
;
/* Optional table to store results in */
List
*
params
;
/* Values to assign to parameters */
}
ExecuteStmt
;
/* ----------------------
* DEALLOCATE Statement
* ----------------------
*/
typedef
struct
DeallocateStmt
{
NodeTag
type
;
char
*
name
;
/* The name of the plan to remove */
}
DeallocateStmt
;
#endif
/* PARSENODES_H */
src/include/parser/gramparse.h
View file @
28e82066
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: gramparse.h,v 1.2
3 2002/06/20 20:29:51 momjian
Exp $
* $Id: gramparse.h,v 1.2
4 2002/08/27 04:55:12 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -19,6 +19,8 @@
#include "nodes/parsenodes.h"
/* from parser.c */
extern
void
parser_param_set
(
Oid
*
typev
,
int
nargs
);
extern
Oid
param_type
(
int
t
);
extern
int
yylex
(
void
);
/* from scan.l */
...
...
@@ -28,8 +30,7 @@ extern int base_yylex(void);
extern
void
yyerror
(
const
char
*
message
);
/* from gram.y */
extern
void
parser_init
(
Oid
*
typev
,
int
nargs
);
extern
Oid
param_type
(
int
t
);
extern
void
parser_init
(
void
);
extern
int
yyparse
(
void
);
extern
List
*
SystemFuncName
(
char
*
name
);
extern
TypeName
*
SystemTypeName
(
char
*
name
);
...
...
src/test/regress/expected/prepare.out
0 → 100644
View file @
28e82066
-- Regression tests for prepareable statements
PREPARE q1 AS SELECT 1;
EXECUTE q1;
?column?
----------
1
(1 row)
-- should fail
PREPARE q1 AS SELECT 2;
ERROR: Prepared statement with name "q1" already exists
-- should succeed
DEALLOCATE q1;
PREPARE q1 AS SELECT 2;
EXECUTE q1;
?column?
----------
2
(1 row)
-- sql92 syntax
DEALLOCATE PREPARE q1;
-- parameterized queries
PREPARE q2(text) AS
SELECT datname, datistemplate, datallowconn
FROM pg_database WHERE datname = $1;
EXECUTE q2('regression');
datname | datistemplate | datallowconn
------------+---------------+--------------
regression | f | t
(1 row)
PREPARE q3(text, int, float, boolean, oid, smallint) AS
SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR
ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int);
EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 500::oid, 4::bigint);
unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4
---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------
4502 | 412 | 0 | 2 | 2 | 2 | 2 | 502 | 502 | 4502 | 4502 | 4 | 5 | ERAAAA | WPAAAA | AAAAxx
102 | 612 | 0 | 2 | 2 | 2 | 2 | 102 | 102 | 102 | 102 | 4 | 5 | YDAAAA | OXAAAA | AAAAxx
7602 | 1040 | 0 | 2 | 2 | 2 | 2 | 602 | 1602 | 2602 | 7602 | 4 | 5 | KGAAAA | AOBAAA | AAAAxx
902 | 1104 | 0 | 2 | 2 | 2 | 2 | 902 | 902 | 902 | 902 | 4 | 5 | SIAAAA | MQBAAA | AAAAxx
4902 | 1600 | 0 | 2 | 2 | 2 | 2 | 902 | 902 | 4902 | 4902 | 4 | 5 | OGAAAA | OJCAAA | AAAAxx
9502 | 1812 | 0 | 2 | 2 | 2 | 2 | 502 | 1502 | 4502 | 9502 | 4 | 5 | MBAAAA | SRCAAA | AAAAxx
4702 | 2520 | 0 | 2 | 2 | 2 | 2 | 702 | 702 | 4702 | 4702 | 4 | 5 | WYAAAA | YSDAAA | AAAAxx
1002 | 2580 | 0 | 2 | 2 | 2 | 2 | 2 | 1002 | 1002 | 1002 | 4 | 5 | OMAAAA | GVDAAA | AAAAxx
2 | 2716 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 4 | 5 | CAAAAA | MAEAAA | AAAAxx
802 | 2908 | 0 | 2 | 2 | 2 | 2 | 802 | 802 | 802 | 802 | 4 | 5 | WEAAAA | WHEAAA | AAAAxx
6402 | 3808 | 0 | 2 | 2 | 2 | 2 | 402 | 402 | 1402 | 6402 | 4 | 5 | GMAAAA | MQFAAA | AAAAxx
8602 | 5440 | 0 | 2 | 2 | 2 | 2 | 602 | 602 | 3602 | 8602 | 4 | 5 | WSAAAA | GBIAAA | AAAAxx
8402 | 5708 | 0 | 2 | 2 | 2 | 2 | 402 | 402 | 3402 | 8402 | 4 | 5 | ELAAAA | OLIAAA | AAAAxx
2102 | 6184 | 0 | 2 | 2 | 2 | 2 | 102 | 102 | 2102 | 2102 | 4 | 5 | WCAAAA | WDJAAA | AAAAxx
4202 | 6628 | 0 | 2 | 2 | 2 | 2 | 202 | 202 | 4202 | 4202 | 4 | 5 | QFAAAA | YUJAAA | AAAAxx
2902 | 6816 | 0 | 2 | 2 | 2 | 2 | 902 | 902 | 2902 | 2902 | 4 | 5 | QHAAAA | ECKAAA | AAAAxx
2302 | 7112 | 0 | 2 | 2 | 2 | 2 | 302 | 302 | 2302 | 2302 | 4 | 5 | OKAAAA | ONKAAA | AAAAxx
3202 | 7128 | 0 | 2 | 2 | 2 | 2 | 202 | 1202 | 3202 | 3202 | 4 | 5 | ETAAAA | EOKAAA | AAAAxx
7802 | 7508 | 0 | 2 | 2 | 2 | 2 | 802 | 1802 | 2802 | 7802 | 4 | 5 | COAAAA | UCLAAA | AAAAxx
4102 | 7676 | 0 | 2 | 2 | 2 | 2 | 102 | 102 | 4102 | 4102 | 4 | 5 | UBAAAA | GJLAAA | AAAAxx
8302 | 7800 | 0 | 2 | 2 | 2 | 2 | 302 | 302 | 3302 | 8302 | 4 | 5 | IHAAAA | AOLAAA | AAAAxx
1702 | 7940 | 0 | 2 | 2 | 2 | 2 | 702 | 1702 | 1702 | 1702 | 4 | 5 | MNAAAA | KTLAAA | AAAAxx
2202 | 8028 | 0 | 2 | 2 | 2 | 2 | 202 | 202 | 2202 | 2202 | 4 | 5 | SGAAAA | UWLAAA | AAAAxx
1602 | 8148 | 0 | 2 | 2 | 2 | 2 | 602 | 1602 | 1602 | 1602 | 4 | 5 | QJAAAA | KBMAAA | AAAAxx
5602 | 8796 | 0 | 2 | 2 | 2 | 2 | 602 | 1602 | 602 | 5602 | 4 | 5 | MHAAAA | IANAAA | AAAAxx
6002 | 8932 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 1002 | 6002 | 4 | 5 | WWAAAA | OFNAAA | AAAAxx
3902 | 9224 | 0 | 2 | 2 | 2 | 2 | 902 | 1902 | 3902 | 3902 | 4 | 5 | CUAAAA | UQNAAA | AAAAxx
9602 | 9972 | 0 | 2 | 2 | 2 | 2 | 602 | 1602 | 4602 | 9602 | 4 | 5 | IFAAAA | OTOAAA | AAAAxx
8002 | 9980 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 3002 | 8002 | 4 | 5 | UVAAAA | WTOAAA | AAAAxx
(29 rows)
-- too few params
EXECUTE q3('bool');
ERROR: Wrong number of parameters, expected 6 but got 1
-- too many params
EXECUTE q3('bytea', 5::smallint, 10.5::float, false, 500::oid, 4::bigint, true);
ERROR: Wrong number of parameters, expected 6 but got 7
-- wrong param types
EXECUTE q3(5::smallint, 10.5::float, false, 500::oid, 4::bigint, 'bytea');
ERROR: Parameter $2 of type double precision cannot be coerced into the expected type integer
You will need to rewrite or cast the expression
-- invalid type
PREPARE q4(nonexistenttype) AS SELECT $1;
ERROR: Type "nonexistenttype" does not exist
-- execute into
PREPARE q5(int, text) AS
SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2;
EXECUTE q5(200, 'DTAAAA') INTO TEMPORARY q5_prep_results;
SELECT * FROM q5_prep_results;
unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4
---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------
2525 | 64 | 1 | 1 | 5 | 5 | 25 | 525 | 525 | 2525 | 2525 | 50 | 51 | DTAAAA | MCAAAA | AAAAxx
7257 | 1895 | 1 | 1 | 7 | 17 | 57 | 257 | 1257 | 2257 | 7257 | 114 | 115 | DTAAAA | XUCAAA | VVVVxx
9961 | 2058 | 1 | 1 | 1 | 1 | 61 | 961 | 1961 | 4961 | 9961 | 122 | 123 | DTAAAA | EBDAAA | OOOOxx
3877 | 4060 | 1 | 1 | 7 | 17 | 77 | 877 | 1877 | 3877 | 3877 | 154 | 155 | DTAAAA | EAGAAA | AAAAxx
4553 | 4113 | 1 | 1 | 3 | 13 | 53 | 553 | 553 | 4553 | 4553 | 106 | 107 | DTAAAA | FCGAAA | HHHHxx
7933 | 4514 | 1 | 1 | 3 | 13 | 33 | 933 | 1933 | 2933 | 7933 | 66 | 67 | DTAAAA | QRGAAA | OOOOxx
6581 | 4686 | 1 | 1 | 1 | 1 | 81 | 581 | 581 | 1581 | 6581 | 162 | 163 | DTAAAA | GYGAAA | OOOOxx
8609 | 5918 | 1 | 1 | 9 | 9 | 9 | 609 | 609 | 3609 | 8609 | 18 | 19 | DTAAAA | QTIAAA | OOOOxx
5229 | 6407 | 1 | 1 | 9 | 9 | 29 | 229 | 1229 | 229 | 5229 | 58 | 59 | DTAAAA | LMJAAA | VVVVxx
1173 | 6699 | 1 | 1 | 3 | 13 | 73 | 173 | 1173 | 1173 | 1173 | 146 | 147 | DTAAAA | RXJAAA | VVVVxx
3201 | 7309 | 1 | 1 | 1 | 1 | 1 | 201 | 1201 | 3201 | 3201 | 2 | 3 | DTAAAA | DVKAAA | HHHHxx
1849 | 8143 | 1 | 1 | 9 | 9 | 49 | 849 | 1849 | 1849 | 1849 | 98 | 99 | DTAAAA | FBMAAA | VVVVxx
9285 | 8469 | 1 | 1 | 5 | 5 | 85 | 285 | 1285 | 4285 | 9285 | 170 | 171 | DTAAAA | TNMAAA | HHHHxx
497 | 9092 | 1 | 1 | 7 | 17 | 97 | 497 | 497 | 497 | 497 | 194 | 195 | DTAAAA | SLNAAA | AAAAxx
200 | 9441 | 0 | 0 | 0 | 0 | 0 | 200 | 200 | 200 | 200 | 0 | 1 | SHAAAA | DZNAAA | HHHHxx
5905 | 9537 | 1 | 1 | 5 | 5 | 5 | 905 | 1905 | 905 | 5905 | 10 | 11 | DTAAAA | VCOAAA | HHHHxx
(16 rows)
src/test/regress/parallel_schedule
View file @
28e82066
...
...
@@ -74,4 +74,4 @@ test: select_views alter_table portals_p2 rules foreign_key cluster
# The sixth group of parallel test
# ----------
# "plpgsql" cannot run concurrently with "rules"
test: limit plpgsql
temp domain rangefuncs copy2 conversion without_oid
truncate
test: limit plpgsql
copy2 temp domain rangefuncs prepare without_oid conversion
truncate
src/test/regress/serial_schedule
View file @
28e82066
# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.1
6 2002/08/22 04:51:06 momjian
Exp $
# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.1
7 2002/08/27 04:55:12 tgl
Exp $
# This should probably be in an order similar to parallel_schedule.
test: boolean
test: char
...
...
@@ -86,6 +86,7 @@ test: copy2
test: temp
test: domain
test: rangefuncs
test: prepare
test: without_oid
test: conversion
test: truncate
src/test/regress/sql/prepare.sql
0 → 100644
View file @
28e82066
-- Regression tests for prepareable statements
PREPARE
q1
AS
SELECT
1
;
EXECUTE
q1
;
-- should fail
PREPARE
q1
AS
SELECT
2
;
-- should succeed
DEALLOCATE
q1
;
PREPARE
q1
AS
SELECT
2
;
EXECUTE
q1
;
-- sql92 syntax
DEALLOCATE
PREPARE
q1
;
-- parameterized queries
PREPARE
q2
(
text
)
AS
SELECT
datname
,
datistemplate
,
datallowconn
FROM
pg_database
WHERE
datname
=
$
1
;
EXECUTE
q2
(
'regression'
);
PREPARE
q3
(
text
,
int
,
float
,
boolean
,
oid
,
smallint
)
AS
SELECT
*
FROM
tenk1
WHERE
string4
=
$
1
AND
(
four
=
$
2
OR
ten
=
$
3
::
bigint
OR
true
=
$
4
OR
oid
=
$
5
OR
odd
=
$
6
::
int
);
EXECUTE
q3
(
'AAAAxx'
,
5
::
smallint
,
10
.
5
::
float
,
false
,
500
::
oid
,
4
::
bigint
);
-- too few params
EXECUTE
q3
(
'bool'
);
-- too many params
EXECUTE
q3
(
'bytea'
,
5
::
smallint
,
10
.
5
::
float
,
false
,
500
::
oid
,
4
::
bigint
,
true
);
-- wrong param types
EXECUTE
q3
(
5
::
smallint
,
10
.
5
::
float
,
false
,
500
::
oid
,
4
::
bigint
,
'bytea'
);
-- invalid type
PREPARE
q4
(
nonexistenttype
)
AS
SELECT
$
1
;
-- execute into
PREPARE
q5
(
int
,
text
)
AS
SELECT
*
FROM
tenk1
WHERE
unique1
=
$
1
OR
stringu1
=
$
2
;
EXECUTE
q5
(
200
,
'DTAAAA'
)
INTO
TEMPORARY
q5_prep_results
;
SELECT
*
FROM
q5_prep_results
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment