From d13e903beaecd45a3721e4c2a7f9ff842ce94a79 Mon Sep 17 00:00:00 2001 From: Neil Conway Date: Thu, 12 Apr 2007 06:53:49 +0000 Subject: [PATCH] RESET SESSION, plus related new DDL commands. Patch from Marko Kreen, reviewed by Neil Conway. This patch adds the following DDL command variants: RESET SESSION, RESET TEMP, RESET PLANS, CLOSE ALL, and DEALLOCATE ALL. RESET SESSION is intended for use by connection pool software and the like, in order to reset a client session to something close to its initial state. Note that while most of these command variants can be executed inside a transaction block (but are not transaction-aware!), RESET SESSION cannot. While this is inconsistent, it is intended to catch programmer mistakes: RESET SESSION in an open transaction block is probably unintended. --- doc/src/sgml/ref/close.sgml | 26 +++++-- doc/src/sgml/ref/deallocate.sgml | 13 +++- doc/src/sgml/ref/reset.sgml | 63 +++++++++++++++- src/backend/catalog/namespace.c | 22 +++++- src/backend/commands/async.c | 5 +- src/backend/commands/portalcmds.c | 11 ++- src/backend/commands/prepare.c | 32 ++++++++- src/backend/parser/gram.y | 20 +++++- src/backend/tcop/utility.c | 28 ++++++-- src/backend/utils/cache/plancache.c | 11 ++- src/backend/utils/misc/guc.c | 37 +++++++++- src/backend/utils/mmgr/portalmem.c | 25 ++++++- src/include/catalog/namespace.h | 4 +- src/include/commands/async.h | 3 +- src/include/commands/prepare.h | 4 +- src/include/nodes/parsenodes.h | 4 +- src/include/utils/guc.h | 4 +- src/include/utils/plancache.h | 4 +- src/include/utils/portal.h | 3 +- src/test/regress/expected/guc.out | 100 ++++++++++++++++++++++++++ src/test/regress/expected/portals.out | 30 ++++++++ src/test/regress/expected/prepare.out | 8 +++ src/test/regress/sql/guc.sql | 39 ++++++++++ src/test/regress/sql/portals.sql | 15 ++++ src/test/regress/sql/prepare.sql | 6 ++ 25 files changed, 479 insertions(+), 38 deletions(-) diff --git a/doc/src/sgml/ref/close.sgml b/doc/src/sgml/ref/close.sgml index f3f37d95f66..2e5309ff0f2 100644 --- a/doc/src/sgml/ref/close.sgml +++ b/doc/src/sgml/ref/close.sgml @@ -1,5 +1,5 @@ @@ -25,7 +25,7 @@ PostgreSQL documentation -CLOSE name +CLOSE { name | ALL } @@ -44,10 +44,10 @@ CLOSE name transaction is terminated by COMMIT or ROLLBACK. A holdable cursor is implicitly closed if the transaction that created it aborts via - ROLLBACK. If the creating transaction successfully - commits, the holdable - cursor remains open until an explicit CLOSE is - executed, or the client disconnects. + ROLLBACK. If the creating transaction + successfully commits, the holdable cursor remains open until an + explicit CLOSE is executed, or the client + disconnects. @@ -63,6 +63,16 @@ CLOSE name + + + ALL + + + Close all open cursors. + + + + @@ -98,7 +108,9 @@ CLOSE liahona; Compatibility - CLOSE is fully conforming with the SQL standard. + CLOSE is fully conforming with the SQL + standard. CLOSE ALL is a PostgreSQL + extension. diff --git a/doc/src/sgml/ref/deallocate.sgml b/doc/src/sgml/ref/deallocate.sgml index 2038767c0d4..26fee6aa06b 100644 --- a/doc/src/sgml/ref/deallocate.sgml +++ b/doc/src/sgml/ref/deallocate.sgml @@ -1,5 +1,5 @@ @@ -25,7 +25,7 @@ PostgreSQL documentation -DEALLOCATE [ PREPARE ] name +DEALLOCATE [ PREPARE ] { name | ALL } @@ -65,6 +65,15 @@ DEALLOCATE [ PREPARE ] name + + + ALL + + + Deallocate all prepared statements. + + + diff --git a/doc/src/sgml/ref/reset.sgml b/doc/src/sgml/ref/reset.sgml index 84426d2cb6a..e94ef0b8d57 100644 --- a/doc/src/sgml/ref/reset.sgml +++ b/doc/src/sgml/ref/reset.sgml @@ -1,5 +1,5 @@ @@ -22,9 +22,10 @@ PostgreSQL documentation RESET configuration_parameter RESET ALL +RESET { PLANS | SESSION | TEMP | TEMPORARY } - + Description @@ -41,7 +42,7 @@ SET configuration_parameter TO DEFA The default value is defined as the value that the parameter would - have had, had no SET ever been issued for it in the + have had, if no SET ever been issued for it in the current session. The actual source of this value might be a compiled-in default, the configuration file, command-line options, or per-database or per-user default settings. See configuration_parameter TO DEFA See the SET reference page for details on the transaction behavior of RESET. + + + RESET can also be used to release internal resources + that are usually released at the end of session. RESET + TEMP drops all temporary tables created in the current session. + RESET PLANS releases all internally cached plans. + RESET SESSION releases all externally visible temporary + resources associated with the current session. + @@ -76,9 +86,56 @@ SET configuration_parameter TO DEFA + + + TEMP, TEMPORARY + + + Drops all temporary tables created in the current session. + + + + + + PLANS + + + Releases all cached query plans. + + + + + + SESSION + + + Releases all temporary resources associated with the current + session. This has the same effect as executing the following + command sequence: + +SET SESSION AUTHORIZATION DEFAULT; +RESET ALL; +DEALLOCATE ALL; +CLOSE ALL; +UNLISTEN *; +RESET PLANS; +RESET TEMP; + + + + + + + Notes + + + RESET SESSION cannot be executed inside a transaction block. + + + Examples diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 6baa9a798b5..16853b3d791 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.93 2007/03/23 19:53:51 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.94 2007/04/12 06:53:46 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -1940,6 +1940,26 @@ InitTempTableNamespace(void) baseSearchPathValid = false; /* need to rebuild list */ } +/* + * Remove all temp tables from the temporary namespace. + */ +void +ResetTempTableNamespace(void) +{ + char namespaceName[NAMEDATALEN]; + Oid namespaceId; + + /* find oid */ + snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId); + namespaceId = GetSysCacheOid(NAMESPACENAME, + CStringGetDatum(namespaceName), + 0, 0, 0); + + /* clean if exists */ + if (OidIsValid(namespaceId)) + RemoveTempRelations(namespaceId); +} + /* * End-of-transaction cleanup for namespaces. */ diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index f96ff139643..55b99f8c922 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.135 2007/01/05 22:19:25 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.136 2007/04/12 06:53:46 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -127,7 +127,6 @@ static bool unlistenExitRegistered = false; bool Trace_notify = false; -static void Async_UnlistenAll(void); static void Async_UnlistenOnExit(int code, Datum arg); static void ProcessIncomingNotify(void); static void NotifyMyFrontEnd(char *relname, int32 listenerPID); @@ -335,7 +334,7 @@ Async_Unlisten(const char *relname) * *-------------------------------------------------------------- */ -static void +void Async_UnlistenAll(void) { Relation lRel; diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c index 98b200d2cff..d759ed4ac2d 100644 --- a/src/backend/commands/portalcmds.c +++ b/src/backend/commands/portalcmds.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.62 2007/03/13 00:33:39 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.63 2007/04/12 06:53:46 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -236,11 +236,18 @@ PerformPortalClose(const char *name) { Portal portal; + /* NULL means CLOSE ALL */ + if (name == NULL) + { + PortalHashTableDeleteAll(); + return; + } + /* * Disallow empty-string cursor name (conflicts with protocol-level * unnamed portal). */ - if (!name || name[0] == '\0') + if (name[0] == '\0') ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_NAME), errmsg("invalid cursor name: must not be empty"))); diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index 2c284cb9be0..fe1a8532f07 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -10,7 +10,7 @@ * Copyright (c) 2002-2007, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.70 2007/03/13 00:33:39 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.71 2007/04/12 06:53:46 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -575,7 +575,10 @@ FetchPreparedStatementTargetList(PreparedStatement *stmt) void DeallocateQuery(DeallocateStmt *stmt) { - DropPreparedStatement(stmt->name, true); + if (stmt->name) + DropPreparedStatement(stmt->name, true); + else + DropAllPreparedStatements(); } /* @@ -601,6 +604,31 @@ DropPreparedStatement(const char *stmt_name, bool showError) } } +/* + * Drop all cached statements. + */ +void +DropAllPreparedStatements(void) +{ + HASH_SEQ_STATUS seq; + PreparedStatement *entry; + + /* nothing cached */ + if (!prepared_queries) + return; + + /* walk over cache */ + hash_seq_init(&seq, prepared_queries); + while ((entry = hash_seq_search(&seq)) != NULL) + { + /* Release the plancache entry */ + DropCachedPlan(entry->plansource); + + /* Now we can remove the hash table entry */ + hash_search(prepared_queries, entry->stmt_name, HASH_REMOVE, NULL); + } +} + /* * Implements the 'EXPLAIN EXECUTE' utility statement. */ diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 56278f56e5d..6aa81eec3ef 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.587 2007/04/08 00:26:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.588 2007/04/12 06:53:46 neilc Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -1667,6 +1667,12 @@ ClosePortalStmt: n->portalname = $2; $$ = (Node *)n; } + | CLOSE ALL + { + ClosePortalStmt *n = makeNode(ClosePortalStmt); + n->portalname = NULL; + $$ = (Node *)n; + } ; @@ -5591,6 +5597,18 @@ DeallocateStmt: DEALLOCATE name n->name = $3; $$ = (Node *) n; } + | DEALLOCATE ALL + { + DeallocateStmt *n = makeNode(DeallocateStmt); + n->name = NULL; + $$ = (Node *) n; + } + | DEALLOCATE PREPARE ALL + { + DeallocateStmt *n = makeNode(DeallocateStmt); + n->name = NULL; + $$ = (Node *) n; + } ; /***************************************************************************** diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 864b6d1dd63..88adb625d55 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.276 2007/04/02 03:49:39 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.277 2007/04/12 06:53:47 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -990,7 +990,7 @@ ProcessUtility(Node *parsetree, { VariableResetStmt *n = (VariableResetStmt *) parsetree; - ResetPGVariable(n->name); + ResetPGVariable(n->name, isTopLevel); } break; @@ -1387,7 +1387,13 @@ CreateCommandTag(Node *parsetree) break; case T_ClosePortalStmt: - tag = "CLOSE CURSOR"; + { + ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree; + if (stmt->portalname == NULL) + tag = "CLOSE CURSOR ALL"; + else + tag = "CLOSE CURSOR"; + } break; case T_FetchStmt: @@ -1746,7 +1752,13 @@ CreateCommandTag(Node *parsetree) break; case T_VariableResetStmt: - tag = "RESET"; + { + VariableResetStmt *stmt = (VariableResetStmt *) parsetree; + if (pg_strcasecmp(stmt->name, "session") == 0) + tag = "RESET SESSION"; + else + tag = "RESET"; + } break; case T_CreateTrigStmt: @@ -1856,7 +1868,13 @@ CreateCommandTag(Node *parsetree) break; case T_DeallocateStmt: - tag = "DEALLOCATE"; + { + DeallocateStmt *stmt = (DeallocateStmt *) parsetree; + if (stmt->name == NULL) + tag = "DEALLOCATE ALL"; + else + tag = "DEALLOCATE"; + } break; /* already-planned queries */ diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c index f02a58e29b1..6165e59c6e6 100644 --- a/src/backend/utils/cache/plancache.c +++ b/src/backend/utils/cache/plancache.c @@ -33,7 +33,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.5 2007/03/26 00:36:19 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.6 2007/04/12 06:53:47 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -880,6 +880,15 @@ PlanCacheCallback(Datum arg, Oid relid) } } +/* + * ResetPlanCache: drop all cached plans. + */ +void +ResetPlanCache(void) +{ + PlanCacheCallback((Datum) 0, InvalidOid); +} + /* * ScanQueryForRelids callback function for PlanCacheCallback */ diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index f921c75a60b..385411c0582 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.383 2007/03/19 23:38:30 wieck Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.384 2007/04/12 06:53:47 neilc Exp $ * *-------------------------------------------------------------------- */ @@ -32,6 +32,7 @@ #include "access/xact.h" #include "catalog/namespace.h" #include "commands/async.h" +#include "commands/prepare.h" #include "commands/vacuum.h" #include "commands/variable.h" #include "commands/trigger.h" @@ -61,6 +62,7 @@ #include "utils/memutils.h" #include "utils/pg_locale.h" #include "utils/plancache.h" +#include "utils/portal.h" #include "utils/ps_status.h" #include "utils/tzparser.h" #include "utils/xml.h" @@ -4951,14 +4953,45 @@ GetPGVariableResultDesc(const char *name) return tupdesc; } +/* + * RESET SESSION command. + */ +static void +ResetSession(bool isTopLevel) +{ + /* + * Disallow RESET SESSION in a transaction block. This is arguably + * inconsistent (we don't make a similar check in the command + * sequence that RESET SESSION is equivalent to), but the idea is + * to catch mistakes: RESET SESSION inside a transaction block + * would leave the transaction still uncommitted. + */ + PreventTransactionChain(isTopLevel, "RESET SESSION"); + + SetPGVariable("session_authorization", NIL, false); + ResetAllOptions(); + DropAllPreparedStatements(); + PortalHashTableDeleteAll(); + Async_UnlistenAll(); + ResetPlanCache(); + ResetTempTableNamespace(); +} + /* * RESET command */ void -ResetPGVariable(const char *name) +ResetPGVariable(const char *name, bool isTopLevel) { if (pg_strcasecmp(name, "all") == 0) ResetAllOptions(); + else if (pg_strcasecmp(name, "session") == 0) + ResetSession(isTopLevel); + else if (pg_strcasecmp(name, "temp") == 0 || + pg_strcasecmp(name, "temporary") == 0) + ResetTempTableNamespace(); + else if (pg_strcasecmp(name, "plans") == 0) + ResetPlanCache(); else set_config_option(name, NULL, diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index 043ea1e57a4..eeba207dc94 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.100 2007/03/13 00:33:42 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.101 2007/04/12 06:53:48 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -452,6 +452,29 @@ PortalDrop(Portal portal, bool isTopCommit) pfree(portal); } +/* + * Delete all declared cursors. + * + * Used by commands: CLOSE ALL, RESET SESSION + */ +void +PortalHashTableDeleteAll(void) +{ + HASH_SEQ_STATUS status; + PortalHashEnt *hentry; + + if (PortalHashTable == NULL) + return; + + hash_seq_init(&status, PortalHashTable); + while ((hentry = hash_seq_search(&status)) != NULL) + { + Portal portal = hentry->portal; + if (portal->status != PORTAL_ACTIVE) + PortalDrop(portal, false); + } +} + /* * Pre-commit processing for portals. diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h index 18e3157b9e3..456d22f942c 100644 --- a/src/include/catalog/namespace.h +++ b/src/include/catalog/namespace.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/namespace.h,v 1.45 2007/03/23 19:53:52 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/namespace.h,v 1.46 2007/04/12 06:53:48 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -100,4 +100,6 @@ extern char *namespace_search_path; extern List *fetch_search_path(bool includeImplicit); +extern void ResetTempTableNamespace(void); + #endif /* NAMESPACE_H */ diff --git a/src/include/commands/async.h b/src/include/commands/async.h index a97abf7dd93..c6a84a0133b 100644 --- a/src/include/commands/async.h +++ b/src/include/commands/async.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/async.h,v 1.34 2007/01/05 22:19:53 momjian Exp $ + * $PostgreSQL: pgsql/src/include/commands/async.h,v 1.35 2007/04/12 06:53:48 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,7 @@ extern bool Trace_notify; extern void Async_Notify(const char *relname); extern void Async_Listen(const char *relname); extern void Async_Unlisten(const char *relname); +extern void Async_UnlistenAll(void); /* perform (or cancel) outbound notify processing at transaction commit */ extern void AtCommit_Notify(void); diff --git a/src/include/commands/prepare.h b/src/include/commands/prepare.h index 4e27ab3bb39..c12d248971e 100644 --- a/src/include/commands/prepare.h +++ b/src/include/commands/prepare.h @@ -6,7 +6,7 @@ * * Copyright (c) 2002-2007, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/commands/prepare.h,v 1.25 2007/03/13 00:33:43 tgl Exp $ + * $PostgreSQL: pgsql/src/include/commands/prepare.h,v 1.26 2007/04/12 06:53:48 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -59,4 +59,6 @@ extern void DropPreparedStatement(const char *stmt_name, bool showError); extern TupleDesc FetchPreparedStatementResultDesc(PreparedStatement *stmt); extern List *FetchPreparedStatementTargetList(PreparedStatement *stmt); +void DropAllPreparedStatements(void); + #endif /* PREPARE_H */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 8552620be3c..bc421e265fc 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.344 2007/04/02 03:49:41 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.345 2007/04/12 06:53:48 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -1451,6 +1451,7 @@ typedef struct ClosePortalStmt { NodeTag type; char *portalname; /* name of the portal (cursor) */ + /* NULL means CLOSE ALL */ } ClosePortalStmt; /* ---------------------- @@ -1981,6 +1982,7 @@ typedef struct DeallocateStmt { NodeTag type; char *name; /* The name of the plan to remove */ + /* NULL means DEALLOCATE ALL */ } DeallocateStmt; /* diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 3efb8618938..e3315c72257 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -7,7 +7,7 @@ * Copyright (c) 2000-2007, PostgreSQL Global Development Group * Written by Peter Eisentraut . * - * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.80 2007/03/06 02:06:15 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.81 2007/04/12 06:53:48 neilc Exp $ *-------------------------------------------------------------------- */ #ifndef GUC_H @@ -201,7 +201,7 @@ extern int GetNumConfigOptions(void); extern void SetPGVariable(const char *name, List *args, bool is_local); extern void GetPGVariable(const char *name, DestReceiver *dest); extern TupleDesc GetPGVariableResultDesc(const char *name); -extern void ResetPGVariable(const char *name); +extern void ResetPGVariable(const char *name, bool isTopLevel); extern char *flatten_set_variable_args(const char *name, List *args); diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h index e193238291d..562b369044f 100644 --- a/src/include/utils/plancache.h +++ b/src/include/utils/plancache.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/plancache.h,v 1.4 2007/03/23 19:53:52 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/plancache.h,v 1.5 2007/04/12 06:53:48 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -105,4 +105,6 @@ extern void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner); extern TupleDesc PlanCacheComputeResultDesc(List *stmt_list); extern bool HaveCachedPlans(void); +extern void ResetPlanCache(void); + #endif /* PLANCACHE_H */ diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h index 47651006a21..4c31e2a121f 100644 --- a/src/include/utils/portal.h +++ b/src/include/utils/portal.h @@ -39,7 +39,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/portal.h,v 1.74 2007/03/13 00:33:43 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/portal.h,v 1.75 2007/04/12 06:53:48 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -212,5 +212,6 @@ extern void PortalDefineQuery(Portal portal, CachedPlan *cplan); extern Node *PortalListGetPrimaryStmt(List *stmts); extern void PortalCreateHoldStore(Portal portal); +extern void PortalHashTableDeleteAll(void); #endif /* PORTAL_H */ diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out index ca1b582630d..484cc356e7f 100644 --- a/src/test/regress/expected/guc.out +++ b/src/test/regress/expected/guc.out @@ -425,3 +425,103 @@ SELECT '2006-08-13 12:34:56'::timestamptz; Sun Aug 13 12:34:56 2006 PDT (1 row) +-- +-- Test RESET TEMP +-- +CREATE TEMP TABLE reset_test ( data text ) ON COMMIT DELETE ROWS; +SELECT relname FROM pg_class WHERE relname = 'reset_test'; + relname +------------ + reset_test +(1 row) + +RESET TEMP; +SELECT relname FROM pg_class WHERE relname = 'reset_test'; + relname +--------- +(0 rows) + +-- +-- Test RESET SESSION +-- +-- do changes +DECLARE foo CURSOR WITH HOLD FOR SELECT 1; +PREPARE foo AS SELECT 1; +LISTEN foo_event; +SET vacuum_cost_delay = 13; +CREATE TEMP TABLE tmp_foo (data text) ON COMMIT DELETE ROWS; +CREATE ROLE temp_reset_user; +SET SESSION AUTHORIZATION temp_reset_user; +-- look changes +SELECT relname FROM pg_listener; + relname +----------- + foo_event +(1 row) + +SELECT name FROM pg_prepared_statements; + name +------ + foo +(1 row) + +SELECT name FROM pg_cursors; + name +------ + foo +(1 row) + +SHOW vacuum_cost_delay; + vacuum_cost_delay +------------------- + 13ms +(1 row) + +SELECT relname from pg_class where relname = 'tmp_foo'; + relname +--------- + tmp_foo +(1 row) + +SELECT current_user = 'temp_reset_user'; + ?column? +---------- + t +(1 row) + +-- big RESET +RESET SESSION; +-- look again +SELECT relname FROM pg_listener; + relname +--------- +(0 rows) + +SELECT name FROM pg_prepared_statements; + name +------ +(0 rows) + +SELECT name FROM pg_cursors; + name +------ +(0 rows) + +SHOW vacuum_cost_delay; + vacuum_cost_delay +------------------- + 0 +(1 row) + +SELECT relname from pg_class where relname = 'tmp_foo'; + relname +--------- +(0 rows) + +SELECT current_user = 'temp_reset_user'; + ?column? +---------- + f +(1 row) + +DROP ROLE temp_reset_user; diff --git a/src/test/regress/expected/portals.out b/src/test/regress/expected/portals.out index ab62ac2705b..9b22aa4dc7d 100644 --- a/src/test/regress/expected/portals.out +++ b/src/test/regress/expected/portals.out @@ -869,3 +869,33 @@ EXECUTE cprep; c2 | declare c2 cursor with hold for select count_tt1_v(), count_tt1_s(); | t | f | f (1 row) +-- test CLOSE ALL; +SELECT name FROM pg_cursors ORDER BY 1; + name +------ + c2 +(1 row) + +CLOSE ALL; +SELECT name FROM pg_cursors ORDER BY 1; + name +------ +(0 rows) + +BEGIN; +DECLARE foo1 CURSOR WITH HOLD FOR SELECT 1; +DECLARE foo2 CURSOR WITHOUT HOLD FOR SELECT 1; +SELECT name FROM pg_cursors ORDER BY 1; + name +------ + foo1 + foo2 +(2 rows) + +CLOSE ALL; +SELECT name FROM pg_cursors ORDER BY 1; + name +------ +(0 rows) + +COMMIT; diff --git a/src/test/regress/expected/prepare.out b/src/test/regress/expected/prepare.out index 73d38c1ca17..695042f6339 100644 --- a/src/test/regress/expected/prepare.out +++ b/src/test/regress/expected/prepare.out @@ -166,3 +166,11 @@ SELECT name, statement, parameter_types FROM pg_prepared_statements : SELECT * FROM road WHERE thepath = $1; (5 rows) +-- test DEALLOCATE ALL; +DEALLOCATE ALL; +SELECT name, statement, parameter_types FROM pg_prepared_statements + ORDER BY name; + name | statement | parameter_types +------+-----------+----------------- +(0 rows) + diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql index 6d17a182412..274007a2c33 100644 --- a/src/test/regress/sql/guc.sql +++ b/src/test/regress/sql/guc.sql @@ -123,3 +123,42 @@ SELECT '2006-08-13 12:34:56'::timestamptz; RESET datestyle; SHOW datestyle; SELECT '2006-08-13 12:34:56'::timestamptz; + +-- +-- Test RESET TEMP +-- +CREATE TEMP TABLE reset_test ( data text ) ON COMMIT DELETE ROWS; +SELECT relname FROM pg_class WHERE relname = 'reset_test'; +RESET TEMP; +SELECT relname FROM pg_class WHERE relname = 'reset_test'; + +-- +-- Test RESET SESSION +-- + +-- do changes +DECLARE foo CURSOR WITH HOLD FOR SELECT 1; +PREPARE foo AS SELECT 1; +LISTEN foo_event; +SET vacuum_cost_delay = 13; +CREATE TEMP TABLE tmp_foo (data text) ON COMMIT DELETE ROWS; +CREATE ROLE temp_reset_user; +SET SESSION AUTHORIZATION temp_reset_user; +-- look changes +SELECT relname FROM pg_listener; +SELECT name FROM pg_prepared_statements; +SELECT name FROM pg_cursors; +SHOW vacuum_cost_delay; +SELECT relname from pg_class where relname = 'tmp_foo'; +SELECT current_user = 'temp_reset_user'; +-- big RESET +RESET SESSION; +-- look again +SELECT relname FROM pg_listener; +SELECT name FROM pg_prepared_statements; +SELECT name FROM pg_cursors; +SHOW vacuum_cost_delay; +SELECT relname from pg_class where relname = 'tmp_foo'; +SELECT current_user = 'temp_reset_user'; +DROP ROLE temp_reset_user; + diff --git a/src/test/regress/sql/portals.sql b/src/test/regress/sql/portals.sql index 43cbf05a90d..278ad64b389 100644 --- a/src/test/regress/sql/portals.sql +++ b/src/test/regress/sql/portals.sql @@ -303,3 +303,18 @@ ROLLBACK; PREPARE cprep AS SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors; EXECUTE cprep; + +-- test CLOSE ALL; +SELECT name FROM pg_cursors ORDER BY 1; +CLOSE ALL; +SELECT name FROM pg_cursors ORDER BY 1; +BEGIN; +DECLARE foo1 CURSOR WITH HOLD FOR SELECT 1; +DECLARE foo2 CURSOR WITHOUT HOLD FOR SELECT 1; +SELECT name FROM pg_cursors ORDER BY 1; +CLOSE ALL; +SELECT name FROM pg_cursors ORDER BY 1; +COMMIT; + + + diff --git a/src/test/regress/sql/prepare.sql b/src/test/regress/sql/prepare.sql index d42b7a0879f..c7b5b136348 100644 --- a/src/test/regress/sql/prepare.sql +++ b/src/test/regress/sql/prepare.sql @@ -68,3 +68,9 @@ PREPARE q7(unknown) AS SELECT name, statement, parameter_types FROM pg_prepared_statements ORDER BY name; + +-- test DEALLOCATE ALL; +DEALLOCATE ALL; +SELECT name, statement, parameter_types FROM pg_prepared_statements + ORDER BY name; +