v20250625-0004-support-of-session-variables-for-psql.patch
text/x-patch
Filename: v20250625-0004-support-of-session-variables-for-psql.patch
Type: text/x-patch
Part: 9
Message:
Re: proposal: schema variables
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v20250625-0004
Subject: support of session variables for psql
| File | + | − |
|---|---|---|
| doc/src/sgml/func.sgml | 12 | 0 |
| doc/src/sgml/ref/psql-ref.sgml | 13 | 0 |
| src/backend/catalog/namespace.c | 14 | 0 |
| src/bin/psql/command.c | 3 | 0 |
| src/bin/psql/describe.c | 99 | 1 |
| src/bin/psql/describe.h | 3 | 0 |
| src/bin/psql/help.c | 1 | 0 |
| src/bin/psql/tab-complete.in.c | 39 | 6 |
| src/include/catalog/pg_proc.dat | 3 | 0 |
| src/test/regress/expected/psql.out | 50 | 0 |
| src/test/regress/sql/psql.sql | 21 | 0 |
From 9e1294dc01a2dc720db392c0c44c44dd5b66f256 Mon Sep 17 00:00:00 2001
From: "okbob@github.com" <pavel.stehule@gmail.com>
Date: Wed, 28 May 2025 22:16:16 +0200
Subject: [PATCH 04/15] support of session variables for psql
This patch enhancing psql to support session variables:
* \dV[+] command
* tab complete for CREATE, DROP, ALTER VARIABLE
Note: tab complete for variable fencing is not supported yet
---
doc/src/sgml/func.sgml | 12 ++++
doc/src/sgml/ref/psql-ref.sgml | 13 ++++
src/backend/catalog/namespace.c | 14 ++++
src/bin/psql/command.c | 3 +
src/bin/psql/describe.c | 100 ++++++++++++++++++++++++++++-
src/bin/psql/describe.h | 3 +
src/bin/psql/help.c | 1 +
src/bin/psql/tab-complete.in.c | 45 +++++++++++--
src/include/catalog/pg_proc.dat | 3 +
src/test/regress/expected/psql.out | 50 +++++++++++++++
src/test/regress/sql/psql.sql | 21 ++++++
11 files changed, 258 insertions(+), 7 deletions(-)
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 84298bc374e..25c373b6417 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -26140,6 +26140,18 @@ SELECT relname FROM pg_class WHERE pg_table_is_visible(oid);
</para></entry>
</row>
+ <row>
+ <entry role="func_table_entry"><para role="func_signature">
+ <indexterm>
+ <primary>pg_variable_is_visible</primary>
+ </indexterm>
+ <function>pg_variable_is_visible</function> ( <parameter>variable</parameter> <type>oid</type> )
+ <returnvalue>boolean</returnvalue>
+ </para>
+ <para>
+ Is session variable visible in search path?
+ </para></entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 95f4cac2467..fb361ce034c 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -2144,6 +2144,19 @@ SELECT $1 \parse stmt1
</listitem>
</varlistentry>
+ <varlistentry id="app-psql-meta-command-dv">
+ <term><literal>\dV[+] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
+ <listitem>
+ <para>
+ Lists session variables.
+ If <replaceable class="parameter">pattern</replaceable> is
+ specified, only session variables whose names match the pattern are listed.
+ If the form <literal>\dV+</literal> is used, additional information
+ about each variable is shown, like access privileges and description.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="app-psql-meta-command-du">
<term><literal>\du[Sx+] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
<listitem>
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 4abbe733f45..b450471e063 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -5292,3 +5292,17 @@ pg_is_other_temp_schema(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(isOtherTempNamespace(oid));
}
+
+Datum
+pg_variable_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+ bool result;
+ bool is_missing = false;
+
+ result = VariableIsVisibleExt(oid, &is_missing);
+
+ if (is_missing)
+ PG_RETURN_NULL();
+ PG_RETURN_BOOL(result);
+}
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 9fcd2db8326..cf2dea845c9 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -1249,6 +1249,9 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
break;
}
break;
+ case 'V': /* Variables */
+ success = listVariables(pattern, show_verbose);
+ break;
case 'x': /* Extensions */
if (show_verbose)
success = listExtensionContents(pattern);
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index dd25d2fe7b8..a18b99c7b0b 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -1224,7 +1224,7 @@ listDefaultACLs(const char *pattern)
"SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n"
" n.nspname AS \"%s\",\n"
" CASE d.defaclobjtype "
- " WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s'"
+ " WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s'"
" WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' END AS \"%s\",\n"
" ",
gettext_noop("Owner"),
@@ -1241,6 +1241,8 @@ listDefaultACLs(const char *pattern)
gettext_noop("schema"),
DEFACLOBJ_LARGEOBJECT,
gettext_noop("large object"),
+ DEFACLOBJ_VARIABLE,
+ gettext_noop("session variable"),
gettext_noop("Type"));
printACLColumn(&buf, "d.defaclacl");
@@ -5314,6 +5316,102 @@ error_return:
return false;
}
+/*
+ * \dV
+ *
+ * listVariables()
+ */
+bool
+listVariables(const char *pattern, bool verbose)
+{
+ PQExpBufferData buf;
+ PGresult *res;
+ printQueryOpt myopt = pset.popt;
+ static const bool translate_columns[] = {false, false, false, false, false, false, false};
+
+ if (pset.sversion < 180000)
+ {
+ char sverbuf[32];
+
+ pg_log_error("The server (version %s) does not support session variables.",
+ formatPGVersionNumber(pset.sversion, false,
+ sverbuf, sizeof(sverbuf)));
+ return true;
+ }
+
+ initPQExpBuffer(&buf);
+
+ printfPQExpBuffer(&buf,
+ "SELECT n.nspname as \"%s\",\n"
+ " v.varname as \"%s\",\n"
+ " pg_catalog.format_type(v.vartype, v.vartypmod) as \"%s\",\n"
+ " (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type bt\n"
+ " WHERE c.oid = v.varcollation AND bt.oid = v.vartype AND v.varcollation <> bt.typcollation) as \"%s\",\n"
+ " pg_catalog.pg_get_userbyid(v.varowner) as \"%s\"\n",
+ gettext_noop("Schema"),
+ gettext_noop("Name"),
+ gettext_noop("Type"),
+ gettext_noop("Collation"),
+ gettext_noop("Owner"));
+
+ if (verbose)
+ {
+ appendPQExpBufferStr(&buf, ",\n ");
+ printACLColumn(&buf, "v.varacl");
+ appendPQExpBuffer(&buf,
+ ",\n pg_catalog.obj_description(v.oid, 'pg_variable') AS \"%s\"",
+ gettext_noop("Description"));
+ }
+
+ appendPQExpBufferStr(&buf,
+ "\nFROM pg_catalog.pg_variable v"
+ "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = v.varnamespace");
+
+ appendPQExpBufferStr(&buf, "\nWHERE true\n");
+ if (!pattern)
+ appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
+ " AND n.nspname <> 'information_schema'\n");
+
+ if (!validateSQLNamePattern(&buf, pattern, true, false,
+ "n.nspname", "v.varname", NULL,
+ "pg_catalog.pg_variable_is_visible(v.oid)",
+ NULL, 3))
+ return false;
+
+ appendPQExpBufferStr(&buf, "ORDER BY 1,2;");
+
+ res = PSQLexec(buf.data);
+ termPQExpBuffer(&buf);
+ if (!res)
+ return false;
+
+ /*
+ * Most functions in this file are content to print an empty table when
+ * there are no matching objects. We intentionally deviate from that
+ * here, but only in !quiet mode, for historical reasons.
+ */
+ if (PQntuples(res) == 0 && !pset.quiet)
+ {
+ if (pattern)
+ pg_log_error("Did not find any session variable named \"%s\".",
+ pattern);
+ else
+ pg_log_error("Did not find any session variables.");
+ }
+ else
+ {
+ myopt.nullPrint = NULL;
+ myopt.title = _("List of variables");
+ myopt.translate_header = true;
+ myopt.translate_columns = translate_columns;
+ myopt.n_translate_columns = lengthof(translate_columns);
+
+ printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+ }
+
+ PQclear(res);
+ return true;
+}
/*
* \dFp
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 18ecaa60949..55ced4aab7b 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -149,4 +149,7 @@ extern bool listOpFamilyFunctions(const char *access_method_pattern,
/* \dl or \lo_list */
extern bool listLargeObjects(bool verbose);
+/* \dV */
+extern bool listVariables(const char *pattern, bool varbose);
+
#endif /* DESCRIBE_H */
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index a2e009ab9be..3b821b9bc55 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -262,6 +262,7 @@ slashUsage(unsigned short int pager)
HELP0(" \\dT[Sx+] [PATTERN] list data types\n");
HELP0(" \\du[Sx+] [PATTERN] list roles\n");
HELP0(" \\dv[Sx+] [PATTERN] list views\n");
+ HELP0(" \\dV[x+] [PATTERN] list session variables\n");
HELP0(" \\dx[x+] [PATTERN] list extensions\n");
HELP0(" \\dX[x] [PATTERN] list extended statistics\n");
HELP0(" \\dy[x+] [PATTERN] list event triggers\n");
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 908eef97c6e..1579748ed75 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -970,6 +970,13 @@ static const SchemaQuery Query_for_trigger_of_table = {
.refnamespace = "c1.relnamespace",
};
+static const SchemaQuery Query_for_list_of_variables = {
+ .min_server_version = 180000,
+ .catname = "pg_catalog.pg_variable v",
+ .viscondition = "pg_catalog.pg_variable_is_visible(v.oid)",
+ .namespace = "v.varnamespace",
+ .result = "v.varname",
+};
/*
* Queries to get lists of names of various kinds of things, possibly
@@ -1318,6 +1325,7 @@ static const pgsql_thing_t words_after_create[] = {
* TABLE ... */
{"USER", Query_for_list_of_roles, NULL, NULL, Keywords_for_user_thing},
{"USER MAPPING FOR", NULL, NULL, NULL},
+ {"VARIABLE", NULL, NULL, &Query_for_list_of_variables},
{"VIEW", NULL, NULL, &Query_for_list_of_views},
{NULL} /* end of list */
};
@@ -1883,7 +1891,7 @@ psql_completion(const char *text, int start, int end)
"\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
"\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\dP", "\\dPi", "\\dPt",
"\\drds", "\\drg", "\\dRs", "\\dRp", "\\ds",
- "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dX", "\\dy",
+ "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dX", "\\dy", "\\dV",
"\\echo", "\\edit", "\\ef", "\\elif", "\\else", "\\encoding",
"\\endif", "\\endpipeline", "\\errverbose", "\\ev",
"\\f", "\\flush", "\\flushrequest",
@@ -2592,6 +2600,9 @@ match_previous_words(int pattern_id,
"ALL");
else if (Matches("ALTER", "SYSTEM", "SET", MatchAny))
COMPLETE_WITH("TO");
+ /* ALTER VARIABLE <name> */
+ else if (Matches("ALTER", "VARIABLE", MatchAny))
+ COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
/* ALTER VIEW <name> */
else if (Matches("ALTER", "VIEW", MatchAny))
COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME", "RESET", "SET");
@@ -3175,7 +3186,7 @@ match_previous_words(int pattern_id,
"ROUTINE", "RULE", "SCHEMA", "SEQUENCE", "SERVER",
"STATISTICS", "SUBSCRIPTION", "TABLE",
"TABLESPACE", "TEXT SEARCH", "TRANSFORM FOR",
- "TRIGGER", "TYPE", "VIEW");
+ "TRIGGER", "TYPE", "VARIABLE", "VIEW");
else if (Matches("COMMENT", "ON", "ACCESS", "METHOD"))
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
else if (Matches("COMMENT", "ON", "CONSTRAINT"))
@@ -3986,6 +3997,13 @@ match_previous_words(int pattern_id,
else if (TailMatches("=", MatchAnyExcept("*)")))
COMPLETE_WITH(",", ")");
}
+/* CREATE VARIABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
+ /* Complete CREATE VARIABLE <name> with AS */
+ else if (TailMatches("CREATE", "VARIABLE", MatchAny))
+ COMPLETE_WITH("AS");
+ else if (TailMatches("VARIABLE", MatchAny, "AS"))
+ /* Complete CREATE VARIABLE <name> with AS types */
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
/* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
/* Complete CREATE [ OR REPLACE ] VIEW <name> with AS or WITH */
@@ -4263,6 +4281,12 @@ 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_SCHEMA_QUERY(Query_for_list_of_variables);
+ else if (Matches("DROP", "VARIABLE", MatchAny))
+ COMPLETE_WITH("CASCADE", "RESTRICT");
+
/* EXECUTE */
else if (Matches("EXECUTE"))
COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
@@ -4464,7 +4488,9 @@ match_previous_words(int pattern_id,
* objects supported.
*/
if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
- COMPLETE_WITH("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS", "LARGE OBJECTS");
+ COMPLETE_WITH("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES",
+ "ROUTINES", "TYPES", "SCHEMAS", "LARGE OBJECTS",
+ "VARIABLES");
else
COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_grantables,
"ALL FUNCTIONS IN SCHEMA",
@@ -4472,6 +4498,7 @@ match_previous_words(int pattern_id,
"ALL ROUTINES IN SCHEMA",
"ALL SEQUENCES IN SCHEMA",
"ALL TABLES IN SCHEMA",
+ "ALL VARIABLES IN SCHEMA",
"DATABASE",
"DOMAIN",
"FOREIGN DATA WRAPPER",
@@ -4486,7 +4513,8 @@ match_previous_words(int pattern_id,
"SEQUENCE",
"TABLE",
"TABLESPACE",
- "TYPE");
+ "TYPE",
+ "VARIABLE");
}
else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL") ||
TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL"))
@@ -4494,7 +4522,8 @@ match_previous_words(int pattern_id,
"PROCEDURES IN SCHEMA",
"ROUTINES IN SCHEMA",
"SEQUENCES IN SCHEMA",
- "TABLES IN SCHEMA");
+ "TABLES IN SCHEMA",
+ "VARIABLES IN SCHEMA");
else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN") ||
TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN"))
COMPLETE_WITH("DATA WRAPPER", "SERVER");
@@ -4530,6 +4559,8 @@ match_previous_words(int pattern_id,
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
else if (TailMatches("TYPE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
+ else if (TailMatches("VARIABLE"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_variables);
else if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny))
COMPLETE_WITH("TO");
else
@@ -4832,7 +4863,7 @@ match_previous_words(int pattern_id,
/* PREPARE xx AS */
else if (Matches("PREPARE", MatchAny, "AS"))
- COMPLETE_WITH("SELECT", "UPDATE", "INSERT INTO", "DELETE FROM");
+ COMPLETE_WITH("SELECT", "UPDATE", "INSERT INTO", "DELETE FROM", "LET");
/*
* PREPARE TRANSACTION is missing on purpose. It's intended for transaction
@@ -5321,6 +5352,8 @@ match_previous_words(int pattern_id,
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
else if (TailMatchesCS("\\dv*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
+ else if (TailMatchesCS("\\dV*"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_variables);
else if (TailMatchesCS("\\dx*"))
COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
else if (TailMatchesCS("\\dX*"))
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 5da9959942c..f72acdd84bd 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6696,6 +6696,9 @@
proname => 'pg_collation_is_visible', procost => '10', provolatile => 's',
prorettype => 'bool', proargtypes => 'oid',
prosrc => 'pg_collation_is_visible' },
+{ oid => '9999', descr => 'is session variable visible in search path?',
+ proname => 'pg_variable_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid', prosrc => 'pg_variable_is_visible' },
{ oid => '2854', descr => 'get OID of current session\'s temp schema, if any',
proname => 'pg_my_temp_schema', provolatile => 's', proparallel => 'r',
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index 236eba2540e..d9b02ee99d5 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -6023,6 +6023,30 @@ COMMIT;
# final ON_ERROR_ROLLBACK: off
DROP TABLE bla;
DROP FUNCTION psql_error;
+-- session variable test
+CREATE ROLE regress_variable_owner;
+SET ROLE TO regress_variable_owner;
+CREATE VARIABLE var1 AS varchar COLLATE "C";
+\dV+ var1
+ List of variables
+ Schema | Name | Type | Collation | Owner | Access privileges | Description
+--------+------+-------------------+-----------+------------------------+-------------------+-------------
+ public | var1 | character varying | C | regress_variable_owner | |
+(1 row)
+
+GRANT SELECT ON VARIABLE var1 TO PUBLIC;
+COMMENT ON VARIABLE var1 IS 'some description';
+\dV+ var1
+ List of variables
+ Schema | Name | Type | Collation | Owner | Access privileges | Description
+--------+------+-------------------+-----------+------------------------+--------------------------------------------------+------------------
+ public | var1 | character varying | C | regress_variable_owner | regress_variable_owner=rw/regress_variable_owner+| some description
+ | | | | | =r/regress_variable_owner |
+(1 row)
+
+DROP VARIABLE var1;
+SET ROLE TO DEFAULT;
+DROP ROLE regress_variable_owner;
-- check describing invalid multipart names
\dA regression.heap
improper qualified name (too many dotted names): regression.heap
@@ -6244,6 +6268,12 @@ cross-database references are not implemented: nonesuch.public.func_deps_stat
improper qualified name (too many dotted names): regression.myevt
\dy nonesuch.myevt
improper qualified name (too many dotted names): nonesuch.myevt
+\dV host.regression.public.var
+improper qualified name (too many dotted names): host.regression.public.var
+\dV regression|mydb.public.var
+cross-database references are not implemented: regression|mydb.public.var
+\dV nonesuch.public.var
+cross-database references are not implemented: nonesuch.public.var
-- check that dots within quoted name segments are not counted
\dA "no.such.access.method"
List of access methods
@@ -6478,6 +6508,12 @@ List of schemas
------+-------+-------+---------+----------+------
(0 rows)
+\dV "no.such.variable"
+ List of variables
+ Schema | Name | Type | Collation | Owner
+--------+------+------+-----------+-------
+(0 rows)
+
-- again, but with dotted schema qualifications.
\dA "no.such.schema"."no.such.access.method"
improper qualified name (too many dotted names): "no.such.schema"."no.such.access.method"
@@ -6647,6 +6683,12 @@ improper qualified name (too many dotted names): "no.such.schema"."no.such.insta
\dy "no.such.schema"."no.such.event.trigger"
improper qualified name (too many dotted names): "no.such.schema"."no.such.event.trigger"
+\dV "no.such.schema"."no.such.variable"
+ List of variables
+ Schema | Name | Type | Collation | Owner
+--------+------+------+-----------+-------
+(0 rows)
+
-- again, but with current database and dotted schema qualifications.
\dt regression."no.such.schema"."no.such.table.relation"
List of tables
@@ -6780,6 +6822,12 @@ List of text search templates
--------+------+------------+-----------+--------------+-----
(0 rows)
+\dV regression."no.such.schema"."no.such.variable"
+ List of variables
+ Schema | Name | Type | Collation | Owner
+--------+------+------+-----------+-------
+(0 rows)
+
-- again, but with dotted database and dotted schema qualifications.
\dt "no.such.database"."no.such.schema"."no.such.table.relation"
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.table.relation"
@@ -6827,6 +6875,8 @@ cross-database references are not implemented: "no.such.database"."no.such.schem
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.data.type"
\dX "no.such.database"."no.such.schema"."no.such.extended.statistics"
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.extended.statistics"
+\dV "no.such.database"."no.such.schema"."no.such.variable"
+cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.variable"
-- check \drg and \du
CREATE ROLE regress_du_role0;
CREATE ROLE regress_du_role1;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index e2e31245439..8fd75d53afe 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -1643,6 +1643,19 @@ COMMIT;
DROP TABLE bla;
DROP FUNCTION psql_error;
+-- session variable test
+CREATE ROLE regress_variable_owner;
+SET ROLE TO regress_variable_owner;
+CREATE VARIABLE var1 AS varchar COLLATE "C";
+\dV+ var1
+GRANT SELECT ON VARIABLE var1 TO PUBLIC;
+COMMENT ON VARIABLE var1 IS 'some description';
+\dV+ var1
+DROP VARIABLE var1;
+
+SET ROLE TO DEFAULT;
+DROP ROLE regress_variable_owner;
+
-- check describing invalid multipart names
\dA regression.heap
\dA nonesuch.heap
@@ -1754,6 +1767,9 @@ DROP FUNCTION psql_error;
\dX nonesuch.public.func_deps_stat
\dy regression.myevt
\dy nonesuch.myevt
+\dV host.regression.public.var
+\dV regression|mydb.public.var
+\dV nonesuch.public.var
-- check that dots within quoted name segments are not counted
\dA "no.such.access.method"
@@ -1795,6 +1811,8 @@ DROP FUNCTION psql_error;
\dx "no.such.installed.extension"
\dX "no.such.extended.statistics"
\dy "no.such.event.trigger"
+\dV "no.such.variable"
+
-- again, but with dotted schema qualifications.
\dA "no.such.schema"."no.such.access.method"
@@ -1835,6 +1853,7 @@ DROP FUNCTION psql_error;
\dx "no.such.schema"."no.such.installed.extension"
\dX "no.such.schema"."no.such.extended.statistics"
\dy "no.such.schema"."no.such.event.trigger"
+\dV "no.such.schema"."no.such.variable"
-- again, but with current database and dotted schema qualifications.
\dt regression."no.such.schema"."no.such.table.relation"
@@ -1859,6 +1878,7 @@ DROP FUNCTION psql_error;
\dP regression."no.such.schema"."no.such.partitioned.relation"
\dT regression."no.such.schema"."no.such.data.type"
\dX regression."no.such.schema"."no.such.extended.statistics"
+\dV regression."no.such.schema"."no.such.variable"
-- again, but with dotted database and dotted schema qualifications.
\dt "no.such.database"."no.such.schema"."no.such.table.relation"
@@ -1884,6 +1904,7 @@ DROP FUNCTION psql_error;
\dP "no.such.database"."no.such.schema"."no.such.partitioned.relation"
\dT "no.such.database"."no.such.schema"."no.such.data.type"
\dX "no.such.database"."no.such.schema"."no.such.extended.statistics"
+\dV "no.such.database"."no.such.schema"."no.such.variable"
-- check \drg and \du
CREATE ROLE regress_du_role0;
--
2.49.0