Op 19-08-2022 om 17:29 schreef Pavel Stehule:
pá 19. 8. 2022 v 15:57 odesílatel Pavel Stehule <pavel.steh...@gmail.com>
napsal:

Hi

I am sending fresh update

- enhanced work with composite types - now the used composite type can be
enhanced, reduced and stored value is converted to expected format
- enhancing find_composite_type_dependencies to support session variables,
so the type of any field of used composite type cannot be changed


update - fix cpp check

v20220819-2-0001-Catalogue-support-for-session-variables.patch
v20220819-2-0002-session-variables.patch
v20220819-2-0003-typecheck-check-of-consistency-of-format-of-stored-v.patch
v20220819-2-0004-LET-command.patch
v20220819-2-0005-Support-of-LET-command-in-PLpgSQL.patch
v20220819-2-0006-DISCARD-VARIABLES-command.patch
v20220819-2-0007-Enhancing-psql-for-session-variables.patch
v20220819-2-0008-Possibility-to-dump-session-variables-by-pg_dump.patch
v20220819-2-0009-typedefs.patch
v20220819-2-0010-Regress-tests-for-session-variables.patch
v20220819-2-0011-fix.patch
v20220819-2-0012-This-patch-changes-error-message-column-doesn-t-exis.patch
v20220819-2-0013-documentation.patch

make check fails as a result of the errors in the attached session_variables.out.


Erik


Regards

Pavel

CREATE SCHEMA svartest;
SET search_path = svartest;
CREATE VARIABLE var1 AS integer;
CREATE TEMP VARIABLE var2 AS text;
DROP VARIABLE var1, var2;
-- functional interface
CREATE VARIABLE var1 AS numeric;
CREATE ROLE var_test_role;
GRANT USAGE ON SCHEMA svartest TO var_test_role;
SET ROLE TO var_test_role;
-- should fail
SELECT var1;
ERROR:  permission denied for session variable var1
SET ROLE TO DEFAULT;
GRANT READ ON VARIABLE var1 TO var_test_role;
SET ROLE TO var_test_role;
-- should fail
LET var1 = 10;
ERROR:  permission denied for session variable var1
-- should work
SELECT var1;
 var1 
------
     
(1 row)

SET ROLE TO DEFAULT;
GRANT WRITE ON VARIABLE var1 TO var_test_role;
SET ROLE TO var_test_role;
-- should work
LET var1 = 333;
SET ROLE TO DEFAULT;
REVOKE ALL ON VARIABLE var1 FROM var_test_role;
CREATE OR REPLACE FUNCTION secure_var()
RETURNS int AS $$
  SELECT svartest.var1::int;
$$ LANGUAGE sql SECURITY DEFINER;
SELECT secure_var();
 secure_var 
------------
        333
(1 row)

SET ROLE TO var_test_role;
-- should fail
SELECT svartest.var1;
ERROR:  permission denied for session variable var1
-- should work;
SELECT secure_var();
 secure_var 
------------
        333
(1 row)

SET ROLE TO DEFAULT;
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM generate_series(1,100) g(v) WHERE v 
= var1;
                  QUERY PLAN                   
-----------------------------------------------
 Function Scan on pg_catalog.generate_series g
   Output: v
   Function Call: generate_series(1, 100)
   Filter: ((g.v)::numeric = var1)
(4 rows)

CREATE VIEW schema_var_view AS SELECT var1;
SELECT * FROM schema_var_view;
 var1 
------
  333
(1 row)

\c -
SET search_path = svartest;
-- should work still, but var will be empty
SELECT * FROM schema_var_view;
 var1 
------
     
(1 row)

LET var1 = pi();
SELECT var1;
       var1       
------------------
 3.14159265358979
(1 row)

-- we can see execution plan of LET statement
EXPLAIN (VERBOSE, COSTS OFF) LET var1 = pi();
         QUERY PLAN         
----------------------------
 SET SESSION VARIABLE
 Result
   Output: 3.14159265358979
(3 rows)

SELECT var1;
       var1       
------------------
 3.14159265358979
(1 row)

