diff options
author | Neil Conway <neilc@samurai.com> | 2007-04-12 06:53:49 +0000 |
---|---|---|
committer | Neil Conway <neilc@samurai.com> | 2007-04-12 06:53:49 +0000 |
commit | d13e903beaecd45a3721e4c2a7f9ff842ce94a79 (patch) | |
tree | 3ded6910c6f451bb982fb5033735afd24927c5b6 /src/backend | |
parent | e6e47f278d2ab0fc744b56fed86cc34299079037 (diff) | |
download | postgresql-d13e903beaecd45a3721e4c2a7f9ff842ce94a79.tar.gz postgresql-d13e903beaecd45a3721e4c2a7f9ff842ce94a79.zip |
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.
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/namespace.c | 22 | ||||
-rw-r--r-- | src/backend/commands/async.c | 5 | ||||
-rw-r--r-- | src/backend/commands/portalcmds.c | 11 | ||||
-rw-r--r-- | src/backend/commands/prepare.c | 32 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 20 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 28 | ||||
-rw-r--r-- | src/backend/utils/cache/plancache.c | 11 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 37 | ||||
-rw-r--r-- | src/backend/utils/mmgr/portalmem.c | 25 |
9 files changed, 173 insertions, 18 deletions
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 $ * *------------------------------------------------------------------------- */ @@ -1941,6 +1941,26 @@ InitTempTableNamespace(void) } /* + * 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. */ void 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(); } /* @@ -602,6 +605,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. */ void 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 $ * *------------------------------------------------------------------------- */ @@ -881,6 +881,15 @@ PlanCacheCallback(Datum arg, Oid relid) } /* + * ResetPlanCache: drop all cached plans. + */ +void +ResetPlanCache(void) +{ + PlanCacheCallback((Datum) 0, InvalidOid); +} + +/* * ScanQueryForRelids callback function for PlanCacheCallback */ static void 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 <peter_e@gmx.net>. * * 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" @@ -4952,13 +4954,44 @@ GetPGVariableResultDesc(const char *name) } /* + * 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. |