-
Notifications
You must be signed in to change notification settings - Fork 2
Version 1.1: Add support of transactions and savepoints #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
5510083
81a684b
595a779
a86437f
430989c
2fb64f8
9126f9c
e7c12d9
a3cefd3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,5 +38,6 @@ lib*.pc | |
/Debug/ | ||
/Release/ | ||
/tmp_install/ | ||
|
||
Dockerfile | ||
pg_variables--1.0.sql | ||
pg_variables--1.1.sql |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ | |
The **pg_variables** module provides functions to work with variables of various | ||
types. Created variables live only in the current user session. | ||
|
||
Note that the module does **not support transactions and savepoints**. For | ||
Note that the module does **not support transactions and savepoints by default**. For | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Я думаю, лучше все предложение целиком выкинуть. Транзакционность просто поддерживается, вот и все. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Если "поддерживается, вот и всё", то она должна по-умолчанию работать. А тут не так. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Не согласен. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Текущая формулировка привлекает внимание к проблеме, которой на самом деле нет. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Хорошо, но мне кажется, что всё равно надо обозначить где-то вначале, что у переменных может быть разное поведение. Может сделать так: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Как раз этот текст меня и смущает. Модуль в любом случае будет поддерживать транзакционность, это пользователь может хотеть или не хотеть использовать данную фичу. Поддержка зависит от кода, а не от настроек. Я предлагаю написать примерно так: By default, created variables are not transactional (i.e. they are not affected by begin, commit or rollback statements). This, however, is customizable via the ... options of pgv_set()... |
||
example: | ||
|
||
```sql | ||
|
@@ -19,13 +19,29 @@ SELECT pgv_set('vars', 'int2', 102); | |
ROLLBACK; | ||
|
||
SELECT * FROM pgv_list() order by package, name; | ||
package | name | ||
---------+------ | ||
vars | int1 | ||
vars | int2 | ||
package | name | is_transactional | ||
---------+------+------------------ | ||
vars | int1 | f | ||
vars | int2 | f | ||
(2 rows) | ||
``` | ||
|
||
But if variable created with flag **is_transactional**, it does: | ||
```sql | ||
BEGIN; | ||
SELECT pgv_set('vars', 'trans_int', 101, true); | ||
SAVEPOINT sp1; | ||
SELECT pgv_set('vars', 'trans_int', 102, true); | ||
ROLLBACK TO sp1; | ||
COMMIT; | ||
SELECT pgv_get('vars', 'trans_int', NULL::int); | ||
|
||
pgv_get | ||
--------- | ||
101 | ||
(1 row) | ||
``` | ||
|
||
## License | ||
|
||
This module available under the same license as | ||
|
@@ -76,7 +92,7 @@ ERROR: variable "int1" requires "integer" value | |
|
||
Function | Returns | ||
-------- | ------- | ||
`pgv_set(package text, name text, value anynonarray)` | `void` | ||
`pgv_set(package text, name text, value anynonarray, is_transactional bool default false)` | `void` | ||
`pgv_get(package text, name text, var_type anynonarray, strict bool default true)` | `anynonarray` | ||
|
||
## **Deprecated** scalar variables functions | ||
|
@@ -85,49 +101,49 @@ Function | Returns | |
|
||
Function | Returns | ||
-------- | ------- | ||
`pgv_set_int(package text, name text, value int)` | `void` | ||
`pgv_set_int(package text, name text, value int, is_transactional bool default false)` | `void` | ||
`pgv_get_int(package text, name text, strict bool default true)` | `int` | ||
|
||
### Text variables | ||
|
||
Function | Returns | ||
-------- | ------- | ||
`pgv_set_text(package text, name text, value text)` | `void` | ||
`pgv_set_text(package text, name text, value text, is_transactional bool default false)` | `void` | ||
`pgv_get_text(package text, name text, strict bool default true)` | `text` | ||
|
||
### Numeric variables | ||
|
||
Function | Returns | ||
-------- | ------- | ||
`pgv_set_numeric(package text, name text, value numeric)` | `void` | ||
`pgv_set_numeric(package text, name text, value numeric, is_transactional bool default false)` | `void` | ||
`pgv_get_numeric(package text, name text, strict bool default true)` | `numeric` | ||
|
||
### Timestamp variables | ||
|
||
Function | Returns | ||
-------- | ------- | ||
`pgv_set_timestamp(package text, name text, value timestamp)` | `void` | ||
`pgv_set_timestamp(package text, name text, value timestamp, is_transactional bool default false)` | `void` | ||
`pgv_get_timestamp(package text, name text, strict bool default true)` | `timestamp` | ||
|
||
### Timestamp with timezone variables | ||
|
||
Function | Returns | ||
-------- | ------- | ||
`pgv_set_timestamptz(package text, name text, value timestamptz)` | `void` | ||
`pgv_set_timestamptz(package text, name text, value timestamptz, is_transactional bool default false)` | `void` | ||
`pgv_get_timestamptz(package text, name text, strict bool default true)` | `timestamptz` | ||
|
||
### Date variables | ||
|
||
Function | Returns | ||
-------- | ------- | ||
`pgv_set_date(package text, name text, value date)` | `void` | ||
`pgv_set_date(package text, name text, value date, is_transactional bool default false)` | `void` | ||
`pgv_get_date(package text, name text, strict bool default true)` | `date` | ||
|
||
### Jsonb variables | ||
|
||
Function | Returns | ||
-------- | ------- | ||
`pgv_set_jsonb(package text, name text, value jsonb)` | `void` | ||
`pgv_set_jsonb(package text, name text, value jsonb, is_transactional bool default false)` | `void` | ||
`pgv_get_jsonb(package text, name text, strict bool default true)` | `jsonb` | ||
|
||
## Record variables functions | ||
|
@@ -146,7 +162,7 @@ raised. | |
|
||
Function | Returns | Description | ||
-------- | ------- | ----------- | ||
`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. | ||
`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. | ||
`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. | ||
`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. | ||
`pgv_select(package text, name text)` | `set of record` | Returns the variable collection records. | ||
|
@@ -162,7 +178,7 @@ Function | Returns | Description | |
`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. | ||
`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. | ||
`pgv_free()` | `void` | Removes all packages and variables. | ||
`pgv_list()` | `table(package text, name text)` | Returns set of records of assigned packages and variables. | ||
`pgv_list()` | `table(package text, name text, is_transactional bool)` | Returns set of records of assigned packages and variables. | ||
`pgv_stats()` | `table(package text, used_memory bigint)` | Returns list of assigned packages and used memory in bytes. | ||
|
||
Note that **pgv_stats()** works only with the PostgreSQL 9.6 and newer. | ||
|
@@ -176,13 +192,13 @@ SELECT pgv_set('vars', 'int1', 101); | |
SELECT pgv_set('vars', 'int2', 102); | ||
|
||
SELECT pgv_get('vars', 'int1', NULL::int); | ||
pgv_get_int | ||
pgv_get_int | ||
------------- | ||
101 | ||
(1 row) | ||
|
||
SELECT pgv_get('vars', 'int2', NULL::int); | ||
pgv_get_int | ||
pgv_get_int | ||
------------- | ||
102 | ||
(1 row) | ||
|
@@ -239,7 +255,7 @@ You can list packages and variables: | |
|
||
```sql | ||
SELECT * FROM pgv_list() order by package, name; | ||
package | name | ||
package | name | ||
---------+------ | ||
vars | int1 | ||
vars | int2 | ||
|
@@ -257,7 +273,7 @@ SELECT * FROM pgv_stats() order by package; | |
(1 row) | ||
``` | ||
|
||
You can delete variables or hole packages: | ||
You can delete variables or whole packages: | ||
|
||
```sql | ||
SELECT pgv_remove('vars', 'int1'); | ||
|
@@ -268,3 +284,66 @@ You can delete all packages and variables: | |
```sql | ||
SELECT pgv_free(); | ||
``` | ||
|
||
If you want variables with support of transactions and savepoints, you should add flag | ||
`is_transactional = true` as the last argument in functions `pgv_set()` | ||
or `pgv_insert()`. | ||
Following use cases describe behavior of transactional variables: | ||
```sql | ||
SELECT pgv_set('pack', 'var_text', 'before transaction block'::text, true); | ||
BEGIN; | ||
SELECT pgv_set('pack', 'var_text', 'before savepoint'::text, true); | ||
SAVEPOINT sp1; | ||
SELECT pgv_set('pack', 'var_text', 'savepoint sp1'::text, true); | ||
SAVEPOINT sp2; | ||
SELECT pgv_set('pack', 'var_text', 'savepoint sp2'::text, true); | ||
RELEASE sp2; | ||
SELECT pgv_get('pack', 'var_text', NULL::text); | ||
pgv_get | ||
--------------- | ||
savepoint sp2 | ||
|
||
ROLLBACK TO sp1; | ||
SELECT pgv_get('pack', 'var_text', NULL::text); | ||
pgv_get | ||
------------------ | ||
before savepoint | ||
(1 row) | ||
|
||
ROLLBACK; | ||
SELECT pgv_get('pack', 'var_text', NULL::text); | ||
pgv_get | ||
-------------------------- | ||
before transaction block | ||
|
||
``` | ||
If you create variable after `BEGIN` or `SAVEPOINT` and than rollback to previous state - variable will not be exist: | ||
```sql | ||
BEGIN; | ||
SAVEPOINT sp1; | ||
SAVEPOINT sp2; | ||
SELECT pgv_set('pack', 'var_int', 122, true); | ||
RELEASE SAVEPOINT sp2; | ||
SELECT pgv_get('pack', 'var_int', NULL::int); | ||
pgv_get | ||
--------- | ||
122 | ||
(1 row) | ||
|
||
ROLLBACK TO sp1; | ||
SELECT pgv_get('pack','var_int', NULL::int); | ||
ERROR: unrecognized variable "var_int" | ||
COMMIT; | ||
``` | ||
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: | ||
```sql | ||
SELECT pgv_insert('pack', 'var_record', row(123::int, 'text'::text), true); | ||
pgv_insert | ||
------------ | ||
|
||
(1 row) | ||
|
||
SELECT pgv_insert('pack', 'var_record', row(456::int, 'another text'::text)); | ||
ERROR: variable "var_record" already created as TRANSACTIONAL | ||
``` | ||
Functions `pgv_update()` and `pgv_delete()` do not require this flag. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Это правило нужно переместить в конец Makefile, потому что оно срабатывает по дефолту первым, и сборка ломается.