CREATE VARIABLE var3 AS int;
CREATE OR REPLACE FUNCTION inc(int)
RETURNS int AS $$
BEGIN
  LET svartest.var3 = COALESCE(svartest.var3 + $1, $1);
  RETURN var3;
END;
$$ LANGUAGE plpgsql;
SELECT inc(1);
 inc 
-----
   1
(1 row)

SELECT inc(1);
 inc 
-----
   2
(1 row)

SELECT inc(1);
 inc 
-----
   3
(1 row)

SELECT inc(1) FROM generate_series(1,10);
 inc 
-----
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
(10 rows)

SET ROLE TO var_test_role;
-- should fail
LET var3 = 0;
ERROR:  permission denied for session variable var3
SET ROLE TO DEFAULT;
DROP VIEW schema_var_view;
DROP VARIABLE var1 CASCADE;
DROP VARIABLE var3 CASCADE;
-- composite variables
CREATE TYPE sv_xyz AS (x int, y int, z numeric(10,2));
CREATE VARIABLE v1 AS sv_xyz;
CREATE VARIABLE v2 AS sv_xyz;
\d v1
\d v2
LET v1 = (1,2,3.14);
LET v2 = (10,20,3.14*10);
-- should work too - there are prepared casts
LET v1 = (1,2,3.14);
SELECT v1;
     v1     
------------
 (1,2,3.14)
(1 row)

SELECT v2;
      v2       
---------------
 (10,20,31.40)
(1 row)

SELECT (v1).*;
 x | y |  z   
---+---+------
 1 | 2 | 3.14
(1 row)

SELECT (v2).*;
 x  | y  |   z   
----+----+-------
 10 | 20 | 31.40
(1 row)

SELECT v1.x + v1.z;
 ?column? 
----------
     4.14
(1 row)

SELECT v2.x + v2.z;
 ?column? 
----------
    41.40
(1 row)

-- access to composite fields should be safe too
-- should fail
SET ROLE TO var_test_role;
SELECT v2.x;
ERROR:  permission denied for session variable v2
SET ROLE TO DEFAULT;
DROP VARIABLE v1;
DROP VARIABLE v2;
REVOKE USAGE ON SCHEMA svartest FROM var_test_role;
DROP ROLE var_test_role;
-- scalar variables should not be in conflict with qualified column
CREATE VARIABLE varx AS text;
SELECT varx.relname FROM pg_class varx WHERE varx.relname = 'pg_class';
 relname  
----------
 pg_class
(1 row)

-- should fail
SELECT varx.xxx;
ERROR:  type text is not composite
-- variables can be updated under RO transaction
BEGIN;
SET TRANSACTION READ ONLY;
LET varx = 'hello';
COMMIT;
SELECT varx;
 varx  
-------
 hello
(1 row)

DROP VARIABLE varx;
CREATE TYPE t1 AS (a int, b numeric, c text);
CREATE VARIABLE v1 AS t1;
LET v1 = (1, pi(), 'hello');
SELECT v1;
             v1             
----------------------------
 (1,3.14159265358979,hello)
(1 row)

LET v1.b = 10.2222;
SELECT v1;
        v1         
-------------------
 (1,10.2222,hello)
(1 row)

-- should fail
LET v1.x = 10;
ERROR:  cannot assign to field "x" of column or variable "v1" because there is 
no such column in data type t1
LINE 1: LET v1.x = 10;
            ^
DROP VARIABLE v1;
DROP TYPE t1;
-- arrays are supported
CREATE VARIABLE va1 AS numeric[];
LET va1 = ARRAY[1.1,2.1];
LET va1[1] = 10.1;
SELECT va1;
    va1     
------------
 {10.1,2.1}
(1 row)

CREATE TYPE ta2 AS (a numeric, b numeric[]);
CREATE VARIABLE va2 AS ta2;
LET va2 = (10.1, ARRAY[0.0, 0.0]);
LET va2.a = 10.2;
SELECT va2;
        va2         
--------------------
 (10.2,"{0.0,0.0}")
(1 row)

LET va2.b[1] = 10.3;
SELECT va2;
         va2         
---------------------
 (10.2,"{10.3,0.0}")
