Skip to content

Commit 3c6831f

Browse files
okbob@github.comCommitfest Bot
authored and
Commitfest Bot
committed
Storage for session variables and SQL interface
Session variables are stored in session memory in a dedicated hash table. They are set by the LET command and read by the SELECT command. The access rights should be checked. The identifiers of session variables should always be shadowed by possible column identifiers: we don't want to break an application by creating some badly named session variable. The limits of this patch (solved by other patches): - session variables block parallel execution - session variables blocks simple expression evaluation (in plpgsql) - SQL functions with session variables are not inlined - CALL statement is not supported (usage of direct access to express executor) - EXECUTE statement is not supported (usage of direct access to express executor) - memory used by dropped session variables is not released Implementations of EXPLAIN LET and PREPARE LET statements are in separate patches (for better readability)
1 parent a27ee09 commit 3c6831f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+4467
-27
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9831,6 +9831,19 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
98319831
</para></entry>
98329832
</row>
98339833

9834+
<row>
9835+
<entry role="catalog_table_entry"><para role="column_definition">
9836+
<structfield>varcreate_lsn</structfield> <type>pg_lsn</type>
9837+
</para>
9838+
<para>
9839+
LSN of the transaction where the variable was created.
9840+
<structfield>varcreate_lsn</structfield> and
9841+
<structfield>oid</structfield> together form the all-time unique
9842+
identifier (<structfield>oid</structfield> alone is not enough, since
9843+
object identifiers can get reused).
9844+
</para></entry>
9845+
</row>
9846+
98349847
<row>
98359848
<entry role="catalog_table_entry"><para role="column_definition">
98369849
<structfield>varname</structfield> <type>name</type>

doc/src/sgml/ddl.sgml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5385,6 +5385,67 @@ EXPLAIN SELECT count(*) FROM measurement WHERE logdate &gt;= DATE '2008-01-01';
53855385
The session variable holds value in session memory. This value is private
53865386
to each session and is released when the session ends.
53875387
</para>
5388+
5389+
<para>
5390+
The value of a session variable is set with the SQL statement
5391+
<command>LET</command>. The value of a session variable can be retrieved
5392+
with the SQL statement <command>SELECT</command>.
5393+
<programlisting>
5394+
CREATE VARIABLE var1 AS date;
5395+
LET var1 = current_date;
5396+
SELECT var1;
5397+
</programlisting>
5398+
5399+
or
5400+
5401+
<programlisting>
5402+
CREATE VARIABLE public.current_user_id AS integer;
5403+
GRANT SELECT ON VARIABLE public.current_user_id TO PUBLIC;
5404+
LET current_user_id = (SELECT id FROM users WHERE usename = session_user);
5405+
SELECT current_user_id;
5406+
</programlisting>
5407+
</para>
5408+
5409+
<para>
5410+
The value of a session variable is local to the current session. Retrieving
5411+
a variable's value returns a <literal>NULL</literal>, unless its value has
5412+
been set to something else in the current session using the
5413+
<command>LET</command> command. Session variables are not transactional:
5414+
any changes made to the value of a session variable in a transaction won't
5415+
be undone if the transaction is rolled back (just like variables in
5416+
procedural languages). Session variables themselves are persistent, but
5417+
their values are neither persistent nor shared (like the content of
5418+
temporary tables).
5419+
</para>
5420+
5421+
<para>
5422+
Inside a query or an expression, a session variable can be
5423+
<quote>shadowed</quote> by a column with the same name. Similarly, the
5424+
name of a function or procedure argument or a PL/pgSQL variable (see
5425+
<xref linkend="plpgsql-declarations"/>) can shadow a session variable
5426+
in the routine's body. Such collisions of identifiers can be resolved
5427+
by using qualified identifiers: Session variables can be qualified with
5428+
the schema name, columns can use table aliases, routine variables can use
5429+
block labels, and routine arguments can use the routine name.
5430+
<programlisting>
5431+
CREATE VARIABLE name AS text;
5432+
LET name = 'John';
5433+
5434+
CREATE TABLE foo(name text);
5435+
INSERT INTO foo VALUES('Alice');
5436+
5437+
-- variable name is shadowed
5438+
SELECT name FROM foo;
5439+
</programlisting>
5440+
5441+
which returns:
5442+
5443+
<programlisting>
5444+
name
5445+
-------
5446+
Alice
5447+
</programlisting>
5448+
</para>
53885449
</sect1>
53895450

