{"id":17196387,"url":"https://github.com/darold/pgtt","last_synced_at":"2026-03-17T23:07:30.363Z","repository":{"id":46601561,"uuid":"256282689","full_name":"darold/pgtt","owner":"darold","description":"PostgreSQL extension to create, manage and use Oracle-style Global Temporary Tables and the others RDBMS","archived":false,"fork":false,"pushed_at":"2026-01-21T15:56:23.000Z","size":298,"stargazers_count":95,"open_issues_count":3,"forks_count":15,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-02-13T07:06:26.552Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/darold.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-04-16T17:23:44.000Z","updated_at":"2026-01-21T16:23:24.000Z","dependencies_parsed_at":"2024-04-15T07:48:14.772Z","dependency_job_id":"db6622e9-fa60-4327-819d-225fffa31b31","html_url":"https://github.com/darold/pgtt","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/darold/pgtt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darold%2Fpgtt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darold%2Fpgtt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darold%2Fpgtt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darold%2Fpgtt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darold","download_url":"https://codeload.github.com/darold/pgtt/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darold%2Fpgtt/sbom","scorecard":{"id":323055,"data":{"date":"2025-08-11","repo":{"name":"github.com/darold/pgtt","commit":"7705cef8adbfb284face1882e49e61303566346c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.2,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":10,"reason":"20 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":2,"reason":"Found 6/23 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/main.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/darold/pgtt/main.yml/master?enable=pin","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: COPYING:0","Info: FSF or OSI recognized license: ISC License: COPYING:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v4.0 not signed: https://api.github.com/repos/darold/pgtt/releases/158271589","Warn: release artifact v4.0 does not have provenance: https://api.github.com/repos/darold/pgtt/releases/158271589"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 13 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T01:50:25.102Z","repository_id":46601561,"created_at":"2025-08-18T01:50:25.102Z","updated_at":"2025-08-18T01:50:25.102Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30635156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-17T22:38:22.569Z","status":"ssl_error","status_checked_at":"2026-03-17T22:38:11.804Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2024-10-15T01:53:05.252Z","updated_at":"2026-03-17T23:07:30.354Z","avatar_url":"https://github.com/darold.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"* [Description](#description)\n* [Installation](#installation)\n* [Configuration](#configuration)\n* [Use of the extension](#use-of-the-extension)\n* [How the extension really works](#how-the-extension-really-works)\n* [Performances](performances)\n* [Authors](#authors)\n\n## PostgreSQL Global Temporary Tables\n\n### [Description](#description)\n\npgtt is a PostgreSQL extension to create, manage and use Oracle-style\nGlobal Temporary Tables and the others RDBMS.\n\nThe objective of this extension it to provide the Global Temporary Table\nfeature to PostgreSQL waiting for an in core implementation. The main\ninterest of this extension is to mimic the Oracle behavior with GTT when\nyou can not or don't want to rewrite the application code when migrating\nto PostgreSQL. In all other case best is to rewrite the code to use standard\nPostgreSQL temporary tables.\n\nThis version of the GTT extension use a regular unlogged table as\n\"template\" table and an internal rerouting to a temporary table. See\nchapter \"How the extension really works\" for more details. A previous\nimplementation of this extension using Row Security Level is still\navailable [here](https://github.com/darold/pgtt-rsl).\n\nPostgreSQL native temporary tables are automatically dropped at the\nend of a session, or optionally at the end of the current transaction.\nGlobal Temporary Tables (GTT) are permanent, they are created\nas regular tables visible to all users but their content is relative\nto the current session or transaction. Even if the table is persistent\na session or transaction can not see rows written by an other session.\n\nUsually this is not a problem, you have learn to deal with the\ntemporary table behavior of PostgreSQL but the problem comes when\nyou are migrating an Oracle database to PostgreSQL. You have to\nrewrite the SQL and PlPgSQL code to follow the application logic and\nuse PostgreSQL temporary table, that mean recreating the temporary\ntable everywhere it is used.\n\nThe other advantage of this kind of object is when your application\ncreates and drops a lot of temporary tables, the PostgreSQL catalogs\nbecomes bloated and the performances start to fall. Usually Global\nTemporary Tables prevent catalog bloating, but with this implementation\nand even if we have a permanent table, all DML are rerouted to a\nregular temporary table created at first access. See below chapter\n\"How the extension really works\" for more information.\n\nDECLARE TEMPORARY TABLE statement is not supported by PostgreSQL and\nby this extension. However this statement defines a temporary table\nfor the current connection / session, it creates tables that do not\nreside in the system catalogs and are not persistent. It cannot be\nshared with other sessions. This is the equivalent of PostgreSQL\nstandard CREATE TEMPORARY TABLE so you might just have to replace the\nDECLARE keyword by CREATE.\n\nAll Oracle's GTT behavior are respected with the different clauses\nminus what is not supported by PostgreSQL:\n\n#### ON COMMIT {DELETE | PRESERVE} ROWS\n\nSpecifies the action taken on the global temporary table when a COMMIT\noperation is performed.\n  - DELETE ROWS: all rows of the table will be deleted if no holdable\n  cursor is open on the table.\n  - PRESERVE ROWS: the rows of the table will be preserved after the\n  COMMIT.\n\n#### LOGGED or NOT LOGGED [ ON ROLLBACK {DELETE | PRESERVE} ROWS ]\n\nSpecifies whether operations for the table are logged. The default is\n`NOT LOGGED ON ROLLBACK DELETE ROWS`.\n\n* NOT LOGGED: Specifies that insert, update, or delete operations\n  against the table are not to be logged, but that the creation or\n  dropping of the table is to be logged. During a ROLLBACK or ROLLBACK\n  TO SAVEPOINT operation:\n\n  - If the table had been created within a transaction, the table is\n  dropped\n  - If the table had been dropped within a transaction, the table is\n    recreated, but without any data\n\n* ON ROLLBACK: Specifies the action that is to be taken on the not\n logged created temporary table when a ROLLBACK or ROLLBACK TO\n SAVEPOINT operation is performed. The default is DELETE ROWS.\n\n  - DELETE ROWS: if the table data has been changed, all the rows will\n  be deleted.\n  - PRESERVE ROWS: rows of the table will be preserved.\n\n* LOGGED: specifies that insert, update, or delete operations against\n the table as well as the creation or dropping of the table are to be\n logged.\n\nWith PostgreSQL only `NOT LOGGED ON ROLLBACK DELETE ROWS` can be\nsupported. Creation or dropping of the Global Temporary Table are\nlogged, see below \"How the extension really works\" for the details.\n\n\n### [Installation](#installation)\n\nTo install the pgtt extension you need at least a PostgreSQL version\n12. Untar the pgtt tarball anywhere you want then you'll need to\ncompile it with pgxs.  The `pg_config` tool must be in your path.\n\nDepending on your installation, you may need to install some devel\npackage. Once `pg_config` is in your path, do\n\n\tmake\n\tsudo make install\n\nThen it will be possible to use it using `session_preload_libraries = 'pgtt'`\nin postgresql.conf\n\nTo create and manage GTT using a non-superuser role you will have to grant\nthe CREATE privilege on the `pgtt_schema` schema to the user. For example:\n\n\tGRANT ALL ON SCHEMA pgtt_schema TO pgtt_user1;\n\nTo run test execute the following command as superuser:\n\n\tmake installcheck\n\nAn additional standalone test is provided to test the use of the\nextension as non superuser. The test can be executed using:\n\n\tmkdir results\n\tcreatedb gtt_privilege\n\tLANG=C psql -d gtt_privilege -f test/privilege.sql \u003e results/privilege.out 2\u003e\u00261\n\tdiff results/privilege.out test/expected/privilege.out\n\tdropdb gtt_privilege\n\tdropuser pgtt_user1\n\n\n### [Configuration](#configuration)\n\n- *pgtt.enabled*\n\nThe extension can be enable / disable using this GUC, default is\nenabled. To disable the extension use:\n\n\tSET pgtt.enabled TO off;\n\nYou can disable or enable the extension at any moment in a session.\n\n### [Use of the extension](#use-of-the-extension)\n\nIn all database where you want to use Global Temporary Tables you\nwill have to create the extension using:\n\n\tCREATE EXTENSION pgtt;\n\nYou can load the extension by setting in postgresql.conf :\n\n\tsession_preload_libraries = 'pgtt';\n\nor by setting it at database level as follow:\n\n\tDO $$\n\tBEGIN\n\t    EXECUTE format('ALTER DATABASE %I SET session_preload_libraries = ''pgtt''', current_database());\n\tEND\n\t$$;\n\n\nThe pgtt extension use a dedicated schema to store related objects,\nby default: `pgtt_schema`. The extension take care that this schema\nis always at end of the `search_path`.\n\n\tgtt_testdb=# SHOW search_path;\n\t    search_path\n\t--------------------\n\t public,pgtt_schema\n\t(1 row)\n\n\tgtt_testdb=# SET search_path TO appschema,public;\n\tSET\n\tgtt_testdb=# SHOW search_path;\n\t\t  search_path\n\t--------------------------------\n\t appschema, public, pgtt_schema\n\t(1 row)\n\nThe pgtt schema is automatically added to the search_path when you\nload the extension and if you change the `search_path` later.\n\nYou must also give the USAGE privilege on this schema to users that will\nmanipulate the global temporary tables.\n\n#### Create a Global Temporary Table\n\nTo create a GTT table named \"test_table\" use the following statement:\n\n\tCREATE GLOBAL TEMPORARY TABLE test_gtt_table (\n\t\tid integer,\n\t\tlbl text\n\t) ON COMMIT { PRESERVE | DELETE } ROWS;\n\n\nThe GLOBAL keyword is obsolete but can be used safely, the only thing\nis that it will generate a warning:\n\n\tWARNING:  GLOBAL is deprecated in temporary table creation\n\nIf you don't want to be annoyed by this warning message you can use\nit like a comment instead:\n\n\tCREATE /*GLOBAL*/ TEMPORARY TABLE test_gtt_table (\n\t\tLIKE other_table LIKE\n\t\tINCLUDING DEFAULTS\n\t\tINCLUDING CONSTRAINTS\n\t\tINCLUDING INDEXES\n\t) ON COMMIT { PRESERVE | DELETE } ROWS;\n\nthe extension will detect the GLOBAL keyword.\n\nAs you can see in the example above the LIKE clause is supported,\nas well as the AS clause WITH DATA or WITH NO DATA (default):\n\n\tCREATE /*GLOBAL*/ TEMPORARY TABLE test_gtt_table\n\tAS SELECT * FROM source_table WITH DATA;\n\nIn case of WITH DATA, the extension will fill the GTT with data\nreturned from the SELECT statement for the current session only.\n\nPostgreSQL temporary table clause `ON COMMIT DROP` is not supported by\nthe extension, GTT are persistent over transactions. If the clause is\nused an error will be raised.\n\nTemporary table rows are deleted or preserved at transactions commit\nfollowing the clause:\n\n\tON COMMIT { PRESERVE | DELETE } ROWS\n\n#### Drop a Global Temporary Table\n\nTo drop a Global Temporary Table you just proceed as for a normal\ntable:\n\n\tDROP TABLE test_gtt_table;\n\nA Global Temporary Table can be dropped even if it is used by other session.\n\n#### Create index on Global Temporary Table\n\nYou can create indexes on the global temporary table:\n\n\tCREATE INDEX ON test_gtt_table (id);\n\njust like with any other tables.\n\n#### Constraints on Global Temporary Table\n\nYou can add any constraint on a Global Temporary Table except FOREIGN KEYS.\n\n\tCREATE GLOBAL TEMPORARY TABLE t2 (\n\t\tc1 serial PRIMARY KEY,\n\t\tc2 VARCHAR (50) UNIQUE NOT NULL,\n\t\tc3 boolean DEFAULT false\n\t)\n\nThe use of FOREIGN KEYS in a Global Temporary Table is not allowed.\n\n\tCREATE GLOBAL TEMPORARY TABLE t1 (c1 integer, FOREIGN KEY (c1) REFERENCES source (id));\n\tERROR:  attempt to create referential integrity constraint on global temporary table\n\n\tALTER TABLE t2 ADD FOREIGN KEY (c1) REFERENCES source (id);\n\tERROR:  attempt to create referential integrity constraint on global temporary table\n\nEven if PostgreSQL allow foreign keys on temporary table, the pgtt extension try\nto mimic as much as possible the same behavior of Oracle and other RDBMS like DB2,\nSQL Server or MySQL.\n\n\tORA-14455: attempt to create referential integrity constraint on temporary table.\n\n#### Partitioning\n\nPartitioning on Global Temporary Table is not supported, again not because\nPostgreSQL do not allow partition on temporary table but because other RDBMS\nlike Oracle, DB2 and MySQL do not support it. SQL Server supports partition\non global temporary table.\n\n\n### [How the extension really works](#how-the-extension-really-works)\n\n#### Global Temporary Table usage\n\nWhen `pgtt.enabled` is true (default) and the extension have been\nloaded using any of the three methods:\n\n- `session_preload_libraries = 'pgtt'` in postgresql.conf\n- `ALTER DATABASE mydb SET session_preload_libraries = 'pgtt'`\n- in a session `LOAD 'pgtt';`\n\nthe first access to the table using a SELECT, UPDATE or DELETE statement\nwill produce the creation of a temporary table using the definition of the\n\"template\" table created during the call to `CREATE GLOBAL TEMPORARY TABLE`\nstatement.\n\nOnce the temporary table is created at the first access, the original\nSELECT, UPDATE or DELETE statement is automatically rerouted to the\nnew regular temporary table. All other access will use the new\ntemporary table, the `pg_temp*` schema where the table is created is\nalways looked first in the search path this is why the \"template\"\ntable is not concerned by subsequent access.\n\nCreating, renaming and removing a GTT is an administration task it\nshall not be done in an application session.\n\nNote that rerouting is active even if you add a namespace qualifier\nto the table. For example looking at the internal unlogged template\ntable:\n\n\tbench=# LOAD 'pgtt';\n\tLOAD\n\tbench=# CREATE /*GLOBAL*/ TEMPORARY TABLE test_tt (id int, lbl text) ON COMMIT PRESERVE ROWS;\n\tCREATE TABLE\n\tbench=# INSERT INTO test_tt VALUES (1, 'one'), (2, 'two'), (3, 'three');\n\tINSERT 0 3\n\tbench=# SELECT * FROM pgtt_schema.test_tt;\n\t id |  lbl\n\t----+-------\n\t  1 | one\n\t  2 | two\n\t  3 | three\n\t(3 rows)\n\nwill actually result in the same as looking at the associated\ntemporary table like follow:\n\n\tbench=# SELECT * FROM test_tt;\n\t id |  lbl\n\t----+-------\n\t  1 | one\n\t  2 | two\n\t  3 | three\n\t(3 rows)\n\nor\n\n\tbench=# SELECT * FROM pg_temp.test_tt;\n\t id |  lbl\n\t----+-------\n\t  1 | one\n\t  2 | two\n\t  3 | three\n\t(3 rows)\n\nIf you want to really look at the template table to be sure that\nit contains no rows, you must disable the extension rerouting:\n\n\tbench=# SET pgtt.enabled TO off;\n\tSET\n\tbench=# SELECT * FROM pgtt_schema.test_tt;\n\t id | lbl\n\t----+-----\n\t(0 rows)\n\n\tbench=# SET pgtt.enabled TO on;\n\tSET\n\tbench=# SELECT * FROM pgtt_schema.test_tt;\n\t id |  lbl\n\t----+-------\n\t  1 | one\n\t  2 | two\n\t  3 | three\n\t(3 rows)\n\nLook at test file for more examples.\n\nThis also mean that you can relocate the extension in a dedicated\nnamespace. This can be useful if your application's queries use the schema\nqualifier with the table name to access to the GTT and you can't change\nit. See t/sql/relocation.sql for an example. By default the extension\nis not relocatable in an other schema, there is some configuration\nchange to perform to be able to use this feature.\n\nIf you use the CREATE AS form with the WITH DATA clause like in this\nexample:\n\n\tCREATE /*GLOBAL*/ TEMPORARY TABLE test_gtt_table\n\tAS SELECT * FROM source_table WITH DATA;\n\nthe extension will first create the template unlogged table and will\ncreate immediately the associated temporary table filled with all data\nreturned by the SELECT statement. The first access will not have to\ncreate the table it already exists with data.\n\n#### Table creation\n\nThe extension intercept the call to `CREATE TEMPORARY TABLE ...`\nstatement and look if there is the keyword `GLOBAL` or the comment\n`/*GLOBAL*/`. When it is found, instead of creating the temporary\ntable, it creates a \"template\" unlogged persistent table following\nthe temporary table definition. When the template is created it\nregisters the table into a \"catalog\" table `pg_global_temp_tables`.\n\nBoth objects are created in the extension schema `pgtt_schema`.\n\nWhen `pgtt.enabled` is false nothing is done.\n\nHere is the description of the catalog table:\n\n```\n          Table « pgtt_schema.pg_global_temp_tables »\n  Colonne  |  Type   | Collationnement | NULL-able | Par défaut\n-----------+---------+-----------------+-----------+------------\n relid     | integer |                 | not null  |\n nspname   | name    |                 | not null  |\n relname   | name    |                 | not null  |\n preserved | boolean |                 |           |\n code      | text    |                 |           |\nIndex :\n    \"pg_global_temp_tables_nspname_relname_key\" UNIQUE CONSTRAINT, btree (nspname, relname)\n```\n\n* `relid`: Oid of the \"template\" unlogged table.\n* `nspname`: namespace of the extension `pgtt_schema` by default.\n* `relname`: name of the GTT relation.\n* `preserved`: true or false for `ON COMMIT { PRESERVE | DELETE}`.\n* `code`: code used at Global Temporary Table creation time.\n\n\n#### Table removing\n\nThe extension intercept the call to `DROP TABLE` and look in the\n`pg_global_temp_tables` table to see if it is declared. When it is\nfound it drops the template unlogged table and the corresponding\nentry from the pgtt catalog table `pg_global_temp_tables`.\n\nWhen `pgtt.enabled` is false nothing is done.\n\nDropping a GTT that is in use, when the temporary table has already\nbeen created, will raise an error. This is not allowed.\n\n\n#### Table renaming\n\nThe extension intercept the call to `ALTER TABLE ... RENAME` and look\nin the `pg_global_temp_tables` table to see if it is declared. When it\nis found it renames the \"template\" table and update the name of the\nrelation in the `pg_global_temp_tables` table. If the GTT has already\nbeen used in the session the corresponding temporary table exists, in\nthis case the extension will refuse to rename it. It must be inactive\nto be renamed.\n\nWhen `pgtt.enabled` is false nothing is done.\n\nRenaming a GTT that is in use, when the temporary table has already\nbeen created, will raise an error. This is not allowed.\n\n#### pg_dump / pg_restore\n\nWhen dumping a database using the pgtt extension, the content of the\n\"catalog\" table `pg_global_temp_tables` will be dumped as well as\nall template unlogged tables. Restoring the dump will recreate the\ndatabase in the same state.\n\n### [Performances](#performances)\n\nOverhead of loading the extension but without using it in a pgbench\ntpcb-like scenario.\n\n* Without loading the extension\n\n```\n$ pgbench -h localhost bench -c 20 -j 4 -T 60 -f test/bench/bench_noload.sql\nstarting vacuum...end.\ntransaction type: test/bench/bench_noload.sql\nscaling factor: 1\nquery mode: simple\nnumber of clients: 20\nnumber of threads: 4\nduration: 60 s\nnumber of transactions actually processed: 51741\nlatency average = 23.201 ms\ntps = 862.038042 (including connections establishing)\ntps = 862.165341 (excluding connections establishing)\n```\n\n* With loading the extension\n\n```\n$ pgbench -h localhost bench -c 20 -j 4 -T 60 -f test/bench/bench_load.sql\nstarting vacuum...end.\ntransaction type: test/bench/bench_load.sql\nscaling factor: 1\nquery mode: simple\nnumber of clients: 20\nnumber of threads: 4\nduration: 60 s\nnumber of transactions actually processed: 51171\nlatency average = 23.461 ms\ntps = 852.495877 (including connections establishing)\ntps = 852.599010 (excluding connections establishing)\n```\n\nNow a test between using a regular temporary table and a PGTT in the\npgbench tpcb-like scenario.\n\n* Using a regular Temporary Table\n\n```\n$ pgbench -h localhost bench -c 20 -j 4 -T 60 -f test/bench/bench_use_rtt.sql\nstarting vacuum...end.\ntransaction type: test/bench/bench_use_rtt.sql\nscaling factor: 1\nquery mode: simple\nnumber of clients: 20\nnumber of threads: 4\nduration: 60 s\nnumber of transactions actually processed: 17153\nlatency average = 70.058 ms\ntps = 285.477860 (including connections establishing)\ntps = 285.514186 (excluding connections establishing)\n```\n\n* Using a Global Temporary Table\n\nCreated using:\n\n\tCREATE GLOBAL TEMPORARY TABLE test_tt (id int, lbl text)\n\t\t\tON COMMIT DELETE ROWS;\n\n```\n$ pgbench -h localhost bench -c 20 -j 4 -T 60 -f test/bench/bench_use_gtt.sql\nstarting vacuum...end.\ntransaction type: test/bench/bench_use_gtt.sql\nscaling factor: 1\nquery mode: simple\nnumber of clients: 20\nnumber of threads: 4\nduration: 60 s\nnumber of transactions actually processed: 17540\nlatency average = 68.495 ms\ntps = 291.993502 (including connections establishing)\ntps = 292.028832 (excluding connections establishing)\n```\n\nEven if this last test shows a significant performances improvement\ncomparing to regular temporary tables, most of the time this will\nnot be the case.\n\n### [Authors](#authors)\n\n- Gilles Darold\n- Julien Rouhaud\n\n### [License](#license)\n\nThis extension is free software distributed under the PostgreSQL\nLicence.\n\n        Copyright (c) 2018-2025, Gilles Darold\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarold%2Fpgtt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarold%2Fpgtt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarold%2Fpgtt/lists"}