(1 row)

DROP VARIABLE va1;
DROP VARIABLE va2;
DROP TYPE ta2;
-- default values
CREATE VARIABLE v1 AS numeric DEFAULT pi();
LET v1 = v1 * 2;
SELECT v1;
        v1        
------------------
 6.28318530717958
(1 row)

CREATE TYPE t2 AS (a numeric, b text);
CREATE VARIABLE v2 AS t2 DEFAULT (NULL, 'Hello');
LET svartest.v2.a = pi();
SELECT v2;
            v2            
--------------------------
 (3.14159265358979,Hello)
(1 row)

-- should fail due dependency
DROP TYPE t2;
ERROR:  cannot drop type t2 because other objects depend on it
DETAIL:  session variable v2 depends on type t2
HINT:  Use DROP ... CASCADE to drop the dependent objects too.
-- should be ok
DROP VARIABLE v1;
DROP VARIABLE v2;
-- tests of alters
CREATE SCHEMA var_schema1;
CREATE SCHEMA var_schema2;
CREATE VARIABLE var_schema1.var1 AS integer;
LET var_schema1.var1 = 1000;
SELECT var_schema1.var1;
 var1 
------
 1000
(1 row)

ALTER VARIABLE var_schema1.var1 SET SCHEMA var_schema2;
SELECT var_schema2.var1;
 var1 
------
 1000
(1 row)

CREATE ROLE var_test_role;
ALTER VARIABLE var_schema2.var1 OWNER TO var_test_role;
SET ROLE TO var_test_role;
-- should fail, no access to schema var_schema2.var
SELECT var_schema2.var1;
ERROR:  permission denied for schema var_schema2
DROP VARIABLE var_schema2.var1;
ERROR:  permission denied for schema var_schema2
SET ROLE TO DEFAULT;
ALTER VARIABLE var_schema2.var1 SET SCHEMA public;
SET ROLE TO var_test_role;
SELECT public.var1;
 var1 
------
 1000
(1 row)

ALTER VARIABLE public.var1 RENAME TO var1_renamed;
SELECT public.var1_renamed;
 var1_renamed 
--------------
         1000
(1 row)

DROP VARIABLE public.var1_renamed;
SET ROLE TO DEFAULt;
-- default rights test
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON VARIABLES TO 
var_test_role;
CREATE VARIABLE public.var2 AS int;
SET ROLE TO var_test_role;
-- should be ok
LET public.var2 = 100;
SELECT public.var2;
 var2 
------
  100
(1 row)

SET ROLE TO DEFAULt;
DROP VARIABLE public.var2;
DROP OWNED BY var_test_role;
DROP ROLE var_test_role;
CREATE VARIABLE xx AS text DEFAULT 'hello';
SELECT xx, upper(xx);
  xx   | upper 
-------+-------
 hello | HELLO
(1 row)

LET xx = 'Hi';
SELECT xx;
 xx 
----
 Hi
(1 row)

DROP VARIABLE xx;
-- ON TRANSACTION END RESET tests
CREATE VARIABLE t1 AS int DEFAULT -1 ON TRANSACTION END RESET;
BEGIN;
  SELECT t1;
 t1 
----
 -1
(1 row)

  LET t1 = 100;
  SELECT t1;
 t1  
-----
 100
(1 row)

COMMIT;
SELECT t1;
 t1 
----
 -1
(1 row)

BEGIN;
  SELECT t1;
 t1 
----
 -1
(1 row)

  LET t1 = 100;
  SELECT t1;
 t1  
-----
 100
(1 row)

ROLLBACK;
SELECT t1;
 t1 
----
 -1
(1 row)

DROP VARIABLE t1;
CREATE VARIABLE v1 AS int DEFAULT 0;
CREATE VARIABLE v2 AS text DEFAULT 'none';
LET v1 = 100;
LET v2 = 'Hello';
SELECT v1, v2;
 v1  |  v2   
-----+-------
 100 | Hello
(1 row)

LET v1 = DEFAULT;
LET v2 = DEFAULT;
SELECT v1, v2;
 v1 |  v2  
----+------
  0 | none
