Skip to content

Commit 5510083

Browse files
Version 1.1: Add support of transactions and savepoints
1 parent 8829bc2 commit 5510083

13 files changed

+4710
-172
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ MODULE_big = pg_variables
44
OBJS = pg_variables.o pg_variables_record.o $(WIN32RES)
55

66
EXTENSION = pg_variables
7-
DATA = pg_variables--1.0.sql
7+
DATA = pg_variables--1.0.sql pg_variables--1.1.sql pg_variables--1.0--1.1.sql
88
PGFILEDESC = "pg_variables - sessional variables"
99

10-
REGRESS = pg_variables pg_variables_any
10+
REGRESS = pg_variables pg_variables_any pg_variables_trans
1111

1212
ifdef USE_PGXS
1313
PG_CONFIG = pg_config

README.md

Lines changed: 99 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
The **pg_variables** module provides functions to work with variables of various
66
types. Created variables live only in the current user session.
77

8-
Note that the module does **not support transactions and savepoints**. For
8+
Note that the module does **not support transactions and savepoints by default**. For
99
example:
1010

1111
```sql
@@ -15,13 +15,29 @@ SELECT pgv_set('vars', 'int2', 102);
1515
ROLLBACK;
1616

1717
SELECT * FROM pgv_list() order by package, name;
18-
package | name
19-
---------+------
20-
vars | int1
21-
vars | int2
18+
package | name | is_transactional
19+
---------+------+------------------
20+
vars | int1 | f
21+
vars | int2 | f
2222
(2 rows)
2323
```
2424

25+
But if variable created with flag **is_transactional**, it does:
26+
```sql
27+
BEGIN;
28+
SELECT pgv_set('vars', 'trans_int', 101, true);
29+
SAVEPOINT sp1;
30+
SELECT pgv_set('vars', 'trans_int', 102, true);
31+
ROLLBACK TO sp1;
32+
COMMIT;
33+
SELECT pgv_get('vars', 'trans_int', NULL::int);
34+
35+
pgv_get
36+
---------
37+
101
38+
(1 row)
39+
```
40+
2541
## License
2642

2743
This module available under the same license as
@@ -72,7 +88,7 @@ ERROR: variable "int1" requires "integer" value
7288

7389
Function | Returns
7490
-------- | -------
75-
`pgv_set(package text, name text, value anynonarray)` | `void`
91+
`pgv_set(package text, name text, value anynonarray, is_transactional bool default false)` | `void`
7692
`pgv_get(package text, name text, var_type anynonarray, strict bool default true)` | `anynonarray`
7793

7894
## **Deprecated** scalar variables functions
@@ -81,49 +97,49 @@ Function | Returns
8197

8298
Function | Returns
8399
-------- | -------
84-
`pgv_set_int(package text, name text, value int)` | `void`
100+
`pgv_set_int(package text, name text, value int, is_transactional bool default false)` | `void`
85101
`pgv_get_int(package text, name text, strict bool default true)` | `int`
86102

87103
### Text variables
88104

89105
Function | Returns
90106
-------- | -------
91-
`pgv_set_text(package text, name text, value text)` | `void`
107+
`pgv_set_text(package text, name text, value text, is_transactional bool default false)` | `void`
92108
`pgv_get_text(package text, name text, strict bool default true)` | `text`
93109

94110
### Numeric variables
95111

96112
Function | Returns
97113
-------- | -------
98-
`pgv_set_numeric(package text, name text, value numeric)` | `void`
114+
`pgv_set_numeric(package text, name text, value numeric, is_transactional bool default false)` | `void`
99115
`pgv_get_numeric(package text, name text, strict bool default true)` | `numeric`
100116

101117
### Timestamp variables
102118

103119
Function | Returns
104120
-------- | -------
105-
`pgv_set_timestamp(package text, name text, value timestamp)` | `void`
121+
`pgv_set_timestamp(package text, name text, value timestamp, is_transactional bool default false)` | `void`
106122
`pgv_get_timestamp(package text, name text, strict bool default true)` | `timestamp`
107123

108124
### Timestamp with timezone variables
109125

110126
Function | Returns
111127
-------- | -------
112-
`pgv_set_timestamptz(package text, name text, value timestamptz)` | `void`
128+
`pgv_set_timestamptz(package text, name text, value timestamptz, is_transactional bool default false)` | `void`
113129
`pgv_get_timestamptz(package text, name text, strict bool default true)` | `timestamptz`
114130

115131
### Date variables
116132

117133
Function | Returns
118134
-------- | -------
119-
`pgv_set_date(package text, name text, value date)` | `void`
135+
`pgv_set_date(package text, name text, value date, is_transactional bool default false)` | `void`
120136
`pgv_get_date(package text, name text, strict bool default true)` | `date`
121137

122138
### Jsonb variables
123139

124140
Function | Returns
125141
-------- | -------
126-
`pgv_set_jsonb(package text, name text, value jsonb)` | `void`
142+
`pgv_set_jsonb(package text, name text, value jsonb, is_transactional bool default false)` | `void`
127143
`pgv_get_jsonb(package text, name text, strict bool default true)` | `jsonb`
128144

