mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-30 19:00:29 +08:00
Add a new system view, pg_prepared_statements, that can be used to
access information about the prepared statements that are available in the current session. Original patch from Joachim Wieland, various improvements by Neil Conway. The "statement" column of the view contains the literal query string sent by the client, without any rewriting or pretty printing. This means that prepared statements created via SQL will be prefixed with "PREPARE ... AS ", whereas those prepared via the FE/BE protocol will not. That is unfortunate, but discussion on -patches did not yield an efficient way to improve this, and there is some merit in returning exactly what the client sent to the backend. Catalog version bumped, regression tests updated.
This commit is contained in:
parent
afa8f1971a
commit
44b928e876
@ -1,6 +1,6 @@
|
||||
<!--
|
||||
Documentation of the system catalogs, directed toward PostgreSQL developers
|
||||
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.115 2005/11/04 23:13:59 petere Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.116 2006/01/08 07:00:24 neilc Exp $
|
||||
-->
|
||||
|
||||
<chapter id="catalogs">
|
||||
@ -4372,6 +4372,11 @@
|
||||
<entry>currently held locks</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><link linkend="view-pg-prepared-statements"><structname>pg_prepared_statements</structname></link></entry>
|
||||
<entry>current prepared statements</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><link linkend="view-pg-prepared-xacts"><structname>pg_prepared_xacts</structname></link></entry>
|
||||
<entry>currently prepared transactions</entry>
|
||||
@ -4778,6 +4783,101 @@
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="view-pg-prepared-statements">
|
||||
<title><structname>pg_prepared_statements</structname></title>
|
||||
|
||||
<indexterm zone="view-pg-prepared-statements">
|
||||
<primary>pg_prepared_statements</primary>
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
The <structname>pg_prepared_statements</structname> view displays
|
||||
all the prepared statements that are available in the current
|
||||
session. See <xref linkend="sql-prepare"
|
||||
endterm="sql-prepare-title"> for more information about prepared
|
||||
statements.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<structname>pg_prepared_statements</structname> contains one row
|
||||
for each prepared statement. Rows are added to the view when a new
|
||||
prepared statement is created, and removed when a prepared
|
||||
statement is released (for example, via the <xref
|
||||
linkend="sql-deallocate" endterm="sql-deallocate-title">
|
||||
command).
|
||||
</para>
|
||||
|
||||
<table>
|
||||
<title><structname>pg_prepared_statements</> Columns</title>
|
||||
|
||||
<tgroup cols=4>
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Name</entry>
|
||||
<entry>Type</entry>
|
||||
<entry>References</entry>
|
||||
<entry>Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><structfield>name</structfield></entry>
|
||||
<entry><type>text</type></entry>
|
||||
<entry></entry>
|
||||
<entry>
|
||||
The identifier of the prepared statement.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><structfield>statement</structfield></entry>
|
||||
<entry><type>text</type></entry>
|
||||
<entry></entry>
|
||||
<entry>
|
||||
The query string submitted by the client to create this
|
||||
prepared statement. For prepared statements created via SQL,
|
||||
this is the <command>PREPARE</command> statement submitted by
|
||||
the client. For prepared statements created via the
|
||||
frontend/backend protocol, this is the text of the prepared
|
||||
statement itself.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><structfield>prepare_time</structfield></entry>
|
||||
<entry><type>timestamptz</type></entry>
|
||||
<entry></entry>
|
||||
<entry>
|
||||
The time at which the prepared statement was created.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><structfield>parameter_types</structfield></entry>
|
||||
<entry><type>oid[]</type></entry>
|
||||
<entry></entry>
|
||||
<entry>
|
||||
The expected parameter types for the prepared statement in the form of
|
||||
an array of type OIDs.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><structfield>from_sql</structfield></entry>
|
||||
<entry><type>boolean</type></entry>
|
||||
<entry></entry>
|
||||
<entry>
|
||||
<literal>true</literal> if the prepared statement was created
|
||||
via the <command>PREPARE</command> SQL statement;
|
||||
<literal>false</literal> if the statement was prepared via the
|
||||
frontend/backend protocol.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
The <structname>pg_prepared_statements</structname> view is read only.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="view-pg-prepared-xacts">
|
||||
<title><structname>pg_prepared_xacts</structname></title>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/prepare.sgml,v 1.16 2005/10/15 01:47:12 neilc Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/prepare.sgml,v 1.17 2006/01/08 07:00:25 neilc Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -145,6 +145,11 @@ PREPARE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable c
|
||||
the <xref linkend="sql-analyze" endterm="sql-analyze-title">
|
||||
documentation.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You can see all available prepared statements of a session by querying the
|
||||
<structname>pg_prepared_statements</> system view.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="sql-prepare-examples">
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.22 2005/10/06 02:29:15 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.23 2006/01/08 07:00:25 neilc Exp $
|
||||
*/
|
||||
|
||||
CREATE VIEW pg_roles AS
|
||||
@ -156,6 +156,12 @@ CREATE VIEW pg_prepared_xacts AS
|
||||
LEFT JOIN pg_authid U ON P.ownerid = U.oid
|
||||
LEFT JOIN pg_database D ON P.dbid = D.oid;
|
||||
|
||||
CREATE VIEW pg_prepared_statements AS
|
||||
SELECT P.name, P.statement, P.prepare_time, P.parameter_types, P.from_sql
|
||||
FROM pg_prepared_statement() AS P
|
||||
(name text, statement text, prepare_time timestamptz,
|
||||
parameter_types oid[], from_sql boolean);
|
||||
|
||||
CREATE VIEW pg_settings AS
|
||||
SELECT *
|
||||
FROM pg_show_all_settings() AS A
|
||||
|
@ -10,21 +10,26 @@
|
||||
* Copyright (c) 2002-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.44 2005/12/14 17:06:27 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.45 2006/01/08 07:00:25 neilc Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/explain.h"
|
||||
#include "commands/prepare.h"
|
||||
#include "executor/executor.h"
|
||||
#include "utils/guc.h"
|
||||
#include "funcapi.h"
|
||||
#include "parser/parsetree.h"
|
||||
#include "optimizer/planner.h"
|
||||
#include "rewrite/rewriteHandler.h"
|
||||
#include "tcop/pquery.h"
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "tcop/utility.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/hsearch.h"
|
||||
#include "utils/memutils.h"
|
||||
|
||||
@ -40,6 +45,7 @@ static HTAB *prepared_queries = NULL;
|
||||
static void InitQueryHashTable(void);
|
||||
static ParamListInfo EvaluateParams(EState *estate,
|
||||
List *params, List *argtypes);
|
||||
static Datum build_oid_array(List *oid_list);
|
||||
|
||||
/*
|
||||
* Implements the 'PREPARE' utility statement.
|
||||
@ -114,7 +120,8 @@ PrepareQuery(PrepareStmt *stmt)
|
||||
commandTag,
|
||||
query_list,
|
||||
plan_list,
|
||||
stmt->argtype_oids);
|
||||
stmt->argtype_oids,
|
||||
true);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -298,7 +305,8 @@ StorePreparedStatement(const char *stmt_name,
|
||||
const char *commandTag,
|
||||
List *query_list,
|
||||
List *plan_list,
|
||||
List *argtype_list)
|
||||
List *argtype_list,
|
||||
bool from_sql)
|
||||
{
|
||||
PreparedStatement *entry;
|
||||
MemoryContext oldcxt,
|
||||
@ -361,6 +369,8 @@ StorePreparedStatement(const char *stmt_name,
|
||||
entry->plan_list = plan_list;
|
||||
entry->argtype_list = argtype_list;
|
||||
entry->context = entrycxt;
|
||||
entry->prepare_time = GetCurrentTimestamp();
|
||||
entry->from_sql = from_sql;
|
||||
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
}
|
||||
@ -383,7 +393,7 @@ FetchPreparedStatement(const char *stmt_name, bool throwError)
|
||||
{
|
||||
/*
|
||||
* 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
|
||||
* hash package is picky enough that it needs to be NUL-padded out to
|
||||
* the appropriate length to work correctly.
|
||||
*/
|
||||
StrNCpy(key, stmt_name, sizeof(key));
|
||||
@ -661,3 +671,125 @@ ExplainExecuteQuery(ExplainStmt *stmt, ParamListInfo params,
|
||||
if (estate)
|
||||
FreeExecutorState(estate);
|
||||
}
|
||||
|
||||
/*
|
||||
* This set returning function reads all the prepared statements and
|
||||
* returns a set of (name, statement, prepare_time, param_types).
|
||||
*/
|
||||
Datum
|
||||
pg_prepared_statement(PG_FUNCTION_ARGS)
|
||||
{
|
||||
FuncCallContext *funcctx;
|
||||
HASH_SEQ_STATUS *hash_seq;
|
||||
PreparedStatement *prep_stmt;
|
||||
|
||||
/* stuff done only on the first call of the function */
|
||||
if (SRF_IS_FIRSTCALL())
|
||||
{
|
||||
TupleDesc tupdesc;
|
||||
MemoryContext oldcontext;
|
||||
|
||||
/* create a function context for cross-call persistence */
|
||||
funcctx = SRF_FIRSTCALL_INIT();
|
||||
|
||||
/*
|
||||
* switch to memory context appropriate for multiple function
|
||||
* calls
|
||||
*/
|
||||
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
||||
|
||||
/* allocate memory for user context */
|
||||
if (prepared_queries)
|
||||
{
|
||||
hash_seq = (HASH_SEQ_STATUS *) palloc(sizeof(HASH_SEQ_STATUS));
|
||||
hash_seq_init(hash_seq, prepared_queries);
|
||||
funcctx->user_fctx = (void *) hash_seq;
|
||||
}
|
||||
else
|
||||
funcctx->user_fctx = NULL;
|
||||
|
||||
/*
|
||||
* build tupdesc for result tuples. This must match the
|
||||
* definition of the pg_prepared_statements view in
|
||||
* system_views.sql
|
||||
*/
|
||||
tupdesc = CreateTemplateTupleDesc(5, false);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
|
||||
TEXTOID, -1, 0);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "statement",
|
||||
TEXTOID, -1, 0);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "prepare_time",
|
||||
TIMESTAMPTZOID, -1, 0);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "parameter_types",
|
||||
OIDARRAYOID, -1, 0);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "from_sql",
|
||||
BOOLOID, -1, 0);
|
||||
|
||||
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
}
|
||||
|
||||
/* stuff done on every call of the function */
|
||||
funcctx = SRF_PERCALL_SETUP();
|
||||
hash_seq = (HASH_SEQ_STATUS *) funcctx->user_fctx;
|
||||
|
||||
/* if the hash table is uninitialized, we're done */
|
||||
if (hash_seq == NULL)
|
||||
SRF_RETURN_DONE(funcctx);
|
||||
|
||||
prep_stmt = hash_seq_search(hash_seq);
|
||||
if (prep_stmt)
|
||||
{
|
||||
Datum result;
|
||||
HeapTuple tuple;
|
||||
Datum values[5];
|
||||
bool nulls[5];
|
||||
|
||||
MemSet(nulls, 0, sizeof(nulls));
|
||||
|
||||
values[0] = DirectFunctionCall1(textin,
|
||||
CStringGetDatum(prep_stmt->stmt_name));
|
||||
|
||||
if (prep_stmt->query_string == NULL)
|
||||
nulls[1] = true;
|
||||
else
|
||||
values[1] = DirectFunctionCall1(textin,
|
||||
CStringGetDatum(prep_stmt->query_string));
|
||||
|
||||
values[2] = TimestampTzGetDatum(prep_stmt->prepare_time);
|
||||
values[3] = build_oid_array(prep_stmt->argtype_list);
|
||||
values[4] = BoolGetDatum(prep_stmt->from_sql);
|
||||
|
||||
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
|
||||
result = HeapTupleGetDatum(tuple);
|
||||
SRF_RETURN_NEXT(funcctx, result);
|
||||
}
|
||||
|
||||
SRF_RETURN_DONE(funcctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* This utility function takes a List of Oids, and returns a Datum
|
||||
* pointing to a Postgres array containing those OIDs. The empty list
|
||||
* is returned as a zero-element array, not NULL.
|
||||
*/
|
||||
static Datum
|
||||
build_oid_array(List *oid_list)
|
||||
{
|
||||
ListCell *lc;
|
||||
int len;
|
||||
int i;
|
||||
Datum *tmp_ary;
|
||||
ArrayType *ary;
|
||||
|
||||
len = list_length(oid_list);
|
||||
tmp_ary = (Datum *) palloc(len * sizeof(Datum));
|
||||
|
||||
i = 0;
|
||||
foreach(lc, oid_list)
|
||||
tmp_ary[i++] = ObjectIdGetDatum(lfirst_oid(lc));
|
||||
|
||||
/* XXX: this hardcodes assumptions about the OID type... */
|
||||
ary = construct_array(tmp_ary, len, OIDOID, sizeof(Oid), true, 'i');
|
||||
return PointerGetDatum(ary);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.477 2006/01/05 10:07:45 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.478 2006/01/08 07:00:25 neilc Exp $
|
||||
*
|
||||
* NOTES
|
||||
* this is the "main" module of the postgres backend and
|
||||
@ -55,6 +55,7 @@
|
||||
#include "tcop/pquery.h"
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "tcop/utility.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/flatfiles.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/lsyscache.h"
|
||||
@ -1308,7 +1309,8 @@ exec_parse_message(const char *query_string, /* string to execute */
|
||||
commandTag,
|
||||
querytree_list,
|
||||
plantree_list,
|
||||
param_list);
|
||||
param_list,
|
||||
false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1322,6 +1324,7 @@ exec_parse_message(const char *query_string, /* string to execute */
|
||||
pstmt->query_list = querytree_list;
|
||||
pstmt->plan_list = plantree_list;
|
||||
pstmt->argtype_list = param_list;
|
||||
pstmt->from_sql = false;
|
||||
pstmt->context = unnamed_stmt_context;
|
||||
/* Now the unnamed statement is complete and valid */
|
||||
unnamed_stmt_pstmt = pstmt;
|
||||
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.308 2005/12/28 01:30:01 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.309 2006/01/08 07:00:25 neilc Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200512271
|
||||
#define CATALOG_VERSION_NO 200601081
|
||||
|
||||
#endif
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.389 2005/11/17 22:14:54 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.390 2006/01/08 07:00:25 neilc Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The script catalog/genbki.sh reads this file and generates .bki
|
||||
@ -3617,6 +3617,8 @@ DATA(insert OID = 2508 ( pg_get_constraintdef PGNSP PGUID 12 f f t f s 2 25 "26
|
||||
DESCR("constraint description with pretty-print option");
|
||||
DATA(insert OID = 2509 ( pg_get_expr PGNSP PGUID 12 f f t f s 3 25 "25 26 16" _null_ _null_ _null_ pg_get_expr_ext - _null_ ));
|
||||
DESCR("deparse an encoded expression with pretty-print option");
|
||||
DATA(insert OID = 2510 ( pg_prepared_statement PGNSP PGUID 12 f f t t s 0 2249 "" _null_ _null_ _null_ pg_prepared_statement - _null_ ));
|
||||
DESCR("get the prepared statements for this session");
|
||||
|
||||
/* non-persistent series generator */
|
||||
DATA(insert OID = 1066 ( generate_series PGNSP PGUID 12 f f t t v 3 23 "23 23 23" _null_ _null_ _null_ generate_series_step_int4 - _null_ ));
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.167 2005/11/22 18:17:30 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.168 2006/01/08 07:00:26 neilc Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -406,6 +406,7 @@ DATA(insert OID = 1007 ( _int4 PGNSP PGUID -1 f b t \054 0 23 array_in array_
|
||||
DATA(insert OID = 1008 ( _regproc PGNSP PGUID -1 f b t \054 0 24 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
|
||||
DATA(insert OID = 1009 ( _text PGNSP PGUID -1 f b t \054 0 25 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
|
||||
DATA(insert OID = 1028 ( _oid PGNSP PGUID -1 f b t \054 0 26 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
|
||||
#define OIDARRAYOID 1028
|
||||
DATA(insert OID = 1010 ( _tid PGNSP PGUID -1 f b t \054 0 27 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
|
||||
DATA(insert OID = 1011 ( _xid PGNSP PGUID -1 f b t \054 0 28 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
|
||||
DATA(insert OID = 1012 ( _cid PGNSP PGUID -1 f b t \054 0 29 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* Copyright (c) 2002-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/commands/prepare.h,v 1.16 2005/12/14 17:06:28 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/commands/prepare.h,v 1.17 2006/01/08 07:00:26 neilc Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -30,13 +30,16 @@
|
||||
typedef struct
|
||||
{
|
||||
/* dynahash.c requires key to be first field */
|
||||
char stmt_name[NAMEDATALEN];
|
||||
char *query_string; /* text of query, or NULL */
|
||||
const char *commandTag; /* command tag (a constant!), or NULL */
|
||||
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 */
|
||||
char stmt_name[NAMEDATALEN];
|
||||
char *query_string; /* text of query, or NULL */
|
||||
const char *commandTag; /* command tag (a constant!), or NULL */
|
||||
List *query_list; /* list of queries, rewritten */
|
||||
List *plan_list; /* list of plans */
|
||||
List *argtype_list; /* list of parameter type OIDs */
|
||||
TimestampTz prepare_time; /* the time when the stmt was prepared */
|
||||
bool from_sql; /* stmt prepared via SQL, not
|
||||
* FE/BE protocol? */
|
||||
MemoryContext context; /* context containing this query */
|
||||
} PreparedStatement;
|
||||
|
||||
|
||||
@ -54,7 +57,8 @@ extern void StorePreparedStatement(const char *stmt_name,
|
||||
const char *commandTag,
|
||||
List *query_list,
|
||||
List *plan_list,
|
||||
List *argtype_list);
|
||||
List *argtype_list,
|
||||
bool from_sql);
|
||||
extern PreparedStatement *FetchPreparedStatement(const char *stmt_name,
|
||||
bool throwError);
|
||||
extern void DropPreparedStatement(const char *stmt_name, bool showError);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.268 2005/11/22 18:17:32 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.269 2006/01/08 07:00:26 neilc Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -861,4 +861,7 @@ extern Datum pg_prepared_xact(PG_FUNCTION_ARGS);
|
||||
/* catalog/pg_conversion.c */
|
||||
extern Datum pg_convert_using(PG_FUNCTION_ARGS);
|
||||
|
||||
/* commands/prepare.c */
|
||||
extern Datum pg_prepared_statement(PG_FUNCTION_ARGS);
|
||||
|
||||
#endif /* BUILTINS_H */
|
||||
|
@ -1,9 +1,22 @@
|
||||
-- Regression tests for prepareable statements
|
||||
PREPARE q1 AS SELECT 1;
|
||||
-- Regression tests for prepareable statements. We query the content
|
||||
-- of the pg_prepared_statements view as prepared statements are
|
||||
-- created and removed.
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
name | statement | parameter_types
|
||||
------+-----------+-----------------
|
||||
(0 rows)
|
||||
|
||||
PREPARE q1 AS SELECT 1 AS a;
|
||||
EXECUTE q1;
|
||||
?column?
|
||||
----------
|
||||
1
|
||||
a
|
||||
---
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
name | statement | parameter_types
|
||||
------+------------------------------+-----------------
|
||||
q1 | PREPARE q1 AS SELECT 1 AS a; | {}
|
||||
(1 row)
|
||||
|
||||
-- should fail
|
||||
@ -18,12 +31,41 @@ EXECUTE q1;
|
||||
2
|
||||
(1 row)
|
||||
|
||||
PREPARE q2 AS SELECT 2 AS b;
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
name | statement | parameter_types
|
||||
------+------------------------------+-----------------
|
||||
q1 | PREPARE q1 AS SELECT 2; | {}
|
||||
q2 | PREPARE q2 AS SELECT 2 AS b; | {}
|
||||
(2 rows)
|
||||
|
||||
-- sql92 syntax
|
||||
DEALLOCATE PREPARE q1;
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
name | statement | parameter_types
|
||||
------+------------------------------+-----------------
|
||||
q2 | PREPARE q2 AS SELECT 2 AS b; | {}
|
||||
(1 row)
|
||||
|
||||
DEALLOCATE PREPARE q2;
|
||||
-- the view should return the empty set again
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
name | statement | parameter_types
|
||||
------+-----------+-----------------
|
||||
(0 rows)
|
||||
|
||||
-- parameterized queries
|
||||
PREPARE q2(text) AS
|
||||
SELECT datname, datistemplate, datallowconn
|
||||
FROM pg_database WHERE datname = $1;
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
name | statement | parameter_types
|
||||
------+--------------------------------------------------------------------------------------------------------+-----------------
|
||||
q2 | PREPARE q2(text) AS
|
||||
SELECT datname, datistemplate, datallowconn
|
||||
FROM pg_database WHERE datname = $1; | {25}
|
||||
(1 row)
|
||||
|
||||
EXECUTE q2('regression');
|
||||
datname | datistemplate | datallowconn
|
||||
------------+---------------+--------------
|
||||
@ -33,6 +75,17 @@ 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);
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
name | statement | parameter_types
|
||||
------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------
|
||||
q2 | PREPARE q2(text) AS
|
||||
SELECT datname, datistemplate, datallowconn
|
||||
FROM pg_database WHERE datname = $1; | {25}
|
||||
q3 | 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); | {25,23,701,16,26,21}
|
||||
(2 rows)
|
||||
|
||||
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
|
||||
---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------
|
||||
|
@ -1280,6 +1280,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
|
||||
pg_group | SELECT pg_authid.rolname AS groname, pg_authid.oid AS grosysid, ARRAY(SELECT pg_auth_members.member FROM pg_auth_members WHERE (pg_auth_members.roleid = pg_authid.oid)) AS grolist FROM pg_authid WHERE (NOT pg_authid.rolcanlogin);
|
||||
pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS "tablespace", pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
|
||||
pg_locks | SELECT l.locktype, l."database", l.relation, l.page, l.tuple, l.transactionid, l.classid, l.objid, l.objsubid, l."transaction", l.pid, l."mode", l."granted" FROM pg_lock_status() l(locktype text, "database" oid, relation oid, page integer, tuple smallint, transactionid xid, classid oid, objid oid, objsubid smallint, "transaction" xid, pid integer, "mode" text, "granted" boolean);
|
||||
pg_prepared_statements | SELECT p.name, p."statement", p.prepare_time, p.parameter_types, p.from_sql FROM pg_prepared_statement() p(name text, "statement" text, prepare_time timestamp with time zone, parameter_types oid[], from_sql boolean);
|
||||
pg_prepared_xacts | SELECT p."transaction", p.gid, p."prepared", u.rolname AS "owner", d.datname AS "database" FROM ((pg_prepared_xact() p("transaction" xid, gid text, "prepared" timestamp with time zone, ownerid oid, dbid oid) LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) LEFT JOIN pg_database d ON ((p.dbid = d.oid)));
|
||||
pg_roles | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolinherit, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, pg_authid.rolconnlimit, '********'::text AS rolpassword, pg_authid.rolvaliduntil, pg_authid.rolconfig, pg_authid.oid FROM pg_authid;
|
||||
pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
|
||||
@ -1320,7 +1321,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
|
||||
shoelace_obsolete | SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM shoelace WHERE (NOT (EXISTS (SELECT shoe.shoename FROM shoe WHERE (shoe.slcolor = shoelace.sl_color))));
|
||||
street | SELECT r.name, r.thepath, c.cname FROM ONLY road r, real_city c WHERE (c.outline ## r.thepath);
|
||||
toyemp | SELECT emp.name, emp.age, emp."location", (12 * emp.salary) AS annualsal FROM emp;
|
||||
(44 rows)
|
||||
(45 rows)
|
||||
|
||||
SELECT tablename, rulename, definition FROM pg_rules
|
||||
ORDER BY tablename, rulename;
|
||||
|
@ -1,8 +1,14 @@
|
||||
-- Regression tests for prepareable statements
|
||||
-- Regression tests for prepareable statements. We query the content
|
||||
-- of the pg_prepared_statements view as prepared statements are
|
||||
-- created and removed.
|
||||
|
||||
PREPARE q1 AS SELECT 1;
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
|
||||
PREPARE q1 AS SELECT 1 AS a;
|
||||
EXECUTE q1;
|
||||
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
|
||||
-- should fail
|
||||
PREPARE q1 AS SELECT 2;
|
||||
|
||||
@ -11,19 +17,33 @@ DEALLOCATE q1;
|
||||
PREPARE q1 AS SELECT 2;
|
||||
EXECUTE q1;
|
||||
|
||||
PREPARE q2 AS SELECT 2 AS b;
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
|
||||
-- sql92 syntax
|
||||
DEALLOCATE PREPARE q1;
|
||||
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
|
||||
DEALLOCATE PREPARE q2;
|
||||
-- the view should return the empty set again
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
|
||||
-- parameterized queries
|
||||
PREPARE q2(text) AS
|
||||
SELECT datname, datistemplate, datallowconn
|
||||
FROM pg_database WHERE datname = $1;
|
||||
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
|
||||
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);
|
||||
|
||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
||||
|
||||
EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 500::oid, 4::bigint);
|
||||
|
||||
-- too few params
|
||||
|
Loading…
Reference in New Issue
Block a user