(1 row)

DROP VARIABLE v1;
DROP VARIABLE v2;
-- ON COMMIT DROP tests
-- should be 0 always
SELECT count(*) FROM pg_variable;
 count 
-------
     0
(1 row)

CREATE TEMP VARIABLE g AS int ON COMMIT DROP;
SELECT count(*) FROM pg_variable;
 count 
-------
     0
(1 row)

BEGIN;
  CREATE TEMP VARIABLE g AS int ON COMMIT DROP;
COMMIT;
SELECT count(*) FROM pg_variable;
 count 
-------
     0
(1 row)

BEGIN;
  CREATE TEMP VARIABLE g AS int ON COMMIT DROP;
ROLLBACK;
SELECT count(*) FROM pg_variable;
 count 
-------
     0
(1 row)

-- test on query with workers
CREATE TABLE svar_test(a int);
INSERT INTO svar_test SELECT * FROM generate_series(1,1000000);
ANALYZE svar_test;
CREATE VARIABLE zero int;
LET zero = 0;
-- parallel workers should be used
EXPLAIN (costs off) SELECT count(*) FROM svar_test WHERE a%10 = zero;
                    QUERY PLAN                    
--------------------------------------------------
 Finalize Aggregate
   ->  Gather
         Workers Planned: 2
         ->  Partial Aggregate
               ->  Parallel Seq Scan on svar_test
                     Filter: ((a % 10) = zero)
(6 rows)

-- result should be 100000
SELECT count(*) FROM svar_test WHERE a%10 = zero;
 count  
--------
 100000
(1 row)

LET zero = (SELECT count(*) FROM svar_test);
-- result should be 1000000
SELECT zero;
  zero   
---------
 1000000
(1 row)

-- parallel workers should be used
EXPLAIN (costs off) LET zero = (SELECT count(*) FROM svar_test);
                        QUERY PLAN                        
----------------------------------------------------------
 SET SESSION VARIABLE
 Result
   InitPlan 1 (returns $1)
     ->  Finalize Aggregate
           ->  Gather
                 Workers Planned: 2
                 ->  Partial Aggregate
                       ->  Parallel Seq Scan on svar_test
(8 rows)

DROP TABLE svar_test;
DROP VARIABLE zero;
-- use variables in prepared statements
CREATE VARIABLE v AS numeric;
LET v = 3.14;
-- use variables in views
CREATE VIEW vv AS SELECT COALESCE(v, 0) + 1000 AS result;
SELECT * FROM vv;
 result  
---------
 1003.14
(1 row)

-- start a new session
\c
SET search_path to svartest;
SELECT * FROM vv;
 result 
--------
   1000
(1 row)

LET v = 3.14;
SELECT * FROM vv;
 result  
---------
 1003.14
(1 row)

-- should fail, dependency
DROP VARIABLE v;
ERROR:  cannot drop session variable v because other objects depend on it
DETAIL:  view vv depends on session variable v
HINT:  Use DROP ... CASCADE to drop the dependent objects too.
-- should be ok
DROP VARIABLE v CASCADE;
NOTICE:  drop cascades to view vv
-- other features
CREATE VARIABLE dt AS integer DEFAULT 0;
LET dt = 100;
SELECT dt;
 dt  
-----
 100
(1 row)

DISCARD VARIABLES;
SELECT dt;
 dt 
----
  0
(1 row)

DROP VARIABLE dt;
-- NOT NULL
CREATE VARIABLE v1 AS int NOT NULL;
CREATE VARIABLE v2 AS int NOT NULL DEFAULT NULL;
-- should fail
SELECT v1;
ERROR:  null value is not allowed for NOT NULL session variable "svartest.v1"
DETAIL:  The session variable was not initialized yet.
SELECT v2;
ERROR:  null value is not allowed for NOT NULL session variable "svartest.v2"
LET v1 = NULL;
ERROR:  null value is not allowed for NOT NULL session variable "svartest.v1"
LET v2 = NULL;
ERROR:  null value is not allowed for NOT NULL session variable "svartest.v2"
LET v1 = DEFAULT;
ERROR:  null value is not allowed for NOT NULL session variable "svartest.v1"
LET v2 = DEFAULT;
ERROR:  null value is not allowed for NOT NULL session variable "svartest.v2"
-- should be ok
LET v1 = 100;
LET v2 = 1000;
SELECT v1, v2;
 v1  |  v2  