129145
## Record variables functions
@@ -142,7 +158,7 @@ raised.
142158

143159
Function | Returns | Description
144160
-------- | ------- | -----------
145-
`pgv_insert(package text, name text, r record)` | `void` | Inserts a record to the variable collection. If package and variable do not exists they will be created. The first column of **r** will be a primary key. If exists a record with the same primary key the error will be raised. If this variable collection has other structure the error will be raised.
161+
`pgv_insert(package text, name text, r record, is_transactional bool default false)` | `void` | Inserts a record to the variable collection. If package and variable do not exists they will be created. The first column of **r** will be a primary key. If exists a record with the same primary key the error will be raised. If this variable collection has other structure the error will be raised.
146162
`pgv_update(package text, name text, r record)` | `boolean` | Updates a record with the corresponding primary key (the first column of **r** is a primary key). Returns **true** if a record was found. If this variable collection has other structure the error will be raised.
147163
`pgv_delete(package text, name text, value anynonarray)` | `boolean` | Deletes a record with the corresponding primary key (the first column of **r** is a primary key). Returns **true** if a record was found.
148164
`pgv_select(package text, name text)` | `set of record` | Returns the variable collection records.
@@ -158,7 +174,7 @@ Function | Returns | Description
158174
`pgv_remove(package text, name text)` | `void` | Removes the variable with the corresponding name. Required package and variable must exists, otherwise the error will be raised.
159175
`pgv_remove(package text)` | `void` | Removes the package and all package variables with the corresponding name. Required package must exists, otherwise the error will be raised.
160176
`pgv_free()` | `void` | Removes all packages and variables.
161-
`pgv_list()` | `table(package text, name text)` | Returns set of records of assigned packages and variables.
177+
`pgv_list()` | `table(package text, name text, is_transactional bool)` | Returns set of records of assigned packages and variables.
162178
`pgv_stats()` | `table(package text, used_memory bigint)` | Returns list of assigned packages and used memory in bytes.
163179

164180
Note that **pgv_stats()** works only with the PostgreSQL 9.6 and newer.
@@ -172,13 +188,13 @@ SELECT pgv_set('vars', 'int1', 101);
172188
SELECT pgv_set('vars', 'int2', 102);
173189

174190
SELECT pgv_get('vars', 'int1', NULL::int);
175-
pgv_get_int
191+
pgv_get_int
176192
-------------
177193
101
178194
(1 row)
179195

180196
SELECT pgv_get('vars', 'int2', NULL::int);
181-
pgv_get_int
197+
pgv_get_int
182198
-------------
183199
102
184200
(1 row)
@@ -235,7 +251,7 @@ You can list packages and variables:
235251

236252
```sql
237253
SELECT * FROM pgv_list() order by package, name;
238-
package | name
254+
package | name
239255
---------+------
240256
vars | int1
241257
vars | int2
@@ -253,7 +269,7 @@ SELECT * FROM pgv_stats() order by package;
253269
(1 row)
254270
```
255271

256-
You can delete variables or hole packages:
272+
You can delete variables or whole packages:
257273

