v20251208-0009-use-names-of-currently-used-temp-variables-for-tab-c.patch
application/x-patch
Filename: v20251208-0009-use-names-of-currently-used-temp-variables-for-tab-c.patch
Type: application/x-patch
Part: 3
Message:
Re: proposal: schema variables
From 06dcab5ba4d22e658acb0ff62910cad249acfbd3 Mon Sep 17 00:00:00 2001
From: "okbob@github.com" <pavel.stehule@gmail.com>
Date: Thu, 4 Dec 2025 18:49:06 +0100
Subject: [PATCH 09/11] use names of currently used temp variables for tab
complete of DROP VARIABLE, LET and VARIABLE()
---
src/backend/commands/session_variable.c | 36 +++++++++++++++++++
src/bin/psql/tab-complete.in.c | 19 +++++++++-
src/include/catalog/pg_proc.dat | 5 +++
.../expected/session_variables_ddl.out | 16 +++++++++
.../regress/sql/session_variables_ddl.sql | 8 +++++
5 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/src/backend/commands/session_variable.c b/src/backend/commands/session_variable.c
index 2be23a456ab..21345217863 100644
--- a/src/backend/commands/session_variable.c
+++ b/src/backend/commands/session_variable.c
@@ -21,6 +21,7 @@
#include "commands/session_variable.h"
#include "executor/executor.h"
#include "executor/svariableReceiver.h"
+#include "funcapi.h"
#include "miscadmin.h"
#include "parser/parse_type.h"
#include "rewrite/rewriteHandler.h"
@@ -470,3 +471,38 @@ ResetSessionVariables(void)
if (SVariableMemoryContext != NULL)
MemoryContextReset(SVariableMemoryContext);
}
+
+/*
+ * pg_get_temporary_session_variables_names
+ *
+ * Returns list of temporary session variables. It is used by psql's
+ * tab complete for DROP VARIABLE and LET commands.
+ */
+Datum
+pg_get_temporary_session_variables_names(PG_FUNCTION_ARGS)
+{
+ InitMaterializedSRF(fcinfo, MAT_SRF_USE_EXPECTED_DESC);
+
+ if (sessionvars)
+ {
+ ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+ HASH_SEQ_STATUS status;
+ SVariable svar;
+
+ hash_seq_init(&status, sessionvars);
+
+ while ((svar = (SVariable) hash_seq_search(&status)) != NULL)
+ {
+ Datum values[1];
+ bool nulls[1];
+
+ values[0] = CStringGetTextDatum((NameStr(svar->varname)));
+ nulls[0] = false;
+
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
+ }
+ }
+
+ return (Datum) 0;
+}
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 4451959b81e..bef22a331ed 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -1200,6 +1200,11 @@ Keywords_for_list_of_owner_roles, "PUBLIC"
" FROM pg_catalog.pg_timezone_names() "\
" WHERE pg_catalog.quote_literal(pg_catalog.lower(name)) LIKE pg_catalog.lower('%s')"
+#define Query_for_list_of_temporary_session_variables \
+"SELECT varname "\
+" FROM pg_catalog.pg_get_temporary_session_variables_names() AS varname "\
+" WHERE varname LIKE '%s'"
+
/* Privilege options shared between GRANT and REVOKE */
#define Privilege_options_of_grant_and_revoke \
"SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER", \
@@ -4360,6 +4365,10 @@ match_previous_words(int pattern_id,
else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE", MatchAny))
COMPLETE_WITH("CASCADE", "RESTRICT");
+ /* DROP VARIABLE */
+ else if (Matches("DROP", "VARIABLE"))
+ COMPLETE_WITH_QUERY(Query_for_list_of_temporary_session_variables);
+
/* EXECUTE */
else if (Matches("EXECUTE"))
COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
@@ -4800,6 +4809,8 @@ match_previous_words(int pattern_id,
/* LET */
/* Complete LET <variable> with "=" */
+ else if (Matches("LET"))
+ COMPLETE_WITH_QUERY(Query_for_list_of_temporary_session_variables);
else if (TailMatches("LET", MatchAny))
COMPLETE_WITH("=");
@@ -5292,7 +5303,7 @@ match_previous_words(int pattern_id,
COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
"VERBOSE",
"ANALYZE",
- "ONLY");
+ "ONLY");
else if (Matches("VACUUM", MatchAnyN, "VERBOSE"))
COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
"ANALYZE",
@@ -5359,6 +5370,12 @@ match_previous_words(int pattern_id,
*/
}
+/*
+ * VARIABLE fence
+ */
+ else if (TailMatches("VARIABLE", "("))
+ COMPLETE_WITH_QUERY(Query_for_list_of_temporary_session_variables);
+
/* WITH [RECURSIVE] */
/*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index fd9448ec7b9..ac08a4de8fe 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12612,4 +12612,9 @@
proargnames => '{pid,io_id,io_generation,state,operation,off,length,target,handle_data_len,raw_result,result,target_desc,f_sync,f_localmem,f_buffered}',
prosrc => 'pg_get_aios' },
+# Session variables support
+{ oid => '8068', descr => 'returns names of temporary session variables',
+ proname => 'pg_get_temporary_session_variables_names', prorows => '1000', proretset => 't',
+ provolatile => 'v', proparallel => 'r', prorettype => 'text', proargtypes => '',
+ prosrc => 'pg_get_temporary_session_variables_names' },
]
diff --git a/src/test/regress/expected/session_variables_ddl.out b/src/test/regress/expected/session_variables_ddl.out
index c935d75fa01..b8d6f629596 100644
--- a/src/test/regress/expected/session_variables_ddl.out
+++ b/src/test/regress/expected/session_variables_ddl.out
@@ -54,3 +54,19 @@ NOTICE: session variable "x" already exists, skipping
DROP VARIABLE x;
DROP VARIABLE IF EXISTS x;
NOTICE: session variable "x" does not exists, skipping
+CREATE TEMP VARIABLE x AS int;
+CREATE TEMP VARIABLE y AS int;
+SELECT * FROM pg_get_temporary_session_variables_names();
+ pg_get_temporary_session_variables_names
+------------------------------------------
+ y
+ x
+(2 rows)
+
+DROP VARIABLE x;
+DROP VARIABLE y;
+SELECT * FROM pg_get_temporary_session_variables_names();
+ pg_get_temporary_session_variables_names
+------------------------------------------
+(0 rows)
+
diff --git a/src/test/regress/sql/session_variables_ddl.sql b/src/test/regress/sql/session_variables_ddl.sql
index 013d4fe4625..02af365338f 100644
--- a/src/test/regress/sql/session_variables_ddl.sql
+++ b/src/test/regress/sql/session_variables_ddl.sql
@@ -70,3 +70,11 @@ CREATE TEMP VARIABLE IF NOT EXISTS x AS int;
DROP VARIABLE x;
DROP VARIABLE IF EXISTS x;
+
+CREATE TEMP VARIABLE x AS int;
+CREATE TEMP VARIABLE y AS int;
+SELECT * FROM pg_get_temporary_session_variables_names();
+
+DROP VARIABLE x;
+DROP VARIABLE y;
+SELECT * FROM pg_get_temporary_session_variables_names();
--
2.52.0