-----+------
 100 | 1000
(1 row)

DROP VARIABLE v1;
DROP VARIABLE v2;
CREATE VARIABLE tv AS int;
CREATE VARIABLE IF NOT EXISTS tv AS int;
NOTICE:  session variable "tv" already exists, skipping
DROP VARIABLE tv;
CREATE IMMUTABLE VARIABLE iv AS int DEFAULT 100;
SELECT iv;
 iv  
-----
 100
(1 row)

-- should fail;
LET iv = 10000;
ERROR:  session variable "svartest.iv" is declared IMMUTABLE
DROP VARIABLE iv;
-- different order
CREATE IMMUTABLE VARIABLE iv AS int DEFAULT 100;
-- should to fail
LET iv = 10000;
ERROR:  session variable "svartest.iv" is declared IMMUTABLE
-- should be ok
SELECT iv;
 iv  
-----
 100
(1 row)

DROP VARIABLE iv;
CREATE IMMUTABLE VARIABLE iv AS int;
-- should be ok
LET iv = NULL;
-- should fail
LET iv = NULL;
ERROR:  session variable "svartest.iv" is declared IMMUTABLE
DROP VARIABLE iv;
-- create variable inside plpgsql block
DO $$
BEGIN
  CREATE VARIABLE do_test_svar AS date DEFAULT '2000-01-01';
END;
$$;
SELECT do_test_svar;
 do_test_svar 
--------------
 01-01-2000
(1 row)

DROP VARIABLE do_test_svar;
-- should fail
CREATE IMMUTABLE VARIABLE xx AS int NOT NULL;
ERROR:  IMMUTABLE NOT NULL variable requires default expression
-- REASSIGN OWNED test
CREATE ROLE var_test_role1;
CREATE ROLE var_test_role2;
CREATE VARIABLE xxx_var AS int;
ALTER VARIABLE xxx_var OWNER TO var_test_role1;
REASSIGN OWNED BY var_test_role1 to var_test_role2;
SELECT varowner::regrole FROM pg_variable WHERE varname = 'xxx_var';
    varowner    
----------------
 var_test_role2
(1 row)

DROP OWNED BY var_test_role1;
DROP ROLE var_test_role1;
SELECT count(*) FROM pg_variable WHERE varname = 'xxx_var';
 count 
-------
     1
(1 row)

DROP OWNED BY var_test_role2;
DROP ROLE var_test_role2;
SELECT count(*) FROM pg_variable WHERE varname = 'xxx_var';
 count 
-------
     0
(1 row)

-- creating, dropping temporary variable
BEGIN;
CREATE TEMP VARIABLE tempvar AS INT ON COMMIT DROP;
LET tempvar = 100;
SAVEPOINT s1;
DROP VARIABLE tempvar;
ROLLBACK TO s1;
SELECT tempvar;
 tempvar 
---------
     100
(1 row)

COMMIT;
-- should to fail
LET tempvar = 100;
ERROR:  session variable "tempvar" doesn't exist
LINE 1: LET tempvar = 100;
            ^
BEGIN;
SAVEPOINT s1;
CREATE TEMP VARIABLE tempvar AS INT ON COMMIT DROP;
LET tempvar = 100;
ROLLBACK TO s1;
COMMIT;
-- should to fail
LET tempvar = 100;
ERROR:  session variable "tempvar" doesn't exist
LINE 1: LET tempvar = 100;
            ^
CREATE VARIABLE var1 AS int;
LET var1 = 100;
BEGIN;
DROP VARIABLE var1;
ROLLBACK;
SELECT var1;
 var1 
------
  100
(1 row)

DROP VARIABLE var1;
CREATE VARIABLE var1 AS int DEFAULT 100;
COMMENT ON VARIABLE var1 IS 'some variable comment';
SELECT pg_catalog.obj_description(oid, 'pg_variable') FROM pg_variable WHERE 
varname = 'var1';
    obj_description    
