{"id":19458476,"url":"https://github.com/postgrespro/pg_variables","last_synced_at":"2025-04-15T00:45:51.129Z","repository":{"id":43012948,"uuid":"59569235","full_name":"postgrespro/pg_variables","owner":"postgrespro","description":"Session wide variables for PostgreSQL","archived":false,"fork":false,"pushed_at":"2024-10-23T12:42:21.000Z","size":424,"stargazers_count":4,"open_issues_count":5,"forks_count":2,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-04-15T00:45:33.660Z","etag":null,"topics":["json","numeric","postgres","postgresql","session","timestamp","variables"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/postgrespro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2016-05-24T11:59:49.000Z","updated_at":"2024-11-08T06:04:16.000Z","dependencies_parsed_at":"2024-02-02T18:47:17.020Z","dependency_job_id":"d5a97e61-2049-42f1-a4da-cc54b5c1f200","html_url":"https://github.com/postgrespro/pg_variables","commit_stats":{"total_commits":157,"total_committers":14,"mean_commits":"11.214285714285714","dds":0.6751592356687899,"last_synced_commit":"83b5759fbf8e187023b1bca2a4b11f6509cc1d0e"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/postgrespro%2Fpg_variables","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/postgrespro%2Fpg_variables/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/postgrespro%2Fpg_variables/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/postgrespro%2Fpg_variables/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/postgrespro","download_url":"https://codeload.github.com/postgrespro/pg_variables/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248986274,"owners_count":21194024,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","numeric","postgres","postgresql","session","timestamp","variables"],"created_at":"2024-11-10T17:27:15.187Z","updated_at":"2025-04-15T00:45:51.087Z","avatar_url":"https://github.com/postgrespro.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pg_variables - session variables with various types\n\n[![Build Status](https://travis-ci.com/postgrespro/pg_variables.svg?branch=master)](https://travis-ci.com/postgrespro/pg_variables)\n[![codecov](https://codecov.io/gh/postgrespro/pg_variables/branch/master/graph/badge.svg)](https://codecov.io/gh/postgrespro/pg_variables)\n[![GitHub license](https://img.shields.io/badge/license-PostgreSQL-blue.svg)](https://raw.githubusercontent.com/postgrespro/pg_variables/master/README.md)\n\n## Introduction\n\nThe **pg_variables** module provides functions to work with variables of various\ntypes. Created variables live only in the current user session.\nBy default, created variables are not transactional (i.e. they are not affected\nby `BEGIN`, `COMMIT` or `ROLLBACK` statements). This, however, is customizable\nby argument `is_transactional` of `pgv_set()`:\n```sql\nSELECT pgv_set('vars', 'int1', 101);\nBEGIN;\nSELECT pgv_set('vars', 'int2', 102);\nROLLBACK;\n\nSELECT * FROM pgv_list() order by package, name;\n package | name | is_transactional\n---------+------+------------------\n vars    | int1 | f\n vars    | int2 | f\n```\n\nBut if variable created with flag **is_transactional**:\n```sql\nBEGIN;\nSELECT pgv_set('vars', 'trans_int', 101, true);\nSAVEPOINT sp1;\nSELECT pgv_set('vars', 'trans_int', 102, true);\nROLLBACK TO sp1;\nCOMMIT;\nSELECT pgv_get('vars', 'trans_int', NULL::int);\n pgv_get\n---------\n     101\n```\n\nYou can aggregate variables into packages. This is done to be able to have\nvariables with different names or to quickly remove the whole batch of\nvariables. If the package becomes empty, it is automatically deleted.\n\n## License\n\nThis module available under the [license](LICENSE) similar to\n[PostgreSQL](http://www.postgresql.org/about/licence/).\n\n## Installation\n\nTypical installation procedure may look like this:\n\n    $ cd pg_variables\n    $ make USE_PGXS=1\n    $ sudo make USE_PGXS=1 install\n    $ make USE_PGXS=1 installcheck\n    $ psql DB -c \"CREATE EXTENSION pg_variables;\"\n\n## Module functions\n\nThe functions provided by the **pg_variables** module are shown in the tables\nbelow.\n\nTo use **pgv_get()** function required package and variable must exists. It is\nnecessary to set variable with **pgv_set()** function to use **pgv_get()**\nfunction.\n\nIf a package does not exists you will get the following error:\n\n```sql\nSELECT pgv_get('vars', 'int1', NULL::int);\nERROR:  unrecognized package \"vars\"\n```\n\nIf a variable does not exists you will get the following error:\n\n```sql\nSELECT pgv_get('vars', 'int1', NULL::int);\nERROR:  unrecognized variable \"int1\"\n```\n\n**pgv_get()** function check the variable type. If the variable type does not\nmatch with the function type the error will be raised:\n\n```sql\nSELECT pgv_get('vars', 'int1', NULL::text);\nERROR:  variable \"int1\" requires \"integer\" value\n```\n\n## Scalar variables functions\n\nFunction | Returns\n-------- | -------\n`pgv_set(package text, name text, value anynonarray, is_transactional bool default false)` | `void`\n`pgv_get(package text, name text, var_type anynonarray, strict bool default true)` | `anynonarray`\n\n## Array variables functions\n\nFunction | Returns\n-------- | -------\n`pgv_set(package text, name text, value anyarray, is_transactional bool default false)` | `void`\n`pgv_get(package text, name text, var_type anyarray, strict bool default true)` | `anyarray`\n\n`pgv_set` arguments:\n- `package` - name of the package, it will be created if it doesn't exist.\n- `name` - name of the variable, it will be created if it doesn't exist.\n`pgv_set` fails if the variable already exists and its transactionality doesn't\nmatch `is_transactional` argument.\n- `value` - new value for the variable. `pgv_set` fails if the variable already\nexists and its type doesn't match new value's type.\n- `is_transactional` - transactionality of the newly created variable, by\ndefault it is false.\n\n`pgv_get` arguments:\n- `package` - name of the existing package. If the package doesn't exist result\ndepends on `strict` argument: if it is false then `pgv_get` returns NULL\notherwise it fails.\n- `name` - name of the the existing variable. If the variable doesn't exist\nresult depends on `strict` argument: if it is false then `pgv_get` returns NULL\notherwise it fails.\n- `var_type` - type of the existing variable. It is necessary to pass it to get\ncorrect return type.\n- `strict` - pass false if `pgv_get` shouldn't raise an error if a variable or a\npackage didn't created before, by default it is true.\n\n## **Deprecated** scalar variables functions\n\n### Integer variables\n\nFunction | Returns\n-------- | -------\n`pgv_set_int(package text, name text, value int, is_transactional bool default false)` | `void`\n`pgv_get_int(package text, name text, strict bool default true)` | `int`\n\n### Text variables\n\nFunction | Returns\n-------- | -------\n`pgv_set_text(package text, name text, value text, is_transactional bool default false)` | `void`\n`pgv_get_text(package text, name text, strict bool default true)` | `text`\n\n### Numeric variables\n\nFunction | Returns\n-------- | -------\n`pgv_set_numeric(package text, name text, value numeric, is_transactional bool default false)` | `void`\n`pgv_get_numeric(package text, name text, strict bool default true)` | `numeric`\n\n### Timestamp variables\n\nFunction | Returns\n-------- | -------\n`pgv_set_timestamp(package text, name text, value timestamp, is_transactional bool default false)` | `void`\n`pgv_get_timestamp(package text, name text, strict bool default true)` | `timestamp`\n\n### Timestamp with timezone variables\n\nFunction | Returns\n-------- | -------\n`pgv_set_timestamptz(package text, name text, value timestamptz, is_transactional bool default false)` | `void`\n`pgv_get_timestamptz(package text, name text, strict bool default true)` | `timestamptz`\n\n### Date variables\n\nFunction | Returns\n-------- | -------\n`pgv_set_date(package text, name text, value date, is_transactional bool default false)` | `void`\n`pgv_get_date(package text, name text, strict bool default true)` | `date`\n\n### Jsonb variables\n\nFunction | Returns\n-------- | -------\n`pgv_set_jsonb(package text, name text, value jsonb, is_transactional bool default false)` | `void`\n`pgv_get_jsonb(package text, name text, strict bool default true)` | `jsonb`\n\n## Record variables functions\n\nThe following functions are provided by the module to work with collections of\nrecord types.\n\nTo use **pgv_update()**, **pgv_delete()** and **pgv_select()** functions\nrequired package and variable must exists. Otherwise the error will be raised.\nIt is necessary to set variable with **pgv_insert()** function to use these\nfunctions.\n\n**pgv_update()**, **pgv_delete()** and **pgv_select()** functions check the\nvariable type. If the variable type does not **record** type the error will be\nraised.\n\nFunction | Returns | Description\n-------- | ------- | -----------\n`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.\n`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.\n`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.\n`pgv_select(package text, name text)` | `set of record` | Returns the variable collection records.\n`pgv_select(package text, name text, value anynonarray)` | `record` | Returns the record with the corresponding primary key (the first column of **r** is a primary key).\n`pgv_select(package text, name text, value anyarray)` | `set of record` | Returns the variable collection records with the corresponding primary keys (the first column of **r** is a primary key).\n\n### Miscellaneous functions\n\nFunction | Returns | Description\n-------- | ------- | -----------\n`pgv_exists(package text, name text)` | `bool` | Returns **true** if package and variable exists.\n`pgv_exists(package text)` | `bool` | Returns **true** if package exists.\n`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.\n`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.\n`pgv_free()` | `void` | Removes all packages and variables.\n`pgv_list()` | `table(package text, name text, is_transactional bool)` | Returns set of records of assigned packages and variables.\n`pgv_stats()` | `table(package text, allocated_memory bigint)` | Returns list of assigned packages and used memory in bytes.\n\nNote that **pgv_stats()** works only with the PostgreSQL 9.6 and newer.\n\n## Examples\n\nIt is easy to use functions to work with scalar and array variables:\n\n```sql\nSELECT pgv_set('vars', 'int1', 101);\nSELECT pgv_set('vars', 'text1', 'text variable'::text);\n\nSELECT pgv_get('vars', 'int1', NULL::int);\n pgv_get_int\n-------------\n         101\n\nSELECT SELECT pgv_get('vars', 'text1', NULL::text);\n    pgv_get\n---------------\n text variable\n\nSELECT pgv_set('vars', 'arr1', '{101,102}'::int[]);\n\nSELECT pgv_get('vars', 'arr1', NULL::int[]);\n  pgv_get\n-----------\n {101,102}\n```\n\nLet's assume we have a **tab** table:\n\n```sql\nCREATE TABLE tab (id int, t varchar);\nINSERT INTO tab VALUES (0, 'str00'), (1, 'str11');\n```\n\nThen you can use functions to work with record variables:\n\n```sql\nSELECT pgv_insert('vars', 'r1', tab) FROM tab;\n\nSELECT pgv_select('vars', 'r1');\n pgv_select\n------------\n (1,str11)\n (0,str00)\n\nSELECT pgv_select('vars', 'r1', 1);\n pgv_select\n------------\n (1,str11)\n\nSELECT pgv_select('vars', 'r1', 0);\n pgv_select\n------------\n (0,str00)\n\nSELECT pgv_select('vars', 'r1', ARRAY[1, 0]);\n pgv_select\n------------\n (1,str11)\n (0,str00)\n\nSELECT pgv_delete('vars', 'r1', 1);\n\nSELECT pgv_select('vars', 'r1');\n pgv_select\n------------\n (0,str00)\n```\n\nYou can list packages and variables:\n\n```sql\nSELECT * FROM pgv_list() order by package, name;\n package | name  | is_transactional\n---------+-------+------------------\n vars    | arr1  | f\n vars    | int1  | f\n vars    | r1    | f\n vars    | text1 | f\n```\n\nAnd get used memory in bytes:\n\n```sql\nSELECT * FROM pgv_stats() order by package;\n package | allocated_memory\n---------+------------------\n vars    |            49152\n```\n\nYou can delete variables or whole packages:\n\n```sql\nSELECT pgv_remove('vars', 'int1');\nSELECT pgv_remove('vars');\n```\n\nYou can delete all packages and variables:\n```sql\nSELECT pgv_free();\n```\n\nIf you want variables with support of transactions and savepoints, you should\nadd flag `is_transactional = true` as the last argument in functions `pgv_set()`\nor `pgv_insert()`.\nFollowing use cases describe behavior of transactional variables:\n\n```sql\nSELECT pgv_set('pack', 'var_text', 'before transaction block'::text, true);\nBEGIN;\nSELECT pgv_set('pack', 'var_text', 'before savepoint'::text, true);\nSAVEPOINT sp1;\nSELECT pgv_set('pack', 'var_text', 'savepoint sp1'::text, true);\nSAVEPOINT sp2;\nSELECT pgv_set('pack', 'var_text', 'savepoint sp2'::text, true);\nRELEASE sp2;\nSELECT pgv_get('pack', 'var_text', NULL::text);\n    pgv_get\n---------------\n savepoint sp2\n\nROLLBACK TO sp1;\nSELECT pgv_get('pack', 'var_text', NULL::text);\n     pgv_get\n------------------\n before savepoint\n\nROLLBACK;\nSELECT pgv_get('pack', 'var_text', NULL::text);\n         pgv_get\n--------------------------\n before transaction block\n```\n\nIf you create a transactional variable after `BEGIN` or `SAVEPOINT` statements\nand then rollback to previous state - variable will not be exist:\n\n```sql\nBEGIN;\nSAVEPOINT sp1;\nSAVEPOINT sp2;\nSELECT pgv_set('pack', 'var_int', 122, true);\nRELEASE SAVEPOINT sp2;\nSELECT pgv_get('pack', 'var_int', NULL::int);\npgv_get\n---------\n     122\n\nROLLBACK TO sp1;\nSELECT pgv_get('pack','var_int', NULL::int);\nERROR:  unrecognized variable \"var_int\"\nCOMMIT;\n```\n\nYou can undo removal of a transactional variable by `ROLLBACK`, but if you remove\na whole package, all regular variables will be removed permanently:\n\n```sql\nSELECT pgv_set('pack', 'var_reg', 123);\nSELECT pgv_set('pack', 'var_trans', 456, true);\nBEGIN;\nSELECT pgv_free();\nSELECT * FROM pgv_list();\n package | name | is_transactional\n---------+------+------------------\n(0 rows)\n\n-- Memory is allocated yet\nSELECT * FROM pgv_stats();\n package | allocated_memory\n---------+------------------\n pack    |            24576\n\nROLLBACK;\nSELECT * FROM pgv_list();\n package |   name    | is_transactional\n---------+-----------+------------------\n pack    | var_trans | t\n```\n\nIf you created transactional variable once, you should use flag `is_transactional`\nevery time when you want to change variable value by functions `pgv_set()`,\n`pgv_insert()` and deprecated setters (i.e. `pgv_set_int()`). If you try to\nchange this option, you'll get an error:\n\n```sql\nSELECT pgv_insert('pack', 'var_record', row(123::int, 'text'::text), true);\n\nSELECT pgv_insert('pack', 'var_record', row(456::int, 'another text'::text));\nERROR:  variable \"var_record\" already created as TRANSACTIONAL\n```\n\nFunctions `pgv_update()` and `pgv_delete()` do not require this flag.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpostgrespro%2Fpg_variables","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpostgrespro%2Fpg_variables","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpostgrespro%2Fpg_variables/lists"}