summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Conway2007-04-12 06:53:49 +0000
committerNeil Conway2007-04-12 06:53:49 +0000
commitf1e6f869851530649baac42305882ae6df769251 (patch)
treea5b1a15897762359bc416343a06240065707579d
parent8ad7dc017f0d6d5dc4031ddcd31d1ad287defa8b (diff)
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.
-rw-r--r--doc/src/sgml/ref/close.sgml24
-rw-r--r--doc/src/sgml/ref/deallocate.sgml11
-rw-r--r--doc/src/sgml/ref/reset.sgml61
-rw-r--r--src/backend/catalog/namespace.c20
-rw-r--r--src/backend/commands/async.c3
-rw-r--r--src/backend/commands/portalcmds.c9
-rw-r--r--src/backend/commands/prepare.c30
-rw-r--r--src/backend/parser/gram.y18
-rw-r--r--src/backend/tcop/utility.c26
-rw-r--r--src/backend/utils/cache/plancache.c9
-rw-r--r--src/backend/utils/misc/guc.c35
-rw-r--r--src/backend/utils/mmgr/portalmem.c23
-rw-r--r--src/include/catalog/namespace.h2
-rw-r--r--src/include/commands/async.h1
-rw-r--r--src/include/commands/prepare.h2
-rw-r--r--src/include/nodes/parsenodes.h2
-rw-r--r--src/include/utils/guc.h2
-rw-r--r--src/include/utils/plancache.h2
-rw-r--r--src/include/utils/portal.h1
-rw-r--r--src/test/regress/expected/guc.out100
-rw-r--r--src/test/regress/expected/portals.out30
-rw-r--r--src/test/regress/expected/prepare.out8
-rw-r--r--src/test/regress/sql/guc.sql39
-rw-r--r--src/test/regress/sql/portals.sql15
-rw-r--r--src/test/regress/sql/prepare.sql6
25 files changed, 460 insertions, 19 deletions
diff --git a/doc/src/sgml/ref/close.sgml b/doc/src/sgml/ref/close.sgml
index 78c5870a85..1a7144cdd9 100644
--- a/doc/src/sgml/ref/close.sgml
+++ b/doc/src/sgml/ref/close.sgml
@@ -25,7 +25,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
-CLOSE <replaceable class="PARAMETER">name</replaceable>
+CLOSE { <replaceable class="PARAMETER">name</replaceable> | ALL }
</synopsis>
</refsynopsisdiv>
@@ -44,10 +44,10 @@ CLOSE <replaceable class="PARAMETER">name</replaceable>
transaction is terminated by <command>COMMIT</command> or
<command>ROLLBACK</command>. A holdable cursor is implicitly
closed if the transaction that created it aborts via
- <command>ROLLBACK</command>. If the creating transaction successfully
- commits, the holdable
- cursor remains open until an explicit <command>CLOSE</command> is
- executed, or the client disconnects.
+ <command>ROLLBACK</command>. If the creating transaction
+ successfully commits, the holdable cursor remains open until an
+ explicit <command>CLOSE</command> is executed, or the client
+ disconnects.
</para>
</refsect1>
@@ -63,6 +63,16 @@ CLOSE <replaceable class="PARAMETER">name</replaceable>
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><literal>ALL</literal></term>
+ <listitem>
+ <para>
+ Close all open cursors.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
@@ -98,7 +108,9 @@ CLOSE liahona;
<title>Compatibility</title>
<para>
- <command>CLOSE</command> is fully conforming with the SQL standard.
+ <command>CLOSE</command> is fully conforming with the SQL
+ standard. <command>CLOSE ALL</> is a <productname>PostgreSQL</>
+ extension.
</para>
</refsect1>
diff --git a/doc/src/sgml/ref/deallocate.sgml b/doc/src/sgml/ref/deallocate.sgml
index 7318a92a7c..fc90d781ad 100644
--- a/doc/src/sgml/ref/deallocate.sgml
+++ b/doc/src/sgml/ref/deallocate.sgml
@@ -25,7 +25,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
-DEALLOCATE [ PREPARE ] <replaceable class="parameter">name</replaceable>
+DEALLOCATE [ PREPARE ] { <replaceable class="parameter">name</replaceable> | ALL }
</synopsis>
</refsynopsisdiv>
@@ -65,6 +65,15 @@ DEALLOCATE [ PREPARE ] <replaceable class="parameter">name</replaceable>
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><literal>ALL</literal></term>
+ <listitem>
+ <para>
+ Deallocate all prepared statements.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/doc/src/sgml/ref/reset.sgml b/doc/src/sgml/ref/reset.sgml
index 60ff2d38ee..ee26e94031 100644
--- a/doc/src/sgml/ref/reset.sgml
+++ b/doc/src/sgml/ref/reset.sgml
@@ -22,9 +22,10 @@ PostgreSQL documentation
<synopsis>
RESET <replaceable class="PARAMETER">configuration_parameter</replaceable>
RESET ALL
+RESET { PLANS | SESSION | TEMP | TEMPORARY }
</synopsis>
</refsynopsisdiv>
-
+
<refsect1>
<title>Description</title>
@@ -41,7 +42,7 @@ SET <replaceable class="parameter">configuration_parameter</replaceable> TO DEFA
<para>
The default value is defined as the value that the parameter would
- have had, had no <command>SET</> ever been issued for it in the
+ have had, if no <command>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 <xref
@@ -52,6 +53,15 @@ SET <replaceable class="parameter">configuration_parameter</replaceable> TO DEFA
See the <command>SET</> reference page for details on the
transaction behavior of <command>RESET</>.
</para>
+
+ <para>
+ <command>RESET</> can also be used to release internal resources
+ that are usually released at the end of session. <command>RESET
+ TEMP</> drops all temporary tables created in the current session.
+ <command>RESET PLANS</> releases all internally cached plans.
+ <command>RESET SESSION</> releases all externally visible temporary
+ resources associated with the current session.
+ </para>
</refsect1>
<refsect1>
@@ -76,10 +86,57 @@ SET <replaceable class="parameter">configuration_parameter</replaceable> TO DEFA
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><literal>TEMP, TEMPORARY</literal></term>
+ <listitem>
+ <para>
+ Drops all temporary tables created in the current session.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>PLANS</literal></term>
+ <listitem>
+ <para>
+ Releases all cached query plans.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>SESSION</literal></term>
+ <listitem>
+ <para>
+ Releases all temporary resources associated with the current
+ session. This has the same effect as executing the following
+ command sequence:
+<synopsis>
+SET SESSION AUTHORIZATION DEFAULT;
+RESET ALL;
+DEALLOCATE ALL;
+CLOSE ALL;
+UNLISTEN *;
+RESET PLANS;
+RESET TEMP;
+</synopsis>
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
<refsect1>
+ <title>Notes</title>
+
+ <para>
+ <command>RESET SESSION</> cannot be executed inside a transaction block.
+ </para>
+ </refsect1>
+
+ <refsect1>
<title>Examples</title>
<para>
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index c9c8837294..4e85bc0ad4 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -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 8cd429577f..9a53e51f65 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -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 f218f9cfe4..7a76054168 100644
--- a/src/backend/commands/portalcmds.c
+++ b/src/backend/commands/portalcmds.c
@@ -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 467ab4141b..65b337af20 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -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 ff56f888f4..30b365fdf9 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -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 fe8e656a64..26bf62fa93 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -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 4ca50f8835..c461881310 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -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 63a893a31d..288b996ede 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -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 c4789d02cb..d4952e51ee 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -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 2ba32d357b..79783ce8b3 100644
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -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 b5639d9714..2fcf0d5c1f 100644
--- a/src/include/commands/async.h
+++ b/src/include/commands/async.h
@@ -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 176d24d091..6cc1542433 100644
--- a/src/include/commands/prepare.h
+++ b/src/include/commands/prepare.h
@@ -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 952c6aab3c..479e3c8254 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -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 e6d4c646f5..15c4e6b484 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/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 52ddde4b5c..4055bcccfa 100644
--- a/src/include/utils/plancache.h
+++ b/src/include/utils/plancache.h
@@ -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 a93e225d5f..95fcad8283 100644
--- a/src/include/utils/portal.h
+++ b/src/include/utils/portal.h
@@ -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 ca1b582630..484cc356e7 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 ab62ac2705..9b22aa4dc7 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 73d38c1ca1..695042f633 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 6d17a18241..274007a2c3 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 43cbf05a90..278ad64b38 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 d42b7a0879..c7b5b13634 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;
+