-----------------------
 some variable comment
(1 row)

DROP VARIABLE var1;
CREATE TABLE xxtab(avar int);
CREATE TYPE xxtype AS (avar int);
CREATE VARIABLE xxtab AS xxtype;
INSERT INTO xxtab VALUES(10);
-- it is ambiguous, but columns are preferred
SELECT xxtab.avar FROM xxtab;
 avar 
------
   10
(1 row)

SET session_variables_ambiguity_warning TO on;
SELECT xxtab.avar FROM xxtab;
WARNING:  session variable "xxtab.avar" is shadowed
LINE 1: SELECT xxtab.avar FROM xxtab;
               ^
DETAIL:  Session variables can be shadowed by columns, routine's variables and 
routine's arguments with same name.
 avar 
------
   10
(1 row)

SET search_path = svartest;
CREATE VARIABLE testvar as int;
-- plpgsql variables are preferred against session variables
DO $$
<<myblock>>
DECLARE testvar int;
BEGIN
  -- should be ok without warning
  LET testvar = 100;
  -- should be ok without warning
  testvar := 1000;
  -- should be ok without warning
  RAISE NOTICE 'session variable is %', svartest.testvar;
  -- should be ok without warning
  RAISE NOTICE 'plpgsql variable is %', myblock.testvar;
  -- should to print plpgsql variable with warning
  RAISE NOTICE 'variable is %', testvar;
END;
$$;
NOTICE:  session variable is 100
NOTICE:  plpgsql variable is 1000
WARNING:  session variable "testvar" is shadowed
LINE 1: testvar
        ^
DETAIL:  Session variables can be shadowed by columns, routine's variables and 
routine's arguments with same name.
QUERY:  testvar
NOTICE:  variable is 1000
DROP VARIABLE testvar;
SET session_variables_ambiguity_warning TO default;
-- should be ok
SELECT avar FROM xxtab;
 avar 
------
   10
(1 row)

CREATE VARIABLE public.avar AS int;
-- should to fail
SELECT avar FROM xxtab;
 avar 
------
   10
(1 row)

-- should be ok
SELECT public.avar FROM xxtab;
 avar 
------
     
(1 row)

DROP VARIABLE xxtab;
SELECT xxtab.avar FROM xxtab;
 avar 
------
   10
(1 row)

DROP VARIABLE public.avar;
DROP TYPE xxtype;
DROP TABLE xxtab;
-- test of plan cache invalidation
CREATE VARIABLE xx AS int;
SET plan_cache_mode = force_generic_plan;
PREPARE pp AS SELECT xx;
EXECUTE pp;
 xx 
----
   
(1 row)

DROP VARIABLE xx;
CREATE VARIABLE xx AS int;
-- should to work
EXECUTE pp;
 xx 
----
   
(1 row)

DROP VARIABLE xx;
DEALLOCATE pp;
SET plan_cache_mode = DEFAULT;
CREATE ROLE var_test_role;
CREATE SCHEMA vartest;
GRANT USAGE ON SCHEMA vartest TO var_test_role;
CREATE VARIABLE vartest.x AS int;
CREATE VARIABLE vartest.y AS int;
LET vartest.x = 100;
LET vartest.y = 101;
GRANT READ ON ALL VARIABLES IN SCHEMA vartest TO var_test_role;
SET ROLE TO var_test_role;
SELECT vartest.x, vartest.y;
  x  |  y  
-----+-----
 100 | 101
(1 row)

SET ROLE TO DEFAULT;
REVOKE READ ON ALL VARIABLES IN SCHEMA vartest FROM var_test_role;
SET ROLE TO var_test_role;
-- should to fail
SELECT vartest.x;
ERROR:  permission denied for session variable x
SELECT vartest.y;
ERROR:  permission denied for session variable y
SET ROLE TO DEFAULT;
DROP VARIABLE vartest.x, vartest.y;
DROP SCHEMA vartest;
DROP ROLE var_test_role;
-- test cached plan
CREATE VARIABLE v1 AS text;
CREATE VARIABLE v2 AS int;
CREATE VARIABLE v3 AS int;
LET v1 = 'test';
LET v2 = 10;
LET v3 = 5;
PREPARE q1 AS SELECT v1 || i FROM generate_series(1, v2) g(i) WHERE i IN (v2, 
v3);
SET plan_cache_mode to force_generic_plan;
EXECUTE q1;
 ?column? 