53905451
<sect1 id="ddl-others">

doc/src/sgml/func.sgml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25860,8 +25860,8 @@ SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute');
2586025860
't' for <literal>TABLESPACE</literal>,
2586125861
'F' for <literal>FOREIGN DATA WRAPPER</literal>,
2586225862
'S' for <literal>FOREIGN SERVER</literal>,
25863-
or
25864-
'T' for <literal>TYPE</literal> or <literal>DOMAIN</literal>.
25863+
'T' for <literal>TYPE</literal> or <literal>DOMAIN</literal> or
25864+
'V' for <literal>SESSION VARIABLE</literal>.
2586525865
</para></entry>
2586625866
</row>
2586725867

doc/src/sgml/glossary.sgml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,8 +1714,9 @@
17141714
<para>
17151715
A persistent database object that holds a value in session memory. This
17161716
value is private to each session and is released when the session ends.
1717-
Read or write access to session variables is controlled by privileges,
1718-
similar to other database objects.
1717+
The default value of the session variable is null. Read or write access
1718+
to session variables is controlled by privileges, similar to other database
1719+
objects.
17191720
</para>
17201721
<para>
17211722
For more information, see <xref linkend="ddl-session-variables"/>.

doc/src/sgml/parallel.sgml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,12 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
515515
Plan nodes that reference a correlated <literal>SubPlan</literal>.
516516
</para>
517517
</listitem>
518+
519+
<listitem>
520+
<para>
521+
Plan nodes that use a session variable.
522+
</para>
523+
</listitem>
518524
</itemizedlist>
519525

520526
<sect2 id="parallel-labeling">

doc/src/sgml/plpgsql.sgml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6036,6 +6036,20 @@ $$ LANGUAGE plpgsql STRICT IMMUTABLE;
60366036
</programlisting>
60376037
</para>
60386038
</sect3>
6039+
6040+
<sect3 id="plpgsql-porting-package-variables">
6041+
<title><command>Packages and package variables</command></title>
6042+
6043+
<para>
6044+
The <application>PL/pgSQL</application> language has no packages, and
6045+
therefore no package variables or package constants.
6046+
You can consider translating an Oracle package into a schema in
6047+
<productname>PostgreSQL</productname>. Package functions and procedures
6048+
would then become functions and procedures in that schema, and package
6049+
variables could be translated to session variables in that schema.
6050+
(see <xref linkend="ddl-session-variables"/>).
6051+
</para>
6052+
</sect3>
60396053
</sect2>
60406054

60416055
<sect2 id="plpgsql-porting-appendix">

doc/src/sgml/ref/allfiles.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ Complete list of usable sgml source files in this directory.
158158
<!ENTITY grant SYSTEM "grant.sgml">
159159
<!ENTITY importForeignSchema SYSTEM "import_foreign_schema.sgml">
160160
<!ENTITY insert SYSTEM "insert.sgml">
161+
<!ENTITY let SYSTEM "let.sgml">
161162
<!ENTITY listen SYSTEM "listen.sgml">
162163
<!ENTITY load SYSTEM "load.sgml">
163164
<!ENTITY lock SYSTEM "lock.sgml">

doc/src/sgml/ref/alter_variable.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ ALTER VARIABLE boo SET SCHEMA private;
173173
<simplelist type="inline">
174174
<member><xref linkend="sql-createvariable"/></member>
175175
<member><xref linkend="sql-dropvariable"/></member>
176+
<member><xref linkend="sql-let"/></member>
176177
</simplelist>
177178
</refsect1>
178179
</refentry>

doc/src/sgml/ref/create_variable.sgml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,11 @@ CREATE VARIABLE [ IF NOT EXISTS ] <replaceable class="parameter">name</replaceab
120120
<title>Examples</title>
121121

122122
<para>
123-
Create an date session variable <literal>var1</literal>:
123+
Create a session variable <literal>var1</literal> of data type date:
124124
<programlisting>
125125
CREATE VARIABLE var1 AS date;
126+
LET var1 = current_date;
127+
SELECT var1;
126128
</programlisting>
127129
</para>
128130

