From 8a21c2bd85ab46d45128872bf2bbc98716356936 Mon Sep 17 00:00:00 2001 From: "okbob@github.com" Date: Sun, 11 Jun 2023 06:42:10 +0200 Subject: [PATCH 3/9] DISCARD VARIABLES Implementation of DISCARD VARIABLES commands by removing hash table with session variables and resetting related memory context. --- doc/src/sgml/ref/discard.sgml | 14 ++++- src/backend/commands/discard.c | 6 ++ src/backend/commands/session_variable.c | 20 ++++++ src/backend/parser/gram.y | 6 ++ src/backend/tcop/utility.c | 3 + src/bin/psql/tab-complete.c | 2 +- src/include/commands/session_variable.h | 2 + src/include/nodes/parsenodes.h | 3 +- src/include/tcop/cmdtaglist.h | 1 + .../regress/expected/session_variables.out | 63 +++++++++++++++++++ src/test/regress/sql/session_variables.sql | 37 +++++++++++ 11 files changed, 154 insertions(+), 3 deletions(-) diff --git a/doc/src/sgml/ref/discard.sgml b/doc/src/sgml/ref/discard.sgml index bf44c523ca..6b0cb95034 100644 --- a/doc/src/sgml/ref/discard.sgml +++ b/doc/src/sgml/ref/discard.sgml @@ -21,7 +21,7 @@ PostgreSQL documentation -DISCARD { ALL | PLANS | SEQUENCES | TEMPORARY | TEMP } +DISCARD { ALL | PLANS | SEQUENCES | TEMPORARY | TEMP | VARIABLES } @@ -66,6 +66,17 @@ DISCARD { ALL | PLANS | SEQUENCES | TEMPORARY | TEMP } + + VARIABLES + + + Resets the value of all session variables. If a variable + is later reused, it is re-initialized to either + NULL or its default value. + + + + TEMPORARY or TEMP @@ -93,6 +104,7 @@ SELECT pg_advisory_unlock_all(); DISCARD PLANS; DISCARD TEMP; DISCARD SEQUENCES; +DISCARD VARIABLES; diff --git a/src/backend/commands/discard.c b/src/backend/commands/discard.c index 296dc82d2e..14ee0f7aaa 100644 --- a/src/backend/commands/discard.c +++ b/src/backend/commands/discard.c @@ -18,6 +18,7 @@ #include "commands/async.h" #include "commands/discard.h" #include "commands/prepare.h" +#include "commands/session_variable.h" #include "commands/sequence.h" #include "utils/guc.h" #include "utils/portal.h" @@ -48,6 +49,10 @@ DiscardCommand(DiscardStmt *stmt, bool isTopLevel) ResetTempTableNamespace(); break; + case DISCARD_VARIABLES: + ResetSessionVariables(); + break; + default: elog(ERROR, "unrecognized DISCARD target: %d", stmt->target); } @@ -75,4 +80,5 @@ DiscardAll(bool isTopLevel) ResetPlanCache(); ResetTempTableNamespace(); ResetSequenceCaches(); + ResetSessionVariables(); } diff --git a/src/backend/commands/session_variable.c b/src/backend/commands/session_variable.c index 3a3a3b7c35..12b02ca1e0 100644 --- a/src/backend/commands/session_variable.c +++ b/src/backend/commands/session_variable.c @@ -607,6 +607,26 @@ ExecuteLetStmt(ParseState *pstate, PopActiveSnapshot(); } +/* + * Fast drop of the complete content of all session variables hash table, and + * cleanup of any list that wouldn't be relevant anymore. + * This is used by DISCARD VARIABLES (and DISCARD ALL) command. + */ +void +ResetSessionVariables(void) +{ + /* Destroy hash table and reset related memory context */ + if (sessionvars) + { + hash_destroy(sessionvars); + sessionvars = NULL; + } + + /* Release memory allocated by session variables */ + if (SVariableMemoryContext != NULL) + MemoryContextReset(SVariableMemoryContext); +} + /* * pg_session_variables - designed for testing * diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 929a9a1fed..1b0ead9255 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -2048,7 +2048,13 @@ DiscardStmt: n->target = DISCARD_SEQUENCES; $$ = (Node *) n; } + | DISCARD VARIABLES + { + DiscardStmt *n = makeNode(DiscardStmt); + n->target = DISCARD_VARIABLES; + $$ = (Node *) n; + } ; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 475c7226e7..c5fa33e3a4 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -2963,6 +2963,9 @@ CreateCommandTag(Node *parsetree) case DISCARD_SEQUENCES: tag = CMDTAG_DISCARD_SEQUENCES; break; + case DISCARD_VARIABLES: + tag = CMDTAG_DISCARD_VARIABLES; + break; default: tag = CMDTAG_UNKNOWN; } diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 3a63a33e87..acd53742cb 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3656,7 +3656,7 @@ psql_completion(const char *text, int start, int end) /* DISCARD */ else if (Matches("DISCARD")) - COMPLETE_WITH("ALL", "PLANS", "SEQUENCES", "TEMP"); + COMPLETE_WITH("ALL", "PLANS", "SEQUENCES", "TEMP", "VARIABLES"); /* DO */ else if (Matches("DO")) diff --git a/src/include/commands/session_variable.h b/src/include/commands/session_variable.h index 53ff2a348a..e4fab99439 100644 --- a/src/include/commands/session_variable.h +++ b/src/include/commands/session_variable.h @@ -29,4 +29,6 @@ extern Datum GetSessionVariableWithTypeCheck(Oid varid, bool *isNull, Oid expect extern void ExecuteLetStmt(ParseState *pstate, LetStmt *stmt, ParamListInfo params, QueryEnvironment *queryEnv, QueryCompletion *qc); +extern void ResetSessionVariables(void); + #endif diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 493496d883..fc344ec78f 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -3790,7 +3790,8 @@ typedef enum DiscardMode DISCARD_ALL, DISCARD_PLANS, DISCARD_SEQUENCES, - DISCARD_TEMP + DISCARD_TEMP, + DISCARD_VARIABLES } DiscardMode; typedef struct DiscardStmt diff --git a/src/include/tcop/cmdtaglist.h b/src/include/tcop/cmdtaglist.h index 648a4af305..8ce00b4ea1 100644 --- a/src/include/tcop/cmdtaglist.h +++ b/src/include/tcop/cmdtaglist.h @@ -135,6 +135,7 @@ PG_CMDTAG(CMDTAG_DISCARD_ALL, "DISCARD ALL", false, false, false) PG_CMDTAG(CMDTAG_DISCARD_PLANS, "DISCARD PLANS", false, false, false) PG_CMDTAG(CMDTAG_DISCARD_SEQUENCES, "DISCARD SEQUENCES", false, false, false) PG_CMDTAG(CMDTAG_DISCARD_TEMP, "DISCARD TEMP", false, false, false) +PG_CMDTAG(CMDTAG_DISCARD_VARIABLES, "DISCARD VARIABLES", false, false, false) PG_CMDTAG(CMDTAG_DO, "DO", false, false, false) PG_CMDTAG(CMDTAG_DROP_ACCESS_METHOD, "DROP ACCESS METHOD", true, false, false) PG_CMDTAG(CMDTAG_DROP_AGGREGATE, "DROP AGGREGATE", true, false, false) diff --git a/src/test/regress/expected/session_variables.out b/src/test/regress/expected/session_variables.out index 81263c50eb..c0f624bf55 100644 --- a/src/test/regress/expected/session_variables.out +++ b/src/test/regress/expected/session_variables.out @@ -955,3 +955,66 @@ DROP VARIABLE :"DBNAME".:"DBNAME".b; DROP VARIABLE :"DBNAME".:"DBNAME".:"DBNAME"; DROP SCHEMA :"DBNAME"; RESET search_path; +-- memory cleaning by DISCARD command +CREATE VARIABLE var1 AS varchar; +LET var1 = 'Hello'; +SELECT var1; + var1 +------- + Hello +(1 row) + +DISCARD ALL; +SELECT var1; + var1 +------ + +(1 row) + +LET var1 = 'AHOJ'; +SELECT var1; + var1 +------ + AHOJ +(1 row) + +DISCARD VARIABLES; +SELECT var1; + var1 +------ + +(1 row) + +DROP VARIABLE var1; +-- initial test of debug pg_session_variables function +-- should be zero now +DISCARD VARIABLES; +SELECT count(*) FROM pg_session_variables(); + count +------- + 0 +(1 row) + +CREATE VARIABLE var1 AS varchar; +-- should be zero still +SELECT count(*) FROM pg_session_variables(); + count +------- + 0 +(1 row) + +LET var1 = 'AHOJ'; +SELECT name, typname, can_select, can_update FROM pg_session_variables(); + name | typname | can_select | can_update +------+-------------------+------------+------------ + var1 | character varying | t | t +(1 row) + +DISCARD VARIABLES; +-- should be zero again +SELECT count(*) FROM pg_session_variables(); + count +------- + 0 +(1 row) + diff --git a/src/test/regress/sql/session_variables.sql b/src/test/regress/sql/session_variables.sql index 48fb428ec9..f6f0336646 100644 --- a/src/test/regress/sql/session_variables.sql +++ b/src/test/regress/sql/session_variables.sql @@ -646,3 +646,40 @@ DROP VARIABLE :"DBNAME".:"DBNAME".:"DBNAME"; DROP SCHEMA :"DBNAME"; RESET search_path; + +-- memory cleaning by DISCARD command +CREATE VARIABLE var1 AS varchar; +LET var1 = 'Hello'; +SELECT var1; + +DISCARD ALL; +SELECT var1; + +LET var1 = 'AHOJ'; +SELECT var1; + +DISCARD VARIABLES; +SELECT var1; + +DROP VARIABLE var1; + +-- initial test of debug pg_session_variables function +-- should be zero now +DISCARD VARIABLES; + +SELECT count(*) FROM pg_session_variables(); + +CREATE VARIABLE var1 AS varchar; + +-- should be zero still +SELECT count(*) FROM pg_session_variables(); + +LET var1 = 'AHOJ'; + +SELECT name, typname, can_select, can_update FROM pg_session_variables(); + +DISCARD VARIABLES; + +-- should be zero again +SELECT count(*) FROM pg_session_variables(); + -- 2.41.0