----------
 test5
 test10
(2 rows)

EXPLAIN EXECUTE q1;
                              QUERY PLAN                               
-----------------------------------------------------------------------
 Function Scan on generate_series g  (cost=0.00..0.14 rows=2 width=32)
   Filter: (i = ANY (ARRAY[v2, v3]))
(2 rows)

-- dependecy check
DROP VARIABLE v3;
-- recreate v3 again
CREATE VARIABLE v3 AS int DEFAULT 6;
-- should to work, the plan should be recreated
EXECUTE q1;
 ?column? 
----------
 test6
 test10
(2 rows)

DEALLOCATE q1;
-- fill v1 by long text
LET v1 = repeat(' ', 10000);
PREPARE q1 AS SELECT length(v1);
EXECUTE q1;
 length 
--------
  10000
(1 row)

LET v1 = repeat(' ', 5000);
EXECUTE q1;
 length 
--------
   5000
(1 row)

DEALLOCATE q1;
SET plan_cache_mode to default;
DROP VARIABLE v1, v2, v3;
CREATE ROLE var_test_role;
CREATE VARIABLE public.v1 AS int DEFAULT 0;
-- check acl when variable is acessed by simple eval expr method
CREATE OR REPLACE FUNCTION public.fx_var(int)
RETURNS int AS $$
DECLARE xx int;
BEGIN
  xx := public.v1 + $1;
  RETURN xx;
END;
$$ LANGUAGE plpgsql;
-- should be ok
SELECT public.fx_var(0);
 fx_var 
--------
      0
(1 row)

SET ROLE TO var_test_role;
-- should to fail
SELECT public.fx_var(0);
ERROR:  permission denied for session variable v1
CONTEXT:  PL/pgSQL function public.fx_var(integer) line 4 at assignment
SET ROLE TO default;
GRANT READ ON VARIABLE public.v1 TO var_test_role;
SET ROLE TO var_test_role;
-- should be ok
SELECT public.fx_var(0);
 fx_var 
--------
      0
(1 row)

SET ROLE TO default;
REVOKE READ ON VARIABLE public.v1 FROM var_test_role;
SET ROLE TO var_test_role;
-- should be fail
SELECT public.fx_var(0);
ERROR:  permission denied for session variable v1
CONTEXT:  PL/pgSQL function public.fx_var(integer) line 4 at assignment
SET ROLE TO DEFAULT;
DROP FUNCTION public.fx_var(int);
DROP VARIABLE public.v1;
DROP ROLE var_test_role;
CREATE TYPE public.svar_test_type AS (a int, b int, c numeric);
CREATE VARIABLE public.svar AS public.svar_test_type;
LET public.svar = ROW(10,20,30);
SELECT public.svar;
    svar    
------------
 (10,20,30)
(1 row)

ALTER TYPE public.svar_test_type DROP ATTRIBUTE c;
-- should to fail
SELECT public.svar;
  svar   
---------
 (10,20)
(1 row)

ALTER TYPE public.svar_test_type ADD ATTRIBUTE c int;
-- should to fail too (different type, different generation number);
SELECT public.svar;
   svar   
----------
 (10,20,)
(1 row)

LET public.svar = ROW(10,20,30);
-- should be ok again for new value
SELECT public.svar;
    svar    
------------
 (10,20,30)
(1 row)

DROP VARIABLE public.svar;
DROP TYPE public.svar_test_type;
CREATE VARIABLE public.svar AS int;
SELECT schema, name, removed FROM pg_debug_show_used_session_variables();
 schema | name | removed 
--------+------+---------
(0 rows)

LET public.svar = 100;
SELECT schema, name, removed FROM pg_debug_show_used_session_variables();
 schema | name | removed 
--------+------+---------
 public | svar | f