258274
```sql
259275
SELECT pgv_remove('vars', 'int1');
@@ -264,3 +280,67 @@ You can delete all packages and variables:
264280
```sql
265281
SELECT pgv_free();
266282
```
283+
284+
If you want variables with support of transactions and savepoints, you should add flag
285+
`is_transactional = true` as the last argument in functions `pgv_set()`
286+
or `pgv_insert()`.
287+
Following use cases describe behavior of transactional variables:
288+
```sql
289+
SELECT pgv_set('pack', 'var_text', 'before transaction block'::text, true);
290+
BEGIN;
291+
SELECT pgv_set('pack', 'var_text', 'before savepoint'::text, true);
292+
SAVEPOINT sp1;
293+
SELECT pgv_set('pack', 'var_text', 'savepoint sp1'::text, true);
294+
SELECT pgv_get('pack', 'var_text', NULL::text);
295+
SAVEPOINT sp2;
296+
SELECT pgv_set('pack', 'var_text', 'savepoint sp2'::text, true);
297+
RELEASE sp2;
298+
SELECT pgv_get('pack', 'var_text', NULL::text);
299+
pgv_get
300+
---------------
301+
savepoint sp2
302+
303+
ROLLBACK TO sp1;
304+
SELECT pgv_get('pack', 'var_text', NULL::text);
305+
pgv_get
306+
------------------
307+
before savepoint
308+
(1 row)
309+
310+
ROLLBACK;
311+
SELECT pgv_get('pack', 'var_text', NULL::text);
312+
pgv_get
313+
--------------------------
314+
before transaction block
315+
316+
```
317+
If you create variable after `BEGIN` or `SAVEPOINT` and than rollback to previous state - variable will not be exist:
318+
```sql
319+
BEGIN;
320+
SAVEPOINT sp1;
321+
SAVEPOINT sp2;
322+
SELECT pgv_set('pack', 'var_int', 122, true);
323+
RELEASE SAVEPOINT sp2;
324+
SELECT pgv_get('pack', 'var_int', NULL::int);
325+
pgv_get
326+
---------
327+
122
328+
(1 row)
329+
330+
ROLLBACK TO sp1;
331+
SELECT pgv_get('pack','var_int', NULL::int);
332+
ERROR: unrecognized variable "var_int"
333+
COMMIT;
334+
```
335+
If you created transactional variable once, you should use flag `is_transactional` every time when you want to change variable value by functions `pgv_set()`, `pgv_insert()` and deprecated setters (i.e. `pgv_set_int()`). If you try to change this option, you'll get an error:
336+
```sql
337+
SELECT pgv_insert('pack', 'var_record', row(123::int, 'text'::text), true);
338+
pgv_insert
339+
------------
340+
341+
(1 row)
342+
343+
SELECT pgv_insert('pack', 'var_record', row(456::int, 'another text'::text));
344+
ERROR: variable "var_record" already created as TRANSACTIONAL
345+
```
346+
Functions `pgv_update()` and `pgv_delete()` do not require this flag.

expected/pg_variables.out

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -645,32 +645,40 @@ SELECT pgv_select('vars2', 'j1');
645645
ERROR: variable "j1" requires "jsonb" value
646646
-- Manipulate variables
647647
SELECT * FROM pgv_list() order by package, name;
648-
package | name
649-
---------+----------
650-
vars | d1
651-
vars | d2
652-
vars | dNULL
653-
vars | int1
654-
vars | int2
655-
vars | intNULL
656-
vars | jNULL
657-
vars | num1
658-
vars | num2
659-
vars | numNULL
660-
vars | str1
661-
vars | str2
662-
vars | strNULL
663-
vars | ts1
664-
vars | ts2
665-
vars | tsNULL
666-
vars | tstz1
667-
vars | tstz2
668-
vars | tstzNULL
669-
vars2 | j1
670-
vars2 | j2
671-
vars3 | r1
648+
package | name | is_transactional
649+
---------+----------+------------------
650+
vars | d1 | f
651+
vars | d2 | f
652+
vars | dNULL | f
653+
vars | int1 | f
654+
vars | int2 | f
655+
vars | intNULL | f
656+
vars | jNULL | f
657+
vars | num1 | f
658+
vars | num2 | f
659+
vars | numNULL | f
660+
vars | str1 | f
661+
vars | str2 | f
662+
vars | strNULL | f
663+
vars | ts1 | f
664+
vars | ts2 | f
665+
vars | tsNULL | f
666+
vars | tstz1 | f
667+
vars | tstz2 | f
668+
vars | tstzNULL | f
669+
vars2 | j1 | f
670+
vars2 | j2 | f
671+
vars3 | r1 | f
672672
(22 rows)
673673

674+
SELECT package FROM pgv_stats() order by package;
675+
package
676+
---------
677+
vars
678+
vars2
679+
vars3
680+
(3 rows)
681+
674682
SELECT pgv_remove('vars', 'int3');
675683
ERROR: unrecognized variable "int3"
676684
SELECT pgv_remove('vars', 'int1');
@@ -702,27 +710,27 @@ SELECT pgv_exists('vars2');
702710
(1 row)
703711

704712
SELECT * FROM pgv_list() order by package, name;
705-
package | name
706-
---------+----------
707-
vars | d1
708-
vars | d2
709-
vars | dNULL
710-
vars | int2
711-
vars | intNULL
712-
vars | jNULL
713-
vars | num1
714-
vars | num2
715-
vars | numNULL
716-
vars | str1
717-
vars | str2
718-
vars | strNULL
719-
vars | ts1
720-
vars | ts2
721-
vars | tsNULL
722-
vars | tstz1
723-
vars | tstz2
724-
vars | tstzNULL
725-
vars3 | r1
713+
package | name | is_transactional
714+
---------+----------+------------------
715+
vars | d1 | f
716+
vars | d2 | f
717+
vars | dNULL | f
718+
vars | int2 | f
719+
vars | intNULL | f
720+
vars | jNULL | f
721+
vars | num1 | f
722+
vars | num2 | f
723+
vars | numNULL | f
724+
vars | str1 | f
725+
vars | str2 | f
726+
vars | strNULL | f
727+
vars | ts1 | f
728+
vars | ts2 | f
729+
vars | tsNULL | f
730+
vars | tstz1 | f
731+
vars | tstz2 | f
732+
vars | tstzNULL | f
733+
vars3 | r1 | f
726734
(19 rows)
727735

728736
SELECT pgv_free();
@@ -738,7 +746,7 @@ SELECT pgv_exists('vars');
738746
(1 row)
739747

740748
SELECT * FROM pgv_list() order by package, name;
741-
package | name
742-
---------+------
749+
package | name | is_transactional
750+
---------+------+------------------
743751
(0 rows)
744752

0 commit comments

Comments
 (0)