From 2806cf758eb9b20aa94e79df650503d0cfb37d2a Mon Sep 17 00:00:00 2001
From: Maxim Orlov <m.orlov@postgrespro.ru>
Date: Wed, 23 Jun 2021 17:28:33 +0300
Subject: [PATCH] Add support for PostgreSQL 14.

---
 expected/pg_variables_trans_0.out | 3840 +++++++++++++++++++++++++++++
 pg_variables.c                    |   16 +-
 2 files changed, 3853 insertions(+), 3 deletions(-)
 create mode 100644 expected/pg_variables_trans_0.out

diff --git a/expected/pg_variables_trans_0.out b/expected/pg_variables_trans_0.out
new file mode 100644
index 0000000..7c29138
--- /dev/null
+++ b/expected/pg_variables_trans_0.out
@@ -0,0 +1,3840 @@
+SET timezone = 'Europe/Moscow'; -- Need to proper output of datetime variables
+--CHECK SAVEPOINT RELEASE
+BEGIN;
+-- Declare variables
+SELECT pgv_set('vars', 'any1', 'some value'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set('vars', 'any2', 'some value'::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set_int('vars', 'int1', 101, true);
+ pgv_set_int 
+-------------
+ 
+(1 row)
+
+SELECT pgv_set_int('vars', 'int2', 102);
+ pgv_set_int 
+-------------
+ 
+(1 row)
+
+SELECT pgv_set_int('vars', 'intNULL', NULL, true);
+ pgv_set_int 
+-------------
+ 
+(1 row)
+
+SELECT pgv_set_text('vars', 'str1', 's101', true);
+ pgv_set_text 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_text('vars', 'str2', 's102');
+ pgv_set_text 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_numeric('vars', 'num1', 1.01, true);
+ pgv_set_numeric 
+-----------------
+ 
+(1 row)
+
+SELECT pgv_set_numeric('vars', 'num2', 1.02);
+ pgv_set_numeric 
+-----------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamp('vars', 'ts1', '2016-03-30 10:00:00', true);
+ pgv_set_timestamp 
+-------------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamp('vars', 'ts2', '2016-03-30 11:00:00');
+ pgv_set_timestamp 
+-------------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamptz('vars', 'tstz1', '2016-03-30 10:00:00 GMT+01', true);
+ pgv_set_timestamptz 
+---------------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamptz('vars', 'tstz2', '2016-03-30 11:00:00 GMT+02');
+ pgv_set_timestamptz 
+---------------------
+ 
+(1 row)
+
+SELECT pgv_set_date('vars', 'd1', '2016-03-29', true);
+ pgv_set_date 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_date('vars', 'd2', '2016-03-30');
+ pgv_set_date 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_jsonb('vars2', 'j1', '[1, 2, "foo", null]', true);
+ pgv_set_jsonb 
+---------------
+ 
+(1 row)
+
+SELECT pgv_set_jsonb('vars2', 'j2', '{"bar": "baz", "balance": 7.77, "active": false}');
+ pgv_set_jsonb 
+---------------
+ 
+(1 row)
+
+SAVEPOINT comm;
+-- Set new values
+SELECT pgv_set('vars', 'any1', 'another value'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set('vars', 'any2', 'another value'::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set_int('vars', 'int1', 103, true);
+ pgv_set_int 
+-------------
+ 
+(1 row)
+
+SELECT pgv_set_int('vars', 'int2', 103);
+ pgv_set_int 
+-------------
+ 
+(1 row)
+
+SELECT pgv_set_int('vars', 'intNULL', 104, true);
+ pgv_set_int 
+-------------
+ 
+(1 row)
+
+SELECT pgv_set_text('vars', 'str1', 's103', true);
+ pgv_set_text 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_text('vars', 'str2', 's103');
+ pgv_set_text 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_numeric('vars', 'num1', 1.03, true);
+ pgv_set_numeric 
+-----------------
+ 
+(1 row)
+
+SELECT pgv_set_numeric('vars', 'num2', 1.03);
+ pgv_set_numeric 
+-----------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamp('vars', 'ts1', '2016-03-30 12:00:00', true);
+ pgv_set_timestamp 
+-------------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamp('vars', 'ts2', '2016-03-30 12:00:00');
+ pgv_set_timestamp 
+-------------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamptz('vars', 'tstz1', '2016-03-30 12:00:00 GMT+03', true);
+ pgv_set_timestamptz 
+---------------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamptz('vars', 'tstz2', '2016-03-30 12:00:00 GMT+03');
+ pgv_set_timestamptz 
+---------------------
+ 
+(1 row)
+
+SELECT pgv_set_date('vars', 'd1', '2016-04-02', true);
+ pgv_set_date 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_date('vars', 'd2', '2016-04-02');
+ pgv_set_date 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_jsonb('vars2', 'j1', '{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}', true);
+ pgv_set_jsonb 
+---------------
+ 
+(1 row)
+
+SELECT pgv_set_jsonb('vars2', 'j2', '{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}');
+ pgv_set_jsonb 
+---------------
+ 
+(1 row)
+
+-- Check values before releasing savepoint
+SELECT pgv_get('vars', 'any1',NULL::text);
+    pgv_get    
+---------------
+ another value
+(1 row)
+
+SELECT pgv_get('vars', 'any2',NULL::text);
+    pgv_get    
+---------------
+ another value
+(1 row)
+
+SELECT pgv_get_int('vars', 'int1');
+ pgv_get_int 
+-------------
+         103
+(1 row)
+
+SELECT pgv_get_int('vars', 'int2');
+ pgv_get_int 
+-------------
+         103
+(1 row)
+
+SELECT pgv_get_int('vars', 'intNULL');
+ pgv_get_int 
+-------------
+         104
+(1 row)
+
+SELECT pgv_get_text('vars', 'str1');
+ pgv_get_text 
+--------------
+ s103
+(1 row)
+
+SELECT pgv_get_text('vars', 'str2');
+ pgv_get_text 
+--------------
+ s103
+(1 row)
+
+SELECT pgv_get_numeric('vars', 'num1');
+ pgv_get_numeric 
+-----------------
+            1.03
+(1 row)
+
+SELECT pgv_get_numeric('vars', 'num2');
+ pgv_get_numeric 
+-----------------
+            1.03
+(1 row)
+
+SELECT pgv_get_timestamp('vars', 'ts1');
+    pgv_get_timestamp     
+--------------------------
+ Wed Mar 30 12:00:00 2016
+(1 row)
+
+SELECT pgv_get_timestamp('vars', 'ts2');
+    pgv_get_timestamp     
+--------------------------
+ Wed Mar 30 12:00:00 2016
+(1 row)
+
+SELECT pgv_get_timestamptz('vars', 'tstz1');
+     pgv_get_timestamptz      
+------------------------------
+ Wed Mar 30 18:00:00 2016 MSK
+(1 row)
+
+SELECT pgv_get_timestamptz('vars', 'tstz2');
+     pgv_get_timestamptz      
+------------------------------
+ Wed Mar 30 18:00:00 2016 MSK
+(1 row)
+
+SELECT pgv_get_date('vars', 'd1');
+ pgv_get_date 
+--------------
+ 04-02-2016
+(1 row)
+
+SELECT pgv_get_date('vars', 'd2');
+ pgv_get_date 
+--------------
+ 04-02-2016
+(1 row)
+
+SELECT pgv_get_jsonb('vars2', 'j1');
+                    pgv_get_jsonb                    
+-----------------------------------------------------
+ {"foo": [true, "bar"], "tags": {"a": 1, "b": null}}
+(1 row)
+
+SELECT pgv_get_jsonb('vars2', 'j2');
+                    pgv_get_jsonb                    
+-----------------------------------------------------
+ {"foo": [true, "bar"], "tags": {"a": 1, "b": null}}
+(1 row)
+
+-- Check values after releasing savepoint
+RELEASE comm;
+SELECT pgv_get('vars', 'any1',NULL::text);
+    pgv_get    
+---------------
+ another value
+(1 row)
+
+SELECT pgv_get('vars', 'any2',NULL::text);
+    pgv_get    
+---------------
+ another value
+(1 row)
+
+SELECT pgv_get_int('vars', 'int1');
+ pgv_get_int 
+-------------
+         103
+(1 row)
+
+SELECT pgv_get_int('vars', 'int2');
+ pgv_get_int 
+-------------
+         103
+(1 row)
+
+SELECT pgv_get_int('vars', 'intNULL');
+ pgv_get_int 
+-------------
+         104
+(1 row)
+
+SELECT pgv_get_text('vars', 'str1');
+ pgv_get_text 
+--------------
+ s103
+(1 row)
+
+SELECT pgv_get_text('vars', 'str2');
+ pgv_get_text 
+--------------
+ s103
+(1 row)
+
+SELECT pgv_get_numeric('vars', 'num1');
+ pgv_get_numeric 
+-----------------
+            1.03
+(1 row)
+
+SELECT pgv_get_numeric('vars', 'num2');
+ pgv_get_numeric 
+-----------------
+            1.03
+(1 row)
+
+SELECT pgv_get_timestamp('vars', 'ts1');
+    pgv_get_timestamp     
+--------------------------
+ Wed Mar 30 12:00:00 2016
+(1 row)
+
+SELECT pgv_get_timestamp('vars', 'ts2');
+    pgv_get_timestamp     
+--------------------------
+ Wed Mar 30 12:00:00 2016
+(1 row)
+
+SELECT pgv_get_timestamptz('vars', 'tstz1');
+     pgv_get_timestamptz      
+------------------------------
+ Wed Mar 30 18:00:00 2016 MSK
+(1 row)
+
+SELECT pgv_get_timestamptz('vars', 'tstz2');
+     pgv_get_timestamptz      
+------------------------------
+ Wed Mar 30 18:00:00 2016 MSK
+(1 row)
+
+SELECT pgv_get_date('vars', 'd1');
+ pgv_get_date 
+--------------
+ 04-02-2016
+(1 row)
+
+SELECT pgv_get_date('vars', 'd2');
+ pgv_get_date 
+--------------
+ 04-02-2016
+(1 row)
+
+SELECT pgv_get_jsonb('vars2', 'j1');
+                    pgv_get_jsonb                    
+-----------------------------------------------------
+ {"foo": [true, "bar"], "tags": {"a": 1, "b": null}}
+(1 row)
+
+SELECT pgv_get_jsonb('vars2', 'j2');
+                    pgv_get_jsonb                    
+-----------------------------------------------------
+ {"foo": [true, "bar"], "tags": {"a": 1, "b": null}}
+(1 row)
+
+COMMIT;
+CREATE TABLE tab (id int, t varchar);
+INSERT INTO tab VALUES (0, 'str00'), (1, 'str33'), (2, NULL), (NULL, 'strNULL');
+BEGIN;
+SELECT pgv_insert('vars3', 'r1', tab, true) FROM tab;
+ pgv_insert 
+------------
+ 
+ 
+ 
+ 
+(4 rows)
+
+SELECT pgv_insert('vars3', 'r2', tab) FROM tab;
+ pgv_insert 
+------------
+ 
+ 
+ 
+ 
+(4 rows)
+
+SAVEPOINT comm;
+SELECT pgv_insert('vars3', 'r1', row(5 :: integer, 'str55' :: varchar),true);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('vars3', 'r2', row(5 :: integer, 'str55' :: varchar));
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('vars3', 'r1');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,str55)
+ (0,str00)
+(5 rows)
+
+SELECT pgv_select('vars3', 'r2');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,str55)
+ (0,str00)
+(5 rows)
+
+RELEASE comm;
+SELECT pgv_select('vars3', 'r1');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,str55)
+ (0,str00)
+(5 rows)
+
+SELECT pgv_select('vars3', 'r2');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,str55)
+ (0,str00)
+(5 rows)
+
+COMMIT;
+--CHECK SAVEPOINT ROLLBACK
+BEGIN;
+-- Variables are already declared
+SAVEPOINT comm2;
+-- Set new values
+SELECT pgv_set('vars', 'any1', 'one more value'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set('vars', 'any2', 'one more value'::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set_int('vars', 'int1', 101, true);
+ pgv_set_int 
+-------------
+ 
+(1 row)
+
+SELECT pgv_set_int('vars', 'int2', 102);
+ pgv_set_int 
+-------------
+ 
+(1 row)
+
+SELECT pgv_set_int('vars', 'intNULL', NULL, true);
+ pgv_set_int 
+-------------
+ 
+(1 row)
+
+SELECT pgv_set_text('vars', 'str1', 's101', true);
+ pgv_set_text 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_text('vars', 'str2', 's102');
+ pgv_set_text 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_numeric('vars', 'num1', 1.01, true);
+ pgv_set_numeric 
+-----------------
+ 
+(1 row)
+
+SELECT pgv_set_numeric('vars', 'num2', 1.02);
+ pgv_set_numeric 
+-----------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamp('vars', 'ts1', '2016-03-30 10:00:00', true);
+ pgv_set_timestamp 
+-------------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamp('vars', 'ts2', '2016-03-30 11:00:00');
+ pgv_set_timestamp 
+-------------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamptz('vars', 'tstz1', '2016-03-30 10:00:00 GMT+01', true);
+ pgv_set_timestamptz 
+---------------------
+ 
+(1 row)
+
+SELECT pgv_set_timestamptz('vars', 'tstz2', '2016-03-30 11:00:00 GMT+02');
+ pgv_set_timestamptz 
+---------------------
+ 
+(1 row)
+
+SELECT pgv_set_date('vars', 'd1', '2016-03-29', true);
+ pgv_set_date 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_date('vars', 'd2', '2016-03-30');
+ pgv_set_date 
+--------------
+ 
+(1 row)
+
+SELECT pgv_set_jsonb('vars2', 'j1', '[1, 2, "foo", null]', true);
+ pgv_set_jsonb 
+---------------
+ 
+(1 row)
+
+SELECT pgv_set_jsonb('vars2', 'j2', '{"bar": "baz", "balance": 7.77, "active": false}');
+ pgv_set_jsonb 
+---------------
+ 
+(1 row)
+
+-- Check values before rollback to savepoint
+SELECT pgv_get('vars', 'any1',NULL::text);
+    pgv_get     
+----------------
+ one more value
+(1 row)
+
+SELECT pgv_get('vars', 'any2',NULL::text);
+    pgv_get     
+----------------
+ one more value
+(1 row)
+
+SELECT pgv_get_int('vars', 'int1');
+ pgv_get_int 
+-------------
+         101
+(1 row)
+
+SELECT pgv_get_int('vars', 'int2');
+ pgv_get_int 
+-------------
+         102
+(1 row)
+
+SELECT pgv_get_int('vars', 'intNULL');
+ pgv_get_int 
+-------------
+            
+(1 row)
+
+SELECT pgv_get_text('vars', 'str1');
+ pgv_get_text 
+--------------
+ s101
+(1 row)
+
+SELECT pgv_get_text('vars', 'str2');
+ pgv_get_text 
+--------------
+ s102
+(1 row)
+
+SELECT pgv_get_numeric('vars', 'num1');
+ pgv_get_numeric 
+-----------------
+            1.01
+(1 row)
+
+SELECT pgv_get_numeric('vars', 'num2');
+ pgv_get_numeric 
+-----------------
+            1.02
+(1 row)
+
+SELECT pgv_get_timestamp('vars', 'ts1');
+    pgv_get_timestamp     
+--------------------------
+ Wed Mar 30 10:00:00 2016
+(1 row)
+
+SELECT pgv_get_timestamp('vars', 'ts2');
+    pgv_get_timestamp     
+--------------------------
+ Wed Mar 30 11:00:00 2016
+(1 row)
+
+SELECT pgv_get_timestamptz('vars', 'tstz1');
+     pgv_get_timestamptz      
+------------------------------
+ Wed Mar 30 14:00:00 2016 MSK
+(1 row)
+
+SELECT pgv_get_timestamptz('vars', 'tstz2');
+     pgv_get_timestamptz      
+------------------------------
+ Wed Mar 30 16:00:00 2016 MSK
+(1 row)
+
+SELECT pgv_get_date('vars', 'd1');
+ pgv_get_date 
+--------------
+ 03-29-2016
+(1 row)
+
+SELECT pgv_get_date('vars', 'd2');
+ pgv_get_date 
+--------------
+ 03-30-2016
+(1 row)
+
+SELECT pgv_get_jsonb('vars2', 'j1');
+    pgv_get_jsonb    
+---------------------
+ [1, 2, "foo", null]
+(1 row)
+
+SELECT pgv_get_jsonb('vars2', 'j2');
+                  pgv_get_jsonb                   
+--------------------------------------------------
+ {"bar": "baz", "active": false, "balance": 7.77}
+(1 row)
+
+-- Check values after rollback to savepoint
+ROLLBACK TO comm2;
+SELECT pgv_get('vars', 'any1',NULL::text);
+    pgv_get    
+---------------
+ another value
+(1 row)
+
+SELECT pgv_get('vars', 'any2',NULL::text);
+    pgv_get     
+----------------
+ one more value
+(1 row)
+
+SELECT pgv_get_int('vars', 'int1');
+ pgv_get_int 
+-------------
+         103
+(1 row)
+
+SELECT pgv_get_int('vars', 'int2');
+ pgv_get_int 
+-------------
+         102
+(1 row)
+
+SELECT pgv_get_int('vars', 'intNULL');
+ pgv_get_int 
+-------------
+         104
+(1 row)
+
+SELECT pgv_get_text('vars', 'str1');
+ pgv_get_text 
+--------------
+ s103
+(1 row)
+
+SELECT pgv_get_text('vars', 'str2');
+ pgv_get_text 
+--------------
+ s102
+(1 row)
+
+SELECT pgv_get_numeric('vars', 'num1');
+ pgv_get_numeric 
+-----------------
+            1.03
+(1 row)
+
+SELECT pgv_get_numeric('vars', 'num2');
+ pgv_get_numeric 
+-----------------
+            1.02
+(1 row)
+
+SELECT pgv_get_timestamp('vars', 'ts1');
+    pgv_get_timestamp     
+--------------------------
+ Wed Mar 30 12:00:00 2016
+(1 row)
+
+SELECT pgv_get_timestamp('vars', 'ts2');
+    pgv_get_timestamp     
+--------------------------
+ Wed Mar 30 11:00:00 2016
+(1 row)
+
+SELECT pgv_get_timestamptz('vars', 'tstz1');
+     pgv_get_timestamptz      
+------------------------------
+ Wed Mar 30 18:00:00 2016 MSK
+(1 row)
+
+SELECT pgv_get_timestamptz('vars', 'tstz2');
+     pgv_get_timestamptz      
+------------------------------
+ Wed Mar 30 16:00:00 2016 MSK
+(1 row)
+
+SELECT pgv_get_date('vars', 'd1');
+ pgv_get_date 
+--------------
+ 04-02-2016
+(1 row)
+
+SELECT pgv_get_date('vars', 'd2');
+ pgv_get_date 
+--------------
+ 03-30-2016
+(1 row)
+
+SELECT pgv_get_jsonb('vars2', 'j1');
+                    pgv_get_jsonb                    
+-----------------------------------------------------
+ {"foo": [true, "bar"], "tags": {"a": 1, "b": null}}
+(1 row)
+
+SELECT pgv_get_jsonb('vars2', 'j2');
+                  pgv_get_jsonb                   
+--------------------------------------------------
+ {"bar": "baz", "active": false, "balance": 7.77}
+(1 row)
+
+COMMIT;
+-- Record variables
+BEGIN;
+SAVEPOINT comm2;
+SELECT pgv_delete('vars3', 'r1', 5);
+ pgv_delete 
+------------
+ t
+(1 row)
+
+SELECT pgv_delete('vars3', 'r2', 5);
+ pgv_delete 
+------------
+ t
+(1 row)
+
+SELECT pgv_select('vars3', 'r1');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (0,str00)
+(4 rows)
+
+SELECT pgv_select('vars3', 'r2');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (0,str00)
+(4 rows)
+
+ROLLBACK to comm2;
+SELECT pgv_select('vars3', 'r1');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,str55)
+ (0,str00)
+(5 rows)
+
+SELECT pgv_select('vars3', 'r2');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (0,str00)
+(4 rows)
+
+COMMIT;
+-- TRYING TO CHANGE FLAG 'IS_TRANSACTIONAL'
+SELECT pgv_set('vars', 'any1', 'value'::text);
+ERROR:  variable "any1" already created as TRANSACTIONAL
+SELECT pgv_set('vars', 'any2', 'value'::text, true);
+ERROR:  variable "any2" already created as NOT TRANSACTIONAL
+SELECT pgv_set_int('vars', 'int1', 301);
+ERROR:  variable "int1" already created as TRANSACTIONAL
+SELECT pgv_set_int('vars', 'int2', 302, true);
+ERROR:  variable "int2" already created as NOT TRANSACTIONAL
+SELECT pgv_set_text('vars', 'str1', 's301');
+ERROR:  variable "str1" already created as TRANSACTIONAL
+SELECT pgv_set_text('vars', 'str2', 's302', true);
+ERROR:  variable "str2" already created as NOT TRANSACTIONAL
+SELECT pgv_set_numeric('vars', 'num1', 3.01);
+ERROR:  variable "num1" already created as TRANSACTIONAL
+SELECT pgv_set_numeric('vars', 'num2', 3.02, true);
+ERROR:  variable "num2" already created as NOT TRANSACTIONAL
+SELECT pgv_set_timestamp('vars', 'ts1', '2016-03-30 20:00:00');
+ERROR:  variable "ts1" already created as TRANSACTIONAL
+SELECT pgv_set_timestamp('vars', 'ts2', '2016-03-30 21:00:00', true);
+ERROR:  variable "ts2" already created as NOT TRANSACTIONAL
+SELECT pgv_set_timestamptz('vars', 'tstz1', '2016-03-30 20:00:00 GMT+01');
+ERROR:  variable "tstz1" already created as TRANSACTIONAL
+SELECT pgv_set_timestamptz('vars', 'tstz2', '2016-03-30 21:00:00 GMT+02', true);
+ERROR:  variable "tstz2" already created as NOT TRANSACTIONAL
+SELECT pgv_set_date('vars', 'd1', '2016-04-29');
+ERROR:  variable "d1" already created as TRANSACTIONAL
+SELECT pgv_set_date('vars', 'd2', '2016-04-30', true);
+ERROR:  variable "d2" already created as NOT TRANSACTIONAL
+SELECT pgv_set_jsonb('vars2', 'j1', '[1, 2, "foo2", null]');
+ERROR:  variable "j1" already created as TRANSACTIONAL
+SELECT pgv_set_jsonb('vars2', 'j2', '{"bar": "baz2", "balance": 7.77, "active": true}', true);
+ERROR:  variable "j2" already created as NOT TRANSACTIONAL
+SELECT pgv_insert('vars3', 'r1', row(6 :: integer, 'str66' :: varchar));
+ERROR:  variable "r1" already created as TRANSACTIONAL
+SELECT pgv_insert('vars3', 'r2', row(6 :: integer, 'str66' :: varchar),true);
+ERROR:  variable "r2" already created as NOT TRANSACTIONAL
+-- CHECK pgv_list() WHILE WE HAVE A LOT OF MISCELLANEOUS VARIABLES
+SELECT * FROM pgv_list() order by package, name;
+ package |  name   | is_transactional 
+---------+---------+------------------
+ vars    | any1    | t
+ vars    | any2    | f
+ vars    | d1      | t
+ vars    | d2      | f
+ vars    | int1    | t
+ vars    | int2    | f
+ vars    | intNULL | t
+ vars    | num1    | t
+ vars    | num2    | f
+ vars    | str1    | t
+ vars    | str2    | f
+ vars    | ts1     | t
+ vars    | ts2     | f
+ vars    | tstz1   | t
+ vars    | tstz2   | f
+ vars2   | j1      | t
+ vars2   | j2      | f
+ vars3   | r1      | t
+ vars3   | r2      | f
+(19 rows)
+
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+-- VARIABLES DECLARED IN SUBTRANSACTION SHOULD BE DESTROYED AFTER ROLLBACK TO SAVEPOINT
+-- For better readability we don't use deprecated api functions in test below
+BEGIN;
+SAVEPOINT sp_to_rollback;
+SELECT pgv_set('vars', 'any1', 'text value'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set('vars', 'any2', 'text value'::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_insert('vars3', 'r1', row(6 :: integer, 'str44' :: varchar), true);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('vars3', 'r2', row(6 :: integer, 'str44' :: varchar));
+ pgv_insert 
+------------
+ 
+(1 row)
+
+ROLLBACK TO sp_to_rollback;
+COMMIT;
+SELECT pgv_get('vars', 'any1',NULL::text);
+ERROR:  unrecognized variable "any1"
+SELECT pgv_get('vars', 'any2',NULL::text);
+  pgv_get   
+------------
+ text value
+(1 row)
+
+SELECT pgv_select('vars3', 'r1');
+ERROR:  unrecognized variable "r1"
+SELECT pgv_select('vars3', 'r2');
+ pgv_select 
+------------
+ (6,str44)
+(1 row)
+
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+-- CHECK ROLLBACK AFTER COMMITTING SUBTRANSACTION
+BEGIN;
+SELECT pgv_set('vars', 'any1', 'before savepoint sp1'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SAVEPOINT sp1;
+SELECT pgv_set('vars', 'any1', 'after savepoint sp1'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SAVEPOINT sp2;
+SELECT pgv_set('vars', 'any1', 'after savepoint sp2'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+RELEASE sp2;
+SELECT pgv_get('vars', 'any1',NULL::text);
+       pgv_get       
+---------------------
+ after savepoint sp2
+(1 row)
+
+ROLLBACK TO sp1;
+SELECT pgv_get('vars', 'any1',NULL::text);
+       pgv_get        
+----------------------
+ before savepoint sp1
+(1 row)
+
+COMMIT;
+BEGIN;
+SAVEPOINT sp1;
+SAVEPOINT sp2;
+SELECT pgv_set('vars2', 'any1', 'variable exists'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+RELEASE sp2;
+SELECT pgv_get('vars2', 'any1',NULL::text);
+     pgv_get     
+-----------------
+ variable exists
+(1 row)
+
+ROLLBACK TO sp1;
+COMMIT;
+SELECT pgv_get('vars2', 'any1',NULL::text);
+ERROR:  unrecognized package "vars2"
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+--CHECK TRANSACTION COMMIT
+-- Declare variables
+SELECT pgv_set('vars', 'any1', 'some value'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set('vars', 'any2', 'some value'::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+BEGIN;
+-- Set new values
+SELECT pgv_set('vars', 'any1', 'another value'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set('vars', 'any2', 'another value'::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+-- Check values before committing transaction
+SELECT pgv_get('vars', 'any1',NULL::text);
+    pgv_get    
+---------------
+ another value
+(1 row)
+
+SELECT pgv_get('vars', 'any2',NULL::text);
+    pgv_get    
+---------------
+ another value
+(1 row)
+
+-- Check values after committing transaction
+COMMIT;
+SELECT pgv_get('vars', 'any1',NULL::text);
+    pgv_get    
+---------------
+ another value
+(1 row)
+
+SELECT pgv_get('vars', 'any2',NULL::text);
+    pgv_get    
+---------------
+ another value
+(1 row)
+
+SELECT pgv_insert('vars3', 'r1', tab, true) FROM tab;
+ pgv_insert 
+------------
+ 
+ 
+ 
+ 
+(4 rows)
+
+SELECT pgv_insert('vars3', 'r2', tab) FROM tab;
+ pgv_insert 
+------------
+ 
+ 
+ 
+ 
+(4 rows)
+
+BEGIN;
+SELECT pgv_insert('vars3', 'r1', row(5 :: integer, 'str55' :: varchar),true);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('vars3', 'r2', row(5 :: integer, 'str55' :: varchar));
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('vars3', 'r1');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,str55)
+ (0,str00)
+(5 rows)
+
+SELECT pgv_select('vars3', 'r2');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,str55)
+ (0,str00)
+(5 rows)
+
+COMMIT;
+SELECT pgv_select('vars3', 'r1');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,str55)
+ (0,str00)
+(5 rows)
+
+SELECT pgv_select('vars3', 'r2');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,str55)
+ (0,str00)
+(5 rows)
+
+-- CHECK TRANSACTION ROLLBACK
+-- Variables are already declared
+BEGIN;
+-- Set new values
+SELECT pgv_set('vars', 'any1', 'one more value'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set('vars', 'any2', 'one more value'::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+-- Check values before rollback
+SELECT pgv_get('vars', 'any1',NULL::text);
+    pgv_get     
+----------------
+ one more value
+(1 row)
+
+SELECT pgv_get('vars', 'any2',NULL::text);
+    pgv_get     
+----------------
+ one more value
+(1 row)
+
+-- Check values after rollback
+ROLLBACK;
+SELECT pgv_get('vars', 'any1',NULL::text);
+    pgv_get    
+---------------
+ another value
+(1 row)
+
+SELECT pgv_get('vars', 'any2',NULL::text);
+    pgv_get     
+----------------
+ one more value
+(1 row)
+
+-- Record variables
+BEGIN;
+SELECT pgv_delete('vars3', 'r1', 5);
+ pgv_delete 
+------------
+ t
+(1 row)
+
+SELECT pgv_delete('vars3', 'r2', 5);
+ pgv_delete 
+------------
+ t
+(1 row)
+
+SELECT pgv_select('vars3', 'r1');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (0,str00)
+(4 rows)
+
+SELECT pgv_select('vars3', 'r2');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (0,str00)
+(4 rows)
+
+ROLLBACK;
+SELECT pgv_select('vars3', 'r1');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,str55)
+ (0,str00)
+(5 rows)
+
+SELECT pgv_select('vars3', 'r2');
+ pgv_select 
+------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (0,str00)
+(4 rows)
+
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+-- VARIABLES DECLARED IN TRANSACTION SHOULD BE DESTROYED AFTER ROLLBACK
+BEGIN;
+SELECT pgv_set('vars', 'any1', 'text value'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set('vars', 'any2', 'text value'::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_insert('vars', 'r1', row(6 :: integer, 'str44' :: varchar), true);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('vars', 'r2', row(6 :: integer, 'str44' :: varchar));
+ pgv_insert 
+------------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT pgv_get('vars', 'any1',NULL::text);
+ERROR:  unrecognized variable "any1"
+SELECT pgv_get('vars', 'any2',NULL::text);
+  pgv_get   
+------------
+ text value
+(1 row)
+
+SELECT pgv_select('vars', 'r1');
+ERROR:  unrecognized variable "r1"
+SELECT pgv_select('vars', 'r2');
+ pgv_select 
+------------
+ (6,str44)
+(1 row)
+
+SELECT pgv_remove('vars');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+-- CHECK ROLLBACK AFTER COMMITTING SUBTRANSACTION
+SELECT pgv_set('vars', 'any1', 'before transaction block'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+BEGIN;
+SELECT pgv_set('vars', 'any1', 'before savepoint sp1'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SAVEPOINT sp1;
+SELECT pgv_set('vars', 'any1', 'after savepoint sp1'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SAVEPOINT sp2;
+SELECT pgv_set('vars', 'any1', 'after savepoint sp2'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+RELEASE sp2;
+SELECT pgv_get('vars', 'any1',NULL::text);
+       pgv_get       
+---------------------
+ after savepoint sp2
+(1 row)
+
+ROLLBACK TO sp1;
+SELECT pgv_get('vars', 'any1',NULL::text);
+       pgv_get        
+----------------------
+ before savepoint sp1
+(1 row)
+
+ROLLBACK;
+SELECT pgv_get('vars', 'any1',NULL::text);
+         pgv_get          
+--------------------------
+ before transaction block
+(1 row)
+
+BEGIN;
+SAVEPOINT sp1;
+SELECT pgv_set('vars2', 'any1', 'variable exists'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+RELEASE sp1;
+SELECT pgv_get('vars2', 'any1',NULL::text);
+     pgv_get     
+-----------------
+ variable exists
+(1 row)
+
+ROLLBACK;
+SELECT pgv_get('vars2', 'any1',NULL::text);
+ERROR:  unrecognized package "vars2"
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+-- Additional tests
+SELECT pgv_insert('vars3', 'r1', tab, true) FROM tab;
+ pgv_insert 
+------------
+ 
+ 
+ 
+ 
+(4 rows)
+
+BEGIN;
+SELECT pgv_insert('vars3', 'r1', row(5 :: integer, 'before savepoint sp1' :: varchar),true);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SAVEPOINT sp1;
+SELECT pgv_update('vars3', 'r1', row(5 :: integer, 'after savepoint sp1' :: varchar));
+ pgv_update 
+------------
+ t
+(1 row)
+
+SAVEPOINT sp2;
+SELECT pgv_insert('vars3', 'r1', row(7 :: integer, 'row after sp2 to remove in sp4' :: varchar),true);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SAVEPOINT sp3;
+SAVEPOINT sp4;
+SELECT pgv_delete('vars3', 'r1', 7);
+ pgv_delete 
+------------
+ t
+(1 row)
+
+SAVEPOINT sp5;
+SELECT pgv_select('vars3', 'r1');
+        pgv_select         
+---------------------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,"after savepoint sp1")
+ (0,str00)
+(5 rows)
+
+ROLLBACK TO sp5;
+SELECT pgv_select('vars3', 'r1');
+        pgv_select         
+---------------------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,"after savepoint sp1")
+ (0,str00)
+(5 rows)
+
+RELEASE sp4;
+SELECT pgv_select('vars3', 'r1');
+        pgv_select         
+---------------------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,"after savepoint sp1")
+ (0,str00)
+(5 rows)
+
+ROLLBACK TO sp3;
+SELECT pgv_select('vars3', 'r1');
+              pgv_select              
+--------------------------------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,"after savepoint sp1")
+ (0,str00)
+ (7,"row after sp2 to remove in sp4")
+(6 rows)
+
+RELEASE sp2;
+SELECT pgv_select('vars3', 'r1');
+              pgv_select              
+--------------------------------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,"after savepoint sp1")
+ (0,str00)
+ (7,"row after sp2 to remove in sp4")
+(6 rows)
+
+ROLLBACK TO sp1;
+SELECT pgv_select('vars3', 'r1');
+         pgv_select         
+----------------------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,"before savepoint sp1")
+ (0,str00)
+(5 rows)
+
+COMMIT;
+SELECT pgv_select('vars3', 'r1');
+         pgv_select         
+----------------------------
+ (,strNULL)
+ (1,str33)
+ (2,)
+ (5,"before savepoint sp1")
+ (0,str00)
+(5 rows)
+
+SELECT pgv_set('vars', 'any1', 'outer'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+BEGIN;
+SELECT pgv_set('vars', 'any1', 'begin'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SAVEPOINT sp1;
+SELECT pgv_set('vars', 'any1', 'sp1'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SAVEPOINT sp2;
+SELECT pgv_set('vars', 'any1', 'sp2'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SAVEPOINT sp3;
+SAVEPOINT sp4;
+SELECT pgv_set('vars', 'any1', 'sp4'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SAVEPOINT sp5;
+SELECT pgv_get('vars', 'any1',NULL::text);
+ pgv_get 
+---------
+ sp4
+(1 row)
+
+ROLLBACK TO sp5;
+SELECT pgv_get('vars', 'any1',NULL::text);
+ pgv_get 
+---------
+ sp4
+(1 row)
+
+RELEASE sp4;
+SELECT pgv_get('vars', 'any1',NULL::text);
+ pgv_get 
+---------
+ sp4
+(1 row)
+
+ROLLBACK TO sp3;
+SELECT pgv_get('vars', 'any1',NULL::text);
+ pgv_get 
+---------
+ sp2
+(1 row)
+
+RELEASE sp2;
+SELECT pgv_get('vars', 'any1',NULL::text);
+ pgv_get 
+---------
+ sp2
+(1 row)
+
+ROLLBACK TO sp1;
+SELECT pgv_get('vars', 'any1',NULL::text);
+ pgv_get 
+---------
+ begin
+(1 row)
+
+ROLLBACK;
+SELECT pgv_get('vars', 'any1',NULL::text);
+ pgv_get 
+---------
+ outer
+(1 row)
+
+BEGIN;
+SELECT pgv_set('vars', 'any1', 'wrong type'::varchar, true);
+ERROR:  variable "any1" requires "text" value
+COMMIT;
+-- THE REMOVAL OF THE VARIABLE MUST BE CANCELED ON ROLLBACK
+SELECT pgv_set('vars', 'any1', 'variable exists'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+BEGIN;
+SELECT pgv_remove('vars', 'any1');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+SELECT pgv_exists('vars', 'any1');
+ pgv_exists 
+------------
+ f
+(1 row)
+
+ROLLBACK;
+SELECT pgv_exists('vars', 'any1');
+ pgv_exists 
+------------
+ t
+(1 row)
+
+SELECT pgv_get('vars', 'any1',NULL::text);
+     pgv_get     
+-----------------
+ variable exists
+(1 row)
+
+BEGIN;
+SELECT pgv_remove('vars', 'any1');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+SELECT pgv_exists('vars', 'any1');
+ pgv_exists 
+------------
+ f
+(1 row)
+
+COMMIT;
+SELECT pgv_exists('vars', 'any1');
+ pgv_exists 
+------------
+ f
+(1 row)
+
+SELECT pgv_get('vars', 'any1',NULL::text);
+ERROR:  unrecognized package "vars"
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package | name | is_transactional 
+---------+------+------------------
+ vars3   | r1   | t
+(1 row)
+
+BEGIN;
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package | name | is_transactional 
+---------+------+------------------
+ vars3   | r1   | t
+(1 row)
+
+BEGIN;
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+COMMIT;
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package | name | is_transactional 
+---------+------+------------------
+(0 rows)
+
+SELECT pgv_set('vars', 'regular', 'regular variable exists'::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set('vars', 'trans1', 'trans1 variable exists'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+BEGIN;
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+SELECT pgv_free(); -- Check sequential package removal in one subtransaction
+ pgv_free 
+----------
+ 
+(1 row)
+
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package | name | is_transactional 
+---------+------+------------------
+(0 rows)
+
+SELECT pgv_set('vars', 'trans2', 'trans2 variable exists'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package |  name  | is_transactional 
+---------+--------+------------------
+ vars    | trans2 | t
+(1 row)
+
+SELECT pgv_remove('vars');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package | name | is_transactional 
+---------+------+------------------
+(0 rows)
+
+ROLLBACK;
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package |  name  | is_transactional 
+---------+--------+------------------
+ vars    | trans1 | t
+(1 row)
+
+BEGIN;
+SAVEPOINT sp1;
+SAVEPOINT sp2;
+SAVEPOINT sp3;
+SELECT pgv_set('vars2', 'trans2', 'trans2 variable exists'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SAVEPOINT sp4;
+SAVEPOINT sp5;
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+SELECT package FROM pgv_stats() ORDER BY package;
+ package 
+---------
+ vars
+ vars2
+(2 rows)
+
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package | name | is_transactional 
+---------+------+------------------
+(0 rows)
+
+RELEASE sp5;
+SELECT package FROM pgv_stats() ORDER BY package;
+ package 
+---------
+ vars
+ vars2
+(2 rows)
+
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package | name | is_transactional 
+---------+------+------------------
+(0 rows)
+
+RELEASE sp4;
+SELECT package FROM pgv_stats() ORDER BY package;
+ package 
+---------
+ vars
+ vars2
+(2 rows)
+
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package | name | is_transactional 
+---------+------+------------------
+(0 rows)
+
+COMMIT;
+SELECT package FROM pgv_stats() ORDER BY package;
+ package 
+---------
+(0 rows)
+
+BEGIN;
+SELECT pgv_set('vars', 'trans1', 'package created'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_remove('vars');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package | name | is_transactional 
+---------+------+------------------
+(0 rows)
+
+SELECT pgv_set('vars', 'trans1', 'package restored'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT * FROM pgv_list() ORDER BY package, name;
+ package |  name  | is_transactional 
+---------+--------+------------------
+ vars    | trans1 | t
+(1 row)
+
+COMMIT;
+SELECT pgv_remove('vars');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+-- REMOVED TRANSACTIONAL VARIABLE SHOULD BE NOT ACCESSIBLE THROUGH LastVariable
+SELECT pgv_insert('package', 'errs',row(n), true)
+FROM generate_series(1,5) AS gs(n) WHERE 1.0/(n-3)<>0;
+ERROR:  division by zero
+SELECT pgv_insert('package', 'errs',row(1), true);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+-- Variable should not exists in case when error occurs during creation
+SELECT pgv_insert('vars4', 'r1', row('str1', 'str1'));
+ERROR:  could not identify a hash function for type unknown
+SELECT pgv_select('vars4', 'r1', 0);
+ERROR:  unrecognized package "vars4"
+-- If variable created and removed in same transaction level,
+-- it should be totally removed and should not be present
+-- in changes list and cache.
+BEGIN;
+SELECT pgv_set('vars', 'any1', 'some value'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SAVEPOINT comm;
+SELECT pgv_remove('vars', 'any1');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+RELEASE comm;
+SELECT pgv_get('vars', 'any1',NULL::text);
+ERROR:  unrecognized package "vars"
+COMMIT;
+-- Tests for PGPRO-2440
+SELECT pgv_insert('vars3', 'r3', row(1 :: integer, NULL::varchar), true);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+SELECT pgv_insert('vars3', 'r3', row(2 :: integer, NULL::varchar), true);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SAVEPOINT comm;
+SELECT pgv_insert('vars3', 'r3', row(3 :: integer, NULL::varchar), true);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+COMMIT;
+SELECT pgv_delete('vars3', 'r3', 3);
+ pgv_delete 
+------------
+ t
+(1 row)
+
+BEGIN;
+SELECT pgv_set('vars1', 't1', ''::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_set('vars2', 't2', ''::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SAVEPOINT sp1;
+SAVEPOINT sp2;
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+ERROR;
+ERROR:  syntax error at or near "ERROR"
+LINE 1: ERROR;
+        ^
+COMMIT;
+BEGIN;
+SELECT pgv_set('vars', 'any1', 'some value'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+SAVEPOINT sp_to_rollback;
+SELECT pgv_set('vars', 'any1', 'some value'::text, true);
+ pgv_set 
+---------
+ 
+(1 row)
+
+ROLLBACK TO sp_to_rollback;
+COMMIT;
+SELECT package FROM pgv_stats() ORDER BY package;
+ package 
+---------
+(0 rows)
+
+-- Package should exist after rollback if it contains regular variable
+BEGIN;
+SELECT pgv_set('vars', 'any1', 'some value'::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT package FROM pgv_stats() ORDER BY package;
+ package 
+---------
+ vars
+(1 row)
+
+-- Package should not exist if it becomes empty in rolled back transaction
+BEGIN;
+SAVEPOINT comm2;
+SELECT pgv_remove('vars');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+ROLLBACK TO comm2;
+SELECT pgv_exists('vars');
+ pgv_exists 
+------------
+ f
+(1 row)
+
+SELECT package FROM pgv_stats() ORDER BY package;
+ package 
+---------
+ vars
+(1 row)
+
+COMMIT;
+SELECT package FROM pgv_stats() ORDER BY package;
+ package 
+---------
+(0 rows)
+
+SELECT pgv_set('vars', 'any1', 'some value'::text);
+ pgv_set 
+---------
+ 
+(1 row)
+
+BEGIN;
+SELECT pgv_remove('vars');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT package FROM pgv_stats() ORDER BY package;
+ package 
+---------
+(0 rows)
+
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+-- Variables should be insertable after pgv_remove (variable)
+BEGIN;
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_remove('test', 'x');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'x', ROW (1::int, 3::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,3)
+(1 row)
+
+SELECT pgv_insert('test', 'x', ROW (2::int, 4::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,3)
+ (2,4)
+(2 rows)
+
+ROLLBACK;
+SELECT * FROM pgv_list() order by package, name;
+ package | name | is_transactional 
+---------+------+------------------
+(0 rows)
+
+BEGIN;
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_remove('test', 'x');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'x', ROW (1::int, 3::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,3)
+(1 row)
+
+SELECT pgv_insert('test', 'x', ROW (2::int, 4::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,3)
+ (2,4)
+(2 rows)
+
+COMMIT;
+SELECT * FROM pgv_list() order by package, name;
+ package | name | is_transactional 
+---------+------+------------------
+ test    | x    | t
+(1 row)
+
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,3)
+ (2,4)
+(2 rows)
+
+-- Variables should be insertable after pgv_remove (package)
+BEGIN;
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_remove('test');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (1::int, 3::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,3)
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (2::int, 4::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,3)
+ (2,4)
+(2 rows)
+
+ROLLBACK;
+SELECT * FROM pgv_list() order by package, name;
+ package | name | is_transactional 
+---------+------+------------------
+ test    | x    | t
+(1 row)
+
+BEGIN;
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_remove('test');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (1::int, 3::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,3)
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (2::int, 4::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,3)
+ (2,4)
+(2 rows)
+
+COMMIT;
+SELECT * FROM pgv_list() order by package, name;
+ package | name | is_transactional 
+---------+------+------------------
+ test    | y    | t
+(1 row)
+
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,3)
+ (2,4)
+(2 rows)
+
+-- Variables should be insertable after pgv_free
+BEGIN;
+SELECT pgv_insert('test', 'z', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'z');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'z', ROW (1::int, 3::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'z');
+ pgv_select 
+------------
+ (1,3)
+(1 row)
+
+SELECT pgv_insert('test', 'z', ROW (2::int, 4::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'z');
+ pgv_select 
+------------
+ (1,3)
+ (2,4)
+(2 rows)
+
+ROLLBACK;
+SELECT * FROM pgv_list() order by package, name;
+ package | name | is_transactional 
+---------+------+------------------
+ test    | y    | t
+(1 row)
+
+BEGIN;
+SELECT pgv_insert('test', 'z', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'z');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'z', ROW (1::int, 3::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'z');
+ pgv_select 
+------------
+ (1,3)
+(1 row)
+
+SELECT pgv_insert('test', 'z', ROW (2::int, 4::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'z');
+ pgv_select 
+------------
+ (1,3)
+ (2,4)
+(2 rows)
+
+COMMIT;
+SELECT * FROM pgv_list() order by package, name;
+ package | name | is_transactional 
+---------+------+------------------
+ test    | z    | t
+(1 row)
+
+SELECT pgv_select('test', 'z');
+ pgv_select 
+------------
+ (1,3)
+ (2,4)
+(2 rows)
+
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+-- Variables should be rollbackable if transactional
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'x', ROW (2::int, 3::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+BEGIN;
+SELECT pgv_remove('test', 'x');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+BEGIN;
+SELECT pgv_remove('test');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+BEGIN;
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+---
+--- Variables should not be rollbackable if not transactional
+---
+-- case 1 (remove var)
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (2::int, 3::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+BEGIN;
+SELECT pgv_remove('test', 'y');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT pgv_select('test', 'y');
+ERROR:  unrecognized variable "y"
+-- case 2 (remove pack)
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (2::int, 3::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+BEGIN;
+SELECT pgv_remove('test');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT pgv_select('test', 'y');
+ERROR:  unrecognized variable "y"
+-- case 3 (free)
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (2::int, 3::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+BEGIN;
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT pgv_select('test', 'y');
+ERROR:  unrecognized variable "y"
+-- clear all
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+---
+--- Cursors test #1 (remove var)
+---
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+SELECT pgv_remove('test', 'x');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'y');
+SELECT pgv_remove('test', 'y');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized variable "y"
+ROLLBACK;
+SELECT pgv_select('test', 'y');
+ERROR:  unrecognized variable "y"
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+---
+--- Cursors test #2 (remove pack)
+---
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+SELECT pgv_remove('test');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'y');
+SELECT pgv_remove('test');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test');
+ERROR:  function pgv_select(unknown) does not exist
+LINE 1: SELECT pgv_select('test');
+               ^
+HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+---
+--- Cursors test #3 (free)
+---
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'y');
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test');
+ERROR:  function pgv_select(unknown) does not exist
+LINE 1: SELECT pgv_select('test');
+               ^
+HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+---
+--- Cursor test #4
+---
+-- non transactional, remove var
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+SELECT pgv_remove('test', 'x');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ERROR:  unrecognized package "test"
+-- non transactional, remove pac
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+SELECT pgv_remove('test');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ERROR:  unrecognized package "test"
+-- non transactional, free
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ERROR:  unrecognized package "test"
+-- transactional, remove var
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'y');
+SELECT pgv_remove('test', 'y');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+-- transactional, remove pack
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'y');
+SELECT pgv_remove('test');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+-- transactional, free
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'y');
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'y');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+---
+--- Cursor test #5
+---
+-- non transactional
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+CLOSE r1_cur;
+SELECT pgv_remove('test', 'x');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ERROR:  unrecognized package "test"
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+CLOSE r1_cur;
+SELECT pgv_remove('test');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ERROR:  unrecognized package "test"
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+CLOSE r1_cur;
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ERROR:  unrecognized package "test"
+-- transactional
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_remove('test', 'x');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_remove('test');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized package "test"
+ROLLBACK;
+SELECT pgv_select('test', 'x');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+---
+--- Cursor test #6
+---
+--SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), TRUE);
+--BEGIN;
+--DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+--FETCH 1 in r1_cur;
+--CLOSE r1_cur;
+--SELECT pgv_remove('test', 'x');
+--COMMIT;
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+---
+--- Tests for "leaked hash_seq_search scan for hash table"
+---
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'x', ROW (2::int, 3::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'x', ROW (3::int, 4::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'x') LIMIT 1;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_select('test', 'x') LIMIT 2;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+SELECT pgv_select('test', 'x') LIMIT 3;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+BEGIN;
+SELECT pgv_select('test', 'x') LIMIT 1;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_select('test', 'x') LIMIT 2;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+SELECT pgv_select('test', 'x') LIMIT 3;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+ROLLBACK;
+BEGIN;
+SELECT pgv_select('test', 'x') LIMIT 1;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_select('test', 'x') LIMIT 2;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+SELECT pgv_select('test', 'x') LIMIT 3;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+COMMIT;
+SELECT pgv_insert('test', 'y', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (2::int, 3::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'y', ROW (3::int, 4::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('test', 'y') LIMIT 1;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_select('test', 'y') LIMIT 2;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+SELECT pgv_select('test', 'y') LIMIT 3;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+BEGIN;
+SELECT pgv_select('test', 'y') LIMIT 1;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_select('test', 'y') LIMIT 2;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+SELECT pgv_select('test', 'y') LIMIT 3;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+ROLLBACK;
+BEGIN;
+SELECT pgv_select('test', 'y') LIMIT 1;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+SELECT pgv_select('test', 'y') LIMIT 2;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+SELECT pgv_select('test', 'y') LIMIT 3;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+COMMIT;
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+DECLARE r2_cur CURSOR FOR SELECT pgv_select('test', 'y');
+DECLARE r3_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+FETCH 1 in r2_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+FETCH 1 in r3_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+ROLLBACK;
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+DECLARE r2_cur CURSOR FOR SELECT pgv_select('test', 'y');
+DECLARE r3_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 2 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+FETCH 2 in r2_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+FETCH 2 in r3_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+ROLLBACK;
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+DECLARE r2_cur CURSOR FOR SELECT pgv_select('test', 'y');
+DECLARE r3_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 3 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+FETCH 3 in r2_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+FETCH 3 in r3_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+ROLLBACK;
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+DECLARE r2_cur CURSOR FOR SELECT pgv_select('test', 'y');
+DECLARE r3_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+FETCH 1 in r2_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+FETCH 1 in r3_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+COMMIT;
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+DECLARE r2_cur CURSOR FOR SELECT pgv_select('test', 'y');
+DECLARE r3_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 2 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+FETCH 2 in r2_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+FETCH 2 in r3_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+COMMIT;
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+DECLARE r2_cur CURSOR FOR SELECT pgv_select('test', 'y');
+DECLARE r3_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 3 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+FETCH 3 in r2_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+FETCH 3 in r3_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+COMMIT;
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+DECLARE r2_cur CURSOR FOR SELECT pgv_select('test', 'y');
+DECLARE r3_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+FETCH 2 in r2_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+FETCH 3 in r3_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+ROLLBACK;
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+DECLARE r2_cur CURSOR FOR SELECT pgv_select('test', 'y');
+DECLARE r3_cur CURSOR FOR SELECT pgv_select('test', 'x');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+FETCH 2 in r2_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+FETCH 3 in r3_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+ (3,4)
+(3 rows)
+
+COMMIT;
+---
+--- Some special cases
+---
+-- take #1
+SELECT pgv_insert('test', 'z1', ROW (2::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'z1');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (2,2)
+(1 row)
+
+SELECT pgv_remove('test', 'z1');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  unrecognized variable "z1"
+ROLLBACK;
+SELECT pgv_select('test', 'z1');
+ pgv_select 
+------------
+ (2,2)
+(1 row)
+
+-- take #2
+SELECT pgv_insert('test', 'z2', ROW (2::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'z2');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (2,2)
+(1 row)
+
+CLOSE r1_cur;
+SELECT pgv_remove('test', 'z2');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  cursor "r1_cur" does not exist
+ROLLBACK;
+SELECT pgv_select('test', 'z2');
+ERROR:  unrecognized variable "z2"
+SELECT pgv_insert('test', 'z2', ROW (1::int, 2::int), FALSE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+-- take #3
+SELECT pgv_insert('test', 'z3', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'z3');
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+CLOSE r1_cur;
+SELECT pgv_remove('test', 'z3');
+ pgv_remove 
+------------
+ 
+(1 row)
+
+FETCH 1 in r1_cur;
+ERROR:  cursor "r1_cur" does not exist
+ROLLBACK;
+SELECT pgv_select('test', 'z3');
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+--BEGIN;
+--DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'z3');
+--FETCH 1 in r1_cur;
+--SELECT pgv_remove('test', 'z3');
+--COMMIT;
+--SELECT pgv_select('test', 'z3');
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+-- take #4
+SELECT pgv_insert('test', 'x', ROW (1::int, 2::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test', 'x', ROW (2::int, 3::int), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+SAVEPOINT sp1;
+FETCH 1 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+ROLLBACK TO SAVEPOINT sp1;
+COMMIT;
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pgv_select('test', 'x');
+SAVEPOINT sp1;
+FETCH 2 in r1_cur;
+ pgv_select 
+------------
+ (1,2)
+ (2,3)
+(2 rows)
+
+ROLLBACK TO SAVEPOINT sp1;
+COMMIT;
+BEGIN;
+SAVEPOINT sp1;
+SELECT pgv_select('test', 'x') LIMIT 1;
+ pgv_select 
+------------
+ (1,2)
+(1 row)
+
+ROLLBACK TO SAVEPOINT sp1;
+COMMIT;
+---
+--- Test cases for pgv_stats
+---
+--- Amount of allocated memory may vary from version to version, as well as from
+--- platform to platform. Moreover, postgres versions less than 90600 always
+--- show zero allocated memory. So, it's much easier to check if allocated
+--- memory size is multiple of 8k since we use ALLOCSET_DEFAULT_INITSIZE
+--- (see memutils.h), insted of creating multiple outputs files.
+---
+CREATE TEMP VIEW pgv_stats_view(pack, mem_mult) AS
+    SELECT package, allocated_memory % 8192 as allocated_multiple_8192
+      FROM pgv_stats()
+     ORDER BY 1;
+SELECT pgv_insert('test1', 'y', ROW (2::float, 1::float), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('test1', 'x', ROW (2::float, 1::float), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+DECLARE r2_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+FETCH 1 in r1_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+FETCH 1 in r2_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+COMMIT;
+SELECT pgv_insert('test1', 'y', ROW (2::float, 1::float), TRUE);
+ERROR:  there is a record in the variable "y" with same key
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+DECLARE r2_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+FETCH 1 in r1_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+FETCH 1 in r2_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+ROLLBACK;
+SELECT pgv_insert('test1', 'y', ROW (2::float, 1::float), FALSE);
+ERROR:  variable "y" already created as TRANSACTIONAL
+SELECT pgv_insert('test1', 'y', ROW (2::float, 1::float), FALSE);
+ERROR:  variable "y" already created as TRANSACTIONAL
+SELECT pgv_insert('test1', 'x', ROW (2::float, 1::float), FALSE);
+ERROR:  variable "x" already created as TRANSACTIONAL
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+DECLARE r2_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+FETCH 1 in r1_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+FETCH 1 in r2_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+COMMIT;
+SELECT pgv_insert('test1', 'y', ROW (2::float, 1::float), FALSE);
+ERROR:  variable "y" already created as TRANSACTIONAL
+BEGIN;
+DECLARE r1_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+DECLARE r2_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+FETCH 1 in r1_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+FETCH 1 in r2_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+ROLLBACK;
+SELECT pgv_insert('test1', 'y', ROW (2::float, 1::float), FALSE);
+ERROR:  variable "y" already created as TRANSACTIONAL
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+---
+--- Some special cases
+---
+-- 1
+BEGIN;
+SAVEPOINT comm2;
+SELECT pgv_insert('test', 'x1', ROW (2::float, 1::float), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+DECLARE r1_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+DECLARE r2_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+FETCH 1 in r1_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+FETCH 1 in r2_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+COMMIT;
+-- 2
+BEGIN;
+SELECT pgv_insert('test', 'x2', ROW (2::float, 1::float), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SAVEPOINT comm2;
+DECLARE r1_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+DECLARE r2_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+FETCH 1 in r1_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+FETCH 1 in r2_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+COMMIT;
+-- 3
+BEGIN;
+SELECT pgv_insert('test', 'x3', ROW (2::float, 1::float), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+DECLARE r1_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+DECLARE r2_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+SAVEPOINT comm2;
+FETCH 1 in r1_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+FETCH 1 in r2_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+COMMIT;
+-- 4
+BEGIN;
+SELECT pgv_insert('test', 'x4', ROW (2::float, 1::float), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+DECLARE r1_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+DECLARE r2_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+FETCH 1 in r1_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+SAVEPOINT comm2;
+FETCH 1 in r2_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+COMMIT;
+-- 5
+BEGIN;
+SELECT pgv_insert('test', 'x5', ROW (2::float, 1::float), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
+DECLARE r1_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+DECLARE r2_cur CURSOR FOR SELECT pack, mem_mult FROM pgv_stats_view;
+FETCH 1 in r1_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+FETCH 1 in r2_cur;
+ pack | mem_mult 
+------+----------
+ test |        0
+(1 row)
+
+SAVEPOINT comm2;
+COMMIT;
+DROP VIEW pgv_stats_view;
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+---
+--- Test case for issue #32 [PGPRO-4456]
+---
+CREATE TEMP TABLE tab (id int, t varchar);
+INSERT INTO tab VALUES (0, 'str00');
+SELECT pgv_insert('vars', 'r1', row(1, 'str1', 'str2'));
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('vars', 'a', tab) FROM tab;
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('vars', 'r1', tab) FROM tab;
+ERROR:  new record structure have 2 attributes, but variable "r1" structure have 3.
+SELECT pgv_select('vars', 'r1');
+  pgv_select   
+---------------
+ (1,str1,str2)
+(1 row)
+
+SELECT pgv_insert('vars', 'r2', row(1, 'str1'::varchar));
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('vars', 'b', tab) FROM tab;
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_insert('vars', 'r2', tab) FROM tab;
+ pgv_insert 
+------------
+ 
+(1 row)
+
+SELECT pgv_select('vars', 'r2');
+ pgv_select 
+------------
+ (1,str1)
+ (0,str00)
+(2 rows)
+
+SELECT pgv_free();
+ pgv_free 
+----------
+ 
+(1 row)
+
+--
+-- Test case for issue #38 [PGPRO-4676]
+--
+SELECT pgv_insert('test', 'x5', ROW ((2::int, 1::int)), TRUE);
+ pgv_insert 
+------------
+ 
+(1 row)
+
diff --git a/pg_variables.c b/pg_variables.c
index d76e01f..bcd0e21 100644
--- a/pg_variables.c
+++ b/pg_variables.c
@@ -1489,7 +1489,9 @@ getMemoryTotalSpace(MemoryContext context, int level, Size *totalspace)
 
 	/* Examine the context itself */
 	memset(&totals, 0, sizeof(totals));
-#if PG_VERSION_NUM >= 110000
+#if PG_VERSION_NUM >= 140000
+	(*context->methods->stats) (context, NULL, NULL, &totals, true);
+#elif PG_VERSION_NUM >= 110000
 	(*context->methods->stats) (context, NULL, NULL, &totals);
 #else
 	(*context->methods->stats) (context, level, false, &totals);
@@ -1641,7 +1643,11 @@ ensurePackagesHashExists(void)
 
 	packagesHash = hash_create("Packages hash",
 							   NUMPACKAGES, &ctl,
-							   HASH_ELEM | HASH_CONTEXT);
+							   HASH_ELEM | 
+#							   if PG_VERSION_NUM >= 140000
+							   HASH_STRINGS |
+#							   endif
+							   HASH_CONTEXT);
 }
 
 /*
@@ -1668,7 +1674,11 @@ makePackHTAB(Package *package, bool is_trans)
 	ctl.hcxt = *context;
 
 	*htab = hash_create(hash_name, NUMVARIABLES, &ctl,
-						HASH_ELEM | HASH_CONTEXT);
+						HASH_ELEM |
+#						if PG_VERSION_NUM >= 140000
+						HASH_STRINGS |
+#						endif
+						HASH_CONTEXT);
 }
 
 static void