@@ -143,6 +145,7 @@ CREATE VARIABLE var1 AS date;
143145
<simplelist type="inline">
144146
<member><xref linkend="sql-altervariable"/></member>
145147
<member><xref linkend="sql-dropvariable"/></member>
148+
<member><xref linkend="sql-let"/></member>
146149
</simplelist>
147150
</refsect1>
148151

doc/src/sgml/ref/drop_variable.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ DROP VARIABLE var1;
111111
<simplelist type="inline">
112112
<member><xref linkend="sql-altervariable"/></member>
113113
<member><xref linkend="sql-createvariable"/></member>
114+
<member><xref linkend="sql-let"/></member>
114115
</simplelist>
115116
</refsect1>
116117

doc/src/sgml/ref/let.sgml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<!--
2+
doc/src/sgml/ref/let.sgml
3+
PostgreSQL documentation
4+
-->
5+
6+
<refentry id="sql-let">
7+
<indexterm zone="sql-let">
8+
<primary>LET</primary>
9+
</indexterm>
10+
11+
<indexterm>
12+
<primary>session variable</primary>
13+
<secondary>changing</secondary>
14+
</indexterm>
15+
16+
<refmeta>
17+
<refentrytitle>LET</refentrytitle>
18+
<manvolnum>7</manvolnum>
19+
<refmiscinfo>SQL - Language Statements</refmiscinfo>
20+
</refmeta>
21+
22+
<refnamediv>
23+
<refname>LET</refname>
24+
<refpurpose>change a session variable's value</refpurpose>
25+
</refnamediv>
26+
27+
<refsynopsisdiv>
28+
<synopsis>
29+
LET <replaceable class="parameter">session_variable</replaceable> = <replaceable class="parameter">sql_expression</replaceable>
30+
</synopsis>
31+
</refsynopsisdiv>
32+
33+
<refsect1>
34+
<title>Description</title>
35+
36+
<para>
37+
The <command>LET</command> command assigns a value to the specified session
38+
variable.
39+
</para>
40+
41+
</refsect1>
42+
43+
<refsect1>
44+
<title>Parameters</title>
45+
46+
<variablelist>
47+
<varlistentry>
48+
<term><replaceable class="parameter">session_variable</replaceable></term>
49+
<listitem>
50+
<para>
51+
The name of the session variable.
52+
</para>
53+
</listitem>
54+
</varlistentry>
55+
56+
<varlistentry>
57+
<term><replaceable class="parameter">sql_expression</replaceable></term>
58+
<listitem>
59+
<para>
60+
An arbitrary SQL expression. The result must be of a data type that can
61+
be cast to the type of the session variable in an assignment.
62+
</para>
63+
</listitem>
64+
</varlistentry>
65+
66+
</variablelist>
67+
</refsect1>
68+
69+
<refsect1>
70+
<title>Examples</title>
71+
<programlisting>
72+
CREATE VARIABLE myvar AS integer;
73+
LET myvar = 10;
74+
LET myvar = (SELECT sum(val) FROM tab);
75+
</programlisting>
76+
</refsect1>
77+
78+
<refsect1>
79+
<title>Compatibility</title>
80+
81+
<para>
82+
The <command>LET</command> is a <productname>PostgreSQL</productname>
83+
extension.
84+
</para>
85+
</refsect1>
86+
87+
<refsect1>
88+
<title>See Also</title>
89+
90+
<simplelist type="inline">
91+
<member><xref linkend="sql-altervariable"/></member>
92+
<member><xref linkend="sql-createvariable"/></member>
93+
<member><xref linkend="sql-dropvariable"/></member>
94+
</simplelist>
95+
</refsect1>
96+
</refentry>

doc/src/sgml/reference.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@
186186
&grant;
187187
&importForeignSchema;
188188
&insert;
189+
&let;
189190
&listen;
190191
&load;
191192
&lock;

src/backend/catalog/dependency.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,6 +1864,11 @@ find_expr_references_walker(Node *node,
18641864
{
18651865
Param *param = (Param *) node;
18661866

1867+
/* a variable parameter depends on the session variable */
1868+
if (param->paramkind == PARAM_VARIABLE)
1869+
add_object_address(VariableRelationId, param->paramvarid, 0,
1870+
context->addrs);
1871+
18671872
/* A parameter must depend on the parameter's datatype */
18681873
add_object_address(TypeRelationId, param->paramtype, 0,
18691874
context->addrs);

0 commit comments

Comments
 (0)