(1 row)

BEGIN;
DROP VARIABLE public.svar;
-- value should be in memory
SELECT schema, name, removed FROM pg_debug_show_used_session_variables();
 schema | name | removed 
--------+------+---------
 public | svar | t
(1 row)

ROLLBACK;
-- value should be in memory
SELECT schema, name, removed FROM pg_debug_show_used_session_variables() WHERE 
schema = 'public' and name = 'svar';
 schema | name | removed 
--------+------+---------
 public | svar | f
(1 row)

SELECT public.svar;
 svar 
------
  100
(1 row)

BEGIN;
DROP VARIABLE public.svar;
-- value should be in memory
SELECT schema, name, removed FROM pg_debug_show_used_session_variables() WHERE 
schema = 'public' and name = 'svar';
 schema | name | removed 
--------+------+---------
 public | svar | t
(1 row)

COMMIT;
-- the memory should be clean;
SELECT schema, name, removed FROM pg_debug_show_used_session_variables() WHERE 
schema = 'public' and name = 'svar';
 schema | name | removed 
--------+------+---------
(0 rows)

BEGIN;
CREATE VARIABLE public.svar AS int;
LET public.svar = 100;
ROLLBACK;
-- the memory should be clean;
SELECT schema, name, removed FROM pg_debug_show_used_session_variables() WHERE 
schema = 'public' and name = 'svar';
 schema | name | removed 
--------+------+---------
(0 rows)

CREATE VARIABLE public.svar AS int;
LET public.svar = 100;
-- repeated aborted transaction
BEGIN; DROP VARIABLE public.svar; ROLLBACK;
BEGIN; DROP VARIABLE public.svar; ROLLBACK;
BEGIN; DROP VARIABLE public.svar; ROLLBACK;
-- the value should be still available
SELECT public.svar;
 svar 
------
  100
(1 row)

DROP VARIABLE public.svar;
CREATE TYPE public.svar_test_type AS (a int, b int);
CREATE VARIABLE public.svar AS public.svar_test_type;
SELECT public.svar;
 svar 
------
 
(1 row)

ALTER TYPE public.svar_test_type ADD ATTRIBUTE c int;
SELECT public.svar;
 svar 
------
 
(1 row)

ALTER TYPE public.svar_test_type DROP ATTRIBUTE b;
SELECT public.svar;
 svar 
------
 
(1 row)

DROP VARIABLE public.svar;
DROP TYPE public.svar_test_type;
CREATE TYPE public.svar_test_type AS (a int, b int);
CREATE VARIABLE public.svar AS public.svar_test_type;
CREATE VARIABLE public.svar2 AS public.svar_test_type;
LET public.svar = (10, 20);
ALTER TYPE public.svar_test_type ADD ATTRIBUTE c int;
SELECT public.svar;
   svar   
----------
 (10,20,)
(1 row)

LET public.svar2 = (10, 20, 30);
ALTER TYPE public.svar_test_type DROP ATTRIBUTE b;
SELECT public.svar;
 svar  
-------
 (10,)
(1 row)

SELECT public.svar2;
  svar2  
---------
 (10,30)
(1 row)

DROP VARIABLE public.svar;
DROP VARIABLE public.svar2;
DROP TYPE public.svar_test_type;
-- The composite type cannot be changed when it is used
CREATE TYPE public.svar_type AS (a int, b int);
CREATE VARIABLE public.svar AS public.svar_type;
-- should to fail
ALTER TYPE public.svar_type ALTER ATTRIBUTE b TYPE numeric;
ERROR:  cannot alter type "svar_type" because session variable "public.svar" 
uses it
DROP VARIABLE public.svar;
CREATE TYPE public.svar_type2 AS (a int, b int, c public.svar_type);
CREATE VARIABLE public.svar AS public.svar_type2;
-- should to fail
ALTER TYPE public.svar_type ALTER ATTRIBUTE b TYPE numeric;
ERROR:  cannot alter type "svar_type" because session variable "public.svar" 
uses it
DROP VARIABLE public.svar;
DROP TYPE public.svar_type2;
DROP TYPE public.svar_type;

Reply via email to