# Table of Contents - [PostgreSQL: Books](#postgresql-books) - [PostgreSQL: FAQ](#postgresql-faq) - [PostgreSQL: Tutorials & Other Resources](#postgresql-tutorials-other-resources) - [PostgreSQL: Documentation: 18: 52.65. pg_user_mapping](#postgresql-documentation-18-52-65-pg-user-mapping) - [PostgreSQL: Documentation: 18: 52.65. pg_user_mapping](#postgresql-documentation-18-52-65-pg-user-mapping) - [PostgreSQL: Documentation: 18: F.5. basic_archive — an example WAL archive module](#postgresql-documentation-18-f-5-basic-archive-an-example-wal-archive-module) - [PostgreSQL: Documentation: 18: 55.3. Error Message Style Guide](#postgresql-documentation-18-55-3-error-message-style-guide) - [PostgreSQL: Documentation: 18: F.5. basic_archive — an example WAL archive module](#postgresql-documentation-18-f-5-basic-archive-an-example-wal-archive-module) - [PostgreSQL: Documentation: 18: 43.7. PL/Perl Event Triggers](#postgresql-documentation-18-43-7-pl-perl-event-triggers) - [PostgreSQL: Documentation: 18: 43.7. PL/Perl Event Triggers](#postgresql-documentation-18-43-7-pl-perl-event-triggers) - [PostgreSQL: Documentation: 18: 53.6. pg_config](#postgresql-documentation-18-53-6-pg-config) - [PostgreSQL: Documentation: 18: pg_createsubscriber](#postgresql-documentation-18-pg-createsubscriber) - [PostgreSQL: Documentation: 18: Chapter 46. Background Worker Processes](#postgresql-documentation-18-chapter-46-background-worker-processes) - [PostgreSQL: Documentation: 18: 53.6. pg_config](#postgresql-documentation-18-53-6-pg-config) - [PostgreSQL: Documentation: 18: 64.1. Generic WAL Records](#postgresql-documentation-18-64-1-generic-wal-records) - [PostgreSQL: Documentation: 18: pg_createsubscriber](#postgresql-documentation-18-pg-createsubscriber) - [PostgreSQL: Documentation: 18: 55.3. Error Message Style Guide](#postgresql-documentation-18-55-3-error-message-style-guide) - [PostgreSQL: Documentation: 18: Chapter 46. Background Worker Processes](#postgresql-documentation-18-chapter-46-background-worker-processes) - [PostgreSQL: Documentation: 18: 36.18. Extension Building Infrastructure](#postgresql-documentation-18-36-18-extension-building-infrastructure) - [PostgreSQL: Documentation: 18: 38.3. A Complete Event Trigger Example](#postgresql-documentation-18-38-3-a-complete-event-trigger-example) - [PostgreSQL: Documentation: 18: 53.5. pg_backend_memory_contexts](#postgresql-documentation-18-53-5-pg-backend-memory-contexts) - [PostgreSQL: Documentation: 18: 42.2. PL/Tcl Functions and Arguments](#postgresql-documentation-18-42-2-pl-tcl-functions-and-arguments) - [PostgreSQL: Documentation: 18: 64.1. Generic WAL Records](#postgresql-documentation-18-64-1-generic-wal-records) - [PostgreSQL: Documentation: 18: 38.3. A Complete Event Trigger Example](#postgresql-documentation-18-38-3-a-complete-event-trigger-example) - [PostgreSQL: Documentation: 18: O.2. Default Roles Renamed to Predefined Roles](#postgresql-documentation-18-o-2-default-roles-renamed-to-predefined-roles) - [PostgreSQL: Documentation: 18: 53.2. pg_aios](#postgresql-documentation-18-53-2-pg-aios) - [PostgreSQL: Documentation: 18: 53.5. pg_backend_memory_contexts](#postgresql-documentation-18-53-5-pg-backend-memory-contexts) - [PostgreSQL: Documentation: 18: 53.2. pg_aios](#postgresql-documentation-18-53-2-pg-aios) - [PostgreSQL: Documentation: 18: E.1. Release 18.1](#postgresql-documentation-18-e-1-release-18-1) - [PostgreSQL: Documentation: 18: E.1. Release 18.1](#postgresql-documentation-18-e-1-release-18-1) - [PostgreSQL: Documentation: 18: SPI_execute_plan_extended](#postgresql-documentation-18-spi-execute-plan-extended) - [PostgreSQL: Documentation: 18: SPI_execute_plan_extended](#postgresql-documentation-18-spi-execute-plan-extended) - [PostgreSQL: Documentation: 18: SPI_start_transaction](#postgresql-documentation-18-spi-start-transaction) - [PostgreSQL: Documentation: 18: 44.8. Transaction Management](#postgresql-documentation-18-44-8-transaction-management) - [PostgreSQL: Documentation: 18: 44.8. Transaction Management](#postgresql-documentation-18-44-8-transaction-management) - [PostgreSQL: Documentation: 18: F.48. unaccent — a text search dictionary which removes diacritics](#postgresql-documentation-18-f-48-unaccent-a-text-search-dictionary-which-removes-diacritics) - [PostgreSQL: Documentation: 18: F.48. unaccent — a text search dictionary which removes diacritics](#postgresql-documentation-18-f-48-unaccent-a-text-search-dictionary-which-removes-diacritics) - [PostgreSQL: Documentation: 18: 35.47. sequences](#postgresql-documentation-18-35-47-sequences) - [PostgreSQL: Documentation: 18: F.37. pg_walinspect — low-level WAL inspection](#postgresql-documentation-18-f-37-pg-walinspect-low-level-wal-inspection) - [PostgreSQL: Documentation: 18: Chapter 16. Installation from Binaries](#postgresql-documentation-18-chapter-16-installation-from-binaries) - [PostgreSQL: Documentation: 18: F.37. pg_walinspect — low-level WAL inspection](#postgresql-documentation-18-f-37-pg-walinspect-low-level-wal-inspection) - [PostgreSQL: Documentation: 18: 13.5. Serialization Failure Handling](#postgresql-documentation-18-13-5-serialization-failure-handling) - [PostgreSQL: Documentation: 18: Chapter 16. Installation from Binaries](#postgresql-documentation-18-chapter-16-installation-from-binaries) - [PostgreSQL: Documentation: 18: 13.5. Serialization Failure Handling](#postgresql-documentation-18-13-5-serialization-failure-handling) - [PostgreSQL: Documentation: 18: DROP PUBLICATION](#postgresql-documentation-18-drop-publication) - [PostgreSQL: Documentation: 18: 35.43. routine_sequence_usage](#postgresql-documentation-18-35-43-routine-sequence-usage) - [PostgreSQL: Documentation: 18: 32.5. Pipeline Mode](#postgresql-documentation-18-32-5-pipeline-mode) - [PostgreSQL: Documentation: 18: DROP PUBLICATION](#postgresql-documentation-18-drop-publication) - [PostgreSQL: Documentation: 18: 32.5. Pipeline Mode](#postgresql-documentation-18-32-5-pipeline-mode) - [PostgreSQL: Documentation: 18: 29.13. Upgrade](#postgresql-documentation-18-29-13-upgrade) - [PostgreSQL: Documentation: 18: 15.1. How Parallel Query Works](#postgresql-documentation-18-15-1-how-parallel-query-works) - [PostgreSQL: Documentation: 18: 29.13. Upgrade](#postgresql-documentation-18-29-13-upgrade) - [PostgreSQL: Documentation: 18: 65.1. B-Tree Indexes](#postgresql-documentation-18-65-1-b-tree-indexes) - [PostgreSQL: Documentation: 18: ALTER LARGE OBJECT](#postgresql-documentation-18-alter-large-object) - [PostgreSQL: Documentation: 18: ALTER ROUTINE](#postgresql-documentation-18-alter-routine) - [PostgreSQL: Documentation: 18: 15.1. How Parallel Query Works](#postgresql-documentation-18-15-1-how-parallel-query-works) - [PostgreSQL: Documentation: 18: 65.1. B-Tree Indexes](#postgresql-documentation-18-65-1-b-tree-indexes) - [PostgreSQL: Documentation: 18: 26.4. Hot Standby](#postgresql-documentation-18-26-4-hot-standby) - [PostgreSQL: Documentation: 18: ALTER ROUTINE](#postgresql-documentation-18-alter-routine) - [PostgreSQL: Documentation: 18: 15.4. Parallel Safety](#postgresql-documentation-18-15-4-parallel-safety) - [PostgreSQL: Documentation: 18: DROP ROUTINE](#postgresql-documentation-18-drop-routine) - [PostgreSQL: Documentation: 18: Chapter 59. Writing a Table Sampling Method](#postgresql-documentation-18-chapter-59-writing-a-table-sampling-method) - [PostgreSQL: Documentation: 18: ALTER LARGE OBJECT](#postgresql-documentation-18-alter-large-object) - [PostgreSQL: Documentation: 18: 26.4. Hot Standby](#postgresql-documentation-18-26-4-hot-standby) - [PostgreSQL: Documentation: 18: 29.2. Subscription](#postgresql-documentation-18-29-2-subscription) - [PostgreSQL: Documentation: 18: DROP ROUTINE](#postgresql-documentation-18-drop-routine) - [PostgreSQL: Documentation: 18: Chapter 59. Writing a Table Sampling Method](#postgresql-documentation-18-chapter-59-writing-a-table-sampling-method) - [PostgreSQL: Documentation: 18: 29.2. Subscription](#postgresql-documentation-18-29-2-subscription) - [PostgreSQL: Documentation: 18: 15.4. Parallel Safety](#postgresql-documentation-18-15-4-parallel-safety) - [PostgreSQL: Documentation: 18: 27.4. Progress Reporting](#postgresql-documentation-18-27-4-progress-reporting) - [PostgreSQL: Documentation: 18: CREATE TEXT SEARCH DICTIONARY](#postgresql-documentation-18-create-text-search-dictionary) - [PostgreSQL: Documentation: 18: 27.4. Progress Reporting](#postgresql-documentation-18-27-4-progress-reporting) - [PostgreSQL: Documentation: 18: 66.6. Database Page Layout](#postgresql-documentation-18-66-6-database-page-layout) - [PostgreSQL: Documentation: 18: 52.40. pg_publication](#postgresql-documentation-18-52-40-pg-publication) - [PostgreSQL: Documentation: 18: 66.6. Database Page Layout](#postgresql-documentation-18-66-6-database-page-layout) - [PostgreSQL: Documentation: 18: 21.4. Dropping Roles](#postgresql-documentation-18-21-4-dropping-roles) - [PostgreSQL: Documentation: 18: F.14. earthdistance — calculate great-circle distances](#postgresql-documentation-18-f-14-earthdistance-calculate-great-circle-distances) - [PostgreSQL: Documentation: 18: 52.40. pg_publication](#postgresql-documentation-18-52-40-pg-publication) - [PostgreSQL: Documentation: 18: SPI_scroll_cursor_fetch](#postgresql-documentation-18-spi-scroll-cursor-fetch) - [PostgreSQL: Documentation: 18: 21.4. Dropping Roles](#postgresql-documentation-18-21-4-dropping-roles) - [PostgreSQL: Documentation: 18: F.8. btree_gist — GiST operator classes with B-tree behavior](#postgresql-documentation-18-f-8-btree-gist-gist-operator-classes-with-b-tree-behavior) - [PostgreSQL: Documentation: 18: 44.9. Utility Functions](#postgresql-documentation-18-44-9-utility-functions) - [PostgreSQL: Documentation: 18: 44.9. Utility Functions](#postgresql-documentation-18-44-9-utility-functions) - [PostgreSQL: Documentation: 18: F.8. btree_gist — GiST operator classes with B-tree behavior](#postgresql-documentation-18-f-8-btree-gist-gist-operator-classes-with-b-tree-behavior) - [PostgreSQL: Documentation: 18: F.7. btree_gin — GIN operator classes with B-tree behavior](#postgresql-documentation-18-f-7-btree-gin-gin-operator-classes-with-b-tree-behavior) - [PostgreSQL: Documentation: 18: DISCONNECT](#postgresql-documentation-18-disconnect) - [PostgreSQL: Documentation: 18: SPI_scroll_cursor_fetch](#postgresql-documentation-18-spi-scroll-cursor-fetch) - [PostgreSQL: Documentation: 18: F.14. earthdistance — calculate great-circle distances](#postgresql-documentation-18-f-14-earthdistance-calculate-great-circle-distances) - [PostgreSQL: Documentation: 18: F.7. btree_gin — GIN operator classes with B-tree behavior](#postgresql-documentation-18-f-7-btree-gin-gin-operator-classes-with-b-tree-behavior) - [PostgreSQL: Documentation: 18: DISCONNECT](#postgresql-documentation-18-disconnect) - [PostgreSQL: Documentation: 18: SPI_cursor_move](#postgresql-documentation-18-spi-cursor-move) - [PostgreSQL: Documentation: 18: CREATE TEXT SEARCH PARSER](#postgresql-documentation-18-create-text-search-parser) - [PostgreSQL: Documentation: 18: 35.5. applicable_roles](#postgresql-documentation-18-35-5-applicable-roles) - [PostgreSQL: Documentation: 18: SPI_cursor_move](#postgresql-documentation-18-spi-cursor-move) - [PostgreSQL: Documentation: 18: 35.4. administrable_role_​authorizations](#postgresql-documentation-18-35-4-administrable-role-authorizations) - [PostgreSQL: Documentation: 18: 35.5. applicable_roles](#postgresql-documentation-18-35-5-applicable-roles) - [PostgreSQL: Documentation: 18: 35.4. administrable_role_​authorizations](#postgresql-documentation-18-35-4-administrable-role-authorizations) - [PostgreSQL: Documentation: 18: H.4. Extensions](#postgresql-documentation-18-h-4-extensions) - [PostgreSQL: Documentation: 18: 35.52. table_constraints](#postgresql-documentation-18-35-52-table-constraints) - [PostgreSQL: Documentation: 18: CREATE TEXT SEARCH DICTIONARY](#postgresql-documentation-18-create-text-search-dictionary) - [PostgreSQL: Documentation: 18: 35.52. table_constraints](#postgresql-documentation-18-35-52-table-constraints) - [PostgreSQL: Documentation: 18: SPI_cursor_open](#postgresql-documentation-18-spi-cursor-open) - [PostgreSQL: Documentation: 18: 5.2. Default Values](#postgresql-documentation-18-5-2-default-values) - [PostgreSQL: Documentation: 18: 43.2. Data Values in PL/Perl](#postgresql-documentation-18-43-2-data-values-in-pl-perl) - [PostgreSQL: Documentation: 18: pg_controldata](#postgresql-documentation-18-pg-controldata) - [PostgreSQL: Documentation: 18: DROP ROLE](#postgresql-documentation-18-drop-role) - [PostgreSQL: Documentation: 18: 5.2. Default Values](#postgresql-documentation-18-5-2-default-values) - [PostgreSQL: Documentation: 18: 42.5. Database Access from PL/Tcl](#postgresql-documentation-18-42-5-database-access-from-pl-tcl) - [PostgreSQL: Documentation: 18: 10.5. UNION, CASE, and Related Constructs](#postgresql-documentation-18-10-5-union-case-and-related-constructs) - [PostgreSQL: Documentation: 18: 42.5. Database Access from PL/Tcl](#postgresql-documentation-18-42-5-database-access-from-pl-tcl) - [PostgreSQL: Documentation: 18: Preface](#postgresql-documentation-18-preface) - [PostgreSQL: Documentation: 18: CHECKPOINT](#postgresql-documentation-18-checkpoint) - [PostgreSQL: Documentation: 18: DROP RULE](#postgresql-documentation-18-drop-rule) - [PostgreSQL: Documentation: 18: 5.5. Constraints](#postgresql-documentation-18-5-5-constraints) - [PostgreSQL: Documentation: 18: 53.25. pg_settings](#postgresql-documentation-18-53-25-pg-settings) - [PostgreSQL: Documentation: 18: 53.25. pg_settings](#postgresql-documentation-18-53-25-pg-settings) - [PostgreSQL: Documentation: 18: 19.8. Error Reporting and Logging](#postgresql-documentation-18-19-8-error-reporting-and-logging) - [PostgreSQL: Documentation: 18: 52.34. pg_operator](#postgresql-documentation-18-52-34-pg-operator) - [PostgreSQL: Documentation: 18: 18.7. Preventing Server Spoofing](#postgresql-documentation-18-18-7-preventing-server-spoofing) - [PostgreSQL: Documentation: 18: CREATE TEXT SEARCH PARSER](#postgresql-documentation-18-create-text-search-parser) - [PostgreSQL: Documentation: 18: H.4. Extensions](#postgresql-documentation-18-h-4-extensions) - [PostgreSQL: Documentation: 18: 18.7. Preventing Server Spoofing](#postgresql-documentation-18-18-7-preventing-server-spoofing) - [PostgreSQL: Documentation: 18: 52.32. pg_namespace](#postgresql-documentation-18-52-32-pg-namespace) - [PostgreSQL: Documentation: 18: F.17. hstore — hstore key/value datatype](#postgresql-documentation-18-f-17-hstore-hstore-key-value-datatype) - [PostgreSQL: Documentation: 18: 43.2. Data Values in PL/Perl](#postgresql-documentation-18-43-2-data-values-in-pl-perl) - [PostgreSQL: Documentation: 18: pg_controldata](#postgresql-documentation-18-pg-controldata) - [PostgreSQL: Documentation: 18: F.17. hstore — hstore key/value datatype](#postgresql-documentation-18-f-17-hstore-hstore-key-value-datatype) - [PostgreSQL: Documentation: 18: SPI_cursor_open](#postgresql-documentation-18-spi-cursor-open) - [PostgreSQL: Documentation: 18: 52.32. pg_namespace](#postgresql-documentation-18-52-32-pg-namespace) - [PostgreSQL: Documentation: 18: 5.1. Table Basics](#postgresql-documentation-18-5-1-table-basics) - [PostgreSQL: Documentation: 18: 33.3. Client Interfaces](#postgresql-documentation-18-33-3-client-interfaces) - [PostgreSQL: Documentation: 18: 33.3. Client Interfaces](#postgresql-documentation-18-33-3-client-interfaces) - [PostgreSQL: Documentation: 18: 5.1. Table Basics](#postgresql-documentation-18-5-1-table-basics) - [PostgreSQL: Documentation: 18: 10.5. UNION, CASE, and Related Constructs](#postgresql-documentation-18-10-5-union-case-and-related-constructs) - [PostgreSQL: Documentation: 18: Preface](#postgresql-documentation-18-preface) - [PostgreSQL: Documentation: 18: DROP ROLE](#postgresql-documentation-18-drop-role) - [PostgreSQL: Documentation: 18: CHECKPOINT](#postgresql-documentation-18-checkpoint) - [PostgreSQL: Documentation: 18: 36.16. Interfacing Extensions to Indexes](#postgresql-documentation-18-36-16-interfacing-extensions-to-indexes) - [PostgreSQL: Documentation: 18: DROP RULE](#postgresql-documentation-18-drop-rule) - [PostgreSQL: Documentation: 18: 5.5. Constraints](#postgresql-documentation-18-5-5-constraints) - [PostgreSQL: Documentation: 18: 36.16. Interfacing Extensions to Indexes](#postgresql-documentation-18-36-16-interfacing-extensions-to-indexes) - [PostgreSQL: Documentation: 18: 52.34. pg_operator](#postgresql-documentation-18-52-34-pg-operator) - [PostgreSQL: Documentation: 18: 19.8. Error Reporting and Logging](#postgresql-documentation-18-19-8-error-reporting-and-logging) - [PostgreSQL: Documentation: 18: postgres](#postgresql-documentation-18-postgres) - [PostgreSQL: Documentation: 18: postgres](#postgresql-documentation-18-postgres) - [PostgreSQL: Documentation: 18: CREATE LANGUAGE](#postgresql-documentation-18-create-language) - [PostgreSQL: Documentation: 18: CREATE LANGUAGE](#postgresql-documentation-18-create-language) - [PostgreSQL: Documentation: 18: 9.28. System Administration Functions](#postgresql-documentation-18-9-28-system-administration-functions) - [PostgreSQL: Documentation: 18: 35.43. routine_sequence_usage](#postgresql-documentation-18-35-43-routine-sequence-usage) - [PostgreSQL: Documentation: 18: 9.28. System Administration Functions](#postgresql-documentation-18-9-28-system-administration-functions) - [PostgreSQL: Documentation: 18: 52.41. pg_publication_namespace](#postgresql-documentation-18-52-41-pg-publication-namespace) - [PostgreSQL: Documentation: 18: 52.41. pg_publication_namespace](#postgresql-documentation-18-52-41-pg-publication-namespace) - [PostgreSQL: Documentation: 18: CREATE TEXT SEARCH TEMPLATE](#postgresql-documentation-18-create-text-search-template) - [PostgreSQL: Documentation: 18: CREATE TEXT SEARCH TEMPLATE](#postgresql-documentation-18-create-text-search-template) - [PostgreSQL: Documentation: 18: 29.11. Security](#postgresql-documentation-18-29-11-security) - [PostgreSQL: Documentation: 18: 29.11. Security](#postgresql-documentation-18-29-11-security) - [PostgreSQL: Documentation: 18: 35.6. attributes](#postgresql-documentation-18-35-6-attributes) - [PostgreSQL: Documentation: 18: 35.6. attributes](#postgresql-documentation-18-35-6-attributes) - [PostgreSQL: Documentation: 18: 32.17. The Connection Service File](#postgresql-documentation-18-32-17-the-connection-service-file) - [PostgreSQL: Documentation: 18: 32.17. The Connection Service File](#postgresql-documentation-18-32-17-the-connection-service-file) - [PostgreSQL: Documentation: 18: 53.24. pg_sequences](#postgresql-documentation-18-53-24-pg-sequences) - [PostgreSQL: Documentation: 18: 53.24. pg_sequences](#postgresql-documentation-18-53-24-pg-sequences) - [PostgreSQL: Documentation: 18: Appendix A. PostgreSQL Error Codes](#postgresql-documentation-18-appendix-a-postgresql-error-codes) - [PostgreSQL: Documentation: 18: 10.6. SELECT Output Columns](#postgresql-documentation-18-10-6-select-output-columns) - [PostgreSQL: Documentation: 18: 35.7. character_sets](#postgresql-documentation-18-35-7-character-sets) - [PostgreSQL: Documentation: 18: 10.6. SELECT Output Columns](#postgresql-documentation-18-10-6-select-output-columns) - [PostgreSQL: Documentation: 18: pg_isready](#postgresql-documentation-18-pg-isready) - [PostgreSQL: Documentation: 18: pg_isready](#postgresql-documentation-18-pg-isready) - [PostgreSQL: Documentation: 18: 35.7. character_sets](#postgresql-documentation-18-35-7-character-sets) - [PostgreSQL: Documentation: 18: SPI_is_cursor_plan](#postgresql-documentation-18-spi-is-cursor-plan) - [PostgreSQL: Documentation: 18: Chapter 22. Managing Databases](#postgresql-documentation-18-chapter-22-managing-databases) - [PostgreSQL: Documentation: 18: Chapter 55. PostgreSQL Coding Conventions](#postgresql-documentation-18-chapter-55-postgresql-coding-conventions) - [PostgreSQL: Documentation: 18: Chapter 27. Monitoring Database Activity](#postgresql-documentation-18-chapter-27-monitoring-database-activity) - [PostgreSQL: Documentation: 18: ALTER OPERATOR](#postgresql-documentation-18-alter-operator) - [PostgreSQL: Documentation: 18: CREATE POLICY](#postgresql-documentation-18-create-policy) - [PostgreSQL: Documentation: 18: 11.10. Operator Classes and Operator Families](#postgresql-documentation-18-11-10-operator-classes-and-operator-families) - [PostgreSQL: Documentation: 8.4: sequences](#postgresql-documentation-8-4-sequences) - [PostgreSQL: Documentation: 18: VACUUM](#postgresql-documentation-18-vacuum) - [PostgreSQL: Documentation: 18: LOCK](#postgresql-documentation-18-lock) - [PostgreSQL: Documentation: 18: Chapter 18. Server Setup and Operation](#postgresql-documentation-18-chapter-18-server-setup-and-operation) - [PostgreSQL: Documentation: 18: 17.6. Supported Platforms](#postgresql-documentation-18-17-6-supported-platforms) - [PostgreSQL: Documentation: 18: 68.1. System Catalog Declaration Rules](#postgresql-documentation-18-68-1-system-catalog-declaration-rules) - [PostgreSQL: Documentation: 9.3: ALTER EXTENSION](#postgresql-documentation-9-3-alter-extension) - [PostgreSQL: Documentation: 18: 32.23. Example Programs](#postgresql-documentation-18-32-23-example-programs) - [PostgreSQL: Documentation: 18: 32.23. Example Programs](#postgresql-documentation-18-32-23-example-programs) - [PostgreSQL: Documentation: 9.2: sequences](#postgresql-documentation-9-2-sequences) - [PostgreSQL: Documentation: 18: IMPORT FOREIGN SCHEMA](#postgresql-documentation-18-import-foreign-schema) - [PostgreSQL: Documentation: 18: 2.7. Aggregate Functions](#postgresql-documentation-18-2-7-aggregate-functions) - [PostgreSQL: Documentation: 18: 53.11. pg_ident_file_mappings](#postgresql-documentation-18-53-11-pg-ident-file-mappings) - [PostgreSQL: Documentation: 18: 53.9. pg_group](#postgresql-documentation-18-53-9-pg-group) - [PostgreSQL: Documentation: 7.2: Example](#postgresql-documentation-7-2-example) - [PostgreSQL: Documentation: 7.2: ALTER TABLE ](#postgresql-documentation-7-2-alter-table-) - [PostgreSQL: Documentation: 18: 51.3. The Parser Stage](#postgresql-documentation-18-51-3-the-parser-stage) - [PostgreSQL: Documentation: 9.0: sequences](#postgresql-documentation-9-0-sequences) - [PostgreSQL: Documentation: 18: 32.14. Event System](#postgresql-documentation-18-32-14-event-system) - [PostgreSQL: Documentation: 18: Chapter 14. Performance Tips](#postgresql-documentation-18-chapter-14-performance-tips) - [PostgreSQL: Documentation: 9.1: ALTER EXTENSION](#postgresql-documentation-9-1-alter-extension) - [PostgreSQL: Documentation: 18: CREATE OPERATOR CLASS](#postgresql-documentation-18-create-operator-class) - [PostgreSQL: Documentation: 18: 53.34. pg_timezone_names](#postgresql-documentation-18-53-34-pg-timezone-names) - [PostgreSQL: Documentation: 18: 43.8. PL/Perl Under the Hood](#postgresql-documentation-18-43-8-pl-perl-under-the-hood) - [PostgreSQL: Documentation: 18: CREATE STATISTICS](#postgresql-documentation-18-create-statistics) - [PostgreSQL: Documentation: 18: ALTER INDEX](#postgresql-documentation-18-alter-index) - [PostgreSQL: Documentation: 18: 53.19. pg_replication_origin_status](#postgresql-documentation-18-53-19-pg-replication-origin-status) - [PostgreSQL: Documentation: 18: Chapter 13. Concurrency Control](#postgresql-documentation-18-chapter-13-concurrency-control) - [PostgreSQL: Documentation: 18: ALTER OPERATOR](#postgresql-documentation-18-alter-operator) - [PostgreSQL: Documentation: 9.3: column_options](#postgresql-documentation-9-3-column-options) - [PostgreSQL: Documentation: 18: 8.8. Geometric Types](#postgresql-documentation-18-8-8-geometric-types) - [PostgreSQL: Documentation: 18: 8.17. Range Types](#postgresql-documentation-18-8-17-range-types) - [PostgreSQL: Documentation: 18: CREATE FUNCTION](#postgresql-documentation-18-create-function) - [PostgreSQL: Documentation: 18: CREATE VIEW](#postgresql-documentation-18-create-view) - [PostgreSQL: Documentation: 18: dropuser](#postgresql-documentation-18-dropuser) - [PostgreSQL: Documentation: 18: Chapter 4. SQL Syntax](#postgresql-documentation-18-chapter-4-sql-syntax) - [PostgreSQL: Documentation: 18: CREATE OPERATOR](#postgresql-documentation-18-create-operator) - [PostgreSQL: Documentation: 9.3: Date/Time Input Interpretation](#postgresql-documentation-9-3-date-time-input-interpretation) - [PostgreSQL: Documentation: 18: CREATE FUNCTION](#postgresql-documentation-18-create-function) - [PostgreSQL: Documentation: 18: Chapter 25. Backup and Restore](#postgresql-documentation-18-chapter-25-backup-and-restore) - [PostgreSQL: Documentation: 18: ALTER DEFAULT PRIVILEGES](#postgresql-documentation-18-alter-default-privileges) - [PostgreSQL: Documentation: 18: 55.4. Miscellaneous Coding Conventions](#postgresql-documentation-18-55-4-miscellaneous-coding-conventions) - [PostgreSQL: Documentation: 18: Chapter 3. Advanced Features](#postgresql-documentation-18-chapter-3-advanced-features) - [PostgreSQL: Documentation: 18: 32.11. Control Functions](#postgresql-documentation-18-32-11-control-functions) - [PostgreSQL: Documentation: 18: 32.22. Building libpq Programs](#postgresql-documentation-18-32-22-building-libpq-programs) - [PostgreSQL: Documentation: 9.3: The Schema](#postgresql-documentation-9-3-the-schema) - [PostgreSQL: Documentation: 9.3: pgcrypto](#postgresql-documentation-9-3-pgcrypto) - [PostgreSQL: Documentation: 9.3: CREATE USER MAPPING](#postgresql-documentation-9-3-create-user-mapping) - [PostgreSQL: Documentation: 9.3: DEALLOCATE DESCRIPTOR](#postgresql-documentation-9-3-deallocate-descriptor) - [PostgreSQL: Documentation: 16: ALTER LANGUAGE](#postgresql-documentation-16-alter-language) - [PostgreSQL: Documentation: 16: Chapter 22. Database Roles](#postgresql-documentation-16-chapter-22-database-roles) - [PostgreSQL: Documentation: 16: ALTER TABLE](#postgresql-documentation-16-alter-table) - [PostgreSQL: Documentation: 16: 17.2. Getting the Source](#postgresql-documentation-16-17-2-getting-the-source) - [PostgreSQL: Documentation: 14: 10.3. Functions](#postgresql-documentation-14-10-3-functions) - [PostgreSQL: Documentation: 14: 53.8. Error and Notice Message Fields](#postgresql-documentation-14-53-8-error-and-notice-message-fields) - [PostgreSQL: Documentation: 14: Chapter 56. Writing a Procedural Language Handler](#postgresql-documentation-14-chapter-56-writing-a-procedural-language-handler) - [PostgreSQL: Documentation: 14: TRUNCATE](#postgresql-documentation-14-truncate) - [PostgreSQL: Documentation: 14: 53.2. Message Flow](#postgresql-documentation-14-53-2-message-flow) - [PostgreSQL: Documentation: 11: Chapter 55. Native Language Support](#postgresql-documentation-11-chapter-55-native-language-support) - [PostgreSQL: Documentation: 14: 36.8. Error Handling](#postgresql-documentation-14-36-8-error-handling) - [PostgreSQL: Documentation: 11: ALTER EXTENSION](#postgresql-documentation-11-alter-extension) - [PostgreSQL: Documentation: 11: F.26. pg_freespacemap](#postgresql-documentation-11-f-26-pg-freespacemap) - [PostgreSQL: Documentation: 11: 60.4. Further Reading](#postgresql-documentation-11-60-4-further-reading) - [PostgreSQL: Documentation: 11: 52.31. pg_largeobject_metadata](#postgresql-documentation-11-52-31-pg-largeobject-metadata) - [PostgreSQL: Documentation: 11: 46.6. Trigger Functions](#postgresql-documentation-11-46-6-trigger-functions) - [PostgreSQL: Documentation: 8.1: Release 8.1.18](#postgresql-documentation-8-1-release-8-1-18) - [PostgreSQL: Documentation: 11: 52.3. pg_am](#postgresql-documentation-11-52-3-pg-am) - [PostgreSQL: Documentation: 11: H.3. Procedural Languages](#postgresql-documentation-11-h-3-procedural-languages) - [PostgreSQL: Documentation: 18: 52.30. pg_largeobject](#postgresql-documentation-18-52-30-pg-largeobject) - [PostgreSQL: Documentation: 8.1: Supported Platforms](#postgresql-documentation-8-1-supported-platforms) - [PostgreSQL: Documentation: 7.3: BKI Commands](#postgresql-documentation-7-3-bki-commands) - [PostgreSQL: Documentation: 18: ALTER VIEW](#postgresql-documentation-18-alter-view) - [PostgreSQL: Documentation: 18: ALTER OPERATOR FAMILY](#postgresql-documentation-18-alter-operator-family) - [PostgreSQL: Documentation: 7.3: Dependency Tracking](#postgresql-documentation-7-3-dependency-tracking) - [PostgreSQL: Documentation: 7.2: Controlling the Planner with Explicit JOINs](#postgresql-documentation-7-2-controlling-the-planner-with-explicit-joins) - [PostgreSQL: Documentation: 7.2: BKI Backend Interface](#postgresql-documentation-7-2-bki-backend-interface) - [PostgreSQL: Documentation: 9.0: PL/Perl Under the Hood](#postgresql-documentation-9-0-pl-perl-under-the-hood) - [PostgreSQL: Documentation: 18: 53.38. pg_wait_events](#postgresql-documentation-18-53-38-pg-wait-events) - [PostgreSQL: Documentation: 8.3: dblink_current_query](#postgresql-documentation-8-3-dblink-current-query) - [PostgreSQL: Documentation: 7.2: DROP LANGUAGE](#postgresql-documentation-7-2-drop-language) - [PostgreSQL: Documentation: 7.3: SQL Conformance](#postgresql-documentation-7-3-sql-conformance) - [PostgreSQL: Documentation: 9.5: Preset Options](#postgresql-documentation-9-5-preset-options) - [PostgreSQL: Documentation: 9.5: Binary String Functions and Operators](#postgresql-documentation-9-5-binary-string-functions-and-operators) - [PostgreSQL: Documentation: 9.5: vacuumlo](#postgresql-documentation-9-5-vacuumlo) - [PostgreSQL: Documentation: 9.5: ALTER TEXT SEARCH DICTIONARY](#postgresql-documentation-9-5-alter-text-search-dictionary) - [PostgreSQL: Documentation: 9.5: pg_available_extension_versions](#postgresql-documentation-9-5-pg-available-extension-versions) - [PostgreSQL: Documentation: 9.5: CLUSTER](#postgresql-documentation-9-5-cluster) - [PostgreSQL: Documentation: 17: 34.16. Oracle Compatibility Mode](#postgresql-documentation-17-34-16-oracle-compatibility-mode) - [PostgreSQL: Documentation: 9.5: pg_stats](#postgresql-documentation-9-5-pg-stats) - [PostgreSQL: Documentation: 17: 51.28. pg_init_privs](#postgresql-documentation-17-51-28-pg-init-privs) - [PostgreSQL: Documentation: 9.5: DROP LANGUAGE](#postgresql-documentation-9-5-drop-language) - [PostgreSQL: Documentation: 17: 5.6. System Columns](#postgresql-documentation-17-5-6-system-columns) - [PostgreSQL: Documentation: 17: DROP RULE](#postgresql-documentation-17-drop-rule) - [PostgreSQL: Documentation: 18: 45.5. Visibility of Data Changes](#postgresql-documentation-18-45-5-visibility-of-data-changes) - [PostgreSQL: Documentation: 16: 8.12. UUID Type](#postgresql-documentation-16-8-12-uuid-type) - [PostgreSQL: Documentation: 16: 37.47. sequences](#postgresql-documentation-16-37-47-sequences) - [PostgreSQL: Documentation: 17: dropdb](#postgresql-documentation-17-dropdb) - [PostgreSQL: Documentation: 17: 22.5. Destroying a Database](#postgresql-documentation-17-22-5-destroying-a-database) - [PostgreSQL: Documentation: 18: ALTER ROLE](#postgresql-documentation-18-alter-role) - [PostgreSQL: Documentation: 9.6: pg_event_trigger](#postgresql-documentation-9-6-pg-event-trigger) - [PostgreSQL: Documentation: 17: DROP FUNCTION](#postgresql-documentation-17-drop-function) - [PostgreSQL: Documentation: 16: 5.5. System Columns](#postgresql-documentation-16-5-5-system-columns) - [PostgreSQL: Documentation: 17: 35.39. role_usage_grants](#postgresql-documentation-17-35-39-role-usage-grants) - [PostgreSQL: Documentation: 17: Bibliography](#postgresql-documentation-17-bibliography) - [PostgreSQL: Documentation: 17: 34.17. Internals](#postgresql-documentation-17-34-17-internals) - [PostgreSQL: Documentation: 16: Chapter 75. System Catalog Declarations and Initial Contents](#postgresql-documentation-16-chapter-75-system-catalog-declarations-and-initial-contents) - [PostgreSQL: Documentation: 16: DROP OPERATOR](#postgresql-documentation-16-drop-operator) - [PostgreSQL: Documentation: 16: Chapter 15. Parallel Query](#postgresql-documentation-16-chapter-15-parallel-query) - [PostgreSQL: Documentation: 10: 50.1. The Path of a Query](#postgresql-documentation-10-50-1-the-path-of-a-query) - [PostgreSQL: Documentation: 17: 41.9. Errors and Messages](#postgresql-documentation-17-41-9-errors-and-messages) - [PostgreSQL: Documentation: 15: 44.9. Explicit Subtransactions in PL/Tcl](#postgresql-documentation-15-44-9-explicit-subtransactions-in-pl-tcl) - [PostgreSQL: Documentation: 18: 19.9. Run-time Statistics](#postgresql-documentation-18-19-9-run-time-statistics) - [PostgreSQL: Documentation: 8.4: Overview](#postgresql-documentation-8-4-overview) - [PostgreSQL: Documentation: 9.6: pg_collation](#postgresql-documentation-9-6-pg-collation) - [PostgreSQL: Documentation: 12: ALTER RULE](#postgresql-documentation-12-alter-rule) - [PostgreSQL: Documentation: 8.4: Tcl Procedure Names](#postgresql-documentation-8-4-tcl-procedure-names) - [PostgreSQL: Documentation: 18: 19.18. Short Options](#postgresql-documentation-18-19-18-short-options) - [PostgreSQL: Documentation: 17: 63.2. Custom WAL Resource Managers](#postgresql-documentation-17-63-2-custom-wal-resource-managers) - [PostgreSQL: Documentation: 9.4: CREATE ROLE](#postgresql-documentation-9-4-create-role) - [PostgreSQL: Documentation: 17: 9.8. Data Type Formatting Functions](#postgresql-documentation-17-9-8-data-type-formatting-functions) - [PostgreSQL: Documentation: 16: 36.16. Oracle Compatibility Mode](#postgresql-documentation-16-36-16-oracle-compatibility-mode) - [PostgreSQL: Documentation: 17: Chapter 19. Server Configuration](#postgresql-documentation-17-chapter-19-server-configuration) - [PostgreSQL: Documentation: 16: Chapter 33. Regression Tests](#postgresql-documentation-16-chapter-33-regression-tests) - [PostgreSQL: Documentation: 15: pg_recvlogical](#postgresql-documentation-15-pg-recvlogical) - [PostgreSQL: Documentation: 9.6: pg_amop](#postgresql-documentation-9-6-pg-amop) - [PostgreSQL: Documentation: 17: 20.15. Authentication Problems](#postgresql-documentation-17-20-15-authentication-problems) - [PostgreSQL: Documentation: 9.6: pg_am](#postgresql-documentation-9-6-pg-am) - [PostgreSQL: Documentation: 17: CREATE FOREIGN DATA WRAPPER](#postgresql-documentation-17-create-foreign-data-wrapper) - [PostgreSQL: Documentation: 17: Chapter 42. PL/Tcl — Tcl Procedural Language](#postgresql-documentation-17-chapter-42-pl-tcl-tcl-procedural-language) - [PostgreSQL: Documentation: 8.2: createdb](#postgresql-documentation-8-2-createdb) - [PostgreSQL: Documentation: 16: Chapter 24. Localization](#postgresql-documentation-16-chapter-24-localization) --- # PostgreSQL: Books November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) Quick Links ----------- * [Documentation](https://www.postgresql.org/docs/) * [Manuals](https://www.postgresql.org/docs/) * [Archive](https://www.postgresql.org/docs/manuals/archive/) * [Release Notes](https://www.postgresql.org/docs/release/) * [Books](https://www.postgresql.org/docs/books/) * [Tutorials & Other Resources](https://www.postgresql.org/docs/online-resources/) * [FAQ](https://www.postgresql.org/docs/faq/) * [Wiki](https://wiki.postgresql.org/) Books ===== | Cover | Information | | --- | --- | | [![Decode PostgreSQL: Understanding the World's Most Powerful Open Source Database Without Writing Code](https://www.postgresql.org/media/img/docs/books/decode_postgres.png)](https://decodepress.gumroad.com/l/postgresql) | **Title**: Decode PostgreSQL: Understanding the World's Most Powerful Open Source Database Without Writing Code
**Author**: Ellyne Phneah
**Language**: English
**Current version at publication**: 17
**Format**: eBook
**Published**: September 2025 | | [![PostgreSQL Mistakes and How to Avoid Them](https://www.postgresql.org/media/img/docs/books/postgresql-mistakes-and-how-to-avoid-them.jpg)](https://www.manning.com/books/postgresql-mistakes-and-how-to-avoid-them) | **Title**: PostgreSQL Mistakes and How to Avoid Them
**Author**: Jimmy Angelakos
**Language**: English
**Current version at publication**: 17
**Format**: Paperback, eBook
**Published**: June 2025 | | [![Introduction to PostgreSQL for the data professional](https://www.postgresql.org/media/img/docs/books/postgresql_data_professional.png)](https://www.amazon.com/Introduction-PostgreSQL-data-professional-Ryan/dp/1036902374) | **Title**: Introduction to PostgreSQL for the data professional
**Author**: Ryan Booz, Grant Fritchey
**Language**: English
**Current version at publication**: 17
**Format**: Paperback, eBook
**Published**: February 2025 | | [![Mastering PostgreSQL 17](https://www.postgresql.org/media/img/docs/books/mastering_postgresql17.png)](https://www.packtpub.com/en-se/product/mastering-postgresql-17-9781836205968) | **Title**: Mastering PostgreSQL 17
**Author**: Hans-Jürgen Schönig
**Language**: English
**Current version at publication**: 17
**Format**: Paperback, eBook
**Published**: December 2024 | | [![High Performance PostgreSQL for Rails](https://www.postgresql.org/media/img/docs/books/postgresql_for_rails.png)](https://pragprog.com/titles/aapsql/high-performance-postgresql-for-rails/) | **Title**: High Performance PostgreSQL for Rails
**Author**: Andrew Atkinson
**Language**: English
**Current version at publication**: 16
**Format**: Paperback, eBook
**Published**: June 2024 | | [![PostgreSQL 16 Administration Cookbook](https://www.postgresql.org/media/img/docs/books/postgresql-16-administration-cookbook.jpg)](https://www.packtpub.com/product/postgresql-16-administration-cookbook/9781835460580) | **Title**: PostgreSQL 16 Administration Cookbook
**Authors**: Gianni Ciolli, Boriss Mejías, Jimmy Angelakos, Vibhor Kumar, Simon Riggs
**Language**: English
**Current version at publication**: 16
**Format**: Paperback, eBook
**Published**: December 2023 | | [![Learn PostgreSQL - Second Edition](https://www.postgresql.org/media/img/docs/books/learn_postgresql_second_edition.jpg)](https://www.packtpub.com/product/learn-postgresql-second-edition/9781837635641) | **Title**: Learn PostgreSQL - Second Edition
**Authors**: Luca Ferrari, Enrico Pirozzi
**Language**: English
**Current version at publication**: 16
**Format**: Paperback, eBook
**Published**: October 2023 | | [![PostgreSQL - Architecture et notions avancées](https://www.postgresql.org/media/img/docs/books/architecture-et-notions-avancees-5ed.png)](https://www.d-booker.fr/bases-de-donnees/805-1338-postgresql-architecture-et-notions-avancees-5ed.html) | **Title**: PostgreSQL - Architecture et notions avancées
**Authors**: Guillaume Lelarge, Julien Rouhaud
**Language**: French
**Current version at publication**: 16
**Format**: Paperback, eBook
**Published**: October 2023 | | [![PostgreSQL For Jobseekers book](https://www.postgresql.org/media/img/docs/books/postgresql-for-jobseekers.png)](https://www.amazon.com/dp/B0C8Z4C9TQ/) | **Title**: PostgreSQL for Jobseekers
**Authors**: Sonia Valeja, David Gonzalez
**Language**: English
**Current version at publication**: 15
**Format**: Paperback, eBook
**Published**: June 2023 | | [![POSTGRES: The First Experience](https://www.postgresql.org/media/img/docs/books/postgres_first_experience_v9.png)](https://postgrespro.com/community/books/introbook) | **Title**: POSTGRES: The First Experience
**Author**: Pavel Luzanov, Egor Rogov, Igor Levshin (translated by Liudmila Mantrova)
**Language**: English
**Current version at publication**: 15
**Format**: Paperback, eBook
**Published**: April 2023 | | [![PostgreSQL 14 Internals](https://www.postgresql.org/media/img/docs/books/postgres_internals_14.png)](https://postgrespro.com/community/books/internals) | **Title**: PostgreSQL 14 Internals
**Author**: Egor Rogov
**Language**: English
**Current version at publication**: 14
**Format**: Paperback, eBook
**Published**: March 2023 | | [![PostgreSQL - Architecture et notions avancées](https://www.postgresql.org/media/img/docs/books/architecture-et-notions-avancees-4ed.png)](https://www.d-booker.fr/postgresql/187-architecture-et-notions-avancees.html) | **Title**: PostgreSQL - Architecture et notions avancées
**Authors**: Guillaume Lelarge, Julien Rouhaud
**Language**: French
**Current version at publication**: 14
**Format**: Paperback, eBook
**Published**: April 2022 | | [![PostgreSQL 14 Administration Cookbook](https://www.postgresql.org/media/img/docs/books/packt_postgresql14_admin_cookbook.jpg)](https://www.packtpub.com/product/postgresql-14-administration-cookbook/9781803248974) | **Title**: PostgreSQL 14 Administration Cookbook
**Author**: Simon Riggs, Gianni Ciolli
**Language**: English
**Current version at publication**: 14
**Format**: Paperback, eBook
**Published**: March 2022 | | [![Mastering PostgreSQL 13 - Fourth Edition](https://www.postgresql.org/media/img/docs/books/packt_mastering_postgresql_13_4th.jpg)](https://www.packtpub.com/product/mastering-postgresql-13-fourth-edition/9781800567498) | **Title**: Mastering PostgreSQL 13 - Fourth Edition
**Author**: Hans-Jürgen Schönig
**Language**: English
**Current version at publication**: 13
**Format**: Paperback, eBook
**Published**: November 2020 | | [![Learn PostgreSQL](https://www.postgresql.org/media/img/docs/books/learn-postgresql.png)](https://www.packtpub.com/product/learn-postgresql-12/9781838985288) | **Title**: Learn PostgreSQL
**Authors**: Luca Ferrari, Enrico Pirozzi
**Language**: English
**Current version at publication**: 13
**Format**: Paperback, eBook
**Published**: October 2020 | | [![Fundamentos para el trabajo con PostgreSQL](https://www.postgresql.org/media/img/docs/books/fundamentos-postgresql.png)](https://www.amazon.com/dp/B088JZZHSR/ref=sr_1_1?dchild=1&keywords=yudisney&qid=1589400405&sr=8-1) | **Title**: Fundamentos para el trabajo con PostgreSQL
**Author**: Yudisney Vazquez Ortíz, Anthony R. Sotolongo León
**Language**: Spanish
**Current version at publication**: 12
**Format**: Paperback, eBook
**Published**: May 2020 | | [![PostgreSQL for DBA: PostgreSQL 12](https://www.postgresql.org/media/img/docs/books/postgresql-for-dba-12.jpg)](https://www.amazon.com/dp/1796506044) | **Title**: PostgreSQL for DBA: PostgreSQL 12
**Author**: Federico Campoli
**Language**: English
**Current version at publication**: 12
**Format**: Paperback, eBook
**Published**: February 2020 | | [![The Art of PostgreSQL](https://www.postgresql.org/media/img/docs/books/art_of_postgresql.png)](https://theartofpostgresql.com/) | **Title**: The Art of PostgreSQL
**Author**: Dimitri Fontaine
**Language**: English
**Current version at publication**: 11
**Format**: Paperback, eBook
**Published**: August 2019 | | [![PostgreSQL 11 Administration Cookbook](https://www.postgresql.org/media/img/docs/books/postgresql-11-administration-cookbook.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-11-administration-cookbook) | **Title**: PostgreSQL 11 Administration Cookbook
**Author**: Simon Riggs, Gianni Ciolli, Sudheer Kumar Meesala
**Language**: English
**Current version at publication**: 11
**Format**: Paperback, eBook
**Published**: May 2019 | | [![PostgreSQL for DBA volume 1: Structure and Administration](https://www.postgresql.org/media/img/docs/books/postgresql-for-dba-vol-1.jpg)](https://www.amazon.com/dp/1791794122) | **Title**: PostgreSQL for DBA volume 1: Structure and Administration
**Author**: Federico Campoli
**Language**: English
**Current version at publication**: 11
**Format**: Paperback, eBook
**Published**: January 2019 | | [![PostgreSQL 11 Server Side Programming Quick Start Guide](https://www.postgresql.org/media/img/docs/books/packt_postgresql_11_server_side_programming.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-11-server-side-programming-quick-start-guide) | **Title**: PostgreSQL 11 Server Side Programming Quick Start Guide
**Author**: Luca Ferrari
**Language**: English
**Current version at publication**: 11
**Format**: Paperback, eBook
**Published**: November 2018 | | [![Mastering PostgreSQL 11 - Second Edition](https://www.postgresql.org/media/img/docs/books/packt_mastering_postgresql_11_2nd.png)](https://www.packtpub.com/big-data-and-business-intelligence/mastering-postgresql-11-second-edition) | **Title**: Mastering PostgreSQL 11 - Second Edition
**Author**: Hans-Jürgen Schönig
**Language**: English
**Current version at publication**: 11
**Format**: Paperback, eBook
**Published**: October 2018 | | [![PostgreSQL 10 Administration Cookbook](https://www.postgresql.org/media/img/docs/books/packt_postgresql_10_admin_cookbook.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-10-administration-cookbook) | **Title**: PostgreSQL 10 Administration Cookbook
**Author**: Simon Riggs, Gianni Ciolli
**Language**: English
**Current version at publication**: 10
**Format**: Paperback, eBook
**Published**: May 2018 | | [![PostgreSQL 10 High Performance](https://www.postgresql.org/media/img/docs/books/packt_postgresql_10_high_performance.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-10-high-performance) | **Title**: PostgreSQL 10 High Performance
**Author**: Ibrar Ahmed, Gregory Smith, Enrico Pirozzi
**Language**: English
**Current version at publication**: 10
**Format**: Paperback, eBook
**Published**: April 2018 | | [![PostgreSQL for beginners](https://www.postgresql.org/media/img/docs/books/PostgreSQL_for_beginners.png)](https://edu.postgrespro.ru/introbook_v4_en.pdf) | **Title**: PostgreSQL for beginners
**Author**: Pavel Luzanov, Egor Rogov, Igor Levshin (translated by Liudmila Mantrova)
**Language**: English
**Current version at publication**: 10
**Format**: Paperback, eBook
**Published**: March 2018 | | [![PostGIS Cookbook, 2nd Edition](https://www.postgresql.org/media/img/docs/books/packt_postgis_cookbook.png)](https://www.packtpub.com/application-development/postgis-cookbook-second-edition) | **Title**: PostGIS Cookbook, 2nd Edition
**Author**: Mayra Zurbaran et al
**Language**: English
**Current version at publication**: 10
**Format**: Paperback, eBook
**Published**: March 2018 | | [![Mastering PostgreSQL 10](https://www.postgresql.org/media/img/docs/books/packt_mastering_postgresql_10.png)](https://www.packtpub.com/big-data-and-business-intelligence/mastering-postgresql-10) | **Title**: Mastering PostgreSQL 10
**Author**: Hans-Jürgen Schönig
**Language**: English
**Current version at publication**: 10
**Format**: Paperback, eBook
**Published**: January 2018 | | [![A Curious Moon](https://www.postgresql.org/media/img/docs/books/a_curious_moon.jpg)](https://bigmachine.io/products/a-curious-moon) | **Title**: A Curious Moon
**Author**: Rob Conery
**Language**: English
**Current version at publication**: 10
**Format**: eBook
**Published**: December 2017 | | [![PostgreSQL - Architecture et notions avancées](https://www.postgresql.org/media/img/docs/books/architecture-et-notions-avancees.png)](https://www.d-booker.fr/postgresql/187-architecture-et-notions-avancees.html) | **Title**: PostgreSQL - Architecture et notions avancées
**Authors**: Guillaume Lelarge, Julien Rouhaud
**Language**: French
**Current version at publication**: 10
**Format**: Paperback, eBook
**Published**: December 2017 | | [![Mastering PostgreSQL In Application Development](https://www.postgresql.org/media/img/docs/books/dim_mastering_postgresql.png)](https://masteringpostgresql.com/) | **Title**: Mastering PostgreSQL In Application Development
**Author**: Dimitri Fontaine
**Language**: English
**Current version at publication**: 10
**Format**: Paperback, eBook
**Published**: November 2017 | | [![PostgreSQL: Up and Running](https://www.postgresql.org/media/img/docs/books/postgres_up_and_running_3.gif)](https://shop.oreilly.com/product/0636920052715.do) | **Title**: PostgreSQL: Up and Running, 3rd Edition
**Author**: Regina Obe, Leo Hsu
**Language**: English
**Current version at publication**: 10
**Format**: Paperback, eBook
**Published**: October 2017 | | [![PostgreSQL 9.6 High Performance](https://www.postgresql.org/media/img/docs/books/packt_pg96_high_performance.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-high-performance-second-edition) | **Title**: PostgreSQL 9.6 High Performance
**Author**: Ibrar Ahmed, Gregory Smith
**Language**: English
**Current version at publication**: 9.6
**Format**: Paperback, eBook
**Published**: May 2017 | | [![Mastering PostgreSQL 9.6](https://www.postgresql.org/media/img/docs/books/packt_mastering_pg96.png)](https://www.packtpub.com/big-data-and-business-intelligence/mastering-postgresql-96) | **Title**: Mastering PostgreSQL 9.6
**Author**: Hans-Jürgen Schönig
**Language**: English
**Current version at publication**: 9.6
**Format**: Paperback, eBook
**Published**: May 2017 | | [![PostgreSQL Administration Cookbook - 9.5/9.6 Edition](https://www.postgresql.org/media/img/docs/books/packt_postgresql_admin_cookbook_9596edition.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-administration-cookbook-9596-edition) | **Title**: PostgreSQL Administration Cookbook - 9.5/9.6 Edition
**Author**: Simon Riggs, Gianni Ciolli, Gabriele Bartolini
**Language**: English
**Current version at publication**: 9.6
**Format**: Paperback, eBook
**Published**: April 2017 | | [![PostgreSQL High Performance Cookbook](https://www.postgresql.org/media/img/docs/books/packt_postgresql_high_performance_cookbook.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-high-performance-cookbook) | **Title**: PostgreSQL High Performance Cookbook
**Author**: Chitij Chauhan, Dinesh Kumar
**Language**: English
**Current version at publication**: 9.6
**Format**: Paperback, eBook
**Published**: March 2017 | | [![Working with PostgreSQL: configuration and scaling](https://www.postgresql.org/media/img/docs/books/working-with-postgresql.png)](https://postgresql.leopard.in.ua/) | **Title**: Working with PostgreSQL: configuration and scaling
**Author**: Alexey Vasyliev
**Language**: Russian
**Current version at publication**: 9.6
**Format**: eBook
**Published**: March 2017 | | [![PostgreSQL High Availability Cookbook Second Edition](https://www.postgresql.org/media/img/docs/books/packt_ha_cookbook_2ed.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-high-availability-cookbook-second-edition) | **Title**: PostgreSQL High Availability Cookbook Second Edition
**Author**: Shaun M. Thomas
**Language**: English
**Current version at publication**: 9.6
**Format**: Paperback, eBook
**Published**: February 2017 | | [![PL/pgSQL y otros lenguajes procedurales en PostgreSQL](https://www.postgresql.org/media/img/docs/books/plpgsql_y_otros_lenguajes.jpg)](https://www.lulu.com/shop/yudisney-vazquez-ortiz-and-anthony-r-sotolongo-le%C3%B3n/plpgsql-y-otros-lenguajes-procedurales-en-postgresql/ebook/product-1665k4d9.html) | **Title**: PL/pgSQL y otros lenguajes procedurales en PostgreSQL
**Author**: Anthony R. Sotolongo León, Yudisney Vazquez Ortiz
**Language**: Spanish
**Current version at publication**: 9.6
**Format**: eBook
**Published**: June 2019 | | [![PostgreSQL Development Essentials](https://www.postgresql.org/media/img/docs/books/packt_postgresql_development_essentials.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-development-essentials) | **Title**: PostgreSQL Development Essentials
**Author**: Manpreet Kaur, Baji Shaik
**Language**: English
**Current version at publication**: 9.5
**Format**: Paperback, eBook
**Published**: September 2016 | | [![PostgreSQL - Architecture et notions avancées](https://www.postgresql.org/media/img/docs/books/architecture-et-notions-avancees.png)](https://www.d-booker.fr/postgresql/187-architecture-et-notions-avancees.html) | **Title**: PostgreSQL - Architecture et notions avancées
**Author**: Guillaume Lelarge
**Language**: French
**Current version at publication**: 9.4
**Format**: Paperback, eBook
**Published**: December 2015 | | [![Learning PostgreSQL](https://www.postgresql.org/media/img/docs/books/packt_learning_postgresql.png)](https://www.packtpub.com/big-data-and-business-intelligence/learning-postgresql) | **Title**: Learning PostgreSQL
**Author**: Salahaldin Juba, Achim Vannahme, Andrey Volkov
**Language**: English
**Current version at publication**: 9.4
**Format**: Paperback, eBook
**Published**: November 2015 | | [![PostgreSQL Replication - 2nd Edition](https://www.postgresql.org/media/img/docs/books/packt_postgresql_replication_2nd.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-replication-second-edition) | **Title**: PostgreSQL Replication - 2nd Edition
**Author**: Hans-Jürgen Schönig
**Language**: English
**Current version at publication**: 9.4
**Format**: Paperback, eBook
**Published**: July 2015 | | [![PostgreSQL 9 Administration Cookbook - Second Edition](https://www.postgresql.org/media/img/docs/books/packt_postgresql_9_admin_cookbook.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-9-administration-cookbook-second-edition/?utm_source=PoD&utm_medium=referral&utm_campaign=1849519064) | **Title**: PostgreSQL 9 Administration Cookbook - Second Edition
**Author**: Gabriele Bartolini, Gianni Ciolli, Simon Riggs, Hannu Krosing
**Language**: English
**Current version at publication**: 9.4
**Format**: Paperback, eBook
**Published**: April 2015 | | [![PostgreSQL for Data Architects](https://www.postgresql.org/media/img/docs/books/packt_for_data_architects.png)](https://www.packtpub.com/product/postgresql-for-data-architects/9781783288601) | **Title**: PostgreSQL for Data Architects
**Author**: Jayadevan Maymala
**Language**: English
**Current version at publication**: 9.4
**Format**: Paperback, eBook
**Published**: March 2015 | | [![Troubleshooting PostgreSQL](https://www.postgresql.org/media/img/docs/books/packt_troubleshooting_postgresql.png)](https://www.packtpub.com/big-data-and-business-intelligence/troubleshooting-postgresql/?utm_source=PoD&utm_medium=referral&utm_campaign=1783555319) | **Title**: Troubleshooting PostgreSQL
**Author**: Hans-Jürgen Schönig
**Language**: English
**Current version at publication**: 9.4
**Format**: Paperback, eBook
**Published**: March 2015 | | ![PostgreSQL Developer's Guide](https://www.postgresql.org/media/img/docs/books/packt_developers_guide.png) | **Title**: PostgreSQL Developer's Guide
**Author**: Ibrar Ahmed, Asif Fayyaz, Amjad Shahzad
**Language**: English
**Current version at publication**: 9.4
**Format**: Paperback, eBook
**Published**: February 2015 | | [![PostgreSQL Server Programming - Second Edition](https://www.postgresql.org/media/img/docs/books/packt_server_programming.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-server-programming-second-edition/?utm_source=PoD&utm_medium=referral&utm_campaign=1783980583) | **Title**: PostgreSQL Server Programming - Second Edition
**Author**: Usama Dar, Hannu Krosing, Jim Mlodgenski, Kirk Roybal
**Language**: English
**Current version at publication**: 9.4
**Format**: Paperback, eBook
**Published**: February 2015 | | ![PostgreSQL Cookbook](https://www.postgresql.org/media/img/docs/books/packt_postgresql_cookbook.png) | **Title**: PostgreSQL Cookbook
**Author**: Chitij Chauhan
**Language**: English
**Current version at publication**: 9.3
**Format**: Paperback, eBook
**Published**: January 2015 | | [![PostgreSQL Up & Running (2nd Edition)](https://www.postgresql.org/media/img/docs/books/postgres_up_and_running.gif)](https://shop.oreilly.com/product/0636920032144.do) | **Title**: PostgreSQL Up & Running (2nd Edition)
**Author**: Regina Obe, Leo Hsu
**Language**: English
**Current version at publication**: 9.4
**Format**: Paperback, eBook
**Published**: December 2014 | | [![PostgreSQL Administration Essentials](https://www.postgresql.org/media/img/docs/books/packt_administration_essentials.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-administration-essentials/?utm_source=PoD&utm_medium=referral&utm_campaign=1783988983) | **Title**: PostgreSQL Administration Essentials
**Author**: Hans-Jürgen Schönig
**Language**: English
**Current version at publication**: 9.3
**Format**: Paperback, eBook
**Published**: October 2014 | | [![PostgreSQL 9 High Availability Cookbook](https://www.postgresql.org/media/img/docs/books/packt_postgresql_9_ha_cookbook.png)](https://www.packtpub.com/big-data-and-business-intelligence/postgresql-9-high-availability-cookbook/?utm_source=PoD&utm_medium=referral&utm_campaign=1849516960) | **Title**: PostgreSQL 9 High Availability Cookbook
**Author**: Shaun M. Thomas
**Language**: English
**Current version at publication**: 9.3
**Format**: Paperback, eBook
**Published**: July 2014 | | [![Postgres Succinctly](https://www.postgresql.org/media/img/docs/books/postgres-succinctly.png)](https://www.syncfusion.com/resources/techportal/ebooks/postgres) | **Title**: Postgres Succinctly
**Author**: Peter Shaw
**Language**: English
**Current version at publication**: 9.3
**Format**: eBook
**Published**: January 2014 | | [![PostgreSQL Replication](https://www.postgresql.org/media/img/docs/books/pg-replication-packt.jpg)](https://www.packtpub.com/postgresql-replication/book) | **Title**: PostgreSQL Replication
**Author**: Zoltan Böszörmenyi, Hans-Jürgen Schönig
**Language**: English
**Current version at publication**: 9.2
**Format**: Paperback, eBook
**Published**: March 2013 | | [![PostgreSQL Backup and Restore How-to](https://www.postgresql.org/media/img/docs/books/pg-backup-restore-packt.jpg)](https://www.packtpub.com/product/instant-postgresql-backup-and-restore-how-to/9781782169109) | **Title**: PostgreSQL Backup and Restore How-to
**Author**: Shaun M. Thomas
**Language**: English
**Current version at publication**: 9.2
**Format**: eBook
**Published**: March 2013 | | ![Instant PostgreSQL Starter](https://www.postgresql.org/media/img/docs/books/instant-pg-starter-packt.jpg) | **Title**: Instant PostgreSQL Starter
**Author**: Daniel K. Lyons
**Language**: English
**Current version at publication**: 9.2
**Format**: eBook
**Published**: March 2013 | | [![PostgreSQL Server Programming](https://www.postgresql.org/media/img/docs/books/pg-programming-packt.jpg)](https://www.packtpub.com/postgresql-server-programming/book) | **Title**: PostgreSQL Server Programming
**Author**: Hannu Krosing, Kirk Roybal
**Language**: English
**Current version at publication**: 9.2
**Format**: Paperback, eBook
**Published**: January 2013 | | [![PostgreSQL: Up and Running](https://www.postgresql.org/media/img/docs/books/51gStZeVDL._AA160_.jpg)](https://shop.oreilly.com/product/0636920025061.do) | **Title**: PostgreSQL: Up and Running
**Author**: Regina Obe, Leo Hsu
**Language**: English
**Current version at publication**: 9.2
**Format**: Paperback
**Published**: July 2012 | | ![Bases de données PostgreSQL, Gestion des performances](https://www.postgresql.org/media/img/docs/books/pearson_9782744024832.png) | **Title**: Bases de données PostgreSQL, Gestion des performances
**Author**: Gregory Smith
**Language**: French
**Current version at publication**: 9.0
**Format**: Paperback
**Published**: May 2011 | | ![PostgreSQL Reference Manual - Volume 1](https://www.postgresql.org/media/img/docs/books/0954612027.92.jpg) | **Title**: PostgreSQL Reference Manual - Volume 1-3
**Author**: The PostgreSQL Global Development Group
**Language**: English
**Current version at publication**: 9.0
**Format**: Paperback
**Published**: November 2010 _This is the official reference documentation for the PostgreSQL RDBMS, in printed format._ | | [![PostgreSQL 9.0 High Performance](https://www.postgresql.org/media/img/docs/books/0301OS_MockupCover.jpg)](https://2ndquadrant.com/books/postgresql-9-0-high-performance/) | **Title**: PostgreSQL 9.0 High Performance
**Author**: Gregory Smith
**Language**: English
**Current version at publication**: 9.0
**Format**: PDF, Paperback
**Published**: October 2010 | | [![PostgreSQL 9 Administration Cookbook](https://www.postgresql.org/media/img/docs/books/0288OS_MockupCover_Cookbook.jpg)](https://2ndquadrant.com/books/postgresql-9-admin-cookbook/) | **Title**: PostgreSQL 9 Administration Cookbook
**Author**: Simon Riggs, Hannu Krosing
**Language**: English
**Current version at publication**: 9.0
**Format**: PDF, Paperback
**Published**: October 2010 | | ![Utiliser PostgreSQL](https://www.postgresql.org/media/img/docs/books/9782815001984.jpg) | **Title**: Utiliser PostgreSQL
**Author**: Dominique Colombani
**Language**: French
**Current version at publication**: 8.4
**Format**: PDF
**Published**: April 2010 | | ![Installer et débuter avec PostgreSQL](https://www.postgresql.org/media/img/docs/books/9782815001809.png) | **Title**: Installer et débuter avec PostgreSQL
**Author**: Dominique Colombani
**Language**: French
**Current version at publication**: 8.4
**Format**: PDF
**Published**: September 2009 | | [![PostgreSQL. Datenbankpraxis für Anwender, Administratoren und Entwickler (Broschiert)](https://www.postgresql.org/media/img/docs/books/PB_Titel_PostgreSQL_small.png)](https://postgresql-buch.de/) | **Title**: PostgreSQL. Datenbankpraxis für Anwender, Administratoren und Entwickler (Broschiert)
**Author**: Andreas Scherbaum
**Language**: German
**Current version at publication**: 8.4
**Format**: Paperback
**Published**: August 2009 | | ![PostgreSQL](https://www.postgresql.org/media/img/docs/books/51im2FLd-IL._SL500_AA300_.jpg) | **Title**: PostgreSQL
**Author**: François-Marie Colonna
**Language**: French
**Current version at publication**: 8.3
**Format**: Paperback
**Published**: November 2008 | | [![PostgreSQL-Administration](https://www.postgresql.org/media/img/docs/books/21r2crI2nWL._SL500_AA180_.jpg)](https://www.amazon.de/PostgreSQL-Administration-Peter-Eisentraut/dp/3897217775/) | **Title**: PostgreSQL-Administration
**Author**: Peter Eisentraut, Bernd Helmle
**Language**: German
**Current version at publication**: 8.3
**Format**: Hardback
**Published**: October 2008 | | ![PostgreSQL - Administration et exploitation d’une base de données (2ème édition)](https://www.postgresql.org/media/img/docs/books/seblbook_ed2.jpg) | **Title**: PostgreSQL - Administration et exploitation d’une base de données (2ème édition)
**Author**: Sébastien LARDIERE
**Language**: French
**Current version at publication**: 8.2
**Format**: Paperback
**Published**: October 2007 | | [![PostgreSQL 8 For Windows](https://www.postgresql.org/media/img/docs/books/51t2AbIfT4L._SS500_.jpg)](https://www.amazon.com/PostgreSQL-Windows-Database-Professionals-Library/dp/0071485627/) | **Title**: PostgreSQL 8 For Windows
**Author**: Richard Blum
**Language**: English
**Current version at publication**: 8.2
**Format**: Paperback
**Published**: March 2007 | | [![Cover of Beginning PHP and PostgreSQL E-Commerce](https://www.postgresql.org/media/img/docs/books/159059648X.01._AA240_SCLZZZZZZZ_V46693183_.jpg)](https://www.amazon.com/Beginning-PHP-PostgreSQL-E-Commerce-Professional/dp/159059648X/ref=nosim/cristiandarie-20) | **Title**: Beginning PHP and PostgreSQL E-Commerce
**Author**: Cristian Darie, Emilian Balanescu, Mihai Bucica
**Language**: English
**Current version at publication**: 8.1
**Format**: Paperback
**Published**: December 2006 | | [![Cover of PHP and PostgreSQL 8](https://www.postgresql.org/media/img/docs/books/1590595475.01._AA240_SCLZZZZZZZ_.jpg)](https://www.amazon.com/exec/obidos/redirect?link_code=as2&path=ASIN/1590595475&tag=zillablog-20&camp=1789&creative=9325) | **Title**: Beginning PHP & PostgreSQL 8: From Novice to Professionnal
**Author**: W. Jason Gilmore, Robert H. Treat
**Language**: English
**Current version at publication**: 8.1
**Format**: Paperback
**Published**: March 2006 | | [![Cover of PostgreSQL ile Programlama](https://www.postgresql.org/media/img/docs/books/kitap_kapak.jpg)](http://www.students.itu.edu.tr/~yazicivo/doc/postgresql-ile-programlama.html) | **Title**: PostgreSQL ile Programlama
**Author**: Volkan YAZICI
**Language**: Turkish
**Current version at publication**: 8.1
**Format**: Paperback
**Published**: February 2006 | | [![Cover of PostgreSQL, 2nd Edition](https://www.postgresql.org/media/img/docs/books/0735712573.01.LZZZZZZZ.jpg)](https://www.amazon.com/exec/obidos/tg/detail/-/0672327562/qid=1127439720/sr=2-1/ref=pd_bbs_b_2_1/103-1309672-0439005?v=glance&s=books) | **Title**: PostgreSQL, 2nd Edition
**Author**: Korry Douglas, Susan Douglas
**Language**: English
**Current version at publication**: 8.0
**Format**: Paperback
**Published**: July 2005 | | [![Cover of Beginning Databases with PostgreSQL, 2nd Edition](https://www.postgresql.org/media/img/docs/books/1590594789.01.MZZZZZZZ.jpg)](https://www.amazon.com/exec/obidos/tg/detail/-/1590594789/qid=1120009860/sr=1-3/ref=sr_1_3/104-6660226-5122336?v=glance&s=books) | **Title**: Beginning Databases with PostgreSQL, 2nd Edition
**Author**: Neil Matthew, Richard Stone
**Language**: English
**Current version at publication**: 8.0
**Format**: Paperback
**Published**: April 2005 | | [![Cover of PostgreSQL GE-PACKT](https://www.postgresql.org/media/img/docs/books/3826614933.03.MZZZZZZZ.jpg)](https://www.amazon.de/exec/obidos/ASIN/3826614933/qid=1119990657/sr=2-1/ref=sr_2_11_1/028-1975809-0670932) | **Title**: PostgreSQL GE-PACKT
**Author**: Peter Eisentraut
**Language**: German
**Current version at publication**: 8.0
**Format**: Paperback
**Published**: January 2005 | | [![Cover of PostgreSQL, m. CD-ROM](https://www.postgresql.org/media/img/docs/books/3936546223.03.MZZZZZZZ.jpg)](https://www.amazon.de/exec/obidos/ASIN/3936546223/qid=1119990657/sr=2-3/ref=sr_2_11_3/028-1975809-0670932) | **Title**: PostgreSQL, m. CD-ROM
**Author**: Paul Weinstabl
**Language**: German
**Current version at publication**: 7.4
**Format**: Paperback
**Published**: November 2004 | | [![Cover of PostgreSQL: Das offizielle Handbuch](https://www.postgresql.org/media/img/docs/books/3826613376.03.LZZZZZZZ.jpg)](https://www.amazon.de/exec/obidos/ASIN/3826613376/qid=1068391203/sr=2-2/ref=sr_2_11_2/302-2683521-4281640) | **Title**: PostgreSQL: Das offizielle Handbuch
**Author**: Peter Eisentraut
**Language**: German
**Current version at publication**: <7.4
**Format**: Paperback
**Published**: August 2003 [Available online](https://www.postgresql.org/docs/books/pghandbuch.html.de)
(auf Deutsch/in German) | | [![Cover of PostgreSQL. Grundlagen - Praxis - Anwendungsentwicklung mit PHP](https://www.postgresql.org/media/img/docs/books/3898641759.03.MZZZZZZZ.jpg)](https://www.amazon.de/exec/obidos/ASIN/3898641759/postgresql-20) | **Title**: PostgreSQL. Grundlagen - Praxis - Anwendungsentwicklung mit PHP
**Author**: Cornelia Boenigk
**Language**: German
**Current version at publication**: <7.4
**Format**: Paperback
**Published**: September 2002 | | [![Cover of PHP and PostgreSQL Advanced Web Programming](https://www.postgresql.org/media/img/docs/books/0672323826.01._PE30_SCMZZZZZZZ_.jpg)](https://www.amazon.com/exec/obidos/ASIN/0672323826/postgresql-20) | **Title**: PHP and PostgreSQL Advanced Web Programming
**Author**: Ewald Geschwinde, Hans-Jürgen Schönig
**Language**: English
**Current version at publication**: <7.4
**Format**: Paperback
**Published**: June 2002 | | [![Cover of Practical PostgreSQL](https://www.postgresql.org/media/img/docs/books/1565928466.01.TZZZZZZZ.jpg)](https://www.amazon.com/exec/obidos/ASIN/1565928466/postgresql-20) | **Title**: Practical PostgreSQL (O'Reilly Unix)
**Author**: Command Prompt Inc (Editor) et al
**Language**: English
**Current version at publication**: <7.4
**Format**: Paperback
**Published**: January 2002 | | [![Cover of Postgresql Developer's Handbook](https://www.postgresql.org/media/img/docs/books/0672322609.01.TZZZZZZZ.jpg)](https://www.amazon.com/exec/obidos/ASIN/0672322609/postgresql-20) | **Title**: Postgresql Developer's Handbook
**Author**: Ewald Geschwinde et al
**Language**: English
**Current version at publication**: <7.4
**Format**: Paperback
**Published**: December 2001 | | [![Cover of PostgreSQL](https://www.postgresql.org/media/img/docs/books/193184142X.01.TZZZZZZZ.jpg)](https://www.amazon.com/exec/obidos/ASIN/193184142X/postgresql-20) | **Title**: PostgreSQL
**Author**: Jeff Perkins
**Language**: English
**Current version at publication**: <7.4
**Format**: Paperback
**Published**: October 2001 | | [![Cover of PostgreSQL Essential Reference](https://www.postgresql.org/media/img/docs/books/0735711216.01.TZZZZZZZ.jpg)](https://www.amazon.com/exec/obidos/ASIN/0735711216/postgresql-20) | **Title**: PostgreSQL Essential Reference
**Author**: Barry Stinson
**Language**: English
**Current version at publication**: <7.4
**Format**: Paperback
**Published**: October 2001 | | [![Cover of Beginning Databases with PostgreSQL](https://www.postgresql.org/media/img/docs/books/1861005156.01.TZZZZZZZ.jpg)](https://www.amazon.com/exec/obidos/ASIN/1861005156/postgresql-20) | **Title**: Beginning Databases with PostgreSQL
**Author**: Richard Stones, Neil Matthew
**Language**: English
**Current version at publication**: <7.4
**Format**: Paperback
**Published**: September 2001 | | [![Cover of PostgreSQL: Introduction and Concepts](https://www.postgresql.org/media/img/docs/books/0201703319.01.TZZZZZZZ.jpg)](https://www.amazon.com/exec/obidos/ASIN/0201703319/postgresql-20) | **Title**: PostgreSQL: Introduction and Concepts
**Author**: Bruce Momjian
**Language**: English
**Current version at publication**: <7.4
**Format**: Paperback
**Published**: December 2000 | | [![Cover of Postgresql Programmer's Guide](https://www.postgresql.org/media/img/docs/books/0595149170.01.TZZZZZZZ.jpg)](https://www.amazon.com/exec/obidos/ASIN/0595149170/postgresql-20) | **Title**: Postgresql Programmer's Guide
**Author**: Thomas Lockhart (Editor)
**Language**: English
**Current version at publication**: 7.0
**Format**: Paperback
**Published**: December 2000 | --- # PostgreSQL: FAQ November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) Quick Links ----------- * [Documentation](https://www.postgresql.org/docs/) * [Manuals](https://www.postgresql.org/docs/) * [Archive](https://www.postgresql.org/docs/manuals/archive/) * [Release Notes](https://www.postgresql.org/docs/release/) * [Books](https://www.postgresql.org/docs/books/) * [Tutorials & Other Resources](https://www.postgresql.org/docs/online-resources/) * [FAQ](https://www.postgresql.org/docs/faq/) * [Wiki](https://wiki.postgresql.org/) Frequently Asked Questions ========================== Press FAQ --------- For a [high-level overview](https://www.postgresql.org/about/press/faq/) of many questions we receive about PostgreSQL. please review our [press FAQ](https://www.postgresql.org/about/press/faq/) . General FAQ ----------- What platforms support PostgreSQL? How do I know what version of PostgreSQL I'm running? How do you even pronounce _PostgreSQL_? We've received many questions about PostgreSQL through the years and have put together a helpful [FAQ](https://wiki.postgresql.org/wiki/FAQ) page to help you out. You can read our FAQ here: [PostgreSQL FAQ](https://wiki.postgresql.org/wiki/FAQ) PostgreSQL Development FAQ -------------------------- Interested in contributing code to PostgreSQL? Great! We've also put together a [FAQ](https://wiki.postgresql.org/wiki/Developer_FAQ) to help you get started developing code for PostgreSQL! You can read the development code here: [PostgreSQL Development FAQ](https://wiki.postgresql.org/wiki/Developer_FAQ) Other FAQs ---------- There are several more platform-specific and language-specific FAQs available on [our wiki](https://wiki.postgresql.org/wiki/Category:FAQ) . --- # PostgreSQL: Tutorials & Other Resources November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) Quick Links ----------- * [Documentation](https://www.postgresql.org/docs/) * [Manuals](https://www.postgresql.org/docs/) * [Archive](https://www.postgresql.org/docs/manuals/archive/) * [Release Notes](https://www.postgresql.org/docs/release/) * [Books](https://www.postgresql.org/docs/books/) * [Tutorials & Other Resources](https://www.postgresql.org/docs/online-resources/) * [FAQ](https://www.postgresql.org/docs/faq/) * [Wiki](https://wiki.postgresql.org/) Tutorials & Other Resources =========================== | Website URL | Description | | --- | --- | | [pgPedia](https://pgpedia.info/) | A detailed encyclopedia of PostgreSQL-related topics, including howtos, feature information, and release history. | | [PostgreSQL Tutorial](https://www.postgresqltutorial.com/) | Learn PostgreSQL and how to get started quickly through practical examples. | | [Tutorials Point PostgreSQL](https://www.tutorialspoint.com/postgresql/) | A full, free online course for walking through PostgreSQL, from the basics to advanced administration. | | [PG Exercises](https://pgexercises.com/) | Free online exercises for learning PostgreSQL in an interactive manner. | | [PostgreSQL Primer for Busy People](https://zaiste.net/posts/postgresql-primer-for-busy-people/) | A handy single-paged resource and reference guide for getting started with PostgreSQL. | | [Awesome Postgres](https://github.com/dhamaniasad/awesome-postgres) | A curated list of awesome PostgreSQL software, libraries, tools and resources. | --- # PostgreSQL: Documentation: 18: 52.65. pg_user_mapping November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-user-mapping.html "PostgreSQL 18 - 52.65. pg_user_mapping") ([18](https://www.postgresql.org/docs/18/catalog-pg-user-mapping.html "PostgreSQL 18 - 52.65. pg_user_mapping") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-user-mapping.html "PostgreSQL 17 - 52.65. pg_user_mapping") / [16](https://www.postgresql.org/docs/16/catalog-pg-user-mapping.html "PostgreSQL 16 - 52.65. pg_user_mapping") / [15](https://www.postgresql.org/docs/15/catalog-pg-user-mapping.html "PostgreSQL 15 - 52.65. pg_user_mapping") / [14](https://www.postgresql.org/docs/14/catalog-pg-user-mapping.html "PostgreSQL 14 - 52.65. pg_user_mapping") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-user-mapping.html "PostgreSQL devel - 52.65. pg_user_mapping") Unsupported versions: [13](https://www.postgresql.org/docs/13/catalog-pg-user-mapping.html "PostgreSQL 13 - 52.65. pg_user_mapping") / [12](https://www.postgresql.org/docs/12/catalog-pg-user-mapping.html "PostgreSQL 12 - 52.65. pg_user_mapping") / [11](https://www.postgresql.org/docs/11/catalog-pg-user-mapping.html "PostgreSQL 11 - 52.65. pg_user_mapping") / [10](https://www.postgresql.org/docs/10/catalog-pg-user-mapping.html "PostgreSQL 10 - 52.65. pg_user_mapping") / [9.6](https://www.postgresql.org/docs/9.6/catalog-pg-user-mapping.html "PostgreSQL 9.6 - 52.65. pg_user_mapping") / [9.5](https://www.postgresql.org/docs/9.5/catalog-pg-user-mapping.html "PostgreSQL 9.5 - 52.65. pg_user_mapping") / [9.4](https://www.postgresql.org/docs/9.4/catalog-pg-user-mapping.html "PostgreSQL 9.4 - 52.65. pg_user_mapping") / [9.3](https://www.postgresql.org/docs/9.3/catalog-pg-user-mapping.html "PostgreSQL 9.3 - 52.65. pg_user_mapping") / [9.2](https://www.postgresql.org/docs/9.2/catalog-pg-user-mapping.html "PostgreSQL 9.2 - 52.65. pg_user_mapping") / [9.1](https://www.postgresql.org/docs/9.1/catalog-pg-user-mapping.html "PostgreSQL 9.1 - 52.65. pg_user_mapping") / [9.0](https://www.postgresql.org/docs/9.0/catalog-pg-user-mapping.html "PostgreSQL 9.0 - 52.65. pg_user_mapping") / [8.4](https://www.postgresql.org/docs/8.4/catalog-pg-user-mapping.html "PostgreSQL 8.4 - 52.65. pg_user_mapping") | 52.65. `pg_user_mapping` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/catalog-pg-type.html "52.64. pg_type") | [Up](https://www.postgresql.org/docs/18/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | * * * 52.65. `pg_user_mapping` [#](https://www.postgresql.org/docs/18/catalog-pg-user-mapping.html#CATALOG-PG-USER-MAPPING) ---------------------------------------------------------------------------------------------------------------------- The catalog `pg_user_mapping` stores the mappings from local user to remote. Access to this catalog is restricted from normal users, use the view [`pg_user_mappings`](https://www.postgresql.org/docs/18/view-pg-user-mappings.html "53.36. pg_user_mappings") instead. **Table 52.66. `pg_user_mapping` Columns** | Column Type

Description | | --- | | `oid` `oid`

Row identifier | | `umuser` `oid` (references [`pg_authid`](https://www.postgresql.org/docs/18/catalog-pg-authid.html "52.8. pg_authid")
.`oid`)

OID of the local role being mapped, or zero if the user mapping is public | | `umserver` `oid` (references [`pg_foreign_server`](https://www.postgresql.org/docs/18/catalog-pg-foreign-server.html "52.24. pg_foreign_server")
.`oid`)

The OID of the foreign server that contains this mapping | | `umoptions` `text[]`

User mapping specific options, as “keyword=value” strings | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/catalog-pg-type.html "52.64. pg_type") | [Up](https://www.postgresql.org/docs/18/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | | 52.64. `pg_type` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | Chapter 53. System Views | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/catalog-pg-user-mapping.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 52.65. pg_user_mapping November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-user-mapping.html "PostgreSQL 18 - 52.65. pg_user_mapping") ([18](https://www.postgresql.org/docs/18/catalog-pg-user-mapping.html "PostgreSQL 18 - 52.65. pg_user_mapping") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-user-mapping.html "PostgreSQL 17 - 52.65. pg_user_mapping") / [16](https://www.postgresql.org/docs/16/catalog-pg-user-mapping.html "PostgreSQL 16 - 52.65. pg_user_mapping") / [15](https://www.postgresql.org/docs/15/catalog-pg-user-mapping.html "PostgreSQL 15 - 52.65. pg_user_mapping") / [14](https://www.postgresql.org/docs/14/catalog-pg-user-mapping.html "PostgreSQL 14 - 52.65. pg_user_mapping") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-user-mapping.html "PostgreSQL devel - 52.65. pg_user_mapping") Unsupported versions: [13](https://www.postgresql.org/docs/13/catalog-pg-user-mapping.html "PostgreSQL 13 - 52.65. pg_user_mapping") / [12](https://www.postgresql.org/docs/12/catalog-pg-user-mapping.html "PostgreSQL 12 - 52.65. pg_user_mapping") / [11](https://www.postgresql.org/docs/11/catalog-pg-user-mapping.html "PostgreSQL 11 - 52.65. pg_user_mapping") / [10](https://www.postgresql.org/docs/10/catalog-pg-user-mapping.html "PostgreSQL 10 - 52.65. pg_user_mapping") / [9.6](https://www.postgresql.org/docs/9.6/catalog-pg-user-mapping.html "PostgreSQL 9.6 - 52.65. pg_user_mapping") / [9.5](https://www.postgresql.org/docs/9.5/catalog-pg-user-mapping.html "PostgreSQL 9.5 - 52.65. pg_user_mapping") / [9.4](https://www.postgresql.org/docs/9.4/catalog-pg-user-mapping.html "PostgreSQL 9.4 - 52.65. pg_user_mapping") / [9.3](https://www.postgresql.org/docs/9.3/catalog-pg-user-mapping.html "PostgreSQL 9.3 - 52.65. pg_user_mapping") / [9.2](https://www.postgresql.org/docs/9.2/catalog-pg-user-mapping.html "PostgreSQL 9.2 - 52.65. pg_user_mapping") / [9.1](https://www.postgresql.org/docs/9.1/catalog-pg-user-mapping.html "PostgreSQL 9.1 - 52.65. pg_user_mapping") / [9.0](https://www.postgresql.org/docs/9.0/catalog-pg-user-mapping.html "PostgreSQL 9.0 - 52.65. pg_user_mapping") / [8.4](https://www.postgresql.org/docs/8.4/catalog-pg-user-mapping.html "PostgreSQL 8.4 - 52.65. pg_user_mapping") | 52.65. `pg_user_mapping` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-type.html "52.64. pg_type") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | * * * 52.65. `pg_user_mapping` [#](https://www.postgresql.org/docs/current/catalog-pg-user-mapping.html#CATALOG-PG-USER-MAPPING) --------------------------------------------------------------------------------------------------------------------------- The catalog `pg_user_mapping` stores the mappings from local user to remote. Access to this catalog is restricted from normal users, use the view [`pg_user_mappings`](https://www.postgresql.org/docs/current/view-pg-user-mappings.html "53.36. pg_user_mappings") instead. **Table 52.66. `pg_user_mapping` Columns** | Column Type

Description | | --- | | `oid` `oid`

Row identifier | | `umuser` `oid` (references [`pg_authid`](https://www.postgresql.org/docs/current/catalog-pg-authid.html "52.8. pg_authid")
.`oid`)

OID of the local role being mapped, or zero if the user mapping is public | | `umserver` `oid` (references [`pg_foreign_server`](https://www.postgresql.org/docs/current/catalog-pg-foreign-server.html "52.24. pg_foreign_server")
.`oid`)

The OID of the foreign server that contains this mapping | | `umoptions` `text[]`

User mapping specific options, as “keyword=value” strings | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-type.html "52.64. pg_type") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | | 52.64. `pg_type` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Chapter 53. System Views | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/catalog-pg-user-mapping.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.5. basic_archive — an example WAL archive module November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/basic-archive.html "PostgreSQL 18 - F.5. basic_archive — an example WAL archive module") ([18](https://www.postgresql.org/docs/18/basic-archive.html "PostgreSQL 18 - F.5. basic_archive — an example WAL archive module") ) / [17](https://www.postgresql.org/docs/17/basic-archive.html "PostgreSQL 17 - F.5. basic_archive — an example WAL archive module") / [16](https://www.postgresql.org/docs/16/basic-archive.html "PostgreSQL 16 - F.5. basic_archive — an example WAL archive module") / [15](https://www.postgresql.org/docs/15/basic-archive.html "PostgreSQL 15 - F.5. basic_archive — an example WAL archive module") Development Versions: [devel](https://www.postgresql.org/docs/devel/basic-archive.html "PostgreSQL devel - F.5. basic_archive — an example WAL archive module") | F.5. basic\_archive — an example WAL archive module | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/basebackup-to-shell.html "F.4. basebackup_to_shell — example "shell" pg_basebackup module") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/bloom.html "F.6. bloom — bloom filter index access method") | * * * F.5. basic\_archive — an example WAL archive module [#](https://www.postgresql.org/docs/18/basic-archive.html#BASIC-ARCHIVE) ----------------------------------------------------------------------------------------------------------------------------- [F.5.1. Configuration Parameters](https://www.postgresql.org/docs/18/basic-archive.html#BASIC-ARCHIVE-CONFIGURATION-PARAMETERS) [F.5.2. Notes](https://www.postgresql.org/docs/18/basic-archive.html#BASIC-ARCHIVE-NOTES) [F.5.3. Author](https://www.postgresql.org/docs/18/basic-archive.html#BASIC-ARCHIVE-AUTHOR) `basic_archive` is an example of an archive module. This module copies completed WAL segment files to the specified directory. This may not be especially useful, but it can serve as a starting point for developing your own archive module. For more information about archive modules, see [Chapter 49](https://www.postgresql.org/docs/18/archive-modules.html "Chapter 49. Archive Modules") . In order to function, this module must be loaded via [archive\_library](https://www.postgresql.org/docs/18/runtime-config-wal.html#GUC-ARCHIVE-LIBRARY) , and [archive\_mode](https://www.postgresql.org/docs/18/runtime-config-wal.html#GUC-ARCHIVE-MODE) must be enabled. ### F.5.1. Configuration Parameters [#](https://www.postgresql.org/docs/18/basic-archive.html#BASIC-ARCHIVE-CONFIGURATION-PARAMETERS) `basic_archive.archive_directory` (`string`) The directory where the server should copy WAL segment files. This directory must already exist. The default is an empty string, which effectively halts WAL archiving, but if [archive\_mode](https://www.postgresql.org/docs/18/runtime-config-wal.html#GUC-ARCHIVE-MODE) is enabled, the server will accumulate WAL segment files in the expectation that a value will soon be provided. These parameters must be set in `postgresql.conf`. Typical usage might be: \# postgresql.conf archive\_mode = 'on' archive\_library = 'basic\_archive' basic\_archive.archive\_directory = '/path/to/archive/directory' ### F.5.2. Notes [#](https://www.postgresql.org/docs/18/basic-archive.html#BASIC-ARCHIVE-NOTES) Server crashes may leave temporary files with the prefix `archtemp` in the archive directory. It is recommended to delete such files before restarting the server after a crash. It is safe to remove such files while the server is running as long as they are unrelated to any archiving still in progress, but users should use extra caution when doing so. ### F.5.3. Author [#](https://www.postgresql.org/docs/18/basic-archive.html#BASIC-ARCHIVE-AUTHOR) Nathan Bossart * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/basebackup-to-shell.html "F.4. basebackup_to_shell — example "shell" pg_basebackup module") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/18/bloom.html "F.6. bloom — bloom filter index access method") | | F.4. basebackup\_to\_shell — example "shell" pg\_basebackup module | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | F.6. bloom — bloom filter index access method | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/basic-archive.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 55.3. Error Message Style Guide November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/error-style-guide.html "PostgreSQL 18 - 55.3. Error Message Style Guide") ([18](https://www.postgresql.org/docs/18/error-style-guide.html "PostgreSQL 18 - 55.3. Error Message Style Guide") ) / [17](https://www.postgresql.org/docs/17/error-style-guide.html "PostgreSQL 17 - 55.3. Error Message Style Guide") / [16](https://www.postgresql.org/docs/16/error-style-guide.html "PostgreSQL 16 - 55.3. Error Message Style Guide") / [15](https://www.postgresql.org/docs/15/error-style-guide.html "PostgreSQL 15 - 55.3. Error Message Style Guide") / [14](https://www.postgresql.org/docs/14/error-style-guide.html "PostgreSQL 14 - 55.3. Error Message Style Guide") Development Versions: [devel](https://www.postgresql.org/docs/devel/error-style-guide.html "PostgreSQL devel - 55.3. Error Message Style Guide") Unsupported versions: [13](https://www.postgresql.org/docs/13/error-style-guide.html "PostgreSQL 13 - 55.3. Error Message Style Guide") / [12](https://www.postgresql.org/docs/12/error-style-guide.html "PostgreSQL 12 - 55.3. Error Message Style Guide") / [11](https://www.postgresql.org/docs/11/error-style-guide.html "PostgreSQL 11 - 55.3. Error Message Style Guide") / [10](https://www.postgresql.org/docs/10/error-style-guide.html "PostgreSQL 10 - 55.3. Error Message Style Guide") / [9.6](https://www.postgresql.org/docs/9.6/error-style-guide.html "PostgreSQL 9.6 - 55.3. Error Message Style Guide") / [9.5](https://www.postgresql.org/docs/9.5/error-style-guide.html "PostgreSQL 9.5 - 55.3. Error Message Style Guide") / [9.4](https://www.postgresql.org/docs/9.4/error-style-guide.html "PostgreSQL 9.4 - 55.3. Error Message Style Guide") / [9.3](https://www.postgresql.org/docs/9.3/error-style-guide.html "PostgreSQL 9.3 - 55.3. Error Message Style Guide") / [9.2](https://www.postgresql.org/docs/9.2/error-style-guide.html "PostgreSQL 9.2 - 55.3. Error Message Style Guide") / [9.1](https://www.postgresql.org/docs/9.1/error-style-guide.html "PostgreSQL 9.1 - 55.3. Error Message Style Guide") / [9.0](https://www.postgresql.org/docs/9.0/error-style-guide.html "PostgreSQL 9.0 - 55.3. Error Message Style Guide") / [8.4](https://www.postgresql.org/docs/8.4/error-style-guide.html "PostgreSQL 8.4 - 55.3. Error Message Style Guide") / [8.3](https://www.postgresql.org/docs/8.3/error-style-guide.html "PostgreSQL 8.3 - 55.3. Error Message Style Guide") / [8.2](https://www.postgresql.org/docs/8.2/error-style-guide.html "PostgreSQL 8.2 - 55.3. Error Message Style Guide") / [8.1](https://www.postgresql.org/docs/8.1/error-style-guide.html "PostgreSQL 8.1 - 55.3. Error Message Style Guide") / [8.0](https://www.postgresql.org/docs/8.0/error-style-guide.html "PostgreSQL 8.0 - 55.3. Error Message Style Guide") / [7.4](https://www.postgresql.org/docs/7.4/error-style-guide.html "PostgreSQL 7.4 - 55.3. Error Message Style Guide") | 55.3. Error Message Style Guide | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/error-message-reporting.html "55.2. Reporting Errors Within the Server") | [Up](https://www.postgresql.org/docs/18/source.html "Chapter 55. PostgreSQL Coding Conventions") | Chapter 55. PostgreSQL Coding Conventions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/source-conventions.html "55.4. Miscellaneous Coding Conventions") | * * * 55.3. Error Message Style Guide [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE) ----------------------------------------------------------------------------------------------------------------- This style guide is offered in the hope of maintaining a consistent, user-friendly style throughout all the messages generated by PostgreSQL. ### What Goes Where [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-WHAT-GOES-WHERE) The primary message should be short, factual, and avoid reference to implementation details such as specific function names. “Short” means “should fit on one line under normal conditions”. Use a detail message if needed to keep the primary message short, or if you feel a need to mention implementation details such as the particular system call that failed. Both primary and detail messages should be factual. Use a hint message for suggestions about what to do to fix the problem, especially if the suggestion might not always be applicable. For example, instead of: IpcMemoryCreate: shmget(key=%d, size=%u, 0%o) failed: %m (plus a long addendum that is basically a hint) write: Primary: could not create shared memory segment: %m Detail: Failed syscall was shmget(key=%d, size=%u, 0%o). Hint: The addendum, written as a complete sentence. Rationale: keeping the primary message short helps keep it to the point, and lets clients lay out screen space on the assumption that one line is enough for error messages. Detail and hint messages can be relegated to a verbose mode, or perhaps a pop-up error-details window. Also, details and hints would normally be suppressed from the server log to save space. Reference to implementation details is best avoided since users aren't expected to know the details. ### Formatting [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-FORMATTING) Don't put any specific assumptions about formatting into the message texts. Expect clients and the server log to wrap lines to fit their own needs. In long messages, newline characters (\\n) can be used to indicate suggested paragraph breaks. Don't end a message with a newline. Don't use tabs or other formatting characters. (In error context displays, newlines are automatically added to separate levels of context such as function calls.) Rationale: Messages are not necessarily displayed on terminal-type displays. In GUI displays or browsers these formatting instructions are at best ignored. ### Quotation Marks [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-QUOTATION-MARKS) English text should use double quotes when quoting is appropriate. Text in other languages should consistently use one kind of quotes that is consistent with publishing customs and computer output of other programs. Rationale: The choice of double quotes over single quotes is somewhat arbitrary, but tends to be the preferred use. Some have suggested choosing the kind of quotes depending on the type of object according to SQL conventions (namely, strings single quoted, identifiers double quoted). But this is a language-internal technical issue that many users aren't even familiar with, it won't scale to other kinds of quoted terms, it doesn't translate to other languages, and it's pretty pointless, too. ### Use of Quotes [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-QUOTES) Always use quotes to delimit file names, user-supplied identifiers, configuration variable names, and other variables that might contain words. Do not use them to mark up variables that will not contain words (for example, operator names). There are functions in the backend that will double-quote their own output as needed (for example, `format_type_be()`). Do not put additional quotes around the output of such functions. Rationale: Objects can have names that create ambiguity when embedded in a message. Be consistent about denoting where a plugged-in name starts and ends. But don't clutter messages with unnecessary or duplicate quote marks. ### Grammar and Punctuation [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-GRAMMAR-PUNCTUATION) The rules are different for primary error messages and for detail/hint messages: Primary error messages: Do not capitalize the first letter. Do not end a message with a period. Do not even think about ending a message with an exclamation point. Detail and hint messages: Use complete sentences, and end each with a period. Capitalize the first word of sentences. Put two spaces after the period if another sentence follows (for English text; might be inappropriate in other languages). Error context strings: Do not capitalize the first letter and do not end the string with a period. Context strings should normally not be complete sentences. Rationale: Avoiding punctuation makes it easier for client applications to embed the message into a variety of grammatical contexts. Often, primary messages are not grammatically complete sentences anyway. (And if they're long enough to be more than one sentence, they should be split into primary and detail parts.) However, detail and hint messages are longer and might need to include multiple sentences. For consistency, they should follow complete-sentence style even when there's only one sentence. ### Upper Case vs. Lower Case [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-CASE) Use lower case for message wording, including the first letter of a primary error message. Use upper case for SQL commands and key words if they appear in the message. Rationale: It's easier to make everything look more consistent this way, since some messages are complete sentences and some not. ### Avoid Passive Voice [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-PASSIVE-VOICE) Use the active voice. Use complete sentences when there is an acting subject (“A could not do B”). Use telegram style without subject if the subject would be the program itself; do not use “I” for the program. Rationale: The program is not human. Don't pretend otherwise. ### Present vs. Past Tense [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-TENSE) Use past tense if an attempt to do something failed, but could perhaps succeed next time (perhaps after fixing some problem). Use present tense if the failure is certainly permanent. There is a nontrivial semantic difference between sentences of the form: could not open file "%s": %m and: cannot open file "%s" The first one means that the attempt to open the file failed. The message should give a reason, such as “disk full” or “file doesn't exist”. The past tense is appropriate because next time the disk might not be full anymore or the file in question might exist. The second form indicates that the functionality of opening the named file does not exist at all in the program, or that it's conceptually impossible. The present tense is appropriate because the condition will persist indefinitely. Rationale: Granted, the average user will not be able to draw great conclusions merely from the tense of the message, but since the language provides us with a grammar we should use it correctly. ### Type of the Object [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-OBJECT-TYPE) When citing the name of an object, state what kind of object it is. Rationale: Otherwise no one will know what “foo.bar.baz” refers to. ### Brackets [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-BRACKETS) Square brackets are only to be used (1) in command synopses to denote optional arguments, or (2) to denote an array subscript. Rationale: Anything else does not correspond to widely-known customary usage and will confuse people. ### Assembling Error Messages [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-ERROR-MESSAGES) When a message includes text that is generated elsewhere, embed it in this style: could not open file %s: %m Rationale: It would be difficult to account for all possible error codes to paste this into a single smooth sentence, so some sort of punctuation is needed. Putting the embedded text in parentheses has also been suggested, but it's unnatural if the embedded text is likely to be the most important part of the message, as is often the case. ### Reasons for Errors [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-ERROR-REASONS) Messages should always state the reason why an error occurred. For example: BAD: could not open file %s BETTER: could not open file %s (I/O failure) If no reason is known you better fix the code. ### Function Names [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-FUNCTION-NAMES) Don't include the name of the reporting routine in the error text. We have other mechanisms for finding that out when needed, and for most users it's not helpful information. If the error text doesn't make as much sense without the function name, reword it. BAD: pg\_strtoint32: error in "z": cannot parse "z" BETTER: invalid input syntax for type integer: "z" Avoid mentioning called function names, either; instead say what the code was trying to do: BAD: open() failed: %m BETTER: could not open file %s: %m If it really seems necessary, mention the system call in the detail message. (In some cases, providing the actual values passed to the system call might be appropriate information for the detail message.) Rationale: Users don't know what all those functions do. ### Tricky Words to Avoid [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-TRICKY-WORDS) **Unable.**  “Unable” is nearly the passive voice. Better use “cannot” or “could not”, as appropriate. **Bad.**  Error messages like “bad result” are really hard to interpret intelligently. It's better to write why the result is “bad”, e.g., “invalid format”. **Illegal.**  “Illegal” stands for a violation of the law, the rest is “invalid”. Better yet, say why it's invalid. **Unknown.**  Try to avoid “unknown”. Consider “error: unknown response”. If you don't know what the response is, how do you know it's erroneous? “Unrecognized” is often a better choice. Also, be sure to include the value being complained of. BAD: unknown node type BETTER: unrecognized node type: 42 **Find vs. Exists.**  If the program uses a nontrivial algorithm to locate a resource (e.g., a path search) and that algorithm fails, it is fair to say that the program couldn't “find” the resource. If, on the other hand, the expected location of the resource is known but the program cannot access it there then say that the resource doesn't “exist”. Using “find” in this case sounds weak and confuses the issue. **May vs. Can vs. Might.**  “May” suggests permission (e.g., "You may borrow my rake."), and has little use in documentation or error messages. “Can” suggests ability (e.g., "I can lift that log."), and “might” suggests possibility (e.g., "It might rain today."). Using the proper word clarifies meaning and assists translation. **Contractions.**  Avoid contractions, like “can't”; use “cannot” instead. **Non-negative.**  Avoid “non-negative” as it is ambiguous about whether it accepts zero. It's better to use “greater than zero” or “greater than or equal to zero”. ### Proper Spelling [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-SPELLING) Spell out words in full. For instance, avoid: * spec * stats * parens * auth * xact Rationale: This will improve consistency. ### Localization [#](https://www.postgresql.org/docs/18/error-style-guide.html#ERROR-STYLE-GUIDE-LOCALIZATION) Keep in mind that error message texts need to be translated into other languages. Follow the guidelines in [Section 56.2.2](https://www.postgresql.org/docs/18/nls-programmer.html#NLS-GUIDELINES "56.2.2. Message-Writing Guidelines") to avoid making life difficult for translators. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/error-message-reporting.html "55.2. Reporting Errors Within the Server") | [Up](https://www.postgresql.org/docs/18/source.html "Chapter 55. PostgreSQL Coding Conventions") | [Next](https://www.postgresql.org/docs/18/source-conventions.html "55.4. Miscellaneous Coding Conventions") | | 55.2. Reporting Errors Within the Server | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 55.4. Miscellaneous Coding Conventions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/error-style-guide.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.5. basic_archive — an example WAL archive module November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/basic-archive.html "PostgreSQL 18 - F.5. basic_archive — an example WAL archive module") ([18](https://www.postgresql.org/docs/18/basic-archive.html "PostgreSQL 18 - F.5. basic_archive — an example WAL archive module") ) / [17](https://www.postgresql.org/docs/17/basic-archive.html "PostgreSQL 17 - F.5. basic_archive — an example WAL archive module") / [16](https://www.postgresql.org/docs/16/basic-archive.html "PostgreSQL 16 - F.5. basic_archive — an example WAL archive module") / [15](https://www.postgresql.org/docs/15/basic-archive.html "PostgreSQL 15 - F.5. basic_archive — an example WAL archive module") Development Versions: [devel](https://www.postgresql.org/docs/devel/basic-archive.html "PostgreSQL devel - F.5. basic_archive — an example WAL archive module") | F.5. basic\_archive — an example WAL archive module | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/basebackup-to-shell.html "F.4. basebackup_to_shell — example "shell" pg_basebackup module") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/bloom.html "F.6. bloom — bloom filter index access method") | * * * F.5. basic\_archive — an example WAL archive module [#](https://www.postgresql.org/docs/current/basic-archive.html#BASIC-ARCHIVE) ---------------------------------------------------------------------------------------------------------------------------------- [F.5.1. Configuration Parameters](https://www.postgresql.org/docs/current/basic-archive.html#BASIC-ARCHIVE-CONFIGURATION-PARAMETERS) [F.5.2. Notes](https://www.postgresql.org/docs/current/basic-archive.html#BASIC-ARCHIVE-NOTES) [F.5.3. Author](https://www.postgresql.org/docs/current/basic-archive.html#BASIC-ARCHIVE-AUTHOR) `basic_archive` is an example of an archive module. This module copies completed WAL segment files to the specified directory. This may not be especially useful, but it can serve as a starting point for developing your own archive module. For more information about archive modules, see [Chapter 49](https://www.postgresql.org/docs/current/archive-modules.html "Chapter 49. Archive Modules") . In order to function, this module must be loaded via [archive\_library](https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-ARCHIVE-LIBRARY) , and [archive\_mode](https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-ARCHIVE-MODE) must be enabled. ### F.5.1. Configuration Parameters [#](https://www.postgresql.org/docs/current/basic-archive.html#BASIC-ARCHIVE-CONFIGURATION-PARAMETERS) `basic_archive.archive_directory` (`string`) The directory where the server should copy WAL segment files. This directory must already exist. The default is an empty string, which effectively halts WAL archiving, but if [archive\_mode](https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-ARCHIVE-MODE) is enabled, the server will accumulate WAL segment files in the expectation that a value will soon be provided. These parameters must be set in `postgresql.conf`. Typical usage might be: \# postgresql.conf archive\_mode = 'on' archive\_library = 'basic\_archive' basic\_archive.archive\_directory = '/path/to/archive/directory' ### F.5.2. Notes [#](https://www.postgresql.org/docs/current/basic-archive.html#BASIC-ARCHIVE-NOTES) Server crashes may leave temporary files with the prefix `archtemp` in the archive directory. It is recommended to delete such files before restarting the server after a crash. It is safe to remove such files while the server is running as long as they are unrelated to any archiving still in progress, but users should use extra caution when doing so. ### F.5.3. Author [#](https://www.postgresql.org/docs/current/basic-archive.html#BASIC-ARCHIVE-AUTHOR) Nathan Bossart * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/basebackup-to-shell.html "F.4. basebackup_to_shell — example "shell" pg_basebackup module") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/current/bloom.html "F.6. bloom — bloom filter index access method") | | F.4. basebackup\_to\_shell — example "shell" pg\_basebackup module | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | F.6. bloom — bloom filter index access method | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/basic-archive.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 43.7. PL/Perl Event Triggers November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plperl-event-triggers.html "PostgreSQL 18 - 43.7. PL/Perl Event Triggers") ([18](https://www.postgresql.org/docs/18/plperl-event-triggers.html "PostgreSQL 18 - 43.7. PL/Perl Event Triggers") ) / [17](https://www.postgresql.org/docs/17/plperl-event-triggers.html "PostgreSQL 17 - 43.7. PL/Perl Event Triggers") / [16](https://www.postgresql.org/docs/16/plperl-event-triggers.html "PostgreSQL 16 - 43.7. PL/Perl Event Triggers") / [15](https://www.postgresql.org/docs/15/plperl-event-triggers.html "PostgreSQL 15 - 43.7. PL/Perl Event Triggers") / [14](https://www.postgresql.org/docs/14/plperl-event-triggers.html "PostgreSQL 14 - 43.7. PL/Perl Event Triggers") Development Versions: [devel](https://www.postgresql.org/docs/devel/plperl-event-triggers.html "PostgreSQL devel - 43.7. PL/Perl Event Triggers") Unsupported versions: [13](https://www.postgresql.org/docs/13/plperl-event-triggers.html "PostgreSQL 13 - 43.7. PL/Perl Event Triggers") / [12](https://www.postgresql.org/docs/12/plperl-event-triggers.html "PostgreSQL 12 - 43.7. PL/Perl Event Triggers") / [11](https://www.postgresql.org/docs/11/plperl-event-triggers.html "PostgreSQL 11 - 43.7. PL/Perl Event Triggers") / [10](https://www.postgresql.org/docs/10/plperl-event-triggers.html "PostgreSQL 10 - 43.7. PL/Perl Event Triggers") / [9.6](https://www.postgresql.org/docs/9.6/plperl-event-triggers.html "PostgreSQL 9.6 - 43.7. PL/Perl Event Triggers") / [9.5](https://www.postgresql.org/docs/9.5/plperl-event-triggers.html "PostgreSQL 9.5 - 43.7. PL/Perl Event Triggers") / [9.4](https://www.postgresql.org/docs/9.4/plperl-event-triggers.html "PostgreSQL 9.4 - 43.7. PL/Perl Event Triggers") | 43.7. PL/Perl Event Triggers | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/plperl-triggers.html "43.6. PL/Perl Triggers") | [Up](https://www.postgresql.org/docs/current/plperl.html "Chapter 43. PL/Perl — Perl Procedural Language") | Chapter 43. PL/Perl — Perl Procedural Language | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/plperl-under-the-hood.html "43.8. PL/Perl Under the Hood") | * * * 43.7. PL/Perl Event Triggers [#](https://www.postgresql.org/docs/current/plperl-event-triggers.html#PLPERL-EVENT-TRIGGERS) --------------------------------------------------------------------------------------------------------------------------- PL/Perl can be used to write event trigger functions. In an event trigger function, the hash reference `$_TD` contains information about the current trigger event. `$_TD` is a global variable, which gets a separate local value for each invocation of the trigger. The fields of the `$_TD` hash reference are: `$_TD->{event}` The name of the event the trigger is fired for. `$_TD->{tag}` The command tag for which the trigger is fired. The return value of the trigger function is ignored. Here is an example of an event trigger function, illustrating some of the above: CREATE OR REPLACE FUNCTION perlsnitch() RETURNS event\_trigger AS $$ elog(NOTICE, "perlsnitch: " . $\_TD->{event} . " " . $\_TD->{tag} . " "); $$ LANGUAGE plperl; CREATE EVENT TRIGGER perl\_a\_snitch ON ddl\_command\_start EXECUTE FUNCTION perlsnitch(); * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/plperl-triggers.html "43.6. PL/Perl Triggers") | [Up](https://www.postgresql.org/docs/current/plperl.html "Chapter 43. PL/Perl — Perl Procedural Language") | [Next](https://www.postgresql.org/docs/current/plperl-under-the-hood.html "43.8. PL/Perl Under the Hood") | | 43.6. PL/Perl Triggers | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 43.8. PL/Perl Under the Hood | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/plperl-event-triggers.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 43.7. PL/Perl Event Triggers November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plperl-event-triggers.html "PostgreSQL 18 - 43.7. PL/Perl Event Triggers") ([18](https://www.postgresql.org/docs/18/plperl-event-triggers.html "PostgreSQL 18 - 43.7. PL/Perl Event Triggers") ) / [17](https://www.postgresql.org/docs/17/plperl-event-triggers.html "PostgreSQL 17 - 43.7. PL/Perl Event Triggers") / [16](https://www.postgresql.org/docs/16/plperl-event-triggers.html "PostgreSQL 16 - 43.7. PL/Perl Event Triggers") / [15](https://www.postgresql.org/docs/15/plperl-event-triggers.html "PostgreSQL 15 - 43.7. PL/Perl Event Triggers") / [14](https://www.postgresql.org/docs/14/plperl-event-triggers.html "PostgreSQL 14 - 43.7. PL/Perl Event Triggers") Development Versions: [devel](https://www.postgresql.org/docs/devel/plperl-event-triggers.html "PostgreSQL devel - 43.7. PL/Perl Event Triggers") Unsupported versions: [13](https://www.postgresql.org/docs/13/plperl-event-triggers.html "PostgreSQL 13 - 43.7. PL/Perl Event Triggers") / [12](https://www.postgresql.org/docs/12/plperl-event-triggers.html "PostgreSQL 12 - 43.7. PL/Perl Event Triggers") / [11](https://www.postgresql.org/docs/11/plperl-event-triggers.html "PostgreSQL 11 - 43.7. PL/Perl Event Triggers") / [10](https://www.postgresql.org/docs/10/plperl-event-triggers.html "PostgreSQL 10 - 43.7. PL/Perl Event Triggers") / [9.6](https://www.postgresql.org/docs/9.6/plperl-event-triggers.html "PostgreSQL 9.6 - 43.7. PL/Perl Event Triggers") / [9.5](https://www.postgresql.org/docs/9.5/plperl-event-triggers.html "PostgreSQL 9.5 - 43.7. PL/Perl Event Triggers") / [9.4](https://www.postgresql.org/docs/9.4/plperl-event-triggers.html "PostgreSQL 9.4 - 43.7. PL/Perl Event Triggers") | 43.7. PL/Perl Event Triggers | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/plperl-triggers.html "43.6. PL/Perl Triggers") | [Up](https://www.postgresql.org/docs/18/plperl.html "Chapter 43. PL/Perl — Perl Procedural Language") | Chapter 43. PL/Perl — Perl Procedural Language | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/plperl-under-the-hood.html "43.8. PL/Perl Under the Hood") | * * * 43.7. PL/Perl Event Triggers [#](https://www.postgresql.org/docs/18/plperl-event-triggers.html#PLPERL-EVENT-TRIGGERS) ---------------------------------------------------------------------------------------------------------------------- PL/Perl can be used to write event trigger functions. In an event trigger function, the hash reference `$_TD` contains information about the current trigger event. `$_TD` is a global variable, which gets a separate local value for each invocation of the trigger. The fields of the `$_TD` hash reference are: `$_TD->{event}` The name of the event the trigger is fired for. `$_TD->{tag}` The command tag for which the trigger is fired. The return value of the trigger function is ignored. Here is an example of an event trigger function, illustrating some of the above: CREATE OR REPLACE FUNCTION perlsnitch() RETURNS event\_trigger AS $$ elog(NOTICE, "perlsnitch: " . $\_TD->{event} . " " . $\_TD->{tag} . " "); $$ LANGUAGE plperl; CREATE EVENT TRIGGER perl\_a\_snitch ON ddl\_command\_start EXECUTE FUNCTION perlsnitch(); * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/plperl-triggers.html "43.6. PL/Perl Triggers") | [Up](https://www.postgresql.org/docs/18/plperl.html "Chapter 43. PL/Perl — Perl Procedural Language") | [Next](https://www.postgresql.org/docs/18/plperl-under-the-hood.html "43.8. PL/Perl Under the Hood") | | 43.6. PL/Perl Triggers | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 43.8. PL/Perl Under the Hood | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/plperl-event-triggers.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.6. pg_config November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-config.html "PostgreSQL 18 - 53.6. pg_config") ([18](https://www.postgresql.org/docs/18/view-pg-config.html "PostgreSQL 18 - 53.6. pg_config") ) / [17](https://www.postgresql.org/docs/17/view-pg-config.html "PostgreSQL 17 - 53.6. pg_config") / [16](https://www.postgresql.org/docs/16/view-pg-config.html "PostgreSQL 16 - 53.6. pg_config") / [15](https://www.postgresql.org/docs/15/view-pg-config.html "PostgreSQL 15 - 53.6. pg_config") / [14](https://www.postgresql.org/docs/14/view-pg-config.html "PostgreSQL 14 - 53.6. pg_config") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-config.html "PostgreSQL devel - 53.6. pg_config") Unsupported versions: [13](https://www.postgresql.org/docs/13/view-pg-config.html "PostgreSQL 13 - 53.6. pg_config") / [12](https://www.postgresql.org/docs/12/view-pg-config.html "PostgreSQL 12 - 53.6. pg_config") / [11](https://www.postgresql.org/docs/11/view-pg-config.html "PostgreSQL 11 - 53.6. pg_config") / [10](https://www.postgresql.org/docs/10/view-pg-config.html "PostgreSQL 10 - 53.6. pg_config") / [9.6](https://www.postgresql.org/docs/9.6/view-pg-config.html "PostgreSQL 9.6 - 53.6. pg_config") | 53.6. `pg_config` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-backend-memory-contexts.html "53.5. pg_backend_memory_contexts") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/view-pg-cursors.html "53.7. pg_cursors") | * * * 53.6. `pg_config` [#](https://www.postgresql.org/docs/18/view-pg-config.html#VIEW-PG-CONFIG) --------------------------------------------------------------------------------------------- The view `pg_config` describes the compile-time configuration parameters of the currently installed version of PostgreSQL. It is intended, for example, to be used by software packages that want to interface to PostgreSQL to facilitate finding the required header files and libraries. It provides the same basic information as the [pg\_config](https://www.postgresql.org/docs/18/app-pgconfig.html "pg_config") PostgreSQL client application. By default, the `pg_config` view can be read only by superusers. **Table 53.6. `pg_config` Columns** | Column Type

Description | | --- | | `name` `text`

The parameter name | | `setting` `text`

The parameter value | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-backend-memory-contexts.html "53.5. pg_backend_memory_contexts") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/18/view-pg-cursors.html "53.7. pg_cursors") | | 53.5. `pg_backend_memory_contexts` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 53.7. `pg_cursors` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-config.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: pg_createsubscriber November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/app-pgcreatesubscriber.html "PostgreSQL 18 - pg_createsubscriber") ([18](https://www.postgresql.org/docs/18/app-pgcreatesubscriber.html "PostgreSQL 18 - pg_createsubscriber") ) / [17](https://www.postgresql.org/docs/17/app-pgcreatesubscriber.html "PostgreSQL 17 - pg_createsubscriber") Development Versions: [devel](https://www.postgresql.org/docs/devel/app-pgcreatesubscriber.html "PostgreSQL devel - pg_createsubscriber") | pg\_createsubscriber | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/app-pgcontroldata.html "pg_controldata") | [Up](https://www.postgresql.org/docs/18/reference-server.html "PostgreSQL Server Applications") | PostgreSQL Server Applications | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/app-pg-ctl.html "pg_ctl") | * * * pg\_createsubscriber -------------------- pg\_createsubscriber — convert a physical replica into a new logical replica Synopsis -------- `pg_createsubscriber` \[_`option`_...\] { `-d` | `--database` }_`dbname`_ { `-D` | `--pgdata` }_`datadir`_ { `-P` | `--publisher-server` }_`connstr`_ Description ----------- pg\_createsubscriber creates a new logical replica from a physical standby server. All tables in the specified database are included in the [logical replication](https://www.postgresql.org/docs/18/logical-replication.html "Chapter 29. Logical Replication") setup. A pair of publication and subscription objects are created for each database. It must be run at the target server. After a successful run, the state of the target server is analogous to a fresh logical replication setup. The main difference between the logical replication setup and pg\_createsubscriber is how the data synchronization is done. pg\_createsubscriber does not copy the initial table data. It does only the synchronization phase, which ensures each table is brought up to a synchronized state. pg\_createsubscriber targets large database systems because in logical replication setup, most of the time is spent doing the initial data copy. Furthermore, a side effect of this long time spent synchronizing data is usually a large amount of changes to be applied (that were produced during the initial data copy), which increases even more the time when the logical replica will be available. For smaller databases, it is recommended to set up logical replication with initial data synchronization. For details, see the `CREATE SUBSCRIPTION` [`copy_data`](https://www.postgresql.org/docs/18/sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-COPY-DATA) option. Options ------- pg\_createsubscriber accepts the following command-line arguments: `-a` `--all` Create one subscription per database on the target server. Exceptions are template databases and databases that don't allow connections. To discover the list of all databases, connect to the source server using the database name specified in the `--publisher-server` connection string, or if not specified, the `postgres` database will be used, or if that does not exist, `template1` will be used. Automatically generated names for subscriptions, publications, and replication slots are used when this option is specified. This option cannot be used along with `--database`, `--publication`, `--replication-slot`, or `--subscription`. ``-d _`dbname`_`` ``--database=_`dbname`_`` The name of the database in which to create a subscription. Multiple databases can be selected by writing multiple `-d` switches. This option cannot be used together with `-a`. If `-d` option is not provided, the database name will be obtained from `-P` option. If the database name is not specified in either the `-d` option, or the `-P` option, and `-a` option is not specified, an error will be reported. ``-D _`directory`_`` ``--pgdata=_`directory`_`` The target directory that contains a cluster directory from a physical replica. `-n` `--dry-run` Do everything except actually modifying the target directory. ``-p _`port`_`` ``--subscriber-port=_`port`_`` The port number on which the target server is listening for connections. Defaults to running the target server on port 50432 to avoid unintended client connections. ``-P _`connstr`_`` ``--publisher-server=_`connstr`_`` The connection string to the publisher. For details see [Section 32.1.1](https://www.postgresql.org/docs/18/libpq-connect.html#LIBPQ-CONNSTRING "32.1.1. Connection Strings") . ``-s _`dir`_`` ``--socketdir=_`dir`_`` The directory to use for postmaster sockets on target server. The default is current directory. ``-t _`seconds`_`` ``--recovery-timeout=_`seconds`_`` The maximum number of seconds to wait for recovery to end. Setting to 0 disables. The default is 0. `-T` `--enable-two-phase` Enables [`two_phase`](https://www.postgresql.org/docs/18/sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-TWO-PHASE) commit for the subscription. When multiple databases are specified, this option applies uniformly to all subscriptions created on those databases. The default is `false`. ``-U _`username`_`` ``--subscriber-username=_`username`_`` The user name to connect as on target server. Defaults to the current operating system user name. `-v` `--verbose` Enables verbose mode. This will cause pg\_createsubscriber to output progress messages and detailed information about each step to standard error. Repeating the option causes additional debug-level messages to appear on standard error. ``--clean=_`objtype`_`` Drop all objects of the specified type from specified databases on the target server. * `publications`: The `FOR ALL TABLES` publications established for this subscriber are always dropped; specifying this object type causes all other publications replicated from the source server to be dropped as well. The objects selected to be dropped are individually logged, including during a `--dry-run`. There is no opportunity to affect or stop the dropping of the selected objects, so consider taking a backup of them using pg\_dump. ``--config-file=_`filename`_`` Use the specified main server configuration file for the target data directory. pg\_createsubscriber internally uses the pg\_ctl command to start and stop the target server. It allows you to specify the actual `postgresql.conf` configuration file if it is stored outside the data directory. ``--publication=_`name`_`` The publication name to set up the logical replication. Multiple publications can be specified by writing multiple `--publication` switches. The number of publication names must match the number of specified databases, otherwise an error is reported. The order of the multiple publication name switches must match the order of database switches. If this option is not specified, a generated name is assigned to the publication name. This option cannot be used together with `--all`. ``--replication-slot=_`name`_`` The replication slot name to set up the logical replication. Multiple replication slots can be specified by writing multiple `--replication-slot` switches. The number of replication slot names must match the number of specified databases, otherwise an error is reported. The order of the multiple replication slot name switches must match the order of database switches. If this option is not specified, the subscription name is assigned to the replication slot name. This option cannot be used together with `--all`. ``--subscription=_`name`_`` The subscription name to set up the logical replication. Multiple subscriptions can be specified by writing multiple `--subscription` switches. The number of subscription names must match the number of specified databases, otherwise an error is reported. The order of the multiple subscription name switches must match the order of database switches. If this option is not specified, a generated name is assigned to the subscription name. This option cannot be used together with `--all`. `-V` `--version` Print the pg\_createsubscriber version and exit. `-?` `--help` Show help about pg\_createsubscriber command line arguments, and exit. Notes ----- ### Prerequisites There are some prerequisites for pg\_createsubscriber to convert the target server into a logical replica. If these are not met, an error will be reported. The source and target servers must have the same major version as the pg\_createsubscriber. The given target data directory must have the same system identifier as the source data directory. The given database user for the target data directory must have privileges for creating [subscriptions](https://www.postgresql.org/docs/18/sql-createsubscription.html "CREATE SUBSCRIPTION") and using [`pg_replication_origin_advance()`](https://www.postgresql.org/docs/18/functions-admin.html#PG-REPLICATION-ORIGIN-ADVANCE) . The target server must be used as a physical standby. The target server must have [max\_active\_replication\_origins](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-ACTIVE-REPLICATION-ORIGINS) and [max\_logical\_replication\_workers](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-LOGICAL-REPLICATION-WORKERS) configured to a value greater than or equal to the number of specified databases. The target server must have [max\_worker\_processes](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES) configured to a value greater than the number of specified databases. The target server must accept local connections. If you are planning to use the `--enable-two-phase` switch then you will also need to set the [max\_prepared\_transactions](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-MAX-PREPARED-TRANSACTIONS) appropriately. The source server must accept connections from the target server. The source server must not be in recovery. The source server must have [wal\_level](https://www.postgresql.org/docs/18/runtime-config-wal.html#GUC-WAL-LEVEL) as `logical`. The source server must have [max\_replication\_slots](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-REPLICATION-SLOTS) configured to a value greater than or equal to the number of specified databases plus existing replication slots. The source server must have [max\_wal\_senders](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-WAL-SENDERS) configured to a value greater than or equal to the number of specified databases and existing WAL sender processes. ### Warnings If pg\_createsubscriber fails after the target server was promoted, then the data directory is likely not in a state that can be recovered. In such case, creating a new standby server is recommended. pg\_createsubscriber usually starts the target server with different connection settings during transformation. Hence, connections to the target server should fail. Since DDL commands are not replicated by logical replication, avoid executing DDL commands that change the database schema while running pg\_createsubscriber. If the target server has already been converted to logical replica, the DDL commands might not be replicated, which might cause an error. If pg\_createsubscriber fails while processing, objects (publications, replication slots) created on the source server are removed. The removal might fail if the target server cannot connect to the source server. In such a case, a warning message will inform the objects left. If the target server is running, it will be stopped. If the replication is using [primary\_slot\_name](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-PRIMARY-SLOT-NAME) , it will be removed from the source server after the logical replication setup. If the target server is a synchronous replica, transaction commits on the primary might wait for replication while running pg\_createsubscriber. Unless the `--enable-two-phase` switch is specified, pg\_createsubscriber sets up logical replication with two-phase commit disabled. This means that any prepared transactions will be replicated at the time of `COMMIT PREPARED`, without advance preparation. Once setup is complete, you can manually drop and re-create the subscription(s) with the [`two_phase`](https://www.postgresql.org/docs/18/sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-TWO-PHASE) option enabled. pg\_createsubscriber changes the system identifier using pg\_resetwal. It would avoid situations in which the target server might use WAL files from the source server. If the target server has a standby, replication will break and a fresh standby should be created. Replication failures can occur if required WAL files are missing. To prevent this, the source server must set [max\_slot\_wal\_keep\_size](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-SLOT-WAL-KEEP-SIZE) to `-1` to ensure that required WAL files are not prematurely removed. ### How It Works The basic idea is to have a replication start point from the source server and set up a logical replication to start from this point: 1. Start the target server with the specified command-line options. If the target server is already running, pg\_createsubscriber will terminate with an error. 2. Check if the target server can be converted. There are also a few checks on the source server. If any of the prerequisites are not met, pg\_createsubscriber will terminate with an error. 3. Create a publication and replication slot for each specified database on the source server. Each publication is created using [`FOR ALL TABLES`](https://www.postgresql.org/docs/18/sql-createpublication.html#SQL-CREATEPUBLICATION-PARAMS-FOR-ALL-TABLES) . If the `--publication` option is not specified, the publication has the following name pattern: “`pg_createsubscriber_%u_%x`” (parameter: database _`oid`_, random _`int`_). If the `--replication-slot` option is not specified, the replication slot has the following name pattern: “`pg_createsubscriber_%u_%x`” (parameters: database _`oid`_, random _`int`_). These replication slots will be used by the subscriptions in a future step. The last replication slot LSN is used as a stopping point in the [recovery\_target\_lsn](https://www.postgresql.org/docs/18/runtime-config-wal.html#GUC-RECOVERY-TARGET-LSN) parameter and by the subscriptions as a replication start point. It guarantees that no transaction will be lost. 4. Write recovery parameters into the target data directory and restart the target server. It specifies an LSN ([recovery\_target\_lsn](https://www.postgresql.org/docs/18/runtime-config-wal.html#GUC-RECOVERY-TARGET-LSN) ) of the write-ahead log location up to which recovery will proceed. It also specifies `promote` as the action that the server should take once the recovery target is reached. Additional [recovery parameters](https://www.postgresql.org/docs/18/runtime-config-wal.html#RUNTIME-CONFIG-WAL-RECOVERY-TARGET "19.5.6. Recovery Target") are added to avoid unexpected behavior during the recovery process such as end of the recovery as soon as a consistent state is reached (WAL should be applied until the replication start location) and multiple recovery targets that can cause a failure. This step finishes once the server ends standby mode and is accepting read-write transactions. If `--recovery-timeout` option is set, pg\_createsubscriber terminates if recovery does not end until the given number of seconds. 5. Create a subscription for each specified database on the target server. If the `--subscription` option is not specified, the subscription has the following name pattern: “`pg_createsubscriber_%u_%x`” (parameters: database _`oid`_, random _`int`_). It does not copy existing data from the source server. It does not create a replication slot. Instead, it uses the replication slot that was created in a previous step. The subscription is created but it is not enabled yet. The reason is the replication progress must be set to the replication start point before starting the replication. 6. Drop publications on the target server that were replicated because they were created before the replication start location. It has no use on the subscriber. 7. Set the replication progress to the replication start point for each subscription. When the target server starts the recovery process, it catches up to the replication start point. This is the exact LSN to be used as a initial replication location for each subscription. The replication origin name is obtained since the subscription was created. The replication origin name and the replication start point are used in [`pg_replication_origin_advance()`](https://www.postgresql.org/docs/18/functions-admin.html#PG-REPLICATION-ORIGIN-ADVANCE) to set up the initial replication location. 8. Enable the subscription for each specified database on the target server. The subscription starts applying transactions from the replication start point. 9. If the standby server was using [primary\_slot\_name](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-PRIMARY-SLOT-NAME) , it has no use from now on so drop it. 10. If the standby server contains [failover replication slots](https://www.postgresql.org/docs/18/logicaldecoding-explanation.html#LOGICALDECODING-REPLICATION-SLOTS-SYNCHRONIZATION "47.2.3. Replication Slot Synchronization") , they cannot be synchronized anymore, so drop them. 11. Update the system identifier on the target server. The [pg\_resetwal](https://www.postgresql.org/docs/18/app-pgresetwal.html "pg_resetwal") is run to modify the system identifier. The target server is stopped as a `pg_resetwal` requirement. Examples -------- To create a logical replica for databases `hr` and `finance` from a physical replica at `foo`: $ See Also -------- [pg\_basebackup](https://www.postgresql.org/docs/18/app-pgbasebackup.html "pg_basebackup") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/app-pgcontroldata.html "pg_controldata") | [Up](https://www.postgresql.org/docs/18/reference-server.html "PostgreSQL Server Applications") | [Next](https://www.postgresql.org/docs/18/app-pg-ctl.html "pg_ctl") | | pg\_controldata | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | pg\_ctl | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/app-pgcreatesubscriber.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 46. Background Worker Processes November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/bgworker.html "PostgreSQL 18 - Chapter 46. Background Worker Processes") ([18](https://www.postgresql.org/docs/18/bgworker.html "PostgreSQL 18 - Chapter 46. Background Worker Processes") ) / [17](https://www.postgresql.org/docs/17/bgworker.html "PostgreSQL 17 - Chapter 46. Background Worker Processes") / [16](https://www.postgresql.org/docs/16/bgworker.html "PostgreSQL 16 - Chapter 46. Background Worker Processes") / [15](https://www.postgresql.org/docs/15/bgworker.html "PostgreSQL 15 - Chapter 46. Background Worker Processes") / [14](https://www.postgresql.org/docs/14/bgworker.html "PostgreSQL 14 - Chapter 46. Background Worker Processes") Development Versions: [devel](https://www.postgresql.org/docs/devel/bgworker.html "PostgreSQL devel - Chapter 46. Background Worker Processes") Unsupported versions: [13](https://www.postgresql.org/docs/13/bgworker.html "PostgreSQL 13 - Chapter 46. Background Worker Processes") / [12](https://www.postgresql.org/docs/12/bgworker.html "PostgreSQL 12 - Chapter 46. Background Worker Processes") / [11](https://www.postgresql.org/docs/11/bgworker.html "PostgreSQL 11 - Chapter 46. Background Worker Processes") / [10](https://www.postgresql.org/docs/10/bgworker.html "PostgreSQL 10 - Chapter 46. Background Worker Processes") / [9.6](https://www.postgresql.org/docs/9.6/bgworker.html "PostgreSQL 9.6 - Chapter 46. Background Worker Processes") / [9.5](https://www.postgresql.org/docs/9.5/bgworker.html "PostgreSQL 9.5 - Chapter 46. Background Worker Processes") / [9.4](https://www.postgresql.org/docs/9.4/bgworker.html "PostgreSQL 9.4 - Chapter 46. Background Worker Processes") / [9.3](https://www.postgresql.org/docs/9.3/bgworker.html "PostgreSQL 9.3 - Chapter 46. Background Worker Processes") | Chapter 46. Background Worker Processes | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-start-transaction.html "SPI_start_transaction") | [Up](https://www.postgresql.org/docs/18/server-programming.html "Part V. Server Programming") | Part V. Server Programming | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/logicaldecoding.html "Chapter 47. Logical Decoding") | * * * Chapter 46. Background Worker Processes --------------------------------------- PostgreSQL can be extended to run user-supplied code in separate processes. Such processes are started, stopped and monitored by `postgres`, which permits them to have a lifetime closely linked to the server's status. These processes are attached to PostgreSQL's shared memory area and have the option to connect to databases internally; they can also run multiple transactions serially, just like a regular client-connected server process. Also, by linking to libpq they can connect to the server and behave like a regular client application. ### Warning There are considerable robustness and security risks in using background worker processes because, being written in the `C` language, they have unrestricted access to data. Administrators wishing to enable modules that include background worker processes should exercise extreme caution. Only carefully audited modules should be permitted to run background worker processes. Background workers can be initialized at the time that PostgreSQL is started by including the module name in `shared_preload_libraries`. A module wishing to run a background worker can register it by calling ``RegisterBackgroundWorker(`BackgroundWorker` *_`worker`_)`` from its `_PG_init()` function. Background workers can also be started after the system is up and running by calling ``RegisterDynamicBackgroundWorker(`BackgroundWorker` *_`worker`_, `BackgroundWorkerHandle` **_`handle`_)``. Unlike `RegisterBackgroundWorker`, which can only be called from within the postmaster process, `RegisterDynamicBackgroundWorker` must be called from a regular backend or another background worker. The structure `BackgroundWorker` is defined thus: typedef void (\*bgworker\_main\_type)(Datum main\_arg); typedef struct BackgroundWorker { char bgw\_name\[BGW\_MAXLEN\]; char bgw\_type\[BGW\_MAXLEN\]; int bgw\_flags; BgWorkerStartTime bgw\_start\_time; int bgw\_restart\_time; /\* in seconds, or BGW\_NEVER\_RESTART \*/ char bgw\_library\_name\[MAXPGPATH\]; char bgw\_function\_name\[BGW\_MAXLEN\]; Datum bgw\_main\_arg; char bgw\_extra\[BGW\_EXTRALEN\]; pid\_t bgw\_notify\_pid; } BackgroundWorker; `bgw_name` and `bgw_type` are strings to be used in log messages, process listings and similar contexts. `bgw_type` should be the same for all background workers of the same type, so that it is possible to group such workers in a process listing, for example. `bgw_name` on the other hand can contain additional information about the specific process. (Typically, the string for `bgw_name` will contain the type somehow, but that is not strictly required.) `bgw_flags` is a bitwise-or'd bit mask indicating the capabilities that the module wants. Possible values are: `BGWORKER_SHMEM_ACCESS` Requests shared memory access. This flag is required. `BGWORKER_BACKEND_DATABASE_CONNECTION` Requests the ability to establish a database connection through which it can later run transactions and queries. A background worker using `BGWORKER_BACKEND_DATABASE_CONNECTION` to connect to a database must also attach shared memory using `BGWORKER_SHMEM_ACCESS`, or worker start-up will fail. `bgw_start_time` is the server state during which `postgres` should start the process; it can be one of `BgWorkerStart_PostmasterStart` (start as soon as `postgres` itself has finished its own initialization; processes requesting this are not eligible for database connections), `BgWorkerStart_ConsistentState` (start as soon as a consistent state has been reached in a hot standby, allowing processes to connect to databases and run read-only queries), and `BgWorkerStart_RecoveryFinished` (start as soon as the system has entered normal read-write state). Note the last two values are equivalent in a server that's not a hot standby. Note that this setting only indicates when the processes are to be started; they do not stop when a different state is reached. `bgw_restart_time` is the interval, in seconds, that `postgres` should wait before restarting the process in the event that it crashes. It can be any positive value, or `BGW_NEVER_RESTART`, indicating not to restart the process in case of a crash. `bgw_library_name` is the name of a library in which the initial entry point for the background worker should be sought. The named library will be dynamically loaded by the worker process and `bgw_function_name` will be used to identify the function to be called. If calling a function in the core code, this must be set to `"postgres"`. `bgw_function_name` is the name of the function to use as the initial entry point for the new background worker. If this function is in a dynamically loaded library, it must be marked `PGDLLEXPORT` (and not `static`). `bgw_main_arg` is the `Datum` argument to the background worker main function. This main function should take a single argument of type `Datum` and return `void`. `bgw_main_arg` will be passed as the argument. In addition, the global variable `MyBgworkerEntry` points to a copy of the `BackgroundWorker` structure passed at registration time; the worker may find it helpful to examine this structure. On Windows (and anywhere else where `EXEC_BACKEND` is defined) or in dynamic background workers it is not safe to pass a `Datum` by reference, only by value. If an argument is required, it is safest to pass an int32 or other small value and use that as an index into an array allocated in shared memory. If a value like a `cstring` or `text` is passed then the pointer won't be valid from the new background worker process. `bgw_extra` can contain extra data to be passed to the background worker. Unlike `bgw_main_arg`, this data is not passed as an argument to the worker's main function, but it can be accessed via `MyBgworkerEntry`, as discussed above. `bgw_notify_pid` is the PID of a PostgreSQL backend process to which the postmaster should send `SIGUSR1` when the process is started or exits. It should be 0 for workers registered at postmaster startup time, or when the backend registering the worker does not wish to wait for the worker to start up. Otherwise, it should be initialized to `MyProcPid`. Once running, the process can connect to a database by calling ``BackgroundWorkerInitializeConnection(_`char *dbname`_, _`char *username`_, _`uint32 flags`_)`` or ``BackgroundWorkerInitializeConnectionByOid(_`Oid dboid`_, _`Oid useroid`_, _`uint32 flags`_)``. This allows the process to run transactions and queries using the `SPI` interface. If `dbname` is NULL or `dboid` is `InvalidOid`, the session is not connected to any particular database, but shared catalogs can be accessed. If `username` is NULL or `useroid` is `InvalidOid`, the process will run as the superuser created during `initdb`. If `BGWORKER_BYPASS_ALLOWCONN` is specified as `flags` it is possible to bypass the restriction to connect to databases not allowing user connections. If `BGWORKER_BYPASS_ROLELOGINCHECK` is specified as `flags` it is possible to bypass the login check for the role used to connect to databases. A background worker can only call one of these two functions, and only once. It is not possible to switch databases. Signals are initially blocked when control reaches the background worker's main function, and must be unblocked by it; this is to allow the process to customize its signal handlers, if necessary. Signals can be unblocked in the new process by calling `BackgroundWorkerUnblockSignals` and blocked by calling `BackgroundWorkerBlockSignals`. If `bgw_restart_time` for a background worker is configured as `BGW_NEVER_RESTART`, or if it exits with an exit code of 0 or is terminated by `TerminateBackgroundWorker`, it will be automatically unregistered by the postmaster on exit. Otherwise, it will be restarted after the time period configured via `bgw_restart_time`, or immediately if the postmaster reinitializes the cluster due to a backend failure. Backends which need to suspend execution only temporarily should use an interruptible sleep rather than exiting; this can be achieved by calling `WaitLatch()`. Make sure the `WL_POSTMASTER_DEATH` flag is set when calling that function, and verify the return code for a prompt exit in the emergency case that `postgres` itself has terminated. When a background worker is registered using the `RegisterDynamicBackgroundWorker` function, it is possible for the backend performing the registration to obtain information regarding the status of the worker. Backends wishing to do this should pass the address of a `BackgroundWorkerHandle *` as the second argument to `RegisterDynamicBackgroundWorker`. If the worker is successfully registered, this pointer will be initialized with an opaque handle that can subsequently be passed to ``GetBackgroundWorkerPid(_`BackgroundWorkerHandle *`_, _`pid_t *`_)`` or ``TerminateBackgroundWorker(_`BackgroundWorkerHandle *`_)``. `GetBackgroundWorkerPid` can be used to poll the status of the worker: a return value of `BGWH_NOT_YET_STARTED` indicates that the worker has not yet been started by the postmaster; `BGWH_STOPPED` indicates that it has been started but is no longer running; and `BGWH_STARTED` indicates that it is currently running. In this last case, the PID will also be returned via the second argument. `TerminateBackgroundWorker` causes the postmaster to send `SIGTERM` to the worker if it is running, and to unregister it as soon as it is not. In some cases, a process which registers a background worker may wish to wait for the worker to start up. This can be accomplished by initializing `bgw_notify_pid` to `MyProcPid` and then passing the `BackgroundWorkerHandle *` obtained at registration time to ``WaitForBackgroundWorkerStartup(_`BackgroundWorkerHandle *handle`_, _`pid_t *`_)`` function. This function will block until the postmaster has attempted to start the background worker, or until the postmaster dies. If the background worker is running, the return value will be `BGWH_STARTED`, and the PID will be written to the provided address. Otherwise, the return value will be `BGWH_STOPPED` or `BGWH_POSTMASTER_DIED`. A process can also wait for a background worker to shut down, by using the ``WaitForBackgroundWorkerShutdown(_`BackgroundWorkerHandle *handle`_)`` function and passing the `BackgroundWorkerHandle *` obtained at registration. This function will block until the background worker exits, or postmaster dies. When the background worker exits, the return value is `BGWH_STOPPED`, if postmaster dies it will return `BGWH_POSTMASTER_DIED`. Background workers can send asynchronous notification messages, either by using the `NOTIFY` command via SPI, or directly via `Async_Notify()`. Such notifications will be sent at transaction commit. Background workers should not register to receive asynchronous notifications with the `LISTEN` command, as there is no infrastructure for a worker to consume such notifications. The `src/test/modules/worker_spi` module contains a working example, which demonstrates some useful techniques. The maximum number of registered background workers is limited by [max\_worker\_processes](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES) . * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-start-transaction.html "SPI_start_transaction") | [Up](https://www.postgresql.org/docs/18/server-programming.html "Part V. Server Programming") | [Next](https://www.postgresql.org/docs/18/logicaldecoding.html "Chapter 47. Logical Decoding") | | SPI\_start\_transaction | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | Chapter 47. Logical Decoding | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/bgworker.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.6. pg_config November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-config.html "PostgreSQL 18 - 53.6. pg_config") ([18](https://www.postgresql.org/docs/18/view-pg-config.html "PostgreSQL 18 - 53.6. pg_config") ) / [17](https://www.postgresql.org/docs/17/view-pg-config.html "PostgreSQL 17 - 53.6. pg_config") / [16](https://www.postgresql.org/docs/16/view-pg-config.html "PostgreSQL 16 - 53.6. pg_config") / [15](https://www.postgresql.org/docs/15/view-pg-config.html "PostgreSQL 15 - 53.6. pg_config") / [14](https://www.postgresql.org/docs/14/view-pg-config.html "PostgreSQL 14 - 53.6. pg_config") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-config.html "PostgreSQL devel - 53.6. pg_config") Unsupported versions: [13](https://www.postgresql.org/docs/13/view-pg-config.html "PostgreSQL 13 - 53.6. pg_config") / [12](https://www.postgresql.org/docs/12/view-pg-config.html "PostgreSQL 12 - 53.6. pg_config") / [11](https://www.postgresql.org/docs/11/view-pg-config.html "PostgreSQL 11 - 53.6. pg_config") / [10](https://www.postgresql.org/docs/10/view-pg-config.html "PostgreSQL 10 - 53.6. pg_config") / [9.6](https://www.postgresql.org/docs/9.6/view-pg-config.html "PostgreSQL 9.6 - 53.6. pg_config") | 53.6. `pg_config` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-backend-memory-contexts.html "53.5. pg_backend_memory_contexts") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/view-pg-cursors.html "53.7. pg_cursors") | * * * 53.6. `pg_config` [#](https://www.postgresql.org/docs/current/view-pg-config.html#VIEW-PG-CONFIG) -------------------------------------------------------------------------------------------------- The view `pg_config` describes the compile-time configuration parameters of the currently installed version of PostgreSQL. It is intended, for example, to be used by software packages that want to interface to PostgreSQL to facilitate finding the required header files and libraries. It provides the same basic information as the [pg\_config](https://www.postgresql.org/docs/current/app-pgconfig.html "pg_config") PostgreSQL client application. By default, the `pg_config` view can be read only by superusers. **Table 53.6. `pg_config` Columns** | Column Type

Description | | --- | | `name` `text`

The parameter name | | `setting` `text`

The parameter value | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-backend-memory-contexts.html "53.5. pg_backend_memory_contexts") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/current/view-pg-cursors.html "53.7. pg_cursors") | | 53.5. `pg_backend_memory_contexts` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 53.7. `pg_cursors` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-config.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 64.1. Generic WAL Records November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/generic-wal.html "PostgreSQL 18 - 64.1. Generic WAL Records") ([18](https://www.postgresql.org/docs/18/generic-wal.html "PostgreSQL 18 - 64.1. Generic WAL Records") ) / [17](https://www.postgresql.org/docs/17/generic-wal.html "PostgreSQL 17 - 64.1. Generic WAL Records") / [16](https://www.postgresql.org/docs/16/generic-wal.html "PostgreSQL 16 - 64.1. Generic WAL Records") / [15](https://www.postgresql.org/docs/15/generic-wal.html "PostgreSQL 15 - 64.1. Generic WAL Records") / [14](https://www.postgresql.org/docs/14/generic-wal.html "PostgreSQL 14 - 64.1. Generic WAL Records") Development Versions: [devel](https://www.postgresql.org/docs/devel/generic-wal.html "PostgreSQL devel - 64.1. Generic WAL Records") Unsupported versions: [13](https://www.postgresql.org/docs/13/generic-wal.html "PostgreSQL 13 - 64.1. Generic WAL Records") / [12](https://www.postgresql.org/docs/12/generic-wal.html "PostgreSQL 12 - 64.1. Generic WAL Records") / [11](https://www.postgresql.org/docs/11/generic-wal.html "PostgreSQL 11 - 64.1. Generic WAL Records") / [10](https://www.postgresql.org/docs/10/generic-wal.html "PostgreSQL 10 - 64.1. Generic WAL Records") / [9.6](https://www.postgresql.org/docs/9.6/generic-wal.html "PostgreSQL 9.6 - 64.1. Generic WAL Records") | 64.1. Generic WAL Records | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/wal-for-extensions.html "Chapter 64. Write Ahead Logging for Extensions") | [Up](https://www.postgresql.org/docs/18/wal-for-extensions.html "Chapter 64. Write Ahead Logging for Extensions") | Chapter 64. Write Ahead Logging for Extensions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/custom-rmgr.html "64.2. Custom WAL Resource Managers") | * * * 64.1. Generic WAL Records [#](https://www.postgresql.org/docs/18/generic-wal.html#GENERIC-WAL) ----------------------------------------------------------------------------------------------- Although all built-in WAL-logged modules have their own types of WAL records, there is also a generic WAL record type, which describes changes to pages in a generic way. ### Note Generic WAL records are ignored during [Logical Decoding](https://www.postgresql.org/docs/18/logicaldecoding.html "Chapter 47. Logical Decoding") . If logical decoding is required for your extension, consider a Custom WAL Resource Manager. The API for constructing generic WAL records is defined in `access/generic_xlog.h` and implemented in `access/transam/generic_xlog.c`. To perform a WAL-logged data update using the generic WAL record facility, follow these steps: 1. `state = GenericXLogStart(relation)` — start construction of a generic WAL record for the given relation. 2. `page = GenericXLogRegisterBuffer(state, buffer, flags)` — register a buffer to be modified within the current generic WAL record. This function returns a pointer to a temporary copy of the buffer's page, where modifications should be made. (Do not modify the buffer's contents directly.) The third argument is a bit mask of flags applicable to the operation. Currently the only such flag is `GENERIC_XLOG_FULL_IMAGE`, which indicates that a full-page image rather than a delta update should be included in the WAL record. Typically this flag would be set if the page is new or has been rewritten completely. `GenericXLogRegisterBuffer` can be repeated if the WAL-logged action needs to modify multiple pages. 3. Apply modifications to the page images obtained in the previous step. 4. `GenericXLogFinish(state)` — apply the changes to the buffers and emit the generic WAL record. WAL record construction can be canceled between any of the above steps by calling `GenericXLogAbort(state)`. This will discard all changes to the page image copies. Please note the following points when using the generic WAL record facility: * No direct modifications of buffers are allowed! All modifications must be done in copies acquired from `GenericXLogRegisterBuffer()`. In other words, code that makes generic WAL records should never call `BufferGetPage()` for itself. However, it remains the caller's responsibility to pin/unpin and lock/unlock the buffers at appropriate times. Exclusive lock must be held on each target buffer from before `GenericXLogRegisterBuffer()` until after `GenericXLogFinish()`. * Registrations of buffers (step 2) and modifications of page images (step 3) can be mixed freely, i.e., both steps may be repeated in any sequence. Keep in mind that buffers should be registered in the same order in which locks are to be obtained on them during replay. * The maximum number of buffers that can be registered for a generic WAL record is `MAX_GENERIC_XLOG_PAGES`. An error will be thrown if this limit is exceeded. * Generic WAL assumes that the pages to be modified have standard layout, and in particular that there is no useful data between `pd_lower` and `pd_upper`. * Since you are modifying copies of buffer pages, `GenericXLogStart()` does not start a critical section. Thus, you can safely do memory allocation, error throwing, etc. between `GenericXLogStart()` and `GenericXLogFinish()`. The only actual critical section is present inside `GenericXLogFinish()`. There is no need to worry about calling `GenericXLogAbort()` during an error exit, either. * `GenericXLogFinish()` takes care of marking buffers dirty and setting their LSNs. You do not need to do this explicitly. * For unlogged relations, everything works the same except that no actual WAL record is emitted. Thus, you typically do not need to do any explicit checks for unlogged relations. * The generic WAL redo function will acquire exclusive locks to buffers in the same order as they were registered. After redoing all changes, the locks will be released in the same order. * If `GENERIC_XLOG_FULL_IMAGE` is not specified for a registered buffer, the generic WAL record contains a delta between the old and the new page images. This delta is based on byte-by-byte comparison. This is not very compact for the case of moving data within a page, and might be improved in the future. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/wal-for-extensions.html "Chapter 64. Write Ahead Logging for Extensions") | [Up](https://www.postgresql.org/docs/18/wal-for-extensions.html "Chapter 64. Write Ahead Logging for Extensions") | [Next](https://www.postgresql.org/docs/18/custom-rmgr.html "64.2. Custom WAL Resource Managers") | | Chapter 64. Write Ahead Logging for Extensions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 64.2. Custom WAL Resource Managers | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/generic-wal.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: pg_createsubscriber November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/app-pgcreatesubscriber.html "PostgreSQL 18 - pg_createsubscriber") ([18](https://www.postgresql.org/docs/18/app-pgcreatesubscriber.html "PostgreSQL 18 - pg_createsubscriber") ) / [17](https://www.postgresql.org/docs/17/app-pgcreatesubscriber.html "PostgreSQL 17 - pg_createsubscriber") Development Versions: [devel](https://www.postgresql.org/docs/devel/app-pgcreatesubscriber.html "PostgreSQL devel - pg_createsubscriber") | pg\_createsubscriber | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/app-pgcontroldata.html "pg_controldata") | [Up](https://www.postgresql.org/docs/current/reference-server.html "PostgreSQL Server Applications") | PostgreSQL Server Applications | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/app-pg-ctl.html "pg_ctl") | * * * pg\_createsubscriber -------------------- pg\_createsubscriber — convert a physical replica into a new logical replica Synopsis -------- `pg_createsubscriber` \[_`option`_...\] { `-d` | `--database` }_`dbname`_ { `-D` | `--pgdata` }_`datadir`_ { `-P` | `--publisher-server` }_`connstr`_ Description ----------- pg\_createsubscriber creates a new logical replica from a physical standby server. All tables in the specified database are included in the [logical replication](https://www.postgresql.org/docs/current/logical-replication.html "Chapter 29. Logical Replication") setup. A pair of publication and subscription objects are created for each database. It must be run at the target server. After a successful run, the state of the target server is analogous to a fresh logical replication setup. The main difference between the logical replication setup and pg\_createsubscriber is how the data synchronization is done. pg\_createsubscriber does not copy the initial table data. It does only the synchronization phase, which ensures each table is brought up to a synchronized state. pg\_createsubscriber targets large database systems because in logical replication setup, most of the time is spent doing the initial data copy. Furthermore, a side effect of this long time spent synchronizing data is usually a large amount of changes to be applied (that were produced during the initial data copy), which increases even more the time when the logical replica will be available. For smaller databases, it is recommended to set up logical replication with initial data synchronization. For details, see the `CREATE SUBSCRIPTION` [`copy_data`](https://www.postgresql.org/docs/current/sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-COPY-DATA) option. Options ------- pg\_createsubscriber accepts the following command-line arguments: `-a` `--all` Create one subscription per database on the target server. Exceptions are template databases and databases that don't allow connections. To discover the list of all databases, connect to the source server using the database name specified in the `--publisher-server` connection string, or if not specified, the `postgres` database will be used, or if that does not exist, `template1` will be used. Automatically generated names for subscriptions, publications, and replication slots are used when this option is specified. This option cannot be used along with `--database`, `--publication`, `--replication-slot`, or `--subscription`. ``-d _`dbname`_`` ``--database=_`dbname`_`` The name of the database in which to create a subscription. Multiple databases can be selected by writing multiple `-d` switches. This option cannot be used together with `-a`. If `-d` option is not provided, the database name will be obtained from `-P` option. If the database name is not specified in either the `-d` option, or the `-P` option, and `-a` option is not specified, an error will be reported. ``-D _`directory`_`` ``--pgdata=_`directory`_`` The target directory that contains a cluster directory from a physical replica. `-n` `--dry-run` Do everything except actually modifying the target directory. ``-p _`port`_`` ``--subscriber-port=_`port`_`` The port number on which the target server is listening for connections. Defaults to running the target server on port 50432 to avoid unintended client connections. ``-P _`connstr`_`` ``--publisher-server=_`connstr`_`` The connection string to the publisher. For details see [Section 32.1.1](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING "32.1.1. Connection Strings") . ``-s _`dir`_`` ``--socketdir=_`dir`_`` The directory to use for postmaster sockets on target server. The default is current directory. ``-t _`seconds`_`` ``--recovery-timeout=_`seconds`_`` The maximum number of seconds to wait for recovery to end. Setting to 0 disables. The default is 0. `-T` `--enable-two-phase` Enables [`two_phase`](https://www.postgresql.org/docs/current/sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-TWO-PHASE) commit for the subscription. When multiple databases are specified, this option applies uniformly to all subscriptions created on those databases. The default is `false`. ``-U _`username`_`` ``--subscriber-username=_`username`_`` The user name to connect as on target server. Defaults to the current operating system user name. `-v` `--verbose` Enables verbose mode. This will cause pg\_createsubscriber to output progress messages and detailed information about each step to standard error. Repeating the option causes additional debug-level messages to appear on standard error. ``--clean=_`objtype`_`` Drop all objects of the specified type from specified databases on the target server. * `publications`: The `FOR ALL TABLES` publications established for this subscriber are always dropped; specifying this object type causes all other publications replicated from the source server to be dropped as well. The objects selected to be dropped are individually logged, including during a `--dry-run`. There is no opportunity to affect or stop the dropping of the selected objects, so consider taking a backup of them using pg\_dump. ``--config-file=_`filename`_`` Use the specified main server configuration file for the target data directory. pg\_createsubscriber internally uses the pg\_ctl command to start and stop the target server. It allows you to specify the actual `postgresql.conf` configuration file if it is stored outside the data directory. ``--publication=_`name`_`` The publication name to set up the logical replication. Multiple publications can be specified by writing multiple `--publication` switches. The number of publication names must match the number of specified databases, otherwise an error is reported. The order of the multiple publication name switches must match the order of database switches. If this option is not specified, a generated name is assigned to the publication name. This option cannot be used together with `--all`. ``--replication-slot=_`name`_`` The replication slot name to set up the logical replication. Multiple replication slots can be specified by writing multiple `--replication-slot` switches. The number of replication slot names must match the number of specified databases, otherwise an error is reported. The order of the multiple replication slot name switches must match the order of database switches. If this option is not specified, the subscription name is assigned to the replication slot name. This option cannot be used together with `--all`. ``--subscription=_`name`_`` The subscription name to set up the logical replication. Multiple subscriptions can be specified by writing multiple `--subscription` switches. The number of subscription names must match the number of specified databases, otherwise an error is reported. The order of the multiple subscription name switches must match the order of database switches. If this option is not specified, a generated name is assigned to the subscription name. This option cannot be used together with `--all`. `-V` `--version` Print the pg\_createsubscriber version and exit. `-?` `--help` Show help about pg\_createsubscriber command line arguments, and exit. Notes ----- ### Prerequisites There are some prerequisites for pg\_createsubscriber to convert the target server into a logical replica. If these are not met, an error will be reported. The source and target servers must have the same major version as the pg\_createsubscriber. The given target data directory must have the same system identifier as the source data directory. The given database user for the target data directory must have privileges for creating [subscriptions](https://www.postgresql.org/docs/current/sql-createsubscription.html "CREATE SUBSCRIPTION") and using [`pg_replication_origin_advance()`](https://www.postgresql.org/docs/current/functions-admin.html#PG-REPLICATION-ORIGIN-ADVANCE) . The target server must be used as a physical standby. The target server must have [max\_active\_replication\_origins](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-ACTIVE-REPLICATION-ORIGINS) and [max\_logical\_replication\_workers](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-LOGICAL-REPLICATION-WORKERS) configured to a value greater than or equal to the number of specified databases. The target server must have [max\_worker\_processes](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES) configured to a value greater than the number of specified databases. The target server must accept local connections. If you are planning to use the `--enable-two-phase` switch then you will also need to set the [max\_prepared\_transactions](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-MAX-PREPARED-TRANSACTIONS) appropriately. The source server must accept connections from the target server. The source server must not be in recovery. The source server must have [wal\_level](https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-WAL-LEVEL) as `logical`. The source server must have [max\_replication\_slots](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-REPLICATION-SLOTS) configured to a value greater than or equal to the number of specified databases plus existing replication slots. The source server must have [max\_wal\_senders](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-WAL-SENDERS) configured to a value greater than or equal to the number of specified databases and existing WAL sender processes. ### Warnings If pg\_createsubscriber fails after the target server was promoted, then the data directory is likely not in a state that can be recovered. In such case, creating a new standby server is recommended. pg\_createsubscriber usually starts the target server with different connection settings during transformation. Hence, connections to the target server should fail. Since DDL commands are not replicated by logical replication, avoid executing DDL commands that change the database schema while running pg\_createsubscriber. If the target server has already been converted to logical replica, the DDL commands might not be replicated, which might cause an error. If pg\_createsubscriber fails while processing, objects (publications, replication slots) created on the source server are removed. The removal might fail if the target server cannot connect to the source server. In such a case, a warning message will inform the objects left. If the target server is running, it will be stopped. If the replication is using [primary\_slot\_name](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-PRIMARY-SLOT-NAME) , it will be removed from the source server after the logical replication setup. If the target server is a synchronous replica, transaction commits on the primary might wait for replication while running pg\_createsubscriber. Unless the `--enable-two-phase` switch is specified, pg\_createsubscriber sets up logical replication with two-phase commit disabled. This means that any prepared transactions will be replicated at the time of `COMMIT PREPARED`, without advance preparation. Once setup is complete, you can manually drop and re-create the subscription(s) with the [`two_phase`](https://www.postgresql.org/docs/current/sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-TWO-PHASE) option enabled. pg\_createsubscriber changes the system identifier using pg\_resetwal. It would avoid situations in which the target server might use WAL files from the source server. If the target server has a standby, replication will break and a fresh standby should be created. Replication failures can occur if required WAL files are missing. To prevent this, the source server must set [max\_slot\_wal\_keep\_size](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-SLOT-WAL-KEEP-SIZE) to `-1` to ensure that required WAL files are not prematurely removed. ### How It Works The basic idea is to have a replication start point from the source server and set up a logical replication to start from this point: 1. Start the target server with the specified command-line options. If the target server is already running, pg\_createsubscriber will terminate with an error. 2. Check if the target server can be converted. There are also a few checks on the source server. If any of the prerequisites are not met, pg\_createsubscriber will terminate with an error. 3. Create a publication and replication slot for each specified database on the source server. Each publication is created using [`FOR ALL TABLES`](https://www.postgresql.org/docs/current/sql-createpublication.html#SQL-CREATEPUBLICATION-PARAMS-FOR-ALL-TABLES) . If the `--publication` option is not specified, the publication has the following name pattern: “`pg_createsubscriber_%u_%x`” (parameter: database _`oid`_, random _`int`_). If the `--replication-slot` option is not specified, the replication slot has the following name pattern: “`pg_createsubscriber_%u_%x`” (parameters: database _`oid`_, random _`int`_). These replication slots will be used by the subscriptions in a future step. The last replication slot LSN is used as a stopping point in the [recovery\_target\_lsn](https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-RECOVERY-TARGET-LSN) parameter and by the subscriptions as a replication start point. It guarantees that no transaction will be lost. 4. Write recovery parameters into the target data directory and restart the target server. It specifies an LSN ([recovery\_target\_lsn](https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-RECOVERY-TARGET-LSN) ) of the write-ahead log location up to which recovery will proceed. It also specifies `promote` as the action that the server should take once the recovery target is reached. Additional [recovery parameters](https://www.postgresql.org/docs/current/runtime-config-wal.html#RUNTIME-CONFIG-WAL-RECOVERY-TARGET "19.5.6. Recovery Target") are added to avoid unexpected behavior during the recovery process such as end of the recovery as soon as a consistent state is reached (WAL should be applied until the replication start location) and multiple recovery targets that can cause a failure. This step finishes once the server ends standby mode and is accepting read-write transactions. If `--recovery-timeout` option is set, pg\_createsubscriber terminates if recovery does not end until the given number of seconds. 5. Create a subscription for each specified database on the target server. If the `--subscription` option is not specified, the subscription has the following name pattern: “`pg_createsubscriber_%u_%x`” (parameters: database _`oid`_, random _`int`_). It does not copy existing data from the source server. It does not create a replication slot. Instead, it uses the replication slot that was created in a previous step. The subscription is created but it is not enabled yet. The reason is the replication progress must be set to the replication start point before starting the replication. 6. Drop publications on the target server that were replicated because they were created before the replication start location. It has no use on the subscriber. 7. Set the replication progress to the replication start point for each subscription. When the target server starts the recovery process, it catches up to the replication start point. This is the exact LSN to be used as a initial replication location for each subscription. The replication origin name is obtained since the subscription was created. The replication origin name and the replication start point are used in [`pg_replication_origin_advance()`](https://www.postgresql.org/docs/current/functions-admin.html#PG-REPLICATION-ORIGIN-ADVANCE) to set up the initial replication location. 8. Enable the subscription for each specified database on the target server. The subscription starts applying transactions from the replication start point. 9. If the standby server was using [primary\_slot\_name](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-PRIMARY-SLOT-NAME) , it has no use from now on so drop it. 10. If the standby server contains [failover replication slots](https://www.postgresql.org/docs/current/logicaldecoding-explanation.html#LOGICALDECODING-REPLICATION-SLOTS-SYNCHRONIZATION "47.2.3. Replication Slot Synchronization") , they cannot be synchronized anymore, so drop them. 11. Update the system identifier on the target server. The [pg\_resetwal](https://www.postgresql.org/docs/current/app-pgresetwal.html "pg_resetwal") is run to modify the system identifier. The target server is stopped as a `pg_resetwal` requirement. Examples -------- To create a logical replica for databases `hr` and `finance` from a physical replica at `foo`: $ See Also -------- [pg\_basebackup](https://www.postgresql.org/docs/current/app-pgbasebackup.html "pg_basebackup") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/app-pgcontroldata.html "pg_controldata") | [Up](https://www.postgresql.org/docs/current/reference-server.html "PostgreSQL Server Applications") | [Next](https://www.postgresql.org/docs/current/app-pg-ctl.html "pg_ctl") | | pg\_controldata | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | pg\_ctl | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/app-pgcreatesubscriber.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 55.3. Error Message Style Guide November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/error-style-guide.html "PostgreSQL 18 - 55.3. Error Message Style Guide") ([18](https://www.postgresql.org/docs/18/error-style-guide.html "PostgreSQL 18 - 55.3. Error Message Style Guide") ) / [17](https://www.postgresql.org/docs/17/error-style-guide.html "PostgreSQL 17 - 55.3. Error Message Style Guide") / [16](https://www.postgresql.org/docs/16/error-style-guide.html "PostgreSQL 16 - 55.3. Error Message Style Guide") / [15](https://www.postgresql.org/docs/15/error-style-guide.html "PostgreSQL 15 - 55.3. Error Message Style Guide") / [14](https://www.postgresql.org/docs/14/error-style-guide.html "PostgreSQL 14 - 55.3. Error Message Style Guide") Development Versions: [devel](https://www.postgresql.org/docs/devel/error-style-guide.html "PostgreSQL devel - 55.3. Error Message Style Guide") Unsupported versions: [13](https://www.postgresql.org/docs/13/error-style-guide.html "PostgreSQL 13 - 55.3. Error Message Style Guide") / [12](https://www.postgresql.org/docs/12/error-style-guide.html "PostgreSQL 12 - 55.3. Error Message Style Guide") / [11](https://www.postgresql.org/docs/11/error-style-guide.html "PostgreSQL 11 - 55.3. Error Message Style Guide") / [10](https://www.postgresql.org/docs/10/error-style-guide.html "PostgreSQL 10 - 55.3. Error Message Style Guide") / [9.6](https://www.postgresql.org/docs/9.6/error-style-guide.html "PostgreSQL 9.6 - 55.3. Error Message Style Guide") / [9.5](https://www.postgresql.org/docs/9.5/error-style-guide.html "PostgreSQL 9.5 - 55.3. Error Message Style Guide") / [9.4](https://www.postgresql.org/docs/9.4/error-style-guide.html "PostgreSQL 9.4 - 55.3. Error Message Style Guide") / [9.3](https://www.postgresql.org/docs/9.3/error-style-guide.html "PostgreSQL 9.3 - 55.3. Error Message Style Guide") / [9.2](https://www.postgresql.org/docs/9.2/error-style-guide.html "PostgreSQL 9.2 - 55.3. Error Message Style Guide") / [9.1](https://www.postgresql.org/docs/9.1/error-style-guide.html "PostgreSQL 9.1 - 55.3. Error Message Style Guide") / [9.0](https://www.postgresql.org/docs/9.0/error-style-guide.html "PostgreSQL 9.0 - 55.3. Error Message Style Guide") / [8.4](https://www.postgresql.org/docs/8.4/error-style-guide.html "PostgreSQL 8.4 - 55.3. Error Message Style Guide") / [8.3](https://www.postgresql.org/docs/8.3/error-style-guide.html "PostgreSQL 8.3 - 55.3. Error Message Style Guide") / [8.2](https://www.postgresql.org/docs/8.2/error-style-guide.html "PostgreSQL 8.2 - 55.3. Error Message Style Guide") / [8.1](https://www.postgresql.org/docs/8.1/error-style-guide.html "PostgreSQL 8.1 - 55.3. Error Message Style Guide") / [8.0](https://www.postgresql.org/docs/8.0/error-style-guide.html "PostgreSQL 8.0 - 55.3. Error Message Style Guide") / [7.4](https://www.postgresql.org/docs/7.4/error-style-guide.html "PostgreSQL 7.4 - 55.3. Error Message Style Guide") | 55.3. Error Message Style Guide | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/error-message-reporting.html "55.2. Reporting Errors Within the Server") | [Up](https://www.postgresql.org/docs/current/source.html "Chapter 55. PostgreSQL Coding Conventions") | Chapter 55. PostgreSQL Coding Conventions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/source-conventions.html "55.4. Miscellaneous Coding Conventions") | * * * 55.3. Error Message Style Guide [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE) ---------------------------------------------------------------------------------------------------------------------- This style guide is offered in the hope of maintaining a consistent, user-friendly style throughout all the messages generated by PostgreSQL. ### What Goes Where [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-WHAT-GOES-WHERE) The primary message should be short, factual, and avoid reference to implementation details such as specific function names. “Short” means “should fit on one line under normal conditions”. Use a detail message if needed to keep the primary message short, or if you feel a need to mention implementation details such as the particular system call that failed. Both primary and detail messages should be factual. Use a hint message for suggestions about what to do to fix the problem, especially if the suggestion might not always be applicable. For example, instead of: IpcMemoryCreate: shmget(key=%d, size=%u, 0%o) failed: %m (plus a long addendum that is basically a hint) write: Primary: could not create shared memory segment: %m Detail: Failed syscall was shmget(key=%d, size=%u, 0%o). Hint: The addendum, written as a complete sentence. Rationale: keeping the primary message short helps keep it to the point, and lets clients lay out screen space on the assumption that one line is enough for error messages. Detail and hint messages can be relegated to a verbose mode, or perhaps a pop-up error-details window. Also, details and hints would normally be suppressed from the server log to save space. Reference to implementation details is best avoided since users aren't expected to know the details. ### Formatting [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-FORMATTING) Don't put any specific assumptions about formatting into the message texts. Expect clients and the server log to wrap lines to fit their own needs. In long messages, newline characters (\\n) can be used to indicate suggested paragraph breaks. Don't end a message with a newline. Don't use tabs or other formatting characters. (In error context displays, newlines are automatically added to separate levels of context such as function calls.) Rationale: Messages are not necessarily displayed on terminal-type displays. In GUI displays or browsers these formatting instructions are at best ignored. ### Quotation Marks [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-QUOTATION-MARKS) English text should use double quotes when quoting is appropriate. Text in other languages should consistently use one kind of quotes that is consistent with publishing customs and computer output of other programs. Rationale: The choice of double quotes over single quotes is somewhat arbitrary, but tends to be the preferred use. Some have suggested choosing the kind of quotes depending on the type of object according to SQL conventions (namely, strings single quoted, identifiers double quoted). But this is a language-internal technical issue that many users aren't even familiar with, it won't scale to other kinds of quoted terms, it doesn't translate to other languages, and it's pretty pointless, too. ### Use of Quotes [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-QUOTES) Always use quotes to delimit file names, user-supplied identifiers, configuration variable names, and other variables that might contain words. Do not use them to mark up variables that will not contain words (for example, operator names). There are functions in the backend that will double-quote their own output as needed (for example, `format_type_be()`). Do not put additional quotes around the output of such functions. Rationale: Objects can have names that create ambiguity when embedded in a message. Be consistent about denoting where a plugged-in name starts and ends. But don't clutter messages with unnecessary or duplicate quote marks. ### Grammar and Punctuation [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-GRAMMAR-PUNCTUATION) The rules are different for primary error messages and for detail/hint messages: Primary error messages: Do not capitalize the first letter. Do not end a message with a period. Do not even think about ending a message with an exclamation point. Detail and hint messages: Use complete sentences, and end each with a period. Capitalize the first word of sentences. Put two spaces after the period if another sentence follows (for English text; might be inappropriate in other languages). Error context strings: Do not capitalize the first letter and do not end the string with a period. Context strings should normally not be complete sentences. Rationale: Avoiding punctuation makes it easier for client applications to embed the message into a variety of grammatical contexts. Often, primary messages are not grammatically complete sentences anyway. (And if they're long enough to be more than one sentence, they should be split into primary and detail parts.) However, detail and hint messages are longer and might need to include multiple sentences. For consistency, they should follow complete-sentence style even when there's only one sentence. ### Upper Case vs. Lower Case [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-CASE) Use lower case for message wording, including the first letter of a primary error message. Use upper case for SQL commands and key words if they appear in the message. Rationale: It's easier to make everything look more consistent this way, since some messages are complete sentences and some not. ### Avoid Passive Voice [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-PASSIVE-VOICE) Use the active voice. Use complete sentences when there is an acting subject (“A could not do B”). Use telegram style without subject if the subject would be the program itself; do not use “I” for the program. Rationale: The program is not human. Don't pretend otherwise. ### Present vs. Past Tense [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-TENSE) Use past tense if an attempt to do something failed, but could perhaps succeed next time (perhaps after fixing some problem). Use present tense if the failure is certainly permanent. There is a nontrivial semantic difference between sentences of the form: could not open file "%s": %m and: cannot open file "%s" The first one means that the attempt to open the file failed. The message should give a reason, such as “disk full” or “file doesn't exist”. The past tense is appropriate because next time the disk might not be full anymore or the file in question might exist. The second form indicates that the functionality of opening the named file does not exist at all in the program, or that it's conceptually impossible. The present tense is appropriate because the condition will persist indefinitely. Rationale: Granted, the average user will not be able to draw great conclusions merely from the tense of the message, but since the language provides us with a grammar we should use it correctly. ### Type of the Object [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-OBJECT-TYPE) When citing the name of an object, state what kind of object it is. Rationale: Otherwise no one will know what “foo.bar.baz” refers to. ### Brackets [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-BRACKETS) Square brackets are only to be used (1) in command synopses to denote optional arguments, or (2) to denote an array subscript. Rationale: Anything else does not correspond to widely-known customary usage and will confuse people. ### Assembling Error Messages [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-ERROR-MESSAGES) When a message includes text that is generated elsewhere, embed it in this style: could not open file %s: %m Rationale: It would be difficult to account for all possible error codes to paste this into a single smooth sentence, so some sort of punctuation is needed. Putting the embedded text in parentheses has also been suggested, but it's unnatural if the embedded text is likely to be the most important part of the message, as is often the case. ### Reasons for Errors [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-ERROR-REASONS) Messages should always state the reason why an error occurred. For example: BAD: could not open file %s BETTER: could not open file %s (I/O failure) If no reason is known you better fix the code. ### Function Names [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-FUNCTION-NAMES) Don't include the name of the reporting routine in the error text. We have other mechanisms for finding that out when needed, and for most users it's not helpful information. If the error text doesn't make as much sense without the function name, reword it. BAD: pg\_strtoint32: error in "z": cannot parse "z" BETTER: invalid input syntax for type integer: "z" Avoid mentioning called function names, either; instead say what the code was trying to do: BAD: open() failed: %m BETTER: could not open file %s: %m If it really seems necessary, mention the system call in the detail message. (In some cases, providing the actual values passed to the system call might be appropriate information for the detail message.) Rationale: Users don't know what all those functions do. ### Tricky Words to Avoid [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-TRICKY-WORDS) **Unable.**  “Unable” is nearly the passive voice. Better use “cannot” or “could not”, as appropriate. **Bad.**  Error messages like “bad result” are really hard to interpret intelligently. It's better to write why the result is “bad”, e.g., “invalid format”. **Illegal.**  “Illegal” stands for a violation of the law, the rest is “invalid”. Better yet, say why it's invalid. **Unknown.**  Try to avoid “unknown”. Consider “error: unknown response”. If you don't know what the response is, how do you know it's erroneous? “Unrecognized” is often a better choice. Also, be sure to include the value being complained of. BAD: unknown node type BETTER: unrecognized node type: 42 **Find vs. Exists.**  If the program uses a nontrivial algorithm to locate a resource (e.g., a path search) and that algorithm fails, it is fair to say that the program couldn't “find” the resource. If, on the other hand, the expected location of the resource is known but the program cannot access it there then say that the resource doesn't “exist”. Using “find” in this case sounds weak and confuses the issue. **May vs. Can vs. Might.**  “May” suggests permission (e.g., "You may borrow my rake."), and has little use in documentation or error messages. “Can” suggests ability (e.g., "I can lift that log."), and “might” suggests possibility (e.g., "It might rain today."). Using the proper word clarifies meaning and assists translation. **Contractions.**  Avoid contractions, like “can't”; use “cannot” instead. **Non-negative.**  Avoid “non-negative” as it is ambiguous about whether it accepts zero. It's better to use “greater than zero” or “greater than or equal to zero”. ### Proper Spelling [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-SPELLING) Spell out words in full. For instance, avoid: * spec * stats * parens * auth * xact Rationale: This will improve consistency. ### Localization [#](https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-LOCALIZATION) Keep in mind that error message texts need to be translated into other languages. Follow the guidelines in [Section 56.2.2](https://www.postgresql.org/docs/current/nls-programmer.html#NLS-GUIDELINES "56.2.2. Message-Writing Guidelines") to avoid making life difficult for translators. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/error-message-reporting.html "55.2. Reporting Errors Within the Server") | [Up](https://www.postgresql.org/docs/current/source.html "Chapter 55. PostgreSQL Coding Conventions") | [Next](https://www.postgresql.org/docs/current/source-conventions.html "55.4. Miscellaneous Coding Conventions") | | 55.2. Reporting Errors Within the Server | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 55.4. Miscellaneous Coding Conventions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/error-style-guide.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 46. Background Worker Processes November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/bgworker.html "PostgreSQL 18 - Chapter 46. Background Worker Processes") ([18](https://www.postgresql.org/docs/18/bgworker.html "PostgreSQL 18 - Chapter 46. Background Worker Processes") ) / [17](https://www.postgresql.org/docs/17/bgworker.html "PostgreSQL 17 - Chapter 46. Background Worker Processes") / [16](https://www.postgresql.org/docs/16/bgworker.html "PostgreSQL 16 - Chapter 46. Background Worker Processes") / [15](https://www.postgresql.org/docs/15/bgworker.html "PostgreSQL 15 - Chapter 46. Background Worker Processes") / [14](https://www.postgresql.org/docs/14/bgworker.html "PostgreSQL 14 - Chapter 46. Background Worker Processes") Development Versions: [devel](https://www.postgresql.org/docs/devel/bgworker.html "PostgreSQL devel - Chapter 46. Background Worker Processes") Unsupported versions: [13](https://www.postgresql.org/docs/13/bgworker.html "PostgreSQL 13 - Chapter 46. Background Worker Processes") / [12](https://www.postgresql.org/docs/12/bgworker.html "PostgreSQL 12 - Chapter 46. Background Worker Processes") / [11](https://www.postgresql.org/docs/11/bgworker.html "PostgreSQL 11 - Chapter 46. Background Worker Processes") / [10](https://www.postgresql.org/docs/10/bgworker.html "PostgreSQL 10 - Chapter 46. Background Worker Processes") / [9.6](https://www.postgresql.org/docs/9.6/bgworker.html "PostgreSQL 9.6 - Chapter 46. Background Worker Processes") / [9.5](https://www.postgresql.org/docs/9.5/bgworker.html "PostgreSQL 9.5 - Chapter 46. Background Worker Processes") / [9.4](https://www.postgresql.org/docs/9.4/bgworker.html "PostgreSQL 9.4 - Chapter 46. Background Worker Processes") / [9.3](https://www.postgresql.org/docs/9.3/bgworker.html "PostgreSQL 9.3 - Chapter 46. Background Worker Processes") | Chapter 46. Background Worker Processes | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-start-transaction.html "SPI_start_transaction") | [Up](https://www.postgresql.org/docs/current/server-programming.html "Part V. Server Programming") | Part V. Server Programming | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/logicaldecoding.html "Chapter 47. Logical Decoding") | * * * Chapter 46. Background Worker Processes --------------------------------------- PostgreSQL can be extended to run user-supplied code in separate processes. Such processes are started, stopped and monitored by `postgres`, which permits them to have a lifetime closely linked to the server's status. These processes are attached to PostgreSQL's shared memory area and have the option to connect to databases internally; they can also run multiple transactions serially, just like a regular client-connected server process. Also, by linking to libpq they can connect to the server and behave like a regular client application. ### Warning There are considerable robustness and security risks in using background worker processes because, being written in the `C` language, they have unrestricted access to data. Administrators wishing to enable modules that include background worker processes should exercise extreme caution. Only carefully audited modules should be permitted to run background worker processes. Background workers can be initialized at the time that PostgreSQL is started by including the module name in `shared_preload_libraries`. A module wishing to run a background worker can register it by calling ``RegisterBackgroundWorker(`BackgroundWorker` *_`worker`_)`` from its `_PG_init()` function. Background workers can also be started after the system is up and running by calling ``RegisterDynamicBackgroundWorker(`BackgroundWorker` *_`worker`_, `BackgroundWorkerHandle` **_`handle`_)``. Unlike `RegisterBackgroundWorker`, which can only be called from within the postmaster process, `RegisterDynamicBackgroundWorker` must be called from a regular backend or another background worker. The structure `BackgroundWorker` is defined thus: typedef void (\*bgworker\_main\_type)(Datum main\_arg); typedef struct BackgroundWorker { char bgw\_name\[BGW\_MAXLEN\]; char bgw\_type\[BGW\_MAXLEN\]; int bgw\_flags; BgWorkerStartTime bgw\_start\_time; int bgw\_restart\_time; /\* in seconds, or BGW\_NEVER\_RESTART \*/ char bgw\_library\_name\[MAXPGPATH\]; char bgw\_function\_name\[BGW\_MAXLEN\]; Datum bgw\_main\_arg; char bgw\_extra\[BGW\_EXTRALEN\]; pid\_t bgw\_notify\_pid; } BackgroundWorker; `bgw_name` and `bgw_type` are strings to be used in log messages, process listings and similar contexts. `bgw_type` should be the same for all background workers of the same type, so that it is possible to group such workers in a process listing, for example. `bgw_name` on the other hand can contain additional information about the specific process. (Typically, the string for `bgw_name` will contain the type somehow, but that is not strictly required.) `bgw_flags` is a bitwise-or'd bit mask indicating the capabilities that the module wants. Possible values are: `BGWORKER_SHMEM_ACCESS` Requests shared memory access. This flag is required. `BGWORKER_BACKEND_DATABASE_CONNECTION` Requests the ability to establish a database connection through which it can later run transactions and queries. A background worker using `BGWORKER_BACKEND_DATABASE_CONNECTION` to connect to a database must also attach shared memory using `BGWORKER_SHMEM_ACCESS`, or worker start-up will fail. `bgw_start_time` is the server state during which `postgres` should start the process; it can be one of `BgWorkerStart_PostmasterStart` (start as soon as `postgres` itself has finished its own initialization; processes requesting this are not eligible for database connections), `BgWorkerStart_ConsistentState` (start as soon as a consistent state has been reached in a hot standby, allowing processes to connect to databases and run read-only queries), and `BgWorkerStart_RecoveryFinished` (start as soon as the system has entered normal read-write state). Note the last two values are equivalent in a server that's not a hot standby. Note that this setting only indicates when the processes are to be started; they do not stop when a different state is reached. `bgw_restart_time` is the interval, in seconds, that `postgres` should wait before restarting the process in the event that it crashes. It can be any positive value, or `BGW_NEVER_RESTART`, indicating not to restart the process in case of a crash. `bgw_library_name` is the name of a library in which the initial entry point for the background worker should be sought. The named library will be dynamically loaded by the worker process and `bgw_function_name` will be used to identify the function to be called. If calling a function in the core code, this must be set to `"postgres"`. `bgw_function_name` is the name of the function to use as the initial entry point for the new background worker. If this function is in a dynamically loaded library, it must be marked `PGDLLEXPORT` (and not `static`). `bgw_main_arg` is the `Datum` argument to the background worker main function. This main function should take a single argument of type `Datum` and return `void`. `bgw_main_arg` will be passed as the argument. In addition, the global variable `MyBgworkerEntry` points to a copy of the `BackgroundWorker` structure passed at registration time; the worker may find it helpful to examine this structure. On Windows (and anywhere else where `EXEC_BACKEND` is defined) or in dynamic background workers it is not safe to pass a `Datum` by reference, only by value. If an argument is required, it is safest to pass an int32 or other small value and use that as an index into an array allocated in shared memory. If a value like a `cstring` or `text` is passed then the pointer won't be valid from the new background worker process. `bgw_extra` can contain extra data to be passed to the background worker. Unlike `bgw_main_arg`, this data is not passed as an argument to the worker's main function, but it can be accessed via `MyBgworkerEntry`, as discussed above. `bgw_notify_pid` is the PID of a PostgreSQL backend process to which the postmaster should send `SIGUSR1` when the process is started or exits. It should be 0 for workers registered at postmaster startup time, or when the backend registering the worker does not wish to wait for the worker to start up. Otherwise, it should be initialized to `MyProcPid`. Once running, the process can connect to a database by calling ``BackgroundWorkerInitializeConnection(_`char *dbname`_, _`char *username`_, _`uint32 flags`_)`` or ``BackgroundWorkerInitializeConnectionByOid(_`Oid dboid`_, _`Oid useroid`_, _`uint32 flags`_)``. This allows the process to run transactions and queries using the `SPI` interface. If `dbname` is NULL or `dboid` is `InvalidOid`, the session is not connected to any particular database, but shared catalogs can be accessed. If `username` is NULL or `useroid` is `InvalidOid`, the process will run as the superuser created during `initdb`. If `BGWORKER_BYPASS_ALLOWCONN` is specified as `flags` it is possible to bypass the restriction to connect to databases not allowing user connections. If `BGWORKER_BYPASS_ROLELOGINCHECK` is specified as `flags` it is possible to bypass the login check for the role used to connect to databases. A background worker can only call one of these two functions, and only once. It is not possible to switch databases. Signals are initially blocked when control reaches the background worker's main function, and must be unblocked by it; this is to allow the process to customize its signal handlers, if necessary. Signals can be unblocked in the new process by calling `BackgroundWorkerUnblockSignals` and blocked by calling `BackgroundWorkerBlockSignals`. If `bgw_restart_time` for a background worker is configured as `BGW_NEVER_RESTART`, or if it exits with an exit code of 0 or is terminated by `TerminateBackgroundWorker`, it will be automatically unregistered by the postmaster on exit. Otherwise, it will be restarted after the time period configured via `bgw_restart_time`, or immediately if the postmaster reinitializes the cluster due to a backend failure. Backends which need to suspend execution only temporarily should use an interruptible sleep rather than exiting; this can be achieved by calling `WaitLatch()`. Make sure the `WL_POSTMASTER_DEATH` flag is set when calling that function, and verify the return code for a prompt exit in the emergency case that `postgres` itself has terminated. When a background worker is registered using the `RegisterDynamicBackgroundWorker` function, it is possible for the backend performing the registration to obtain information regarding the status of the worker. Backends wishing to do this should pass the address of a `BackgroundWorkerHandle *` as the second argument to `RegisterDynamicBackgroundWorker`. If the worker is successfully registered, this pointer will be initialized with an opaque handle that can subsequently be passed to ``GetBackgroundWorkerPid(_`BackgroundWorkerHandle *`_, _`pid_t *`_)`` or ``TerminateBackgroundWorker(_`BackgroundWorkerHandle *`_)``. `GetBackgroundWorkerPid` can be used to poll the status of the worker: a return value of `BGWH_NOT_YET_STARTED` indicates that the worker has not yet been started by the postmaster; `BGWH_STOPPED` indicates that it has been started but is no longer running; and `BGWH_STARTED` indicates that it is currently running. In this last case, the PID will also be returned via the second argument. `TerminateBackgroundWorker` causes the postmaster to send `SIGTERM` to the worker if it is running, and to unregister it as soon as it is not. In some cases, a process which registers a background worker may wish to wait for the worker to start up. This can be accomplished by initializing `bgw_notify_pid` to `MyProcPid` and then passing the `BackgroundWorkerHandle *` obtained at registration time to ``WaitForBackgroundWorkerStartup(_`BackgroundWorkerHandle *handle`_, _`pid_t *`_)`` function. This function will block until the postmaster has attempted to start the background worker, or until the postmaster dies. If the background worker is running, the return value will be `BGWH_STARTED`, and the PID will be written to the provided address. Otherwise, the return value will be `BGWH_STOPPED` or `BGWH_POSTMASTER_DIED`. A process can also wait for a background worker to shut down, by using the ``WaitForBackgroundWorkerShutdown(_`BackgroundWorkerHandle *handle`_)`` function and passing the `BackgroundWorkerHandle *` obtained at registration. This function will block until the background worker exits, or postmaster dies. When the background worker exits, the return value is `BGWH_STOPPED`, if postmaster dies it will return `BGWH_POSTMASTER_DIED`. Background workers can send asynchronous notification messages, either by using the `NOTIFY` command via SPI, or directly via `Async_Notify()`. Such notifications will be sent at transaction commit. Background workers should not register to receive asynchronous notifications with the `LISTEN` command, as there is no infrastructure for a worker to consume such notifications. The `src/test/modules/worker_spi` module contains a working example, which demonstrates some useful techniques. The maximum number of registered background workers is limited by [max\_worker\_processes](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES) . * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-start-transaction.html "SPI_start_transaction") | [Up](https://www.postgresql.org/docs/current/server-programming.html "Part V. Server Programming") | [Next](https://www.postgresql.org/docs/current/logicaldecoding.html "Chapter 47. Logical Decoding") | | SPI\_start\_transaction | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Chapter 47. Logical Decoding | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/bgworker.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 36.18. Extension Building Infrastructure November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/extend-pgxs.html "PostgreSQL 18 - 36.18. Extension Building Infrastructure") ([18](https://www.postgresql.org/docs/18/extend-pgxs.html "PostgreSQL 18 - 36.18. Extension Building Infrastructure") ) / [17](https://www.postgresql.org/docs/17/extend-pgxs.html "PostgreSQL 17 - 36.18. Extension Building Infrastructure") / [16](https://www.postgresql.org/docs/16/extend-pgxs.html "PostgreSQL 16 - 36.18. Extension Building Infrastructure") / [15](https://www.postgresql.org/docs/15/extend-pgxs.html "PostgreSQL 15 - 36.18. Extension Building Infrastructure") / [14](https://www.postgresql.org/docs/14/extend-pgxs.html "PostgreSQL 14 - 36.18. Extension Building Infrastructure") Development Versions: [devel](https://www.postgresql.org/docs/devel/extend-pgxs.html "PostgreSQL devel - 36.18. Extension Building Infrastructure") Unsupported versions: [13](https://www.postgresql.org/docs/13/extend-pgxs.html "PostgreSQL 13 - 36.18. Extension Building Infrastructure") / [12](https://www.postgresql.org/docs/12/extend-pgxs.html "PostgreSQL 12 - 36.18. Extension Building Infrastructure") / [11](https://www.postgresql.org/docs/11/extend-pgxs.html "PostgreSQL 11 - 36.18. Extension Building Infrastructure") / [10](https://www.postgresql.org/docs/10/extend-pgxs.html "PostgreSQL 10 - 36.18. Extension Building Infrastructure") / [9.6](https://www.postgresql.org/docs/9.6/extend-pgxs.html "PostgreSQL 9.6 - 36.18. Extension Building Infrastructure") / [9.5](https://www.postgresql.org/docs/9.5/extend-pgxs.html "PostgreSQL 9.5 - 36.18. Extension Building Infrastructure") / [9.4](https://www.postgresql.org/docs/9.4/extend-pgxs.html "PostgreSQL 9.4 - 36.18. Extension Building Infrastructure") / [9.3](https://www.postgresql.org/docs/9.3/extend-pgxs.html "PostgreSQL 9.3 - 36.18. Extension Building Infrastructure") / [9.2](https://www.postgresql.org/docs/9.2/extend-pgxs.html "PostgreSQL 9.2 - 36.18. Extension Building Infrastructure") / [9.1](https://www.postgresql.org/docs/9.1/extend-pgxs.html "PostgreSQL 9.1 - 36.18. Extension Building Infrastructure") | 36.18. Extension Building Infrastructure | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/extend-extensions.html "36.17. Packaging Related Objects into an Extension") | [Up](https://www.postgresql.org/docs/18/extend.html "Chapter 36. Extending SQL") | Chapter 36. Extending SQL | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/triggers.html "Chapter 37. Triggers") | * * * 36.18. Extension Building Infrastructure [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS) -------------------------------------------------------------------------------------------------------------- If you are thinking about distributing your PostgreSQL extension modules, setting up a portable build system for them can be fairly difficult. Therefore the PostgreSQL installation provides a build infrastructure for extensions, called PGXS, so that simple extension modules can be built simply against an already installed server. PGXS is mainly intended for extensions that include C code, although it can be used for pure-SQL extensions too. Note that PGXS is not intended to be a universal build system framework that can be used to build any software interfacing to PostgreSQL; it simply automates common build rules for simple server extension modules. For more complicated packages, you might need to write your own build system. To use the PGXS infrastructure for your extension, you must write a simple makefile. In the makefile, you need to set some variables and include the global PGXS makefile. Here is an example that builds an extension module named `isbn_issn`, consisting of a shared library containing some C code, an extension control file, an SQL script, an include file (only needed if other modules might need to access the extension functions without going via SQL), and a documentation text file: MODULES = isbn\_issn EXTENSION = isbn\_issn DATA = isbn\_issn--1.0.sql DOCS = README.isbn\_issn HEADERS\_isbn\_issn = isbn\_issn.h PG\_CONFIG = pg\_config PGXS := $(shell $(PG\_CONFIG) --pgxs) include $(PGXS) The last three lines should always be the same. Earlier in the file, you assign variables or add custom make rules. Set one of these three variables to specify what is built: `MODULES` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-MODULES) list of shared-library objects to be built from source files with same stem (do not include library suffixes in this list) `MODULE_big` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-MODULE-BIG) a shared library to build from multiple source files (list object files in `OBJS`) `PROGRAM` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-PROGRAM) an executable program to build (list object files in `OBJS`) The following variables can also be set: `EXTENSION` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-EXTENSION) extension name(s); for each name you must provide an ``_`extension`_.control`` file, which will be installed into ``_`prefix`_/share/extension`` `MODULEDIR` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-MODULEDIR) subdirectory of ``_`prefix`_/share`` into which DATA and DOCS files should be installed (if not set, default is `extension` if `EXTENSION` is set, or `contrib` if not) `DATA` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-DATA) random files to install into ``_`prefix`_/share/$MODULEDIR`` `DATA_built` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-DATA-BUILT) random files to install into ``_`prefix`_/share/$MODULEDIR``, which need to be built first `DATA_TSEARCH` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-DATA-TSEARCH) random files to install under ``_`prefix`_/share/tsearch_data`` `DOCS` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-DOCS) random files to install under ``_`prefix`_/doc/$MODULEDIR`` `HEADERS` `HEADERS_built` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-HEADERS) Files to (optionally build and) install under ``_`prefix`_/include/server/$MODULEDIR/$MODULE_big``. Unlike `DATA_built`, files in `HEADERS_built` are not removed by the `clean` target; if you want them removed, also add them to `EXTRA_CLEAN` or add your own rules to do it. `HEADERS_$MODULE` `HEADERS_built_$MODULE` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-HEADERS-MODULE) Files to install (after building if specified) under ``_`prefix`_/include/server/$MODULEDIR/$MODULE``, where `$MODULE` must be a module name used in `MODULES` or `MODULE_big`. Unlike `DATA_built`, files in `HEADERS_built_$MODULE` are not removed by the `clean` target; if you want them removed, also add them to `EXTRA_CLEAN` or add your own rules to do it. It is legal to use both variables for the same module, or any combination, unless you have two module names in the `MODULES` list that differ only by the presence of a prefix `built_`, which would cause ambiguity. In that (hopefully unlikely) case, you should use only the `HEADERS_built_$MODULE` variables. `SCRIPTS` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-SCRIPTS) script files (not binaries) to install into ``_`prefix`_/bin`` `SCRIPTS_built` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-SCRIPTS-BUILT) script files (not binaries) to install into ``_`prefix`_/bin``, which need to be built first `REGRESS` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-REGRESS) list of regression test cases (without suffix), see below `REGRESS_OPTS` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-REGRESS-OPTS) additional switches to pass to pg\_regress `ISOLATION` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-ISOLATION) list of isolation test cases, see below for more details `ISOLATION_OPTS` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-ISOLATION-OPTS) additional switches to pass to pg\_isolation\_regress `TAP_TESTS` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-TAP-TESTS) switch defining if TAP tests need to be run, see below `NO_INSTALL` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-NO-INSTALL) don't define an `install` target, useful for test modules that don't need their build products to be installed `NO_INSTALLCHECK` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-NO-INSTALLCHECK) don't define an `installcheck` target, useful e.g., if tests require special configuration, or don't use pg\_regress `EXTRA_CLEAN` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-EXTRA-CLEAN) extra files to remove in `make clean` `PG_CPPFLAGS` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-PG-CPPFLAGS) will be prepended to `CPPFLAGS` `PG_CFLAGS` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-PG-CFLAGS) will be appended to `CFLAGS` `PG_CXXFLAGS` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-PG-CXXFLAGS) will be appended to `CXXFLAGS` `PG_LDFLAGS` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-PG-LDFLAGS) will be prepended to `LDFLAGS` `PG_LIBS` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-PG-LIBS) will be added to `PROGRAM` link line `SHLIB_LINK` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-SHLIB-LINK) will be added to `MODULE_big` link line `PG_CONFIG` [#](https://www.postgresql.org/docs/18/extend-pgxs.html#EXTEND-PGXS-PG-CONFIG) path to pg\_config program for the PostgreSQL installation to build against (typically just `pg_config` to use the first one in your `PATH`) Put this makefile as `Makefile` in the directory which holds your extension. Then you can do `make` to compile, and then `make install` to install your module. By default, the extension is compiled and installed for the PostgreSQL installation that corresponds to the first `pg_config` program found in your `PATH`. You can use a different installation by setting `PG_CONFIG` to point to its `pg_config` program, either within the makefile or on the `make` command line. You can select a separate directory prefix in which to install your extension's files, by setting the `make` variable `prefix` when executing `make install` like so: make install prefix=/usr/local/postgresql This will install the extension control and SQL files into `/usr/local/postgresql/share` and the shared modules into `/usr/local/postgresql/lib`. If the prefix does not include the strings `postgres` or `pgsql`, such as make install prefix=/usr/local/extras then `postgresql` will be appended to the directory names, installing the control and SQL files into `/usr/local/extras/share/postgresql/extension` and the shared modules into `/usr/local/extras/lib/postgresql`. Either way, you'll need to set [extension\_control\_path](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-EXTENSION-CONTROL-PATH) and [dynamic\_library\_path](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH) to enable the PostgreSQL server to find the files: extension\_control\_path = '/usr/local/extras/share/postgresql:$system' dynamic\_library\_path = '/usr/local/extras/lib/postgresql:$libdir' You can also run `make` in a directory outside the source tree of your extension, if you want to keep the build directory separate. This procedure is also called a _VPATH_ build. Here's how: mkdir build\_dir cd build\_dir make -f /path/to/extension/source/tree/Makefile make -f /path/to/extension/source/tree/Makefile install Alternatively, you can set up a directory for a VPATH build in a similar way to how it is done for the core code. One way to do this is using the core script `config/prep_buildtree`. Once this has been done you can build by setting the `make` variable `VPATH` like this: make VPATH=/path/to/extension/source/tree make VPATH=/path/to/extension/source/tree install This procedure can work with a greater variety of directory layouts. The scripts listed in the `REGRESS` variable are used for regression testing of your module, which can be invoked by `make installcheck` after doing `make install`. For this to work you must have a running PostgreSQL server. The script files listed in `REGRESS` must appear in a subdirectory named `sql/` in your extension's directory. These files must have extension `.sql`, which must not be included in the `REGRESS` list in the makefile. For each test there should also be a file containing the expected output in a subdirectory named `expected/`, with the same stem and extension `.out`. `make installcheck` executes each test script with psql, and compares the resulting output to the matching expected file. Any differences will be written to the file `regression.diffs` in `diff -c` format. Note that trying to run a test that is missing its expected file will be reported as “trouble”, so make sure you have all expected files. The scripts listed in the `ISOLATION` variable are used for tests stressing behavior of concurrent session with your module, which can be invoked by `make installcheck` after doing `make install`. For this to work you must have a running PostgreSQL server. The script files listed in `ISOLATION` must appear in a subdirectory named `specs/` in your extension's directory. These files must have extension `.spec`, which must not be included in the `ISOLATION` list in the makefile. For each test there should also be a file containing the expected output in a subdirectory named `expected/`, with the same stem and extension `.out`. `make installcheck` executes each test script, and compares the resulting output to the matching expected file. Any differences will be written to the file `output_iso/regression.diffs` in `diff -c` format. Note that trying to run a test that is missing its expected file will be reported as “trouble”, so make sure you have all expected files. `TAP_TESTS` enables the use of TAP tests. Data from each run is present in a subdirectory named `tmp_check/`. See also [Section 31.4](https://www.postgresql.org/docs/18/regress-tap.html "31.4. TAP Tests") for more details. ### Tip The easiest way to create the expected files is to create empty files, then do a test run (which will of course report differences). Inspect the actual result files found in the `results/` directory (for tests in `REGRESS`), or `output_iso/results/` directory (for tests in `ISOLATION`), then copy them to `expected/` if they match what you expect from the test. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/extend-extensions.html "36.17. Packaging Related Objects into an Extension") | [Up](https://www.postgresql.org/docs/18/extend.html "Chapter 36. Extending SQL") | [Next](https://www.postgresql.org/docs/18/triggers.html "Chapter 37. Triggers") | | 36.17. Packaging Related Objects into an Extension | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | Chapter 37. Triggers | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/extend-pgxs.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 38.3. A Complete Event Trigger Example November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/event-trigger-example.html "PostgreSQL 18 - 38.3. A Complete Event Trigger Example") ([18](https://www.postgresql.org/docs/18/event-trigger-example.html "PostgreSQL 18 - 38.3. A Complete Event Trigger Example") ) / [17](https://www.postgresql.org/docs/17/event-trigger-example.html "PostgreSQL 17 - 38.3. A Complete Event Trigger Example") / [16](https://www.postgresql.org/docs/16/event-trigger-example.html "PostgreSQL 16 - 38.3. A Complete Event Trigger Example") / [15](https://www.postgresql.org/docs/15/event-trigger-example.html "PostgreSQL 15 - 38.3. A Complete Event Trigger Example") / [14](https://www.postgresql.org/docs/14/event-trigger-example.html "PostgreSQL 14 - 38.3. A Complete Event Trigger Example") Development Versions: [devel](https://www.postgresql.org/docs/devel/event-trigger-example.html "PostgreSQL devel - 38.3. A Complete Event Trigger Example") Unsupported versions: [13](https://www.postgresql.org/docs/13/event-trigger-example.html "PostgreSQL 13 - 38.3. A Complete Event Trigger Example") / [12](https://www.postgresql.org/docs/12/event-trigger-example.html "PostgreSQL 12 - 38.3. A Complete Event Trigger Example") / [11](https://www.postgresql.org/docs/11/event-trigger-example.html "PostgreSQL 11 - 38.3. A Complete Event Trigger Example") / [10](https://www.postgresql.org/docs/10/event-trigger-example.html "PostgreSQL 10 - 38.3. A Complete Event Trigger Example") / [9.6](https://www.postgresql.org/docs/9.6/event-trigger-example.html "PostgreSQL 9.6 - 38.3. A Complete Event Trigger Example") / [9.5](https://www.postgresql.org/docs/9.5/event-trigger-example.html "PostgreSQL 9.5 - 38.3. A Complete Event Trigger Example") / [9.4](https://www.postgresql.org/docs/9.4/event-trigger-example.html "PostgreSQL 9.4 - 38.3. A Complete Event Trigger Example") / [9.3](https://www.postgresql.org/docs/9.3/event-trigger-example.html "PostgreSQL 9.3 - 38.3. A Complete Event Trigger Example") | 38.3. A Complete Event Trigger Example | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/event-trigger-interface.html "38.2. Writing Event Trigger Functions in C") | [Up](https://www.postgresql.org/docs/18/event-triggers.html "Chapter 38. Event Triggers") | Chapter 38. Event Triggers | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/event-trigger-table-rewrite-example.html "38.4. A Table Rewrite Event Trigger Example") | * * * 38.3. A Complete Event Trigger Example [#](https://www.postgresql.org/docs/18/event-trigger-example.html#EVENT-TRIGGER-EXAMPLE) -------------------------------------------------------------------------------------------------------------------------------- Here is a very simple example of an event trigger function written in C. (Examples of triggers written in procedural languages can be found in the documentation of the procedural languages.) The function `noddl` raises an exception each time it is called. The event trigger definition associated the function with the `ddl_command_start` event. The effect is that all DDL commands (with the exceptions mentioned in [Section 38.1](https://www.postgresql.org/docs/18/event-trigger-definition.html "38.1. Overview of Event Trigger Behavior") ) are prevented from running. This is the source code of the trigger function: #include "postgres.h" #include "commands/event\_trigger.h" #include "fmgr.h" PG\_MODULE\_MAGIC; PG\_FUNCTION\_INFO\_V1(noddl); Datum noddl(PG\_FUNCTION\_ARGS) { EventTriggerData \*trigdata; if (!CALLED\_AS\_EVENT\_TRIGGER(fcinfo)) /\* internal error \*/ elog(ERROR, "not fired by event trigger manager"); trigdata = (EventTriggerData \*) fcinfo->context; ereport(ERROR, (errcode(ERRCODE\_INSUFFICIENT\_PRIVILEGE), errmsg("command \\"%s\\" denied", GetCommandTagName(trigdata->tag)))); PG\_RETURN\_NULL(); } After you have compiled the source code (see [Section 36.10.5](https://www.postgresql.org/docs/18/xfunc-c.html#DFUNC "36.10.5. Compiling and Linking Dynamically-Loaded Functions") ), declare the function and the triggers: CREATE FUNCTION noddl() RETURNS event\_trigger AS 'noddl' LANGUAGE C; CREATE EVENT TRIGGER noddl ON ddl\_command\_start EXECUTE FUNCTION noddl(); Now you can test the operation of the trigger: \=# \\dy List of event triggers Name | Event | Owner | Enabled | Function | Tags -------+-------------------+-------+---------+----------+------ noddl | ddl\_command\_start | dim | enabled | noddl | (1 row) =# CREATE TABLE foo(id serial); ERROR: command "CREATE TABLE" denied In this situation, in order to be able to run some DDL commands when you need to do so, you have to either drop the event trigger or disable it. It can be convenient to disable the trigger for only the duration of a transaction: BEGIN; ALTER EVENT TRIGGER noddl DISABLE; CREATE TABLE foo (id serial); ALTER EVENT TRIGGER noddl ENABLE; COMMIT; (Recall that DDL commands on event triggers themselves are not affected by event triggers.) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/event-trigger-interface.html "38.2. Writing Event Trigger Functions in C") | [Up](https://www.postgresql.org/docs/18/event-triggers.html "Chapter 38. Event Triggers") | [Next](https://www.postgresql.org/docs/18/event-trigger-table-rewrite-example.html "38.4. A Table Rewrite Event Trigger Example") | | 38.2. Writing Event Trigger Functions in C | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 38.4. A Table Rewrite Event Trigger Example | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/event-trigger-example.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.5. pg_backend_memory_contexts November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-backend-memory-contexts.html "PostgreSQL 18 - 53.5. pg_backend_memory_contexts") ([18](https://www.postgresql.org/docs/18/view-pg-backend-memory-contexts.html "PostgreSQL 18 - 53.5. pg_backend_memory_contexts") ) / [17](https://www.postgresql.org/docs/17/view-pg-backend-memory-contexts.html "PostgreSQL 17 - 53.5. pg_backend_memory_contexts") / [16](https://www.postgresql.org/docs/16/view-pg-backend-memory-contexts.html "PostgreSQL 16 - 53.5. pg_backend_memory_contexts") / [15](https://www.postgresql.org/docs/15/view-pg-backend-memory-contexts.html "PostgreSQL 15 - 53.5. pg_backend_memory_contexts") / [14](https://www.postgresql.org/docs/14/view-pg-backend-memory-contexts.html "PostgreSQL 14 - 53.5. pg_backend_memory_contexts") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-backend-memory-contexts.html "PostgreSQL devel - 53.5. pg_backend_memory_contexts") | 53.5. `pg_backend_memory_contexts` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-available-extension-versions.html "53.4. pg_available_extension_versions") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/view-pg-config.html "53.6. pg_config") | * * * 53.5. `pg_backend_memory_contexts` [#](https://www.postgresql.org/docs/18/view-pg-backend-memory-contexts.html#VIEW-PG-BACKEND-MEMORY-CONTEXTS) ------------------------------------------------------------------------------------------------------------------------------------------------ The view `pg_backend_memory_contexts` displays all the memory contexts of the server process attached to the current session. `pg_backend_memory_contexts` contains one row for each memory context. **Table 53.5. `pg_backend_memory_contexts` Columns** | Column Type

Description | | --- | | `name` `text`

Name of the memory context | | `ident` `text`

Identification information of the memory context. This field is truncated at 1024 bytes | | `type` `text`

Type of the memory context | | `level` `int4`

The 1-based level of the context in the memory context hierarchy. The level of a context also shows the position of that context in the `path` column. | | `path` `int4[]`

Array of transient numerical identifiers to describe the memory context hierarchy. The first element is for `TopMemoryContext`, subsequent elements contain intermediate parents and the final element contains the identifier for the current context. | | `total_bytes` `int8`

Total bytes allocated for this memory context | | `total_nblocks` `int8`

Total number of blocks allocated for this memory context | | `free_bytes` `int8`

Free space in bytes | | `free_chunks` `int8`

Total number of free chunks | | `used_bytes` `int8`

Used space in bytes | By default, the `pg_backend_memory_contexts` view can be read only by superusers or roles with the privileges of the `pg_read_all_stats` role. Since memory contexts are created and destroyed during the running of a query, the identifiers stored in the `path` column can be unstable between multiple invocations of the view in the same query. The example below demonstrates an effective usage of this column and calculates the total number of bytes used by `CacheMemoryContext` and all of its children: WITH memory\_contexts AS ( SELECT \* FROM pg\_backend\_memory\_contexts ) SELECT sum(c1.total\_bytes) FROM memory\_contexts c1, memory\_contexts c2 WHERE c2.name = 'CacheMemoryContext' AND c1.path\[c2.level\] = c2.path\[c2.level\]; The [Common Table Expression](https://www.postgresql.org/docs/18/queries-with.html "7.8. WITH Queries (Common Table Expressions)") is used to ensure the context IDs in the `path` column match between both evaluations of the view. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-available-extension-versions.html "53.4. pg_available_extension_versions") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/18/view-pg-config.html "53.6. pg_config") | | 53.4. `pg_available_extension_versions` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 53.6. `pg_config` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-backend-memory-contexts.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 42.2. PL/Tcl Functions and Arguments November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/pltcl-functions.html "PostgreSQL 18 - 42.2. PL/Tcl Functions and Arguments") ([18](https://www.postgresql.org/docs/18/pltcl-functions.html "PostgreSQL 18 - 42.2. PL/Tcl Functions and Arguments") ) / [17](https://www.postgresql.org/docs/17/pltcl-functions.html "PostgreSQL 17 - 42.2. PL/Tcl Functions and Arguments") / [16](https://www.postgresql.org/docs/16/pltcl-functions.html "PostgreSQL 16 - 42.2. PL/Tcl Functions and Arguments") / [15](https://www.postgresql.org/docs/15/pltcl-functions.html "PostgreSQL 15 - 42.2. PL/Tcl Functions and Arguments") / [14](https://www.postgresql.org/docs/14/pltcl-functions.html "PostgreSQL 14 - 42.2. PL/Tcl Functions and Arguments") Development Versions: [devel](https://www.postgresql.org/docs/devel/pltcl-functions.html "PostgreSQL devel - 42.2. PL/Tcl Functions and Arguments") Unsupported versions: [13](https://www.postgresql.org/docs/13/pltcl-functions.html "PostgreSQL 13 - 42.2. PL/Tcl Functions and Arguments") / [12](https://www.postgresql.org/docs/12/pltcl-functions.html "PostgreSQL 12 - 42.2. PL/Tcl Functions and Arguments") / [11](https://www.postgresql.org/docs/11/pltcl-functions.html "PostgreSQL 11 - 42.2. PL/Tcl Functions and Arguments") / [10](https://www.postgresql.org/docs/10/pltcl-functions.html "PostgreSQL 10 - 42.2. PL/Tcl Functions and Arguments") / [9.6](https://www.postgresql.org/docs/9.6/pltcl-functions.html "PostgreSQL 9.6 - 42.2. PL/Tcl Functions and Arguments") / [9.5](https://www.postgresql.org/docs/9.5/pltcl-functions.html "PostgreSQL 9.5 - 42.2. PL/Tcl Functions and Arguments") / [9.4](https://www.postgresql.org/docs/9.4/pltcl-functions.html "PostgreSQL 9.4 - 42.2. PL/Tcl Functions and Arguments") / [9.3](https://www.postgresql.org/docs/9.3/pltcl-functions.html "PostgreSQL 9.3 - 42.2. PL/Tcl Functions and Arguments") / [9.2](https://www.postgresql.org/docs/9.2/pltcl-functions.html "PostgreSQL 9.2 - 42.2. PL/Tcl Functions and Arguments") / [9.1](https://www.postgresql.org/docs/9.1/pltcl-functions.html "PostgreSQL 9.1 - 42.2. PL/Tcl Functions and Arguments") / [9.0](https://www.postgresql.org/docs/9.0/pltcl-functions.html "PostgreSQL 9.0 - 42.2. PL/Tcl Functions and Arguments") / [8.4](https://www.postgresql.org/docs/8.4/pltcl-functions.html "PostgreSQL 8.4 - 42.2. PL/Tcl Functions and Arguments") / [8.3](https://www.postgresql.org/docs/8.3/pltcl-functions.html "PostgreSQL 8.3 - 42.2. PL/Tcl Functions and Arguments") / [8.2](https://www.postgresql.org/docs/8.2/pltcl-functions.html "PostgreSQL 8.2 - 42.2. PL/Tcl Functions and Arguments") / [8.1](https://www.postgresql.org/docs/8.1/pltcl-functions.html "PostgreSQL 8.1 - 42.2. PL/Tcl Functions and Arguments") / [8.0](https://www.postgresql.org/docs/8.0/pltcl-functions.html "PostgreSQL 8.0 - 42.2. PL/Tcl Functions and Arguments") / [7.4](https://www.postgresql.org/docs/7.4/pltcl-functions.html "PostgreSQL 7.4 - 42.2. PL/Tcl Functions and Arguments") | 42.2. PL/Tcl Functions and Arguments | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/pltcl-overview.html "42.1. Overview") | [Up](https://www.postgresql.org/docs/18/pltcl.html "Chapter 42. PL/Tcl — Tcl Procedural Language") | Chapter 42. PL/Tcl — Tcl Procedural Language | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/pltcl-data.html "42.3. Data Values in PL/Tcl") | * * * 42.2. PL/Tcl Functions and Arguments [#](https://www.postgresql.org/docs/18/pltcl-functions.html#PLTCL-FUNCTIONS) ------------------------------------------------------------------------------------------------------------------ To create a function in the PL/Tcl language, use the standard [CREATE FUNCTION](https://www.postgresql.org/docs/18/sql-createfunction.html "CREATE FUNCTION") syntax: CREATE FUNCTION _`funcname`_ (_`argument-types`_) RETURNS _`return-type`_ AS $$ # PL/Tcl function body $$ LANGUAGE pltcl; PL/TclU is the same, except that the language has to be specified as `pltclu`. The body of the function is simply a piece of Tcl script. When the function is called, the argument values are passed to the Tcl script as variables named `1` ... ``_`n`_``. The result is returned from the Tcl code in the usual way, with a `return` statement. In a procedure, the return value from the Tcl code is ignored. For example, a function returning the greater of two integer values could be defined as: CREATE FUNCTION tcl\_max(integer, integer) RETURNS integer AS $$ if {$1 > $2} {return $1} return $2 $$ LANGUAGE pltcl STRICT; Note the clause `STRICT`, which saves us from having to think about null input values: if a null value is passed, the function will not be called at all, but will just return a null result automatically. In a nonstrict function, if the actual value of an argument is null, the corresponding ``$_`n`_`` variable will be set to an empty string. To detect whether a particular argument is null, use the function `argisnull`. For example, suppose that we wanted `tcl_max` with one null and one nonnull argument to return the nonnull argument, rather than null: CREATE FUNCTION tcl\_max(integer, integer) RETURNS integer AS $$ if {\[argisnull 1\]} { if {\[argisnull 2\]} { return\_null } return $2 } if {\[argisnull 2\]} { return $1 } if {$1 > $2} {return $1} return $2 $$ LANGUAGE pltcl; As shown above, to return a null value from a PL/Tcl function, execute `return_null`. This can be done whether the function is strict or not. Composite-type arguments are passed to the function as Tcl arrays. The element names of the array are the attribute names of the composite type. If an attribute in the passed row has the null value, it will not appear in the array. Here is an example: CREATE TABLE employee ( name text, salary integer, age integer ); CREATE FUNCTION overpaid(employee) RETURNS boolean AS $$ if {200000.0 < $1(salary)} { return "t" } if {$1(age) < 30 && 100000.0 < $1(salary)} { return "t" } return "f" $$ LANGUAGE pltcl; PL/Tcl functions can return composite-type results, too. To do this, the Tcl code must return a list of column name/value pairs matching the expected result type. Any column names omitted from the list are returned as nulls, and an error is raised if there are unexpected column names. Here is an example: CREATE FUNCTION square\_cube(in int, out squared int, out cubed int) AS $$ return \[list squared \[expr {$1 \* $1}\] cubed \[expr {$1 \* $1 \* $1}\]\] $$ LANGUAGE pltcl; Output arguments of procedures are returned in the same way, for example: CREATE PROCEDURE tcl\_triple(INOUT a integer, INOUT b integer) AS $$ return \[list a \[expr {$1 \* 3}\] b \[expr {$2 \* 3}\]\] $$ LANGUAGE pltcl; CALL tcl\_triple(5, 10); ### Tip The result list can be made from an array representation of the desired tuple with the `array get` Tcl command. For example: CREATE FUNCTION raise\_pay(employee, delta int) RETURNS employee AS $$ set 1(salary) \[expr {$1(salary) + $2}\] return \[array get 1\] $$ LANGUAGE pltcl; PL/Tcl functions can return sets. To do this, the Tcl code should call `return_next` once per row to be returned, passing either the appropriate value when returning a scalar type, or a list of column name/value pairs when returning a composite type. Here is an example returning a scalar type: CREATE FUNCTION sequence(int, int) RETURNS SETOF int AS $$ for {set i $1} {$i < $2} {incr i} { return\_next $i } $$ LANGUAGE pltcl; and here is one returning a composite type: CREATE FUNCTION table\_of\_squares(int, int) RETURNS TABLE (x int, x2 int) AS $$ for {set i $1} {$i < $2} {incr i} { return\_next \[list x $i x2 \[expr {$i \* $i}\]\] } $$ LANGUAGE pltcl; * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/pltcl-overview.html "42.1. Overview") | [Up](https://www.postgresql.org/docs/18/pltcl.html "Chapter 42. PL/Tcl — Tcl Procedural Language") | [Next](https://www.postgresql.org/docs/18/pltcl-data.html "42.3. Data Values in PL/Tcl") | | 42.1. Overview | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 42.3. Data Values in PL/Tcl | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/pltcl-functions.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 64.1. Generic WAL Records November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/generic-wal.html "PostgreSQL 18 - 64.1. Generic WAL Records") ([18](https://www.postgresql.org/docs/18/generic-wal.html "PostgreSQL 18 - 64.1. Generic WAL Records") ) / [17](https://www.postgresql.org/docs/17/generic-wal.html "PostgreSQL 17 - 64.1. Generic WAL Records") / [16](https://www.postgresql.org/docs/16/generic-wal.html "PostgreSQL 16 - 64.1. Generic WAL Records") / [15](https://www.postgresql.org/docs/15/generic-wal.html "PostgreSQL 15 - 64.1. Generic WAL Records") / [14](https://www.postgresql.org/docs/14/generic-wal.html "PostgreSQL 14 - 64.1. Generic WAL Records") Development Versions: [devel](https://www.postgresql.org/docs/devel/generic-wal.html "PostgreSQL devel - 64.1. Generic WAL Records") Unsupported versions: [13](https://www.postgresql.org/docs/13/generic-wal.html "PostgreSQL 13 - 64.1. Generic WAL Records") / [12](https://www.postgresql.org/docs/12/generic-wal.html "PostgreSQL 12 - 64.1. Generic WAL Records") / [11](https://www.postgresql.org/docs/11/generic-wal.html "PostgreSQL 11 - 64.1. Generic WAL Records") / [10](https://www.postgresql.org/docs/10/generic-wal.html "PostgreSQL 10 - 64.1. Generic WAL Records") / [9.6](https://www.postgresql.org/docs/9.6/generic-wal.html "PostgreSQL 9.6 - 64.1. Generic WAL Records") | 64.1. Generic WAL Records | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/wal-for-extensions.html "Chapter 64. Write Ahead Logging for Extensions") | [Up](https://www.postgresql.org/docs/current/wal-for-extensions.html "Chapter 64. Write Ahead Logging for Extensions") | Chapter 64. Write Ahead Logging for Extensions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/custom-rmgr.html "64.2. Custom WAL Resource Managers") | * * * 64.1. Generic WAL Records [#](https://www.postgresql.org/docs/current/generic-wal.html#GENERIC-WAL) ---------------------------------------------------------------------------------------------------- Although all built-in WAL-logged modules have their own types of WAL records, there is also a generic WAL record type, which describes changes to pages in a generic way. ### Note Generic WAL records are ignored during [Logical Decoding](https://www.postgresql.org/docs/current/logicaldecoding.html "Chapter 47. Logical Decoding") . If logical decoding is required for your extension, consider a Custom WAL Resource Manager. The API for constructing generic WAL records is defined in `access/generic_xlog.h` and implemented in `access/transam/generic_xlog.c`. To perform a WAL-logged data update using the generic WAL record facility, follow these steps: 1. `state = GenericXLogStart(relation)` — start construction of a generic WAL record for the given relation. 2. `page = GenericXLogRegisterBuffer(state, buffer, flags)` — register a buffer to be modified within the current generic WAL record. This function returns a pointer to a temporary copy of the buffer's page, where modifications should be made. (Do not modify the buffer's contents directly.) The third argument is a bit mask of flags applicable to the operation. Currently the only such flag is `GENERIC_XLOG_FULL_IMAGE`, which indicates that a full-page image rather than a delta update should be included in the WAL record. Typically this flag would be set if the page is new or has been rewritten completely. `GenericXLogRegisterBuffer` can be repeated if the WAL-logged action needs to modify multiple pages. 3. Apply modifications to the page images obtained in the previous step. 4. `GenericXLogFinish(state)` — apply the changes to the buffers and emit the generic WAL record. WAL record construction can be canceled between any of the above steps by calling `GenericXLogAbort(state)`. This will discard all changes to the page image copies. Please note the following points when using the generic WAL record facility: * No direct modifications of buffers are allowed! All modifications must be done in copies acquired from `GenericXLogRegisterBuffer()`. In other words, code that makes generic WAL records should never call `BufferGetPage()` for itself. However, it remains the caller's responsibility to pin/unpin and lock/unlock the buffers at appropriate times. Exclusive lock must be held on each target buffer from before `GenericXLogRegisterBuffer()` until after `GenericXLogFinish()`. * Registrations of buffers (step 2) and modifications of page images (step 3) can be mixed freely, i.e., both steps may be repeated in any sequence. Keep in mind that buffers should be registered in the same order in which locks are to be obtained on them during replay. * The maximum number of buffers that can be registered for a generic WAL record is `MAX_GENERIC_XLOG_PAGES`. An error will be thrown if this limit is exceeded. * Generic WAL assumes that the pages to be modified have standard layout, and in particular that there is no useful data between `pd_lower` and `pd_upper`. * Since you are modifying copies of buffer pages, `GenericXLogStart()` does not start a critical section. Thus, you can safely do memory allocation, error throwing, etc. between `GenericXLogStart()` and `GenericXLogFinish()`. The only actual critical section is present inside `GenericXLogFinish()`. There is no need to worry about calling `GenericXLogAbort()` during an error exit, either. * `GenericXLogFinish()` takes care of marking buffers dirty and setting their LSNs. You do not need to do this explicitly. * For unlogged relations, everything works the same except that no actual WAL record is emitted. Thus, you typically do not need to do any explicit checks for unlogged relations. * The generic WAL redo function will acquire exclusive locks to buffers in the same order as they were registered. After redoing all changes, the locks will be released in the same order. * If `GENERIC_XLOG_FULL_IMAGE` is not specified for a registered buffer, the generic WAL record contains a delta between the old and the new page images. This delta is based on byte-by-byte comparison. This is not very compact for the case of moving data within a page, and might be improved in the future. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/wal-for-extensions.html "Chapter 64. Write Ahead Logging for Extensions") | [Up](https://www.postgresql.org/docs/current/wal-for-extensions.html "Chapter 64. Write Ahead Logging for Extensions") | [Next](https://www.postgresql.org/docs/current/custom-rmgr.html "64.2. Custom WAL Resource Managers") | | Chapter 64. Write Ahead Logging for Extensions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 64.2. Custom WAL Resource Managers | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/generic-wal.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 38.3. A Complete Event Trigger Example November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/event-trigger-example.html "PostgreSQL 18 - 38.3. A Complete Event Trigger Example") ([18](https://www.postgresql.org/docs/18/event-trigger-example.html "PostgreSQL 18 - 38.3. A Complete Event Trigger Example") ) / [17](https://www.postgresql.org/docs/17/event-trigger-example.html "PostgreSQL 17 - 38.3. A Complete Event Trigger Example") / [16](https://www.postgresql.org/docs/16/event-trigger-example.html "PostgreSQL 16 - 38.3. A Complete Event Trigger Example") / [15](https://www.postgresql.org/docs/15/event-trigger-example.html "PostgreSQL 15 - 38.3. A Complete Event Trigger Example") / [14](https://www.postgresql.org/docs/14/event-trigger-example.html "PostgreSQL 14 - 38.3. A Complete Event Trigger Example") Development Versions: [devel](https://www.postgresql.org/docs/devel/event-trigger-example.html "PostgreSQL devel - 38.3. A Complete Event Trigger Example") Unsupported versions: [13](https://www.postgresql.org/docs/13/event-trigger-example.html "PostgreSQL 13 - 38.3. A Complete Event Trigger Example") / [12](https://www.postgresql.org/docs/12/event-trigger-example.html "PostgreSQL 12 - 38.3. A Complete Event Trigger Example") / [11](https://www.postgresql.org/docs/11/event-trigger-example.html "PostgreSQL 11 - 38.3. A Complete Event Trigger Example") / [10](https://www.postgresql.org/docs/10/event-trigger-example.html "PostgreSQL 10 - 38.3. A Complete Event Trigger Example") / [9.6](https://www.postgresql.org/docs/9.6/event-trigger-example.html "PostgreSQL 9.6 - 38.3. A Complete Event Trigger Example") / [9.5](https://www.postgresql.org/docs/9.5/event-trigger-example.html "PostgreSQL 9.5 - 38.3. A Complete Event Trigger Example") / [9.4](https://www.postgresql.org/docs/9.4/event-trigger-example.html "PostgreSQL 9.4 - 38.3. A Complete Event Trigger Example") / [9.3](https://www.postgresql.org/docs/9.3/event-trigger-example.html "PostgreSQL 9.3 - 38.3. A Complete Event Trigger Example") | 38.3. A Complete Event Trigger Example | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/event-trigger-interface.html "38.2. Writing Event Trigger Functions in C") | [Up](https://www.postgresql.org/docs/current/event-triggers.html "Chapter 38. Event Triggers") | Chapter 38. Event Triggers | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/event-trigger-table-rewrite-example.html "38.4. A Table Rewrite Event Trigger Example") | * * * 38.3. A Complete Event Trigger Example [#](https://www.postgresql.org/docs/current/event-trigger-example.html#EVENT-TRIGGER-EXAMPLE) ------------------------------------------------------------------------------------------------------------------------------------- Here is a very simple example of an event trigger function written in C. (Examples of triggers written in procedural languages can be found in the documentation of the procedural languages.) The function `noddl` raises an exception each time it is called. The event trigger definition associated the function with the `ddl_command_start` event. The effect is that all DDL commands (with the exceptions mentioned in [Section 38.1](https://www.postgresql.org/docs/current/event-trigger-definition.html "38.1. Overview of Event Trigger Behavior") ) are prevented from running. This is the source code of the trigger function: #include "postgres.h" #include "commands/event\_trigger.h" #include "fmgr.h" PG\_MODULE\_MAGIC; PG\_FUNCTION\_INFO\_V1(noddl); Datum noddl(PG\_FUNCTION\_ARGS) { EventTriggerData \*trigdata; if (!CALLED\_AS\_EVENT\_TRIGGER(fcinfo)) /\* internal error \*/ elog(ERROR, "not fired by event trigger manager"); trigdata = (EventTriggerData \*) fcinfo->context; ereport(ERROR, (errcode(ERRCODE\_INSUFFICIENT\_PRIVILEGE), errmsg("command \\"%s\\" denied", GetCommandTagName(trigdata->tag)))); PG\_RETURN\_NULL(); } After you have compiled the source code (see [Section 36.10.5](https://www.postgresql.org/docs/current/xfunc-c.html#DFUNC "36.10.5. Compiling and Linking Dynamically-Loaded Functions") ), declare the function and the triggers: CREATE FUNCTION noddl() RETURNS event\_trigger AS 'noddl' LANGUAGE C; CREATE EVENT TRIGGER noddl ON ddl\_command\_start EXECUTE FUNCTION noddl(); Now you can test the operation of the trigger: \=# \\dy List of event triggers Name | Event | Owner | Enabled | Function | Tags -------+-------------------+-------+---------+----------+------ noddl | ddl\_command\_start | dim | enabled | noddl | (1 row) =# CREATE TABLE foo(id serial); ERROR: command "CREATE TABLE" denied In this situation, in order to be able to run some DDL commands when you need to do so, you have to either drop the event trigger or disable it. It can be convenient to disable the trigger for only the duration of a transaction: BEGIN; ALTER EVENT TRIGGER noddl DISABLE; CREATE TABLE foo (id serial); ALTER EVENT TRIGGER noddl ENABLE; COMMIT; (Recall that DDL commands on event triggers themselves are not affected by event triggers.) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/event-trigger-interface.html "38.2. Writing Event Trigger Functions in C") | [Up](https://www.postgresql.org/docs/current/event-triggers.html "Chapter 38. Event Triggers") | [Next](https://www.postgresql.org/docs/current/event-trigger-table-rewrite-example.html "38.4. A Table Rewrite Event Trigger Example") | | 38.2. Writing Event Trigger Functions in C | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 38.4. A Table Rewrite Event Trigger Example | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/event-trigger-example.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: O.2. Default Roles Renamed to Predefined Roles November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/default-roles.html "PostgreSQL 18 - O.2. Default Roles Renamed to Predefined Roles") ([18](https://www.postgresql.org/docs/18/default-roles.html "PostgreSQL 18 - O.2. Default Roles Renamed to Predefined Roles") ) / [17](https://www.postgresql.org/docs/17/default-roles.html "PostgreSQL 17 - O.2. Default Roles Renamed to Predefined Roles") / [16](https://www.postgresql.org/docs/16/default-roles.html "PostgreSQL 16 - O.2. Default Roles Renamed to Predefined Roles") / [15](https://www.postgresql.org/docs/15/default-roles.html "PostgreSQL 15 - O.2. Default Roles Renamed to Predefined Roles") / [14](https://www.postgresql.org/docs/14/default-roles.html "PostgreSQL 14 - O.2. Default Roles Renamed to Predefined Roles") Development Versions: [devel](https://www.postgresql.org/docs/devel/default-roles.html "PostgreSQL devel - O.2. Default Roles Renamed to Predefined Roles") Unsupported versions: [13](https://www.postgresql.org/docs/13/default-roles.html "PostgreSQL 13 - O.2. Default Roles Renamed to Predefined Roles") / [12](https://www.postgresql.org/docs/12/default-roles.html "PostgreSQL 12 - O.2. Default Roles Renamed to Predefined Roles") / [11](https://www.postgresql.org/docs/11/default-roles.html "PostgreSQL 11 - O.2. Default Roles Renamed to Predefined Roles") / [10](https://www.postgresql.org/docs/10/default-roles.html "PostgreSQL 10 - O.2. Default Roles Renamed to Predefined Roles") / [9.6](https://www.postgresql.org/docs/9.6/default-roles.html "PostgreSQL 9.6 - O.2. Default Roles Renamed to Predefined Roles") | O.2. Default Roles Renamed to Predefined Roles | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/recovery-config.html "O.1. recovery.conf file merged into postgresql.conf") | [Up](https://www.postgresql.org/docs/18/appendix-obsolete.html "Appendix O. Obsolete or Renamed Features") | Appendix O. Obsolete or Renamed Features | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/pgxlogdump.html "O.3. pg_xlogdump renamed to pg_waldump") | * * * O.2. Default Roles Renamed to Predefined Roles [#](https://www.postgresql.org/docs/18/default-roles.html#DEFAULT-ROLES) ------------------------------------------------------------------------------------------------------------------------ PostgreSQL 13 and below used the term “Default Roles”. However, as these roles are not able to actually be changed and are installed as part of the system at initialization time, the more appropriate term to use is “Predefined Roles”. See [Section 21.5](https://www.postgresql.org/docs/18/predefined-roles.html "21.5. Predefined Roles") for current documentation regarding Predefined Roles, and [the release notes for PostgreSQL 14](https://www.postgresql.org/docs/18/release-prior.html "E.3. Prior Releases") for details on this change. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/recovery-config.html "O.1. recovery.conf file merged into postgresql.conf") | [Up](https://www.postgresql.org/docs/18/appendix-obsolete.html "Appendix O. Obsolete or Renamed Features") | [Next](https://www.postgresql.org/docs/18/pgxlogdump.html "O.3. pg_xlogdump renamed to pg_waldump") | | O.1. `recovery.conf` file merged into `postgresql.conf` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | O.3. `pg_xlogdump` renamed to `pg_waldump` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/default-roles.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.2. pg_aios November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-aios.html "PostgreSQL 18 - 53.2. pg_aios") ([18](https://www.postgresql.org/docs/18/view-pg-aios.html "PostgreSQL 18 - 53.2. pg_aios") ) Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-aios.html "PostgreSQL devel - 53.2. pg_aios") | 53.2. `pg_aios` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/views-overview.html "53.1. Overview") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/view-pg-available-extensions.html "53.3. pg_available_extensions") | * * * 53.2. `pg_aios` [#](https://www.postgresql.org/docs/18/view-pg-aios.html#VIEW-PG-AIOS) --------------------------------------------------------------------------------------- The `pg_aios` view lists all [Asynchronous I/O](https://www.postgresql.org/docs/18/glossary.html#GLOSSARY-AIO "Asynchronous I/O") handles that are currently in-use. An I/O handle is used to reference an I/O operation that is being prepared, executed or is in the process of completing. `pg_aios` contains one row for each I/O handle. This view is mainly useful for developers of PostgreSQL, but may also be useful when tuning PostgreSQL. **Table 53.2. `pg_aios` Columns** | Column Type

Description | | --- | | `pid` `int4`

Process ID of the server process that is issuing this I/O. | | `io_id` `int4`

Identifier of the I/O handle. Handles are reused once the I/O completed (or if the handle is released before I/O is started). On reuse [`pg_aios`.`io_generation`](https://www.postgresql.org/docs/18/view-pg-aios.html#VIEW-PG-AIOS-IO-GENERATION)
is incremented. | | `io_generation` `int8`

Generation of the I/O handle. | | `state` `text`

State of the I/O handle:

* `HANDED_OUT`, referenced by code but not yet used

* `DEFINED`, information necessary for execution is known

* `STAGED`, ready for execution

* `SUBMITTED`, submitted for execution

* `COMPLETED_IO`, finished, but result has not yet been processed

* `COMPLETED_SHARED`, shared completion processing completed

* `COMPLETED_LOCAL`, backend local completion processing completed | | `operation` `text`

Operation performed using the I/O handle:

* `invalid`, not yet known

* `readv`, a vectored read

* `writev`, a vectored write | | `off` `int8`

Offset of the I/O operation. | | `length` `int8`

Length of the I/O operation. | | `target` `text`

What kind of object is the I/O targeting:

* `smgr`, I/O on relations | | `handle_data_len` `int2`

Length of the data associated with the I/O operation. For I/O to/from [shared\_buffers](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-SHARED-BUFFERS)
and [temp\_buffers](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-TEMP-BUFFERS)
, this indicates the number of buffers the I/O is operating on. | | `raw_result` `int4`

Low-level result of the I/O operation, or NULL if the operation has not yet completed. | | `result` `text`

High-level result of the I/O operation:

* `UNKNOWN` means that the result of the operation is not yet known.

* `OK` means the I/O completed successfully.

* `PARTIAL` means that the I/O completed without error, but did not process all data. Commonly callers will need to retry and perform the remainder of the work in a separate I/O.

* `WARNING` means that the I/O completed without error, but that execution of the IO triggered a warning. E.g. when encountering a corrupted buffer with [zero\_damaged\_pages](https://www.postgresql.org/docs/18/runtime-config-developer.html#GUC-ZERO-DAMAGED-PAGES)
enabled.

* `ERROR` means the I/O failed with an error. | | `target_desc` `text`

Description of what the I/O operation is targeting. | | `f_sync` `bool`

Flag indicating whether the I/O is executed synchronously. | | `f_localmem` `bool`

Flag indicating whether the I/O references process local memory. | | `f_buffered` `bool`

Flag indicating whether the I/O is buffered I/O. | The `pg_aios` view is read-only. By default, the `pg_aios` view can be read only by superusers or roles with privileges of the `pg_read_all_stats` role. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/views-overview.html "53.1. Overview") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/18/view-pg-available-extensions.html "53.3. pg_available_extensions") | | 53.1. Overview | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 53.3. `pg_available_extensions` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-aios.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.5. pg_backend_memory_contexts November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-backend-memory-contexts.html "PostgreSQL 18 - 53.5. pg_backend_memory_contexts") ([18](https://www.postgresql.org/docs/18/view-pg-backend-memory-contexts.html "PostgreSQL 18 - 53.5. pg_backend_memory_contexts") ) / [17](https://www.postgresql.org/docs/17/view-pg-backend-memory-contexts.html "PostgreSQL 17 - 53.5. pg_backend_memory_contexts") / [16](https://www.postgresql.org/docs/16/view-pg-backend-memory-contexts.html "PostgreSQL 16 - 53.5. pg_backend_memory_contexts") / [15](https://www.postgresql.org/docs/15/view-pg-backend-memory-contexts.html "PostgreSQL 15 - 53.5. pg_backend_memory_contexts") / [14](https://www.postgresql.org/docs/14/view-pg-backend-memory-contexts.html "PostgreSQL 14 - 53.5. pg_backend_memory_contexts") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-backend-memory-contexts.html "PostgreSQL devel - 53.5. pg_backend_memory_contexts") | 53.5. `pg_backend_memory_contexts` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-available-extension-versions.html "53.4. pg_available_extension_versions") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/view-pg-config.html "53.6. pg_config") | * * * 53.5. `pg_backend_memory_contexts` [#](https://www.postgresql.org/docs/current/view-pg-backend-memory-contexts.html#VIEW-PG-BACKEND-MEMORY-CONTEXTS) ----------------------------------------------------------------------------------------------------------------------------------------------------- The view `pg_backend_memory_contexts` displays all the memory contexts of the server process attached to the current session. `pg_backend_memory_contexts` contains one row for each memory context. **Table 53.5. `pg_backend_memory_contexts` Columns** | Column Type

Description | | --- | | `name` `text`

Name of the memory context | | `ident` `text`

Identification information of the memory context. This field is truncated at 1024 bytes | | `type` `text`

Type of the memory context | | `level` `int4`

The 1-based level of the context in the memory context hierarchy. The level of a context also shows the position of that context in the `path` column. | | `path` `int4[]`

Array of transient numerical identifiers to describe the memory context hierarchy. The first element is for `TopMemoryContext`, subsequent elements contain intermediate parents and the final element contains the identifier for the current context. | | `total_bytes` `int8`

Total bytes allocated for this memory context | | `total_nblocks` `int8`

Total number of blocks allocated for this memory context | | `free_bytes` `int8`

Free space in bytes | | `free_chunks` `int8`

Total number of free chunks | | `used_bytes` `int8`

Used space in bytes | By default, the `pg_backend_memory_contexts` view can be read only by superusers or roles with the privileges of the `pg_read_all_stats` role. Since memory contexts are created and destroyed during the running of a query, the identifiers stored in the `path` column can be unstable between multiple invocations of the view in the same query. The example below demonstrates an effective usage of this column and calculates the total number of bytes used by `CacheMemoryContext` and all of its children: WITH memory\_contexts AS ( SELECT \* FROM pg\_backend\_memory\_contexts ) SELECT sum(c1.total\_bytes) FROM memory\_contexts c1, memory\_contexts c2 WHERE c2.name = 'CacheMemoryContext' AND c1.path\[c2.level\] = c2.path\[c2.level\]; The [Common Table Expression](https://www.postgresql.org/docs/current/queries-with.html "7.8. WITH Queries (Common Table Expressions)") is used to ensure the context IDs in the `path` column match between both evaluations of the view. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-available-extension-versions.html "53.4. pg_available_extension_versions") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/current/view-pg-config.html "53.6. pg_config") | | 53.4. `pg_available_extension_versions` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 53.6. `pg_config` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-backend-memory-contexts.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.2. pg_aios November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-aios.html "PostgreSQL 18 - 53.2. pg_aios") ([18](https://www.postgresql.org/docs/18/view-pg-aios.html "PostgreSQL 18 - 53.2. pg_aios") ) Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-aios.html "PostgreSQL devel - 53.2. pg_aios") | 53.2. `pg_aios` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/views-overview.html "53.1. Overview") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/view-pg-available-extensions.html "53.3. pg_available_extensions") | * * * 53.2. `pg_aios` [#](https://www.postgresql.org/docs/current/view-pg-aios.html#VIEW-PG-AIOS) -------------------------------------------------------------------------------------------- The `pg_aios` view lists all [Asynchronous I/O](https://www.postgresql.org/docs/current/glossary.html#GLOSSARY-AIO "Asynchronous I/O") handles that are currently in-use. An I/O handle is used to reference an I/O operation that is being prepared, executed or is in the process of completing. `pg_aios` contains one row for each I/O handle. This view is mainly useful for developers of PostgreSQL, but may also be useful when tuning PostgreSQL. **Table 53.2. `pg_aios` Columns** | Column Type

Description | | --- | | `pid` `int4`

Process ID of the server process that is issuing this I/O. | | `io_id` `int4`

Identifier of the I/O handle. Handles are reused once the I/O completed (or if the handle is released before I/O is started). On reuse [`pg_aios`.`io_generation`](https://www.postgresql.org/docs/current/view-pg-aios.html#VIEW-PG-AIOS-IO-GENERATION)
is incremented. | | `io_generation` `int8`

Generation of the I/O handle. | | `state` `text`

State of the I/O handle:

* `HANDED_OUT`, referenced by code but not yet used

* `DEFINED`, information necessary for execution is known

* `STAGED`, ready for execution

* `SUBMITTED`, submitted for execution

* `COMPLETED_IO`, finished, but result has not yet been processed

* `COMPLETED_SHARED`, shared completion processing completed

* `COMPLETED_LOCAL`, backend local completion processing completed | | `operation` `text`

Operation performed using the I/O handle:

* `invalid`, not yet known

* `readv`, a vectored read

* `writev`, a vectored write | | `off` `int8`

Offset of the I/O operation. | | `length` `int8`

Length of the I/O operation. | | `target` `text`

What kind of object is the I/O targeting:

* `smgr`, I/O on relations | | `handle_data_len` `int2`

Length of the data associated with the I/O operation. For I/O to/from [shared\_buffers](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-SHARED-BUFFERS)
and [temp\_buffers](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-TEMP-BUFFERS)
, this indicates the number of buffers the I/O is operating on. | | `raw_result` `int4`

Low-level result of the I/O operation, or NULL if the operation has not yet completed. | | `result` `text`

High-level result of the I/O operation:

* `UNKNOWN` means that the result of the operation is not yet known.

* `OK` means the I/O completed successfully.

* `PARTIAL` means that the I/O completed without error, but did not process all data. Commonly callers will need to retry and perform the remainder of the work in a separate I/O.

* `WARNING` means that the I/O completed without error, but that execution of the IO triggered a warning. E.g. when encountering a corrupted buffer with [zero\_damaged\_pages](https://www.postgresql.org/docs/current/runtime-config-developer.html#GUC-ZERO-DAMAGED-PAGES)
enabled.

* `ERROR` means the I/O failed with an error. | | `target_desc` `text`

Description of what the I/O operation is targeting. | | `f_sync` `bool`

Flag indicating whether the I/O is executed synchronously. | | `f_localmem` `bool`

Flag indicating whether the I/O references process local memory. | | `f_buffered` `bool`

Flag indicating whether the I/O is buffered I/O. | The `pg_aios` view is read-only. By default, the `pg_aios` view can be read only by superusers or roles with privileges of the `pg_read_all_stats` role. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/views-overview.html "53.1. Overview") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/current/view-pg-available-extensions.html "53.3. pg_available_extensions") | | 53.1. Overview | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 53.3. `pg_available_extensions` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-aios.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: E.1. Release 18.1 November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/release-18-1.html "PostgreSQL 18 - E.1. Release 18.1") ([18](https://www.postgresql.org/docs/18/release-18-1.html "PostgreSQL 18 - E.1. Release 18.1") ) | E.1. Release 18.1 | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/release.html "Appendix E. Release Notes") | [Up](https://www.postgresql.org/docs/18/release.html "Appendix E. Release Notes") | Appendix E. Release Notes | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/release-18.html "E.2. Release 18") | * * * E.1. Release 18.1 [#](https://www.postgresql.org/docs/18/release-18-1.html#RELEASE-18-1) ----------------------------------------------------------------------------------------- [E.1.1. Migration to Version 18.1](https://www.postgresql.org/docs/18/release-18-1.html#RELEASE-18-1-MIGRATION) [E.1.2. Changes](https://www.postgresql.org/docs/18/release-18-1.html#RELEASE-18-1-CHANGES) **Release date:** 2025-11-13 This release contains a variety of fixes from 18.0. For information about new features in major release 18, see [Section E.2](https://www.postgresql.org/docs/18/release-18.html "E.2. Release 18") . ### E.1.1. Migration to Version 18.1 [#](https://www.postgresql.org/docs/18/release-18-1.html#RELEASE-18-1-MIGRATION) A dump/restore is not required for those running 18.X. ### E.1.2. Changes [#](https://www.postgresql.org/docs/18/release-18-1.html#RELEASE-18-1-CHANGES) * Check for `CREATE` privileges on the schema in `CREATE STATISTICS` (Jelte Fennema-Nio) [§](https://postgr.es/c/00eb646ea) This omission allowed table owners to create statistics in any schema, potentially leading to unexpected naming conflicts. The PostgreSQL Project thanks Jelte Fennema-Nio for reporting this problem. (CVE-2025-12817) * Avoid integer overflow in allocation-size calculations within libpq (Jacob Champion) [§](https://postgr.es/c/7eb8fcad8) Several places in libpq were not sufficiently careful about computing the required size of a memory allocation. Sufficiently large inputs could cause integer overflow, resulting in an undersized buffer, which would then lead to writing past the end of the buffer. The PostgreSQL Project thanks Aleksey Solovev of Positive Technologies for reporting this problem. (CVE-2025-12818) * Prevent “unrecognized node type” errors when a SQL/JSON function such as `JSON_VALUE` has a `DEFAULT` clause containing a `COLLATE` expression (Jian He) [§](https://postgr.es/c/dc9125111) [§](https://postgr.es/c/1baae827e) * Avoid incorrect optimization of variable-free `HAVING` clauses with grouping sets (Richard Guo) [§](https://postgr.es/c/40c242830) [§](https://postgr.es/c/ee49f2cf4) * Do not use parallelism in hash right semi joins (Richard Guo) [§](https://postgr.es/c/ef6168baf) The case does not work reliably due to a race condition in updating the join's shared hash table. * Avoid possible division-by-zero when creating ordered-append plans (Richard Guo) [§](https://postgr.es/c/500f64636) This mistake could result in incorrect selection of the cheapest path, or in an assertion failure in debug builds. * Fix planner failure with index types that can do ordered access but not index-only scans (Maxime Schoemans) [§](https://postgr.es/c/74197bdc8) This oversight resulted in errors like “no data returned for index-only scan”. The case does not arise with any in-core index type, but some extensions encountered the problem. * Remove faulty assertion in btree index cleanup (Peter Geoghegan) [§](https://postgr.es/c/61de81a49) * Avoid possible out-of-memory or “invalid memory alloc request size” failures during parallel GIN index build (Tomas Vondra) [§](https://postgr.es/c/a26b753a0) * Ensure that BRIN autosummarization provides a snapshot for index expressions that need one (Álvaro Herrera) [§](https://postgr.es/c/419ffde23) [§](https://postgr.es/c/8733f0b54) Previously, autosummarization would fail for such indexes, and then leave placeholder index tuples behind, causing the index to bloat over time. * Fix integer-overflow hazard in BRIN index scans when the table contains close to 232 pages (Sunil S) [§](https://postgr.es/c/715983a81) This oversight could result in an infinite loop or scanning of unneeded table pages. * Fix incorrect zero-extension of stored values in JIT-generated tuple deforming code (David Rowley) [§](https://postgr.es/c/ceb51d09b) When not using JIT, the equivalent code does sign-extension not zero-extension, leading to a different Datum representation of small integer data types. This inconsistency was masked in most cases, but it is known to lead to “could not find memoization table entry” errors when using Memoize plan nodes, and there might be other symptoms. * Fix rare crash when processing hashed `GROUPING SETS` queries (David Rowley) [§](https://postgr.es/c/0b6a02f03) * Repair faulty hash-table-size-choosing logic in hash joins (Tomas Vondra) [§](https://postgr.es/c/aa151022e) Hash joins sometimes used more memory than intended, or failed to divide it in an efficient way. * Improve relation lookup logic in statistics manipulation functions (Nathan Bossart) [§](https://postgr.es/c/c8af5019b) [§](https://postgr.es/c/15d7dded0) Fix `pg_restore_relation_stats()`, `pg_clear_relation_stats()`, `pg_restore_attribute_stats()`, and `pg_clear_attribute_stats()` to check privileges before acquiring lock on the target relation rather than after. * Fix incorrect logic for caching result-relation information for triggers (David Rowley, Amit Langote) [§](https://postgr.es/c/a2387c32f) In cases where partitions' column sets aren't physically identical to their parent partitioned tables' column sets, this oversight could lead to crashes. * Fix crash during EvalPlanQual rechecks on partitioned tables (David Rowley, Amit Langote) [§](https://postgr.es/c/1296dcf18) * Fix EvalPlanQual handling of foreign or custom joins that do not have an alternative local-join plan prepared for EPQ (Masahiko Sawada, Etsuro Fujita) [§](https://postgr.es/c/b14144325) In such cases the foreign or custom access method should be invoked normally, but that did not happen, typically leading to a crash. * Avoid duplicating hash partition constraints during `DETACH CONCURRENTLY` (Haiyang Li) [§](https://postgr.es/c/08c037dff) `ALTER TABLE DETACH PARTITION CONCURRENTLY` was written to add a copy of the partitioning constraint to the now-detached partition. This was misguided, partially because non-concurrent `DETACH` doesn't do that, but mostly because in the case of hash partitioning the constraint expression contains references to the parent table's OID. That causes problems during dump/restore, or if the parent table is dropped after `DETACH`. In v19 and later, we'll no longer create any such copied constraints at all. In released branches, to minimize the risk of unforeseen consequences, only skip adding a copied constraint if it is for hash partitioning. * Disallow generated columns in partition keys (Jian He, Ashutosh Bapat) [§](https://postgr.es/c/ba99c9491) This was already not allowed, but the check missed some cases, such as where the column reference is implicit in a whole-row reference. * Disallow generated columns in `COPY ... FROM ... WHERE` clauses (Peter Eisentraut, Jian He) [§](https://postgr.es/c/0f9e0068b) Previously, incorrect behavior or an obscure error message resulted from attempting to reference such a column, since generated columns have not yet been computed at the point where `WHERE` filtering is done. * Prevent setting a column as identity if it has a not-null constraint but the constraint is marked as invalid (Jian He) [§](https://postgr.es/c/d9ffc2729) Identity columns must be not-null, but the check for that missed this edge case. * Avoid potential use-after-free in parallel vacuum (Kevin Oommen Anish) [§](https://postgr.es/c/76613b539) This bug seems to have no consequences in standard builds, but it's theoretically a hazard. * Fix visibility checking for statistics objects in `pg_temp` (Noah Misch) [§](https://postgr.es/c/d024160ff) A statistics object located in a temporary schema cannot be named without schema qualification, but `pg_statistics_obj_is_visible()` missed that memo and could return “true” regardless. In turn, functions such as `pg_describe_object()` could fail to schema-qualify the object's name as expected. * Fix minor memory leak during WAL replay of database creation (Nathan Bossart) [§](https://postgr.es/c/33e7b4a7c) * Fix incorrect reporting of replication lag in `pg_stat_replication` view (Fujii Masao) [§](https://postgr.es/c/9670032cc) If any standby server's replay LSN stopped advancing, the `write_lag` and `flush_lag` columns would eventually stop updating. * Avoid duplicative log messages about invalid `primary_slot_name` settings (Fujii Masao) [§](https://postgr.es/c/6ff7ba9fe) * Avoid failures when `synchronized_standby_slots` references nonexistent replication slots (Shlok Kyal) [§](https://postgr.es/c/b45a8d7d8) * Remove the unfinished slot state file after failing to write a replication slot's state to disk (Michael Paquier) [§](https://postgr.es/c/9a6ea00ac) Previously, a failure such as out-of-disk-space resulted in leaving a temporary `state.tmp` file behind. That's problematic because it would block all subsequent attempts to write the state, requiring manual intervention to clean up. * Fix mishandling of lock timeout signals in parallel apply workers for logical replication (Hayato Kuroda) [§](https://postgr.es/c/37fc5de43) The same signal number was being used for both worker shutdown and lock timeout, leading to confusion. * Avoid unwanted WAL receiver shutdown when switching from streaming to archive WAL source (Xuneng Zhou) [§](https://postgr.es/c/a14201073) During a timeline change, a standby server's WAL receiver should remain alive, waiting for a new WAL streaming start point. Instead it was repeatedly shutting down and immediately getting restarted, which could confuse status monitoring code. * Fix use-after-free issue in the relation synchronization cache maintained by the pgoutput logical decoding plugin (Vignesh C, Masahiko Sawada) [§](https://postgr.es/c/32b95fc71) An error during logical decoding could result in crashes in subsequent logical decoding attempts in the same session. The case is only reachable when pgoutput is invoked via SQL functions. * Avoid unnecessary invalidation of logical replication slots (Bertrand Drouvot) [§](https://postgr.es/c/bf3dba508) * Re-establish special case for `C` collation in locale setup (Jeff Davis) [§](https://postgr.es/c/3ebea75f9) This fixes a regression in access to shared catalogs early in backend startup, before a database has been selected. It is not known to be a problem for any core PostgreSQL code, but some extensions were broken. * Fix incorrect printing of messages about failures in checking whether the user has Windows administrator privilege (Bryan Green) [§](https://postgr.es/c/b48ae226e) This code would have crashed or at least printed garbage. No such cases have been reported though, indicating that failure of these system calls is extremely rare. * Avoid crash when attempting to test PostgreSQL with certain libsanitizer options (Emmanuel Sibi, Jacob Champion) [§](https://postgr.es/c/6d8acb777) * Fix false memory-context-checking warnings in debug builds on 64-bit Windows (David Rowley) [§](https://postgr.es/c/af3a79e08) * Correctly handle `GROUP BY DISTINCT` in PL/pgSQL assignment statements (Tom Lane) [§](https://postgr.es/c/78a284b0b) The parser failed to record the `DISTINCT` option in this context, so that the command would act as if it were plain `GROUP BY`. * Avoid leaking memory when handling a SQL error within PL/Python (Tom Lane) [§](https://postgr.es/c/447a794f6) This fixes a session-lifespan memory leak introduced in our previous minor releases. * Fix libpq's handling of socket-related errors on Windows within its GSSAPI logic (Ning Wu, Tom Lane) [§](https://postgr.es/c/d83879a32) The code for encrypting/decrypting transmitted data using GSSAPI did not correctly recognize error conditions on the connection socket, since Windows reports those differently than other platforms. This led to failure to make such connections on Windows. * Fix dumping of non-inherited not-null constraints on inherited table columns (Dilip Kumar) [§](https://postgr.es/c/0fe07fa11) pg\_dump failed to preserve such constraints when dumping from a pre-v18 server. * Fix pg\_dump's sorting of foreign key constraints (Álvaro Herrera) [§](https://postgr.es/c/162e70ea0) Ensure consistent ordering of these database objects, as was already done for other object types. * Fix assorted errors in the data compression logic in pg\_dump and pg\_restore (Daniel Gustafsson, Tom Lane) [§](https://postgr.es/c/8980c724b) [§](https://postgr.es/c/6a4009747) [§](https://postgr.es/c/aa1fcd087) Error checking was missing or incorrect in several places, and there were also portability issues that would manifest on big-endian hardware. These problems had been missed because this code is only used to read compressed TOC files within directory-format dumps. pg\_dump never produces such a dump; the case can be reached only by manually compressing the TOC file after the fact, which is a supported thing to do but very uncommon. * Fix pgbench to error out cleanly if a `COPY` operation is started (Anthonin Bonnefoy) [§](https://postgr.es/c/c00637b5f) pgbench doesn't intend to support this case, but previously it went into an infinite loop. * Fix pgbench's reporting of multiple errors (Yugo Nagata) [§](https://postgr.es/c/29aabbc43) In cases where two successive `PQgetResult` calls both fail, pgbench might report the wrong error message. * In pgbench, fix faulty assertion about errors in pipeline mode (Yugo Nagata) [§](https://postgr.es/c/c736808e0) * Fix per-file memory leakage in pg\_combinebackup (Tom Lane) [§](https://postgr.es/c/e2072b47b) * Ensure that `contrib/pg_buffercache` functions can be canceled (Satyanarayana Narlapuram, Yuhang Qiu) [§](https://postgr.es/c/71aa2e114) [§](https://postgr.es/c/0beb7e933) Some code paths were capable of running for a long time without checking for interrupts. * Fix `contrib/pg_prewarm`'s privilege checks for indexes (Ayush Vatsa, Nathan Bossart) [§](https://postgr.es/c/3ccf8e9ac) [§](https://postgr.es/c/c29d32d27) `pg_prewarm()` requires `SELECT` privilege on relations to be prewarmed. However, since indexes have no SQL privileges of their own, this resulted in non-superusers being unable to prewarm indexes. Instead, check for `SELECT` privilege on the index's table. * In `contrib/pg_stat_statements`, avoid crash when two or more constants are marked as having the same location in the SQL statement text (Sami Imseih, Dmitry Dolgov) [§](https://postgr.es/c/b1635c166) * Make `contrib/pgstattuple` more robust about empty or invalid index pages (Nitin Motiani) [§](https://postgr.es/c/fc295beb7) Count all-zero pages as free space, and ignore pages that are invalid according to a check of the page's special-space size. The code for btree indexes already counted all-zero pages as free, but the hash and gist code would error out, which has been found to be much less user-friendly. Similarly, make all three cases agree on ignoring corrupted pages rather than throwing errors. * Harden our read and write barrier macros to satisfy Clang (Thomas Munro) [§](https://postgr.es/c/f8ccab0e9) We supposed that `__atomic_thread_fence()` is a sufficient barrier to prevent the C compiler from re-ordering memory accesses around it, but it appears that that's not true for Clang, allowing it to generate incorrect code for at least RISC-V, MIPS, and LoongArch machines. Add explicit compiler barriers to fix that. * Fix PGXS build infrastructure to support building NLS `po` files for extensions (Ryo Matsumura) [§](https://postgr.es/c/6aa04a60c) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/release.html "Appendix E. Release Notes") | [Up](https://www.postgresql.org/docs/18/release.html "Appendix E. Release Notes") | [Next](https://www.postgresql.org/docs/18/release-18.html "E.2. Release 18") | | Appendix E. Release Notes | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | E.2. Release 18 | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/release-18-1.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: E.1. Release 18.1 November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/release-18-1.html "PostgreSQL 18 - E.1. Release 18.1") ([18](https://www.postgresql.org/docs/18/release-18-1.html "PostgreSQL 18 - E.1. Release 18.1") ) | E.1. Release 18.1 | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/release.html "Appendix E. Release Notes") | [Up](https://www.postgresql.org/docs/current/release.html "Appendix E. Release Notes") | Appendix E. Release Notes | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/release-18.html "E.2. Release 18") | * * * E.1. Release 18.1 [#](https://www.postgresql.org/docs/current/release-18-1.html#RELEASE-18-1) ---------------------------------------------------------------------------------------------- [E.1.1. Migration to Version 18.1](https://www.postgresql.org/docs/current/release-18-1.html#RELEASE-18-1-MIGRATION) [E.1.2. Changes](https://www.postgresql.org/docs/current/release-18-1.html#RELEASE-18-1-CHANGES) **Release date:** 2025-11-13 This release contains a variety of fixes from 18.0. For information about new features in major release 18, see [Section E.2](https://www.postgresql.org/docs/current/release-18.html "E.2. Release 18") . ### E.1.1. Migration to Version 18.1 [#](https://www.postgresql.org/docs/current/release-18-1.html#RELEASE-18-1-MIGRATION) A dump/restore is not required for those running 18.X. ### E.1.2. Changes [#](https://www.postgresql.org/docs/current/release-18-1.html#RELEASE-18-1-CHANGES) * Check for `CREATE` privileges on the schema in `CREATE STATISTICS` (Jelte Fennema-Nio) [§](https://postgr.es/c/00eb646ea) This omission allowed table owners to create statistics in any schema, potentially leading to unexpected naming conflicts. The PostgreSQL Project thanks Jelte Fennema-Nio for reporting this problem. (CVE-2025-12817) * Avoid integer overflow in allocation-size calculations within libpq (Jacob Champion) [§](https://postgr.es/c/7eb8fcad8) Several places in libpq were not sufficiently careful about computing the required size of a memory allocation. Sufficiently large inputs could cause integer overflow, resulting in an undersized buffer, which would then lead to writing past the end of the buffer. The PostgreSQL Project thanks Aleksey Solovev of Positive Technologies for reporting this problem. (CVE-2025-12818) * Prevent “unrecognized node type” errors when a SQL/JSON function such as `JSON_VALUE` has a `DEFAULT` clause containing a `COLLATE` expression (Jian He) [§](https://postgr.es/c/dc9125111) [§](https://postgr.es/c/1baae827e) * Avoid incorrect optimization of variable-free `HAVING` clauses with grouping sets (Richard Guo) [§](https://postgr.es/c/40c242830) [§](https://postgr.es/c/ee49f2cf4) * Do not use parallelism in hash right semi joins (Richard Guo) [§](https://postgr.es/c/ef6168baf) The case does not work reliably due to a race condition in updating the join's shared hash table. * Avoid possible division-by-zero when creating ordered-append plans (Richard Guo) [§](https://postgr.es/c/500f64636) This mistake could result in incorrect selection of the cheapest path, or in an assertion failure in debug builds. * Fix planner failure with index types that can do ordered access but not index-only scans (Maxime Schoemans) [§](https://postgr.es/c/74197bdc8) This oversight resulted in errors like “no data returned for index-only scan”. The case does not arise with any in-core index type, but some extensions encountered the problem. * Remove faulty assertion in btree index cleanup (Peter Geoghegan) [§](https://postgr.es/c/61de81a49) * Avoid possible out-of-memory or “invalid memory alloc request size” failures during parallel GIN index build (Tomas Vondra) [§](https://postgr.es/c/a26b753a0) * Ensure that BRIN autosummarization provides a snapshot for index expressions that need one (Álvaro Herrera) [§](https://postgr.es/c/419ffde23) [§](https://postgr.es/c/8733f0b54) Previously, autosummarization would fail for such indexes, and then leave placeholder index tuples behind, causing the index to bloat over time. * Fix integer-overflow hazard in BRIN index scans when the table contains close to 232 pages (Sunil S) [§](https://postgr.es/c/715983a81) This oversight could result in an infinite loop or scanning of unneeded table pages. * Fix incorrect zero-extension of stored values in JIT-generated tuple deforming code (David Rowley) [§](https://postgr.es/c/ceb51d09b) When not using JIT, the equivalent code does sign-extension not zero-extension, leading to a different Datum representation of small integer data types. This inconsistency was masked in most cases, but it is known to lead to “could not find memoization table entry” errors when using Memoize plan nodes, and there might be other symptoms. * Fix rare crash when processing hashed `GROUPING SETS` queries (David Rowley) [§](https://postgr.es/c/0b6a02f03) * Repair faulty hash-table-size-choosing logic in hash joins (Tomas Vondra) [§](https://postgr.es/c/aa151022e) Hash joins sometimes used more memory than intended, or failed to divide it in an efficient way. * Improve relation lookup logic in statistics manipulation functions (Nathan Bossart) [§](https://postgr.es/c/c8af5019b) [§](https://postgr.es/c/15d7dded0) Fix `pg_restore_relation_stats()`, `pg_clear_relation_stats()`, `pg_restore_attribute_stats()`, and `pg_clear_attribute_stats()` to check privileges before acquiring lock on the target relation rather than after. * Fix incorrect logic for caching result-relation information for triggers (David Rowley, Amit Langote) [§](https://postgr.es/c/a2387c32f) In cases where partitions' column sets aren't physically identical to their parent partitioned tables' column sets, this oversight could lead to crashes. * Fix crash during EvalPlanQual rechecks on partitioned tables (David Rowley, Amit Langote) [§](https://postgr.es/c/1296dcf18) * Fix EvalPlanQual handling of foreign or custom joins that do not have an alternative local-join plan prepared for EPQ (Masahiko Sawada, Etsuro Fujita) [§](https://postgr.es/c/b14144325) In such cases the foreign or custom access method should be invoked normally, but that did not happen, typically leading to a crash. * Avoid duplicating hash partition constraints during `DETACH CONCURRENTLY` (Haiyang Li) [§](https://postgr.es/c/08c037dff) `ALTER TABLE DETACH PARTITION CONCURRENTLY` was written to add a copy of the partitioning constraint to the now-detached partition. This was misguided, partially because non-concurrent `DETACH` doesn't do that, but mostly because in the case of hash partitioning the constraint expression contains references to the parent table's OID. That causes problems during dump/restore, or if the parent table is dropped after `DETACH`. In v19 and later, we'll no longer create any such copied constraints at all. In released branches, to minimize the risk of unforeseen consequences, only skip adding a copied constraint if it is for hash partitioning. * Disallow generated columns in partition keys (Jian He, Ashutosh Bapat) [§](https://postgr.es/c/ba99c9491) This was already not allowed, but the check missed some cases, such as where the column reference is implicit in a whole-row reference. * Disallow generated columns in `COPY ... FROM ... WHERE` clauses (Peter Eisentraut, Jian He) [§](https://postgr.es/c/0f9e0068b) Previously, incorrect behavior or an obscure error message resulted from attempting to reference such a column, since generated columns have not yet been computed at the point where `WHERE` filtering is done. * Prevent setting a column as identity if it has a not-null constraint but the constraint is marked as invalid (Jian He) [§](https://postgr.es/c/d9ffc2729) Identity columns must be not-null, but the check for that missed this edge case. * Avoid potential use-after-free in parallel vacuum (Kevin Oommen Anish) [§](https://postgr.es/c/76613b539) This bug seems to have no consequences in standard builds, but it's theoretically a hazard. * Fix visibility checking for statistics objects in `pg_temp` (Noah Misch) [§](https://postgr.es/c/d024160ff) A statistics object located in a temporary schema cannot be named without schema qualification, but `pg_statistics_obj_is_visible()` missed that memo and could return “true” regardless. In turn, functions such as `pg_describe_object()` could fail to schema-qualify the object's name as expected. * Fix minor memory leak during WAL replay of database creation (Nathan Bossart) [§](https://postgr.es/c/33e7b4a7c) * Fix incorrect reporting of replication lag in `pg_stat_replication` view (Fujii Masao) [§](https://postgr.es/c/9670032cc) If any standby server's replay LSN stopped advancing, the `write_lag` and `flush_lag` columns would eventually stop updating. * Avoid duplicative log messages about invalid `primary_slot_name` settings (Fujii Masao) [§](https://postgr.es/c/6ff7ba9fe) * Avoid failures when `synchronized_standby_slots` references nonexistent replication slots (Shlok Kyal) [§](https://postgr.es/c/b45a8d7d8) * Remove the unfinished slot state file after failing to write a replication slot's state to disk (Michael Paquier) [§](https://postgr.es/c/9a6ea00ac) Previously, a failure such as out-of-disk-space resulted in leaving a temporary `state.tmp` file behind. That's problematic because it would block all subsequent attempts to write the state, requiring manual intervention to clean up. * Fix mishandling of lock timeout signals in parallel apply workers for logical replication (Hayato Kuroda) [§](https://postgr.es/c/37fc5de43) The same signal number was being used for both worker shutdown and lock timeout, leading to confusion. * Avoid unwanted WAL receiver shutdown when switching from streaming to archive WAL source (Xuneng Zhou) [§](https://postgr.es/c/a14201073) During a timeline change, a standby server's WAL receiver should remain alive, waiting for a new WAL streaming start point. Instead it was repeatedly shutting down and immediately getting restarted, which could confuse status monitoring code. * Fix use-after-free issue in the relation synchronization cache maintained by the pgoutput logical decoding plugin (Vignesh C, Masahiko Sawada) [§](https://postgr.es/c/32b95fc71) An error during logical decoding could result in crashes in subsequent logical decoding attempts in the same session. The case is only reachable when pgoutput is invoked via SQL functions. * Avoid unnecessary invalidation of logical replication slots (Bertrand Drouvot) [§](https://postgr.es/c/bf3dba508) * Re-establish special case for `C` collation in locale setup (Jeff Davis) [§](https://postgr.es/c/3ebea75f9) This fixes a regression in access to shared catalogs early in backend startup, before a database has been selected. It is not known to be a problem for any core PostgreSQL code, but some extensions were broken. * Fix incorrect printing of messages about failures in checking whether the user has Windows administrator privilege (Bryan Green) [§](https://postgr.es/c/b48ae226e) This code would have crashed or at least printed garbage. No such cases have been reported though, indicating that failure of these system calls is extremely rare. * Avoid crash when attempting to test PostgreSQL with certain libsanitizer options (Emmanuel Sibi, Jacob Champion) [§](https://postgr.es/c/6d8acb777) * Fix false memory-context-checking warnings in debug builds on 64-bit Windows (David Rowley) [§](https://postgr.es/c/af3a79e08) * Correctly handle `GROUP BY DISTINCT` in PL/pgSQL assignment statements (Tom Lane) [§](https://postgr.es/c/78a284b0b) The parser failed to record the `DISTINCT` option in this context, so that the command would act as if it were plain `GROUP BY`. * Avoid leaking memory when handling a SQL error within PL/Python (Tom Lane) [§](https://postgr.es/c/447a794f6) This fixes a session-lifespan memory leak introduced in our previous minor releases. * Fix libpq's handling of socket-related errors on Windows within its GSSAPI logic (Ning Wu, Tom Lane) [§](https://postgr.es/c/d83879a32) The code for encrypting/decrypting transmitted data using GSSAPI did not correctly recognize error conditions on the connection socket, since Windows reports those differently than other platforms. This led to failure to make such connections on Windows. * Fix dumping of non-inherited not-null constraints on inherited table columns (Dilip Kumar) [§](https://postgr.es/c/0fe07fa11) pg\_dump failed to preserve such constraints when dumping from a pre-v18 server. * Fix pg\_dump's sorting of foreign key constraints (Álvaro Herrera) [§](https://postgr.es/c/162e70ea0) Ensure consistent ordering of these database objects, as was already done for other object types. * Fix assorted errors in the data compression logic in pg\_dump and pg\_restore (Daniel Gustafsson, Tom Lane) [§](https://postgr.es/c/8980c724b) [§](https://postgr.es/c/6a4009747) [§](https://postgr.es/c/aa1fcd087) Error checking was missing or incorrect in several places, and there were also portability issues that would manifest on big-endian hardware. These problems had been missed because this code is only used to read compressed TOC files within directory-format dumps. pg\_dump never produces such a dump; the case can be reached only by manually compressing the TOC file after the fact, which is a supported thing to do but very uncommon. * Fix pgbench to error out cleanly if a `COPY` operation is started (Anthonin Bonnefoy) [§](https://postgr.es/c/c00637b5f) pgbench doesn't intend to support this case, but previously it went into an infinite loop. * Fix pgbench's reporting of multiple errors (Yugo Nagata) [§](https://postgr.es/c/29aabbc43) In cases where two successive `PQgetResult` calls both fail, pgbench might report the wrong error message. * In pgbench, fix faulty assertion about errors in pipeline mode (Yugo Nagata) [§](https://postgr.es/c/c736808e0) * Fix per-file memory leakage in pg\_combinebackup (Tom Lane) [§](https://postgr.es/c/e2072b47b) * Ensure that `contrib/pg_buffercache` functions can be canceled (Satyanarayana Narlapuram, Yuhang Qiu) [§](https://postgr.es/c/71aa2e114) [§](https://postgr.es/c/0beb7e933) Some code paths were capable of running for a long time without checking for interrupts. * Fix `contrib/pg_prewarm`'s privilege checks for indexes (Ayush Vatsa, Nathan Bossart) [§](https://postgr.es/c/3ccf8e9ac) [§](https://postgr.es/c/c29d32d27) `pg_prewarm()` requires `SELECT` privilege on relations to be prewarmed. However, since indexes have no SQL privileges of their own, this resulted in non-superusers being unable to prewarm indexes. Instead, check for `SELECT` privilege on the index's table. * In `contrib/pg_stat_statements`, avoid crash when two or more constants are marked as having the same location in the SQL statement text (Sami Imseih, Dmitry Dolgov) [§](https://postgr.es/c/b1635c166) * Make `contrib/pgstattuple` more robust about empty or invalid index pages (Nitin Motiani) [§](https://postgr.es/c/fc295beb7) Count all-zero pages as free space, and ignore pages that are invalid according to a check of the page's special-space size. The code for btree indexes already counted all-zero pages as free, but the hash and gist code would error out, which has been found to be much less user-friendly. Similarly, make all three cases agree on ignoring corrupted pages rather than throwing errors. * Harden our read and write barrier macros to satisfy Clang (Thomas Munro) [§](https://postgr.es/c/f8ccab0e9) We supposed that `__atomic_thread_fence()` is a sufficient barrier to prevent the C compiler from re-ordering memory accesses around it, but it appears that that's not true for Clang, allowing it to generate incorrect code for at least RISC-V, MIPS, and LoongArch machines. Add explicit compiler barriers to fix that. * Fix PGXS build infrastructure to support building NLS `po` files for extensions (Ryo Matsumura) [§](https://postgr.es/c/6aa04a60c) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/release.html "Appendix E. Release Notes") | [Up](https://www.postgresql.org/docs/current/release.html "Appendix E. Release Notes") | [Next](https://www.postgresql.org/docs/current/release-18.html "E.2. Release 18") | | Appendix E. Release Notes | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | E.2. Release 18 | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/release-18-1.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: SPI_execute_plan_extended November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/spi-spi-execute-plan-extended.html "PostgreSQL 18 - SPI_execute_plan_extended") ([18](https://www.postgresql.org/docs/18/spi-spi-execute-plan-extended.html "PostgreSQL 18 - SPI_execute_plan_extended") ) / [17](https://www.postgresql.org/docs/17/spi-spi-execute-plan-extended.html "PostgreSQL 17 - SPI_execute_plan_extended") / [16](https://www.postgresql.org/docs/16/spi-spi-execute-plan-extended.html "PostgreSQL 16 - SPI_execute_plan_extended") / [15](https://www.postgresql.org/docs/15/spi-spi-execute-plan-extended.html "PostgreSQL 15 - SPI_execute_plan_extended") / [14](https://www.postgresql.org/docs/14/spi-spi-execute-plan-extended.html "PostgreSQL 14 - SPI_execute_plan_extended") Development Versions: [devel](https://www.postgresql.org/docs/devel/spi-spi-execute-plan-extended.html "PostgreSQL devel - SPI_execute_plan_extended") | SPI\_execute\_plan\_extended | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-execute-plan.html "SPI_execute_plan") | [Up](https://www.postgresql.org/docs/current/spi-interface.html "45.1. Interface Functions") | 45.1. Interface Functions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/spi-spi-execute-plan-with-paramlist.html "SPI_execute_plan_with_paramlist") | * * * SPI\_execute\_plan\_extended ---------------------------- SPI\_execute\_plan\_extended — execute a statement prepared by `SPI_prepare` Synopsis -------- int SPI\_execute\_plan\_extended(SPIPlanPtr _`plan`_, const SPIExecuteOptions \* _`options`_) Description ----------- `SPI_execute_plan_extended` executes a statement prepared by `SPI_prepare` or one of its siblings. This function is equivalent to `SPI_execute_plan`, except that information about the parameter values to be passed to the query is presented differently, and additional execution-controlling options can be passed. Query parameter values are represented by a `ParamListInfo` struct, which is convenient for passing down values that are already available in that format. Dynamic parameter sets can also be used, via hook functions specified in `ParamListInfo`. Also, instead of always accumulating the result tuples into a `SPI_tuptable` structure, tuples can be passed to a caller-supplied `DestReceiver` object as they are generated by the executor. This is particularly helpful for queries that might generate many tuples, since the data can be processed on-the-fly instead of being accumulated in memory. Arguments --------- ``SPIPlanPtr _`plan`_`` prepared statement (returned by `SPI_prepare`) ``const SPIExecuteOptions * _`options`_`` struct containing optional arguments Callers should always zero out the entire _`options`_ struct, then fill whichever fields they want to set. This ensures forward compatibility of code, since any fields that are added to the struct in future will be defined to behave backwards-compatibly if they are zero. The currently available _`options`_ fields are: ``ParamListInfo _`params`_`` data structure containing query parameter types and values; NULL if none ``bool _`read_only`_`` `true` for read-only execution ``bool _`allow_nonatomic`_`` `true` allows non-atomic execution of CALL and DO statements (but this field is ignored unless the `SPI_OPT_NONATOMIC` flag was passed to `SPI_connect_ext`) ``bool _`must_return_tuples`_`` if `true`, raise error if the query is not of a kind that returns tuples (this does not forbid the case where it happens to return zero tuples) ``uint64 _`tcount`_`` maximum number of rows to return, or `0` for no limit ``DestReceiver * _`dest`_`` `DestReceiver` object that will receive any tuples emitted by the query; if NULL, result tuples are accumulated into a `SPI_tuptable` structure, as in `SPI_execute_plan` ``ResourceOwner _`owner`_`` The resource owner that will hold a reference count on the plan while it is executed. If NULL, CurrentResourceOwner is used. Ignored for non-saved plans, as SPI does not acquire reference counts on those. Return Value ------------ The return value is the same as for `SPI_execute_plan`. When _`options->dest`_ is NULL, `SPI_processed` and `SPI_tuptable` are set as in `SPI_execute_plan`. When _`options->dest`_ is not NULL, `SPI_processed` is set to zero and `SPI_tuptable` is set to NULL. If a tuple count is required, the caller's `DestReceiver` object must calculate it. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-execute-plan.html "SPI_execute_plan") | [Up](https://www.postgresql.org/docs/current/spi-interface.html "45.1. Interface Functions") | [Next](https://www.postgresql.org/docs/current/spi-spi-execute-plan-with-paramlist.html "SPI_execute_plan_with_paramlist") | | SPI\_execute\_plan | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | SPI\_execute\_plan\_with\_paramlist | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/spi-spi-execute-plan-extended.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: SPI_execute_plan_extended November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/spi-spi-execute-plan-extended.html "PostgreSQL 18 - SPI_execute_plan_extended") ([18](https://www.postgresql.org/docs/18/spi-spi-execute-plan-extended.html "PostgreSQL 18 - SPI_execute_plan_extended") ) / [17](https://www.postgresql.org/docs/17/spi-spi-execute-plan-extended.html "PostgreSQL 17 - SPI_execute_plan_extended") / [16](https://www.postgresql.org/docs/16/spi-spi-execute-plan-extended.html "PostgreSQL 16 - SPI_execute_plan_extended") / [15](https://www.postgresql.org/docs/15/spi-spi-execute-plan-extended.html "PostgreSQL 15 - SPI_execute_plan_extended") / [14](https://www.postgresql.org/docs/14/spi-spi-execute-plan-extended.html "PostgreSQL 14 - SPI_execute_plan_extended") Development Versions: [devel](https://www.postgresql.org/docs/devel/spi-spi-execute-plan-extended.html "PostgreSQL devel - SPI_execute_plan_extended") | SPI\_execute\_plan\_extended | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-execute-plan.html "SPI_execute_plan") | [Up](https://www.postgresql.org/docs/18/spi-interface.html "45.1. Interface Functions") | 45.1. Interface Functions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/spi-spi-execute-plan-with-paramlist.html "SPI_execute_plan_with_paramlist") | * * * SPI\_execute\_plan\_extended ---------------------------- SPI\_execute\_plan\_extended — execute a statement prepared by `SPI_prepare` Synopsis -------- int SPI\_execute\_plan\_extended(SPIPlanPtr _`plan`_, const SPIExecuteOptions \* _`options`_) Description ----------- `SPI_execute_plan_extended` executes a statement prepared by `SPI_prepare` or one of its siblings. This function is equivalent to `SPI_execute_plan`, except that information about the parameter values to be passed to the query is presented differently, and additional execution-controlling options can be passed. Query parameter values are represented by a `ParamListInfo` struct, which is convenient for passing down values that are already available in that format. Dynamic parameter sets can also be used, via hook functions specified in `ParamListInfo`. Also, instead of always accumulating the result tuples into a `SPI_tuptable` structure, tuples can be passed to a caller-supplied `DestReceiver` object as they are generated by the executor. This is particularly helpful for queries that might generate many tuples, since the data can be processed on-the-fly instead of being accumulated in memory. Arguments --------- ``SPIPlanPtr _`plan`_`` prepared statement (returned by `SPI_prepare`) ``const SPIExecuteOptions * _`options`_`` struct containing optional arguments Callers should always zero out the entire _`options`_ struct, then fill whichever fields they want to set. This ensures forward compatibility of code, since any fields that are added to the struct in future will be defined to behave backwards-compatibly if they are zero. The currently available _`options`_ fields are: ``ParamListInfo _`params`_`` data structure containing query parameter types and values; NULL if none ``bool _`read_only`_`` `true` for read-only execution ``bool _`allow_nonatomic`_`` `true` allows non-atomic execution of CALL and DO statements (but this field is ignored unless the `SPI_OPT_NONATOMIC` flag was passed to `SPI_connect_ext`) ``bool _`must_return_tuples`_`` if `true`, raise error if the query is not of a kind that returns tuples (this does not forbid the case where it happens to return zero tuples) ``uint64 _`tcount`_`` maximum number of rows to return, or `0` for no limit ``DestReceiver * _`dest`_`` `DestReceiver` object that will receive any tuples emitted by the query; if NULL, result tuples are accumulated into a `SPI_tuptable` structure, as in `SPI_execute_plan` ``ResourceOwner _`owner`_`` The resource owner that will hold a reference count on the plan while it is executed. If NULL, CurrentResourceOwner is used. Ignored for non-saved plans, as SPI does not acquire reference counts on those. Return Value ------------ The return value is the same as for `SPI_execute_plan`. When _`options->dest`_ is NULL, `SPI_processed` and `SPI_tuptable` are set as in `SPI_execute_plan`. When _`options->dest`_ is not NULL, `SPI_processed` is set to zero and `SPI_tuptable` is set to NULL. If a tuple count is required, the caller's `DestReceiver` object must calculate it. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-execute-plan.html "SPI_execute_plan") | [Up](https://www.postgresql.org/docs/18/spi-interface.html "45.1. Interface Functions") | [Next](https://www.postgresql.org/docs/18/spi-spi-execute-plan-with-paramlist.html "SPI_execute_plan_with_paramlist") | | SPI\_execute\_plan | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | SPI\_execute\_plan\_with\_paramlist | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/spi-spi-execute-plan-extended.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: SPI_start_transaction November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/spi-spi-start-transaction.html "PostgreSQL 18 - SPI_start_transaction") ([18](https://www.postgresql.org/docs/18/spi-spi-start-transaction.html "PostgreSQL 18 - SPI_start_transaction") ) / [17](https://www.postgresql.org/docs/17/spi-spi-start-transaction.html "PostgreSQL 17 - SPI_start_transaction") / [16](https://www.postgresql.org/docs/16/spi-spi-start-transaction.html "PostgreSQL 16 - SPI_start_transaction") / [15](https://www.postgresql.org/docs/15/spi-spi-start-transaction.html "PostgreSQL 15 - SPI_start_transaction") / [14](https://www.postgresql.org/docs/14/spi-spi-start-transaction.html "PostgreSQL 14 - SPI_start_transaction") Development Versions: [devel](https://www.postgresql.org/docs/devel/spi-spi-start-transaction.html "PostgreSQL devel - SPI_start_transaction") Unsupported versions: [13](https://www.postgresql.org/docs/13/spi-spi-start-transaction.html "PostgreSQL 13 - SPI_start_transaction") / [12](https://www.postgresql.org/docs/12/spi-spi-start-transaction.html "PostgreSQL 12 - SPI_start_transaction") / [11](https://www.postgresql.org/docs/11/spi-spi-start-transaction.html "PostgreSQL 11 - SPI_start_transaction") | SPI\_start\_transaction | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-rollback.html "SPI_rollback") | [Up](https://www.postgresql.org/docs/18/spi-transaction.html "45.4. Transaction Management") | 45.4. Transaction Management | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/spi-visibility.html "45.5. Visibility of Data Changes") | * * * SPI\_start\_transaction ----------------------- SPI\_start\_transaction — obsolete function Synopsis -------- void SPI\_start\_transaction(void) Description ----------- `SPI_start_transaction` does nothing, and exists only for code compatibility with earlier PostgreSQL releases. It used to be required after calling `SPI_commit` or `SPI_rollback`, but now those functions start a new transaction automatically. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-rollback.html "SPI_rollback") | [Up](https://www.postgresql.org/docs/18/spi-transaction.html "45.4. Transaction Management") | [Next](https://www.postgresql.org/docs/18/spi-visibility.html "45.5. Visibility of Data Changes") | | SPI\_rollback | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 45.5. Visibility of Data Changes | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/spi-spi-start-transaction.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 44.8. Transaction Management November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plpython-transactions.html "PostgreSQL 18 - 44.8. Transaction Management") ([18](https://www.postgresql.org/docs/18/plpython-transactions.html "PostgreSQL 18 - 44.8. Transaction Management") ) / [17](https://www.postgresql.org/docs/17/plpython-transactions.html "PostgreSQL 17 - 44.8. Transaction Management") / [16](https://www.postgresql.org/docs/16/plpython-transactions.html "PostgreSQL 16 - 44.8. Transaction Management") / [15](https://www.postgresql.org/docs/15/plpython-transactions.html "PostgreSQL 15 - 44.8. Transaction Management") / [14](https://www.postgresql.org/docs/14/plpython-transactions.html "PostgreSQL 14 - 44.8. Transaction Management") Development Versions: [devel](https://www.postgresql.org/docs/devel/plpython-transactions.html "PostgreSQL devel - 44.8. Transaction Management") Unsupported versions: [13](https://www.postgresql.org/docs/13/plpython-transactions.html "PostgreSQL 13 - 44.8. Transaction Management") / [12](https://www.postgresql.org/docs/12/plpython-transactions.html "PostgreSQL 12 - 44.8. Transaction Management") / [11](https://www.postgresql.org/docs/11/plpython-transactions.html "PostgreSQL 11 - 44.8. Transaction Management") | 44.8. Transaction Management | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/plpython-subtransaction.html "44.7. Explicit Subtransactions") | [Up](https://www.postgresql.org/docs/18/plpython.html "Chapter 44. PL/Python — Python Procedural Language") | Chapter 44. PL/Python — Python Procedural Language | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/plpython-util.html "44.9. Utility Functions") | * * * 44.8. Transaction Management [#](https://www.postgresql.org/docs/18/plpython-transactions.html#PLPYTHON-TRANSACTIONS) ---------------------------------------------------------------------------------------------------------------------- In a procedure called from the top level or an anonymous code block (`DO` command) called from the top level it is possible to control transactions. To commit the current transaction, call `plpy.commit()`. To roll back the current transaction, call `plpy.rollback()`. (Note that it is not possible to run the SQL commands `COMMIT` or `ROLLBACK` via `plpy.execute` or similar. It has to be done using these functions.) After a transaction is ended, a new transaction is automatically started, so there is no separate function for that. Here is an example: CREATE PROCEDURE transaction\_test1() LANGUAGE plpython3u AS $$ for i in range(0, 10): plpy.execute("INSERT INTO test1 (a) VALUES (%d)" % i) if i % 2 == 0: plpy.commit() else: plpy.rollback() $$; CALL transaction\_test1(); Transactions cannot be ended when an explicit subtransaction is active. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/plpython-subtransaction.html "44.7. Explicit Subtransactions") | [Up](https://www.postgresql.org/docs/18/plpython.html "Chapter 44. PL/Python — Python Procedural Language") | [Next](https://www.postgresql.org/docs/18/plpython-util.html "44.9. Utility Functions") | | 44.7. Explicit Subtransactions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 44.9. Utility Functions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/plpython-transactions.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 44.8. Transaction Management November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plpython-transactions.html "PostgreSQL 18 - 44.8. Transaction Management") ([18](https://www.postgresql.org/docs/18/plpython-transactions.html "PostgreSQL 18 - 44.8. Transaction Management") ) / [17](https://www.postgresql.org/docs/17/plpython-transactions.html "PostgreSQL 17 - 44.8. Transaction Management") / [16](https://www.postgresql.org/docs/16/plpython-transactions.html "PostgreSQL 16 - 44.8. Transaction Management") / [15](https://www.postgresql.org/docs/15/plpython-transactions.html "PostgreSQL 15 - 44.8. Transaction Management") / [14](https://www.postgresql.org/docs/14/plpython-transactions.html "PostgreSQL 14 - 44.8. Transaction Management") Development Versions: [devel](https://www.postgresql.org/docs/devel/plpython-transactions.html "PostgreSQL devel - 44.8. Transaction Management") Unsupported versions: [13](https://www.postgresql.org/docs/13/plpython-transactions.html "PostgreSQL 13 - 44.8. Transaction Management") / [12](https://www.postgresql.org/docs/12/plpython-transactions.html "PostgreSQL 12 - 44.8. Transaction Management") / [11](https://www.postgresql.org/docs/11/plpython-transactions.html "PostgreSQL 11 - 44.8. Transaction Management") | 44.8. Transaction Management | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/plpython-subtransaction.html "44.7. Explicit Subtransactions") | [Up](https://www.postgresql.org/docs/current/plpython.html "Chapter 44. PL/Python — Python Procedural Language") | Chapter 44. PL/Python — Python Procedural Language | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/plpython-util.html "44.9. Utility Functions") | * * * 44.8. Transaction Management [#](https://www.postgresql.org/docs/current/plpython-transactions.html#PLPYTHON-TRANSACTIONS) --------------------------------------------------------------------------------------------------------------------------- In a procedure called from the top level or an anonymous code block (`DO` command) called from the top level it is possible to control transactions. To commit the current transaction, call `plpy.commit()`. To roll back the current transaction, call `plpy.rollback()`. (Note that it is not possible to run the SQL commands `COMMIT` or `ROLLBACK` via `plpy.execute` or similar. It has to be done using these functions.) After a transaction is ended, a new transaction is automatically started, so there is no separate function for that. Here is an example: CREATE PROCEDURE transaction\_test1() LANGUAGE plpython3u AS $$ for i in range(0, 10): plpy.execute("INSERT INTO test1 (a) VALUES (%d)" % i) if i % 2 == 0: plpy.commit() else: plpy.rollback() $$; CALL transaction\_test1(); Transactions cannot be ended when an explicit subtransaction is active. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/plpython-subtransaction.html "44.7. Explicit Subtransactions") | [Up](https://www.postgresql.org/docs/current/plpython.html "Chapter 44. PL/Python — Python Procedural Language") | [Next](https://www.postgresql.org/docs/current/plpython-util.html "44.9. Utility Functions") | | 44.7. Explicit Subtransactions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 44.9. Utility Functions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/plpython-transactions.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.48. unaccent — a text search dictionary which removes diacritics November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/unaccent.html "PostgreSQL 18 - F.48. unaccent — a text search dictionary which removes diacritics") ([18](https://www.postgresql.org/docs/18/unaccent.html "PostgreSQL 18 - F.48. unaccent — a text search dictionary which removes diacritics") ) / [17](https://www.postgresql.org/docs/17/unaccent.html "PostgreSQL 17 - F.48. unaccent — a text search dictionary which removes diacritics") / [16](https://www.postgresql.org/docs/16/unaccent.html "PostgreSQL 16 - F.48. unaccent — a text search dictionary which removes diacritics") / [15](https://www.postgresql.org/docs/15/unaccent.html "PostgreSQL 15 - F.48. unaccent — a text search dictionary which removes diacritics") / [14](https://www.postgresql.org/docs/14/unaccent.html "PostgreSQL 14 - F.48. unaccent — a text search dictionary which removes diacritics") Development Versions: [devel](https://www.postgresql.org/docs/devel/unaccent.html "PostgreSQL devel - F.48. unaccent — a text search dictionary which removes diacritics") Unsupported versions: [13](https://www.postgresql.org/docs/13/unaccent.html "PostgreSQL 13 - F.48. unaccent — a text search dictionary which removes diacritics") / [12](https://www.postgresql.org/docs/12/unaccent.html "PostgreSQL 12 - F.48. unaccent — a text search dictionary which removes diacritics") / [11](https://www.postgresql.org/docs/11/unaccent.html "PostgreSQL 11 - F.48. unaccent — a text search dictionary which removes diacritics") / [10](https://www.postgresql.org/docs/10/unaccent.html "PostgreSQL 10 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.6](https://www.postgresql.org/docs/9.6/unaccent.html "PostgreSQL 9.6 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.5](https://www.postgresql.org/docs/9.5/unaccent.html "PostgreSQL 9.5 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.4](https://www.postgresql.org/docs/9.4/unaccent.html "PostgreSQL 9.4 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.3](https://www.postgresql.org/docs/9.3/unaccent.html "PostgreSQL 9.3 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.2](https://www.postgresql.org/docs/9.2/unaccent.html "PostgreSQL 9.2 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.1](https://www.postgresql.org/docs/9.1/unaccent.html "PostgreSQL 9.1 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.0](https://www.postgresql.org/docs/9.0/unaccent.html "PostgreSQL 9.0 - F.48. unaccent — a text search dictionary which removes diacritics") | F.48. unaccent — a text search dictionary which removes diacritics | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/tsm-system-time.html "F.47. tsm_system_time — the SYSTEM_TIME sampling method for TABLESAMPLE") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/uuid-ossp.html "F.49. uuid-ossp — a UUID generator") | * * * F.48. unaccent — a text search dictionary which removes diacritics [#](https://www.postgresql.org/docs/current/unaccent.html#UNACCENT) --------------------------------------------------------------------------------------------------------------------------------------- [F.48.1. Configuration](https://www.postgresql.org/docs/current/unaccent.html#UNACCENT-CONFIGURATION) [F.48.2. Usage](https://www.postgresql.org/docs/current/unaccent.html#UNACCENT-USAGE) [F.48.3. Functions](https://www.postgresql.org/docs/current/unaccent.html#UNACCENT-FUNCTIONS) `unaccent` is a text search dictionary that removes accents (diacritic signs) from lexemes. It's a filtering dictionary, which means its output is always passed to the next dictionary (if any), unlike the normal behavior of dictionaries. This allows accent-insensitive processing for full text search. The current implementation of `unaccent` cannot be used as a normalizing dictionary for the `thesaurus` dictionary. This module is considered “trusted”, that is, it can be installed by non-superusers who have `CREATE` privilege on the current database. ### F.48.1. Configuration [#](https://www.postgresql.org/docs/current/unaccent.html#UNACCENT-CONFIGURATION) An `unaccent` dictionary accepts the following options: * `RULES` is the base name of the file containing the list of translation rules. This file must be stored in `$SHAREDIR/tsearch_data/` (where `$SHAREDIR` means the PostgreSQL installation's shared-data directory). Its name must end in `.rules` (which is not to be included in the `RULES` parameter). The rules file has the following format: * Each line represents one translation rule, consisting of a character with accent followed by a character without accent. The first is translated into the second. For example, À A Á A Â A Ã A Ä A Å A Æ AE The two characters must be separated by whitespace, and any leading or trailing whitespace on a line is ignored. * Alternatively, if only one character is given on a line, instances of that character are deleted; this is useful in languages where accents are represented by separate characters. * Actually, each “character” can be any string not containing whitespace, so `unaccent` dictionaries could be used for other sorts of substring substitutions besides diacritic removal. * Some characters, like numeric symbols, may require whitespaces in their translation rule. It is possible to use double quotes around the translated characters in this case. A double quote needs to be escaped with a second double quote when including one in the translated character. For example: ¼ " 1/4" ½ " 1/2" ¾ " 3/4" “ """" ” """" * As with other PostgreSQL text search configuration files, the rules file must be stored in UTF-8 encoding. The data is automatically translated into the current database's encoding when loaded. Any lines containing untranslatable characters are silently ignored, so that rules files can contain rules that are not applicable in the current encoding. A more complete example, which is directly useful for most European languages, can be found in `unaccent.rules`, which is installed in `$SHAREDIR/tsearch_data/` when the `unaccent` module is installed. This rules file translates characters with accents to the same characters without accents, and it also expands ligatures into the equivalent series of simple characters (for example, Æ to AE). ### F.48.2. Usage [#](https://www.postgresql.org/docs/current/unaccent.html#UNACCENT-USAGE) Installing the `unaccent` extension creates a text search template `unaccent` and a dictionary `unaccent` based on it. The `unaccent` dictionary has the default parameter setting `RULES='unaccent'`, which makes it immediately usable with the standard `unaccent.rules` file. If you wish, you can alter the parameter, for example mydb=# ALTER TEXT SEARCH DICTIONARY unaccent (RULES='my\_rules'); or create new dictionaries based on the template. To test the dictionary, you can try: mydb=# select ts\_lexize('unaccent','Hôtel'); ts\_lexize ----------- {Hotel} (1 row) Here is an example showing how to insert the `unaccent` dictionary into a text search configuration: mydb=# CREATE TEXT SEARCH CONFIGURATION fr ( COPY = french ); mydb=# ALTER TEXT SEARCH CONFIGURATION fr ALTER MAPPING FOR hword, hword\_part, word WITH unaccent, french\_stem; mydb=# select to\_tsvector('fr','Hôtels de la Mer'); to\_tsvector ------------------- 'hotel':1 'mer':4 (1 row) mydb=# select to\_tsvector('fr','Hôtel de la Mer') @@ to\_tsquery('fr','Hotels'); ?column? ---------- t (1 row) mydb=# select ts\_headline('fr','Hôtel de la Mer',to\_tsquery('fr','Hotels')); ts\_headline ------------------------ Hôtel de la Mer (1 row) ### F.48.3. Functions [#](https://www.postgresql.org/docs/current/unaccent.html#UNACCENT-FUNCTIONS) The `unaccent()` function removes accents (diacritic signs) from a given string. Basically, it's a wrapper around `unaccent`\-type dictionaries, but it can be used outside normal text search contexts. unaccent(\[_`dictionary`_ `regdictionary`, \] _`string`_ `text`) returns `text` If the _`dictionary`_ argument is omitted, the text search dictionary named `unaccent` and appearing in the same schema as the `unaccent()` function itself is used. For example: SELECT unaccent('unaccent', 'Hôtel'); SELECT unaccent('Hôtel'); * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/tsm-system-time.html "F.47. tsm_system_time — the SYSTEM_TIME sampling method for TABLESAMPLE") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/current/uuid-ossp.html "F.49. uuid-ossp — a UUID generator") | | F.47. tsm\_system\_time — the `SYSTEM_TIME` sampling method for `TABLESAMPLE` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | F.49. uuid-ossp — a UUID generator | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/unaccent.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.48. unaccent — a text search dictionary which removes diacritics November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/unaccent.html "PostgreSQL 18 - F.48. unaccent — a text search dictionary which removes diacritics") ([18](https://www.postgresql.org/docs/18/unaccent.html "PostgreSQL 18 - F.48. unaccent — a text search dictionary which removes diacritics") ) / [17](https://www.postgresql.org/docs/17/unaccent.html "PostgreSQL 17 - F.48. unaccent — a text search dictionary which removes diacritics") / [16](https://www.postgresql.org/docs/16/unaccent.html "PostgreSQL 16 - F.48. unaccent — a text search dictionary which removes diacritics") / [15](https://www.postgresql.org/docs/15/unaccent.html "PostgreSQL 15 - F.48. unaccent — a text search dictionary which removes diacritics") / [14](https://www.postgresql.org/docs/14/unaccent.html "PostgreSQL 14 - F.48. unaccent — a text search dictionary which removes diacritics") Development Versions: [devel](https://www.postgresql.org/docs/devel/unaccent.html "PostgreSQL devel - F.48. unaccent — a text search dictionary which removes diacritics") Unsupported versions: [13](https://www.postgresql.org/docs/13/unaccent.html "PostgreSQL 13 - F.48. unaccent — a text search dictionary which removes diacritics") / [12](https://www.postgresql.org/docs/12/unaccent.html "PostgreSQL 12 - F.48. unaccent — a text search dictionary which removes diacritics") / [11](https://www.postgresql.org/docs/11/unaccent.html "PostgreSQL 11 - F.48. unaccent — a text search dictionary which removes diacritics") / [10](https://www.postgresql.org/docs/10/unaccent.html "PostgreSQL 10 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.6](https://www.postgresql.org/docs/9.6/unaccent.html "PostgreSQL 9.6 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.5](https://www.postgresql.org/docs/9.5/unaccent.html "PostgreSQL 9.5 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.4](https://www.postgresql.org/docs/9.4/unaccent.html "PostgreSQL 9.4 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.3](https://www.postgresql.org/docs/9.3/unaccent.html "PostgreSQL 9.3 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.2](https://www.postgresql.org/docs/9.2/unaccent.html "PostgreSQL 9.2 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.1](https://www.postgresql.org/docs/9.1/unaccent.html "PostgreSQL 9.1 - F.48. unaccent — a text search dictionary which removes diacritics") / [9.0](https://www.postgresql.org/docs/9.0/unaccent.html "PostgreSQL 9.0 - F.48. unaccent — a text search dictionary which removes diacritics") | F.48. unaccent — a text search dictionary which removes diacritics | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/tsm-system-time.html "F.47. tsm_system_time — the SYSTEM_TIME sampling method for TABLESAMPLE") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/uuid-ossp.html "F.49. uuid-ossp — a UUID generator") | * * * F.48. unaccent — a text search dictionary which removes diacritics [#](https://www.postgresql.org/docs/18/unaccent.html#UNACCENT) ---------------------------------------------------------------------------------------------------------------------------------- [F.48.1. Configuration](https://www.postgresql.org/docs/18/unaccent.html#UNACCENT-CONFIGURATION) [F.48.2. Usage](https://www.postgresql.org/docs/18/unaccent.html#UNACCENT-USAGE) [F.48.3. Functions](https://www.postgresql.org/docs/18/unaccent.html#UNACCENT-FUNCTIONS) `unaccent` is a text search dictionary that removes accents (diacritic signs) from lexemes. It's a filtering dictionary, which means its output is always passed to the next dictionary (if any), unlike the normal behavior of dictionaries. This allows accent-insensitive processing for full text search. The current implementation of `unaccent` cannot be used as a normalizing dictionary for the `thesaurus` dictionary. This module is considered “trusted”, that is, it can be installed by non-superusers who have `CREATE` privilege on the current database. ### F.48.1. Configuration [#](https://www.postgresql.org/docs/18/unaccent.html#UNACCENT-CONFIGURATION) An `unaccent` dictionary accepts the following options: * `RULES` is the base name of the file containing the list of translation rules. This file must be stored in `$SHAREDIR/tsearch_data/` (where `$SHAREDIR` means the PostgreSQL installation's shared-data directory). Its name must end in `.rules` (which is not to be included in the `RULES` parameter). The rules file has the following format: * Each line represents one translation rule, consisting of a character with accent followed by a character without accent. The first is translated into the second. For example, À A Á A Â A Ã A Ä A Å A Æ AE The two characters must be separated by whitespace, and any leading or trailing whitespace on a line is ignored. * Alternatively, if only one character is given on a line, instances of that character are deleted; this is useful in languages where accents are represented by separate characters. * Actually, each “character” can be any string not containing whitespace, so `unaccent` dictionaries could be used for other sorts of substring substitutions besides diacritic removal. * Some characters, like numeric symbols, may require whitespaces in their translation rule. It is possible to use double quotes around the translated characters in this case. A double quote needs to be escaped with a second double quote when including one in the translated character. For example: ¼ " 1/4" ½ " 1/2" ¾ " 3/4" “ """" ” """" * As with other PostgreSQL text search configuration files, the rules file must be stored in UTF-8 encoding. The data is automatically translated into the current database's encoding when loaded. Any lines containing untranslatable characters are silently ignored, so that rules files can contain rules that are not applicable in the current encoding. A more complete example, which is directly useful for most European languages, can be found in `unaccent.rules`, which is installed in `$SHAREDIR/tsearch_data/` when the `unaccent` module is installed. This rules file translates characters with accents to the same characters without accents, and it also expands ligatures into the equivalent series of simple characters (for example, Æ to AE). ### F.48.2. Usage [#](https://www.postgresql.org/docs/18/unaccent.html#UNACCENT-USAGE) Installing the `unaccent` extension creates a text search template `unaccent` and a dictionary `unaccent` based on it. The `unaccent` dictionary has the default parameter setting `RULES='unaccent'`, which makes it immediately usable with the standard `unaccent.rules` file. If you wish, you can alter the parameter, for example mydb=# ALTER TEXT SEARCH DICTIONARY unaccent (RULES='my\_rules'); or create new dictionaries based on the template. To test the dictionary, you can try: mydb=# select ts\_lexize('unaccent','Hôtel'); ts\_lexize ----------- {Hotel} (1 row) Here is an example showing how to insert the `unaccent` dictionary into a text search configuration: mydb=# CREATE TEXT SEARCH CONFIGURATION fr ( COPY = french ); mydb=# ALTER TEXT SEARCH CONFIGURATION fr ALTER MAPPING FOR hword, hword\_part, word WITH unaccent, french\_stem; mydb=# select to\_tsvector('fr','Hôtels de la Mer'); to\_tsvector ------------------- 'hotel':1 'mer':4 (1 row) mydb=# select to\_tsvector('fr','Hôtel de la Mer') @@ to\_tsquery('fr','Hotels'); ?column? ---------- t (1 row) mydb=# select ts\_headline('fr','Hôtel de la Mer',to\_tsquery('fr','Hotels')); ts\_headline ------------------------ Hôtel de la Mer (1 row) ### F.48.3. Functions [#](https://www.postgresql.org/docs/18/unaccent.html#UNACCENT-FUNCTIONS) The `unaccent()` function removes accents (diacritic signs) from a given string. Basically, it's a wrapper around `unaccent`\-type dictionaries, but it can be used outside normal text search contexts. unaccent(\[_`dictionary`_ `regdictionary`, \] _`string`_ `text`) returns `text` If the _`dictionary`_ argument is omitted, the text search dictionary named `unaccent` and appearing in the same schema as the `unaccent()` function itself is used. For example: SELECT unaccent('unaccent', 'Hôtel'); SELECT unaccent('Hôtel'); * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/tsm-system-time.html "F.47. tsm_system_time — the SYSTEM_TIME sampling method for TABLESAMPLE") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/18/uuid-ossp.html "F.49. uuid-ossp — a UUID generator") | | F.47. tsm\_system\_time — the `SYSTEM_TIME` sampling method for `TABLESAMPLE` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | F.49. uuid-ossp — a UUID generator | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/unaccent.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.47. sequences November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-sequences.html "PostgreSQL 18 - 35.47. sequences") ([18](https://www.postgresql.org/docs/18/infoschema-sequences.html "PostgreSQL 18 - 35.47. sequences") ) / [17](https://www.postgresql.org/docs/17/infoschema-sequences.html "PostgreSQL 17 - 35.47. sequences") / [16](https://www.postgresql.org/docs/16/infoschema-sequences.html "PostgreSQL 16 - 35.47. sequences") / [15](https://www.postgresql.org/docs/15/infoschema-sequences.html "PostgreSQL 15 - 35.47. sequences") / [14](https://www.postgresql.org/docs/14/infoschema-sequences.html "PostgreSQL 14 - 35.47. sequences") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-sequences.html "PostgreSQL devel - 35.47. sequences") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-sequences.html "PostgreSQL 13 - 35.47. sequences") / [12](https://www.postgresql.org/docs/12/infoschema-sequences.html "PostgreSQL 12 - 35.47. sequences") / [11](https://www.postgresql.org/docs/11/infoschema-sequences.html "PostgreSQL 11 - 35.47. sequences") / [10](https://www.postgresql.org/docs/10/infoschema-sequences.html "PostgreSQL 10 - 35.47. sequences") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-sequences.html "PostgreSQL 9.6 - 35.47. sequences") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-sequences.html "PostgreSQL 9.5 - 35.47. sequences") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-sequences.html "PostgreSQL 9.4 - 35.47. sequences") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-sequences.html "PostgreSQL 9.3 - 35.47. sequences") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-sequences.html "PostgreSQL 9.2 - 35.47. sequences") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-sequences.html "PostgreSQL 9.1 - 35.47. sequences") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-sequences.html "PostgreSQL 9.0 - 35.47. sequences") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-sequences.html "PostgreSQL 8.4 - 35.47. sequences") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-sequences.html "PostgreSQL 8.3 - 35.47. sequences") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-sequences.html "PostgreSQL 8.2 - 35.47. sequences") | 35.47. `sequences` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-schemata.html "35.46. schemata") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/infoschema-sql-features.html "35.48. sql_features") | * * * 35.47. `sequences` [#](https://www.postgresql.org/docs/18/infoschema-sequences.html#INFOSCHEMA-SEQUENCES) ---------------------------------------------------------------------------------------------------------- The view `sequences` contains all sequences defined in the current database. Only those sequences are shown that the current user has access to (by way of being the owner or having some privilege). **Table 35.45. `sequences` Columns** | Column Type

Description | | --- | | `sequence_catalog` `sql_identifier`

Name of the database that contains the sequence (always the current database) | | `sequence_schema` `sql_identifier`

Name of the schema that contains the sequence | | `sequence_name` `sql_identifier`

Name of the sequence | | `data_type` `character_data`

The data type of the sequence. | | `numeric_precision` `cardinal_number`

This column contains the (declared or implicit) precision of the sequence data type (see above). The precision indicates the number of significant digits. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column `numeric_precision_radix`. | | `numeric_precision_radix` `cardinal_number`

This column indicates in which base the values in the columns `numeric_precision` and `numeric_scale` are expressed. The value is either 2 or 10. | | `numeric_scale` `cardinal_number`

This column contains the (declared or implicit) scale of the sequence data type (see above). The scale indicates the number of significant digits to the right of the decimal point. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column `numeric_precision_radix`. | | `start_value` `character_data`

The start value of the sequence | | `minimum_value` `character_data`

The minimum value of the sequence | | `maximum_value` `character_data`

The maximum value of the sequence | | `increment` `character_data`

The increment of the sequence | | `cycle_option` `yes_or_no`

`YES` if the sequence cycles, else `NO` | Note that in accordance with the SQL standard, the start, minimum, maximum, and increment values are returned as character strings. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-schemata.html "35.46. schemata") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/18/infoschema-sql-features.html "35.48. sql_features") | | 35.46. `schemata` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 35.48. `sql_features` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-sequences.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.37. pg_walinspect — low-level WAL inspection November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/pgwalinspect.html "PostgreSQL 18 - F.37. pg_walinspect — low-level WAL inspection") ([18](https://www.postgresql.org/docs/18/pgwalinspect.html "PostgreSQL 18 - F.37. pg_walinspect — low-level WAL inspection") ) / [17](https://www.postgresql.org/docs/17/pgwalinspect.html "PostgreSQL 17 - F.37. pg_walinspect — low-level WAL inspection") / [16](https://www.postgresql.org/docs/16/pgwalinspect.html "PostgreSQL 16 - F.37. pg_walinspect — low-level WAL inspection") / [15](https://www.postgresql.org/docs/15/pgwalinspect.html "PostgreSQL 15 - F.37. pg_walinspect — low-level WAL inspection") Development Versions: [devel](https://www.postgresql.org/docs/devel/pgwalinspect.html "PostgreSQL devel - F.37. pg_walinspect — low-level WAL inspection") | F.37. pg\_walinspect — low-level WAL inspection | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/pgvisibility.html "F.36. pg_visibility — visibility map information and utilities") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/postgres-fdw.html "F.38. postgres_fdw — access data stored in external PostgreSQL servers") | * * * F.37. pg\_walinspect — low-level WAL inspection [#](https://www.postgresql.org/docs/18/pgwalinspect.html#PGWALINSPECT) ----------------------------------------------------------------------------------------------------------------------- [F.37.1. General Functions](https://www.postgresql.org/docs/18/pgwalinspect.html#PGWALINSPECT-FUNCS) [F.37.2. Author](https://www.postgresql.org/docs/18/pgwalinspect.html#PGWALINSPECT-AUTHOR) The `pg_walinspect` module provides SQL functions that allow you to inspect the contents of write-ahead log of a running PostgreSQL database cluster at a low level, which is useful for debugging, analytical, reporting or educational purposes. It is similar to [pg\_waldump](https://www.postgresql.org/docs/18/pgwaldump.html "pg_waldump") , but accessible through SQL rather than a separate utility. All the functions of this module will provide the WAL information using the server's current timeline ID. ### Note The `pg_walinspect` functions are often called using an LSN argument that specifies the location at which a known WAL record of interest _begins_. However, some functions, such as `[pg_logical_emit_message](https://www.postgresql.org/docs/18/functions-admin.html#PG-LOGICAL-EMIT-MESSAGE) `, return the LSN _after_ the record that was just inserted. ### Tip All of the `pg_walinspect` functions that show information about records that fall within a certain LSN range are permissive about accepting _`end_lsn`_ arguments that are after the server's current LSN. Using an _`end_lsn`_ “from the future” will not raise an error. It may be convenient to provide the value `FFFFFFFF/FFFFFFFF` (the maximum valid `pg_lsn` value) as an _`end_lsn`_ argument. This is equivalent to providing an _`end_lsn`_ argument matching the server's current LSN. By default, use of these functions is restricted to superusers and members of the `pg_read_server_files` role. Access may be granted by superusers to others using `GRANT`. ### F.37.1. General Functions [#](https://www.postgresql.org/docs/18/pgwalinspect.html#PGWALINSPECT-FUNCS) `pg_get_wal_record_info(in_lsn pg_lsn) returns record` [#](https://www.postgresql.org/docs/18/pgwalinspect.html#PGWALINSPECT-FUNCS-PG-GET-WAL-RECORD-INFO) Gets WAL record information about a record that is located at or after the _`in_lsn`_ argument. For example: postgres=# SELECT \* FROM pg\_get\_wal\_record\_info('0/E419E28'); -\[ RECORD 1 \]----+------------------------------------------------- start\_lsn | 0/E419E28 end\_lsn | 0/E419E68 prev\_lsn | 0/E419D78 xid | 0 resource\_manager | Heap2 record\_type | VACUUM record\_length | 58 main\_data\_length | 2 fpi\_length | 0 description | nunused: 5, unused: \[1, 2, 3, 4, 5\] block\_ref | blkref #0: rel 1663/16385/1249 fork main blk 364 If _`in_lsn`_ isn't at the start of a WAL record, information about the next valid WAL record is shown instead. If there is no next valid WAL record, the function raises an error. `pg_get_wal_records_info(start_lsn pg_lsn, end_lsn pg_lsn) returns setof record` [#](https://www.postgresql.org/docs/18/pgwalinspect.html#PGWALINSPECT-FUNCS-PG-GET-WAL-RECORDS-INFO) Gets information of all the valid WAL records between _`start_lsn`_ and _`end_lsn`_. Returns one row per WAL record. For example: postgres=# SELECT \* FROM pg\_get\_wal\_records\_info('0/1E913618', '0/1E913740') LIMIT 1; -\[ RECORD 1 \]----+-------------------------------------------------------------- start\_lsn | 0/1E913618 end\_lsn | 0/1E913650 prev\_lsn | 0/1E9135A0 xid | 0 resource\_manager | Standby record\_type | RUNNING\_XACTS record\_length | 50 main\_data\_length | 24 fpi\_length | 0 description | nextXid 33775 latestCompletedXid 33774 oldestRunningXid 33775 block\_ref | The function raises an error if _`start_lsn`_ is not available. `pg_get_wal_block_info(start_lsn pg_lsn, end_lsn pg_lsn, show_data boolean DEFAULT true) returns setof record` [#](https://www.postgresql.org/docs/18/pgwalinspect.html#PGWALINSPECT-FUNCS-PG-GET-WAL-BLOCK-INFO) Gets information about each block reference from all the valid WAL records between _`start_lsn`_ and _`end_lsn`_ with one or more block references. Returns one row per block reference per WAL record. For example: postgres=# SELECT \* FROM pg\_get\_wal\_block\_info('0/1230278', '0/12302B8'); -\[ RECORD 1 \]-----+----------------------------------- start\_lsn | 0/1230278 end\_lsn | 0/12302B8 prev\_lsn | 0/122FD40 block\_id | 0 reltablespace | 1663 reldatabase | 1 relfilenode | 2658 relforknumber | 0 relblocknumber | 11 xid | 341 resource\_manager | Btree record\_type | INSERT\_LEAF record\_length | 64 main\_data\_length | 2 block\_data\_length | 16 block\_fpi\_length | 0 block\_fpi\_info | description | off: 46 block\_data | \\x00002a00070010402630000070696400 block\_fpi\_data | This example involves a WAL record that only contains one block reference, but many WAL records contain several block references. Rows output by `pg_get_wal_block_info` are guaranteed to have a unique combination of _`start_lsn`_ and _`block_id`_ values. Much of the information shown here matches the output that `pg_get_wal_records_info` would show, given the same arguments. However, `pg_get_wal_block_info` unnests the information from each WAL record into an expanded form by outputting one row per block reference, so certain details are tracked at the block reference level rather than at the whole-record level. This structure is useful with queries that track how individual blocks changed over time. Note that records with no block references (e.g., `COMMIT` WAL records) will have no rows returned, so `pg_get_wal_block_info` may actually return _fewer_ rows than `pg_get_wal_records_info`. The `reltablespace`, `reldatabase`, and `relfilenode` parameters reference [`pg_tablespace`](https://www.postgresql.org/docs/18/catalog-pg-tablespace.html "52.56. pg_tablespace") .`oid`, [`pg_database`](https://www.postgresql.org/docs/18/catalog-pg-database.html "52.15. pg_database") .`oid`, and [`pg_class`](https://www.postgresql.org/docs/18/catalog-pg-class.html "52.11. pg_class") .`relfilenode` respectively. The `relforknumber` field is the fork number within the relation for the block reference; see `common/relpath.h` for details. ### Tip The `pg_filenode_relation` function (see [Table 9.103](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-DBLOCATION "Table 9.103. Database Object Location Functions") ) can help you to determine which relation was modified during original execution. It is possible for clients to avoid the overhead of materializing block data. This may make function execution significantly faster. When _`show_data`_ is set to `false`, `block_data` and `block_fpi_data` values are omitted (that is, the `block_data` and `block_fpi_data` `OUT` arguments are `NULL` for all rows returned). Obviously, this optimization is only feasible with queries where block data isn't truly required. The function raises an error if _`start_lsn`_ is not available. `pg_get_wal_stats(start_lsn pg_lsn, end_lsn pg_lsn, per_record boolean DEFAULT false) returns setof record` [#](https://www.postgresql.org/docs/18/pgwalinspect.html#PGWALINSPECT-FUNCS-PG-GET-WAL-STATS) Gets statistics of all the valid WAL records between _`start_lsn`_ and _`end_lsn`_. By default, it returns one row per _`resource_manager`_ type. When _`per_record`_ is set to `true`, it returns one row per _`record_type`_. For example: postgres=# SELECT \* FROM pg\_get\_wal\_stats('0/1E847D00', '0/1E84F500') WHERE count > 0 AND "resource\_manager/record\_type" = 'Transaction' LIMIT 1; -\[ RECORD 1 \]----------------+------------------- resource\_manager/record\_type | Transaction count | 2 count\_percentage | 8 record\_size | 875 record\_size\_percentage | 41.23468426013195 fpi\_size | 0 fpi\_size\_percentage | 0 combined\_size | 875 combined\_size\_percentage | 2.8634072910530795 The function raises an error if _`start_lsn`_ is not available. ### F.37.2. Author [#](https://www.postgresql.org/docs/18/pgwalinspect.html#PGWALINSPECT-AUTHOR) Bharath Rupireddy `<[bharath.rupireddyforpostgres@gmail.com](mailto:bharath.rupireddyforpostgres@gmail.com) >` * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/pgvisibility.html "F.36. pg_visibility — visibility map information and utilities") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/18/postgres-fdw.html "F.38. postgres_fdw — access data stored in external PostgreSQL servers") | | F.36. pg\_visibility — visibility map information and utilities | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | F.38. postgres\_fdw — access data stored in external PostgreSQL servers | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/pgwalinspect.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 16. Installation from Binaries November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/install-binaries.html "PostgreSQL 18 - Chapter 16. Installation from Binaries") ([18](https://www.postgresql.org/docs/18/install-binaries.html "PostgreSQL 18 - Chapter 16. Installation from Binaries") ) / [17](https://www.postgresql.org/docs/17/install-binaries.html "PostgreSQL 17 - Chapter 16. Installation from Binaries") / [16](https://www.postgresql.org/docs/16/install-binaries.html "PostgreSQL 16 - Chapter 16. Installation from Binaries") / [15](https://www.postgresql.org/docs/15/install-binaries.html "PostgreSQL 15 - Chapter 16. Installation from Binaries") / [14](https://www.postgresql.org/docs/14/install-binaries.html "PostgreSQL 14 - Chapter 16. Installation from Binaries") Development Versions: [devel](https://www.postgresql.org/docs/devel/install-binaries.html "PostgreSQL devel - Chapter 16. Installation from Binaries") | Chapter 16. Installation from Binaries | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/admin.html "Part III. Server Administration") | [Up](https://www.postgresql.org/docs/18/admin.html "Part III. Server Administration") | Part III. Server Administration | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/installation.html "Chapter 17. Installation from Source Code") | * * * Chapter 16. Installation from Binaries -------------------------------------- PostgreSQL is available in the form of binary packages for most common operating systems today. When available, this is the recommended way to install PostgreSQL for users of the system. Building from source (see [Chapter 17](https://www.postgresql.org/docs/18/installation.html "Chapter 17. Installation from Source Code") ) is only recommended for people developing PostgreSQL or extensions. For an updated list of platforms providing binary packages, please visit the download section on the PostgreSQL website at [https://www.postgresql.org/download/](https://www.postgresql.org/download/) and follow the instructions for the specific platform. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/admin.html "Part III. Server Administration") | [Up](https://www.postgresql.org/docs/18/admin.html "Part III. Server Administration") | [Next](https://www.postgresql.org/docs/18/installation.html "Chapter 17. Installation from Source Code") | | Part III. Server Administration | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | Chapter 17. Installation from Source Code | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/install-binaries.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.37. pg_walinspect — low-level WAL inspection November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/pgwalinspect.html "PostgreSQL 18 - F.37. pg_walinspect — low-level WAL inspection") ([18](https://www.postgresql.org/docs/18/pgwalinspect.html "PostgreSQL 18 - F.37. pg_walinspect — low-level WAL inspection") ) / [17](https://www.postgresql.org/docs/17/pgwalinspect.html "PostgreSQL 17 - F.37. pg_walinspect — low-level WAL inspection") / [16](https://www.postgresql.org/docs/16/pgwalinspect.html "PostgreSQL 16 - F.37. pg_walinspect — low-level WAL inspection") / [15](https://www.postgresql.org/docs/15/pgwalinspect.html "PostgreSQL 15 - F.37. pg_walinspect — low-level WAL inspection") Development Versions: [devel](https://www.postgresql.org/docs/devel/pgwalinspect.html "PostgreSQL devel - F.37. pg_walinspect — low-level WAL inspection") | F.37. pg\_walinspect — low-level WAL inspection | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/pgvisibility.html "F.36. pg_visibility — visibility map information and utilities") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/postgres-fdw.html "F.38. postgres_fdw — access data stored in external PostgreSQL servers") | * * * F.37. pg\_walinspect — low-level WAL inspection [#](https://www.postgresql.org/docs/current/pgwalinspect.html#PGWALINSPECT) ---------------------------------------------------------------------------------------------------------------------------- [F.37.1. General Functions](https://www.postgresql.org/docs/current/pgwalinspect.html#PGWALINSPECT-FUNCS) [F.37.2. Author](https://www.postgresql.org/docs/current/pgwalinspect.html#PGWALINSPECT-AUTHOR) The `pg_walinspect` module provides SQL functions that allow you to inspect the contents of write-ahead log of a running PostgreSQL database cluster at a low level, which is useful for debugging, analytical, reporting or educational purposes. It is similar to [pg\_waldump](https://www.postgresql.org/docs/current/pgwaldump.html "pg_waldump") , but accessible through SQL rather than a separate utility. All the functions of this module will provide the WAL information using the server's current timeline ID. ### Note The `pg_walinspect` functions are often called using an LSN argument that specifies the location at which a known WAL record of interest _begins_. However, some functions, such as `[pg_logical_emit_message](https://www.postgresql.org/docs/current/functions-admin.html#PG-LOGICAL-EMIT-MESSAGE) `, return the LSN _after_ the record that was just inserted. ### Tip All of the `pg_walinspect` functions that show information about records that fall within a certain LSN range are permissive about accepting _`end_lsn`_ arguments that are after the server's current LSN. Using an _`end_lsn`_ “from the future” will not raise an error. It may be convenient to provide the value `FFFFFFFF/FFFFFFFF` (the maximum valid `pg_lsn` value) as an _`end_lsn`_ argument. This is equivalent to providing an _`end_lsn`_ argument matching the server's current LSN. By default, use of these functions is restricted to superusers and members of the `pg_read_server_files` role. Access may be granted by superusers to others using `GRANT`. ### F.37.1. General Functions [#](https://www.postgresql.org/docs/current/pgwalinspect.html#PGWALINSPECT-FUNCS) `pg_get_wal_record_info(in_lsn pg_lsn) returns record` [#](https://www.postgresql.org/docs/current/pgwalinspect.html#PGWALINSPECT-FUNCS-PG-GET-WAL-RECORD-INFO) Gets WAL record information about a record that is located at or after the _`in_lsn`_ argument. For example: postgres=# SELECT \* FROM pg\_get\_wal\_record\_info('0/E419E28'); -\[ RECORD 1 \]----+------------------------------------------------- start\_lsn | 0/E419E28 end\_lsn | 0/E419E68 prev\_lsn | 0/E419D78 xid | 0 resource\_manager | Heap2 record\_type | VACUUM record\_length | 58 main\_data\_length | 2 fpi\_length | 0 description | nunused: 5, unused: \[1, 2, 3, 4, 5\] block\_ref | blkref #0: rel 1663/16385/1249 fork main blk 364 If _`in_lsn`_ isn't at the start of a WAL record, information about the next valid WAL record is shown instead. If there is no next valid WAL record, the function raises an error. `pg_get_wal_records_info(start_lsn pg_lsn, end_lsn pg_lsn) returns setof record` [#](https://www.postgresql.org/docs/current/pgwalinspect.html#PGWALINSPECT-FUNCS-PG-GET-WAL-RECORDS-INFO) Gets information of all the valid WAL records between _`start_lsn`_ and _`end_lsn`_. Returns one row per WAL record. For example: postgres=# SELECT \* FROM pg\_get\_wal\_records\_info('0/1E913618', '0/1E913740') LIMIT 1; -\[ RECORD 1 \]----+-------------------------------------------------------------- start\_lsn | 0/1E913618 end\_lsn | 0/1E913650 prev\_lsn | 0/1E9135A0 xid | 0 resource\_manager | Standby record\_type | RUNNING\_XACTS record\_length | 50 main\_data\_length | 24 fpi\_length | 0 description | nextXid 33775 latestCompletedXid 33774 oldestRunningXid 33775 block\_ref | The function raises an error if _`start_lsn`_ is not available. `pg_get_wal_block_info(start_lsn pg_lsn, end_lsn pg_lsn, show_data boolean DEFAULT true) returns setof record` [#](https://www.postgresql.org/docs/current/pgwalinspect.html#PGWALINSPECT-FUNCS-PG-GET-WAL-BLOCK-INFO) Gets information about each block reference from all the valid WAL records between _`start_lsn`_ and _`end_lsn`_ with one or more block references. Returns one row per block reference per WAL record. For example: postgres=# SELECT \* FROM pg\_get\_wal\_block\_info('0/1230278', '0/12302B8'); -\[ RECORD 1 \]-----+----------------------------------- start\_lsn | 0/1230278 end\_lsn | 0/12302B8 prev\_lsn | 0/122FD40 block\_id | 0 reltablespace | 1663 reldatabase | 1 relfilenode | 2658 relforknumber | 0 relblocknumber | 11 xid | 341 resource\_manager | Btree record\_type | INSERT\_LEAF record\_length | 64 main\_data\_length | 2 block\_data\_length | 16 block\_fpi\_length | 0 block\_fpi\_info | description | off: 46 block\_data | \\x00002a00070010402630000070696400 block\_fpi\_data | This example involves a WAL record that only contains one block reference, but many WAL records contain several block references. Rows output by `pg_get_wal_block_info` are guaranteed to have a unique combination of _`start_lsn`_ and _`block_id`_ values. Much of the information shown here matches the output that `pg_get_wal_records_info` would show, given the same arguments. However, `pg_get_wal_block_info` unnests the information from each WAL record into an expanded form by outputting one row per block reference, so certain details are tracked at the block reference level rather than at the whole-record level. This structure is useful with queries that track how individual blocks changed over time. Note that records with no block references (e.g., `COMMIT` WAL records) will have no rows returned, so `pg_get_wal_block_info` may actually return _fewer_ rows than `pg_get_wal_records_info`. The `reltablespace`, `reldatabase`, and `relfilenode` parameters reference [`pg_tablespace`](https://www.postgresql.org/docs/current/catalog-pg-tablespace.html "52.56. pg_tablespace") .`oid`, [`pg_database`](https://www.postgresql.org/docs/current/catalog-pg-database.html "52.15. pg_database") .`oid`, and [`pg_class`](https://www.postgresql.org/docs/current/catalog-pg-class.html "52.11. pg_class") .`relfilenode` respectively. The `relforknumber` field is the fork number within the relation for the block reference; see `common/relpath.h` for details. ### Tip The `pg_filenode_relation` function (see [Table 9.103](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-DBLOCATION "Table 9.103. Database Object Location Functions") ) can help you to determine which relation was modified during original execution. It is possible for clients to avoid the overhead of materializing block data. This may make function execution significantly faster. When _`show_data`_ is set to `false`, `block_data` and `block_fpi_data` values are omitted (that is, the `block_data` and `block_fpi_data` `OUT` arguments are `NULL` for all rows returned). Obviously, this optimization is only feasible with queries where block data isn't truly required. The function raises an error if _`start_lsn`_ is not available. `pg_get_wal_stats(start_lsn pg_lsn, end_lsn pg_lsn, per_record boolean DEFAULT false) returns setof record` [#](https://www.postgresql.org/docs/current/pgwalinspect.html#PGWALINSPECT-FUNCS-PG-GET-WAL-STATS) Gets statistics of all the valid WAL records between _`start_lsn`_ and _`end_lsn`_. By default, it returns one row per _`resource_manager`_ type. When _`per_record`_ is set to `true`, it returns one row per _`record_type`_. For example: postgres=# SELECT \* FROM pg\_get\_wal\_stats('0/1E847D00', '0/1E84F500') WHERE count > 0 AND "resource\_manager/record\_type" = 'Transaction' LIMIT 1; -\[ RECORD 1 \]----------------+------------------- resource\_manager/record\_type | Transaction count | 2 count\_percentage | 8 record\_size | 875 record\_size\_percentage | 41.23468426013195 fpi\_size | 0 fpi\_size\_percentage | 0 combined\_size | 875 combined\_size\_percentage | 2.8634072910530795 The function raises an error if _`start_lsn`_ is not available. ### F.37.2. Author [#](https://www.postgresql.org/docs/current/pgwalinspect.html#PGWALINSPECT-AUTHOR) Bharath Rupireddy `<[bharath.rupireddyforpostgres@gmail.com](mailto:bharath.rupireddyforpostgres@gmail.com) >` * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/pgvisibility.html "F.36. pg_visibility — visibility map information and utilities") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/current/postgres-fdw.html "F.38. postgres_fdw — access data stored in external PostgreSQL servers") | | F.36. pg\_visibility — visibility map information and utilities | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | F.38. postgres\_fdw — access data stored in external PostgreSQL servers | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/pgwalinspect.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 13.5. Serialization Failure Handling November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/mvcc-serialization-failure-handling.html "PostgreSQL 18 - 13.5. Serialization Failure Handling") ([18](https://www.postgresql.org/docs/18/mvcc-serialization-failure-handling.html "PostgreSQL 18 - 13.5. Serialization Failure Handling") ) / [17](https://www.postgresql.org/docs/17/mvcc-serialization-failure-handling.html "PostgreSQL 17 - 13.5. Serialization Failure Handling") / [16](https://www.postgresql.org/docs/16/mvcc-serialization-failure-handling.html "PostgreSQL 16 - 13.5. Serialization Failure Handling") / [15](https://www.postgresql.org/docs/15/mvcc-serialization-failure-handling.html "PostgreSQL 15 - 13.5. Serialization Failure Handling") Development Versions: [devel](https://www.postgresql.org/docs/devel/mvcc-serialization-failure-handling.html "PostgreSQL devel - 13.5. Serialization Failure Handling") | 13.5. Serialization Failure Handling | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/applevel-consistency.html "13.4. Data Consistency Checks at the Application Level") | [Up](https://www.postgresql.org/docs/current/mvcc.html "Chapter 13. Concurrency Control") | Chapter 13. Concurrency Control | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/mvcc-caveats.html "13.6. Caveats") | * * * 13.5. Serialization Failure Handling [#](https://www.postgresql.org/docs/current/mvcc-serialization-failure-handling.html#MVCC-SERIALIZATION-FAILURE-HANDLING) --------------------------------------------------------------------------------------------------------------------------------------------------------------- Both Repeatable Read and Serializable isolation levels can produce errors that are designed to prevent serialization anomalies. As previously stated, applications using these levels must be prepared to retry transactions that fail due to serialization errors. Such an error's message text will vary according to the precise circumstances, but it will always have the SQLSTATE code `40001` (`serialization_failure`). It may also be advisable to retry deadlock failures. These have the SQLSTATE code `40P01` (`deadlock_detected`). In some cases it is also appropriate to retry unique-key failures, which have SQLSTATE code `23505` (`unique_violation`), and exclusion constraint failures, which have SQLSTATE code `23P01` (`exclusion_violation`). For example, if the application selects a new value for a primary key column after inspecting the currently stored keys, it could get a unique-key failure because another application instance selected the same new key concurrently. This is effectively a serialization failure, but the server will not detect it as such because it cannot “see” the connection between the inserted value and the previous reads. There are also some corner cases in which the server will issue a unique-key or exclusion constraint error even though in principle it has enough information to determine that a serialization problem is the underlying cause. While it's recommendable to just retry `serialization_failure` errors unconditionally, more care is needed when retrying these other error codes, since they might represent persistent error conditions rather than transient failures. It is important to retry the complete transaction, including all logic that decides which SQL to issue and/or which values to use. Therefore, PostgreSQL does not offer an automatic retry facility, since it cannot do so with any guarantee of correctness. Transaction retry does not guarantee that the retried transaction will complete; multiple retries may be needed. In cases with very high contention, it is possible that completion of a transaction may take many attempts. In cases involving a conflicting prepared transaction, it may not be possible to make progress until the prepared transaction commits or rolls back. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/applevel-consistency.html "13.4. Data Consistency Checks at the Application Level") | [Up](https://www.postgresql.org/docs/current/mvcc.html "Chapter 13. Concurrency Control") | [Next](https://www.postgresql.org/docs/current/mvcc-caveats.html "13.6. Caveats") | | 13.4. Data Consistency Checks at the Application Level | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 13.6. Caveats | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/mvcc-serialization-failure-handling.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 16. Installation from Binaries November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/install-binaries.html "PostgreSQL 18 - Chapter 16. Installation from Binaries") ([18](https://www.postgresql.org/docs/18/install-binaries.html "PostgreSQL 18 - Chapter 16. Installation from Binaries") ) / [17](https://www.postgresql.org/docs/17/install-binaries.html "PostgreSQL 17 - Chapter 16. Installation from Binaries") / [16](https://www.postgresql.org/docs/16/install-binaries.html "PostgreSQL 16 - Chapter 16. Installation from Binaries") / [15](https://www.postgresql.org/docs/15/install-binaries.html "PostgreSQL 15 - Chapter 16. Installation from Binaries") / [14](https://www.postgresql.org/docs/14/install-binaries.html "PostgreSQL 14 - Chapter 16. Installation from Binaries") Development Versions: [devel](https://www.postgresql.org/docs/devel/install-binaries.html "PostgreSQL devel - Chapter 16. Installation from Binaries") | Chapter 16. Installation from Binaries | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/admin.html "Part III. Server Administration") | [Up](https://www.postgresql.org/docs/current/admin.html "Part III. Server Administration") | Part III. Server Administration | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/installation.html "Chapter 17. Installation from Source Code") | * * * Chapter 16. Installation from Binaries -------------------------------------- PostgreSQL is available in the form of binary packages for most common operating systems today. When available, this is the recommended way to install PostgreSQL for users of the system. Building from source (see [Chapter 17](https://www.postgresql.org/docs/current/installation.html "Chapter 17. Installation from Source Code") ) is only recommended for people developing PostgreSQL or extensions. For an updated list of platforms providing binary packages, please visit the download section on the PostgreSQL website at [https://www.postgresql.org/download/](https://www.postgresql.org/download/) and follow the instructions for the specific platform. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/admin.html "Part III. Server Administration") | [Up](https://www.postgresql.org/docs/current/admin.html "Part III. Server Administration") | [Next](https://www.postgresql.org/docs/current/installation.html "Chapter 17. Installation from Source Code") | | Part III. Server Administration | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Chapter 17. Installation from Source Code | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/install-binaries.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 13.5. Serialization Failure Handling November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/mvcc-serialization-failure-handling.html "PostgreSQL 18 - 13.5. Serialization Failure Handling") ([18](https://www.postgresql.org/docs/18/mvcc-serialization-failure-handling.html "PostgreSQL 18 - 13.5. Serialization Failure Handling") ) / [17](https://www.postgresql.org/docs/17/mvcc-serialization-failure-handling.html "PostgreSQL 17 - 13.5. Serialization Failure Handling") / [16](https://www.postgresql.org/docs/16/mvcc-serialization-failure-handling.html "PostgreSQL 16 - 13.5. Serialization Failure Handling") / [15](https://www.postgresql.org/docs/15/mvcc-serialization-failure-handling.html "PostgreSQL 15 - 13.5. Serialization Failure Handling") Development Versions: [devel](https://www.postgresql.org/docs/devel/mvcc-serialization-failure-handling.html "PostgreSQL devel - 13.5. Serialization Failure Handling") | 13.5. Serialization Failure Handling | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/applevel-consistency.html "13.4. Data Consistency Checks at the Application Level") | [Up](https://www.postgresql.org/docs/18/mvcc.html "Chapter 13. Concurrency Control") | Chapter 13. Concurrency Control | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/mvcc-caveats.html "13.6. Caveats") | * * * 13.5. Serialization Failure Handling [#](https://www.postgresql.org/docs/18/mvcc-serialization-failure-handling.html#MVCC-SERIALIZATION-FAILURE-HANDLING) ---------------------------------------------------------------------------------------------------------------------------------------------------------- Both Repeatable Read and Serializable isolation levels can produce errors that are designed to prevent serialization anomalies. As previously stated, applications using these levels must be prepared to retry transactions that fail due to serialization errors. Such an error's message text will vary according to the precise circumstances, but it will always have the SQLSTATE code `40001` (`serialization_failure`). It may also be advisable to retry deadlock failures. These have the SQLSTATE code `40P01` (`deadlock_detected`). In some cases it is also appropriate to retry unique-key failures, which have SQLSTATE code `23505` (`unique_violation`), and exclusion constraint failures, which have SQLSTATE code `23P01` (`exclusion_violation`). For example, if the application selects a new value for a primary key column after inspecting the currently stored keys, it could get a unique-key failure because another application instance selected the same new key concurrently. This is effectively a serialization failure, but the server will not detect it as such because it cannot “see” the connection between the inserted value and the previous reads. There are also some corner cases in which the server will issue a unique-key or exclusion constraint error even though in principle it has enough information to determine that a serialization problem is the underlying cause. While it's recommendable to just retry `serialization_failure` errors unconditionally, more care is needed when retrying these other error codes, since they might represent persistent error conditions rather than transient failures. It is important to retry the complete transaction, including all logic that decides which SQL to issue and/or which values to use. Therefore, PostgreSQL does not offer an automatic retry facility, since it cannot do so with any guarantee of correctness. Transaction retry does not guarantee that the retried transaction will complete; multiple retries may be needed. In cases with very high contention, it is possible that completion of a transaction may take many attempts. In cases involving a conflicting prepared transaction, it may not be possible to make progress until the prepared transaction commits or rolls back. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/applevel-consistency.html "13.4. Data Consistency Checks at the Application Level") | [Up](https://www.postgresql.org/docs/18/mvcc.html "Chapter 13. Concurrency Control") | [Next](https://www.postgresql.org/docs/18/mvcc-caveats.html "13.6. Caveats") | | 13.4. Data Consistency Checks at the Application Level | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 13.6. Caveats | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/mvcc-serialization-failure-handling.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: DROP PUBLICATION November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-droppublication.html "PostgreSQL 18 - DROP PUBLICATION") ([18](https://www.postgresql.org/docs/18/sql-droppublication.html "PostgreSQL 18 - DROP PUBLICATION") ) / [17](https://www.postgresql.org/docs/17/sql-droppublication.html "PostgreSQL 17 - DROP PUBLICATION") / [16](https://www.postgresql.org/docs/16/sql-droppublication.html "PostgreSQL 16 - DROP PUBLICATION") / [15](https://www.postgresql.org/docs/15/sql-droppublication.html "PostgreSQL 15 - DROP PUBLICATION") / [14](https://www.postgresql.org/docs/14/sql-droppublication.html "PostgreSQL 14 - DROP PUBLICATION") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-droppublication.html "PostgreSQL devel - DROP PUBLICATION") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-droppublication.html "PostgreSQL 13 - DROP PUBLICATION") / [12](https://www.postgresql.org/docs/12/sql-droppublication.html "PostgreSQL 12 - DROP PUBLICATION") / [11](https://www.postgresql.org/docs/11/sql-droppublication.html "PostgreSQL 11 - DROP PUBLICATION") / [10](https://www.postgresql.org/docs/10/sql-droppublication.html "PostgreSQL 10 - DROP PUBLICATION") | DROP PUBLICATION | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-dropprocedure.html "DROP PROCEDURE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-droprole.html "DROP ROLE") | * * * DROP PUBLICATION ---------------- DROP PUBLICATION — remove a publication Synopsis -------- DROP PUBLICATION \[ IF EXISTS \] _`name`_ \[, ...\] \[ CASCADE | RESTRICT \] Description ----------- `DROP PUBLICATION` removes an existing publication from the database. A publication can only be dropped by its owner or a superuser. Parameters ---------- `IF EXISTS` Do not throw an error if the publication does not exist. A notice is issued in this case. _`name`_ The name of an existing publication. `CASCADE` `RESTRICT` These key words do not have any effect, since there are no dependencies on publications. Examples -------- Drop a publication: DROP PUBLICATION mypublication; Compatibility ------------- `DROP PUBLICATION` is a PostgreSQL extension. See Also -------- [CREATE PUBLICATION](https://www.postgresql.org/docs/18/sql-createpublication.html "CREATE PUBLICATION") , [ALTER PUBLICATION](https://www.postgresql.org/docs/18/sql-alterpublication.html "ALTER PUBLICATION") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-dropprocedure.html "DROP PROCEDURE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-droprole.html "DROP ROLE") | | DROP PROCEDURE | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | DROP ROLE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-droppublication.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.43. routine_sequence_usage November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-routine-sequence-usage.html "PostgreSQL 18 - 35.43. routine_sequence_usage") ([18](https://www.postgresql.org/docs/18/infoschema-routine-sequence-usage.html "PostgreSQL 18 - 35.43. routine_sequence_usage") ) / [17](https://www.postgresql.org/docs/17/infoschema-routine-sequence-usage.html "PostgreSQL 17 - 35.43. routine_sequence_usage") / [16](https://www.postgresql.org/docs/16/infoschema-routine-sequence-usage.html "PostgreSQL 16 - 35.43. routine_sequence_usage") / [15](https://www.postgresql.org/docs/15/infoschema-routine-sequence-usage.html "PostgreSQL 15 - 35.43. routine_sequence_usage") / [14](https://www.postgresql.org/docs/14/infoschema-routine-sequence-usage.html "PostgreSQL 14 - 35.43. routine_sequence_usage") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-routine-sequence-usage.html "PostgreSQL devel - 35.43. routine_sequence_usage") | 35.43. `routine_sequence_usage` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-routine-routine-usage.html "35.42. routine_routine_usage") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/infoschema-routine-table-usage.html "35.44. routine_table_usage") | * * * 35.43. `routine_sequence_usage` [#](https://www.postgresql.org/docs/18/infoschema-routine-sequence-usage.html#INFOSCHEMA-ROUTINE-SEQUENCE-USAGE) ------------------------------------------------------------------------------------------------------------------------------------------------- The view `routine_sequence_usage` identifies all sequences that are used by a function or procedure, either in the SQL body or in parameter default expressions. (This only works for unquoted SQL bodies, not quoted bodies or functions in other languages.) A sequence is only included if that sequence is owned by a currently enabled role. **Table 35.41. `routine_sequence_usage` Columns** | Column Type

Description | | --- | | `specific_catalog` `sql_identifier`

Name of the database containing the function (always the current database) | | `specific_schema` `sql_identifier`

Name of the schema containing the function | | `specific_name` `sql_identifier`

The “specific name” of the function. See [Section 35.45](https://www.postgresql.org/docs/18/infoschema-routines.html "35.45. routines")
for more information. | | `routine_catalog` `sql_identifier`

Name of the database containing the function (always the current database) | | `routine_schema` `sql_identifier`

Name of the schema containing the function | | `routine_name` `sql_identifier`

Name of the function (might be duplicated in case of overloading) | | `schema_catalog` `sql_identifier`

Name of the database that contains the sequence that is used by the function (always the current database) | | `sequence_schema` `sql_identifier`

Name of the schema that contains the sequence that is used by the function | | `sequence_name` `sql_identifier`

Name of the sequence that is used by the function | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-routine-routine-usage.html "35.42. routine_routine_usage") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/18/infoschema-routine-table-usage.html "35.44. routine_table_usage") | | 35.42. `routine_routine_usage` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 35.44. `routine_table_usage` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-routine-sequence-usage.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 32.5. Pipeline Mode November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html "PostgreSQL 18 - 32.5. Pipeline Mode") ([18](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html "PostgreSQL 18 - 32.5. Pipeline Mode") ) / [17](https://www.postgresql.org/docs/17/libpq-pipeline-mode.html "PostgreSQL 17 - 32.5. Pipeline Mode") / [16](https://www.postgresql.org/docs/16/libpq-pipeline-mode.html "PostgreSQL 16 - 32.5. Pipeline Mode") / [15](https://www.postgresql.org/docs/15/libpq-pipeline-mode.html "PostgreSQL 15 - 32.5. Pipeline Mode") / [14](https://www.postgresql.org/docs/14/libpq-pipeline-mode.html "PostgreSQL 14 - 32.5. Pipeline Mode") Development Versions: [devel](https://www.postgresql.org/docs/devel/libpq-pipeline-mode.html "PostgreSQL devel - 32.5. Pipeline Mode") | 32.5. Pipeline Mode | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/libpq-async.html "32.4. Asynchronous Command Processing") | [Up](https://www.postgresql.org/docs/18/libpq.html "Chapter 32. libpq — C Library") | Chapter 32. libpq — C Library | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/libpq-single-row-mode.html "32.6. Retrieving Query Results in Chunks") | * * * 32.5. Pipeline Mode [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-MODE) --------------------------------------------------------------------------------------------------------- [32.5.1. Using Pipeline Mode](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-USING) [32.5.2. Functions Associated with Pipeline Mode](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-FUNCTIONS) [32.5.3. When to Use Pipeline Mode](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-TIPS) libpq pipeline mode allows applications to send a query without having to read the result of the previously sent query. Taking advantage of the pipeline mode, a client will wait less for the server, since multiple queries/results can be sent/received in a single network transaction. While pipeline mode provides a significant performance boost, writing clients using the pipeline mode is more complex because it involves managing a queue of pending queries and finding which result corresponds to which query in the queue. Pipeline mode also generally consumes more memory on both the client and server, though careful and aggressive management of the send/receive queue can mitigate this. This applies whether or not the connection is in blocking or non-blocking mode. While libpq's pipeline API was introduced in PostgreSQL 14, it is a client-side feature which doesn't require special server support and works on any server that supports the v3 extended query protocol. For more information see [Section 54.2.4](https://www.postgresql.org/docs/18/protocol-flow.html#PROTOCOL-FLOW-PIPELINING "54.2.4. Pipelining") . ### 32.5.1. Using Pipeline Mode [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-USING) To issue pipelines, the application must switch the connection into pipeline mode, which is done with [`PQenterPipelineMode`](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PQENTERPIPELINEMODE) . [`PQpipelineStatus`](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PQPIPELINESTATUS) can be used to test whether pipeline mode is active. In pipeline mode, only [asynchronous operations](https://www.postgresql.org/docs/18/libpq-async.html "32.4. Asynchronous Command Processing") that utilize the extended query protocol are permitted, command strings containing multiple SQL commands are disallowed, and so is `COPY`. Using synchronous command execution functions such as `PQfn`, `PQexec`, `PQexecParams`, `PQprepare`, `PQexecPrepared`, `PQdescribePrepared`, `PQdescribePortal`, `PQclosePrepared`, `PQclosePortal`, is an error condition. `PQsendQuery` is also disallowed, because it uses the simple query protocol. Once all dispatched commands have had their results processed, and the end pipeline result has been consumed, the application may return to non-pipelined mode with [`PQexitPipelineMode`](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PQEXITPIPELINEMODE) . ### Note It is best to use pipeline mode with libpq in [non-blocking mode](https://www.postgresql.org/docs/18/libpq-async.html#LIBPQ-PQSETNONBLOCKING) . If used in blocking mode it is possible for a client/server deadlock to occur. [\[15\]](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#ftn.id-1.7.3.12.9.3.1.3) #### 32.5.1.1. Issuing Queries [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-SENDING) After entering pipeline mode, the application dispatches requests using [`PQsendQueryParams`](https://www.postgresql.org/docs/18/libpq-async.html#LIBPQ-PQSENDQUERYPARAMS) or its prepared-query sibling [`PQsendQueryPrepared`](https://www.postgresql.org/docs/18/libpq-async.html#LIBPQ-PQSENDQUERYPREPARED) . These requests are queued on the client-side until flushed to the server; this occurs when [`PQpipelineSync`](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PQPIPELINESYNC) is used to establish a synchronization point in the pipeline, or when [`PQflush`](https://www.postgresql.org/docs/18/libpq-async.html#LIBPQ-PQFLUSH) is called. The functions [`PQsendPrepare`](https://www.postgresql.org/docs/18/libpq-async.html#LIBPQ-PQSENDPREPARE) , [`PQsendDescribePrepared`](https://www.postgresql.org/docs/18/libpq-async.html#LIBPQ-PQSENDDESCRIBEPREPARED) , [`PQsendDescribePortal`](https://www.postgresql.org/docs/18/libpq-async.html#LIBPQ-PQSENDDESCRIBEPORTAL) , [`PQsendClosePrepared`](https://www.postgresql.org/docs/18/libpq-async.html#LIBPQ-PQSENDCLOSEPREPARED) , and [`PQsendClosePortal`](https://www.postgresql.org/docs/18/libpq-async.html#LIBPQ-PQSENDCLOSEPORTAL) also work in pipeline mode. Result processing is described below. The server executes statements, and returns results, in the order the client sends them. The server will begin executing the commands in the pipeline immediately, not waiting for the end of the pipeline. Note that results are buffered on the server side; the server flushes that buffer when a synchronization point is established with either `PQpipelineSync` or `PQsendPipelineSync`, or when `PQsendFlushRequest` is called. If any statement encounters an error, the server aborts the current transaction and does not execute any subsequent command in the queue until the next synchronization point; a `PGRES_PIPELINE_ABORTED` result is produced for each such command. (This remains true even if the commands in the pipeline would rollback the transaction.) Query processing resumes after the synchronization point. It's fine for one operation to depend on the results of a prior one; for example, one query may define a table that the next query in the same pipeline uses. Similarly, an application may create a named prepared statement and execute it with later statements in the same pipeline. #### 32.5.1.2. Processing Results [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-RESULTS) To process the result of one query in a pipeline, the application calls `PQgetResult` repeatedly and handles each result until `PQgetResult` returns null. The result from the next query in the pipeline may then be retrieved using `PQgetResult` again and the cycle repeated. The application handles individual statement results as normal. When the results of all the queries in the pipeline have been returned, `PQgetResult` returns a result containing the status value `PGRES_PIPELINE_SYNC` The client may choose to defer result processing until the complete pipeline has been sent, or interleave that with sending further queries in the pipeline; see [Section 32.5.1.4](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-INTERLEAVE "32.5.1.4. Interleaving Result Processing and Query Dispatch") . `PQgetResult` behaves the same as for normal asynchronous processing except that it may contain the new `PGresult` types `PGRES_PIPELINE_SYNC` and `PGRES_PIPELINE_ABORTED`. `PGRES_PIPELINE_SYNC` is reported exactly once for each `PQpipelineSync` or `PQsendPipelineSync` at the corresponding point in the pipeline. `PGRES_PIPELINE_ABORTED` is emitted in place of a normal query result for the first error and all subsequent results until the next `PGRES_PIPELINE_SYNC`; see [Section 32.5.1.3](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-ERRORS "32.5.1.3. Error Handling") . `PQisBusy`, `PQconsumeInput`, etc operate as normal when processing pipeline results. In particular, a call to `PQisBusy` in the middle of a pipeline returns 0 if the results for all the queries issued so far have been consumed. libpq does not provide any information to the application about the query currently being processed (except that `PQgetResult` returns null to indicate that we start returning the results of next query). The application must keep track of the order in which it sent queries, to associate them with their corresponding results. Applications will typically use a state machine or a FIFO queue for this. #### 32.5.1.3. Error Handling [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-ERRORS) From the client's perspective, after `PQresultStatus` returns `PGRES_FATAL_ERROR`, the pipeline is flagged as aborted. `PQresultStatus` will report a `PGRES_PIPELINE_ABORTED` result for each remaining queued operation in an aborted pipeline. The result for `PQpipelineSync` or `PQsendPipelineSync` is reported as `PGRES_PIPELINE_SYNC` to signal the end of the aborted pipeline and resumption of normal result processing. The client _must_ process results with `PQgetResult` during error recovery. If the pipeline used an implicit transaction, then operations that have already executed are rolled back and operations that were queued to follow the failed operation are skipped entirely. The same behavior holds if the pipeline starts and commits a single explicit transaction (i.e. the first statement is `BEGIN` and the last is `COMMIT`) except that the session remains in an aborted transaction state at the end of the pipeline. If a pipeline contains _multiple explicit transactions_, all transactions that committed prior to the error remain committed, the currently in-progress transaction is aborted, and all subsequent operations are skipped completely, including subsequent transactions. If a pipeline synchronization point occurs with an explicit transaction block in aborted state, the next pipeline will become aborted immediately unless the next command puts the transaction in normal mode with `ROLLBACK`. ### Note The client must not assume that work is committed when it _sends_ a `COMMIT` — only when the corresponding result is received to confirm the commit is complete. Because errors arrive asynchronously, the application needs to be able to restart from the last _received_ committed change and resend work done after that point if something goes wrong. #### 32.5.1.4. Interleaving Result Processing and Query Dispatch [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-INTERLEAVE) To avoid deadlocks on large pipelines the client should be structured around a non-blocking event loop using operating system facilities such as `select`, `poll`, `WaitForMultipleObjectEx`, etc. The client application should generally maintain a queue of work remaining to be dispatched and a queue of work that has been dispatched but not yet had its results processed. When the socket is writable it should dispatch more work. When the socket is readable it should read results and process them, matching them up to the next entry in its corresponding results queue. Based on available memory, results from the socket should be read frequently: there's no need to wait until the pipeline end to read the results. Pipelines should be scoped to logical units of work, usually (but not necessarily) one transaction per pipeline. There's no need to exit pipeline mode and re-enter it between pipelines, or to wait for one pipeline to finish before sending the next. An example using `select()` and a simple state machine to track sent and received work is in `src/test/modules/libpq_pipeline/libpq_pipeline.c` in the PostgreSQL source distribution. ### 32.5.2. Functions Associated with Pipeline Mode [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-FUNCTIONS) `PQpipelineStatus` [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PQPIPELINESTATUS) Returns the current pipeline mode status of the libpq connection. PGpipelineStatus PQpipelineStatus(const PGconn \*conn); `PQpipelineStatus` can return one of the following values: `PQ_PIPELINE_ON` The libpq connection is in pipeline mode. `PQ_PIPELINE_OFF` The libpq connection is _not_ in pipeline mode. `PQ_PIPELINE_ABORTED` The libpq connection is in pipeline mode and an error occurred while processing the current pipeline. The aborted flag is cleared when `PQgetResult` returns a result of type `PGRES_PIPELINE_SYNC`. `PQenterPipelineMode` [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PQENTERPIPELINEMODE) Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode. int PQenterPipelineMode(PGconn \*conn); Returns 1 for success. Returns 0 and has no effect if the connection is not currently idle, i.e., it has a result ready, or it is waiting for more input from the server, etc. This function does not actually send anything to the server, it just changes the libpq connection state. `PQexitPipelineMode` [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PQEXITPIPELINEMODE) Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results. int PQexitPipelineMode(PGconn \*conn); Returns 1 for success. Returns 1 and takes no action if not in pipeline mode. If the current statement isn't finished processing, or `PQgetResult` has not been called to collect results from all previously sent query, returns 0 (in which case, use [`PQerrorMessage`](https://www.postgresql.org/docs/18/libpq-status.html#LIBPQ-PQERRORMESSAGE) to get more information about the failure). `PQpipelineSync` [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PQPIPELINESYNC) Marks a synchronization point in a pipeline by sending a [sync message](https://www.postgresql.org/docs/18/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY "54.2.3. Extended Query") and flushing the send buffer. This serves as the delimiter of an implicit transaction and an error recovery point; see [Section 32.5.1.3](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-ERRORS "32.5.1.3. Error Handling") . int PQpipelineSync(PGconn \*conn); Returns 1 for success. Returns 0 if the connection is not in pipeline mode or sending a [sync message](https://www.postgresql.org/docs/18/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY "54.2.3. Extended Query") failed. `PQsendPipelineSync` [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PQSENDPIPELINESYNC) Marks a synchronization point in a pipeline by sending a [sync message](https://www.postgresql.org/docs/18/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY "54.2.3. Extended Query") without flushing the send buffer. This serves as the delimiter of an implicit transaction and an error recovery point; see [Section 32.5.1.3](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-ERRORS "32.5.1.3. Error Handling") . int PQsendPipelineSync(PGconn \*conn); Returns 1 for success. Returns 0 if the connection is not in pipeline mode or sending a [sync message](https://www.postgresql.org/docs/18/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY "54.2.3. Extended Query") failed. Note that the message is not itself flushed to the server automatically; use `PQflush` if necessary. `PQsendFlushRequest` [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PQSENDFLUSHREQUEST) Sends a request for the server to flush its output buffer. int PQsendFlushRequest(PGconn \*conn); Returns 1 for success. Returns 0 on any failure. The server flushes its output buffer automatically as a result of `PQpipelineSync` being called, or on any request when not in pipeline mode; this function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point. Note that the request is not itself flushed to the server automatically; use `PQflush` if necessary. ### 32.5.3. When to Use Pipeline Mode [#](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-TIPS) Much like asynchronous query mode, there is no meaningful performance overhead when using pipeline mode. It increases client application complexity, and extra caution is required to prevent client/server deadlocks, but pipeline mode can offer considerable performance improvements, in exchange for increased memory usage from leaving state around longer. Pipeline mode is most useful when the server is distant, i.e., network latency (“ping time”) is high, and also when many small operations are being performed in rapid succession. There is usually less benefit in using pipelined commands when each query takes many multiples of the client/server round-trip time to execute. A 100-statement operation run on a server 300 ms round-trip-time away would take 30 seconds in network latency alone without pipelining; with pipelining it may spend as little as 0.3 s waiting for results from the server. Use pipelined commands when your application does lots of small `INSERT`, `UPDATE` and `DELETE` operations that can't easily be transformed into operations on sets, or into a `COPY` operation. Pipeline mode is not useful when information from one operation is required by the client to produce the next operation. In such cases, the client would have to introduce a synchronization point and wait for a full client/server round-trip to get the results it needs. However, it's often possible to adjust the client design to exchange the required information server-side. Read-modify-write cycles are especially good candidates; for example: BEGIN; SELECT x FROM mytable WHERE id = 42 FOR UPDATE; -- result: x=2 -- client adds 1 to x: UPDATE mytable SET x = 3 WHERE id = 42; COMMIT; could be much more efficiently done with: UPDATE mytable SET x = x + 1 WHERE id = 42; Pipelining is less useful, and more complex, when a single pipeline contains multiple transactions (see [Section 32.5.1.3](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#LIBPQ-PIPELINE-ERRORS "32.5.1.3. Error Handling") ). * * * [\[15\]](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html#id-1.7.3.12.9.3.1.3) The client will block trying to send queries to the server, but the server will block trying to send results to the client from queries it has already processed. This only occurs when the client sends enough queries to fill both its output buffer and the server's receive buffer before it switches to processing input from the server, but it's hard to predict exactly when that will happen. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/libpq-async.html "32.4. Asynchronous Command Processing") | [Up](https://www.postgresql.org/docs/18/libpq.html "Chapter 32. libpq — C Library") | [Next](https://www.postgresql.org/docs/18/libpq-single-row-mode.html "32.6. Retrieving Query Results in Chunks") | | 32.4. Asynchronous Command Processing | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 32.6. Retrieving Query Results in Chunks | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/libpq-pipeline-mode.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: DROP PUBLICATION November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-droppublication.html "PostgreSQL 18 - DROP PUBLICATION") ([18](https://www.postgresql.org/docs/18/sql-droppublication.html "PostgreSQL 18 - DROP PUBLICATION") ) / [17](https://www.postgresql.org/docs/17/sql-droppublication.html "PostgreSQL 17 - DROP PUBLICATION") / [16](https://www.postgresql.org/docs/16/sql-droppublication.html "PostgreSQL 16 - DROP PUBLICATION") / [15](https://www.postgresql.org/docs/15/sql-droppublication.html "PostgreSQL 15 - DROP PUBLICATION") / [14](https://www.postgresql.org/docs/14/sql-droppublication.html "PostgreSQL 14 - DROP PUBLICATION") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-droppublication.html "PostgreSQL devel - DROP PUBLICATION") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-droppublication.html "PostgreSQL 13 - DROP PUBLICATION") / [12](https://www.postgresql.org/docs/12/sql-droppublication.html "PostgreSQL 12 - DROP PUBLICATION") / [11](https://www.postgresql.org/docs/11/sql-droppublication.html "PostgreSQL 11 - DROP PUBLICATION") / [10](https://www.postgresql.org/docs/10/sql-droppublication.html "PostgreSQL 10 - DROP PUBLICATION") | DROP PUBLICATION | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-dropprocedure.html "DROP PROCEDURE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-droprole.html "DROP ROLE") | * * * DROP PUBLICATION ---------------- DROP PUBLICATION — remove a publication Synopsis -------- DROP PUBLICATION \[ IF EXISTS \] _`name`_ \[, ...\] \[ CASCADE | RESTRICT \] Description ----------- `DROP PUBLICATION` removes an existing publication from the database. A publication can only be dropped by its owner or a superuser. Parameters ---------- `IF EXISTS` Do not throw an error if the publication does not exist. A notice is issued in this case. _`name`_ The name of an existing publication. `CASCADE` `RESTRICT` These key words do not have any effect, since there are no dependencies on publications. Examples -------- Drop a publication: DROP PUBLICATION mypublication; Compatibility ------------- `DROP PUBLICATION` is a PostgreSQL extension. See Also -------- [CREATE PUBLICATION](https://www.postgresql.org/docs/current/sql-createpublication.html "CREATE PUBLICATION") , [ALTER PUBLICATION](https://www.postgresql.org/docs/current/sql-alterpublication.html "ALTER PUBLICATION") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-dropprocedure.html "DROP PROCEDURE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-droprole.html "DROP ROLE") | | DROP PROCEDURE | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | DROP ROLE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-droppublication.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 32.5. Pipeline Mode November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html "PostgreSQL 18 - 32.5. Pipeline Mode") ([18](https://www.postgresql.org/docs/18/libpq-pipeline-mode.html "PostgreSQL 18 - 32.5. Pipeline Mode") ) / [17](https://www.postgresql.org/docs/17/libpq-pipeline-mode.html "PostgreSQL 17 - 32.5. Pipeline Mode") / [16](https://www.postgresql.org/docs/16/libpq-pipeline-mode.html "PostgreSQL 16 - 32.5. Pipeline Mode") / [15](https://www.postgresql.org/docs/15/libpq-pipeline-mode.html "PostgreSQL 15 - 32.5. Pipeline Mode") / [14](https://www.postgresql.org/docs/14/libpq-pipeline-mode.html "PostgreSQL 14 - 32.5. Pipeline Mode") Development Versions: [devel](https://www.postgresql.org/docs/devel/libpq-pipeline-mode.html "PostgreSQL devel - 32.5. Pipeline Mode") | 32.5. Pipeline Mode | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/libpq-async.html "32.4. Asynchronous Command Processing") | [Up](https://www.postgresql.org/docs/current/libpq.html "Chapter 32. libpq — C Library") | Chapter 32. libpq — C Library | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/libpq-single-row-mode.html "32.6. Retrieving Query Results in Chunks") | * * * 32.5. Pipeline Mode [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-MODE) -------------------------------------------------------------------------------------------------------------- [32.5.1. Using Pipeline Mode](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-USING) [32.5.2. Functions Associated with Pipeline Mode](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-FUNCTIONS) [32.5.3. When to Use Pipeline Mode](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-TIPS) libpq pipeline mode allows applications to send a query without having to read the result of the previously sent query. Taking advantage of the pipeline mode, a client will wait less for the server, since multiple queries/results can be sent/received in a single network transaction. While pipeline mode provides a significant performance boost, writing clients using the pipeline mode is more complex because it involves managing a queue of pending queries and finding which result corresponds to which query in the queue. Pipeline mode also generally consumes more memory on both the client and server, though careful and aggressive management of the send/receive queue can mitigate this. This applies whether or not the connection is in blocking or non-blocking mode. While libpq's pipeline API was introduced in PostgreSQL 14, it is a client-side feature which doesn't require special server support and works on any server that supports the v3 extended query protocol. For more information see [Section 54.2.4](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-PIPELINING "54.2.4. Pipelining") . ### 32.5.1. Using Pipeline Mode [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-USING) To issue pipelines, the application must switch the connection into pipeline mode, which is done with [`PQenterPipelineMode`](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PQENTERPIPELINEMODE) . [`PQpipelineStatus`](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PQPIPELINESTATUS) can be used to test whether pipeline mode is active. In pipeline mode, only [asynchronous operations](https://www.postgresql.org/docs/current/libpq-async.html "32.4. Asynchronous Command Processing") that utilize the extended query protocol are permitted, command strings containing multiple SQL commands are disallowed, and so is `COPY`. Using synchronous command execution functions such as `PQfn`, `PQexec`, `PQexecParams`, `PQprepare`, `PQexecPrepared`, `PQdescribePrepared`, `PQdescribePortal`, `PQclosePrepared`, `PQclosePortal`, is an error condition. `PQsendQuery` is also disallowed, because it uses the simple query protocol. Once all dispatched commands have had their results processed, and the end pipeline result has been consumed, the application may return to non-pipelined mode with [`PQexitPipelineMode`](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PQEXITPIPELINEMODE) . ### Note It is best to use pipeline mode with libpq in [non-blocking mode](https://www.postgresql.org/docs/current/libpq-async.html#LIBPQ-PQSETNONBLOCKING) . If used in blocking mode it is possible for a client/server deadlock to occur. [\[15\]](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#ftn.id-1.7.3.12.9.3.1.3) #### 32.5.1.1. Issuing Queries [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-SENDING) After entering pipeline mode, the application dispatches requests using [`PQsendQueryParams`](https://www.postgresql.org/docs/current/libpq-async.html#LIBPQ-PQSENDQUERYPARAMS) or its prepared-query sibling [`PQsendQueryPrepared`](https://www.postgresql.org/docs/current/libpq-async.html#LIBPQ-PQSENDQUERYPREPARED) . These requests are queued on the client-side until flushed to the server; this occurs when [`PQpipelineSync`](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PQPIPELINESYNC) is used to establish a synchronization point in the pipeline, or when [`PQflush`](https://www.postgresql.org/docs/current/libpq-async.html#LIBPQ-PQFLUSH) is called. The functions [`PQsendPrepare`](https://www.postgresql.org/docs/current/libpq-async.html#LIBPQ-PQSENDPREPARE) , [`PQsendDescribePrepared`](https://www.postgresql.org/docs/current/libpq-async.html#LIBPQ-PQSENDDESCRIBEPREPARED) , [`PQsendDescribePortal`](https://www.postgresql.org/docs/current/libpq-async.html#LIBPQ-PQSENDDESCRIBEPORTAL) , [`PQsendClosePrepared`](https://www.postgresql.org/docs/current/libpq-async.html#LIBPQ-PQSENDCLOSEPREPARED) , and [`PQsendClosePortal`](https://www.postgresql.org/docs/current/libpq-async.html#LIBPQ-PQSENDCLOSEPORTAL) also work in pipeline mode. Result processing is described below. The server executes statements, and returns results, in the order the client sends them. The server will begin executing the commands in the pipeline immediately, not waiting for the end of the pipeline. Note that results are buffered on the server side; the server flushes that buffer when a synchronization point is established with either `PQpipelineSync` or `PQsendPipelineSync`, or when `PQsendFlushRequest` is called. If any statement encounters an error, the server aborts the current transaction and does not execute any subsequent command in the queue until the next synchronization point; a `PGRES_PIPELINE_ABORTED` result is produced for each such command. (This remains true even if the commands in the pipeline would rollback the transaction.) Query processing resumes after the synchronization point. It's fine for one operation to depend on the results of a prior one; for example, one query may define a table that the next query in the same pipeline uses. Similarly, an application may create a named prepared statement and execute it with later statements in the same pipeline. #### 32.5.1.2. Processing Results [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-RESULTS) To process the result of one query in a pipeline, the application calls `PQgetResult` repeatedly and handles each result until `PQgetResult` returns null. The result from the next query in the pipeline may then be retrieved using `PQgetResult` again and the cycle repeated. The application handles individual statement results as normal. When the results of all the queries in the pipeline have been returned, `PQgetResult` returns a result containing the status value `PGRES_PIPELINE_SYNC` The client may choose to defer result processing until the complete pipeline has been sent, or interleave that with sending further queries in the pipeline; see [Section 32.5.1.4](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-INTERLEAVE "32.5.1.4. Interleaving Result Processing and Query Dispatch") . `PQgetResult` behaves the same as for normal asynchronous processing except that it may contain the new `PGresult` types `PGRES_PIPELINE_SYNC` and `PGRES_PIPELINE_ABORTED`. `PGRES_PIPELINE_SYNC` is reported exactly once for each `PQpipelineSync` or `PQsendPipelineSync` at the corresponding point in the pipeline. `PGRES_PIPELINE_ABORTED` is emitted in place of a normal query result for the first error and all subsequent results until the next `PGRES_PIPELINE_SYNC`; see [Section 32.5.1.3](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-ERRORS "32.5.1.3. Error Handling") . `PQisBusy`, `PQconsumeInput`, etc operate as normal when processing pipeline results. In particular, a call to `PQisBusy` in the middle of a pipeline returns 0 if the results for all the queries issued so far have been consumed. libpq does not provide any information to the application about the query currently being processed (except that `PQgetResult` returns null to indicate that we start returning the results of next query). The application must keep track of the order in which it sent queries, to associate them with their corresponding results. Applications will typically use a state machine or a FIFO queue for this. #### 32.5.1.3. Error Handling [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-ERRORS) From the client's perspective, after `PQresultStatus` returns `PGRES_FATAL_ERROR`, the pipeline is flagged as aborted. `PQresultStatus` will report a `PGRES_PIPELINE_ABORTED` result for each remaining queued operation in an aborted pipeline. The result for `PQpipelineSync` or `PQsendPipelineSync` is reported as `PGRES_PIPELINE_SYNC` to signal the end of the aborted pipeline and resumption of normal result processing. The client _must_ process results with `PQgetResult` during error recovery. If the pipeline used an implicit transaction, then operations that have already executed are rolled back and operations that were queued to follow the failed operation are skipped entirely. The same behavior holds if the pipeline starts and commits a single explicit transaction (i.e. the first statement is `BEGIN` and the last is `COMMIT`) except that the session remains in an aborted transaction state at the end of the pipeline. If a pipeline contains _multiple explicit transactions_, all transactions that committed prior to the error remain committed, the currently in-progress transaction is aborted, and all subsequent operations are skipped completely, including subsequent transactions. If a pipeline synchronization point occurs with an explicit transaction block in aborted state, the next pipeline will become aborted immediately unless the next command puts the transaction in normal mode with `ROLLBACK`. ### Note The client must not assume that work is committed when it _sends_ a `COMMIT` — only when the corresponding result is received to confirm the commit is complete. Because errors arrive asynchronously, the application needs to be able to restart from the last _received_ committed change and resend work done after that point if something goes wrong. #### 32.5.1.4. Interleaving Result Processing and Query Dispatch [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-INTERLEAVE) To avoid deadlocks on large pipelines the client should be structured around a non-blocking event loop using operating system facilities such as `select`, `poll`, `WaitForMultipleObjectEx`, etc. The client application should generally maintain a queue of work remaining to be dispatched and a queue of work that has been dispatched but not yet had its results processed. When the socket is writable it should dispatch more work. When the socket is readable it should read results and process them, matching them up to the next entry in its corresponding results queue. Based on available memory, results from the socket should be read frequently: there's no need to wait until the pipeline end to read the results. Pipelines should be scoped to logical units of work, usually (but not necessarily) one transaction per pipeline. There's no need to exit pipeline mode and re-enter it between pipelines, or to wait for one pipeline to finish before sending the next. An example using `select()` and a simple state machine to track sent and received work is in `src/test/modules/libpq_pipeline/libpq_pipeline.c` in the PostgreSQL source distribution. ### 32.5.2. Functions Associated with Pipeline Mode [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-FUNCTIONS) `PQpipelineStatus` [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PQPIPELINESTATUS) Returns the current pipeline mode status of the libpq connection. PGpipelineStatus PQpipelineStatus(const PGconn \*conn); `PQpipelineStatus` can return one of the following values: `PQ_PIPELINE_ON` The libpq connection is in pipeline mode. `PQ_PIPELINE_OFF` The libpq connection is _not_ in pipeline mode. `PQ_PIPELINE_ABORTED` The libpq connection is in pipeline mode and an error occurred while processing the current pipeline. The aborted flag is cleared when `PQgetResult` returns a result of type `PGRES_PIPELINE_SYNC`. `PQenterPipelineMode` [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PQENTERPIPELINEMODE) Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode. int PQenterPipelineMode(PGconn \*conn); Returns 1 for success. Returns 0 and has no effect if the connection is not currently idle, i.e., it has a result ready, or it is waiting for more input from the server, etc. This function does not actually send anything to the server, it just changes the libpq connection state. `PQexitPipelineMode` [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PQEXITPIPELINEMODE) Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results. int PQexitPipelineMode(PGconn \*conn); Returns 1 for success. Returns 1 and takes no action if not in pipeline mode. If the current statement isn't finished processing, or `PQgetResult` has not been called to collect results from all previously sent query, returns 0 (in which case, use [`PQerrorMessage`](https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQERRORMESSAGE) to get more information about the failure). `PQpipelineSync` [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PQPIPELINESYNC) Marks a synchronization point in a pipeline by sending a [sync message](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY "54.2.3. Extended Query") and flushing the send buffer. This serves as the delimiter of an implicit transaction and an error recovery point; see [Section 32.5.1.3](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-ERRORS "32.5.1.3. Error Handling") . int PQpipelineSync(PGconn \*conn); Returns 1 for success. Returns 0 if the connection is not in pipeline mode or sending a [sync message](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY "54.2.3. Extended Query") failed. `PQsendPipelineSync` [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PQSENDPIPELINESYNC) Marks a synchronization point in a pipeline by sending a [sync message](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY "54.2.3. Extended Query") without flushing the send buffer. This serves as the delimiter of an implicit transaction and an error recovery point; see [Section 32.5.1.3](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-ERRORS "32.5.1.3. Error Handling") . int PQsendPipelineSync(PGconn \*conn); Returns 1 for success. Returns 0 if the connection is not in pipeline mode or sending a [sync message](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY "54.2.3. Extended Query") failed. Note that the message is not itself flushed to the server automatically; use `PQflush` if necessary. `PQsendFlushRequest` [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PQSENDFLUSHREQUEST) Sends a request for the server to flush its output buffer. int PQsendFlushRequest(PGconn \*conn); Returns 1 for success. Returns 0 on any failure. The server flushes its output buffer automatically as a result of `PQpipelineSync` being called, or on any request when not in pipeline mode; this function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point. Note that the request is not itself flushed to the server automatically; use `PQflush` if necessary. ### 32.5.3. When to Use Pipeline Mode [#](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-TIPS) Much like asynchronous query mode, there is no meaningful performance overhead when using pipeline mode. It increases client application complexity, and extra caution is required to prevent client/server deadlocks, but pipeline mode can offer considerable performance improvements, in exchange for increased memory usage from leaving state around longer. Pipeline mode is most useful when the server is distant, i.e., network latency (“ping time”) is high, and also when many small operations are being performed in rapid succession. There is usually less benefit in using pipelined commands when each query takes many multiples of the client/server round-trip time to execute. A 100-statement operation run on a server 300 ms round-trip-time away would take 30 seconds in network latency alone without pipelining; with pipelining it may spend as little as 0.3 s waiting for results from the server. Use pipelined commands when your application does lots of small `INSERT`, `UPDATE` and `DELETE` operations that can't easily be transformed into operations on sets, or into a `COPY` operation. Pipeline mode is not useful when information from one operation is required by the client to produce the next operation. In such cases, the client would have to introduce a synchronization point and wait for a full client/server round-trip to get the results it needs. However, it's often possible to adjust the client design to exchange the required information server-side. Read-modify-write cycles are especially good candidates; for example: BEGIN; SELECT x FROM mytable WHERE id = 42 FOR UPDATE; -- result: x=2 -- client adds 1 to x: UPDATE mytable SET x = 3 WHERE id = 42; COMMIT; could be much more efficiently done with: UPDATE mytable SET x = x + 1 WHERE id = 42; Pipelining is less useful, and more complex, when a single pipeline contains multiple transactions (see [Section 32.5.1.3](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-ERRORS "32.5.1.3. Error Handling") ). * * * [\[15\]](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#id-1.7.3.12.9.3.1.3) The client will block trying to send queries to the server, but the server will block trying to send results to the client from queries it has already processed. This only occurs when the client sends enough queries to fill both its output buffer and the server's receive buffer before it switches to processing input from the server, but it's hard to predict exactly when that will happen. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/libpq-async.html "32.4. Asynchronous Command Processing") | [Up](https://www.postgresql.org/docs/current/libpq.html "Chapter 32. libpq — C Library") | [Next](https://www.postgresql.org/docs/current/libpq-single-row-mode.html "32.6. Retrieving Query Results in Chunks") | | 32.4. Asynchronous Command Processing | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 32.6. Retrieving Query Results in Chunks | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/libpq-pipeline-mode.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 29.13. Upgrade November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/logical-replication-upgrade.html "PostgreSQL 18 - 29.13. Upgrade") ([18](https://www.postgresql.org/docs/18/logical-replication-upgrade.html "PostgreSQL 18 - 29.13. Upgrade") ) Development Versions: [devel](https://www.postgresql.org/docs/devel/logical-replication-upgrade.html "PostgreSQL devel - 29.13. Upgrade") | 29.13. Upgrade | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/logical-replication-config.html "29.12. Configuration Settings") | [Up](https://www.postgresql.org/docs/18/logical-replication.html "Chapter 29. Logical Replication") | Chapter 29. Logical Replication | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/logical-replication-quick-setup.html "29.14. Quick Setup") | * * * 29.13. Upgrade [#](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#LOGICAL-REPLICATION-UPGRADE) -------------------------------------------------------------------------------------------------------------------- [29.13.1. Prepare for Publisher Upgrades](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#PREPARE-PUBLISHER-UPGRADES) [29.13.2. Prepare for Subscriber Upgrades](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#PREPARE-SUBSCRIBER-UPGRADES) [29.13.3. Upgrading Logical Replication Clusters](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#UPGRADING-LOGICAL-REPLICATION-CLUSTERS) Migration of [](https://www.postgresql.org/docs/18/glossary.html#GLOSSARY-LOGICAL-REPLICATION-CLUSTER) [logical replication clusters](https://www.postgresql.org/docs/18/glossary.html#GLOSSARY-LOGICAL-REPLICATION-CLUSTER "Logical replication cluster") is possible only when all the members of the old logical replication clusters are version 17.0 or later. ### 29.13.1. Prepare for Publisher Upgrades [#](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#PREPARE-PUBLISHER-UPGRADES) pg\_upgrade attempts to migrate logical slots. This helps avoid the need for manually defining the same logical slots on the new publisher. Migration of logical slots is only supported when the old cluster is version 17.0 or later. Logical slots on clusters before version 17.0 will silently be ignored. Before you start upgrading the publisher cluster, ensure that the subscription is temporarily disabled, by executing [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/18/sql-altersubscription.html "ALTER SUBSCRIPTION") . Re-enable the subscription after the upgrade. There are some prerequisites for pg\_upgrade to be able to upgrade the logical slots. If these are not met an error will be reported. * The new cluster must have [`wal_level`](https://www.postgresql.org/docs/18/runtime-config-wal.html#GUC-WAL-LEVEL) as `logical`. * The new cluster must have [`max_replication_slots`](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-REPLICATION-SLOTS) configured to a value greater than or equal to the number of slots present in the old cluster. * The output plugins referenced by the slots on the old cluster must be installed in the new PostgreSQL executable directory. * The old cluster has replicated all the transactions and logical decoding messages to subscribers. * All slots on the old cluster must be usable, i.e., there are no slots whose [pg\_replication\_slots](https://www.postgresql.org/docs/18/view-pg-replication-slots.html "53.20. pg_replication_slots") .`conflicting` is not `true`. * The new cluster must not have permanent logical slots, i.e., there must be no slots where [pg\_replication\_slots](https://www.postgresql.org/docs/18/view-pg-replication-slots.html "53.20. pg_replication_slots") .`temporary` is `false`. ### 29.13.2. Prepare for Subscriber Upgrades [#](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#PREPARE-SUBSCRIBER-UPGRADES) Setup the [subscriber configurations](https://www.postgresql.org/docs/18/logical-replication-config.html#LOGICAL-REPLICATION-CONFIG-SUBSCRIBER "29.12.2. Subscribers") in the new subscriber. pg\_upgrade attempts to migrate subscription dependencies which includes the subscription's table information present in [pg\_subscription\_rel](https://www.postgresql.org/docs/18/catalog-pg-subscription-rel.html "52.55. pg_subscription_rel") system catalog and also the subscription's replication origin. This allows logical replication on the new subscriber to continue from where the old subscriber was up to. Migration of subscription dependencies is only supported when the old cluster is version 17.0 or later. Subscription dependencies on clusters before version 17.0 will silently be ignored. There are some prerequisites for pg\_upgrade to be able to upgrade the subscriptions. If these are not met an error will be reported. * All the subscription tables in the old subscriber should be in state `i` (initialize) or `r` (ready). This can be verified by checking [pg\_subscription\_rel](https://www.postgresql.org/docs/18/catalog-pg-subscription-rel.html "52.55. pg_subscription_rel") .`srsubstate`. * The replication origin entry corresponding to each of the subscriptions should exist in the old cluster. This can be found by checking [pg\_subscription](https://www.postgresql.org/docs/18/catalog-pg-subscription.html "52.54. pg_subscription") and [pg\_replication\_origin](https://www.postgresql.org/docs/18/catalog-pg-replication-origin.html "52.44. pg_replication_origin") system tables. * The new cluster must have [`max_active_replication_origins`](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-ACTIVE-REPLICATION-ORIGINS) configured to a value greater than or equal to the number of subscriptions present in the old cluster. ### 29.13.3. Upgrading Logical Replication Clusters [#](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#UPGRADING-LOGICAL-REPLICATION-CLUSTERS) While upgrading a subscriber, write operations can be performed in the publisher. These changes will be replicated to the subscriber once the subscriber upgrade is completed. ### Note The logical replication restrictions apply to logical replication cluster upgrades also. See [Section 29.8](https://www.postgresql.org/docs/18/logical-replication-restrictions.html "29.8. Restrictions") for details. The prerequisites of publisher upgrade apply to logical replication cluster upgrades also. See [Section 29.13.1](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#PREPARE-PUBLISHER-UPGRADES "29.13.1. Prepare for Publisher Upgrades") for details. The prerequisites of subscriber upgrade apply to logical replication cluster upgrades also. See [Section 29.13.2](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#PREPARE-SUBSCRIBER-UPGRADES "29.13.2. Prepare for Subscriber Upgrades") for details. ### Warning Upgrading logical replication cluster requires multiple steps to be performed on various nodes. Because not all operations are transactional, the user is advised to take backups as described in [Section 25.3.2](https://www.postgresql.org/docs/18/continuous-archiving.html#BACKUP-BASE-BACKUP "25.3.2. Making a Base Backup") . The steps to upgrade the following logical replication clusters are detailed below: * Follow the steps specified in [Section 29.13.3.1](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#STEPS-TWO-NODE-LOGICAL-REPLICATION-CLUSTER "29.13.3.1. Steps to Upgrade a Two-node Logical Replication Cluster") to upgrade a two-node logical replication cluster. * Follow the steps specified in [Section 29.13.3.2](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#STEPS-CASCADED-LOGICAL-REPLICATION-CLUSTER "29.13.3.2. Steps to Upgrade a Cascaded Logical Replication Cluster") to upgrade a cascaded logical replication cluster. * Follow the steps specified in [Section 29.13.3.3](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#STEPS-TWO-NODE-CIRCULAR-LOGICAL-REPLICATION-CLUSTER "29.13.3.3. Steps to Upgrade a Two-node Circular Logical Replication Cluster") to upgrade a two-node circular logical replication cluster. #### 29.13.3.1. Steps to Upgrade a Two-node Logical Replication Cluster [#](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#STEPS-TWO-NODE-LOGICAL-REPLICATION-CLUSTER) Let's say publisher is in `node1` and subscriber is in `node2`. The subscriber `node2` has a subscription `sub1_node1_node2` which is subscribing the changes from `node1`. 1. Disable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-DISABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 DISABLE; 2. Stop the publisher server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1 stop 3. Initialize `data1_upgraded` instance by using the required newer version. 4. Upgrade the publisher `node1`'s server to the required newer version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data1" --new-datadir "/opt/PostgreSQL/postgres/18/data1\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 5. Start the upgraded publisher server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1\_upgraded start -l logfile 6. Stop the subscriber server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2 stop 7. Initialize `data2_upgraded` instance by using the required newer version. 8. Upgrade the subscriber `node2`'s server to the required new version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data2" --new-datadir "/opt/PostgreSQL/postgres/18/data2\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 9. Start the upgraded subscriber server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2\_upgraded start -l logfile 10. On `node2`, create any tables that were created in the upgraded publisher `node1` server between [Step 1](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#TWO-NODE-CLUSTER-DISABLE-SUBSCRIPTIONS-NODE2 "Step 1") and now, e.g.: /\* node2 # \*/ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); 11. Enable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... ENABLE`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-ENABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 ENABLE; 12. Refresh the `node2` subscription's publications using [`ALTER SUBSCRIPTION ... REFRESH PUBLICATION`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-REFRESH-PUBLICATION) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 REFRESH PUBLICATION; ### Note In the steps described above, the publisher is upgraded first, followed by the subscriber. Alternatively, the user can use similar steps to upgrade the subscriber first, followed by the publisher. #### 29.13.3.2. Steps to Upgrade a Cascaded Logical Replication Cluster [#](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#STEPS-CASCADED-LOGICAL-REPLICATION-CLUSTER) Let's say we have a cascaded logical replication setup `node1`\->`node2`\->`node3`. Here `node2` is subscribing the changes from `node1` and `node3` is subscribing the changes from `node2`. The `node2` has a subscription `sub1_node1_node2` which is subscribing the changes from `node1`. The `node3` has a subscription `sub1_node2_node3` which is subscribing the changes from `node2`. 1. Disable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-DISABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 DISABLE; 2. Stop the server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1 stop 3. Initialize `data1_upgraded` instance by using the required newer version. 4. Upgrade the `node1`'s server to the required newer version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data1" --new-datadir "/opt/PostgreSQL/postgres/18/data1\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 5. Start the upgraded server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1\_upgraded start -l logfile 6. Disable all the subscriptions on `node3` that are subscribing the changes from `node2` by using [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-DISABLE) , e.g.: /\* node3 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node3 DISABLE; 7. Stop the server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2 stop 8. Initialize `data2_upgraded` instance by using the required newer version. 9. Upgrade the `node2`'s server to the required new version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data2" --new-datadir "/opt/PostgreSQL/postgres/18/data2\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 10. Start the upgraded server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2\_upgraded start -l logfile 11. On `node2`, create any tables that were created in the upgraded publisher `node1` server between [Step 1](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#CASCADED-CLUSTER-DISABLE-SUB-NODE1-NODE2 "Step 1") and now, e.g.: /\* node2 # \*/ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); 12. Enable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... ENABLE`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-ENABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 ENABLE; 13. Refresh the `node2` subscription's publications using [`ALTER SUBSCRIPTION ... REFRESH PUBLICATION`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-REFRESH-PUBLICATION) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 REFRESH PUBLICATION; 14. Stop the server in `node3`, e.g.: pg\_ctl -D /opt/PostgreSQL/data3 stop 15. Initialize `data3_upgraded` instance by using the required newer version. 16. Upgrade the `node3`'s server to the required new version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data3" --new-datadir "/opt/PostgreSQL/postgres/18/data3\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 17. Start the upgraded server in `node3`, e.g.: pg\_ctl -D /opt/PostgreSQL/data3\_upgraded start -l logfile 18. On `node3`, create any tables that were created in the upgraded `node2` between [Step 6](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#CASCADED-CLUSTER-DISABLE-SUB-NODE2-NODE3 "Step 6") and now, e.g.: /\* node3 # \*/ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); 19. Enable all the subscriptions on `node3` that are subscribing the changes from `node2` by using [`ALTER SUBSCRIPTION ... ENABLE`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-ENABLE) , e.g.: /\* node3 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node3 ENABLE; 20. Refresh the `node3` subscription's publications using [`ALTER SUBSCRIPTION ... REFRESH PUBLICATION`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-REFRESH-PUBLICATION) , e.g.: /\* node3 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node3 REFRESH PUBLICATION; #### 29.13.3.3. Steps to Upgrade a Two-node Circular Logical Replication Cluster [#](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#STEPS-TWO-NODE-CIRCULAR-LOGICAL-REPLICATION-CLUSTER) Let's say we have a circular logical replication setup `node1`\->`node2` and `node2`\->`node1`. Here `node2` is subscribing the changes from `node1` and `node1` is subscribing the changes from `node2`. The `node1` has a subscription `sub1_node2_node1` which is subscribing the changes from `node2`. The `node2` has a subscription `sub1_node1_node2` which is subscribing the changes from `node1`. 1. Disable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-DISABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 DISABLE; 2. Stop the server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1 stop 3. Initialize `data1_upgraded` instance by using the required newer version. 4. Upgrade the `node1`'s server to the required newer version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data1" --new-datadir "/opt/PostgreSQL/postgres/18/data1\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 5. Start the upgraded server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1\_upgraded start -l logfile 6. Enable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... ENABLE`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-ENABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 ENABLE; 7. On `node1`, create any tables that were created in `node2` between [Step 1](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#CIRCULAR-CLUSTER-DISABLE-SUB-NODE2 "Step 1") and now, e.g.: /\* node1 # \*/ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); 8. Refresh the `node1` subscription's publications to copy initial table data from `node2` using [`ALTER SUBSCRIPTION ... REFRESH PUBLICATION`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-REFRESH-PUBLICATION) , e.g.: /\* node1 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node1 REFRESH PUBLICATION; 9. Disable all the subscriptions on `node1` that are subscribing the changes from `node2` by using [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-DISABLE) , e.g.: /\* node1 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node1 DISABLE; 10. Stop the server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2 stop 11. Initialize `data2_upgraded` instance by using the required newer version. 12. Upgrade the `node2`'s server to the required new version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data2" --new-datadir "/opt/PostgreSQL/postgres/18/data2\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 13. Start the upgraded server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2\_upgraded start -l logfile 14. Enable all the subscriptions on `node1` that are subscribing the changes from `node2` by using [`ALTER SUBSCRIPTION ... ENABLE`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-ENABLE) , e.g.: /\* node1 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node1 ENABLE; 15. On `node2`, create any tables that were created in the upgraded `node1` between [Step 9](https://www.postgresql.org/docs/18/logical-replication-upgrade.html#CIRCULAR-CLUSTER-DISABLE-SUB-NODE1 "Step 9") and now, e.g.: /\* node2 # \*/ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); 16. Refresh the `node2` subscription's publications to copy initial table data from `node1` using [`ALTER SUBSCRIPTION ... REFRESH PUBLICATION`](https://www.postgresql.org/docs/18/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-REFRESH-PUBLICATION) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 REFRESH PUBLICATION; * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/logical-replication-config.html "29.12. Configuration Settings") | [Up](https://www.postgresql.org/docs/18/logical-replication.html "Chapter 29. Logical Replication") | [Next](https://www.postgresql.org/docs/18/logical-replication-quick-setup.html "29.14. Quick Setup") | | 29.12. Configuration Settings | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 29.14. Quick Setup | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/logical-replication-upgrade.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 15.1. How Parallel Query Works November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/how-parallel-query-works.html "PostgreSQL 18 - 15.1. How Parallel Query Works") ([18](https://www.postgresql.org/docs/18/how-parallel-query-works.html "PostgreSQL 18 - 15.1. How Parallel Query Works") ) / [17](https://www.postgresql.org/docs/17/how-parallel-query-works.html "PostgreSQL 17 - 15.1. How Parallel Query Works") / [16](https://www.postgresql.org/docs/16/how-parallel-query-works.html "PostgreSQL 16 - 15.1. How Parallel Query Works") / [15](https://www.postgresql.org/docs/15/how-parallel-query-works.html "PostgreSQL 15 - 15.1. How Parallel Query Works") / [14](https://www.postgresql.org/docs/14/how-parallel-query-works.html "PostgreSQL 14 - 15.1. How Parallel Query Works") Development Versions: [devel](https://www.postgresql.org/docs/devel/how-parallel-query-works.html "PostgreSQL devel - 15.1. How Parallel Query Works") Unsupported versions: [13](https://www.postgresql.org/docs/13/how-parallel-query-works.html "PostgreSQL 13 - 15.1. How Parallel Query Works") / [12](https://www.postgresql.org/docs/12/how-parallel-query-works.html "PostgreSQL 12 - 15.1. How Parallel Query Works") / [11](https://www.postgresql.org/docs/11/how-parallel-query-works.html "PostgreSQL 11 - 15.1. How Parallel Query Works") / [10](https://www.postgresql.org/docs/10/how-parallel-query-works.html "PostgreSQL 10 - 15.1. How Parallel Query Works") / [9.6](https://www.postgresql.org/docs/9.6/how-parallel-query-works.html "PostgreSQL 9.6 - 15.1. How Parallel Query Works") | 15.1. How Parallel Query Works | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/parallel-query.html "Chapter 15. Parallel Query") | [Up](https://www.postgresql.org/docs/18/parallel-query.html "Chapter 15. Parallel Query") | Chapter 15. Parallel Query | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/when-can-parallel-query-be-used.html "15.2. When Can Parallel Query Be Used?") | * * * 15.1. How Parallel Query Works [#](https://www.postgresql.org/docs/18/how-parallel-query-works.html#HOW-PARALLEL-QUERY-WORKS) ------------------------------------------------------------------------------------------------------------------------------ When the optimizer determines that parallel query is the fastest execution strategy for a particular query, it will create a query plan that includes a _Gather_ or _Gather Merge_ node. Here is a simple example: EXPLAIN SELECT \* FROM pgbench\_accounts WHERE filler LIKE '%x%'; QUERY PLAN -------------------------------------------------------------------​------------------ Gather (cost=1000.00..217018.43 rows=1 width=97) Workers Planned: 2 -> Parallel Seq Scan on pgbench\_accounts (cost=0.00..216018.33 rows=1 width=97) Filter: (filler ~~ '%x%'::text) (4 rows) In all cases, the `Gather` or `Gather Merge` node will have exactly one child plan, which is the portion of the plan that will be executed in parallel. If the `Gather` or `Gather Merge` node is at the very top of the plan tree, then the entire query will execute in parallel. If it is somewhere else in the plan tree, then only the portion of the plan below it will run in parallel. In the example above, the query accesses only one table, so there is only one plan node other than the `Gather` node itself; since that plan node is a child of the `Gather` node, it will run in parallel. [Using EXPLAIN](https://www.postgresql.org/docs/18/using-explain.html "14.1. Using EXPLAIN") , you can see the number of workers chosen by the planner. When the `Gather` node is reached during query execution, the process that is implementing the user's session will request a number of [background worker processes](https://www.postgresql.org/docs/18/bgworker.html "Chapter 46. Background Worker Processes") equal to the number of workers chosen by the planner. The number of background workers that the planner will consider using is limited to at most [max\_parallel\_workers\_per\_gather](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS-PER-GATHER) . The total number of background workers that can exist at any one time is limited by both [max\_worker\_processes](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES) and [max\_parallel\_workers](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS) . Therefore, it is possible for a parallel query to run with fewer workers than planned, or even with no workers at all. The optimal plan may depend on the number of workers that are available, so this can result in poor query performance. If this occurrence is frequent, consider increasing `max_worker_processes` and `max_parallel_workers` so that more workers can be run simultaneously or alternatively reducing `max_parallel_workers_per_gather` so that the planner requests fewer workers. Every background worker process that is successfully started for a given parallel query will execute the parallel portion of the plan. The leader will also execute that portion of the plan, but it has an additional responsibility: it must also read all of the tuples generated by the workers. When the parallel portion of the plan generates only a small number of tuples, the leader will often behave very much like an additional worker, speeding up query execution. Conversely, when the parallel portion of the plan generates a large number of tuples, the leader may be almost entirely occupied with reading the tuples generated by the workers and performing any further processing steps that are required by plan nodes above the level of the `Gather` node or `Gather Merge` node. In such cases, the leader will do very little of the work of executing the parallel portion of the plan. When the node at the top of the parallel portion of the plan is `Gather Merge` rather than `Gather`, it indicates that each process executing the parallel portion of the plan is producing tuples in sorted order, and that the leader is performing an order-preserving merge. In contrast, `Gather` reads tuples from the workers in whatever order is convenient, destroying any sort order that may have existed. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/parallel-query.html "Chapter 15. Parallel Query") | [Up](https://www.postgresql.org/docs/18/parallel-query.html "Chapter 15. Parallel Query") | [Next](https://www.postgresql.org/docs/18/when-can-parallel-query-be-used.html "15.2. When Can Parallel Query Be Used?") | | Chapter 15. Parallel Query | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 15.2. When Can Parallel Query Be Used? | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/how-parallel-query-works.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 29.13. Upgrade November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/logical-replication-upgrade.html "PostgreSQL 18 - 29.13. Upgrade") ([18](https://www.postgresql.org/docs/18/logical-replication-upgrade.html "PostgreSQL 18 - 29.13. Upgrade") ) Development Versions: [devel](https://www.postgresql.org/docs/devel/logical-replication-upgrade.html "PostgreSQL devel - 29.13. Upgrade") | 29.13. Upgrade | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/logical-replication-config.html "29.12. Configuration Settings") | [Up](https://www.postgresql.org/docs/current/logical-replication.html "Chapter 29. Logical Replication") | Chapter 29. Logical Replication | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/logical-replication-quick-setup.html "29.14. Quick Setup") | * * * 29.13. Upgrade [#](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#LOGICAL-REPLICATION-UPGRADE) ------------------------------------------------------------------------------------------------------------------------- [29.13.1. Prepare for Publisher Upgrades](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#PREPARE-PUBLISHER-UPGRADES) [29.13.2. Prepare for Subscriber Upgrades](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#PREPARE-SUBSCRIBER-UPGRADES) [29.13.3. Upgrading Logical Replication Clusters](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#UPGRADING-LOGICAL-REPLICATION-CLUSTERS) Migration of [](https://www.postgresql.org/docs/current/glossary.html#GLOSSARY-LOGICAL-REPLICATION-CLUSTER) [logical replication clusters](https://www.postgresql.org/docs/current/glossary.html#GLOSSARY-LOGICAL-REPLICATION-CLUSTER "Logical replication cluster") is possible only when all the members of the old logical replication clusters are version 17.0 or later. ### 29.13.1. Prepare for Publisher Upgrades [#](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#PREPARE-PUBLISHER-UPGRADES) pg\_upgrade attempts to migrate logical slots. This helps avoid the need for manually defining the same logical slots on the new publisher. Migration of logical slots is only supported when the old cluster is version 17.0 or later. Logical slots on clusters before version 17.0 will silently be ignored. Before you start upgrading the publisher cluster, ensure that the subscription is temporarily disabled, by executing [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/current/sql-altersubscription.html "ALTER SUBSCRIPTION") . Re-enable the subscription after the upgrade. There are some prerequisites for pg\_upgrade to be able to upgrade the logical slots. If these are not met an error will be reported. * The new cluster must have [`wal_level`](https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-WAL-LEVEL) as `logical`. * The new cluster must have [`max_replication_slots`](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-REPLICATION-SLOTS) configured to a value greater than or equal to the number of slots present in the old cluster. * The output plugins referenced by the slots on the old cluster must be installed in the new PostgreSQL executable directory. * The old cluster has replicated all the transactions and logical decoding messages to subscribers. * All slots on the old cluster must be usable, i.e., there are no slots whose [pg\_replication\_slots](https://www.postgresql.org/docs/current/view-pg-replication-slots.html "53.20. pg_replication_slots") .`conflicting` is not `true`. * The new cluster must not have permanent logical slots, i.e., there must be no slots where [pg\_replication\_slots](https://www.postgresql.org/docs/current/view-pg-replication-slots.html "53.20. pg_replication_slots") .`temporary` is `false`. ### 29.13.2. Prepare for Subscriber Upgrades [#](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#PREPARE-SUBSCRIBER-UPGRADES) Setup the [subscriber configurations](https://www.postgresql.org/docs/current/logical-replication-config.html#LOGICAL-REPLICATION-CONFIG-SUBSCRIBER "29.12.2. Subscribers") in the new subscriber. pg\_upgrade attempts to migrate subscription dependencies which includes the subscription's table information present in [pg\_subscription\_rel](https://www.postgresql.org/docs/current/catalog-pg-subscription-rel.html "52.55. pg_subscription_rel") system catalog and also the subscription's replication origin. This allows logical replication on the new subscriber to continue from where the old subscriber was up to. Migration of subscription dependencies is only supported when the old cluster is version 17.0 or later. Subscription dependencies on clusters before version 17.0 will silently be ignored. There are some prerequisites for pg\_upgrade to be able to upgrade the subscriptions. If these are not met an error will be reported. * All the subscription tables in the old subscriber should be in state `i` (initialize) or `r` (ready). This can be verified by checking [pg\_subscription\_rel](https://www.postgresql.org/docs/current/catalog-pg-subscription-rel.html "52.55. pg_subscription_rel") .`srsubstate`. * The replication origin entry corresponding to each of the subscriptions should exist in the old cluster. This can be found by checking [pg\_subscription](https://www.postgresql.org/docs/current/catalog-pg-subscription.html "52.54. pg_subscription") and [pg\_replication\_origin](https://www.postgresql.org/docs/current/catalog-pg-replication-origin.html "52.44. pg_replication_origin") system tables. * The new cluster must have [`max_active_replication_origins`](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-ACTIVE-REPLICATION-ORIGINS) configured to a value greater than or equal to the number of subscriptions present in the old cluster. ### 29.13.3. Upgrading Logical Replication Clusters [#](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#UPGRADING-LOGICAL-REPLICATION-CLUSTERS) While upgrading a subscriber, write operations can be performed in the publisher. These changes will be replicated to the subscriber once the subscriber upgrade is completed. ### Note The logical replication restrictions apply to logical replication cluster upgrades also. See [Section 29.8](https://www.postgresql.org/docs/current/logical-replication-restrictions.html "29.8. Restrictions") for details. The prerequisites of publisher upgrade apply to logical replication cluster upgrades also. See [Section 29.13.1](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#PREPARE-PUBLISHER-UPGRADES "29.13.1. Prepare for Publisher Upgrades") for details. The prerequisites of subscriber upgrade apply to logical replication cluster upgrades also. See [Section 29.13.2](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#PREPARE-SUBSCRIBER-UPGRADES "29.13.2. Prepare for Subscriber Upgrades") for details. ### Warning Upgrading logical replication cluster requires multiple steps to be performed on various nodes. Because not all operations are transactional, the user is advised to take backups as described in [Section 25.3.2](https://www.postgresql.org/docs/current/continuous-archiving.html#BACKUP-BASE-BACKUP "25.3.2. Making a Base Backup") . The steps to upgrade the following logical replication clusters are detailed below: * Follow the steps specified in [Section 29.13.3.1](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#STEPS-TWO-NODE-LOGICAL-REPLICATION-CLUSTER "29.13.3.1. Steps to Upgrade a Two-node Logical Replication Cluster") to upgrade a two-node logical replication cluster. * Follow the steps specified in [Section 29.13.3.2](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#STEPS-CASCADED-LOGICAL-REPLICATION-CLUSTER "29.13.3.2. Steps to Upgrade a Cascaded Logical Replication Cluster") to upgrade a cascaded logical replication cluster. * Follow the steps specified in [Section 29.13.3.3](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#STEPS-TWO-NODE-CIRCULAR-LOGICAL-REPLICATION-CLUSTER "29.13.3.3. Steps to Upgrade a Two-node Circular Logical Replication Cluster") to upgrade a two-node circular logical replication cluster. #### 29.13.3.1. Steps to Upgrade a Two-node Logical Replication Cluster [#](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#STEPS-TWO-NODE-LOGICAL-REPLICATION-CLUSTER) Let's say publisher is in `node1` and subscriber is in `node2`. The subscriber `node2` has a subscription `sub1_node1_node2` which is subscribing the changes from `node1`. 1. Disable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-DISABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 DISABLE; 2. Stop the publisher server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1 stop 3. Initialize `data1_upgraded` instance by using the required newer version. 4. Upgrade the publisher `node1`'s server to the required newer version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data1" --new-datadir "/opt/PostgreSQL/postgres/18/data1\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 5. Start the upgraded publisher server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1\_upgraded start -l logfile 6. Stop the subscriber server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2 stop 7. Initialize `data2_upgraded` instance by using the required newer version. 8. Upgrade the subscriber `node2`'s server to the required new version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data2" --new-datadir "/opt/PostgreSQL/postgres/18/data2\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 9. Start the upgraded subscriber server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2\_upgraded start -l logfile 10. On `node2`, create any tables that were created in the upgraded publisher `node1` server between [Step 1](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#TWO-NODE-CLUSTER-DISABLE-SUBSCRIPTIONS-NODE2 "Step 1") and now, e.g.: /\* node2 # \*/ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); 11. Enable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... ENABLE`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-ENABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 ENABLE; 12. Refresh the `node2` subscription's publications using [`ALTER SUBSCRIPTION ... REFRESH PUBLICATION`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-REFRESH-PUBLICATION) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 REFRESH PUBLICATION; ### Note In the steps described above, the publisher is upgraded first, followed by the subscriber. Alternatively, the user can use similar steps to upgrade the subscriber first, followed by the publisher. #### 29.13.3.2. Steps to Upgrade a Cascaded Logical Replication Cluster [#](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#STEPS-CASCADED-LOGICAL-REPLICATION-CLUSTER) Let's say we have a cascaded logical replication setup `node1`\->`node2`\->`node3`. Here `node2` is subscribing the changes from `node1` and `node3` is subscribing the changes from `node2`. The `node2` has a subscription `sub1_node1_node2` which is subscribing the changes from `node1`. The `node3` has a subscription `sub1_node2_node3` which is subscribing the changes from `node2`. 1. Disable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-DISABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 DISABLE; 2. Stop the server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1 stop 3. Initialize `data1_upgraded` instance by using the required newer version. 4. Upgrade the `node1`'s server to the required newer version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data1" --new-datadir "/opt/PostgreSQL/postgres/18/data1\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 5. Start the upgraded server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1\_upgraded start -l logfile 6. Disable all the subscriptions on `node3` that are subscribing the changes from `node2` by using [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-DISABLE) , e.g.: /\* node3 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node3 DISABLE; 7. Stop the server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2 stop 8. Initialize `data2_upgraded` instance by using the required newer version. 9. Upgrade the `node2`'s server to the required new version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data2" --new-datadir "/opt/PostgreSQL/postgres/18/data2\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 10. Start the upgraded server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2\_upgraded start -l logfile 11. On `node2`, create any tables that were created in the upgraded publisher `node1` server between [Step 1](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#CASCADED-CLUSTER-DISABLE-SUB-NODE1-NODE2 "Step 1") and now, e.g.: /\* node2 # \*/ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); 12. Enable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... ENABLE`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-ENABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 ENABLE; 13. Refresh the `node2` subscription's publications using [`ALTER SUBSCRIPTION ... REFRESH PUBLICATION`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-REFRESH-PUBLICATION) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 REFRESH PUBLICATION; 14. Stop the server in `node3`, e.g.: pg\_ctl -D /opt/PostgreSQL/data3 stop 15. Initialize `data3_upgraded` instance by using the required newer version. 16. Upgrade the `node3`'s server to the required new version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data3" --new-datadir "/opt/PostgreSQL/postgres/18/data3\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 17. Start the upgraded server in `node3`, e.g.: pg\_ctl -D /opt/PostgreSQL/data3\_upgraded start -l logfile 18. On `node3`, create any tables that were created in the upgraded `node2` between [Step 6](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#CASCADED-CLUSTER-DISABLE-SUB-NODE2-NODE3 "Step 6") and now, e.g.: /\* node3 # \*/ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); 19. Enable all the subscriptions on `node3` that are subscribing the changes from `node2` by using [`ALTER SUBSCRIPTION ... ENABLE`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-ENABLE) , e.g.: /\* node3 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node3 ENABLE; 20. Refresh the `node3` subscription's publications using [`ALTER SUBSCRIPTION ... REFRESH PUBLICATION`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-REFRESH-PUBLICATION) , e.g.: /\* node3 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node3 REFRESH PUBLICATION; #### 29.13.3.3. Steps to Upgrade a Two-node Circular Logical Replication Cluster [#](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#STEPS-TWO-NODE-CIRCULAR-LOGICAL-REPLICATION-CLUSTER) Let's say we have a circular logical replication setup `node1`\->`node2` and `node2`\->`node1`. Here `node2` is subscribing the changes from `node1` and `node1` is subscribing the changes from `node2`. The `node1` has a subscription `sub1_node2_node1` which is subscribing the changes from `node2`. The `node2` has a subscription `sub1_node1_node2` which is subscribing the changes from `node1`. 1. Disable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-DISABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 DISABLE; 2. Stop the server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1 stop 3. Initialize `data1_upgraded` instance by using the required newer version. 4. Upgrade the `node1`'s server to the required newer version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data1" --new-datadir "/opt/PostgreSQL/postgres/18/data1\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 5. Start the upgraded server in `node1`, e.g.: pg\_ctl -D /opt/PostgreSQL/data1\_upgraded start -l logfile 6. Enable all the subscriptions on `node2` that are subscribing the changes from `node1` by using [`ALTER SUBSCRIPTION ... ENABLE`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-ENABLE) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 ENABLE; 7. On `node1`, create any tables that were created in `node2` between [Step 1](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#CIRCULAR-CLUSTER-DISABLE-SUB-NODE2 "Step 1") and now, e.g.: /\* node1 # \*/ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); 8. Refresh the `node1` subscription's publications to copy initial table data from `node2` using [`ALTER SUBSCRIPTION ... REFRESH PUBLICATION`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-REFRESH-PUBLICATION) , e.g.: /\* node1 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node1 REFRESH PUBLICATION; 9. Disable all the subscriptions on `node1` that are subscribing the changes from `node2` by using [`ALTER SUBSCRIPTION ... DISABLE`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-DISABLE) , e.g.: /\* node1 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node1 DISABLE; 10. Stop the server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2 stop 11. Initialize `data2_upgraded` instance by using the required newer version. 12. Upgrade the `node2`'s server to the required new version, e.g.: pg\_upgrade --old-datadir "/opt/PostgreSQL/postgres/17/data2" --new-datadir "/opt/PostgreSQL/postgres/18/data2\_upgraded" --old-bindir "/opt/PostgreSQL/postgres/17/bin" --new-bindir "/opt/PostgreSQL/postgres/18/bin" 13. Start the upgraded server in `node2`, e.g.: pg\_ctl -D /opt/PostgreSQL/data2\_upgraded start -l logfile 14. Enable all the subscriptions on `node1` that are subscribing the changes from `node2` by using [`ALTER SUBSCRIPTION ... ENABLE`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-ENABLE) , e.g.: /\* node1 # \*/ ALTER SUBSCRIPTION sub1\_node2\_node1 ENABLE; 15. On `node2`, create any tables that were created in the upgraded `node1` between [Step 9](https://www.postgresql.org/docs/current/logical-replication-upgrade.html#CIRCULAR-CLUSTER-DISABLE-SUB-NODE1 "Step 9") and now, e.g.: /\* node2 # \*/ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); 16. Refresh the `node2` subscription's publications to copy initial table data from `node1` using [`ALTER SUBSCRIPTION ... REFRESH PUBLICATION`](https://www.postgresql.org/docs/current/sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-REFRESH-PUBLICATION) , e.g.: /\* node2 # \*/ ALTER SUBSCRIPTION sub1\_node1\_node2 REFRESH PUBLICATION; * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/logical-replication-config.html "29.12. Configuration Settings") | [Up](https://www.postgresql.org/docs/current/logical-replication.html "Chapter 29. Logical Replication") | [Next](https://www.postgresql.org/docs/current/logical-replication-quick-setup.html "29.14. Quick Setup") | | 29.12. Configuration Settings | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 29.14. Quick Setup | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/logical-replication-upgrade.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 65.1. B-Tree Indexes November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/btree.html "PostgreSQL 18 - 65.1. B-Tree Indexes") ([18](https://www.postgresql.org/docs/18/btree.html "PostgreSQL 18 - 65.1. B-Tree Indexes") ) / [17](https://www.postgresql.org/docs/17/btree.html "PostgreSQL 17 - 65.1. B-Tree Indexes") / [16](https://www.postgresql.org/docs/16/btree.html "PostgreSQL 16 - 65.1. B-Tree Indexes") / [15](https://www.postgresql.org/docs/15/btree.html "PostgreSQL 15 - 65.1. B-Tree Indexes") / [14](https://www.postgresql.org/docs/14/btree.html "PostgreSQL 14 - 65.1. B-Tree Indexes") Development Versions: [devel](https://www.postgresql.org/docs/devel/btree.html "PostgreSQL devel - 65.1. B-Tree Indexes") Unsupported versions: [13](https://www.postgresql.org/docs/13/btree.html "PostgreSQL 13 - 65.1. B-Tree Indexes") / [12](https://www.postgresql.org/docs/12/btree.html "PostgreSQL 12 - 65.1. B-Tree Indexes") / [11](https://www.postgresql.org/docs/11/btree.html "PostgreSQL 11 - 65.1. B-Tree Indexes") | 65.1. B-Tree Indexes | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/indextypes.html "Chapter 65. Built-in Index Access Methods") | [Up](https://www.postgresql.org/docs/18/indextypes.html "Chapter 65. Built-in Index Access Methods") | Chapter 65. Built-in Index Access Methods | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/gist.html "65.2. GiST Indexes") | * * * 65.1. B-Tree Indexes [#](https://www.postgresql.org/docs/18/btree.html#BTREE) ------------------------------------------------------------------------------ [65.1.1. Introduction](https://www.postgresql.org/docs/18/btree.html#BTREE-INTRO) [65.1.2. Behavior of B-Tree Operator Classes](https://www.postgresql.org/docs/18/btree.html#BTREE-BEHAVIOR) [65.1.3. B-Tree Support Functions](https://www.postgresql.org/docs/18/btree.html#BTREE-SUPPORT-FUNCS) [65.1.4. Implementation](https://www.postgresql.org/docs/18/btree.html#BTREE-IMPLEMENTATION) ### 65.1.1. Introduction [#](https://www.postgresql.org/docs/18/btree.html#BTREE-INTRO) PostgreSQL includes an implementation of the standard btree (multi-way balanced tree) index data structure. Any data type that can be sorted into a well-defined linear order can be indexed by a btree index. The only limitation is that an index entry cannot exceed approximately one-third of a page (after TOAST compression, if applicable). Because each btree operator class imposes a sort order on its data type, btree operator classes (or, really, operator families) have come to be used as PostgreSQL's general representation and understanding of sorting semantics. Therefore, they've acquired some features that go beyond what would be needed just to support btree indexes, and parts of the system that are quite distant from the btree AM make use of them. ### 65.1.2. Behavior of B-Tree Operator Classes [#](https://www.postgresql.org/docs/18/btree.html#BTREE-BEHAVIOR) As shown in [Table 36.3](https://www.postgresql.org/docs/18/xindex.html#XINDEX-BTREE-STRAT-TABLE "Table 36.3. B-Tree Strategies") , a btree operator class must provide five comparison operators, `<`, `<=`, `=`, `>=` and `>`. One might expect that `<>` should also be part of the operator class, but it is not, because it would almost never be useful to use a `<>` WHERE clause in an index search. (For some purposes, the planner treats `<>` as associated with a btree operator class; but it finds that operator via the `=` operator's negator link, rather than from `pg_amop`.) When several data types share near-identical sorting semantics, their operator classes can be grouped into an operator family. Doing so is advantageous because it allows the planner to make deductions about cross-type comparisons. Each operator class within the family should contain the single-type operators (and associated support functions) for its input data type, while cross-type comparison operators and support functions are “loose” in the family. It is recommendable that a complete set of cross-type operators be included in the family, thus ensuring that the planner can represent any comparison conditions that it deduces from transitivity. There are some basic assumptions that a btree operator family must satisfy: * An `=` operator must be an equivalence relation; that is, for all non-null values _`A`_, _`B`_, _`C`_ of the data type: * _`A`_ `=` _`A`_ is true (_reflexive law_) * if _`A`_ `=` _`B`_, then _`B`_ `=` _`A`_ (_symmetric law_) * if _`A`_ `=` _`B`_ and _`B`_ `=` _`C`_, then _`A`_ `=` _`C`_ (_transitive law_) * A `<` operator must be a strong ordering relation; that is, for all non-null values _`A`_, _`B`_, _`C`_: * _`A`_ `<` _`A`_ is false (_irreflexive law_) * if _`A`_ `<` _`B`_ and _`B`_ `<` _`C`_, then _`A`_ `<` _`C`_ (_transitive law_) * Furthermore, the ordering is total; that is, for all non-null values _`A`_, _`B`_: * exactly one of _`A`_ `<` _`B`_, _`A`_ `=` _`B`_, and _`B`_ `<` _`A`_ is true (_trichotomy law_) (The trichotomy law justifies the definition of the comparison support function, of course.) The other three operators are defined in terms of `=` and `<` in the obvious way, and must act consistently with them. For an operator family supporting multiple data types, the above laws must hold when _`A`_, _`B`_, _`C`_ are taken from any data types in the family. The transitive laws are the trickiest to ensure, as in cross-type situations they represent statements that the behaviors of two or three different operators are consistent. As an example, it would not work to put `float8` and `numeric` into the same operator family, at least not with the current semantics that `numeric` values are converted to `float8` for comparison to a `float8`. Because of the limited accuracy of `float8`, this means there are distinct `numeric` values that will compare equal to the same `float8` value, and thus the transitive law would fail. Another requirement for a multiple-data-type family is that any implicit or binary-coercion casts that are defined between data types included in the operator family must not change the associated sort ordering. It should be fairly clear why a btree index requires these laws to hold within a single data type: without them there is no ordering to arrange the keys with. Also, index searches using a comparison key of a different data type require comparisons to behave sanely across two data types. The extensions to three or more data types within a family are not strictly required by the btree index mechanism itself, but the planner relies on them for optimization purposes. ### 65.1.3. B-Tree Support Functions [#](https://www.postgresql.org/docs/18/btree.html#BTREE-SUPPORT-FUNCS) As shown in [Table 36.9](https://www.postgresql.org/docs/18/xindex.html#XINDEX-BTREE-SUPPORT-TABLE "Table 36.9. B-Tree Support Functions") , btree defines one required and five optional support functions. The six user-defined methods are: `order` For each combination of data types that a btree operator family provides comparison operators for, it must provide a comparison support function, registered in `pg_amproc` with support function number 1 and `amproclefttype`/`amprocrighttype` equal to the left and right data types for the comparison (i.e., the same data types that the matching operators are registered with in `pg_amop`). The comparison function must take two non-null values _`A`_ and _`B`_ and return an `int32` value that is `<` `0`, `0`, or `>` `0` when _`A`_ `<` _`B`_, _`A`_ `=` _`B`_, or _`A`_ `>` _`B`_, respectively. A null result is disallowed: all values of the data type must be comparable. See `src/backend/access/nbtree/nbtcompare.c` for examples. If the compared values are of a collatable data type, the appropriate collation OID will be passed to the comparison support function, using the standard `PG_GET_COLLATION()` mechanism. `sortsupport` Optionally, a btree operator family may provide _sort support_ function(s), registered under support function number 2. These functions allow implementing comparisons for sorting purposes in a more efficient way than naively calling the comparison support function. The APIs involved in this are defined in `src/include/utils/sortsupport.h`. `in_range` Optionally, a btree operator family may provide _in\_range_ support function(s), registered under support function number 3. These are not used during btree index operations; rather, they extend the semantics of the operator family so that it can support window clauses containing the `RANGE` _`offset`_ `PRECEDING` and `RANGE` _`offset`_ `FOLLOWING` frame bound types (see [Section 4.2.8](https://www.postgresql.org/docs/18/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS "4.2.8. Window Function Calls") ). Fundamentally, the extra information provided is how to add or subtract an _`offset`_ value in a way that is compatible with the family's data ordering. An `in_range` function must have the signature in\_range(_`val`_ type1, _`base`_ type1, _`offset`_ type2, _`sub`_ bool, _`less`_ bool) returns bool _`val`_ and _`base`_ must be of the same type, which is one of the types supported by the operator family (i.e., a type for which it provides an ordering). However, _`offset`_ could be of a different type, which might be one otherwise unsupported by the family. An example is that the built-in `time_ops` family provides an `in_range` function that has _`offset`_ of type `interval`. A family can provide `in_range` functions for any of its supported types and one or more _`offset`_ types. Each `in_range` function should be entered in `pg_amproc` with `amproclefttype` equal to `type1` and `amprocrighttype` equal to `type2`. The essential semantics of an `in_range` function depend on the two Boolean flag parameters. It should add or subtract _`base`_ and _`offset`_, then compare _`val`_ to the result, as follows: * if `!`_`sub`_ and `!`_`less`_, return _`val`_ `>=` (_`base`_ `+` _`offset`_) * if `!`_`sub`_ and _`less`_, return _`val`_ `<=` (_`base`_ `+` _`offset`_) * if _`sub`_ and `!`_`less`_, return _`val`_ `>=` (_`base`_ `-` _`offset`_) * if _`sub`_ and _`less`_, return _`val`_ `<=` (_`base`_ `-` _`offset`_) Before doing so, the function should check the sign of _`offset`_: if it is less than zero, raise error `ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE` (22013) with error text like “invalid preceding or following size in window function”. (This is required by the SQL standard, although nonstandard operator families might perhaps choose to ignore this restriction, since there seems to be little semantic necessity for it.) This requirement is delegated to the `in_range` function so that the core code needn't understand what “less than zero” means for a particular data type. An additional expectation is that `in_range` functions should, if practical, avoid throwing an error if _`base`_ `+` _`offset`_ or _`base`_ `-` _`offset`_ would overflow. The correct comparison result can be determined even if that value would be out of the data type's range. Note that if the data type includes concepts such as “infinity” or “NaN”, extra care may be needed to ensure that `in_range`'s results agree with the normal sort order of the operator family. The results of the `in_range` function must be consistent with the sort ordering imposed by the operator family. To be precise, given any fixed values of _`offset`_ and _`sub`_, then: * If `in_range` with _`less`_ = true is true for some _`val1`_ and _`base`_, it must be true for every _`val2`_ `<=` _`val1`_ with the same _`base`_. * If `in_range` with _`less`_ = true is false for some _`val1`_ and _`base`_, it must be false for every _`val2`_ `>=` _`val1`_ with the same _`base`_. * If `in_range` with _`less`_ = true is true for some _`val`_ and _`base1`_, it must be true for every _`base2`_ `>=` _`base1`_ with the same _`val`_. * If `in_range` with _`less`_ = true is false for some _`val`_ and _`base1`_, it must be false for every _`base2`_ `<=` _`base1`_ with the same _`val`_. Analogous statements with inverted conditions hold when _`less`_ = false. If the type being ordered (`type1`) is collatable, the appropriate collation OID will be passed to the `in_range` function, using the standard PG\_GET\_COLLATION() mechanism. `in_range` functions need not handle NULL inputs, and typically will be marked strict. `equalimage` Optionally, a btree operator family may provide `equalimage` (“equality implies image equality”) support functions, registered under support function number 4. These functions allow the core code to determine when it is safe to apply the btree deduplication optimization. Currently, `equalimage` functions are only called when building or rebuilding an index. An `equalimage` function must have the signature equalimage(_`opcintype`_ `oid`) returns bool The return value is static information about an operator class and collation. Returning `true` indicates that the `order` function for the operator class is guaranteed to only return `0` (“arguments are equal”) when its _`A`_ and _`B`_ arguments are also interchangeable without any loss of semantic information. Not registering an `equalimage` function or returning `false` indicates that this condition cannot be assumed to hold. The _`opcintype`_ argument is the `` `pg_type`.oid `` of the data type that the operator class indexes. This is a convenience that allows reuse of the same underlying `equalimage` function across operator classes. If _`opcintype`_ is a collatable data type, the appropriate collation OID will be passed to the `equalimage` function, using the standard `PG_GET_COLLATION()` mechanism. As far as the operator class is concerned, returning `true` indicates that deduplication is safe (or safe for the collation whose OID was passed to its `equalimage` function). However, the core code will only deem deduplication safe for an index when _every_ indexed column uses an operator class that registers an `equalimage` function, and each function actually returns `true` when called. Image equality is _almost_ the same condition as simple bitwise equality. There is one subtle difference: When indexing a varlena data type, the on-disk representation of two image equal datums may not be bitwise equal due to inconsistent application of TOAST compression on input. Formally, when an operator class's `equalimage` function returns `true`, it is safe to assume that the `datum_image_eq()` C function will always agree with the operator class's `order` function (provided that the same collation OID is passed to both the `equalimage` and `order` functions). The core code is fundamentally unable to deduce anything about the “equality implies image equality” status of an operator class within a multiple-data-type family based on details from other operator classes in the same family. Also, it is not sensible for an operator family to register a cross-type `equalimage` function, and attempting to do so will result in an error. This is because “equality implies image equality” status does not just depend on sorting/equality semantics, which are more or less defined at the operator family level. In general, the semantics that one particular data type implements must be considered separately. The convention followed by the operator classes included with the core PostgreSQL distribution is to register a stock, generic `equalimage` function. Most operator classes register `btequalimage()`, which indicates that deduplication is safe unconditionally. Operator classes for collatable data types such as `text` register `btvarstrequalimage()`, which indicates that deduplication is safe with deterministic collations. Best practice for third-party extensions is to register their own custom function to retain control. `options` Optionally, a B-tree operator family may provide `options` (“operator class specific options”) support functions, registered under support function number 5. These functions define a set of user-visible parameters that control operator class behavior. An `options` support function must have the signature options(_`relopts`_ `local_relopts *`) returns void The function is passed a pointer to a `local_relopts` struct, which needs to be filled with a set of operator class specific options. The options can be accessed from other support functions using the `PG_HAS_OPCLASS_OPTIONS()` and `PG_GET_OPCLASS_OPTIONS()` macros. Currently, no B-Tree operator class has an `options` support function. B-tree doesn't allow flexible representation of keys like GiST, SP-GiST, GIN and BRIN do. So, `options` probably doesn't have much application in the current B-tree index access method. Nevertheless, this support function was added to B-tree for uniformity, and will probably find uses during further evolution of B-tree in PostgreSQL. `skipsupport` Optionally, a btree operator family may provide a _skip support_ function, registered under support function number 6. These functions give the B-tree code a way to iterate through every possible value that can be represented by an operator class's underlying input type, in key space order. This is used by the core code when it applies the skip scan optimization. The APIs involved in this are defined in `src/include/utils/skipsupport.h`. Operator classes that do not provide a skip support function are still eligible to use skip scan. The core code can still use its fallback strategy, though that might be suboptimal for some discrete types. It usually doesn't make sense (and may not even be feasible) for operator classes on continuous types to provide a skip support function. It is not sensible for an operator family to register a cross-type `skipsupport` function, and attempting to do so will result in an error. This is because determining the next indexable value must happen by incrementing a value copied from an index tuple. The values generated must all be of the same underlying data type (the “skipped” index column's opclass input type). ### 65.1.4. Implementation [#](https://www.postgresql.org/docs/18/btree.html#BTREE-IMPLEMENTATION) This section covers B-Tree index implementation details that may be of use to advanced users. See `src/backend/access/nbtree/README` in the source distribution for a much more detailed, internals-focused description of the B-Tree implementation. #### 65.1.4.1. B-Tree Structure [#](https://www.postgresql.org/docs/18/btree.html#BTREE-STRUCTURE) PostgreSQL B-Tree indexes are multi-level tree structures, where each level of the tree can be used as a doubly-linked list of pages. A single metapage is stored in a fixed position at the start of the first segment file of the index. All other pages are either leaf pages or internal pages. Leaf pages are the pages on the lowest level of the tree. All other levels consist of internal pages. Each leaf page contains tuples that point to table rows. Each internal page contains tuples that point to the next level down in the tree. Typically, over 99% of all pages are leaf pages. Both internal pages and leaf pages use the standard page format described in [Section 66.6](https://www.postgresql.org/docs/18/storage-page-layout.html "66.6. Database Page Layout") . New leaf pages are added to a B-Tree index when an existing leaf page cannot fit an incoming tuple. A _page split_ operation makes room for items that originally belonged on the overflowing page by moving a portion of the items to a new page. Page splits must also insert a new _downlink_ to the new page in the parent page, which may cause the parent to split in turn. Page splits “cascade upwards” in a recursive fashion. When the root page finally cannot fit a new downlink, a _root page split_ operation takes place. This adds a new level to the tree structure by creating a new root page that is one level above the original root page. #### 65.1.4.2. Bottom-up Index Deletion [#](https://www.postgresql.org/docs/18/btree.html#BTREE-DELETION) B-Tree indexes are not directly aware that under MVCC, there might be multiple extant versions of the same logical table row; to an index, each tuple is an independent object that needs its own index entry. “Version churn” tuples may sometimes accumulate and adversely affect query latency and throughput. This typically occurs with `UPDATE`\-heavy workloads where most individual updates cannot apply the [HOT optimization.](https://www.postgresql.org/docs/18/storage-hot.html "66.7. Heap-Only Tuples (HOT)") Changing the value of only one column covered by one index during an `UPDATE` _always_ necessitates a new set of index tuples — one for _each and every_ index on the table. Note in particular that this includes indexes that were not “logically modified” by the `UPDATE`. All indexes will need a successor physical index tuple that points to the latest version in the table. Each new tuple within each index will generally need to coexist with the original “updated” tuple for a short period of time (typically until shortly after the `UPDATE` transaction commits). B-Tree indexes incrementally delete version churn index tuples by performing _bottom-up index deletion_ passes. Each deletion pass is triggered in reaction to an anticipated “version churn page split”. This only happens with indexes that are not logically modified by `UPDATE` statements, where concentrated build up of obsolete versions in particular pages would occur otherwise. A page split will usually be avoided, though it's possible that certain implementation-level heuristics will fail to identify and delete even one garbage index tuple (in which case a page split or deduplication pass resolves the issue of an incoming new tuple not fitting on a leaf page). The worst-case number of versions that any index scan must traverse (for any single logical row) is an important contributor to overall system responsiveness and throughput. A bottom-up index deletion pass targets suspected garbage tuples in a single leaf page based on _qualitative_ distinctions involving logical rows and versions. This contrasts with the “top-down” index cleanup performed by autovacuum workers, which is triggered when certain _quantitative_ table-level thresholds are exceeded (see [Section 24.1.6](https://www.postgresql.org/docs/18/routine-vacuuming.html#AUTOVACUUM "24.1.6. The Autovacuum Daemon") ). ### Note Not all deletion operations that are performed within B-Tree indexes are bottom-up deletion operations. There is a distinct category of index tuple deletion: _simple index tuple deletion_. This is a deferred maintenance operation that deletes index tuples that are known to be safe to delete (those whose item identifier's `LP_DEAD` bit is already set). Like bottom-up index deletion, simple index deletion takes place at the point that a page split is anticipated as a way of avoiding the split. Simple deletion is opportunistic in the sense that it can only take place when recent index scans set the `LP_DEAD` bits of affected items in passing. Prior to PostgreSQL 14, the only category of B-Tree deletion was simple deletion. The main differences between it and bottom-up deletion are that only the former is opportunistically driven by the activity of passing index scans, while only the latter specifically targets version churn from `UPDATE`s that do not logically modify indexed columns. Bottom-up index deletion performs the vast majority of all garbage index tuple cleanup for particular indexes with certain workloads. This is expected with any B-Tree index that is subject to significant version churn from `UPDATE`s that rarely or never logically modify the columns that the index covers. The average and worst-case number of versions per logical row can be kept low purely through targeted incremental deletion passes. It's quite possible that the on-disk size of certain indexes will never increase by even one single page/block despite _constant_ version churn from `UPDATE`s. Even then, an exhaustive “clean sweep” by a `VACUUM` operation (typically run in an autovacuum worker process) will eventually be required as a part of _collective_ cleanup of the table and each of its indexes. Unlike `VACUUM`, bottom-up index deletion does not provide any strong guarantees about how old the oldest garbage index tuple may be. No index can be permitted to retain “floating garbage” index tuples that became dead prior to a conservative cutoff point shared by the table and all of its indexes collectively. This fundamental table-level invariant makes it safe to recycle table TIDs. This is how it is possible for distinct logical rows to reuse the same table TID over time (though this can never happen with two logical rows whose lifetimes span the same `VACUUM` cycle). #### 65.1.4.3. Deduplication [#](https://www.postgresql.org/docs/18/btree.html#BTREE-DEDUPLICATION) A duplicate is a leaf page tuple (a tuple that points to a table row) where _all_ indexed key columns have values that match corresponding column values from at least one other leaf page tuple in the same index. Duplicate tuples are quite common in practice. B-Tree indexes can use a special, space-efficient representation for duplicates when an optional technique is enabled: _deduplication_. Deduplication works by periodically merging groups of duplicate tuples together, forming a single _posting list_ tuple for each group. The column key value(s) only appear once in this representation. This is followed by a sorted array of TIDs that point to rows in the table. This significantly reduces the storage size of indexes where each value (or each distinct combination of column values) appears several times on average. The latency of queries can be reduced significantly. Overall query throughput may increase significantly. The overhead of routine index vacuuming may also be reduced significantly. ### Note B-Tree deduplication is just as effective with “duplicates” that contain a NULL value, even though NULL values are never equal to each other according to the `=` member of any B-Tree operator class. As far as any part of the implementation that understands the on-disk B-Tree structure is concerned, NULL is just another value from the domain of indexed values. The deduplication process occurs lazily, when a new item is inserted that cannot fit on an existing leaf page, though only when index tuple deletion could not free sufficient space for the new item (typically deletion is briefly considered and then skipped over). Unlike GIN posting list tuples, B-Tree posting list tuples do not need to expand every time a new duplicate is inserted; they are merely an alternative physical representation of the original logical contents of the leaf page. This design prioritizes consistent performance with mixed read-write workloads. Most client applications will at least see a moderate performance benefit from using deduplication. Deduplication is enabled by default. `CREATE INDEX` and `REINDEX` apply deduplication to create posting list tuples, though the strategy they use is slightly different. Each group of duplicate ordinary tuples encountered in the sorted input taken from the table is merged into a posting list tuple _before_ being added to the current pending leaf page. Individual posting list tuples are packed with as many TIDs as possible. Leaf pages are written out in the usual way, without any separate deduplication pass. This strategy is well-suited to `CREATE INDEX` and `REINDEX` because they are once-off batch operations. Write-heavy workloads that don't benefit from deduplication due to having few or no duplicate values in indexes will incur a small, fixed performance penalty (unless deduplication is explicitly disabled). The `deduplicate_items` storage parameter can be used to disable deduplication within individual indexes. There is never any performance penalty with read-only workloads, since reading posting list tuples is at least as efficient as reading the standard tuple representation. Disabling deduplication isn't usually helpful. It is sometimes possible for unique indexes (as well as unique constraints) to use deduplication. This allows leaf pages to temporarily “absorb” extra version churn duplicates. Deduplication in unique indexes augments bottom-up index deletion, especially in cases where a long-running transaction holds a snapshot that blocks garbage collection. The goal is to buy time for the bottom-up index deletion strategy to become effective again. Delaying page splits until a single long-running transaction naturally goes away can allow a bottom-up deletion pass to succeed where an earlier deletion pass failed. ### Tip A special heuristic is applied to determine whether a deduplication pass in a unique index should take place. It can often skip straight to splitting a leaf page, avoiding a performance penalty from wasting cycles on unhelpful deduplication passes. If you're concerned about the overhead of deduplication, consider setting `deduplicate_items = off` selectively. Leaving deduplication enabled in unique indexes has little downside. Deduplication cannot be used in all cases due to implementation-level restrictions. Deduplication safety is determined when `CREATE INDEX` or `REINDEX` is run. Note that deduplication is deemed unsafe and cannot be used in the following cases involving semantically significant differences among equal datums: * `text`, `varchar`, and `char` cannot use deduplication when a _nondeterministic_ collation is used. Case and accent differences must be preserved among equal datums. * `numeric` cannot use deduplication. Numeric display scale must be preserved among equal datums. * `jsonb` cannot use deduplication, since the `jsonb` B-Tree operator class uses `numeric` internally. * `float4` and `float8` cannot use deduplication. These types have distinct representations for `-0` and `0`, which are nevertheless considered equal. This difference must be preserved. There is one further implementation-level restriction that may be lifted in a future version of PostgreSQL: * Container types (such as composite types, arrays, or range types) cannot use deduplication. There is one further implementation-level restriction that applies regardless of the operator class or collation used: * `INCLUDE` indexes can never use deduplication. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/indextypes.html "Chapter 65. Built-in Index Access Methods") | [Up](https://www.postgresql.org/docs/18/indextypes.html "Chapter 65. Built-in Index Access Methods") | [Next](https://www.postgresql.org/docs/18/gist.html "65.2. GiST Indexes") | | Chapter 65. Built-in Index Access Methods | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 65.2. GiST Indexes | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/btree.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: ALTER LARGE OBJECT November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alterlargeobject.html "PostgreSQL 18 - ALTER LARGE OBJECT") ([18](https://www.postgresql.org/docs/18/sql-alterlargeobject.html "PostgreSQL 18 - ALTER LARGE OBJECT") ) / [17](https://www.postgresql.org/docs/17/sql-alterlargeobject.html "PostgreSQL 17 - ALTER LARGE OBJECT") / [16](https://www.postgresql.org/docs/16/sql-alterlargeobject.html "PostgreSQL 16 - ALTER LARGE OBJECT") / [15](https://www.postgresql.org/docs/15/sql-alterlargeobject.html "PostgreSQL 15 - ALTER LARGE OBJECT") / [14](https://www.postgresql.org/docs/14/sql-alterlargeobject.html "PostgreSQL 14 - ALTER LARGE OBJECT") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alterlargeobject.html "PostgreSQL devel - ALTER LARGE OBJECT") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alterlargeobject.html "PostgreSQL 13 - ALTER LARGE OBJECT") / [12](https://www.postgresql.org/docs/12/sql-alterlargeobject.html "PostgreSQL 12 - ALTER LARGE OBJECT") / [11](https://www.postgresql.org/docs/11/sql-alterlargeobject.html "PostgreSQL 11 - ALTER LARGE OBJECT") / [10](https://www.postgresql.org/docs/10/sql-alterlargeobject.html "PostgreSQL 10 - ALTER LARGE OBJECT") / [9.6](https://www.postgresql.org/docs/9.6/sql-alterlargeobject.html "PostgreSQL 9.6 - ALTER LARGE OBJECT") / [9.5](https://www.postgresql.org/docs/9.5/sql-alterlargeobject.html "PostgreSQL 9.5 - ALTER LARGE OBJECT") / [9.4](https://www.postgresql.org/docs/9.4/sql-alterlargeobject.html "PostgreSQL 9.4 - ALTER LARGE OBJECT") / [9.3](https://www.postgresql.org/docs/9.3/sql-alterlargeobject.html "PostgreSQL 9.3 - ALTER LARGE OBJECT") / [9.2](https://www.postgresql.org/docs/9.2/sql-alterlargeobject.html "PostgreSQL 9.2 - ALTER LARGE OBJECT") / [9.1](https://www.postgresql.org/docs/9.1/sql-alterlargeobject.html "PostgreSQL 9.1 - ALTER LARGE OBJECT") / [9.0](https://www.postgresql.org/docs/9.0/sql-alterlargeobject.html "PostgreSQL 9.0 - ALTER LARGE OBJECT") | ALTER LARGE OBJECT | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-alterlanguage.html "ALTER LANGUAGE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-altermaterializedview.html "ALTER MATERIALIZED VIEW") | * * * ALTER LARGE OBJECT ------------------ ALTER LARGE OBJECT — change the definition of a large object Synopsis -------- ALTER LARGE OBJECT _`large_object_oid`_ OWNER TO { _`new_owner`_ | CURRENT\_ROLE | CURRENT\_USER | SESSION\_USER } Description ----------- `ALTER LARGE OBJECT` changes the definition of a large object. You must own the large object to use `ALTER LARGE OBJECT`. To alter the owner, you must also be able to `SET ROLE` to the new owning role. (However, a superuser can alter any large object anyway.) Currently, the only functionality is to assign a new owner, so both restrictions always apply. Parameters ---------- _`large_object_oid`_ OID of the large object to be altered _`new_owner`_ The new owner of the large object Compatibility ------------- There is no `ALTER LARGE OBJECT` statement in the SQL standard. See Also -------- [Chapter 33](https://www.postgresql.org/docs/18/largeobjects.html "Chapter 33. Large Objects") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-alterlanguage.html "ALTER LANGUAGE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-altermaterializedview.html "ALTER MATERIALIZED VIEW") | | ALTER LANGUAGE | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | ALTER MATERIALIZED VIEW | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-alterlargeobject.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: ALTER ROUTINE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alterroutine.html "PostgreSQL 18 - ALTER ROUTINE") ([18](https://www.postgresql.org/docs/18/sql-alterroutine.html "PostgreSQL 18 - ALTER ROUTINE") ) / [17](https://www.postgresql.org/docs/17/sql-alterroutine.html "PostgreSQL 17 - ALTER ROUTINE") / [16](https://www.postgresql.org/docs/16/sql-alterroutine.html "PostgreSQL 16 - ALTER ROUTINE") / [15](https://www.postgresql.org/docs/15/sql-alterroutine.html "PostgreSQL 15 - ALTER ROUTINE") / [14](https://www.postgresql.org/docs/14/sql-alterroutine.html "PostgreSQL 14 - ALTER ROUTINE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alterroutine.html "PostgreSQL devel - ALTER ROUTINE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alterroutine.html "PostgreSQL 13 - ALTER ROUTINE") / [12](https://www.postgresql.org/docs/12/sql-alterroutine.html "PostgreSQL 12 - ALTER ROUTINE") / [11](https://www.postgresql.org/docs/11/sql-alterroutine.html "PostgreSQL 11 - ALTER ROUTINE") | ALTER ROUTINE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-alterrole.html "ALTER ROLE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-alterrule.html "ALTER RULE") | * * * ALTER ROUTINE ------------- ALTER ROUTINE — change the definition of a routine Synopsis -------- ALTER ROUTINE _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] _`action`_ \[ ... \] \[ RESTRICT \] ALTER ROUTINE _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] RENAME TO _`new_name`_ ALTER ROUTINE _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] OWNER TO { _`new_owner`_ | CURRENT\_ROLE | CURRENT\_USER | SESSION\_USER } ALTER ROUTINE _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] SET SCHEMA _`new_schema`_ ALTER ROUTINE _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] \[ NO \] DEPENDS ON EXTENSION _`extension_name`_ where _`action`_ is one of: IMMUTABLE | STABLE | VOLATILE \[ NOT \] LEAKPROOF \[ EXTERNAL \] SECURITY INVOKER | \[ EXTERNAL \] SECURITY DEFINER PARALLEL { UNSAFE | RESTRICTED | SAFE } COST _`execution_cost`_ ROWS _`result_rows`_ SET _`configuration_parameter`_ { TO | = } { _`value`_ | DEFAULT } SET _`configuration_parameter`_ FROM CURRENT RESET _`configuration_parameter`_ RESET ALL Description ----------- `ALTER ROUTINE` changes the definition of a routine, which can be an aggregate function, a normal function, or a procedure. See under [ALTER AGGREGATE](https://www.postgresql.org/docs/18/sql-alteraggregate.html "ALTER AGGREGATE") , [ALTER FUNCTION](https://www.postgresql.org/docs/18/sql-alterfunction.html "ALTER FUNCTION") , and [ALTER PROCEDURE](https://www.postgresql.org/docs/18/sql-alterprocedure.html "ALTER PROCEDURE") for the description of the parameters, more examples, and further details. Examples -------- To rename the routine `foo` for type `integer` to `foobar`: ALTER ROUTINE foo(integer) RENAME TO foobar; This command will work independent of whether `foo` is an aggregate, function, or procedure. Compatibility ------------- This statement is partially compatible with the `ALTER ROUTINE` statement in the SQL standard. See under [ALTER FUNCTION](https://www.postgresql.org/docs/18/sql-alterfunction.html "ALTER FUNCTION") and [ALTER PROCEDURE](https://www.postgresql.org/docs/18/sql-alterprocedure.html "ALTER PROCEDURE") for more details. Allowing routine names to refer to aggregate functions is a PostgreSQL extension. See Also -------- [ALTER AGGREGATE](https://www.postgresql.org/docs/18/sql-alteraggregate.html "ALTER AGGREGATE") , [ALTER FUNCTION](https://www.postgresql.org/docs/18/sql-alterfunction.html "ALTER FUNCTION") , [ALTER PROCEDURE](https://www.postgresql.org/docs/18/sql-alterprocedure.html "ALTER PROCEDURE") , [DROP ROUTINE](https://www.postgresql.org/docs/18/sql-droproutine.html "DROP ROUTINE") Note that there is no `CREATE ROUTINE` command. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-alterrole.html "ALTER ROLE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-alterrule.html "ALTER RULE") | | ALTER ROLE | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | ALTER RULE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-alterroutine.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 15.1. How Parallel Query Works November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/how-parallel-query-works.html "PostgreSQL 18 - 15.1. How Parallel Query Works") ([18](https://www.postgresql.org/docs/18/how-parallel-query-works.html "PostgreSQL 18 - 15.1. How Parallel Query Works") ) / [17](https://www.postgresql.org/docs/17/how-parallel-query-works.html "PostgreSQL 17 - 15.1. How Parallel Query Works") / [16](https://www.postgresql.org/docs/16/how-parallel-query-works.html "PostgreSQL 16 - 15.1. How Parallel Query Works") / [15](https://www.postgresql.org/docs/15/how-parallel-query-works.html "PostgreSQL 15 - 15.1. How Parallel Query Works") / [14](https://www.postgresql.org/docs/14/how-parallel-query-works.html "PostgreSQL 14 - 15.1. How Parallel Query Works") Development Versions: [devel](https://www.postgresql.org/docs/devel/how-parallel-query-works.html "PostgreSQL devel - 15.1. How Parallel Query Works") Unsupported versions: [13](https://www.postgresql.org/docs/13/how-parallel-query-works.html "PostgreSQL 13 - 15.1. How Parallel Query Works") / [12](https://www.postgresql.org/docs/12/how-parallel-query-works.html "PostgreSQL 12 - 15.1. How Parallel Query Works") / [11](https://www.postgresql.org/docs/11/how-parallel-query-works.html "PostgreSQL 11 - 15.1. How Parallel Query Works") / [10](https://www.postgresql.org/docs/10/how-parallel-query-works.html "PostgreSQL 10 - 15.1. How Parallel Query Works") / [9.6](https://www.postgresql.org/docs/9.6/how-parallel-query-works.html "PostgreSQL 9.6 - 15.1. How Parallel Query Works") | 15.1. How Parallel Query Works | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/parallel-query.html "Chapter 15. Parallel Query") | [Up](https://www.postgresql.org/docs/current/parallel-query.html "Chapter 15. Parallel Query") | Chapter 15. Parallel Query | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/when-can-parallel-query-be-used.html "15.2. When Can Parallel Query Be Used?") | * * * 15.1. How Parallel Query Works [#](https://www.postgresql.org/docs/current/how-parallel-query-works.html#HOW-PARALLEL-QUERY-WORKS) ----------------------------------------------------------------------------------------------------------------------------------- When the optimizer determines that parallel query is the fastest execution strategy for a particular query, it will create a query plan that includes a _Gather_ or _Gather Merge_ node. Here is a simple example: EXPLAIN SELECT \* FROM pgbench\_accounts WHERE filler LIKE '%x%'; QUERY PLAN -------------------------------------------------------------------​------------------ Gather (cost=1000.00..217018.43 rows=1 width=97) Workers Planned: 2 -> Parallel Seq Scan on pgbench\_accounts (cost=0.00..216018.33 rows=1 width=97) Filter: (filler ~~ '%x%'::text) (4 rows) In all cases, the `Gather` or `Gather Merge` node will have exactly one child plan, which is the portion of the plan that will be executed in parallel. If the `Gather` or `Gather Merge` node is at the very top of the plan tree, then the entire query will execute in parallel. If it is somewhere else in the plan tree, then only the portion of the plan below it will run in parallel. In the example above, the query accesses only one table, so there is only one plan node other than the `Gather` node itself; since that plan node is a child of the `Gather` node, it will run in parallel. [Using EXPLAIN](https://www.postgresql.org/docs/current/using-explain.html "14.1. Using EXPLAIN") , you can see the number of workers chosen by the planner. When the `Gather` node is reached during query execution, the process that is implementing the user's session will request a number of [background worker processes](https://www.postgresql.org/docs/current/bgworker.html "Chapter 46. Background Worker Processes") equal to the number of workers chosen by the planner. The number of background workers that the planner will consider using is limited to at most [max\_parallel\_workers\_per\_gather](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS-PER-GATHER) . The total number of background workers that can exist at any one time is limited by both [max\_worker\_processes](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES) and [max\_parallel\_workers](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS) . Therefore, it is possible for a parallel query to run with fewer workers than planned, or even with no workers at all. The optimal plan may depend on the number of workers that are available, so this can result in poor query performance. If this occurrence is frequent, consider increasing `max_worker_processes` and `max_parallel_workers` so that more workers can be run simultaneously or alternatively reducing `max_parallel_workers_per_gather` so that the planner requests fewer workers. Every background worker process that is successfully started for a given parallel query will execute the parallel portion of the plan. The leader will also execute that portion of the plan, but it has an additional responsibility: it must also read all of the tuples generated by the workers. When the parallel portion of the plan generates only a small number of tuples, the leader will often behave very much like an additional worker, speeding up query execution. Conversely, when the parallel portion of the plan generates a large number of tuples, the leader may be almost entirely occupied with reading the tuples generated by the workers and performing any further processing steps that are required by plan nodes above the level of the `Gather` node or `Gather Merge` node. In such cases, the leader will do very little of the work of executing the parallel portion of the plan. When the node at the top of the parallel portion of the plan is `Gather Merge` rather than `Gather`, it indicates that each process executing the parallel portion of the plan is producing tuples in sorted order, and that the leader is performing an order-preserving merge. In contrast, `Gather` reads tuples from the workers in whatever order is convenient, destroying any sort order that may have existed. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/parallel-query.html "Chapter 15. Parallel Query") | [Up](https://www.postgresql.org/docs/current/parallel-query.html "Chapter 15. Parallel Query") | [Next](https://www.postgresql.org/docs/current/when-can-parallel-query-be-used.html "15.2. When Can Parallel Query Be Used?") | | Chapter 15. Parallel Query | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 15.2. When Can Parallel Query Be Used? | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/how-parallel-query-works.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 65.1. B-Tree Indexes November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/btree.html "PostgreSQL 18 - 65.1. B-Tree Indexes") ([18](https://www.postgresql.org/docs/18/btree.html "PostgreSQL 18 - 65.1. B-Tree Indexes") ) / [17](https://www.postgresql.org/docs/17/btree.html "PostgreSQL 17 - 65.1. B-Tree Indexes") / [16](https://www.postgresql.org/docs/16/btree.html "PostgreSQL 16 - 65.1. B-Tree Indexes") / [15](https://www.postgresql.org/docs/15/btree.html "PostgreSQL 15 - 65.1. B-Tree Indexes") / [14](https://www.postgresql.org/docs/14/btree.html "PostgreSQL 14 - 65.1. B-Tree Indexes") Development Versions: [devel](https://www.postgresql.org/docs/devel/btree.html "PostgreSQL devel - 65.1. B-Tree Indexes") Unsupported versions: [13](https://www.postgresql.org/docs/13/btree.html "PostgreSQL 13 - 65.1. B-Tree Indexes") / [12](https://www.postgresql.org/docs/12/btree.html "PostgreSQL 12 - 65.1. B-Tree Indexes") / [11](https://www.postgresql.org/docs/11/btree.html "PostgreSQL 11 - 65.1. B-Tree Indexes") | 65.1. B-Tree Indexes | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/indextypes.html "Chapter 65. Built-in Index Access Methods") | [Up](https://www.postgresql.org/docs/current/indextypes.html "Chapter 65. Built-in Index Access Methods") | Chapter 65. Built-in Index Access Methods | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/gist.html "65.2. GiST Indexes") | * * * 65.1. B-Tree Indexes [#](https://www.postgresql.org/docs/current/btree.html#BTREE) ----------------------------------------------------------------------------------- [65.1.1. Introduction](https://www.postgresql.org/docs/current/btree.html#BTREE-INTRO) [65.1.2. Behavior of B-Tree Operator Classes](https://www.postgresql.org/docs/current/btree.html#BTREE-BEHAVIOR) [65.1.3. B-Tree Support Functions](https://www.postgresql.org/docs/current/btree.html#BTREE-SUPPORT-FUNCS) [65.1.4. Implementation](https://www.postgresql.org/docs/current/btree.html#BTREE-IMPLEMENTATION) ### 65.1.1. Introduction [#](https://www.postgresql.org/docs/current/btree.html#BTREE-INTRO) PostgreSQL includes an implementation of the standard btree (multi-way balanced tree) index data structure. Any data type that can be sorted into a well-defined linear order can be indexed by a btree index. The only limitation is that an index entry cannot exceed approximately one-third of a page (after TOAST compression, if applicable). Because each btree operator class imposes a sort order on its data type, btree operator classes (or, really, operator families) have come to be used as PostgreSQL's general representation and understanding of sorting semantics. Therefore, they've acquired some features that go beyond what would be needed just to support btree indexes, and parts of the system that are quite distant from the btree AM make use of them. ### 65.1.2. Behavior of B-Tree Operator Classes [#](https://www.postgresql.org/docs/current/btree.html#BTREE-BEHAVIOR) As shown in [Table 36.3](https://www.postgresql.org/docs/current/xindex.html#XINDEX-BTREE-STRAT-TABLE "Table 36.3. B-Tree Strategies") , a btree operator class must provide five comparison operators, `<`, `<=`, `=`, `>=` and `>`. One might expect that `<>` should also be part of the operator class, but it is not, because it would almost never be useful to use a `<>` WHERE clause in an index search. (For some purposes, the planner treats `<>` as associated with a btree operator class; but it finds that operator via the `=` operator's negator link, rather than from `pg_amop`.) When several data types share near-identical sorting semantics, their operator classes can be grouped into an operator family. Doing so is advantageous because it allows the planner to make deductions about cross-type comparisons. Each operator class within the family should contain the single-type operators (and associated support functions) for its input data type, while cross-type comparison operators and support functions are “loose” in the family. It is recommendable that a complete set of cross-type operators be included in the family, thus ensuring that the planner can represent any comparison conditions that it deduces from transitivity. There are some basic assumptions that a btree operator family must satisfy: * An `=` operator must be an equivalence relation; that is, for all non-null values _`A`_, _`B`_, _`C`_ of the data type: * _`A`_ `=` _`A`_ is true (_reflexive law_) * if _`A`_ `=` _`B`_, then _`B`_ `=` _`A`_ (_symmetric law_) * if _`A`_ `=` _`B`_ and _`B`_ `=` _`C`_, then _`A`_ `=` _`C`_ (_transitive law_) * A `<` operator must be a strong ordering relation; that is, for all non-null values _`A`_, _`B`_, _`C`_: * _`A`_ `<` _`A`_ is false (_irreflexive law_) * if _`A`_ `<` _`B`_ and _`B`_ `<` _`C`_, then _`A`_ `<` _`C`_ (_transitive law_) * Furthermore, the ordering is total; that is, for all non-null values _`A`_, _`B`_: * exactly one of _`A`_ `<` _`B`_, _`A`_ `=` _`B`_, and _`B`_ `<` _`A`_ is true (_trichotomy law_) (The trichotomy law justifies the definition of the comparison support function, of course.) The other three operators are defined in terms of `=` and `<` in the obvious way, and must act consistently with them. For an operator family supporting multiple data types, the above laws must hold when _`A`_, _`B`_, _`C`_ are taken from any data types in the family. The transitive laws are the trickiest to ensure, as in cross-type situations they represent statements that the behaviors of two or three different operators are consistent. As an example, it would not work to put `float8` and `numeric` into the same operator family, at least not with the current semantics that `numeric` values are converted to `float8` for comparison to a `float8`. Because of the limited accuracy of `float8`, this means there are distinct `numeric` values that will compare equal to the same `float8` value, and thus the transitive law would fail. Another requirement for a multiple-data-type family is that any implicit or binary-coercion casts that are defined between data types included in the operator family must not change the associated sort ordering. It should be fairly clear why a btree index requires these laws to hold within a single data type: without them there is no ordering to arrange the keys with. Also, index searches using a comparison key of a different data type require comparisons to behave sanely across two data types. The extensions to three or more data types within a family are not strictly required by the btree index mechanism itself, but the planner relies on them for optimization purposes. ### 65.1.3. B-Tree Support Functions [#](https://www.postgresql.org/docs/current/btree.html#BTREE-SUPPORT-FUNCS) As shown in [Table 36.9](https://www.postgresql.org/docs/current/xindex.html#XINDEX-BTREE-SUPPORT-TABLE "Table 36.9. B-Tree Support Functions") , btree defines one required and five optional support functions. The six user-defined methods are: `order` For each combination of data types that a btree operator family provides comparison operators for, it must provide a comparison support function, registered in `pg_amproc` with support function number 1 and `amproclefttype`/`amprocrighttype` equal to the left and right data types for the comparison (i.e., the same data types that the matching operators are registered with in `pg_amop`). The comparison function must take two non-null values _`A`_ and _`B`_ and return an `int32` value that is `<` `0`, `0`, or `>` `0` when _`A`_ `<` _`B`_, _`A`_ `=` _`B`_, or _`A`_ `>` _`B`_, respectively. A null result is disallowed: all values of the data type must be comparable. See `src/backend/access/nbtree/nbtcompare.c` for examples. If the compared values are of a collatable data type, the appropriate collation OID will be passed to the comparison support function, using the standard `PG_GET_COLLATION()` mechanism. `sortsupport` Optionally, a btree operator family may provide _sort support_ function(s), registered under support function number 2. These functions allow implementing comparisons for sorting purposes in a more efficient way than naively calling the comparison support function. The APIs involved in this are defined in `src/include/utils/sortsupport.h`. `in_range` Optionally, a btree operator family may provide _in\_range_ support function(s), registered under support function number 3. These are not used during btree index operations; rather, they extend the semantics of the operator family so that it can support window clauses containing the `RANGE` _`offset`_ `PRECEDING` and `RANGE` _`offset`_ `FOLLOWING` frame bound types (see [Section 4.2.8](https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS "4.2.8. Window Function Calls") ). Fundamentally, the extra information provided is how to add or subtract an _`offset`_ value in a way that is compatible with the family's data ordering. An `in_range` function must have the signature in\_range(_`val`_ type1, _`base`_ type1, _`offset`_ type2, _`sub`_ bool, _`less`_ bool) returns bool _`val`_ and _`base`_ must be of the same type, which is one of the types supported by the operator family (i.e., a type for which it provides an ordering). However, _`offset`_ could be of a different type, which might be one otherwise unsupported by the family. An example is that the built-in `time_ops` family provides an `in_range` function that has _`offset`_ of type `interval`. A family can provide `in_range` functions for any of its supported types and one or more _`offset`_ types. Each `in_range` function should be entered in `pg_amproc` with `amproclefttype` equal to `type1` and `amprocrighttype` equal to `type2`. The essential semantics of an `in_range` function depend on the two Boolean flag parameters. It should add or subtract _`base`_ and _`offset`_, then compare _`val`_ to the result, as follows: * if `!`_`sub`_ and `!`_`less`_, return _`val`_ `>=` (_`base`_ `+` _`offset`_) * if `!`_`sub`_ and _`less`_, return _`val`_ `<=` (_`base`_ `+` _`offset`_) * if _`sub`_ and `!`_`less`_, return _`val`_ `>=` (_`base`_ `-` _`offset`_) * if _`sub`_ and _`less`_, return _`val`_ `<=` (_`base`_ `-` _`offset`_) Before doing so, the function should check the sign of _`offset`_: if it is less than zero, raise error `ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE` (22013) with error text like “invalid preceding or following size in window function”. (This is required by the SQL standard, although nonstandard operator families might perhaps choose to ignore this restriction, since there seems to be little semantic necessity for it.) This requirement is delegated to the `in_range` function so that the core code needn't understand what “less than zero” means for a particular data type. An additional expectation is that `in_range` functions should, if practical, avoid throwing an error if _`base`_ `+` _`offset`_ or _`base`_ `-` _`offset`_ would overflow. The correct comparison result can be determined even if that value would be out of the data type's range. Note that if the data type includes concepts such as “infinity” or “NaN”, extra care may be needed to ensure that `in_range`'s results agree with the normal sort order of the operator family. The results of the `in_range` function must be consistent with the sort ordering imposed by the operator family. To be precise, given any fixed values of _`offset`_ and _`sub`_, then: * If `in_range` with _`less`_ = true is true for some _`val1`_ and _`base`_, it must be true for every _`val2`_ `<=` _`val1`_ with the same _`base`_. * If `in_range` with _`less`_ = true is false for some _`val1`_ and _`base`_, it must be false for every _`val2`_ `>=` _`val1`_ with the same _`base`_. * If `in_range` with _`less`_ = true is true for some _`val`_ and _`base1`_, it must be true for every _`base2`_ `>=` _`base1`_ with the same _`val`_. * If `in_range` with _`less`_ = true is false for some _`val`_ and _`base1`_, it must be false for every _`base2`_ `<=` _`base1`_ with the same _`val`_. Analogous statements with inverted conditions hold when _`less`_ = false. If the type being ordered (`type1`) is collatable, the appropriate collation OID will be passed to the `in_range` function, using the standard PG\_GET\_COLLATION() mechanism. `in_range` functions need not handle NULL inputs, and typically will be marked strict. `equalimage` Optionally, a btree operator family may provide `equalimage` (“equality implies image equality”) support functions, registered under support function number 4. These functions allow the core code to determine when it is safe to apply the btree deduplication optimization. Currently, `equalimage` functions are only called when building or rebuilding an index. An `equalimage` function must have the signature equalimage(_`opcintype`_ `oid`) returns bool The return value is static information about an operator class and collation. Returning `true` indicates that the `order` function for the operator class is guaranteed to only return `0` (“arguments are equal”) when its _`A`_ and _`B`_ arguments are also interchangeable without any loss of semantic information. Not registering an `equalimage` function or returning `false` indicates that this condition cannot be assumed to hold. The _`opcintype`_ argument is the `` `pg_type`.oid `` of the data type that the operator class indexes. This is a convenience that allows reuse of the same underlying `equalimage` function across operator classes. If _`opcintype`_ is a collatable data type, the appropriate collation OID will be passed to the `equalimage` function, using the standard `PG_GET_COLLATION()` mechanism. As far as the operator class is concerned, returning `true` indicates that deduplication is safe (or safe for the collation whose OID was passed to its `equalimage` function). However, the core code will only deem deduplication safe for an index when _every_ indexed column uses an operator class that registers an `equalimage` function, and each function actually returns `true` when called. Image equality is _almost_ the same condition as simple bitwise equality. There is one subtle difference: When indexing a varlena data type, the on-disk representation of two image equal datums may not be bitwise equal due to inconsistent application of TOAST compression on input. Formally, when an operator class's `equalimage` function returns `true`, it is safe to assume that the `datum_image_eq()` C function will always agree with the operator class's `order` function (provided that the same collation OID is passed to both the `equalimage` and `order` functions). The core code is fundamentally unable to deduce anything about the “equality implies image equality” status of an operator class within a multiple-data-type family based on details from other operator classes in the same family. Also, it is not sensible for an operator family to register a cross-type `equalimage` function, and attempting to do so will result in an error. This is because “equality implies image equality” status does not just depend on sorting/equality semantics, which are more or less defined at the operator family level. In general, the semantics that one particular data type implements must be considered separately. The convention followed by the operator classes included with the core PostgreSQL distribution is to register a stock, generic `equalimage` function. Most operator classes register `btequalimage()`, which indicates that deduplication is safe unconditionally. Operator classes for collatable data types such as `text` register `btvarstrequalimage()`, which indicates that deduplication is safe with deterministic collations. Best practice for third-party extensions is to register their own custom function to retain control. `options` Optionally, a B-tree operator family may provide `options` (“operator class specific options”) support functions, registered under support function number 5. These functions define a set of user-visible parameters that control operator class behavior. An `options` support function must have the signature options(_`relopts`_ `local_relopts *`) returns void The function is passed a pointer to a `local_relopts` struct, which needs to be filled with a set of operator class specific options. The options can be accessed from other support functions using the `PG_HAS_OPCLASS_OPTIONS()` and `PG_GET_OPCLASS_OPTIONS()` macros. Currently, no B-Tree operator class has an `options` support function. B-tree doesn't allow flexible representation of keys like GiST, SP-GiST, GIN and BRIN do. So, `options` probably doesn't have much application in the current B-tree index access method. Nevertheless, this support function was added to B-tree for uniformity, and will probably find uses during further evolution of B-tree in PostgreSQL. `skipsupport` Optionally, a btree operator family may provide a _skip support_ function, registered under support function number 6. These functions give the B-tree code a way to iterate through every possible value that can be represented by an operator class's underlying input type, in key space order. This is used by the core code when it applies the skip scan optimization. The APIs involved in this are defined in `src/include/utils/skipsupport.h`. Operator classes that do not provide a skip support function are still eligible to use skip scan. The core code can still use its fallback strategy, though that might be suboptimal for some discrete types. It usually doesn't make sense (and may not even be feasible) for operator classes on continuous types to provide a skip support function. It is not sensible for an operator family to register a cross-type `skipsupport` function, and attempting to do so will result in an error. This is because determining the next indexable value must happen by incrementing a value copied from an index tuple. The values generated must all be of the same underlying data type (the “skipped” index column's opclass input type). ### 65.1.4. Implementation [#](https://www.postgresql.org/docs/current/btree.html#BTREE-IMPLEMENTATION) This section covers B-Tree index implementation details that may be of use to advanced users. See `src/backend/access/nbtree/README` in the source distribution for a much more detailed, internals-focused description of the B-Tree implementation. #### 65.1.4.1. B-Tree Structure [#](https://www.postgresql.org/docs/current/btree.html#BTREE-STRUCTURE) PostgreSQL B-Tree indexes are multi-level tree structures, where each level of the tree can be used as a doubly-linked list of pages. A single metapage is stored in a fixed position at the start of the first segment file of the index. All other pages are either leaf pages or internal pages. Leaf pages are the pages on the lowest level of the tree. All other levels consist of internal pages. Each leaf page contains tuples that point to table rows. Each internal page contains tuples that point to the next level down in the tree. Typically, over 99% of all pages are leaf pages. Both internal pages and leaf pages use the standard page format described in [Section 66.6](https://www.postgresql.org/docs/current/storage-page-layout.html "66.6. Database Page Layout") . New leaf pages are added to a B-Tree index when an existing leaf page cannot fit an incoming tuple. A _page split_ operation makes room for items that originally belonged on the overflowing page by moving a portion of the items to a new page. Page splits must also insert a new _downlink_ to the new page in the parent page, which may cause the parent to split in turn. Page splits “cascade upwards” in a recursive fashion. When the root page finally cannot fit a new downlink, a _root page split_ operation takes place. This adds a new level to the tree structure by creating a new root page that is one level above the original root page. #### 65.1.4.2. Bottom-up Index Deletion [#](https://www.postgresql.org/docs/current/btree.html#BTREE-DELETION) B-Tree indexes are not directly aware that under MVCC, there might be multiple extant versions of the same logical table row; to an index, each tuple is an independent object that needs its own index entry. “Version churn” tuples may sometimes accumulate and adversely affect query latency and throughput. This typically occurs with `UPDATE`\-heavy workloads where most individual updates cannot apply the [HOT optimization.](https://www.postgresql.org/docs/current/storage-hot.html "66.7. Heap-Only Tuples (HOT)") Changing the value of only one column covered by one index during an `UPDATE` _always_ necessitates a new set of index tuples — one for _each and every_ index on the table. Note in particular that this includes indexes that were not “logically modified” by the `UPDATE`. All indexes will need a successor physical index tuple that points to the latest version in the table. Each new tuple within each index will generally need to coexist with the original “updated” tuple for a short period of time (typically until shortly after the `UPDATE` transaction commits). B-Tree indexes incrementally delete version churn index tuples by performing _bottom-up index deletion_ passes. Each deletion pass is triggered in reaction to an anticipated “version churn page split”. This only happens with indexes that are not logically modified by `UPDATE` statements, where concentrated build up of obsolete versions in particular pages would occur otherwise. A page split will usually be avoided, though it's possible that certain implementation-level heuristics will fail to identify and delete even one garbage index tuple (in which case a page split or deduplication pass resolves the issue of an incoming new tuple not fitting on a leaf page). The worst-case number of versions that any index scan must traverse (for any single logical row) is an important contributor to overall system responsiveness and throughput. A bottom-up index deletion pass targets suspected garbage tuples in a single leaf page based on _qualitative_ distinctions involving logical rows and versions. This contrasts with the “top-down” index cleanup performed by autovacuum workers, which is triggered when certain _quantitative_ table-level thresholds are exceeded (see [Section 24.1.6](https://www.postgresql.org/docs/current/routine-vacuuming.html#AUTOVACUUM "24.1.6. The Autovacuum Daemon") ). ### Note Not all deletion operations that are performed within B-Tree indexes are bottom-up deletion operations. There is a distinct category of index tuple deletion: _simple index tuple deletion_. This is a deferred maintenance operation that deletes index tuples that are known to be safe to delete (those whose item identifier's `LP_DEAD` bit is already set). Like bottom-up index deletion, simple index deletion takes place at the point that a page split is anticipated as a way of avoiding the split. Simple deletion is opportunistic in the sense that it can only take place when recent index scans set the `LP_DEAD` bits of affected items in passing. Prior to PostgreSQL 14, the only category of B-Tree deletion was simple deletion. The main differences between it and bottom-up deletion are that only the former is opportunistically driven by the activity of passing index scans, while only the latter specifically targets version churn from `UPDATE`s that do not logically modify indexed columns. Bottom-up index deletion performs the vast majority of all garbage index tuple cleanup for particular indexes with certain workloads. This is expected with any B-Tree index that is subject to significant version churn from `UPDATE`s that rarely or never logically modify the columns that the index covers. The average and worst-case number of versions per logical row can be kept low purely through targeted incremental deletion passes. It's quite possible that the on-disk size of certain indexes will never increase by even one single page/block despite _constant_ version churn from `UPDATE`s. Even then, an exhaustive “clean sweep” by a `VACUUM` operation (typically run in an autovacuum worker process) will eventually be required as a part of _collective_ cleanup of the table and each of its indexes. Unlike `VACUUM`, bottom-up index deletion does not provide any strong guarantees about how old the oldest garbage index tuple may be. No index can be permitted to retain “floating garbage” index tuples that became dead prior to a conservative cutoff point shared by the table and all of its indexes collectively. This fundamental table-level invariant makes it safe to recycle table TIDs. This is how it is possible for distinct logical rows to reuse the same table TID over time (though this can never happen with two logical rows whose lifetimes span the same `VACUUM` cycle). #### 65.1.4.3. Deduplication [#](https://www.postgresql.org/docs/current/btree.html#BTREE-DEDUPLICATION) A duplicate is a leaf page tuple (a tuple that points to a table row) where _all_ indexed key columns have values that match corresponding column values from at least one other leaf page tuple in the same index. Duplicate tuples are quite common in practice. B-Tree indexes can use a special, space-efficient representation for duplicates when an optional technique is enabled: _deduplication_. Deduplication works by periodically merging groups of duplicate tuples together, forming a single _posting list_ tuple for each group. The column key value(s) only appear once in this representation. This is followed by a sorted array of TIDs that point to rows in the table. This significantly reduces the storage size of indexes where each value (or each distinct combination of column values) appears several times on average. The latency of queries can be reduced significantly. Overall query throughput may increase significantly. The overhead of routine index vacuuming may also be reduced significantly. ### Note B-Tree deduplication is just as effective with “duplicates” that contain a NULL value, even though NULL values are never equal to each other according to the `=` member of any B-Tree operator class. As far as any part of the implementation that understands the on-disk B-Tree structure is concerned, NULL is just another value from the domain of indexed values. The deduplication process occurs lazily, when a new item is inserted that cannot fit on an existing leaf page, though only when index tuple deletion could not free sufficient space for the new item (typically deletion is briefly considered and then skipped over). Unlike GIN posting list tuples, B-Tree posting list tuples do not need to expand every time a new duplicate is inserted; they are merely an alternative physical representation of the original logical contents of the leaf page. This design prioritizes consistent performance with mixed read-write workloads. Most client applications will at least see a moderate performance benefit from using deduplication. Deduplication is enabled by default. `CREATE INDEX` and `REINDEX` apply deduplication to create posting list tuples, though the strategy they use is slightly different. Each group of duplicate ordinary tuples encountered in the sorted input taken from the table is merged into a posting list tuple _before_ being added to the current pending leaf page. Individual posting list tuples are packed with as many TIDs as possible. Leaf pages are written out in the usual way, without any separate deduplication pass. This strategy is well-suited to `CREATE INDEX` and `REINDEX` because they are once-off batch operations. Write-heavy workloads that don't benefit from deduplication due to having few or no duplicate values in indexes will incur a small, fixed performance penalty (unless deduplication is explicitly disabled). The `deduplicate_items` storage parameter can be used to disable deduplication within individual indexes. There is never any performance penalty with read-only workloads, since reading posting list tuples is at least as efficient as reading the standard tuple representation. Disabling deduplication isn't usually helpful. It is sometimes possible for unique indexes (as well as unique constraints) to use deduplication. This allows leaf pages to temporarily “absorb” extra version churn duplicates. Deduplication in unique indexes augments bottom-up index deletion, especially in cases where a long-running transaction holds a snapshot that blocks garbage collection. The goal is to buy time for the bottom-up index deletion strategy to become effective again. Delaying page splits until a single long-running transaction naturally goes away can allow a bottom-up deletion pass to succeed where an earlier deletion pass failed. ### Tip A special heuristic is applied to determine whether a deduplication pass in a unique index should take place. It can often skip straight to splitting a leaf page, avoiding a performance penalty from wasting cycles on unhelpful deduplication passes. If you're concerned about the overhead of deduplication, consider setting `deduplicate_items = off` selectively. Leaving deduplication enabled in unique indexes has little downside. Deduplication cannot be used in all cases due to implementation-level restrictions. Deduplication safety is determined when `CREATE INDEX` or `REINDEX` is run. Note that deduplication is deemed unsafe and cannot be used in the following cases involving semantically significant differences among equal datums: * `text`, `varchar`, and `char` cannot use deduplication when a _nondeterministic_ collation is used. Case and accent differences must be preserved among equal datums. * `numeric` cannot use deduplication. Numeric display scale must be preserved among equal datums. * `jsonb` cannot use deduplication, since the `jsonb` B-Tree operator class uses `numeric` internally. * `float4` and `float8` cannot use deduplication. These types have distinct representations for `-0` and `0`, which are nevertheless considered equal. This difference must be preserved. There is one further implementation-level restriction that may be lifted in a future version of PostgreSQL: * Container types (such as composite types, arrays, or range types) cannot use deduplication. There is one further implementation-level restriction that applies regardless of the operator class or collation used: * `INCLUDE` indexes can never use deduplication. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/indextypes.html "Chapter 65. Built-in Index Access Methods") | [Up](https://www.postgresql.org/docs/current/indextypes.html "Chapter 65. Built-in Index Access Methods") | [Next](https://www.postgresql.org/docs/current/gist.html "65.2. GiST Indexes") | | Chapter 65. Built-in Index Access Methods | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 65.2. GiST Indexes | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/btree.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 26.4. Hot Standby November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/hot-standby.html "PostgreSQL 18 - 26.4. Hot Standby") ([18](https://www.postgresql.org/docs/18/hot-standby.html "PostgreSQL 18 - 26.4. Hot Standby") ) / [17](https://www.postgresql.org/docs/17/hot-standby.html "PostgreSQL 17 - 26.4. Hot Standby") / [16](https://www.postgresql.org/docs/16/hot-standby.html "PostgreSQL 16 - 26.4. Hot Standby") / [15](https://www.postgresql.org/docs/15/hot-standby.html "PostgreSQL 15 - 26.4. Hot Standby") / [14](https://www.postgresql.org/docs/14/hot-standby.html "PostgreSQL 14 - 26.4. Hot Standby") Development Versions: [devel](https://www.postgresql.org/docs/devel/hot-standby.html "PostgreSQL devel - 26.4. Hot Standby") Unsupported versions: [13](https://www.postgresql.org/docs/13/hot-standby.html "PostgreSQL 13 - 26.4. Hot Standby") / [12](https://www.postgresql.org/docs/12/hot-standby.html "PostgreSQL 12 - 26.4. Hot Standby") / [11](https://www.postgresql.org/docs/11/hot-standby.html "PostgreSQL 11 - 26.4. Hot Standby") / [10](https://www.postgresql.org/docs/10/hot-standby.html "PostgreSQL 10 - 26.4. Hot Standby") / [9.6](https://www.postgresql.org/docs/9.6/hot-standby.html "PostgreSQL 9.6 - 26.4. Hot Standby") / [9.5](https://www.postgresql.org/docs/9.5/hot-standby.html "PostgreSQL 9.5 - 26.4. Hot Standby") / [9.4](https://www.postgresql.org/docs/9.4/hot-standby.html "PostgreSQL 9.4 - 26.4. Hot Standby") / [9.3](https://www.postgresql.org/docs/9.3/hot-standby.html "PostgreSQL 9.3 - 26.4. Hot Standby") / [9.2](https://www.postgresql.org/docs/9.2/hot-standby.html "PostgreSQL 9.2 - 26.4. Hot Standby") / [9.1](https://www.postgresql.org/docs/9.1/hot-standby.html "PostgreSQL 9.1 - 26.4. Hot Standby") / [9.0](https://www.postgresql.org/docs/9.0/hot-standby.html "PostgreSQL 9.0 - 26.4. Hot Standby") | 26.4. Hot Standby | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/warm-standby-failover.html "26.3. Failover") | [Up](https://www.postgresql.org/docs/18/high-availability.html "Chapter 26. High Availability, Load Balancing, and Replication") | Chapter 26. High Availability, Load Balancing, and Replication | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/monitoring.html "Chapter 27. Monitoring Database Activity") | * * * 26.4. Hot Standby [#](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY) --------------------------------------------------------------------------------------- [26.4.1. User's Overview](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-USERS) [26.4.2. Handling Query Conflicts](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-CONFLICT) [26.4.3. Administrator's Overview](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-ADMIN) [26.4.4. Hot Standby Parameter Reference](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-PARAMETERS) [26.4.5. Caveats](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-CAVEATS) Hot standby is the term used to describe the ability to connect to the server and run read-only queries while the server is in archive recovery or standby mode. This is useful both for replication purposes and for restoring a backup to a desired state with great precision. The term hot standby also refers to the ability of the server to move from recovery through to normal operation while users continue running queries and/or keep their connections open. Running queries in hot standby mode is similar to normal query operation, though there are several usage and administrative differences explained below. ### 26.4.1. User's Overview [#](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-USERS) When the [hot\_standby](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-HOT-STANDBY) parameter is set to true on a standby server, it will begin accepting connections once the recovery has brought the system to a consistent state and be ready for hot standby. All such connections are strictly read-only; not even temporary tables may be written. The data on the standby takes some time to arrive from the primary server so there will be a measurable delay between primary and standby. Running the same query nearly simultaneously on both primary and standby might therefore return differing results. We say that data on the standby is _eventually consistent_ with the primary. Once the commit record for a transaction is replayed on the standby, the changes made by that transaction will be visible to any new snapshots taken on the standby. Snapshots may be taken at the start of each query or at the start of each transaction, depending on the current transaction isolation level. For more details, see [Section 13.2](https://www.postgresql.org/docs/18/transaction-iso.html "13.2. Transaction Isolation") . Transactions started during hot standby may issue the following commands: * Query access: `SELECT`, `COPY TO` * Cursor commands: `DECLARE`, `FETCH`, `CLOSE` * Settings: `SHOW`, `SET`, `RESET` * Transaction management commands: * `BEGIN`, `END`, `ABORT`, `START TRANSACTION` * `SAVEPOINT`, `RELEASE`, `ROLLBACK TO SAVEPOINT` * `EXCEPTION` blocks and other internal subtransactions * `LOCK TABLE`, though only when explicitly in one of these modes: `ACCESS SHARE`, `ROW SHARE` or `ROW EXCLUSIVE`. * Plans and resources: `PREPARE`, `EXECUTE`, `DEALLOCATE`, `DISCARD` * Plugins and extensions: `LOAD` * `UNLISTEN` Transactions started during hot standby will never be assigned a transaction ID and cannot write to the system write-ahead log. Therefore, the following actions will produce error messages: * Data Manipulation Language (DML): `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `COPY FROM`, `TRUNCATE`. Note that there are no allowed actions that result in a trigger being executed during recovery. This restriction applies even to temporary tables, because table rows cannot be read or written without assigning a transaction ID, which is currently not possible in a hot standby environment. * Data Definition Language (DDL): `CREATE`, `DROP`, `ALTER`, `COMMENT`. This restriction applies even to temporary tables, because carrying out these operations would require updating the system catalog tables. * `SELECT ... FOR SHARE | UPDATE`, because row locks cannot be taken without updating the underlying data files. * Rules on `SELECT` statements that generate DML commands. * `LOCK` that explicitly requests a mode higher than `ROW EXCLUSIVE MODE`. * `LOCK` in short default form, since it requests `ACCESS EXCLUSIVE MODE`. * Transaction management commands that explicitly set non-read-only state: * `BEGIN READ WRITE`, `START TRANSACTION READ WRITE` * `SET TRANSACTION READ WRITE`, `SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE` * `SET transaction_read_only = off` * Two-phase commit commands: `PREPARE TRANSACTION`, `COMMIT PREPARED`, `ROLLBACK PREPARED` because even read-only transactions need to write WAL in the prepare phase (the first phase of two phase commit). * Sequence updates: `nextval()`, `setval()` * `LISTEN`, `NOTIFY` In normal operation, “read-only” transactions are allowed to use `LISTEN` and `NOTIFY`, so hot standby sessions operate under slightly tighter restrictions than ordinary read-only sessions. It is possible that some of these restrictions might be loosened in a future release. During hot standby, the parameter `transaction_read_only` is always true and may not be changed. But as long as no attempt is made to modify the database, connections during hot standby will act much like any other database connection. If failover or switchover occurs, the database will switch to normal processing mode. Sessions will remain connected while the server changes mode. Once hot standby finishes, it will be possible to initiate read-write transactions (even from a session begun during hot standby). Users can determine whether hot standby is currently active for their session by issuing `SHOW in_hot_standby`. (In server versions before 14, the `in_hot_standby` parameter did not exist; a workable substitute method for older servers is `SHOW transaction_read_only`.) In addition, a set of functions ([Table 9.98](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-RECOVERY-INFO-TABLE "Table 9.98. Recovery Information Functions") ) allow users to access information about the standby server. These allow you to write programs that are aware of the current state of the database. These can be used to monitor the progress of recovery, or to allow you to write complex programs that restore the database to particular states. ### 26.4.2. Handling Query Conflicts [#](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-CONFLICT) The primary and standby servers are in many ways loosely connected. Actions on the primary will have an effect on the standby. As a result, there is potential for negative interactions or conflicts between them. The easiest conflict to understand is performance: if a huge data load is taking place on the primary then this will generate a similar stream of WAL records on the standby, so standby queries may contend for system resources, such as I/O. There are also additional types of conflict that can occur with hot standby. These conflicts are _hard conflicts_ in the sense that queries might need to be canceled and, in some cases, sessions disconnected to resolve them. The user is provided with several ways to handle these conflicts. Conflict cases include: * Access Exclusive locks taken on the primary server, including both explicit `LOCK` commands and various DDL actions, conflict with table accesses in standby queries. * Dropping a tablespace on the primary conflicts with standby queries using that tablespace for temporary work files. * Dropping a database on the primary conflicts with sessions connected to that database on the standby. * Application of a vacuum cleanup record from WAL conflicts with standby transactions whose snapshots can still “see” any of the rows to be removed. * Application of a vacuum cleanup record from WAL conflicts with queries accessing the target page on the standby, whether or not the data to be removed is visible. On the primary server, these cases simply result in waiting; and the user might choose to cancel either of the conflicting actions. However, on the standby there is no choice: the WAL-logged action already occurred on the primary so the standby must not fail to apply it. Furthermore, allowing WAL application to wait indefinitely may be very undesirable, because the standby's state will become increasingly far behind the primary's. Therefore, a mechanism is provided to forcibly cancel standby queries that conflict with to-be-applied WAL records. An example of the problem situation is an administrator on the primary server running `DROP TABLE` on a table that is currently being queried on the standby server. Clearly the standby query cannot continue if the `DROP TABLE` is applied on the standby. If this situation occurred on the primary, the `DROP TABLE` would wait until the other query had finished. But when `DROP TABLE` is run on the primary, the primary doesn't have information about what queries are running on the standby, so it will not wait for any such standby queries. The WAL change records come through to the standby while the standby query is still running, causing a conflict. The standby server must either delay application of the WAL records (and everything after them, too) or else cancel the conflicting query so that the `DROP TABLE` can be applied. When a conflicting query is short, it's typically desirable to allow it to complete by delaying WAL application for a little bit; but a long delay in WAL application is usually not desirable. So the cancel mechanism has parameters, [max\_standby\_archive\_delay](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-STANDBY-ARCHIVE-DELAY) and [max\_standby\_streaming\_delay](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-STANDBY-STREAMING-DELAY) , that define the maximum allowed delay in WAL application. Conflicting queries will be canceled once it has taken longer than the relevant delay setting to apply any newly-received WAL data. There are two parameters so that different delay values can be specified for the case of reading WAL data from an archive (i.e., initial recovery from a base backup or “catching up” a standby server that has fallen far behind) versus reading WAL data via streaming replication. In a standby server that exists primarily for high availability, it's best to set the delay parameters relatively short, so that the server cannot fall far behind the primary due to delays caused by standby queries. However, if the standby server is meant for executing long-running queries, then a high or even infinite delay value may be preferable. Keep in mind however that a long-running query could cause other sessions on the standby server to not see recent changes on the primary, if it delays application of WAL records. Once the delay specified by `max_standby_archive_delay` or `max_standby_streaming_delay` has been exceeded, conflicting queries will be canceled. This usually results just in a cancellation error, although in the case of replaying a `DROP DATABASE` the entire conflicting session will be terminated. Also, if the conflict is over a lock held by an idle transaction, the conflicting session is terminated (this behavior might change in the future). Canceled queries may be retried immediately (after beginning a new transaction, of course). Since query cancellation depends on the nature of the WAL records being replayed, a query that was canceled may well succeed if it is executed again. Keep in mind that the delay parameters are compared to the elapsed time since the WAL data was received by the standby server. Thus, the grace period allowed to any one query on the standby is never more than the delay parameter, and could be considerably less if the standby has already fallen behind as a result of waiting for previous queries to complete, or as a result of being unable to keep up with a heavy update load. The most common reason for conflict between standby queries and WAL replay is “early cleanup”. Normally, PostgreSQL allows cleanup of old row versions when there are no transactions that need to see them to ensure correct visibility of data according to MVCC rules. However, this rule can only be applied for transactions executing on the primary. So it is possible that cleanup on the primary will remove row versions that are still visible to a transaction on the standby. Row version cleanup isn't the only potential cause of conflicts with standby queries. All index-only scans (including those that run on standbys) must use an MVCC snapshot that “agrees” with the visibility map. Conflicts are therefore required whenever `VACUUM` [sets a page as all-visible in the visibility map](https://www.postgresql.org/docs/18/routine-vacuuming.html#VACUUM-FOR-VISIBILITY-MAP "24.1.4. Updating the Visibility Map") containing one or more rows _not_ visible to all standby queries. So even running `VACUUM` against a table with no updated or deleted rows requiring cleanup might lead to conflicts. Users should be clear that tables that are regularly and heavily updated on the primary server will quickly cause cancellation of longer running queries on the standby. In such cases the setting of a finite value for `max_standby_archive_delay` or `max_standby_streaming_delay` can be considered similar to setting `statement_timeout`. Remedial possibilities exist if the number of standby-query cancellations is found to be unacceptable. The first option is to set the parameter `hot_standby_feedback`, which prevents `VACUUM` from removing recently-dead rows and so cleanup conflicts do not occur. If you do this, you should note that this will delay cleanup of dead rows on the primary, which may result in undesirable table bloat. However, the cleanup situation will be no worse than if the standby queries were running directly on the primary server, and you are still getting the benefit of off-loading execution onto the standby. If standby servers connect and disconnect frequently, you might want to make adjustments to handle the period when `hot_standby_feedback` feedback is not being provided. For example, consider increasing `max_standby_archive_delay` so that queries are not rapidly canceled by conflicts in WAL archive files during disconnected periods. You should also consider increasing `max_standby_streaming_delay` to avoid rapid cancellations by newly-arrived streaming WAL entries after reconnection. The number of query cancels and the reason for them can be viewed using the `pg_stat_database_conflicts` system view on the standby server. The `pg_stat_database` system view also contains summary information. Users can control whether a log message is produced when WAL replay is waiting longer than `deadlock_timeout` for conflicts. This is controlled by the [log\_recovery\_conflict\_waits](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-RECOVERY-CONFLICT-WAITS) parameter. ### 26.4.3. Administrator's Overview [#](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-ADMIN) If `hot_standby` is `on` in `postgresql.conf` (the default value) and there is a [`standby.signal`](https://www.postgresql.org/docs/18/warm-standby.html#FILE-STANDBY-SIGNAL) file present, the server will run in hot standby mode. However, it may take some time for hot standby connections to be allowed, because the server will not accept connections until it has completed sufficient recovery to provide a consistent state against which queries can run. During this period, clients that attempt to connect will be refused with an error message. To confirm the server has come up, either loop trying to connect from the application, or look for these messages in the server logs: LOG: entering standby mode ... then some time later ... LOG: consistent recovery state reached LOG: database system is ready to accept read-only connections Consistency information is recorded once per checkpoint on the primary. It is not possible to enable hot standby when reading WAL written during a period when `wal_level` was not set to `replica` or `logical` on the primary. Even after reaching a consistent state, the recovery snapshot may not be ready for hot standby if both of the following conditions are met, delaying accepting read-only connections. To enable hot standby, long-lived write transactions with more than 64 subtransactions need to be closed on the primary. * A write transaction has more than 64 subtransactions * Very long-lived write transactions If you are running file-based log shipping ("warm standby"), you might need to wait until the next WAL file arrives, which could be as long as the `archive_timeout` setting on the primary. The settings of some parameters determine the size of shared memory for tracking transaction IDs, locks, and prepared transactions. These shared memory structures must be no smaller on a standby than on the primary in order to ensure that the standby does not run out of shared memory during recovery. For example, if the primary had used a prepared transaction but the standby had not allocated any shared memory for tracking prepared transactions, then recovery could not continue until the standby's configuration is changed. The parameters affected are: * `max_connections` * `max_prepared_transactions` * `max_locks_per_transaction` * `max_wal_senders` * `max_worker_processes` The easiest way to ensure this does not become a problem is to have these parameters set on the standbys to values equal to or greater than on the primary. Therefore, if you want to increase these values, you should do so on all standby servers first, before applying the changes to the primary server. Conversely, if you want to decrease these values, you should do so on the primary server first, before applying the changes to all standby servers. Keep in mind that when a standby is promoted, it becomes the new reference for the required parameter settings for the standbys that follow it. Therefore, to avoid this becoming a problem during a switchover or failover, it is recommended to keep these settings the same on all standby servers. The WAL tracks changes to these parameters on the primary. If a hot standby processes WAL that indicates that the current value on the primary is higher than its own value, it will log a warning and pause recovery, for example: WARNING: hot standby is not possible because of insufficient parameter settings DETAIL: max\_connections = 80 is a lower setting than on the primary server, where its value was 100. LOG: recovery has paused DETAIL: If recovery is unpaused, the server will shut down. HINT: You can then restart the server after making the necessary configuration changes. At that point, the settings on the standby need to be updated and the instance restarted before recovery can continue. If the standby is not a hot standby, then when it encounters the incompatible parameter change, it will shut down immediately without pausing, since there is then no value in keeping it up. It is important that the administrator select appropriate settings for [max\_standby\_archive\_delay](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-STANDBY-ARCHIVE-DELAY) and [max\_standby\_streaming\_delay](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-STANDBY-STREAMING-DELAY) . The best choices vary depending on business priorities. For example if the server is primarily tasked as a High Availability server, then you will want low delay settings, perhaps even zero, though that is a very aggressive setting. If the standby server is tasked as an additional server for decision support queries then it might be acceptable to set the maximum delay values to many hours, or even -1 which means wait forever for queries to complete. Transaction status "hint bits" written on the primary are not WAL-logged, so data on the standby will likely re-write the hints again on the standby. Thus, the standby server will still perform disk writes even though all users are read-only; no changes occur to the data values themselves. Users will still write large sort temporary files and re-generate relcache info files, so no part of the database is truly read-only during hot standby mode. Note also that writes to remote databases using dblink module, and other operations outside the database using PL functions will still be possible, even though the transaction is read-only locally. The following types of administration commands are not accepted during recovery mode: * Data Definition Language (DDL): e.g., `CREATE INDEX` * Privilege and Ownership: `GRANT`, `REVOKE`, `REASSIGN` * Maintenance commands: `ANALYZE`, `VACUUM`, `CLUSTER`, `REINDEX` Again, note that some of these commands are actually allowed during "read only" mode transactions on the primary. As a result, you cannot create additional indexes that exist solely on the standby, nor statistics that exist solely on the standby. If these administration commands are needed, they should be executed on the primary, and eventually those changes will propagate to the standby. `pg_cancel_backend()` and `pg_terminate_backend()` will work on user backends, but not the startup process, which performs recovery. `pg_stat_activity` does not show recovering transactions as active. As a result, `pg_prepared_xacts` is always empty during recovery. If you wish to resolve in-doubt prepared transactions, view `pg_prepared_xacts` on the primary and issue commands to resolve transactions there or resolve them after the end of recovery. `pg_locks` will show locks held by backends, as normal. `pg_locks` also shows a virtual transaction managed by the startup process that owns all `AccessExclusiveLocks` held by transactions being replayed by recovery. Note that the startup process does not acquire locks to make database changes, and thus locks other than `AccessExclusiveLocks` do not show in `pg_locks` for the Startup process; they are just presumed to exist. The Nagios plugin check\_pgsql will work, because the simple information it checks for exists. The check\_postgres monitoring script will also work, though some reported values could give different or confusing results. For example, last vacuum time will not be maintained, since no vacuum occurs on the standby. Vacuums running on the primary do still send their changes to the standby. WAL file control commands will not work during recovery, e.g., `pg_backup_start`, `pg_switch_wal` etc. Dynamically loadable modules work, including `pg_stat_statements`. Advisory locks work normally in recovery, including deadlock detection. Note that advisory locks are never WAL logged, so it is impossible for an advisory lock on either the primary or the standby to conflict with WAL replay. Nor is it possible to acquire an advisory lock on the primary and have it initiate a similar advisory lock on the standby. Advisory locks relate only to the server on which they are acquired. Trigger-based replication systems such as Slony, Londiste and Bucardo won't run on the standby at all, though they will run happily on the primary server as long as the changes are not sent to standby servers to be applied. WAL replay is not trigger-based so you cannot relay from the standby to any system that requires additional database writes or relies on the use of triggers. New OIDs cannot be assigned, though some UUID generators may still work as long as they do not rely on writing new status to the database. Currently, temporary table creation is not allowed during read-only transactions, so in some cases existing scripts will not run correctly. This restriction might be relaxed in a later release. This is both an SQL standard compliance issue and a technical issue. `DROP TABLESPACE` can only succeed if the tablespace is empty. Some standby users may be actively using the tablespace via their `temp_tablespaces` parameter. If there are temporary files in the tablespace, all active queries are canceled to ensure that temporary files are removed, so the tablespace can be removed and WAL replay can continue. Running `DROP DATABASE` or `ALTER DATABASE ... SET TABLESPACE` on the primary will generate a WAL entry that will cause all users connected to that database on the standby to be forcibly disconnected. This action occurs immediately, whatever the setting of `max_standby_streaming_delay`. Note that `ALTER DATABASE ... RENAME` does not disconnect users, which in most cases will go unnoticed, though might in some cases cause a program confusion if it depends in some way upon database name. In normal (non-recovery) mode, if you issue `DROP USER` or `DROP ROLE` for a role with login capability while that user is still connected then nothing happens to the connected user — they remain connected. The user cannot reconnect however. This behavior applies in recovery also, so a `DROP USER` on the primary does not disconnect that user on the standby. The cumulative statistics system is active during recovery. All scans, reads, blocks, index usage, etc., will be recorded normally on the standby. However, WAL replay will not increment relation and database specific counters. I.e. replay will not increment `pg_stat_all_tables` columns (like `n_tup_ins`), nor will reads or writes performed by the startup process be tracked in the `pg_statio_` views, nor will associated `pg_stat_database` columns be incremented. Autovacuum is not active during recovery. It will start normally at the end of recovery. The checkpointer process and the background writer process are active during recovery. The checkpointer process will perform restartpoints (similar to checkpoints on the primary) and the background writer process will perform normal block cleaning activities. This can include updates of the hint bit information stored on the standby server. The `CHECKPOINT` command is accepted during recovery, though it performs a restartpoint rather than a new checkpoint. ### 26.4.4. Hot Standby Parameter Reference [#](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-PARAMETERS) Various parameters have been mentioned above in [Section 26.4.2](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-CONFLICT "26.4.2. Handling Query Conflicts") and [Section 26.4.3](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-ADMIN "26.4.3. Administrator's Overview") . On the primary, the [wal\_level](https://www.postgresql.org/docs/18/runtime-config-wal.html#GUC-WAL-LEVEL) parameter can be used. [max\_standby\_archive\_delay](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-STANDBY-ARCHIVE-DELAY) and [max\_standby\_streaming\_delay](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-STANDBY-STREAMING-DELAY) have no effect if set on the primary. On the standby, parameters [hot\_standby](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-HOT-STANDBY) , [max\_standby\_archive\_delay](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-STANDBY-ARCHIVE-DELAY) and [max\_standby\_streaming\_delay](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-MAX-STANDBY-STREAMING-DELAY) can be used. ### 26.4.5. Caveats [#](https://www.postgresql.org/docs/18/hot-standby.html#HOT-STANDBY-CAVEATS) There are several limitations of hot standby. These can and probably will be fixed in future releases: * Full knowledge of running transactions is required before snapshots can be taken. Transactions that use large numbers of subtransactions (currently greater than 64) will delay the start of read-only connections until the completion of the longest running write transaction. If this situation occurs, explanatory messages will be sent to the server log. * Valid starting points for standby queries are generated at each checkpoint on the primary. If the standby is shut down while the primary is in a shutdown state, it might not be possible to re-enter hot standby until the primary is started up, so that it generates further starting points in the WAL logs. This situation isn't a problem in the most common situations where it might happen. Generally, if the primary is shut down and not available anymore, that's likely due to a serious failure that requires the standby being converted to operate as the new primary anyway. And in situations where the primary is being intentionally taken down, coordinating to make sure the standby becomes the new primary smoothly is also standard procedure. * At the end of recovery, `AccessExclusiveLocks` held by prepared transactions will require twice the normal number of lock table entries. If you plan on running either a large number of concurrent prepared transactions that normally take `AccessExclusiveLocks`, or you plan on having one large transaction that takes many `AccessExclusiveLocks`, you are advised to select a larger value of `max_locks_per_transaction`, perhaps as much as twice the value of the parameter on the primary server. You need not consider this at all if your setting of `max_prepared_transactions` is 0. * The Serializable transaction isolation level is not yet available in hot standby. (See [Section 13.2.3](https://www.postgresql.org/docs/18/transaction-iso.html#XACT-SERIALIZABLE "13.2.3. Serializable Isolation Level") and [Section 13.4.1](https://www.postgresql.org/docs/18/applevel-consistency.html#SERIALIZABLE-CONSISTENCY "13.4.1. Enforcing Consistency with Serializable Transactions") for details.) An attempt to set a transaction to the serializable isolation level in hot standby mode will generate an error. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/warm-standby-failover.html "26.3. Failover") | [Up](https://www.postgresql.org/docs/18/high-availability.html "Chapter 26. High Availability, Load Balancing, and Replication") | [Next](https://www.postgresql.org/docs/18/monitoring.html "Chapter 27. Monitoring Database Activity") | | 26.3. Failover | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | Chapter 27. Monitoring Database Activity | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/hot-standby.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: ALTER ROUTINE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alterroutine.html "PostgreSQL 18 - ALTER ROUTINE") ([18](https://www.postgresql.org/docs/18/sql-alterroutine.html "PostgreSQL 18 - ALTER ROUTINE") ) / [17](https://www.postgresql.org/docs/17/sql-alterroutine.html "PostgreSQL 17 - ALTER ROUTINE") / [16](https://www.postgresql.org/docs/16/sql-alterroutine.html "PostgreSQL 16 - ALTER ROUTINE") / [15](https://www.postgresql.org/docs/15/sql-alterroutine.html "PostgreSQL 15 - ALTER ROUTINE") / [14](https://www.postgresql.org/docs/14/sql-alterroutine.html "PostgreSQL 14 - ALTER ROUTINE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alterroutine.html "PostgreSQL devel - ALTER ROUTINE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alterroutine.html "PostgreSQL 13 - ALTER ROUTINE") / [12](https://www.postgresql.org/docs/12/sql-alterroutine.html "PostgreSQL 12 - ALTER ROUTINE") / [11](https://www.postgresql.org/docs/11/sql-alterroutine.html "PostgreSQL 11 - ALTER ROUTINE") | ALTER ROUTINE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-alterrole.html "ALTER ROLE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-alterrule.html "ALTER RULE") | * * * ALTER ROUTINE ------------- ALTER ROUTINE — change the definition of a routine Synopsis -------- ALTER ROUTINE _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] _`action`_ \[ ... \] \[ RESTRICT \] ALTER ROUTINE _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] RENAME TO _`new_name`_ ALTER ROUTINE _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] OWNER TO { _`new_owner`_ | CURRENT\_ROLE | CURRENT\_USER | SESSION\_USER } ALTER ROUTINE _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] SET SCHEMA _`new_schema`_ ALTER ROUTINE _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] \[ NO \] DEPENDS ON EXTENSION _`extension_name`_ where _`action`_ is one of: IMMUTABLE | STABLE | VOLATILE \[ NOT \] LEAKPROOF \[ EXTERNAL \] SECURITY INVOKER | \[ EXTERNAL \] SECURITY DEFINER PARALLEL { UNSAFE | RESTRICTED | SAFE } COST _`execution_cost`_ ROWS _`result_rows`_ SET _`configuration_parameter`_ { TO | = } { _`value`_ | DEFAULT } SET _`configuration_parameter`_ FROM CURRENT RESET _`configuration_parameter`_ RESET ALL Description ----------- `ALTER ROUTINE` changes the definition of a routine, which can be an aggregate function, a normal function, or a procedure. See under [ALTER AGGREGATE](https://www.postgresql.org/docs/current/sql-alteraggregate.html "ALTER AGGREGATE") , [ALTER FUNCTION](https://www.postgresql.org/docs/current/sql-alterfunction.html "ALTER FUNCTION") , and [ALTER PROCEDURE](https://www.postgresql.org/docs/current/sql-alterprocedure.html "ALTER PROCEDURE") for the description of the parameters, more examples, and further details. Examples -------- To rename the routine `foo` for type `integer` to `foobar`: ALTER ROUTINE foo(integer) RENAME TO foobar; This command will work independent of whether `foo` is an aggregate, function, or procedure. Compatibility ------------- This statement is partially compatible with the `ALTER ROUTINE` statement in the SQL standard. See under [ALTER FUNCTION](https://www.postgresql.org/docs/current/sql-alterfunction.html "ALTER FUNCTION") and [ALTER PROCEDURE](https://www.postgresql.org/docs/current/sql-alterprocedure.html "ALTER PROCEDURE") for more details. Allowing routine names to refer to aggregate functions is a PostgreSQL extension. See Also -------- [ALTER AGGREGATE](https://www.postgresql.org/docs/current/sql-alteraggregate.html "ALTER AGGREGATE") , [ALTER FUNCTION](https://www.postgresql.org/docs/current/sql-alterfunction.html "ALTER FUNCTION") , [ALTER PROCEDURE](https://www.postgresql.org/docs/current/sql-alterprocedure.html "ALTER PROCEDURE") , [DROP ROUTINE](https://www.postgresql.org/docs/current/sql-droproutine.html "DROP ROUTINE") Note that there is no `CREATE ROUTINE` command. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-alterrole.html "ALTER ROLE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-alterrule.html "ALTER RULE") | | ALTER ROLE | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | ALTER RULE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-alterroutine.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 15.4. Parallel Safety November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/parallel-safety.html "PostgreSQL 18 - 15.4. Parallel Safety") ([18](https://www.postgresql.org/docs/18/parallel-safety.html "PostgreSQL 18 - 15.4. Parallel Safety") ) / [17](https://www.postgresql.org/docs/17/parallel-safety.html "PostgreSQL 17 - 15.4. Parallel Safety") / [16](https://www.postgresql.org/docs/16/parallel-safety.html "PostgreSQL 16 - 15.4. Parallel Safety") / [15](https://www.postgresql.org/docs/15/parallel-safety.html "PostgreSQL 15 - 15.4. Parallel Safety") / [14](https://www.postgresql.org/docs/14/parallel-safety.html "PostgreSQL 14 - 15.4. Parallel Safety") Development Versions: [devel](https://www.postgresql.org/docs/devel/parallel-safety.html "PostgreSQL devel - 15.4. Parallel Safety") Unsupported versions: [13](https://www.postgresql.org/docs/13/parallel-safety.html "PostgreSQL 13 - 15.4. Parallel Safety") / [12](https://www.postgresql.org/docs/12/parallel-safety.html "PostgreSQL 12 - 15.4. Parallel Safety") / [11](https://www.postgresql.org/docs/11/parallel-safety.html "PostgreSQL 11 - 15.4. Parallel Safety") / [10](https://www.postgresql.org/docs/10/parallel-safety.html "PostgreSQL 10 - 15.4. Parallel Safety") / [9.6](https://www.postgresql.org/docs/9.6/parallel-safety.html "PostgreSQL 9.6 - 15.4. Parallel Safety") | 15.4. Parallel Safety | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/parallel-plans.html "15.3. Parallel Plans") | [Up](https://www.postgresql.org/docs/18/parallel-query.html "Chapter 15. Parallel Query") | Chapter 15. Parallel Query | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/admin.html "Part III. Server Administration") | * * * 15.4. Parallel Safety [#](https://www.postgresql.org/docs/18/parallel-safety.html#PARALLEL-SAFETY) --------------------------------------------------------------------------------------------------- [15.4.1. Parallel Labeling for Functions and Aggregates](https://www.postgresql.org/docs/18/parallel-safety.html#PARALLEL-LABELING) The planner classifies operations involved in a query as either _parallel safe_, _parallel restricted_, or _parallel unsafe_. A parallel safe operation is one that does not conflict with the use of parallel query. A parallel restricted operation is one that cannot be performed in a parallel worker, but that can be performed in the leader while parallel query is in use. Therefore, parallel restricted operations can never occur below a `Gather` or `Gather Merge` node, but can occur elsewhere in a plan that contains such a node. A parallel unsafe operation is one that cannot be performed while parallel query is in use, not even in the leader. When a query contains anything that is parallel unsafe, parallel query is completely disabled for that query. The following operations are always parallel restricted: * Scans of common table expressions (CTEs). * Scans of temporary tables. * Scans of foreign tables, unless the foreign data wrapper has an `IsForeignScanParallelSafe` API that indicates otherwise. * Plan nodes that reference a correlated `SubPlan`. ### 15.4.1. Parallel Labeling for Functions and Aggregates [#](https://www.postgresql.org/docs/18/parallel-safety.html#PARALLEL-LABELING) The planner cannot automatically determine whether a user-defined function or aggregate is parallel safe, parallel restricted, or parallel unsafe, because this would require predicting every operation that the function could possibly perform. In general, this is equivalent to the Halting Problem and therefore impossible. Even for simple functions where it could conceivably be done, we do not try, since this would be expensive and error-prone. Instead, all user-defined functions are assumed to be parallel unsafe unless otherwise marked. When using [CREATE FUNCTION](https://www.postgresql.org/docs/18/sql-createfunction.html "CREATE FUNCTION") or [ALTER FUNCTION](https://www.postgresql.org/docs/18/sql-alterfunction.html "ALTER FUNCTION") , markings can be set by specifying `PARALLEL SAFE`, `PARALLEL RESTRICTED`, or `PARALLEL UNSAFE` as appropriate. When using [CREATE AGGREGATE](https://www.postgresql.org/docs/18/sql-createaggregate.html "CREATE AGGREGATE") , the `PARALLEL` option can be specified with `SAFE`, `RESTRICTED`, or `UNSAFE` as the corresponding value. Functions and aggregates must be marked `PARALLEL UNSAFE` if they write to the database, change the transaction state (other than by using a subtransaction for error recovery), access sequences, or make persistent changes to settings. Similarly, functions must be marked `PARALLEL RESTRICTED` if they access temporary tables, client connection state, cursors, prepared statements, or miscellaneous backend-local state that the system cannot synchronize across workers. For example, `setseed` and `random` are parallel restricted for this last reason. In general, if a function is labeled as being safe when it is restricted or unsafe, or if it is labeled as being restricted when it is in fact unsafe, it may throw errors or produce wrong answers when used in a parallel query. C-language functions could in theory exhibit totally undefined behavior if mislabeled, since there is no way for the system to protect itself against arbitrary C code, but in most likely cases the result will be no worse than for any other function. If in doubt, it is probably best to label functions as `UNSAFE`. If a function executed within a parallel worker acquires locks that are not held by the leader, for example by querying a table not referenced in the query, those locks will be released at worker exit, not end of transaction. If you write a function that does this, and this behavior difference is important to you, mark such functions as `PARALLEL RESTRICTED` to ensure that they execute only in the leader. Note that the query planner does not consider deferring the evaluation of parallel-restricted functions or aggregates involved in the query in order to obtain a superior plan. So, for example, if a `WHERE` clause applied to a particular table is parallel restricted, the query planner will not consider performing a scan of that table in the parallel portion of a plan. In some cases, it would be possible (and perhaps even efficient) to include the scan of that table in the parallel portion of the query and defer the evaluation of the `WHERE` clause so that it happens above the `Gather` node. However, the planner does not do this. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/parallel-plans.html "15.3. Parallel Plans") | [Up](https://www.postgresql.org/docs/18/parallel-query.html "Chapter 15. Parallel Query") | [Next](https://www.postgresql.org/docs/18/admin.html "Part III. Server Administration") | | 15.3. Parallel Plans | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | Part III. Server Administration | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/parallel-safety.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: DROP ROUTINE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-droproutine.html "PostgreSQL 18 - DROP ROUTINE") ([18](https://www.postgresql.org/docs/18/sql-droproutine.html "PostgreSQL 18 - DROP ROUTINE") ) / [17](https://www.postgresql.org/docs/17/sql-droproutine.html "PostgreSQL 17 - DROP ROUTINE") / [16](https://www.postgresql.org/docs/16/sql-droproutine.html "PostgreSQL 16 - DROP ROUTINE") / [15](https://www.postgresql.org/docs/15/sql-droproutine.html "PostgreSQL 15 - DROP ROUTINE") / [14](https://www.postgresql.org/docs/14/sql-droproutine.html "PostgreSQL 14 - DROP ROUTINE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-droproutine.html "PostgreSQL devel - DROP ROUTINE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-droproutine.html "PostgreSQL 13 - DROP ROUTINE") / [12](https://www.postgresql.org/docs/12/sql-droproutine.html "PostgreSQL 12 - DROP ROUTINE") / [11](https://www.postgresql.org/docs/11/sql-droproutine.html "PostgreSQL 11 - DROP ROUTINE") | DROP ROUTINE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-droprole.html "DROP ROLE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-droprule.html "DROP RULE") | * * * DROP ROUTINE ------------ DROP ROUTINE — remove a routine Synopsis -------- DROP ROUTINE \[ IF EXISTS \] _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] \[, ...\] \[ CASCADE | RESTRICT \] Description ----------- `DROP ROUTINE` removes the definition of one or more existing routines. The term “routine” includes aggregate functions, normal functions, and procedures. See under [DROP AGGREGATE](https://www.postgresql.org/docs/18/sql-dropaggregate.html "DROP AGGREGATE") , [DROP FUNCTION](https://www.postgresql.org/docs/18/sql-dropfunction.html "DROP FUNCTION") , and [DROP PROCEDURE](https://www.postgresql.org/docs/18/sql-dropprocedure.html "DROP PROCEDURE") for the description of the parameters, more examples, and further details. Notes ----- The lookup rules used by `DROP ROUTINE` are fundamentally the same as for `DROP PROCEDURE`; in particular, `DROP ROUTINE` shares that command's behavior of considering an argument list that has no _`argmode`_ markers to be possibly using the SQL standard's definition that `OUT` arguments are included in the list. (`DROP AGGREGATE` and `DROP FUNCTION` do not do that.) In some cases where the same name is shared by routines of different kinds, it is possible for `DROP ROUTINE` to fail with an ambiguity error when a more specific command (`DROP FUNCTION`, etc.) would work. Specifying the argument type list more carefully will also resolve such problems. These lookup rules are also used by other commands that act on existing routines, such as `ALTER ROUTINE` and `COMMENT ON ROUTINE`. Examples -------- To drop the routine `foo` for type `integer`: DROP ROUTINE foo(integer); This command will work independent of whether `foo` is an aggregate, function, or procedure. Compatibility ------------- This command conforms to the SQL standard, with these PostgreSQL extensions: * The standard only allows one routine to be dropped per command. * The `IF EXISTS` option is an extension. * The ability to specify argument modes and names is an extension, and the lookup rules differ when modes are given. * User-definable aggregate functions are an extension. See Also -------- [DROP AGGREGATE](https://www.postgresql.org/docs/18/sql-dropaggregate.html "DROP AGGREGATE") , [DROP FUNCTION](https://www.postgresql.org/docs/18/sql-dropfunction.html "DROP FUNCTION") , [DROP PROCEDURE](https://www.postgresql.org/docs/18/sql-dropprocedure.html "DROP PROCEDURE") , [ALTER ROUTINE](https://www.postgresql.org/docs/18/sql-alterroutine.html "ALTER ROUTINE") Note that there is no `CREATE ROUTINE` command. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-droprole.html "DROP ROLE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-droprule.html "DROP RULE") | | DROP ROLE | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | DROP RULE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-droproutine.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 59. Writing a Table Sampling Method November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/tablesample-method.html "PostgreSQL 18 - Chapter 59. Writing a Table Sampling Method") ([18](https://www.postgresql.org/docs/18/tablesample-method.html "PostgreSQL 18 - Chapter 59. Writing a Table Sampling Method") ) / [17](https://www.postgresql.org/docs/17/tablesample-method.html "PostgreSQL 17 - Chapter 59. Writing a Table Sampling Method") / [16](https://www.postgresql.org/docs/16/tablesample-method.html "PostgreSQL 16 - Chapter 59. Writing a Table Sampling Method") / [15](https://www.postgresql.org/docs/15/tablesample-method.html "PostgreSQL 15 - Chapter 59. Writing a Table Sampling Method") / [14](https://www.postgresql.org/docs/14/tablesample-method.html "PostgreSQL 14 - Chapter 59. Writing a Table Sampling Method") Development Versions: [devel](https://www.postgresql.org/docs/devel/tablesample-method.html "PostgreSQL devel - Chapter 59. Writing a Table Sampling Method") Unsupported versions: [13](https://www.postgresql.org/docs/13/tablesample-method.html "PostgreSQL 13 - Chapter 59. Writing a Table Sampling Method") / [12](https://www.postgresql.org/docs/12/tablesample-method.html "PostgreSQL 12 - Chapter 59. Writing a Table Sampling Method") / [11](https://www.postgresql.org/docs/11/tablesample-method.html "PostgreSQL 11 - Chapter 59. Writing a Table Sampling Method") / [10](https://www.postgresql.org/docs/10/tablesample-method.html "PostgreSQL 10 - Chapter 59. Writing a Table Sampling Method") / [9.6](https://www.postgresql.org/docs/9.6/tablesample-method.html "PostgreSQL 9.6 - Chapter 59. Writing a Table Sampling Method") / [9.5](https://www.postgresql.org/docs/9.5/tablesample-method.html "PostgreSQL 9.5 - Chapter 59. Writing a Table Sampling Method") | Chapter 59. Writing a Table Sampling Method | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/fdw-row-locking.html "58.5. Row Locking in Foreign Data Wrappers") | [Up](https://www.postgresql.org/docs/18/internals.html "Part VII. Internals") | Part VII. Internals | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/tablesample-support-functions.html "59.1. Sampling Method Support Functions") | * * * Chapter 59. Writing a Table Sampling Method ------------------------------------------- **Table of Contents** [59.1. Sampling Method Support Functions](https://www.postgresql.org/docs/18/tablesample-support-functions.html) PostgreSQL's implementation of the `TABLESAMPLE` clause supports custom table sampling methods, in addition to the `BERNOULLI` and `SYSTEM` methods that are required by the SQL standard. The sampling method determines which rows of the table will be selected when the `TABLESAMPLE` clause is used. At the SQL level, a table sampling method is represented by a single SQL function, typically implemented in C, having the signature method\_name(internal) RETURNS tsm\_handler The name of the function is the same method name appearing in the `TABLESAMPLE` clause. The `internal` argument is a dummy (always having value zero) that simply serves to prevent this function from being called directly from an SQL command. The result of the function must be a palloc'd struct of type `TsmRoutine`, which contains pointers to support functions for the sampling method. These support functions are plain C functions and are not visible or callable at the SQL level. The support functions are described in [Section 59.1](https://www.postgresql.org/docs/18/tablesample-support-functions.html "59.1. Sampling Method Support Functions") . In addition to function pointers, the `TsmRoutine` struct must provide these additional fields: `List *parameterTypes` This is an OID list containing the data type OIDs of the parameter(s) that will be accepted by the `TABLESAMPLE` clause when this sampling method is used. For example, for the built-in methods, this list contains a single item with value `FLOAT4OID`, which represents the sampling percentage. Custom sampling methods can have more or different parameters. `bool repeatable_across_queries` If `true`, the sampling method can deliver identical samples across successive queries, if the same parameters and `REPEATABLE` seed value are supplied each time and the table contents have not changed. When this is `false`, the `REPEATABLE` clause is not accepted for use with the sampling method. `bool repeatable_across_scans` If `true`, the sampling method can deliver identical samples across successive scans in the same query (assuming unchanging parameters, seed value, and snapshot). When this is `false`, the planner will not select plans that would require scanning the sampled table more than once, since that might result in inconsistent query output. The `TsmRoutine` struct type is declared in `src/include/access/tsmapi.h`, which see for additional details. The table sampling methods included in the standard distribution are good references when trying to write your own. Look into the `src/backend/access/tablesample` subdirectory of the source tree for the built-in sampling methods, and into the `contrib` subdirectory for add-on methods. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/fdw-row-locking.html "58.5. Row Locking in Foreign Data Wrappers") | [Up](https://www.postgresql.org/docs/18/internals.html "Part VII. Internals") | [Next](https://www.postgresql.org/docs/18/tablesample-support-functions.html "59.1. Sampling Method Support Functions") | | 58.5. Row Locking in Foreign Data Wrappers | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 59.1. Sampling Method Support Functions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/tablesample-method.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: ALTER LARGE OBJECT November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alterlargeobject.html "PostgreSQL 18 - ALTER LARGE OBJECT") ([18](https://www.postgresql.org/docs/18/sql-alterlargeobject.html "PostgreSQL 18 - ALTER LARGE OBJECT") ) / [17](https://www.postgresql.org/docs/17/sql-alterlargeobject.html "PostgreSQL 17 - ALTER LARGE OBJECT") / [16](https://www.postgresql.org/docs/16/sql-alterlargeobject.html "PostgreSQL 16 - ALTER LARGE OBJECT") / [15](https://www.postgresql.org/docs/15/sql-alterlargeobject.html "PostgreSQL 15 - ALTER LARGE OBJECT") / [14](https://www.postgresql.org/docs/14/sql-alterlargeobject.html "PostgreSQL 14 - ALTER LARGE OBJECT") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alterlargeobject.html "PostgreSQL devel - ALTER LARGE OBJECT") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alterlargeobject.html "PostgreSQL 13 - ALTER LARGE OBJECT") / [12](https://www.postgresql.org/docs/12/sql-alterlargeobject.html "PostgreSQL 12 - ALTER LARGE OBJECT") / [11](https://www.postgresql.org/docs/11/sql-alterlargeobject.html "PostgreSQL 11 - ALTER LARGE OBJECT") / [10](https://www.postgresql.org/docs/10/sql-alterlargeobject.html "PostgreSQL 10 - ALTER LARGE OBJECT") / [9.6](https://www.postgresql.org/docs/9.6/sql-alterlargeobject.html "PostgreSQL 9.6 - ALTER LARGE OBJECT") / [9.5](https://www.postgresql.org/docs/9.5/sql-alterlargeobject.html "PostgreSQL 9.5 - ALTER LARGE OBJECT") / [9.4](https://www.postgresql.org/docs/9.4/sql-alterlargeobject.html "PostgreSQL 9.4 - ALTER LARGE OBJECT") / [9.3](https://www.postgresql.org/docs/9.3/sql-alterlargeobject.html "PostgreSQL 9.3 - ALTER LARGE OBJECT") / [9.2](https://www.postgresql.org/docs/9.2/sql-alterlargeobject.html "PostgreSQL 9.2 - ALTER LARGE OBJECT") / [9.1](https://www.postgresql.org/docs/9.1/sql-alterlargeobject.html "PostgreSQL 9.1 - ALTER LARGE OBJECT") / [9.0](https://www.postgresql.org/docs/9.0/sql-alterlargeobject.html "PostgreSQL 9.0 - ALTER LARGE OBJECT") | ALTER LARGE OBJECT | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-alterlanguage.html "ALTER LANGUAGE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-altermaterializedview.html "ALTER MATERIALIZED VIEW") | * * * ALTER LARGE OBJECT ------------------ ALTER LARGE OBJECT — change the definition of a large object Synopsis -------- ALTER LARGE OBJECT _`large_object_oid`_ OWNER TO { _`new_owner`_ | CURRENT\_ROLE | CURRENT\_USER | SESSION\_USER } Description ----------- `ALTER LARGE OBJECT` changes the definition of a large object. You must own the large object to use `ALTER LARGE OBJECT`. To alter the owner, you must also be able to `SET ROLE` to the new owning role. (However, a superuser can alter any large object anyway.) Currently, the only functionality is to assign a new owner, so both restrictions always apply. Parameters ---------- _`large_object_oid`_ OID of the large object to be altered _`new_owner`_ The new owner of the large object Compatibility ------------- There is no `ALTER LARGE OBJECT` statement in the SQL standard. See Also -------- [Chapter 33](https://www.postgresql.org/docs/current/largeobjects.html "Chapter 33. Large Objects") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-alterlanguage.html "ALTER LANGUAGE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-altermaterializedview.html "ALTER MATERIALIZED VIEW") | | ALTER LANGUAGE | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | ALTER MATERIALIZED VIEW | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-alterlargeobject.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 26.4. Hot Standby November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/hot-standby.html "PostgreSQL 18 - 26.4. Hot Standby") ([18](https://www.postgresql.org/docs/18/hot-standby.html "PostgreSQL 18 - 26.4. Hot Standby") ) / [17](https://www.postgresql.org/docs/17/hot-standby.html "PostgreSQL 17 - 26.4. Hot Standby") / [16](https://www.postgresql.org/docs/16/hot-standby.html "PostgreSQL 16 - 26.4. Hot Standby") / [15](https://www.postgresql.org/docs/15/hot-standby.html "PostgreSQL 15 - 26.4. Hot Standby") / [14](https://www.postgresql.org/docs/14/hot-standby.html "PostgreSQL 14 - 26.4. Hot Standby") Development Versions: [devel](https://www.postgresql.org/docs/devel/hot-standby.html "PostgreSQL devel - 26.4. Hot Standby") Unsupported versions: [13](https://www.postgresql.org/docs/13/hot-standby.html "PostgreSQL 13 - 26.4. Hot Standby") / [12](https://www.postgresql.org/docs/12/hot-standby.html "PostgreSQL 12 - 26.4. Hot Standby") / [11](https://www.postgresql.org/docs/11/hot-standby.html "PostgreSQL 11 - 26.4. Hot Standby") / [10](https://www.postgresql.org/docs/10/hot-standby.html "PostgreSQL 10 - 26.4. Hot Standby") / [9.6](https://www.postgresql.org/docs/9.6/hot-standby.html "PostgreSQL 9.6 - 26.4. Hot Standby") / [9.5](https://www.postgresql.org/docs/9.5/hot-standby.html "PostgreSQL 9.5 - 26.4. Hot Standby") / [9.4](https://www.postgresql.org/docs/9.4/hot-standby.html "PostgreSQL 9.4 - 26.4. Hot Standby") / [9.3](https://www.postgresql.org/docs/9.3/hot-standby.html "PostgreSQL 9.3 - 26.4. Hot Standby") / [9.2](https://www.postgresql.org/docs/9.2/hot-standby.html "PostgreSQL 9.2 - 26.4. Hot Standby") / [9.1](https://www.postgresql.org/docs/9.1/hot-standby.html "PostgreSQL 9.1 - 26.4. Hot Standby") / [9.0](https://www.postgresql.org/docs/9.0/hot-standby.html "PostgreSQL 9.0 - 26.4. Hot Standby") | 26.4. Hot Standby | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/warm-standby-failover.html "26.3. Failover") | [Up](https://www.postgresql.org/docs/current/high-availability.html "Chapter 26. High Availability, Load Balancing, and Replication") | Chapter 26. High Availability, Load Balancing, and Replication | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/monitoring.html "Chapter 27. Monitoring Database Activity") | * * * 26.4. Hot Standby [#](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY) -------------------------------------------------------------------------------------------- [26.4.1. User's Overview](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-USERS) [26.4.2. Handling Query Conflicts](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CONFLICT) [26.4.3. Administrator's Overview](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-ADMIN) [26.4.4. Hot Standby Parameter Reference](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-PARAMETERS) [26.4.5. Caveats](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CAVEATS) Hot standby is the term used to describe the ability to connect to the server and run read-only queries while the server is in archive recovery or standby mode. This is useful both for replication purposes and for restoring a backup to a desired state with great precision. The term hot standby also refers to the ability of the server to move from recovery through to normal operation while users continue running queries and/or keep their connections open. Running queries in hot standby mode is similar to normal query operation, though there are several usage and administrative differences explained below. ### 26.4.1. User's Overview [#](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-USERS) When the [hot\_standby](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-HOT-STANDBY) parameter is set to true on a standby server, it will begin accepting connections once the recovery has brought the system to a consistent state and be ready for hot standby. All such connections are strictly read-only; not even temporary tables may be written. The data on the standby takes some time to arrive from the primary server so there will be a measurable delay between primary and standby. Running the same query nearly simultaneously on both primary and standby might therefore return differing results. We say that data on the standby is _eventually consistent_ with the primary. Once the commit record for a transaction is replayed on the standby, the changes made by that transaction will be visible to any new snapshots taken on the standby. Snapshots may be taken at the start of each query or at the start of each transaction, depending on the current transaction isolation level. For more details, see [Section 13.2](https://www.postgresql.org/docs/current/transaction-iso.html "13.2. Transaction Isolation") . Transactions started during hot standby may issue the following commands: * Query access: `SELECT`, `COPY TO` * Cursor commands: `DECLARE`, `FETCH`, `CLOSE` * Settings: `SHOW`, `SET`, `RESET` * Transaction management commands: * `BEGIN`, `END`, `ABORT`, `START TRANSACTION` * `SAVEPOINT`, `RELEASE`, `ROLLBACK TO SAVEPOINT` * `EXCEPTION` blocks and other internal subtransactions * `LOCK TABLE`, though only when explicitly in one of these modes: `ACCESS SHARE`, `ROW SHARE` or `ROW EXCLUSIVE`. * Plans and resources: `PREPARE`, `EXECUTE`, `DEALLOCATE`, `DISCARD` * Plugins and extensions: `LOAD` * `UNLISTEN` Transactions started during hot standby will never be assigned a transaction ID and cannot write to the system write-ahead log. Therefore, the following actions will produce error messages: * Data Manipulation Language (DML): `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `COPY FROM`, `TRUNCATE`. Note that there are no allowed actions that result in a trigger being executed during recovery. This restriction applies even to temporary tables, because table rows cannot be read or written without assigning a transaction ID, which is currently not possible in a hot standby environment. * Data Definition Language (DDL): `CREATE`, `DROP`, `ALTER`, `COMMENT`. This restriction applies even to temporary tables, because carrying out these operations would require updating the system catalog tables. * `SELECT ... FOR SHARE | UPDATE`, because row locks cannot be taken without updating the underlying data files. * Rules on `SELECT` statements that generate DML commands. * `LOCK` that explicitly requests a mode higher than `ROW EXCLUSIVE MODE`. * `LOCK` in short default form, since it requests `ACCESS EXCLUSIVE MODE`. * Transaction management commands that explicitly set non-read-only state: * `BEGIN READ WRITE`, `START TRANSACTION READ WRITE` * `SET TRANSACTION READ WRITE`, `SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE` * `SET transaction_read_only = off` * Two-phase commit commands: `PREPARE TRANSACTION`, `COMMIT PREPARED`, `ROLLBACK PREPARED` because even read-only transactions need to write WAL in the prepare phase (the first phase of two phase commit). * Sequence updates: `nextval()`, `setval()` * `LISTEN`, `NOTIFY` In normal operation, “read-only” transactions are allowed to use `LISTEN` and `NOTIFY`, so hot standby sessions operate under slightly tighter restrictions than ordinary read-only sessions. It is possible that some of these restrictions might be loosened in a future release. During hot standby, the parameter `transaction_read_only` is always true and may not be changed. But as long as no attempt is made to modify the database, connections during hot standby will act much like any other database connection. If failover or switchover occurs, the database will switch to normal processing mode. Sessions will remain connected while the server changes mode. Once hot standby finishes, it will be possible to initiate read-write transactions (even from a session begun during hot standby). Users can determine whether hot standby is currently active for their session by issuing `SHOW in_hot_standby`. (In server versions before 14, the `in_hot_standby` parameter did not exist; a workable substitute method for older servers is `SHOW transaction_read_only`.) In addition, a set of functions ([Table 9.98](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-RECOVERY-INFO-TABLE "Table 9.98. Recovery Information Functions") ) allow users to access information about the standby server. These allow you to write programs that are aware of the current state of the database. These can be used to monitor the progress of recovery, or to allow you to write complex programs that restore the database to particular states. ### 26.4.2. Handling Query Conflicts [#](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CONFLICT) The primary and standby servers are in many ways loosely connected. Actions on the primary will have an effect on the standby. As a result, there is potential for negative interactions or conflicts between them. The easiest conflict to understand is performance: if a huge data load is taking place on the primary then this will generate a similar stream of WAL records on the standby, so standby queries may contend for system resources, such as I/O. There are also additional types of conflict that can occur with hot standby. These conflicts are _hard conflicts_ in the sense that queries might need to be canceled and, in some cases, sessions disconnected to resolve them. The user is provided with several ways to handle these conflicts. Conflict cases include: * Access Exclusive locks taken on the primary server, including both explicit `LOCK` commands and various DDL actions, conflict with table accesses in standby queries. * Dropping a tablespace on the primary conflicts with standby queries using that tablespace for temporary work files. * Dropping a database on the primary conflicts with sessions connected to that database on the standby. * Application of a vacuum cleanup record from WAL conflicts with standby transactions whose snapshots can still “see” any of the rows to be removed. * Application of a vacuum cleanup record from WAL conflicts with queries accessing the target page on the standby, whether or not the data to be removed is visible. On the primary server, these cases simply result in waiting; and the user might choose to cancel either of the conflicting actions. However, on the standby there is no choice: the WAL-logged action already occurred on the primary so the standby must not fail to apply it. Furthermore, allowing WAL application to wait indefinitely may be very undesirable, because the standby's state will become increasingly far behind the primary's. Therefore, a mechanism is provided to forcibly cancel standby queries that conflict with to-be-applied WAL records. An example of the problem situation is an administrator on the primary server running `DROP TABLE` on a table that is currently being queried on the standby server. Clearly the standby query cannot continue if the `DROP TABLE` is applied on the standby. If this situation occurred on the primary, the `DROP TABLE` would wait until the other query had finished. But when `DROP TABLE` is run on the primary, the primary doesn't have information about what queries are running on the standby, so it will not wait for any such standby queries. The WAL change records come through to the standby while the standby query is still running, causing a conflict. The standby server must either delay application of the WAL records (and everything after them, too) or else cancel the conflicting query so that the `DROP TABLE` can be applied. When a conflicting query is short, it's typically desirable to allow it to complete by delaying WAL application for a little bit; but a long delay in WAL application is usually not desirable. So the cancel mechanism has parameters, [max\_standby\_archive\_delay](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-STANDBY-ARCHIVE-DELAY) and [max\_standby\_streaming\_delay](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-STANDBY-STREAMING-DELAY) , that define the maximum allowed delay in WAL application. Conflicting queries will be canceled once it has taken longer than the relevant delay setting to apply any newly-received WAL data. There are two parameters so that different delay values can be specified for the case of reading WAL data from an archive (i.e., initial recovery from a base backup or “catching up” a standby server that has fallen far behind) versus reading WAL data via streaming replication. In a standby server that exists primarily for high availability, it's best to set the delay parameters relatively short, so that the server cannot fall far behind the primary due to delays caused by standby queries. However, if the standby server is meant for executing long-running queries, then a high or even infinite delay value may be preferable. Keep in mind however that a long-running query could cause other sessions on the standby server to not see recent changes on the primary, if it delays application of WAL records. Once the delay specified by `max_standby_archive_delay` or `max_standby_streaming_delay` has been exceeded, conflicting queries will be canceled. This usually results just in a cancellation error, although in the case of replaying a `DROP DATABASE` the entire conflicting session will be terminated. Also, if the conflict is over a lock held by an idle transaction, the conflicting session is terminated (this behavior might change in the future). Canceled queries may be retried immediately (after beginning a new transaction, of course). Since query cancellation depends on the nature of the WAL records being replayed, a query that was canceled may well succeed if it is executed again. Keep in mind that the delay parameters are compared to the elapsed time since the WAL data was received by the standby server. Thus, the grace period allowed to any one query on the standby is never more than the delay parameter, and could be considerably less if the standby has already fallen behind as a result of waiting for previous queries to complete, or as a result of being unable to keep up with a heavy update load. The most common reason for conflict between standby queries and WAL replay is “early cleanup”. Normally, PostgreSQL allows cleanup of old row versions when there are no transactions that need to see them to ensure correct visibility of data according to MVCC rules. However, this rule can only be applied for transactions executing on the primary. So it is possible that cleanup on the primary will remove row versions that are still visible to a transaction on the standby. Row version cleanup isn't the only potential cause of conflicts with standby queries. All index-only scans (including those that run on standbys) must use an MVCC snapshot that “agrees” with the visibility map. Conflicts are therefore required whenever `VACUUM` [sets a page as all-visible in the visibility map](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-VISIBILITY-MAP "24.1.4. Updating the Visibility Map") containing one or more rows _not_ visible to all standby queries. So even running `VACUUM` against a table with no updated or deleted rows requiring cleanup might lead to conflicts. Users should be clear that tables that are regularly and heavily updated on the primary server will quickly cause cancellation of longer running queries on the standby. In such cases the setting of a finite value for `max_standby_archive_delay` or `max_standby_streaming_delay` can be considered similar to setting `statement_timeout`. Remedial possibilities exist if the number of standby-query cancellations is found to be unacceptable. The first option is to set the parameter `hot_standby_feedback`, which prevents `VACUUM` from removing recently-dead rows and so cleanup conflicts do not occur. If you do this, you should note that this will delay cleanup of dead rows on the primary, which may result in undesirable table bloat. However, the cleanup situation will be no worse than if the standby queries were running directly on the primary server, and you are still getting the benefit of off-loading execution onto the standby. If standby servers connect and disconnect frequently, you might want to make adjustments to handle the period when `hot_standby_feedback` feedback is not being provided. For example, consider increasing `max_standby_archive_delay` so that queries are not rapidly canceled by conflicts in WAL archive files during disconnected periods. You should also consider increasing `max_standby_streaming_delay` to avoid rapid cancellations by newly-arrived streaming WAL entries after reconnection. The number of query cancels and the reason for them can be viewed using the `pg_stat_database_conflicts` system view on the standby server. The `pg_stat_database` system view also contains summary information. Users can control whether a log message is produced when WAL replay is waiting longer than `deadlock_timeout` for conflicts. This is controlled by the [log\_recovery\_conflict\_waits](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-RECOVERY-CONFLICT-WAITS) parameter. ### 26.4.3. Administrator's Overview [#](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-ADMIN) If `hot_standby` is `on` in `postgresql.conf` (the default value) and there is a [`standby.signal`](https://www.postgresql.org/docs/current/warm-standby.html#FILE-STANDBY-SIGNAL) file present, the server will run in hot standby mode. However, it may take some time for hot standby connections to be allowed, because the server will not accept connections until it has completed sufficient recovery to provide a consistent state against which queries can run. During this period, clients that attempt to connect will be refused with an error message. To confirm the server has come up, either loop trying to connect from the application, or look for these messages in the server logs: LOG: entering standby mode ... then some time later ... LOG: consistent recovery state reached LOG: database system is ready to accept read-only connections Consistency information is recorded once per checkpoint on the primary. It is not possible to enable hot standby when reading WAL written during a period when `wal_level` was not set to `replica` or `logical` on the primary. Even after reaching a consistent state, the recovery snapshot may not be ready for hot standby if both of the following conditions are met, delaying accepting read-only connections. To enable hot standby, long-lived write transactions with more than 64 subtransactions need to be closed on the primary. * A write transaction has more than 64 subtransactions * Very long-lived write transactions If you are running file-based log shipping ("warm standby"), you might need to wait until the next WAL file arrives, which could be as long as the `archive_timeout` setting on the primary. The settings of some parameters determine the size of shared memory for tracking transaction IDs, locks, and prepared transactions. These shared memory structures must be no smaller on a standby than on the primary in order to ensure that the standby does not run out of shared memory during recovery. For example, if the primary had used a prepared transaction but the standby had not allocated any shared memory for tracking prepared transactions, then recovery could not continue until the standby's configuration is changed. The parameters affected are: * `max_connections` * `max_prepared_transactions` * `max_locks_per_transaction` * `max_wal_senders` * `max_worker_processes` The easiest way to ensure this does not become a problem is to have these parameters set on the standbys to values equal to or greater than on the primary. Therefore, if you want to increase these values, you should do so on all standby servers first, before applying the changes to the primary server. Conversely, if you want to decrease these values, you should do so on the primary server first, before applying the changes to all standby servers. Keep in mind that when a standby is promoted, it becomes the new reference for the required parameter settings for the standbys that follow it. Therefore, to avoid this becoming a problem during a switchover or failover, it is recommended to keep these settings the same on all standby servers. The WAL tracks changes to these parameters on the primary. If a hot standby processes WAL that indicates that the current value on the primary is higher than its own value, it will log a warning and pause recovery, for example: WARNING: hot standby is not possible because of insufficient parameter settings DETAIL: max\_connections = 80 is a lower setting than on the primary server, where its value was 100. LOG: recovery has paused DETAIL: If recovery is unpaused, the server will shut down. HINT: You can then restart the server after making the necessary configuration changes. At that point, the settings on the standby need to be updated and the instance restarted before recovery can continue. If the standby is not a hot standby, then when it encounters the incompatible parameter change, it will shut down immediately without pausing, since there is then no value in keeping it up. It is important that the administrator select appropriate settings for [max\_standby\_archive\_delay](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-STANDBY-ARCHIVE-DELAY) and [max\_standby\_streaming\_delay](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-STANDBY-STREAMING-DELAY) . The best choices vary depending on business priorities. For example if the server is primarily tasked as a High Availability server, then you will want low delay settings, perhaps even zero, though that is a very aggressive setting. If the standby server is tasked as an additional server for decision support queries then it might be acceptable to set the maximum delay values to many hours, or even -1 which means wait forever for queries to complete. Transaction status "hint bits" written on the primary are not WAL-logged, so data on the standby will likely re-write the hints again on the standby. Thus, the standby server will still perform disk writes even though all users are read-only; no changes occur to the data values themselves. Users will still write large sort temporary files and re-generate relcache info files, so no part of the database is truly read-only during hot standby mode. Note also that writes to remote databases using dblink module, and other operations outside the database using PL functions will still be possible, even though the transaction is read-only locally. The following types of administration commands are not accepted during recovery mode: * Data Definition Language (DDL): e.g., `CREATE INDEX` * Privilege and Ownership: `GRANT`, `REVOKE`, `REASSIGN` * Maintenance commands: `ANALYZE`, `VACUUM`, `CLUSTER`, `REINDEX` Again, note that some of these commands are actually allowed during "read only" mode transactions on the primary. As a result, you cannot create additional indexes that exist solely on the standby, nor statistics that exist solely on the standby. If these administration commands are needed, they should be executed on the primary, and eventually those changes will propagate to the standby. `pg_cancel_backend()` and `pg_terminate_backend()` will work on user backends, but not the startup process, which performs recovery. `pg_stat_activity` does not show recovering transactions as active. As a result, `pg_prepared_xacts` is always empty during recovery. If you wish to resolve in-doubt prepared transactions, view `pg_prepared_xacts` on the primary and issue commands to resolve transactions there or resolve them after the end of recovery. `pg_locks` will show locks held by backends, as normal. `pg_locks` also shows a virtual transaction managed by the startup process that owns all `AccessExclusiveLocks` held by transactions being replayed by recovery. Note that the startup process does not acquire locks to make database changes, and thus locks other than `AccessExclusiveLocks` do not show in `pg_locks` for the Startup process; they are just presumed to exist. The Nagios plugin check\_pgsql will work, because the simple information it checks for exists. The check\_postgres monitoring script will also work, though some reported values could give different or confusing results. For example, last vacuum time will not be maintained, since no vacuum occurs on the standby. Vacuums running on the primary do still send their changes to the standby. WAL file control commands will not work during recovery, e.g., `pg_backup_start`, `pg_switch_wal` etc. Dynamically loadable modules work, including `pg_stat_statements`. Advisory locks work normally in recovery, including deadlock detection. Note that advisory locks are never WAL logged, so it is impossible for an advisory lock on either the primary or the standby to conflict with WAL replay. Nor is it possible to acquire an advisory lock on the primary and have it initiate a similar advisory lock on the standby. Advisory locks relate only to the server on which they are acquired. Trigger-based replication systems such as Slony, Londiste and Bucardo won't run on the standby at all, though they will run happily on the primary server as long as the changes are not sent to standby servers to be applied. WAL replay is not trigger-based so you cannot relay from the standby to any system that requires additional database writes or relies on the use of triggers. New OIDs cannot be assigned, though some UUID generators may still work as long as they do not rely on writing new status to the database. Currently, temporary table creation is not allowed during read-only transactions, so in some cases existing scripts will not run correctly. This restriction might be relaxed in a later release. This is both an SQL standard compliance issue and a technical issue. `DROP TABLESPACE` can only succeed if the tablespace is empty. Some standby users may be actively using the tablespace via their `temp_tablespaces` parameter. If there are temporary files in the tablespace, all active queries are canceled to ensure that temporary files are removed, so the tablespace can be removed and WAL replay can continue. Running `DROP DATABASE` or `ALTER DATABASE ... SET TABLESPACE` on the primary will generate a WAL entry that will cause all users connected to that database on the standby to be forcibly disconnected. This action occurs immediately, whatever the setting of `max_standby_streaming_delay`. Note that `ALTER DATABASE ... RENAME` does not disconnect users, which in most cases will go unnoticed, though might in some cases cause a program confusion if it depends in some way upon database name. In normal (non-recovery) mode, if you issue `DROP USER` or `DROP ROLE` for a role with login capability while that user is still connected then nothing happens to the connected user — they remain connected. The user cannot reconnect however. This behavior applies in recovery also, so a `DROP USER` on the primary does not disconnect that user on the standby. The cumulative statistics system is active during recovery. All scans, reads, blocks, index usage, etc., will be recorded normally on the standby. However, WAL replay will not increment relation and database specific counters. I.e. replay will not increment `pg_stat_all_tables` columns (like `n_tup_ins`), nor will reads or writes performed by the startup process be tracked in the `pg_statio_` views, nor will associated `pg_stat_database` columns be incremented. Autovacuum is not active during recovery. It will start normally at the end of recovery. The checkpointer process and the background writer process are active during recovery. The checkpointer process will perform restartpoints (similar to checkpoints on the primary) and the background writer process will perform normal block cleaning activities. This can include updates of the hint bit information stored on the standby server. The `CHECKPOINT` command is accepted during recovery, though it performs a restartpoint rather than a new checkpoint. ### 26.4.4. Hot Standby Parameter Reference [#](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-PARAMETERS) Various parameters have been mentioned above in [Section 26.4.2](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CONFLICT "26.4.2. Handling Query Conflicts") and [Section 26.4.3](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-ADMIN "26.4.3. Administrator's Overview") . On the primary, the [wal\_level](https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-WAL-LEVEL) parameter can be used. [max\_standby\_archive\_delay](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-STANDBY-ARCHIVE-DELAY) and [max\_standby\_streaming\_delay](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-STANDBY-STREAMING-DELAY) have no effect if set on the primary. On the standby, parameters [hot\_standby](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-HOT-STANDBY) , [max\_standby\_archive\_delay](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-STANDBY-ARCHIVE-DELAY) and [max\_standby\_streaming\_delay](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-STANDBY-STREAMING-DELAY) can be used. ### 26.4.5. Caveats [#](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CAVEATS) There are several limitations of hot standby. These can and probably will be fixed in future releases: * Full knowledge of running transactions is required before snapshots can be taken. Transactions that use large numbers of subtransactions (currently greater than 64) will delay the start of read-only connections until the completion of the longest running write transaction. If this situation occurs, explanatory messages will be sent to the server log. * Valid starting points for standby queries are generated at each checkpoint on the primary. If the standby is shut down while the primary is in a shutdown state, it might not be possible to re-enter hot standby until the primary is started up, so that it generates further starting points in the WAL logs. This situation isn't a problem in the most common situations where it might happen. Generally, if the primary is shut down and not available anymore, that's likely due to a serious failure that requires the standby being converted to operate as the new primary anyway. And in situations where the primary is being intentionally taken down, coordinating to make sure the standby becomes the new primary smoothly is also standard procedure. * At the end of recovery, `AccessExclusiveLocks` held by prepared transactions will require twice the normal number of lock table entries. If you plan on running either a large number of concurrent prepared transactions that normally take `AccessExclusiveLocks`, or you plan on having one large transaction that takes many `AccessExclusiveLocks`, you are advised to select a larger value of `max_locks_per_transaction`, perhaps as much as twice the value of the parameter on the primary server. You need not consider this at all if your setting of `max_prepared_transactions` is 0. * The Serializable transaction isolation level is not yet available in hot standby. (See [Section 13.2.3](https://www.postgresql.org/docs/current/transaction-iso.html#XACT-SERIALIZABLE "13.2.3. Serializable Isolation Level") and [Section 13.4.1](https://www.postgresql.org/docs/current/applevel-consistency.html#SERIALIZABLE-CONSISTENCY "13.4.1. Enforcing Consistency with Serializable Transactions") for details.) An attempt to set a transaction to the serializable isolation level in hot standby mode will generate an error. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/warm-standby-failover.html "26.3. Failover") | [Up](https://www.postgresql.org/docs/current/high-availability.html "Chapter 26. High Availability, Load Balancing, and Replication") | [Next](https://www.postgresql.org/docs/current/monitoring.html "Chapter 27. Monitoring Database Activity") | | 26.3. Failover | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Chapter 27. Monitoring Database Activity | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/hot-standby.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 29.2. Subscription November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/logical-replication-subscription.html "PostgreSQL 18 - 29.2. Subscription") ([18](https://www.postgresql.org/docs/18/logical-replication-subscription.html "PostgreSQL 18 - 29.2. Subscription") ) / [17](https://www.postgresql.org/docs/17/logical-replication-subscription.html "PostgreSQL 17 - 29.2. Subscription") / [16](https://www.postgresql.org/docs/16/logical-replication-subscription.html "PostgreSQL 16 - 29.2. Subscription") / [15](https://www.postgresql.org/docs/15/logical-replication-subscription.html "PostgreSQL 15 - 29.2. Subscription") / [14](https://www.postgresql.org/docs/14/logical-replication-subscription.html "PostgreSQL 14 - 29.2. Subscription") Development Versions: [devel](https://www.postgresql.org/docs/devel/logical-replication-subscription.html "PostgreSQL devel - 29.2. Subscription") Unsupported versions: [13](https://www.postgresql.org/docs/13/logical-replication-subscription.html "PostgreSQL 13 - 29.2. Subscription") / [12](https://www.postgresql.org/docs/12/logical-replication-subscription.html "PostgreSQL 12 - 29.2. Subscription") / [11](https://www.postgresql.org/docs/11/logical-replication-subscription.html "PostgreSQL 11 - 29.2. Subscription") / [10](https://www.postgresql.org/docs/10/logical-replication-subscription.html "PostgreSQL 10 - 29.2. Subscription") | 29.2. Subscription | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/logical-replication-publication.html "29.1. Publication") | [Up](https://www.postgresql.org/docs/18/logical-replication.html "Chapter 29. Logical Replication") | Chapter 29. Logical Replication | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/logical-replication-failover.html "29.3. Logical Replication Failover") | * * * 29.2. Subscription [#](https://www.postgresql.org/docs/18/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION) ---------------------------------------------------------------------------------------------------------------------------------- [29.2.1. Replication Slot Management](https://www.postgresql.org/docs/18/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-SLOT) [29.2.2. Examples: Set Up Logical Replication](https://www.postgresql.org/docs/18/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-EXAMPLES) [29.2.3. Examples: Deferred Replication Slot Creation](https://www.postgresql.org/docs/18/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-EXAMPLES-DEFERRED-SLOT) A _subscription_ is the downstream side of logical replication. The node where a subscription is defined is referred to as the _subscriber_. A subscription defines the connection to another database and set of publications (one or more) to which it wants to subscribe. The subscriber database behaves in the same way as any other PostgreSQL instance and can be used as a publisher for other databases by defining its own publications. A subscriber node may have multiple subscriptions if desired. It is possible to define multiple subscriptions between a single publisher-subscriber pair, in which case care must be taken to ensure that the subscribed publication objects don't overlap. Each subscription will receive changes via one replication slot (see [Section 26.2.6](https://www.postgresql.org/docs/18/warm-standby.html#STREAMING-REPLICATION-SLOTS "26.2.6. Replication Slots") ). Additional replication slots may be required for the initial data synchronization of pre-existing table data and those will be dropped at the end of data synchronization. A logical replication subscription can be a standby for synchronous replication (see [Section 26.2.8](https://www.postgresql.org/docs/18/warm-standby.html#SYNCHRONOUS-REPLICATION "26.2.8. Synchronous Replication") ). The standby name is by default the subscription name. An alternative name can be specified as `application_name` in the connection information of the subscription. Subscriptions are dumped by `pg_dump` if the current user is a superuser. Otherwise a warning is written and subscriptions are skipped, because non-superusers cannot read all subscription information from the `pg_subscription` catalog. The subscription is added using [`CREATE SUBSCRIPTION`](https://www.postgresql.org/docs/18/sql-createsubscription.html "CREATE SUBSCRIPTION") and can be stopped/resumed at any time using the [`ALTER SUBSCRIPTION`](https://www.postgresql.org/docs/18/sql-altersubscription.html "ALTER SUBSCRIPTION") command and removed using [`DROP SUBSCRIPTION`](https://www.postgresql.org/docs/18/sql-dropsubscription.html "DROP SUBSCRIPTION") . When a subscription is dropped and recreated, the synchronization information is lost. This means that the data has to be resynchronized afterwards. The schema definitions are not replicated, and the published tables must exist on the subscriber. Only regular tables may be the target of replication. For example, you can't replicate to a view. The tables are matched between the publisher and the subscriber using the fully qualified table name. Replication to differently-named tables on the subscriber is not supported. Columns of a table are also matched by name. The order of columns in the subscriber table does not need to match that of the publisher. The data types of the columns do not need to match, as long as the text representation of the data can be converted to the target type. For example, you can replicate from a column of type `integer` to a column of type `bigint`. The target table can also have additional columns not provided by the published table. Any such columns will be filled with the default value as specified in the definition of the target table. However, logical replication in binary format is more restrictive. See the [`binary`](https://www.postgresql.org/docs/18/sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-BINARY) option of `CREATE SUBSCRIPTION` for details. ### 29.2.1. Replication Slot Management [#](https://www.postgresql.org/docs/18/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-SLOT) As mentioned earlier, each (active) subscription receives changes from a replication slot on the remote (publishing) side. Additional table synchronization slots are normally transient, created internally to perform initial table synchronization and dropped automatically when they are no longer needed. These table synchronization slots have generated names: “`pg_%u_sync_%u_%llu`” (parameters: Subscription _`oid`_, Table _`relid`_, system identifier _`sysid`_) Normally, the remote replication slot is created automatically when the subscription is created using [`CREATE SUBSCRIPTION`](https://www.postgresql.org/docs/18/sql-createsubscription.html "CREATE SUBSCRIPTION") and it is dropped automatically when the subscription is dropped using [`DROP SUBSCRIPTION`](https://www.postgresql.org/docs/18/sql-dropsubscription.html "DROP SUBSCRIPTION") . In some situations, however, it can be useful or necessary to manipulate the subscription and the underlying replication slot separately. Here are some scenarios: * When creating a subscription, the replication slot already exists. In that case, the subscription can be created using the `create_slot = false` option to associate with the existing slot. * When creating a subscription, the remote host is not reachable or in an unclear state. In that case, the subscription can be created using the `connect = false` option. The remote host will then not be contacted at all. This is what pg\_dump uses. The remote replication slot will then have to be created manually before the subscription can be activated. * When dropping a subscription, the replication slot should be kept. This could be useful when the subscriber database is being moved to a different host and will be activated from there. In that case, disassociate the slot from the subscription using [`ALTER SUBSCRIPTION`](https://www.postgresql.org/docs/18/sql-altersubscription.html "ALTER SUBSCRIPTION") before attempting to drop the subscription. * When dropping a subscription, the remote host is not reachable. In that case, disassociate the slot from the subscription using `ALTER SUBSCRIPTION` before attempting to drop the subscription. If the remote database instance no longer exists, no further action is then necessary. If, however, the remote database instance is just unreachable, the replication slot (and any still remaining table synchronization slots) should then be dropped manually; otherwise it/they would continue to reserve WAL and might eventually cause the disk to fill up. Such cases should be carefully investigated. ### 29.2.2. Examples: Set Up Logical Replication [#](https://www.postgresql.org/docs/18/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-EXAMPLES) Create some test tables on the publisher. /\* pub # \*/ CREATE TABLE t1(a int, b text, PRIMARY KEY(a)); /\* pub # \*/ CREATE TABLE t2(c int, d text, PRIMARY KEY(c)); /\* pub # \*/ CREATE TABLE t3(e int, f text, PRIMARY KEY(e)); Create the same tables on the subscriber. /\* sub # \*/ CREATE TABLE t1(a int, b text, PRIMARY KEY(a)); /\* sub # \*/ CREATE TABLE t2(c int, d text, PRIMARY KEY(c)); /\* sub # \*/ CREATE TABLE t3(e int, f text, PRIMARY KEY(e)); Insert data to the tables at the publisher side. /\* pub # \*/ INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three'); /\* pub # \*/ INSERT INTO t2 VALUES (1, 'A'), (2, 'B'), (3, 'C'); /\* pub # \*/ INSERT INTO t3 VALUES (1, 'i'), (2, 'ii'), (3, 'iii'); Create publications for the tables. The publications `pub2` and `pub3a` disallow some [`publish`](https://www.postgresql.org/docs/18/sql-createpublication.html#SQL-CREATEPUBLICATION-PARAMS-WITH-PUBLISH) operations. The publication `pub3b` has a row filter (see [Section 29.4](https://www.postgresql.org/docs/18/logical-replication-row-filter.html "29.4. Row Filters") ). /\* pub # \*/ CREATE PUBLICATION pub1 FOR TABLE t1; /\* pub # \*/ CREATE PUBLICATION pub2 FOR TABLE t2 WITH (publish = 'truncate'); /\* pub # \*/ CREATE PUBLICATION pub3a FOR TABLE t3 WITH (publish = 'truncate'); /\* pub # \*/ CREATE PUBLICATION pub3b FOR TABLE t3 WHERE (e > 5); Create subscriptions for the publications. The subscription `sub3` subscribes to both `pub3a` and `pub3b`. All subscriptions will copy initial data by default. /\* sub # \*/ CREATE SUBSCRIPTION sub1 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub application\_name=sub1' /\* sub - \*/ PUBLICATION pub1; /\* sub # \*/ CREATE SUBSCRIPTION sub2 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub application\_name=sub2' /\* sub - \*/ PUBLICATION pub2; /\* sub # \*/ CREATE SUBSCRIPTION sub3 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub application\_name=sub3' /\* sub - \*/ PUBLICATION pub3a, pub3b; Observe that initial table data is copied, regardless of the `publish` operation of the publication. /\* sub # \*/ SELECT \* FROM t1; a | b ---+------- 1 | one 2 | two 3 | three (3 rows) /\* sub # \*/ SELECT \* FROM t2; c | d ---+--- 1 | A 2 | B 3 | C (3 rows) Furthermore, because the initial data copy ignores the `publish` operation, and because publication `pub3a` has no row filter, it means the copied table `t3` contains all rows even when they do not match the row filter of publication `pub3b`. /\* sub # \*/ SELECT \* FROM t3; e | f ---+----- 1 | i 2 | ii 3 | iii (3 rows) Insert more data to the tables at the publisher side. /\* pub # \*/ INSERT INTO t1 VALUES (4, 'four'), (5, 'five'), (6, 'six'); /\* pub # \*/ INSERT INTO t2 VALUES (4, 'D'), (5, 'E'), (6, 'F'); /\* pub # \*/ INSERT INTO t3 VALUES (4, 'iv'), (5, 'v'), (6, 'vi'); Now the publisher side data looks like: /\* pub # \*/ SELECT \* FROM t1; a | b ---+------- 1 | one 2 | two 3 | three 4 | four 5 | five 6 | six (6 rows) /\* pub # \*/ SELECT \* FROM t2; c | d ---+--- 1 | A 2 | B 3 | C 4 | D 5 | E 6 | F (6 rows) /\* pub # \*/ SELECT \* FROM t3; e | f ---+----- 1 | i 2 | ii 3 | iii 4 | iv 5 | v 6 | vi (6 rows) Observe that during normal replication the appropriate `publish` operations are used. This means publications `pub2` and `pub3a` will not replicate the `INSERT`. Also, publication `pub3b` will only replicate data that matches the row filter of `pub3b`. Now the subscriber side data looks like: /\* sub # \*/ SELECT \* FROM t1; a | b ---+------- 1 | one 2 | two 3 | three 4 | four 5 | five 6 | six (6 rows) /\* sub # \*/ SELECT \* FROM t2; c | d ---+--- 1 | A 2 | B 3 | C (3 rows) /\* sub # \*/ SELECT \* FROM t3; e | f ---+----- 1 | i 2 | ii 3 | iii 6 | vi (4 rows) ### 29.2.3. Examples: Deferred Replication Slot Creation [#](https://www.postgresql.org/docs/18/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-EXAMPLES-DEFERRED-SLOT) There are some cases (e.g. [Section 29.2.1](https://www.postgresql.org/docs/18/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-SLOT "29.2.1. Replication Slot Management") ) where, if the remote replication slot was not created automatically, the user must create it manually before the subscription can be activated. The steps to create the slot and activate the subscription are shown in the following examples. These examples specify the standard logical decoding output plugin (`pgoutput`), which is what the built-in logical replication uses. First, create a publication for the examples to use. /\* pub # \*/ CREATE PUBLICATION pub1 FOR ALL TABLES; Example 1: Where the subscription says `connect = false` * Create the subscription. /\* sub # \*/ CREATE SUBSCRIPTION sub1 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub' /\* sub - \*/ PUBLICATION pub1 /\* sub - \*/ WITH (connect=false); WARNING: subscription was created, but is not connected HINT: To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription. * On the publisher, manually create a slot. Because the name was not specified during `CREATE SUBSCRIPTION`, the name of the slot to create is same as the subscription name, e.g. "sub1". /\* pub # \*/ SELECT \* FROM pg\_create\_logical\_replication\_slot('sub1', 'pgoutput'); slot\_name | lsn -----------+----------- sub1 | 0/19404D0 (1 row) * On the subscriber, complete the activation of the subscription. After this the tables of `pub1` will start replicating. /\* sub # \*/ ALTER SUBSCRIPTION sub1 ENABLE; /\* sub # \*/ ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; Example 2: Where the subscription says `connect = false`, but also specifies the [`slot_name`](https://www.postgresql.org/docs/18/sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-SLOT-NAME) option. * Create the subscription. /\* sub # \*/ CREATE SUBSCRIPTION sub1 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub' /\* sub - \*/ PUBLICATION pub1 /\* sub - \*/ WITH (connect=false, slot\_name='myslot'); WARNING: subscription was created, but is not connected HINT: To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription. * On the publisher, manually create a slot using the same name that was specified during `CREATE SUBSCRIPTION`, e.g. "myslot". /\* pub # \*/ SELECT \* FROM pg\_create\_logical\_replication\_slot('myslot', 'pgoutput'); slot\_name | lsn -----------+----------- myslot | 0/19059A0 (1 row) * On the subscriber, the remaining subscription activation steps are the same as before. /\* sub # \*/ ALTER SUBSCRIPTION sub1 ENABLE; /\* sub # \*/ ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; Example 3: Where the subscription specifies `slot_name = NONE` * Create the subscription. When `slot_name = NONE` then `enabled = false`, and `create_slot = false` are also needed. /\* sub # \*/ CREATE SUBSCRIPTION sub1 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub' /\* sub - \*/ PUBLICATION pub1 /\* sub - \*/ WITH (slot\_name=NONE, enabled=false, create\_slot=false); * On the publisher, manually create a slot using any name, e.g. "myslot". /\* pub # \*/ SELECT \* FROM pg\_create\_logical\_replication\_slot('myslot', 'pgoutput'); slot\_name | lsn -----------+----------- myslot | 0/1905930 (1 row) * On the subscriber, associate the subscription with the slot name just created. /\* sub # \*/ ALTER SUBSCRIPTION sub1 SET (slot\_name='myslot'); * The remaining subscription activation steps are same as before. /\* sub # \*/ ALTER SUBSCRIPTION sub1 ENABLE; /\* sub # \*/ ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/logical-replication-publication.html "29.1. Publication") | [Up](https://www.postgresql.org/docs/18/logical-replication.html "Chapter 29. Logical Replication") | [Next](https://www.postgresql.org/docs/18/logical-replication-failover.html "29.3. Logical Replication Failover") | | 29.1. Publication | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 29.3. Logical Replication Failover | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/logical-replication-subscription.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: DROP ROUTINE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-droproutine.html "PostgreSQL 18 - DROP ROUTINE") ([18](https://www.postgresql.org/docs/18/sql-droproutine.html "PostgreSQL 18 - DROP ROUTINE") ) / [17](https://www.postgresql.org/docs/17/sql-droproutine.html "PostgreSQL 17 - DROP ROUTINE") / [16](https://www.postgresql.org/docs/16/sql-droproutine.html "PostgreSQL 16 - DROP ROUTINE") / [15](https://www.postgresql.org/docs/15/sql-droproutine.html "PostgreSQL 15 - DROP ROUTINE") / [14](https://www.postgresql.org/docs/14/sql-droproutine.html "PostgreSQL 14 - DROP ROUTINE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-droproutine.html "PostgreSQL devel - DROP ROUTINE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-droproutine.html "PostgreSQL 13 - DROP ROUTINE") / [12](https://www.postgresql.org/docs/12/sql-droproutine.html "PostgreSQL 12 - DROP ROUTINE") / [11](https://www.postgresql.org/docs/11/sql-droproutine.html "PostgreSQL 11 - DROP ROUTINE") | DROP ROUTINE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-droprole.html "DROP ROLE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-droprule.html "DROP RULE") | * * * DROP ROUTINE ------------ DROP ROUTINE — remove a routine Synopsis -------- DROP ROUTINE \[ IF EXISTS \] _`name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] \[, ...\] \[ CASCADE | RESTRICT \] Description ----------- `DROP ROUTINE` removes the definition of one or more existing routines. The term “routine” includes aggregate functions, normal functions, and procedures. See under [DROP AGGREGATE](https://www.postgresql.org/docs/current/sql-dropaggregate.html "DROP AGGREGATE") , [DROP FUNCTION](https://www.postgresql.org/docs/current/sql-dropfunction.html "DROP FUNCTION") , and [DROP PROCEDURE](https://www.postgresql.org/docs/current/sql-dropprocedure.html "DROP PROCEDURE") for the description of the parameters, more examples, and further details. Notes ----- The lookup rules used by `DROP ROUTINE` are fundamentally the same as for `DROP PROCEDURE`; in particular, `DROP ROUTINE` shares that command's behavior of considering an argument list that has no _`argmode`_ markers to be possibly using the SQL standard's definition that `OUT` arguments are included in the list. (`DROP AGGREGATE` and `DROP FUNCTION` do not do that.) In some cases where the same name is shared by routines of different kinds, it is possible for `DROP ROUTINE` to fail with an ambiguity error when a more specific command (`DROP FUNCTION`, etc.) would work. Specifying the argument type list more carefully will also resolve such problems. These lookup rules are also used by other commands that act on existing routines, such as `ALTER ROUTINE` and `COMMENT ON ROUTINE`. Examples -------- To drop the routine `foo` for type `integer`: DROP ROUTINE foo(integer); This command will work independent of whether `foo` is an aggregate, function, or procedure. Compatibility ------------- This command conforms to the SQL standard, with these PostgreSQL extensions: * The standard only allows one routine to be dropped per command. * The `IF EXISTS` option is an extension. * The ability to specify argument modes and names is an extension, and the lookup rules differ when modes are given. * User-definable aggregate functions are an extension. See Also -------- [DROP AGGREGATE](https://www.postgresql.org/docs/current/sql-dropaggregate.html "DROP AGGREGATE") , [DROP FUNCTION](https://www.postgresql.org/docs/current/sql-dropfunction.html "DROP FUNCTION") , [DROP PROCEDURE](https://www.postgresql.org/docs/current/sql-dropprocedure.html "DROP PROCEDURE") , [ALTER ROUTINE](https://www.postgresql.org/docs/current/sql-alterroutine.html "ALTER ROUTINE") Note that there is no `CREATE ROUTINE` command. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-droprole.html "DROP ROLE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-droprule.html "DROP RULE") | | DROP ROLE | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | DROP RULE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-droproutine.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 59. Writing a Table Sampling Method November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/tablesample-method.html "PostgreSQL 18 - Chapter 59. Writing a Table Sampling Method") ([18](https://www.postgresql.org/docs/18/tablesample-method.html "PostgreSQL 18 - Chapter 59. Writing a Table Sampling Method") ) / [17](https://www.postgresql.org/docs/17/tablesample-method.html "PostgreSQL 17 - Chapter 59. Writing a Table Sampling Method") / [16](https://www.postgresql.org/docs/16/tablesample-method.html "PostgreSQL 16 - Chapter 59. Writing a Table Sampling Method") / [15](https://www.postgresql.org/docs/15/tablesample-method.html "PostgreSQL 15 - Chapter 59. Writing a Table Sampling Method") / [14](https://www.postgresql.org/docs/14/tablesample-method.html "PostgreSQL 14 - Chapter 59. Writing a Table Sampling Method") Development Versions: [devel](https://www.postgresql.org/docs/devel/tablesample-method.html "PostgreSQL devel - Chapter 59. Writing a Table Sampling Method") Unsupported versions: [13](https://www.postgresql.org/docs/13/tablesample-method.html "PostgreSQL 13 - Chapter 59. Writing a Table Sampling Method") / [12](https://www.postgresql.org/docs/12/tablesample-method.html "PostgreSQL 12 - Chapter 59. Writing a Table Sampling Method") / [11](https://www.postgresql.org/docs/11/tablesample-method.html "PostgreSQL 11 - Chapter 59. Writing a Table Sampling Method") / [10](https://www.postgresql.org/docs/10/tablesample-method.html "PostgreSQL 10 - Chapter 59. Writing a Table Sampling Method") / [9.6](https://www.postgresql.org/docs/9.6/tablesample-method.html "PostgreSQL 9.6 - Chapter 59. Writing a Table Sampling Method") / [9.5](https://www.postgresql.org/docs/9.5/tablesample-method.html "PostgreSQL 9.5 - Chapter 59. Writing a Table Sampling Method") | Chapter 59. Writing a Table Sampling Method | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/fdw-row-locking.html "58.5. Row Locking in Foreign Data Wrappers") | [Up](https://www.postgresql.org/docs/current/internals.html "Part VII. Internals") | Part VII. Internals | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/tablesample-support-functions.html "59.1. Sampling Method Support Functions") | * * * Chapter 59. Writing a Table Sampling Method ------------------------------------------- **Table of Contents** [59.1. Sampling Method Support Functions](https://www.postgresql.org/docs/current/tablesample-support-functions.html) PostgreSQL's implementation of the `TABLESAMPLE` clause supports custom table sampling methods, in addition to the `BERNOULLI` and `SYSTEM` methods that are required by the SQL standard. The sampling method determines which rows of the table will be selected when the `TABLESAMPLE` clause is used. At the SQL level, a table sampling method is represented by a single SQL function, typically implemented in C, having the signature method\_name(internal) RETURNS tsm\_handler The name of the function is the same method name appearing in the `TABLESAMPLE` clause. The `internal` argument is a dummy (always having value zero) that simply serves to prevent this function from being called directly from an SQL command. The result of the function must be a palloc'd struct of type `TsmRoutine`, which contains pointers to support functions for the sampling method. These support functions are plain C functions and are not visible or callable at the SQL level. The support functions are described in [Section 59.1](https://www.postgresql.org/docs/current/tablesample-support-functions.html "59.1. Sampling Method Support Functions") . In addition to function pointers, the `TsmRoutine` struct must provide these additional fields: `List *parameterTypes` This is an OID list containing the data type OIDs of the parameter(s) that will be accepted by the `TABLESAMPLE` clause when this sampling method is used. For example, for the built-in methods, this list contains a single item with value `FLOAT4OID`, which represents the sampling percentage. Custom sampling methods can have more or different parameters. `bool repeatable_across_queries` If `true`, the sampling method can deliver identical samples across successive queries, if the same parameters and `REPEATABLE` seed value are supplied each time and the table contents have not changed. When this is `false`, the `REPEATABLE` clause is not accepted for use with the sampling method. `bool repeatable_across_scans` If `true`, the sampling method can deliver identical samples across successive scans in the same query (assuming unchanging parameters, seed value, and snapshot). When this is `false`, the planner will not select plans that would require scanning the sampled table more than once, since that might result in inconsistent query output. The `TsmRoutine` struct type is declared in `src/include/access/tsmapi.h`, which see for additional details. The table sampling methods included in the standard distribution are good references when trying to write your own. Look into the `src/backend/access/tablesample` subdirectory of the source tree for the built-in sampling methods, and into the `contrib` subdirectory for add-on methods. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/fdw-row-locking.html "58.5. Row Locking in Foreign Data Wrappers") | [Up](https://www.postgresql.org/docs/current/internals.html "Part VII. Internals") | [Next](https://www.postgresql.org/docs/current/tablesample-support-functions.html "59.1. Sampling Method Support Functions") | | 58.5. Row Locking in Foreign Data Wrappers | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 59.1. Sampling Method Support Functions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/tablesample-method.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 29.2. Subscription November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/logical-replication-subscription.html "PostgreSQL 18 - 29.2. Subscription") ([18](https://www.postgresql.org/docs/18/logical-replication-subscription.html "PostgreSQL 18 - 29.2. Subscription") ) / [17](https://www.postgresql.org/docs/17/logical-replication-subscription.html "PostgreSQL 17 - 29.2. Subscription") / [16](https://www.postgresql.org/docs/16/logical-replication-subscription.html "PostgreSQL 16 - 29.2. Subscription") / [15](https://www.postgresql.org/docs/15/logical-replication-subscription.html "PostgreSQL 15 - 29.2. Subscription") / [14](https://www.postgresql.org/docs/14/logical-replication-subscription.html "PostgreSQL 14 - 29.2. Subscription") Development Versions: [devel](https://www.postgresql.org/docs/devel/logical-replication-subscription.html "PostgreSQL devel - 29.2. Subscription") Unsupported versions: [13](https://www.postgresql.org/docs/13/logical-replication-subscription.html "PostgreSQL 13 - 29.2. Subscription") / [12](https://www.postgresql.org/docs/12/logical-replication-subscription.html "PostgreSQL 12 - 29.2. Subscription") / [11](https://www.postgresql.org/docs/11/logical-replication-subscription.html "PostgreSQL 11 - 29.2. Subscription") / [10](https://www.postgresql.org/docs/10/logical-replication-subscription.html "PostgreSQL 10 - 29.2. Subscription") | 29.2. Subscription | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/logical-replication-publication.html "29.1. Publication") | [Up](https://www.postgresql.org/docs/current/logical-replication.html "Chapter 29. Logical Replication") | Chapter 29. Logical Replication | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/logical-replication-failover.html "29.3. Logical Replication Failover") | * * * 29.2. Subscription [#](https://www.postgresql.org/docs/current/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION) --------------------------------------------------------------------------------------------------------------------------------------- [29.2.1. Replication Slot Management](https://www.postgresql.org/docs/current/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-SLOT) [29.2.2. Examples: Set Up Logical Replication](https://www.postgresql.org/docs/current/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-EXAMPLES) [29.2.3. Examples: Deferred Replication Slot Creation](https://www.postgresql.org/docs/current/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-EXAMPLES-DEFERRED-SLOT) A _subscription_ is the downstream side of logical replication. The node where a subscription is defined is referred to as the _subscriber_. A subscription defines the connection to another database and set of publications (one or more) to which it wants to subscribe. The subscriber database behaves in the same way as any other PostgreSQL instance and can be used as a publisher for other databases by defining its own publications. A subscriber node may have multiple subscriptions if desired. It is possible to define multiple subscriptions between a single publisher-subscriber pair, in which case care must be taken to ensure that the subscribed publication objects don't overlap. Each subscription will receive changes via one replication slot (see [Section 26.2.6](https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION-SLOTS "26.2.6. Replication Slots") ). Additional replication slots may be required for the initial data synchronization of pre-existing table data and those will be dropped at the end of data synchronization. A logical replication subscription can be a standby for synchronous replication (see [Section 26.2.8](https://www.postgresql.org/docs/current/warm-standby.html#SYNCHRONOUS-REPLICATION "26.2.8. Synchronous Replication") ). The standby name is by default the subscription name. An alternative name can be specified as `application_name` in the connection information of the subscription. Subscriptions are dumped by `pg_dump` if the current user is a superuser. Otherwise a warning is written and subscriptions are skipped, because non-superusers cannot read all subscription information from the `pg_subscription` catalog. The subscription is added using [`CREATE SUBSCRIPTION`](https://www.postgresql.org/docs/current/sql-createsubscription.html "CREATE SUBSCRIPTION") and can be stopped/resumed at any time using the [`ALTER SUBSCRIPTION`](https://www.postgresql.org/docs/current/sql-altersubscription.html "ALTER SUBSCRIPTION") command and removed using [`DROP SUBSCRIPTION`](https://www.postgresql.org/docs/current/sql-dropsubscription.html "DROP SUBSCRIPTION") . When a subscription is dropped and recreated, the synchronization information is lost. This means that the data has to be resynchronized afterwards. The schema definitions are not replicated, and the published tables must exist on the subscriber. Only regular tables may be the target of replication. For example, you can't replicate to a view. The tables are matched between the publisher and the subscriber using the fully qualified table name. Replication to differently-named tables on the subscriber is not supported. Columns of a table are also matched by name. The order of columns in the subscriber table does not need to match that of the publisher. The data types of the columns do not need to match, as long as the text representation of the data can be converted to the target type. For example, you can replicate from a column of type `integer` to a column of type `bigint`. The target table can also have additional columns not provided by the published table. Any such columns will be filled with the default value as specified in the definition of the target table. However, logical replication in binary format is more restrictive. See the [`binary`](https://www.postgresql.org/docs/current/sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-BINARY) option of `CREATE SUBSCRIPTION` for details. ### 29.2.1. Replication Slot Management [#](https://www.postgresql.org/docs/current/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-SLOT) As mentioned earlier, each (active) subscription receives changes from a replication slot on the remote (publishing) side. Additional table synchronization slots are normally transient, created internally to perform initial table synchronization and dropped automatically when they are no longer needed. These table synchronization slots have generated names: “`pg_%u_sync_%u_%llu`” (parameters: Subscription _`oid`_, Table _`relid`_, system identifier _`sysid`_) Normally, the remote replication slot is created automatically when the subscription is created using [`CREATE SUBSCRIPTION`](https://www.postgresql.org/docs/current/sql-createsubscription.html "CREATE SUBSCRIPTION") and it is dropped automatically when the subscription is dropped using [`DROP SUBSCRIPTION`](https://www.postgresql.org/docs/current/sql-dropsubscription.html "DROP SUBSCRIPTION") . In some situations, however, it can be useful or necessary to manipulate the subscription and the underlying replication slot separately. Here are some scenarios: * When creating a subscription, the replication slot already exists. In that case, the subscription can be created using the `create_slot = false` option to associate with the existing slot. * When creating a subscription, the remote host is not reachable or in an unclear state. In that case, the subscription can be created using the `connect = false` option. The remote host will then not be contacted at all. This is what pg\_dump uses. The remote replication slot will then have to be created manually before the subscription can be activated. * When dropping a subscription, the replication slot should be kept. This could be useful when the subscriber database is being moved to a different host and will be activated from there. In that case, disassociate the slot from the subscription using [`ALTER SUBSCRIPTION`](https://www.postgresql.org/docs/current/sql-altersubscription.html "ALTER SUBSCRIPTION") before attempting to drop the subscription. * When dropping a subscription, the remote host is not reachable. In that case, disassociate the slot from the subscription using `ALTER SUBSCRIPTION` before attempting to drop the subscription. If the remote database instance no longer exists, no further action is then necessary. If, however, the remote database instance is just unreachable, the replication slot (and any still remaining table synchronization slots) should then be dropped manually; otherwise it/they would continue to reserve WAL and might eventually cause the disk to fill up. Such cases should be carefully investigated. ### 29.2.2. Examples: Set Up Logical Replication [#](https://www.postgresql.org/docs/current/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-EXAMPLES) Create some test tables on the publisher. /\* pub # \*/ CREATE TABLE t1(a int, b text, PRIMARY KEY(a)); /\* pub # \*/ CREATE TABLE t2(c int, d text, PRIMARY KEY(c)); /\* pub # \*/ CREATE TABLE t3(e int, f text, PRIMARY KEY(e)); Create the same tables on the subscriber. /\* sub # \*/ CREATE TABLE t1(a int, b text, PRIMARY KEY(a)); /\* sub # \*/ CREATE TABLE t2(c int, d text, PRIMARY KEY(c)); /\* sub # \*/ CREATE TABLE t3(e int, f text, PRIMARY KEY(e)); Insert data to the tables at the publisher side. /\* pub # \*/ INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three'); /\* pub # \*/ INSERT INTO t2 VALUES (1, 'A'), (2, 'B'), (3, 'C'); /\* pub # \*/ INSERT INTO t3 VALUES (1, 'i'), (2, 'ii'), (3, 'iii'); Create publications for the tables. The publications `pub2` and `pub3a` disallow some [`publish`](https://www.postgresql.org/docs/current/sql-createpublication.html#SQL-CREATEPUBLICATION-PARAMS-WITH-PUBLISH) operations. The publication `pub3b` has a row filter (see [Section 29.4](https://www.postgresql.org/docs/current/logical-replication-row-filter.html "29.4. Row Filters") ). /\* pub # \*/ CREATE PUBLICATION pub1 FOR TABLE t1; /\* pub # \*/ CREATE PUBLICATION pub2 FOR TABLE t2 WITH (publish = 'truncate'); /\* pub # \*/ CREATE PUBLICATION pub3a FOR TABLE t3 WITH (publish = 'truncate'); /\* pub # \*/ CREATE PUBLICATION pub3b FOR TABLE t3 WHERE (e > 5); Create subscriptions for the publications. The subscription `sub3` subscribes to both `pub3a` and `pub3b`. All subscriptions will copy initial data by default. /\* sub # \*/ CREATE SUBSCRIPTION sub1 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub application\_name=sub1' /\* sub - \*/ PUBLICATION pub1; /\* sub # \*/ CREATE SUBSCRIPTION sub2 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub application\_name=sub2' /\* sub - \*/ PUBLICATION pub2; /\* sub # \*/ CREATE SUBSCRIPTION sub3 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub application\_name=sub3' /\* sub - \*/ PUBLICATION pub3a, pub3b; Observe that initial table data is copied, regardless of the `publish` operation of the publication. /\* sub # \*/ SELECT \* FROM t1; a | b ---+------- 1 | one 2 | two 3 | three (3 rows) /\* sub # \*/ SELECT \* FROM t2; c | d ---+--- 1 | A 2 | B 3 | C (3 rows) Furthermore, because the initial data copy ignores the `publish` operation, and because publication `pub3a` has no row filter, it means the copied table `t3` contains all rows even when they do not match the row filter of publication `pub3b`. /\* sub # \*/ SELECT \* FROM t3; e | f ---+----- 1 | i 2 | ii 3 | iii (3 rows) Insert more data to the tables at the publisher side. /\* pub # \*/ INSERT INTO t1 VALUES (4, 'four'), (5, 'five'), (6, 'six'); /\* pub # \*/ INSERT INTO t2 VALUES (4, 'D'), (5, 'E'), (6, 'F'); /\* pub # \*/ INSERT INTO t3 VALUES (4, 'iv'), (5, 'v'), (6, 'vi'); Now the publisher side data looks like: /\* pub # \*/ SELECT \* FROM t1; a | b ---+------- 1 | one 2 | two 3 | three 4 | four 5 | five 6 | six (6 rows) /\* pub # \*/ SELECT \* FROM t2; c | d ---+--- 1 | A 2 | B 3 | C 4 | D 5 | E 6 | F (6 rows) /\* pub # \*/ SELECT \* FROM t3; e | f ---+----- 1 | i 2 | ii 3 | iii 4 | iv 5 | v 6 | vi (6 rows) Observe that during normal replication the appropriate `publish` operations are used. This means publications `pub2` and `pub3a` will not replicate the `INSERT`. Also, publication `pub3b` will only replicate data that matches the row filter of `pub3b`. Now the subscriber side data looks like: /\* sub # \*/ SELECT \* FROM t1; a | b ---+------- 1 | one 2 | two 3 | three 4 | four 5 | five 6 | six (6 rows) /\* sub # \*/ SELECT \* FROM t2; c | d ---+--- 1 | A 2 | B 3 | C (3 rows) /\* sub # \*/ SELECT \* FROM t3; e | f ---+----- 1 | i 2 | ii 3 | iii 6 | vi (4 rows) ### 29.2.3. Examples: Deferred Replication Slot Creation [#](https://www.postgresql.org/docs/current/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-EXAMPLES-DEFERRED-SLOT) There are some cases (e.g. [Section 29.2.1](https://www.postgresql.org/docs/current/logical-replication-subscription.html#LOGICAL-REPLICATION-SUBSCRIPTION-SLOT "29.2.1. Replication Slot Management") ) where, if the remote replication slot was not created automatically, the user must create it manually before the subscription can be activated. The steps to create the slot and activate the subscription are shown in the following examples. These examples specify the standard logical decoding output plugin (`pgoutput`), which is what the built-in logical replication uses. First, create a publication for the examples to use. /\* pub # \*/ CREATE PUBLICATION pub1 FOR ALL TABLES; Example 1: Where the subscription says `connect = false` * Create the subscription. /\* sub # \*/ CREATE SUBSCRIPTION sub1 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub' /\* sub - \*/ PUBLICATION pub1 /\* sub - \*/ WITH (connect=false); WARNING: subscription was created, but is not connected HINT: To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription. * On the publisher, manually create a slot. Because the name was not specified during `CREATE SUBSCRIPTION`, the name of the slot to create is same as the subscription name, e.g. "sub1". /\* pub # \*/ SELECT \* FROM pg\_create\_logical\_replication\_slot('sub1', 'pgoutput'); slot\_name | lsn -----------+----------- sub1 | 0/19404D0 (1 row) * On the subscriber, complete the activation of the subscription. After this the tables of `pub1` will start replicating. /\* sub # \*/ ALTER SUBSCRIPTION sub1 ENABLE; /\* sub # \*/ ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; Example 2: Where the subscription says `connect = false`, but also specifies the [`slot_name`](https://www.postgresql.org/docs/current/sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-SLOT-NAME) option. * Create the subscription. /\* sub # \*/ CREATE SUBSCRIPTION sub1 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub' /\* sub - \*/ PUBLICATION pub1 /\* sub - \*/ WITH (connect=false, slot\_name='myslot'); WARNING: subscription was created, but is not connected HINT: To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription. * On the publisher, manually create a slot using the same name that was specified during `CREATE SUBSCRIPTION`, e.g. "myslot". /\* pub # \*/ SELECT \* FROM pg\_create\_logical\_replication\_slot('myslot', 'pgoutput'); slot\_name | lsn -----------+----------- myslot | 0/19059A0 (1 row) * On the subscriber, the remaining subscription activation steps are the same as before. /\* sub # \*/ ALTER SUBSCRIPTION sub1 ENABLE; /\* sub # \*/ ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; Example 3: Where the subscription specifies `slot_name = NONE` * Create the subscription. When `slot_name = NONE` then `enabled = false`, and `create_slot = false` are also needed. /\* sub # \*/ CREATE SUBSCRIPTION sub1 /\* sub - \*/ CONNECTION 'host=localhost dbname=test\_pub' /\* sub - \*/ PUBLICATION pub1 /\* sub - \*/ WITH (slot\_name=NONE, enabled=false, create\_slot=false); * On the publisher, manually create a slot using any name, e.g. "myslot". /\* pub # \*/ SELECT \* FROM pg\_create\_logical\_replication\_slot('myslot', 'pgoutput'); slot\_name | lsn -----------+----------- myslot | 0/1905930 (1 row) * On the subscriber, associate the subscription with the slot name just created. /\* sub # \*/ ALTER SUBSCRIPTION sub1 SET (slot\_name='myslot'); * The remaining subscription activation steps are same as before. /\* sub # \*/ ALTER SUBSCRIPTION sub1 ENABLE; /\* sub # \*/ ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/logical-replication-publication.html "29.1. Publication") | [Up](https://www.postgresql.org/docs/current/logical-replication.html "Chapter 29. Logical Replication") | [Next](https://www.postgresql.org/docs/current/logical-replication-failover.html "29.3. Logical Replication Failover") | | 29.1. Publication | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 29.3. Logical Replication Failover | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/logical-replication-subscription.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 15.4. Parallel Safety November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/parallel-safety.html "PostgreSQL 18 - 15.4. Parallel Safety") ([18](https://www.postgresql.org/docs/18/parallel-safety.html "PostgreSQL 18 - 15.4. Parallel Safety") ) / [17](https://www.postgresql.org/docs/17/parallel-safety.html "PostgreSQL 17 - 15.4. Parallel Safety") / [16](https://www.postgresql.org/docs/16/parallel-safety.html "PostgreSQL 16 - 15.4. Parallel Safety") / [15](https://www.postgresql.org/docs/15/parallel-safety.html "PostgreSQL 15 - 15.4. Parallel Safety") / [14](https://www.postgresql.org/docs/14/parallel-safety.html "PostgreSQL 14 - 15.4. Parallel Safety") Development Versions: [devel](https://www.postgresql.org/docs/devel/parallel-safety.html "PostgreSQL devel - 15.4. Parallel Safety") Unsupported versions: [13](https://www.postgresql.org/docs/13/parallel-safety.html "PostgreSQL 13 - 15.4. Parallel Safety") / [12](https://www.postgresql.org/docs/12/parallel-safety.html "PostgreSQL 12 - 15.4. Parallel Safety") / [11](https://www.postgresql.org/docs/11/parallel-safety.html "PostgreSQL 11 - 15.4. Parallel Safety") / [10](https://www.postgresql.org/docs/10/parallel-safety.html "PostgreSQL 10 - 15.4. Parallel Safety") / [9.6](https://www.postgresql.org/docs/9.6/parallel-safety.html "PostgreSQL 9.6 - 15.4. Parallel Safety") | 15.4. Parallel Safety | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/parallel-plans.html "15.3. Parallel Plans") | [Up](https://www.postgresql.org/docs/current/parallel-query.html "Chapter 15. Parallel Query") | Chapter 15. Parallel Query | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/admin.html "Part III. Server Administration") | * * * 15.4. Parallel Safety [#](https://www.postgresql.org/docs/current/parallel-safety.html#PARALLEL-SAFETY) -------------------------------------------------------------------------------------------------------- [15.4.1. Parallel Labeling for Functions and Aggregates](https://www.postgresql.org/docs/current/parallel-safety.html#PARALLEL-LABELING) The planner classifies operations involved in a query as either _parallel safe_, _parallel restricted_, or _parallel unsafe_. A parallel safe operation is one that does not conflict with the use of parallel query. A parallel restricted operation is one that cannot be performed in a parallel worker, but that can be performed in the leader while parallel query is in use. Therefore, parallel restricted operations can never occur below a `Gather` or `Gather Merge` node, but can occur elsewhere in a plan that contains such a node. A parallel unsafe operation is one that cannot be performed while parallel query is in use, not even in the leader. When a query contains anything that is parallel unsafe, parallel query is completely disabled for that query. The following operations are always parallel restricted: * Scans of common table expressions (CTEs). * Scans of temporary tables. * Scans of foreign tables, unless the foreign data wrapper has an `IsForeignScanParallelSafe` API that indicates otherwise. * Plan nodes that reference a correlated `SubPlan`. ### 15.4.1. Parallel Labeling for Functions and Aggregates [#](https://www.postgresql.org/docs/current/parallel-safety.html#PARALLEL-LABELING) The planner cannot automatically determine whether a user-defined function or aggregate is parallel safe, parallel restricted, or parallel unsafe, because this would require predicting every operation that the function could possibly perform. In general, this is equivalent to the Halting Problem and therefore impossible. Even for simple functions where it could conceivably be done, we do not try, since this would be expensive and error-prone. Instead, all user-defined functions are assumed to be parallel unsafe unless otherwise marked. When using [CREATE FUNCTION](https://www.postgresql.org/docs/current/sql-createfunction.html "CREATE FUNCTION") or [ALTER FUNCTION](https://www.postgresql.org/docs/current/sql-alterfunction.html "ALTER FUNCTION") , markings can be set by specifying `PARALLEL SAFE`, `PARALLEL RESTRICTED`, or `PARALLEL UNSAFE` as appropriate. When using [CREATE AGGREGATE](https://www.postgresql.org/docs/current/sql-createaggregate.html "CREATE AGGREGATE") , the `PARALLEL` option can be specified with `SAFE`, `RESTRICTED`, or `UNSAFE` as the corresponding value. Functions and aggregates must be marked `PARALLEL UNSAFE` if they write to the database, change the transaction state (other than by using a subtransaction for error recovery), access sequences, or make persistent changes to settings. Similarly, functions must be marked `PARALLEL RESTRICTED` if they access temporary tables, client connection state, cursors, prepared statements, or miscellaneous backend-local state that the system cannot synchronize across workers. For example, `setseed` and `random` are parallel restricted for this last reason. In general, if a function is labeled as being safe when it is restricted or unsafe, or if it is labeled as being restricted when it is in fact unsafe, it may throw errors or produce wrong answers when used in a parallel query. C-language functions could in theory exhibit totally undefined behavior if mislabeled, since there is no way for the system to protect itself against arbitrary C code, but in most likely cases the result will be no worse than for any other function. If in doubt, it is probably best to label functions as `UNSAFE`. If a function executed within a parallel worker acquires locks that are not held by the leader, for example by querying a table not referenced in the query, those locks will be released at worker exit, not end of transaction. If you write a function that does this, and this behavior difference is important to you, mark such functions as `PARALLEL RESTRICTED` to ensure that they execute only in the leader. Note that the query planner does not consider deferring the evaluation of parallel-restricted functions or aggregates involved in the query in order to obtain a superior plan. So, for example, if a `WHERE` clause applied to a particular table is parallel restricted, the query planner will not consider performing a scan of that table in the parallel portion of a plan. In some cases, it would be possible (and perhaps even efficient) to include the scan of that table in the parallel portion of the query and defer the evaluation of the `WHERE` clause so that it happens above the `Gather` node. However, the planner does not do this. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/parallel-plans.html "15.3. Parallel Plans") | [Up](https://www.postgresql.org/docs/current/parallel-query.html "Chapter 15. Parallel Query") | [Next](https://www.postgresql.org/docs/current/admin.html "Part III. Server Administration") | | 15.3. Parallel Plans | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Part III. Server Administration | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/parallel-safety.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 27.4. Progress Reporting November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/progress-reporting.html "PostgreSQL 18 - 27.4. Progress Reporting") ([18](https://www.postgresql.org/docs/18/progress-reporting.html "PostgreSQL 18 - 27.4. Progress Reporting") ) / [17](https://www.postgresql.org/docs/17/progress-reporting.html "PostgreSQL 17 - 27.4. Progress Reporting") / [16](https://www.postgresql.org/docs/16/progress-reporting.html "PostgreSQL 16 - 27.4. Progress Reporting") / [15](https://www.postgresql.org/docs/15/progress-reporting.html "PostgreSQL 15 - 27.4. Progress Reporting") / [14](https://www.postgresql.org/docs/14/progress-reporting.html "PostgreSQL 14 - 27.4. Progress Reporting") Development Versions: [devel](https://www.postgresql.org/docs/devel/progress-reporting.html "PostgreSQL devel - 27.4. Progress Reporting") Unsupported versions: [13](https://www.postgresql.org/docs/13/progress-reporting.html "PostgreSQL 13 - 27.4. Progress Reporting") / [12](https://www.postgresql.org/docs/12/progress-reporting.html "PostgreSQL 12 - 27.4. Progress Reporting") / [11](https://www.postgresql.org/docs/11/progress-reporting.html "PostgreSQL 11 - 27.4. Progress Reporting") / [10](https://www.postgresql.org/docs/10/progress-reporting.html "PostgreSQL 10 - 27.4. Progress Reporting") / [9.6](https://www.postgresql.org/docs/9.6/progress-reporting.html "PostgreSQL 9.6 - 27.4. Progress Reporting") | 27.4. Progress Reporting | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/monitoring-locks.html "27.3. Viewing Locks") | [Up](https://www.postgresql.org/docs/18/monitoring.html "Chapter 27. Monitoring Database Activity") | Chapter 27. Monitoring Database Activity | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/dynamic-trace.html "27.5. Dynamic Tracing") | * * * 27.4. Progress Reporting [#](https://www.postgresql.org/docs/18/progress-reporting.html#PROGRESS-REPORTING) ------------------------------------------------------------------------------------------------------------ [27.4.1. ANALYZE Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#ANALYZE-PROGRESS-REPORTING) [27.4.2. CLUSTER Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#CLUSTER-PROGRESS-REPORTING) [27.4.3. COPY Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#COPY-PROGRESS-REPORTING) [27.4.4. CREATE INDEX Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING) [27.4.5. VACUUM Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#VACUUM-PROGRESS-REPORTING) [27.4.6. Base Backup Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#BASEBACKUP-PROGRESS-REPORTING) PostgreSQL has the ability to report the progress of certain commands during command execution. Currently, the only commands which support progress reporting are `ANALYZE`, `CLUSTER`, `CREATE INDEX`, `VACUUM`, `COPY`, and [BASE\_BACKUP](https://www.postgresql.org/docs/18/protocol-replication.html#PROTOCOL-REPLICATION-BASE-BACKUP) (i.e., replication command that [pg\_basebackup](https://www.postgresql.org/docs/18/app-pgbasebackup.html "pg_basebackup") issues to take a base backup). This may be expanded in the future. ### 27.4.1. ANALYZE Progress Reporting [#](https://www.postgresql.org/docs/18/progress-reporting.html#ANALYZE-PROGRESS-REPORTING) Whenever `ANALYZE` is running, the `pg_stat_progress_analyze` view will contain a row for each backend that is currently running that command. The tables below describe the information that will be reported and provide information about how to interpret it. **Table 27.38. `pg_stat_progress_analyze` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of backend. | | `datid` `oid`

OID of the database to which this backend is connected. | | `datname` `name`

Name of the database to which this backend is connected. | | `relid` `oid`

OID of the table being analyzed. | | `phase` `text`

Current processing phase. See [Table 27.39](https://www.postgresql.org/docs/18/progress-reporting.html#ANALYZE-PHASES "Table 27.39. ANALYZE Phases")
. | | `sample_blks_total` `bigint`

Total number of heap blocks that will be sampled. | | `sample_blks_scanned` `bigint`

Number of heap blocks scanned. | | `ext_stats_total` `bigint`

Number of extended statistics. | | `ext_stats_computed` `bigint`

Number of extended statistics computed. This counter only advances when the phase is `computing extended statistics`. | | `child_tables_total` `bigint`

Number of child tables. | | `child_tables_done` `bigint`

Number of child tables scanned. This counter only advances when the phase is `acquiring inherited sample rows`. | | `current_child_table_relid` `oid`

OID of the child table currently being scanned. This field is only valid when the phase is `acquiring inherited sample rows`. | | `delay_time` `double precision`

Total time spent sleeping due to cost-based delay (see [Section 19.10.2](https://www.postgresql.org/docs/18/runtime-config-vacuum.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST "19.10.2. Cost-based Vacuum Delay")
), in milliseconds (if [track\_cost\_delay\_timing](https://www.postgresql.org/docs/18/runtime-config-statistics.html#GUC-TRACK-COST-DELAY-TIMING)
is enabled, otherwise zero). | **Table 27.39. ANALYZE Phases** | Phase | Description | | --- | --- | | `initializing` | The command is preparing to begin scanning the heap. This phase is expected to be very brief. | | `acquiring sample rows` | The command is currently scanning the table given by `relid` to obtain sample rows. | | `acquiring inherited sample rows` | The command is currently scanning child tables to obtain sample rows. Columns `child_tables_total`, `child_tables_done`, and `current_child_table_relid` contain the progress information for this phase. | | `computing statistics` | The command is computing statistics from the sample rows obtained during the table scan. | | `computing extended statistics` | The command is computing extended statistics from the sample rows obtained during the table scan. | | `finalizing analyze` | The command is updating `pg_class`. When this phase is completed, `ANALYZE` will end. | ### Note Note that when `ANALYZE` is run on a partitioned table without the `ONLY` keyword, all of its partitions are also recursively analyzed. In that case, `ANALYZE` progress is reported first for the parent table, whereby its inheritance statistics are collected, followed by that for each partition. ### 27.4.2. CLUSTER Progress Reporting [#](https://www.postgresql.org/docs/18/progress-reporting.html#CLUSTER-PROGRESS-REPORTING) Whenever `CLUSTER` or `VACUUM FULL` is running, the `pg_stat_progress_cluster` view will contain a row for each backend that is currently running either command. The tables below describe the information that will be reported and provide information about how to interpret it. **Table 27.40. `pg_stat_progress_cluster` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of backend. | | `datid` `oid`

OID of the database to which this backend is connected. | | `datname` `name`

Name of the database to which this backend is connected. | | `relid` `oid`

OID of the table being clustered. | | `command` `text`

The command that is running. Either `CLUSTER` or `VACUUM FULL`. | | `phase` `text`

Current processing phase. See [Table 27.41](https://www.postgresql.org/docs/18/progress-reporting.html#CLUSTER-PHASES "Table 27.41. CLUSTER and VACUUM FULL Phases")
. | | `cluster_index_relid` `oid`

If the table is being scanned using an index, this is the OID of the index being used; otherwise, it is zero. | | `heap_tuples_scanned` `bigint`

Number of heap tuples scanned. This counter only advances when the phase is `seq scanning heap`, `index scanning heap` or `writing new heap`. | | `heap_tuples_written` `bigint`

Number of heap tuples written. This counter only advances when the phase is `seq scanning heap`, `index scanning heap` or `writing new heap`. | | `heap_blks_total` `bigint`

Total number of heap blocks in the table. This number is reported as of the beginning of `seq scanning heap`. | | `heap_blks_scanned` `bigint`

Number of heap blocks scanned. This counter only advances when the phase is `seq scanning heap`. | | `index_rebuild_count` `bigint`

Number of indexes rebuilt. This counter only advances when the phase is `rebuilding index`. | **Table 27.41. CLUSTER and VACUUM FULL Phases** | Phase | Description | | --- | --- | | `initializing` | The command is preparing to begin scanning the heap. This phase is expected to be very brief. | | `seq scanning heap` | The command is currently scanning the table using a sequential scan. | | `index scanning heap` | `CLUSTER` is currently scanning the table using an index scan. | | `sorting tuples` | `CLUSTER` is currently sorting tuples. | | `writing new heap` | `CLUSTER` is currently writing the new heap. | | `swapping relation files` | The command is currently swapping newly-built files into place. | | `rebuilding index` | The command is currently rebuilding an index. | | `performing final cleanup` | The command is performing final cleanup. When this phase is completed, `CLUSTER` or `VACUUM FULL` will end. | ### 27.4.3. COPY Progress Reporting [#](https://www.postgresql.org/docs/18/progress-reporting.html#COPY-PROGRESS-REPORTING) Whenever `COPY` is running, the `pg_stat_progress_copy` view will contain one row for each backend that is currently running a `COPY` command. The table below describes the information that will be reported and provides information about how to interpret it. **Table 27.42. `pg_stat_progress_copy` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of backend. | | `datid` `oid`

OID of the database to which this backend is connected. | | `datname` `name`

Name of the database to which this backend is connected. | | `relid` `oid`

OID of the table on which the `COPY` command is executed. It is set to `0` if copying from a `SELECT` query. | | `command` `text`

The command that is running: `COPY FROM`, or `COPY TO`. | | `type` `text`

The I/O type that the data is read from or written to: `FILE`, `PROGRAM`, `PIPE` (for `COPY FROM STDIN` and `COPY TO STDOUT`), or `CALLBACK` (used for example during the initial table synchronization in logical replication). | | `bytes_processed` `bigint`

Number of bytes already processed by `COPY` command. | | `bytes_total` `bigint`

Size of source file for `COPY FROM` command in bytes. It is set to `0` if not available. | | `tuples_processed` `bigint`

Number of tuples already processed by `COPY` command. | | `tuples_excluded` `bigint`

Number of tuples not processed because they were excluded by the `WHERE` clause of the `COPY` command. | | `tuples_skipped` `bigint`

Number of tuples skipped because they contain malformed data. This counter only advances when a value other than `stop` is specified to the `ON_ERROR` option. | ### 27.4.4. CREATE INDEX Progress Reporting [#](https://www.postgresql.org/docs/18/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING) Whenever `CREATE INDEX` or `REINDEX` is running, the `pg_stat_progress_create_index` view will contain one row for each backend that is currently creating indexes. The tables below describe the information that will be reported and provide information about how to interpret it. **Table 27.43. `pg_stat_progress_create_index` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of the backend creating indexes. | | `datid` `oid`

OID of the database to which this backend is connected. | | `datname` `name`

Name of the database to which this backend is connected. | | `relid` `oid`

OID of the table on which the index is being created. | | `index_relid` `oid`

OID of the index being created or reindexed. During a non-concurrent `CREATE INDEX`, this is 0. | | `command` `text`

Specific command type: `CREATE INDEX`, `CREATE INDEX CONCURRENTLY`, `REINDEX`, or `REINDEX CONCURRENTLY`. | | `phase` `text`

Current processing phase of index creation. See [Table 27.44](https://www.postgresql.org/docs/18/progress-reporting.html#CREATE-INDEX-PHASES "Table 27.44. CREATE INDEX Phases")
. | | `lockers_total` `bigint`

Total number of lockers to wait for, when applicable. | | `lockers_done` `bigint`

Number of lockers already waited for. | | `current_locker_pid` `bigint`

Process ID of the locker currently being waited for. | | `blocks_total` `bigint`

Total number of blocks to be processed in the current phase. | | `blocks_done` `bigint`

Number of blocks already processed in the current phase. | | `tuples_total` `bigint`

Total number of tuples to be processed in the current phase. | | `tuples_done` `bigint`

Number of tuples already processed in the current phase. | | `partitions_total` `bigint`

Total number of partitions on which the index is to be created or attached, including both direct and indirect partitions. `0` during a `REINDEX`, or when the index is not partitioned. | | `partitions_done` `bigint`

Number of partitions on which the index has already been created or attached, including both direct and indirect partitions. `0` during a `REINDEX`, or when the index is not partitioned. | **Table 27.44. CREATE INDEX Phases** | Phase | Description | | --- | --- | | `initializing` | `CREATE INDEX` or `REINDEX` is preparing to create the index. This phase is expected to be very brief. | | `waiting for writers before build` | `CREATE INDEX CONCURRENTLY` or `REINDEX CONCURRENTLY` is waiting for transactions with write locks that can potentially see the table to finish. This phase is skipped when not in concurrent mode. Columns `lockers_total`, `lockers_done` and `current_locker_pid` contain the progress information for this phase. | | `building index` | The index is being built by the access method-specific code. In this phase, access methods that support progress reporting fill in their own progress data, and the subphase is indicated in this column. Typically, `blocks_total` and `blocks_done` will contain progress data, as well as potentially `tuples_total` and `tuples_done`. | | `waiting for writers before validation` | `CREATE INDEX CONCURRENTLY` or `REINDEX CONCURRENTLY` is waiting for transactions with write locks that can potentially write into the table to finish. This phase is skipped when not in concurrent mode. Columns `lockers_total`, `lockers_done` and `current_locker_pid` contain the progress information for this phase. | | `index validation: scanning index` | `CREATE INDEX CONCURRENTLY` is scanning the index searching for tuples that need to be validated. This phase is skipped when not in concurrent mode. Columns `blocks_total` (set to the total size of the index) and `blocks_done` contain the progress information for this phase. | | `index validation: sorting tuples` | `CREATE INDEX CONCURRENTLY` is sorting the output of the index scanning phase. | | `index validation: scanning table` | `CREATE INDEX CONCURRENTLY` is scanning the table to validate the index tuples collected in the previous two phases. This phase is skipped when not in concurrent mode. Columns `blocks_total` (set to the total size of the table) and `blocks_done` contain the progress information for this phase. | | `waiting for old snapshots` | `CREATE INDEX CONCURRENTLY` or `REINDEX CONCURRENTLY` is waiting for transactions that can potentially see the table to release their snapshots. This phase is skipped when not in concurrent mode. Columns `lockers_total`, `lockers_done` and `current_locker_pid` contain the progress information for this phase. | | `waiting for readers before marking dead` | `REINDEX CONCURRENTLY` is waiting for transactions with read locks on the table to finish, before marking the old index dead. This phase is skipped when not in concurrent mode. Columns `lockers_total`, `lockers_done` and `current_locker_pid` contain the progress information for this phase. | | `waiting for readers before dropping` | `REINDEX CONCURRENTLY` is waiting for transactions with read locks on the table to finish, before dropping the old index. This phase is skipped when not in concurrent mode. Columns `lockers_total`, `lockers_done` and `current_locker_pid` contain the progress information for this phase. | ### 27.4.5. VACUUM Progress Reporting [#](https://www.postgresql.org/docs/18/progress-reporting.html#VACUUM-PROGRESS-REPORTING) Whenever `VACUUM` is running, the `pg_stat_progress_vacuum` view will contain one row for each backend (including autovacuum worker processes) that is currently vacuuming. The tables below describe the information that will be reported and provide information about how to interpret it. Progress for `VACUUM FULL` commands is reported via `pg_stat_progress_cluster` because both `VACUUM FULL` and `CLUSTER` rewrite the table, while regular `VACUUM` only modifies it in place. See [Section 27.4.2](https://www.postgresql.org/docs/18/progress-reporting.html#CLUSTER-PROGRESS-REPORTING "27.4.2. CLUSTER Progress Reporting") . **Table 27.45. `pg_stat_progress_vacuum` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of backend. | | `datid` `oid`

OID of the database to which this backend is connected. | | `datname` `name`

Name of the database to which this backend is connected. | | `relid` `oid`

OID of the table being vacuumed. | | `phase` `text`

Current processing phase of vacuum. See [Table 27.46](https://www.postgresql.org/docs/18/progress-reporting.html#VACUUM-PHASES "Table 27.46. VACUUM Phases")
. | | `heap_blks_total` `bigint`

Total number of heap blocks in the table. This number is reported as of the beginning of the scan; blocks added later will not be (and need not be) visited by this `VACUUM`. | | `heap_blks_scanned` `bigint`

Number of heap blocks scanned. Because the [visibility map](https://www.postgresql.org/docs/18/storage-vm.html "66.4. Visibility Map")
is used to optimize scans, some blocks will be skipped without inspection; skipped blocks are included in this total, so that this number will eventually become equal to `heap_blks_total` when the vacuum is complete. This counter only advances when the phase is `scanning heap`. | | `heap_blks_vacuumed` `bigint`

Number of heap blocks vacuumed. Unless the table has no indexes, this counter only advances when the phase is `vacuuming heap`. Blocks that contain no dead tuples are skipped, so the counter may sometimes skip forward in large increments. | | `index_vacuum_count` `bigint`

Number of completed index vacuum cycles. | | `max_dead_tuple_bytes` `bigint`

Amount of dead tuple data that we can store before needing to perform an index vacuum cycle, based on [maintenance\_work\_mem](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM)
. | | `dead_tuple_bytes` `bigint`

Amount of dead tuple data collected since the last index vacuum cycle. | | `num_dead_item_ids` `bigint`

Number of dead item identifiers collected since the last index vacuum cycle. | | `indexes_total` `bigint`

Total number of indexes that will be vacuumed or cleaned up. This number is reported at the beginning of the `vacuuming indexes` phase or the `cleaning up indexes` phase. | | `indexes_processed` `bigint`

Number of indexes processed. This counter only advances when the phase is `vacuuming indexes` or `cleaning up indexes`. | | `delay_time` `double precision`

Total time spent sleeping due to cost-based delay (see [Section 19.10.2](https://www.postgresql.org/docs/18/runtime-config-vacuum.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST "19.10.2. Cost-based Vacuum Delay")
), in milliseconds (if [track\_cost\_delay\_timing](https://www.postgresql.org/docs/18/runtime-config-statistics.html#GUC-TRACK-COST-DELAY-TIMING)
is enabled, otherwise zero). This includes the time that any associated parallel workers have slept. However, parallel workers report their sleep time no more frequently than once per second, so the reported value may be slightly stale. | **Table 27.46. VACUUM Phases** | Phase | Description | | --- | --- | | `initializing` | `VACUUM` is preparing to begin scanning the heap. This phase is expected to be very brief. | | `scanning heap` | `VACUUM` is currently scanning the heap. It will prune and defragment each page if required, and possibly perform freezing activity. The `heap_blks_scanned` column can be used to monitor the progress of the scan. | | `vacuuming indexes` | `VACUUM` is currently vacuuming the indexes. If a table has any indexes, this will happen at least once per vacuum, after the heap has been completely scanned. It may happen multiple times per vacuum if [maintenance\_work\_mem](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM)
(or, in the case of autovacuum, [autovacuum\_work\_mem](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM)
if set) is insufficient to store the number of dead tuples found. | | `vacuuming heap` | `VACUUM` is currently vacuuming the heap. Vacuuming the heap is distinct from scanning the heap, and occurs after each instance of vacuuming indexes. If `heap_blks_scanned` is less than `heap_blks_total`, the system will return to scanning the heap after this phase is completed; otherwise, it will begin cleaning up indexes after this phase is completed. | | `cleaning up indexes` | `VACUUM` is currently cleaning up indexes. This occurs after the heap has been completely scanned and all vacuuming of the indexes and the heap has been completed. | | `truncating heap` | `VACUUM` is currently truncating the heap so as to return empty pages at the end of the relation to the operating system. This occurs after cleaning up indexes. | | `performing final cleanup` | `VACUUM` is performing final cleanup. During this phase, `VACUUM` will vacuum the free space map, update statistics in `pg_class`, and report statistics to the cumulative statistics system. When this phase is completed, `VACUUM` will end. | ### 27.4.6. Base Backup Progress Reporting [#](https://www.postgresql.org/docs/18/progress-reporting.html#BASEBACKUP-PROGRESS-REPORTING) Whenever an application like pg\_basebackup is taking a base backup, the `pg_stat_progress_basebackup` view will contain a row for each WAL sender process that is currently running the `BASE_BACKUP` replication command and streaming the backup. The tables below describe the information that will be reported and provide information about how to interpret it. **Table 27.47. `pg_stat_progress_basebackup` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of a WAL sender process. | | `phase` `text`

Current processing phase. See [Table 27.48](https://www.postgresql.org/docs/18/progress-reporting.html#BASEBACKUP-PHASES "Table 27.48. Base Backup Phases")
. | | `backup_total` `bigint`

Total amount of data that will be streamed. This is estimated and reported as of the beginning of `streaming database files` phase. Note that this is only an approximation since the database may change during `streaming database files` phase and WAL log may be included in the backup later. This is always the same value as `backup_streamed` once the amount of data streamed exceeds the estimated total size. If the estimation is disabled in pg\_basebackup (i.e., `--no-estimate-size` option is specified), this is `NULL`. | | `backup_streamed` `bigint`

Amount of data streamed. This counter only advances when the phase is `streaming database files` or `transferring wal files`. | | `tablespaces_total` `bigint`

Total number of tablespaces that will be streamed. | | `tablespaces_streamed` `bigint`

Number of tablespaces streamed. This counter only advances when the phase is `streaming database files`. | **Table 27.48. Base Backup Phases** | Phase | Description | | --- | --- | | `initializing` | The WAL sender process is preparing to begin the backup. This phase is expected to be very brief. | | `waiting for checkpoint to finish` | The WAL sender process is currently performing `pg_backup_start` to prepare to take a base backup, and waiting for the start-of-backup checkpoint to finish. | | `estimating backup size` | The WAL sender process is currently estimating the total amount of database files that will be streamed as a base backup. | | `streaming database files` | The WAL sender process is currently streaming database files as a base backup. | | `waiting for wal archiving to finish` | The WAL sender process is currently performing `pg_backup_stop` to finish the backup, and waiting for all the WAL files required for the base backup to be successfully archived. If either `--wal-method=none` or `--wal-method=stream` is specified in pg\_basebackup, the backup will end when this phase is completed. | | `transferring wal files` | The WAL sender process is currently transferring all WAL logs generated during the backup. This phase occurs after `waiting for wal archiving to finish` phase if `--wal-method=fetch` is specified in pg\_basebackup. The backup will end when this phase is completed. | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/monitoring-locks.html "27.3. Viewing Locks") | [Up](https://www.postgresql.org/docs/18/monitoring.html "Chapter 27. Monitoring Database Activity") | [Next](https://www.postgresql.org/docs/18/dynamic-trace.html "27.5. Dynamic Tracing") | | 27.3. Viewing Locks | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 27.5. Dynamic Tracing | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/progress-reporting.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE TEXT SEARCH DICTIONARY November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createtsdictionary.html "PostgreSQL 18 - CREATE TEXT SEARCH DICTIONARY") ([18](https://www.postgresql.org/docs/18/sql-createtsdictionary.html "PostgreSQL 18 - CREATE TEXT SEARCH DICTIONARY") ) / [17](https://www.postgresql.org/docs/17/sql-createtsdictionary.html "PostgreSQL 17 - CREATE TEXT SEARCH DICTIONARY") / [16](https://www.postgresql.org/docs/16/sql-createtsdictionary.html "PostgreSQL 16 - CREATE TEXT SEARCH DICTIONARY") / [15](https://www.postgresql.org/docs/15/sql-createtsdictionary.html "PostgreSQL 15 - CREATE TEXT SEARCH DICTIONARY") / [14](https://www.postgresql.org/docs/14/sql-createtsdictionary.html "PostgreSQL 14 - CREATE TEXT SEARCH DICTIONARY") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createtsdictionary.html "PostgreSQL devel - CREATE TEXT SEARCH DICTIONARY") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createtsdictionary.html "PostgreSQL 13 - CREATE TEXT SEARCH DICTIONARY") / [12](https://www.postgresql.org/docs/12/sql-createtsdictionary.html "PostgreSQL 12 - CREATE TEXT SEARCH DICTIONARY") / [11](https://www.postgresql.org/docs/11/sql-createtsdictionary.html "PostgreSQL 11 - CREATE TEXT SEARCH DICTIONARY") / [10](https://www.postgresql.org/docs/10/sql-createtsdictionary.html "PostgreSQL 10 - CREATE TEXT SEARCH DICTIONARY") / [9.6](https://www.postgresql.org/docs/9.6/sql-createtsdictionary.html "PostgreSQL 9.6 - CREATE TEXT SEARCH DICTIONARY") / [9.5](https://www.postgresql.org/docs/9.5/sql-createtsdictionary.html "PostgreSQL 9.5 - CREATE TEXT SEARCH DICTIONARY") / [9.4](https://www.postgresql.org/docs/9.4/sql-createtsdictionary.html "PostgreSQL 9.4 - CREATE TEXT SEARCH DICTIONARY") / [9.3](https://www.postgresql.org/docs/9.3/sql-createtsdictionary.html "PostgreSQL 9.3 - CREATE TEXT SEARCH DICTIONARY") / [9.2](https://www.postgresql.org/docs/9.2/sql-createtsdictionary.html "PostgreSQL 9.2 - CREATE TEXT SEARCH DICTIONARY") / [9.1](https://www.postgresql.org/docs/9.1/sql-createtsdictionary.html "PostgreSQL 9.1 - CREATE TEXT SEARCH DICTIONARY") / [9.0](https://www.postgresql.org/docs/9.0/sql-createtsdictionary.html "PostgreSQL 9.0 - CREATE TEXT SEARCH DICTIONARY") / [8.4](https://www.postgresql.org/docs/8.4/sql-createtsdictionary.html "PostgreSQL 8.4 - CREATE TEXT SEARCH DICTIONARY") / [8.3](https://www.postgresql.org/docs/8.3/sql-createtsdictionary.html "PostgreSQL 8.3 - CREATE TEXT SEARCH DICTIONARY") | CREATE TEXT SEARCH DICTIONARY | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createtsconfig.html "CREATE TEXT SEARCH CONFIGURATION") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-createtsparser.html "CREATE TEXT SEARCH PARSER") | * * * CREATE TEXT SEARCH DICTIONARY ----------------------------- CREATE TEXT SEARCH DICTIONARY — define a new text search dictionary Synopsis -------- CREATE TEXT SEARCH DICTIONARY _`name`_ ( TEMPLATE = _`template`_ \[, _`option`_ = _`value`_ \[, ... \]\] ) Description ----------- `CREATE TEXT SEARCH DICTIONARY` creates a new text search dictionary. A text search dictionary specifies a way of recognizing interesting or uninteresting words for searching. A dictionary depends on a text search template, which specifies the functions that actually perform the work. Typically the dictionary provides some options that control the detailed behavior of the template's functions. If a schema name is given then the text search dictionary is created in the specified schema. Otherwise it is created in the current schema. The user who defines a text search dictionary becomes its owner. Refer to [Chapter 12](https://www.postgresql.org/docs/18/textsearch.html "Chapter 12. Full Text Search") for further information. Parameters ---------- _`name`_ The name of the text search dictionary to be created. The name can be schema-qualified. _`template`_ The name of the text search template that will define the basic behavior of this dictionary. _`option`_ The name of a template-specific option to be set for this dictionary. _`value`_ The value to use for a template-specific option. If the value is not a simple identifier or number, it must be quoted (but you can always quote it, if you wish). The options can appear in any order. Examples -------- The following example command creates a Snowball-based dictionary with a nonstandard list of stop words. CREATE TEXT SEARCH DICTIONARY my\_russian ( template = snowball, language = russian, stopwords = myrussian ); Compatibility ------------- There is no `CREATE TEXT SEARCH DICTIONARY` statement in the SQL standard. See Also -------- [ALTER TEXT SEARCH DICTIONARY](https://www.postgresql.org/docs/18/sql-altertsdictionary.html "ALTER TEXT SEARCH DICTIONARY") , [DROP TEXT SEARCH DICTIONARY](https://www.postgresql.org/docs/18/sql-droptsdictionary.html "DROP TEXT SEARCH DICTIONARY") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createtsconfig.html "CREATE TEXT SEARCH CONFIGURATION") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-createtsparser.html "CREATE TEXT SEARCH PARSER") | | CREATE TEXT SEARCH CONFIGURATION | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | CREATE TEXT SEARCH PARSER | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createtsdictionary.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 27.4. Progress Reporting November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/progress-reporting.html "PostgreSQL 18 - 27.4. Progress Reporting") ([18](https://www.postgresql.org/docs/18/progress-reporting.html "PostgreSQL 18 - 27.4. Progress Reporting") ) / [17](https://www.postgresql.org/docs/17/progress-reporting.html "PostgreSQL 17 - 27.4. Progress Reporting") / [16](https://www.postgresql.org/docs/16/progress-reporting.html "PostgreSQL 16 - 27.4. Progress Reporting") / [15](https://www.postgresql.org/docs/15/progress-reporting.html "PostgreSQL 15 - 27.4. Progress Reporting") / [14](https://www.postgresql.org/docs/14/progress-reporting.html "PostgreSQL 14 - 27.4. Progress Reporting") Development Versions: [devel](https://www.postgresql.org/docs/devel/progress-reporting.html "PostgreSQL devel - 27.4. Progress Reporting") Unsupported versions: [13](https://www.postgresql.org/docs/13/progress-reporting.html "PostgreSQL 13 - 27.4. Progress Reporting") / [12](https://www.postgresql.org/docs/12/progress-reporting.html "PostgreSQL 12 - 27.4. Progress Reporting") / [11](https://www.postgresql.org/docs/11/progress-reporting.html "PostgreSQL 11 - 27.4. Progress Reporting") / [10](https://www.postgresql.org/docs/10/progress-reporting.html "PostgreSQL 10 - 27.4. Progress Reporting") / [9.6](https://www.postgresql.org/docs/9.6/progress-reporting.html "PostgreSQL 9.6 - 27.4. Progress Reporting") | 27.4. Progress Reporting | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/monitoring-locks.html "27.3. Viewing Locks") | [Up](https://www.postgresql.org/docs/current/monitoring.html "Chapter 27. Monitoring Database Activity") | Chapter 27. Monitoring Database Activity | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/dynamic-trace.html "27.5. Dynamic Tracing") | * * * 27.4. Progress Reporting [#](https://www.postgresql.org/docs/current/progress-reporting.html#PROGRESS-REPORTING) ----------------------------------------------------------------------------------------------------------------- [27.4.1. ANALYZE Progress Reporting](https://www.postgresql.org/docs/current/progress-reporting.html#ANALYZE-PROGRESS-REPORTING) [27.4.2. CLUSTER Progress Reporting](https://www.postgresql.org/docs/current/progress-reporting.html#CLUSTER-PROGRESS-REPORTING) [27.4.3. COPY Progress Reporting](https://www.postgresql.org/docs/current/progress-reporting.html#COPY-PROGRESS-REPORTING) [27.4.4. CREATE INDEX Progress Reporting](https://www.postgresql.org/docs/current/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING) [27.4.5. VACUUM Progress Reporting](https://www.postgresql.org/docs/current/progress-reporting.html#VACUUM-PROGRESS-REPORTING) [27.4.6. Base Backup Progress Reporting](https://www.postgresql.org/docs/current/progress-reporting.html#BASEBACKUP-PROGRESS-REPORTING) PostgreSQL has the ability to report the progress of certain commands during command execution. Currently, the only commands which support progress reporting are `ANALYZE`, `CLUSTER`, `CREATE INDEX`, `VACUUM`, `COPY`, and [BASE\_BACKUP](https://www.postgresql.org/docs/current/protocol-replication.html#PROTOCOL-REPLICATION-BASE-BACKUP) (i.e., replication command that [pg\_basebackup](https://www.postgresql.org/docs/current/app-pgbasebackup.html "pg_basebackup") issues to take a base backup). This may be expanded in the future. ### 27.4.1. ANALYZE Progress Reporting [#](https://www.postgresql.org/docs/current/progress-reporting.html#ANALYZE-PROGRESS-REPORTING) Whenever `ANALYZE` is running, the `pg_stat_progress_analyze` view will contain a row for each backend that is currently running that command. The tables below describe the information that will be reported and provide information about how to interpret it. **Table 27.38. `pg_stat_progress_analyze` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of backend. | | `datid` `oid`

OID of the database to which this backend is connected. | | `datname` `name`

Name of the database to which this backend is connected. | | `relid` `oid`

OID of the table being analyzed. | | `phase` `text`

Current processing phase. See [Table 27.39](https://www.postgresql.org/docs/current/progress-reporting.html#ANALYZE-PHASES "Table 27.39. ANALYZE Phases")
. | | `sample_blks_total` `bigint`

Total number of heap blocks that will be sampled. | | `sample_blks_scanned` `bigint`

Number of heap blocks scanned. | | `ext_stats_total` `bigint`

Number of extended statistics. | | `ext_stats_computed` `bigint`

Number of extended statistics computed. This counter only advances when the phase is `computing extended statistics`. | | `child_tables_total` `bigint`

Number of child tables. | | `child_tables_done` `bigint`

Number of child tables scanned. This counter only advances when the phase is `acquiring inherited sample rows`. | | `current_child_table_relid` `oid`

OID of the child table currently being scanned. This field is only valid when the phase is `acquiring inherited sample rows`. | | `delay_time` `double precision`

Total time spent sleeping due to cost-based delay (see [Section 19.10.2](https://www.postgresql.org/docs/current/runtime-config-vacuum.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST "19.10.2. Cost-based Vacuum Delay")
), in milliseconds (if [track\_cost\_delay\_timing](https://www.postgresql.org/docs/current/runtime-config-statistics.html#GUC-TRACK-COST-DELAY-TIMING)
is enabled, otherwise zero). | **Table 27.39. ANALYZE Phases** | Phase | Description | | --- | --- | | `initializing` | The command is preparing to begin scanning the heap. This phase is expected to be very brief. | | `acquiring sample rows` | The command is currently scanning the table given by `relid` to obtain sample rows. | | `acquiring inherited sample rows` | The command is currently scanning child tables to obtain sample rows. Columns `child_tables_total`, `child_tables_done`, and `current_child_table_relid` contain the progress information for this phase. | | `computing statistics` | The command is computing statistics from the sample rows obtained during the table scan. | | `computing extended statistics` | The command is computing extended statistics from the sample rows obtained during the table scan. | | `finalizing analyze` | The command is updating `pg_class`. When this phase is completed, `ANALYZE` will end. | ### Note Note that when `ANALYZE` is run on a partitioned table without the `ONLY` keyword, all of its partitions are also recursively analyzed. In that case, `ANALYZE` progress is reported first for the parent table, whereby its inheritance statistics are collected, followed by that for each partition. ### 27.4.2. CLUSTER Progress Reporting [#](https://www.postgresql.org/docs/current/progress-reporting.html#CLUSTER-PROGRESS-REPORTING) Whenever `CLUSTER` or `VACUUM FULL` is running, the `pg_stat_progress_cluster` view will contain a row for each backend that is currently running either command. The tables below describe the information that will be reported and provide information about how to interpret it. **Table 27.40. `pg_stat_progress_cluster` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of backend. | | `datid` `oid`

OID of the database to which this backend is connected. | | `datname` `name`

Name of the database to which this backend is connected. | | `relid` `oid`

OID of the table being clustered. | | `command` `text`

The command that is running. Either `CLUSTER` or `VACUUM FULL`. | | `phase` `text`

Current processing phase. See [Table 27.41](https://www.postgresql.org/docs/current/progress-reporting.html#CLUSTER-PHASES "Table 27.41. CLUSTER and VACUUM FULL Phases")
. | | `cluster_index_relid` `oid`

If the table is being scanned using an index, this is the OID of the index being used; otherwise, it is zero. | | `heap_tuples_scanned` `bigint`

Number of heap tuples scanned. This counter only advances when the phase is `seq scanning heap`, `index scanning heap` or `writing new heap`. | | `heap_tuples_written` `bigint`

Number of heap tuples written. This counter only advances when the phase is `seq scanning heap`, `index scanning heap` or `writing new heap`. | | `heap_blks_total` `bigint`

Total number of heap blocks in the table. This number is reported as of the beginning of `seq scanning heap`. | | `heap_blks_scanned` `bigint`

Number of heap blocks scanned. This counter only advances when the phase is `seq scanning heap`. | | `index_rebuild_count` `bigint`

Number of indexes rebuilt. This counter only advances when the phase is `rebuilding index`. | **Table 27.41. CLUSTER and VACUUM FULL Phases** | Phase | Description | | --- | --- | | `initializing` | The command is preparing to begin scanning the heap. This phase is expected to be very brief. | | `seq scanning heap` | The command is currently scanning the table using a sequential scan. | | `index scanning heap` | `CLUSTER` is currently scanning the table using an index scan. | | `sorting tuples` | `CLUSTER` is currently sorting tuples. | | `writing new heap` | `CLUSTER` is currently writing the new heap. | | `swapping relation files` | The command is currently swapping newly-built files into place. | | `rebuilding index` | The command is currently rebuilding an index. | | `performing final cleanup` | The command is performing final cleanup. When this phase is completed, `CLUSTER` or `VACUUM FULL` will end. | ### 27.4.3. COPY Progress Reporting [#](https://www.postgresql.org/docs/current/progress-reporting.html#COPY-PROGRESS-REPORTING) Whenever `COPY` is running, the `pg_stat_progress_copy` view will contain one row for each backend that is currently running a `COPY` command. The table below describes the information that will be reported and provides information about how to interpret it. **Table 27.42. `pg_stat_progress_copy` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of backend. | | `datid` `oid`

OID of the database to which this backend is connected. | | `datname` `name`

Name of the database to which this backend is connected. | | `relid` `oid`

OID of the table on which the `COPY` command is executed. It is set to `0` if copying from a `SELECT` query. | | `command` `text`

The command that is running: `COPY FROM`, or `COPY TO`. | | `type` `text`

The I/O type that the data is read from or written to: `FILE`, `PROGRAM`, `PIPE` (for `COPY FROM STDIN` and `COPY TO STDOUT`), or `CALLBACK` (used for example during the initial table synchronization in logical replication). | | `bytes_processed` `bigint`

Number of bytes already processed by `COPY` command. | | `bytes_total` `bigint`

Size of source file for `COPY FROM` command in bytes. It is set to `0` if not available. | | `tuples_processed` `bigint`

Number of tuples already processed by `COPY` command. | | `tuples_excluded` `bigint`

Number of tuples not processed because they were excluded by the `WHERE` clause of the `COPY` command. | | `tuples_skipped` `bigint`

Number of tuples skipped because they contain malformed data. This counter only advances when a value other than `stop` is specified to the `ON_ERROR` option. | ### 27.4.4. CREATE INDEX Progress Reporting [#](https://www.postgresql.org/docs/current/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING) Whenever `CREATE INDEX` or `REINDEX` is running, the `pg_stat_progress_create_index` view will contain one row for each backend that is currently creating indexes. The tables below describe the information that will be reported and provide information about how to interpret it. **Table 27.43. `pg_stat_progress_create_index` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of the backend creating indexes. | | `datid` `oid`

OID of the database to which this backend is connected. | | `datname` `name`

Name of the database to which this backend is connected. | | `relid` `oid`

OID of the table on which the index is being created. | | `index_relid` `oid`

OID of the index being created or reindexed. During a non-concurrent `CREATE INDEX`, this is 0. | | `command` `text`

Specific command type: `CREATE INDEX`, `CREATE INDEX CONCURRENTLY`, `REINDEX`, or `REINDEX CONCURRENTLY`. | | `phase` `text`

Current processing phase of index creation. See [Table 27.44](https://www.postgresql.org/docs/current/progress-reporting.html#CREATE-INDEX-PHASES "Table 27.44. CREATE INDEX Phases")
. | | `lockers_total` `bigint`

Total number of lockers to wait for, when applicable. | | `lockers_done` `bigint`

Number of lockers already waited for. | | `current_locker_pid` `bigint`

Process ID of the locker currently being waited for. | | `blocks_total` `bigint`

Total number of blocks to be processed in the current phase. | | `blocks_done` `bigint`

Number of blocks already processed in the current phase. | | `tuples_total` `bigint`

Total number of tuples to be processed in the current phase. | | `tuples_done` `bigint`

Number of tuples already processed in the current phase. | | `partitions_total` `bigint`

Total number of partitions on which the index is to be created or attached, including both direct and indirect partitions. `0` during a `REINDEX`, or when the index is not partitioned. | | `partitions_done` `bigint`

Number of partitions on which the index has already been created or attached, including both direct and indirect partitions. `0` during a `REINDEX`, or when the index is not partitioned. | **Table 27.44. CREATE INDEX Phases** | Phase | Description | | --- | --- | | `initializing` | `CREATE INDEX` or `REINDEX` is preparing to create the index. This phase is expected to be very brief. | | `waiting for writers before build` | `CREATE INDEX CONCURRENTLY` or `REINDEX CONCURRENTLY` is waiting for transactions with write locks that can potentially see the table to finish. This phase is skipped when not in concurrent mode. Columns `lockers_total`, `lockers_done` and `current_locker_pid` contain the progress information for this phase. | | `building index` | The index is being built by the access method-specific code. In this phase, access methods that support progress reporting fill in their own progress data, and the subphase is indicated in this column. Typically, `blocks_total` and `blocks_done` will contain progress data, as well as potentially `tuples_total` and `tuples_done`. | | `waiting for writers before validation` | `CREATE INDEX CONCURRENTLY` or `REINDEX CONCURRENTLY` is waiting for transactions with write locks that can potentially write into the table to finish. This phase is skipped when not in concurrent mode. Columns `lockers_total`, `lockers_done` and `current_locker_pid` contain the progress information for this phase. | | `index validation: scanning index` | `CREATE INDEX CONCURRENTLY` is scanning the index searching for tuples that need to be validated. This phase is skipped when not in concurrent mode. Columns `blocks_total` (set to the total size of the index) and `blocks_done` contain the progress information for this phase. | | `index validation: sorting tuples` | `CREATE INDEX CONCURRENTLY` is sorting the output of the index scanning phase. | | `index validation: scanning table` | `CREATE INDEX CONCURRENTLY` is scanning the table to validate the index tuples collected in the previous two phases. This phase is skipped when not in concurrent mode. Columns `blocks_total` (set to the total size of the table) and `blocks_done` contain the progress information for this phase. | | `waiting for old snapshots` | `CREATE INDEX CONCURRENTLY` or `REINDEX CONCURRENTLY` is waiting for transactions that can potentially see the table to release their snapshots. This phase is skipped when not in concurrent mode. Columns `lockers_total`, `lockers_done` and `current_locker_pid` contain the progress information for this phase. | | `waiting for readers before marking dead` | `REINDEX CONCURRENTLY` is waiting for transactions with read locks on the table to finish, before marking the old index dead. This phase is skipped when not in concurrent mode. Columns `lockers_total`, `lockers_done` and `current_locker_pid` contain the progress information for this phase. | | `waiting for readers before dropping` | `REINDEX CONCURRENTLY` is waiting for transactions with read locks on the table to finish, before dropping the old index. This phase is skipped when not in concurrent mode. Columns `lockers_total`, `lockers_done` and `current_locker_pid` contain the progress information for this phase. | ### 27.4.5. VACUUM Progress Reporting [#](https://www.postgresql.org/docs/current/progress-reporting.html#VACUUM-PROGRESS-REPORTING) Whenever `VACUUM` is running, the `pg_stat_progress_vacuum` view will contain one row for each backend (including autovacuum worker processes) that is currently vacuuming. The tables below describe the information that will be reported and provide information about how to interpret it. Progress for `VACUUM FULL` commands is reported via `pg_stat_progress_cluster` because both `VACUUM FULL` and `CLUSTER` rewrite the table, while regular `VACUUM` only modifies it in place. See [Section 27.4.2](https://www.postgresql.org/docs/current/progress-reporting.html#CLUSTER-PROGRESS-REPORTING "27.4.2. CLUSTER Progress Reporting") . **Table 27.45. `pg_stat_progress_vacuum` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of backend. | | `datid` `oid`

OID of the database to which this backend is connected. | | `datname` `name`

Name of the database to which this backend is connected. | | `relid` `oid`

OID of the table being vacuumed. | | `phase` `text`

Current processing phase of vacuum. See [Table 27.46](https://www.postgresql.org/docs/current/progress-reporting.html#VACUUM-PHASES "Table 27.46. VACUUM Phases")
. | | `heap_blks_total` `bigint`

Total number of heap blocks in the table. This number is reported as of the beginning of the scan; blocks added later will not be (and need not be) visited by this `VACUUM`. | | `heap_blks_scanned` `bigint`

Number of heap blocks scanned. Because the [visibility map](https://www.postgresql.org/docs/current/storage-vm.html "66.4. Visibility Map")
is used to optimize scans, some blocks will be skipped without inspection; skipped blocks are included in this total, so that this number will eventually become equal to `heap_blks_total` when the vacuum is complete. This counter only advances when the phase is `scanning heap`. | | `heap_blks_vacuumed` `bigint`

Number of heap blocks vacuumed. Unless the table has no indexes, this counter only advances when the phase is `vacuuming heap`. Blocks that contain no dead tuples are skipped, so the counter may sometimes skip forward in large increments. | | `index_vacuum_count` `bigint`

Number of completed index vacuum cycles. | | `max_dead_tuple_bytes` `bigint`

Amount of dead tuple data that we can store before needing to perform an index vacuum cycle, based on [maintenance\_work\_mem](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM)
. | | `dead_tuple_bytes` `bigint`

Amount of dead tuple data collected since the last index vacuum cycle. | | `num_dead_item_ids` `bigint`

Number of dead item identifiers collected since the last index vacuum cycle. | | `indexes_total` `bigint`

Total number of indexes that will be vacuumed or cleaned up. This number is reported at the beginning of the `vacuuming indexes` phase or the `cleaning up indexes` phase. | | `indexes_processed` `bigint`

Number of indexes processed. This counter only advances when the phase is `vacuuming indexes` or `cleaning up indexes`. | | `delay_time` `double precision`

Total time spent sleeping due to cost-based delay (see [Section 19.10.2](https://www.postgresql.org/docs/current/runtime-config-vacuum.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST "19.10.2. Cost-based Vacuum Delay")
), in milliseconds (if [track\_cost\_delay\_timing](https://www.postgresql.org/docs/current/runtime-config-statistics.html#GUC-TRACK-COST-DELAY-TIMING)
is enabled, otherwise zero). This includes the time that any associated parallel workers have slept. However, parallel workers report their sleep time no more frequently than once per second, so the reported value may be slightly stale. | **Table 27.46. VACUUM Phases** | Phase | Description | | --- | --- | | `initializing` | `VACUUM` is preparing to begin scanning the heap. This phase is expected to be very brief. | | `scanning heap` | `VACUUM` is currently scanning the heap. It will prune and defragment each page if required, and possibly perform freezing activity. The `heap_blks_scanned` column can be used to monitor the progress of the scan. | | `vacuuming indexes` | `VACUUM` is currently vacuuming the indexes. If a table has any indexes, this will happen at least once per vacuum, after the heap has been completely scanned. It may happen multiple times per vacuum if [maintenance\_work\_mem](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM)
(or, in the case of autovacuum, [autovacuum\_work\_mem](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM)
if set) is insufficient to store the number of dead tuples found. | | `vacuuming heap` | `VACUUM` is currently vacuuming the heap. Vacuuming the heap is distinct from scanning the heap, and occurs after each instance of vacuuming indexes. If `heap_blks_scanned` is less than `heap_blks_total`, the system will return to scanning the heap after this phase is completed; otherwise, it will begin cleaning up indexes after this phase is completed. | | `cleaning up indexes` | `VACUUM` is currently cleaning up indexes. This occurs after the heap has been completely scanned and all vacuuming of the indexes and the heap has been completed. | | `truncating heap` | `VACUUM` is currently truncating the heap so as to return empty pages at the end of the relation to the operating system. This occurs after cleaning up indexes. | | `performing final cleanup` | `VACUUM` is performing final cleanup. During this phase, `VACUUM` will vacuum the free space map, update statistics in `pg_class`, and report statistics to the cumulative statistics system. When this phase is completed, `VACUUM` will end. | ### 27.4.6. Base Backup Progress Reporting [#](https://www.postgresql.org/docs/current/progress-reporting.html#BASEBACKUP-PROGRESS-REPORTING) Whenever an application like pg\_basebackup is taking a base backup, the `pg_stat_progress_basebackup` view will contain a row for each WAL sender process that is currently running the `BASE_BACKUP` replication command and streaming the backup. The tables below describe the information that will be reported and provide information about how to interpret it. **Table 27.47. `pg_stat_progress_basebackup` View** | Column Type

Description | | --- | | `pid` `integer`

Process ID of a WAL sender process. | | `phase` `text`

Current processing phase. See [Table 27.48](https://www.postgresql.org/docs/current/progress-reporting.html#BASEBACKUP-PHASES "Table 27.48. Base Backup Phases")
. | | `backup_total` `bigint`

Total amount of data that will be streamed. This is estimated and reported as of the beginning of `streaming database files` phase. Note that this is only an approximation since the database may change during `streaming database files` phase and WAL log may be included in the backup later. This is always the same value as `backup_streamed` once the amount of data streamed exceeds the estimated total size. If the estimation is disabled in pg\_basebackup (i.e., `--no-estimate-size` option is specified), this is `NULL`. | | `backup_streamed` `bigint`

Amount of data streamed. This counter only advances when the phase is `streaming database files` or `transferring wal files`. | | `tablespaces_total` `bigint`

Total number of tablespaces that will be streamed. | | `tablespaces_streamed` `bigint`

Number of tablespaces streamed. This counter only advances when the phase is `streaming database files`. | **Table 27.48. Base Backup Phases** | Phase | Description | | --- | --- | | `initializing` | The WAL sender process is preparing to begin the backup. This phase is expected to be very brief. | | `waiting for checkpoint to finish` | The WAL sender process is currently performing `pg_backup_start` to prepare to take a base backup, and waiting for the start-of-backup checkpoint to finish. | | `estimating backup size` | The WAL sender process is currently estimating the total amount of database files that will be streamed as a base backup. | | `streaming database files` | The WAL sender process is currently streaming database files as a base backup. | | `waiting for wal archiving to finish` | The WAL sender process is currently performing `pg_backup_stop` to finish the backup, and waiting for all the WAL files required for the base backup to be successfully archived. If either `--wal-method=none` or `--wal-method=stream` is specified in pg\_basebackup, the backup will end when this phase is completed. | | `transferring wal files` | The WAL sender process is currently transferring all WAL logs generated during the backup. This phase occurs after `waiting for wal archiving to finish` phase if `--wal-method=fetch` is specified in pg\_basebackup. The backup will end when this phase is completed. | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/monitoring-locks.html "27.3. Viewing Locks") | [Up](https://www.postgresql.org/docs/current/monitoring.html "Chapter 27. Monitoring Database Activity") | [Next](https://www.postgresql.org/docs/current/dynamic-trace.html "27.5. Dynamic Tracing") | | 27.3. Viewing Locks | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 27.5. Dynamic Tracing | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/progress-reporting.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 66.6. Database Page Layout November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/storage-page-layout.html "PostgreSQL 18 - 66.6. Database Page Layout") ([18](https://www.postgresql.org/docs/18/storage-page-layout.html "PostgreSQL 18 - 66.6. Database Page Layout") ) / [17](https://www.postgresql.org/docs/17/storage-page-layout.html "PostgreSQL 17 - 66.6. Database Page Layout") / [16](https://www.postgresql.org/docs/16/storage-page-layout.html "PostgreSQL 16 - 66.6. Database Page Layout") / [15](https://www.postgresql.org/docs/15/storage-page-layout.html "PostgreSQL 15 - 66.6. Database Page Layout") / [14](https://www.postgresql.org/docs/14/storage-page-layout.html "PostgreSQL 14 - 66.6. Database Page Layout") Development Versions: [devel](https://www.postgresql.org/docs/devel/storage-page-layout.html "PostgreSQL devel - 66.6. Database Page Layout") Unsupported versions: [13](https://www.postgresql.org/docs/13/storage-page-layout.html "PostgreSQL 13 - 66.6. Database Page Layout") / [12](https://www.postgresql.org/docs/12/storage-page-layout.html "PostgreSQL 12 - 66.6. Database Page Layout") / [11](https://www.postgresql.org/docs/11/storage-page-layout.html "PostgreSQL 11 - 66.6. Database Page Layout") / [10](https://www.postgresql.org/docs/10/storage-page-layout.html "PostgreSQL 10 - 66.6. Database Page Layout") / [9.6](https://www.postgresql.org/docs/9.6/storage-page-layout.html "PostgreSQL 9.6 - 66.6. Database Page Layout") / [9.5](https://www.postgresql.org/docs/9.5/storage-page-layout.html "PostgreSQL 9.5 - 66.6. Database Page Layout") / [9.4](https://www.postgresql.org/docs/9.4/storage-page-layout.html "PostgreSQL 9.4 - 66.6. Database Page Layout") / [9.3](https://www.postgresql.org/docs/9.3/storage-page-layout.html "PostgreSQL 9.3 - 66.6. Database Page Layout") / [9.2](https://www.postgresql.org/docs/9.2/storage-page-layout.html "PostgreSQL 9.2 - 66.6. Database Page Layout") / [9.1](https://www.postgresql.org/docs/9.1/storage-page-layout.html "PostgreSQL 9.1 - 66.6. Database Page Layout") / [9.0](https://www.postgresql.org/docs/9.0/storage-page-layout.html "PostgreSQL 9.0 - 66.6. Database Page Layout") / [8.4](https://www.postgresql.org/docs/8.4/storage-page-layout.html "PostgreSQL 8.4 - 66.6. Database Page Layout") / [8.3](https://www.postgresql.org/docs/8.3/storage-page-layout.html "PostgreSQL 8.3 - 66.6. Database Page Layout") / [8.2](https://www.postgresql.org/docs/8.2/storage-page-layout.html "PostgreSQL 8.2 - 66.6. Database Page Layout") / [8.1](https://www.postgresql.org/docs/8.1/storage-page-layout.html "PostgreSQL 8.1 - 66.6. Database Page Layout") / [8.0](https://www.postgresql.org/docs/8.0/storage-page-layout.html "PostgreSQL 8.0 - 66.6. Database Page Layout") | 66.6. Database Page Layout | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/storage-init.html "66.5. The Initialization Fork") | [Up](https://www.postgresql.org/docs/18/storage.html "Chapter 66. Database Physical Storage") | Chapter 66. Database Physical Storage | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/storage-hot.html "66.7. Heap-Only Tuples (HOT)") | * * * 66.6. Database Page Layout [#](https://www.postgresql.org/docs/18/storage-page-layout.html#STORAGE-PAGE-LAYOUT) ---------------------------------------------------------------------------------------------------------------- [66.6.1. Table Row Layout](https://www.postgresql.org/docs/18/storage-page-layout.html#STORAGE-TUPLE-LAYOUT) This section provides an overview of the page format used within PostgreSQL tables and indexes.[\[19\]](https://www.postgresql.org/docs/18/storage-page-layout.html#ftn.id-1.10.18.8.2.2) Sequences and TOAST tables are formatted just like a regular table. In the following explanation, a _byte_ is assumed to contain 8 bits. In addition, the term _item_ refers to an individual data value that is stored on a page. In a table, an item is a row; in an index, an item is an index entry. Every table and index is stored as an array of _pages_ of a fixed size (usually 8 kB, although a different page size can be selected when compiling the server). In a table, all the pages are logically equivalent, so a particular item (row) can be stored in any page. In indexes, the first page is generally reserved as a _metapage_ holding control information, and there can be different types of pages within the index, depending on the index access method. [Table 66.2](https://www.postgresql.org/docs/18/storage-page-layout.html#PAGE-TABLE "Table 66.2. Overall Page Layout") shows the overall layout of a page. There are five parts to each page. **Table 66.2. Overall Page Layout** | Item | Description | | --- | --- | | PageHeaderData | 24 bytes long. Contains general information about the page, including free space pointers. | | ItemIdData | Array of item identifiers pointing to the actual items. Each entry is an (offset,length) pair. 4 bytes per item. | | Free space | The unallocated space. New item identifiers are allocated from the start of this area, new items from the end. | | Items | The actual items themselves. | | Special space | Index access method specific data. Different methods store different data. Empty in ordinary tables. | The first 24 bytes of each page consists of a page header (`PageHeaderData`). Its format is detailed in [Table 66.3](https://www.postgresql.org/docs/18/storage-page-layout.html#PAGEHEADERDATA-TABLE "Table 66.3. PageHeaderData Layout") . The first field tracks the most recent WAL entry related to this page. The second field contains the page checksum if [`-k`](https://www.postgresql.org/docs/18/app-initdb.html#APP-INITDB-DATA-CHECKSUMS) are enabled. Next is a 2-byte field containing flag bits. This is followed by three 2-byte integer fields (`pd_lower`, `pd_upper`, and `pd_special`). These contain byte offsets from the page start to the start of unallocated space, to the end of unallocated space, and to the start of the special space. The next 2 bytes of the page header, `pd_pagesize_version`, store both the page size and a version indicator. Beginning with PostgreSQL 8.3 the version number is 4; PostgreSQL 8.1 and 8.2 used version number 3; PostgreSQL 8.0 used version number 2; PostgreSQL 7.3 and 7.4 used version number 1; prior releases used version number 0. (The basic page layout and header format has not changed in most of these versions, but the layout of heap row headers has.) The page size is basically only present as a cross-check; there is no support for having more than one page size in an installation. The last field is a hint that shows whether pruning the page is likely to be profitable: it tracks the oldest un-pruned XMAX on the page. **Table 66.3. PageHeaderData Layout** | Field | Type | Length | Description | | --- | --- | --- | --- | | pd\_lsn | PageXLogRecPtr | 8 bytes | LSN: next byte after last byte of WAL record for last change to this page | | pd\_checksum | uint16 | 2 bytes | Page checksum | | pd\_flags | uint16 | 2 bytes | Flag bits | | pd\_lower | LocationIndex | 2 bytes | Offset to start of free space | | pd\_upper | LocationIndex | 2 bytes | Offset to end of free space | | pd\_special | LocationIndex | 2 bytes | Offset to start of special space | | pd\_pagesize\_version | uint16 | 2 bytes | Page size and layout version number information | | pd\_prune\_xid | TransactionId | 4 bytes | Oldest unpruned XMAX on page, or zero if none | All the details can be found in `src/include/storage/bufpage.h`. Following the page header are item identifiers (`ItemIdData`), each requiring four bytes. An item identifier contains a byte-offset to the start of an item, its length in bytes, and a few attribute bits which affect its interpretation. New item identifiers are allocated as needed from the beginning of the unallocated space. The number of item identifiers present can be determined by looking at `pd_lower`, which is increased to allocate a new identifier. Because an item identifier is never moved until it is freed, its index can be used on a long-term basis to reference an item, even when the item itself is moved around on the page to compact free space. In fact, every pointer to an item (`ItemPointer`, also known as `CTID`) created by PostgreSQL consists of a page number and the index of an item identifier. The items themselves are stored in space allocated backwards from the end of unallocated space. The exact structure varies depending on what the table is to contain. Tables and sequences both use a structure named `HeapTupleHeaderData`, described below. The final section is the “special section” which can contain anything the access method wishes to store. For example, b-tree indexes store links to the page's left and right siblings, as well as some other data relevant to the index structure. Ordinary tables do not use a special section at all (indicated by setting `pd_special` to equal the page size). [Figure 66.1](https://www.postgresql.org/docs/18/storage-page-layout.html#STORAGE-PAGE-LAYOUT-FIGURE "Figure 66.1. Page Layout") illustrates how these parts are laid out in a page. **Figure 66.1. Page Layout** ### 66.6.1. Table Row Layout [#](https://www.postgresql.org/docs/18/storage-page-layout.html#STORAGE-TUPLE-LAYOUT) All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in [Table 66.4](https://www.postgresql.org/docs/18/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE "Table 66.4. HeapTupleHeaderData Layout") . The actual user data (columns of the row) begins at the offset indicated by `t_hoff`, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the _HEAP\_HASNULL_ bit is set in `t_infomask`. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in `t_infomask2`). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the _HEAP\_HASOID\_OLD_ bit is set in `t_infomask`. If present, it appears just before the `t_hoff` boundary. Any padding needed to make `t_hoff` a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.) **Table 66.4. HeapTupleHeaderData Layout** | Field | Type | Length | Description | | --- | --- | --- | --- | | t\_xmin | TransactionId | 4 bytes | insert XID stamp | | t\_xmax | TransactionId | 4 bytes | delete XID stamp | | t\_cid | CommandId | 4 bytes | insert and/or delete CID stamp (overlays with t\_xvac) | | t\_xvac | TransactionId | 4 bytes | XID for VACUUM operation moving a row version | | t\_ctid | ItemPointerData | 6 bytes | current TID of this or newer row version | | t\_infomask2 | uint16 | 2 bytes | number of attributes, plus various flag bits | | t\_infomask | uint16 | 2 bytes | various flag bits | | t\_hoff | uint8 | 1 byte | offset to user data | All the details can be found in `src/include/access/htup_details.h`. Interpreting the actual data can only be done with information obtained from other tables, mostly `pg_attribute`. The key values needed to identify field locations are `attlen` and `attalign`. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions _heap\_getattr_, _fastgetattr_ and _heap\_getsysattr_. To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure `struct varlena`, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see [Section 66.2](https://www.postgresql.org/docs/18/storage-toast.html "66.2. TOAST") ). * * * [\[19\]](https://www.postgresql.org/docs/18/storage-page-layout.html#id-1.10.18.8.2.2) Actually, use of this page format is not required for either table or index access methods. The `heap` table access method always uses this format. All the existing index methods also use the basic format, but the data kept on index metapages usually doesn't follow the item layout rules. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/storage-init.html "66.5. The Initialization Fork") | [Up](https://www.postgresql.org/docs/18/storage.html "Chapter 66. Database Physical Storage") | [Next](https://www.postgresql.org/docs/18/storage-hot.html "66.7. Heap-Only Tuples (HOT)") | | 66.5. The Initialization Fork | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 66.7. Heap-Only Tuples (HOT) | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/storage-page-layout.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 52.40. pg_publication November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-publication.html "PostgreSQL 18 - 52.40. pg_publication") ([18](https://www.postgresql.org/docs/18/catalog-pg-publication.html "PostgreSQL 18 - 52.40. pg_publication") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-publication.html "PostgreSQL 17 - 52.40. pg_publication") / [16](https://www.postgresql.org/docs/16/catalog-pg-publication.html "PostgreSQL 16 - 52.40. pg_publication") / [15](https://www.postgresql.org/docs/15/catalog-pg-publication.html "PostgreSQL 15 - 52.40. pg_publication") / [14](https://www.postgresql.org/docs/14/catalog-pg-publication.html "PostgreSQL 14 - 52.40. pg_publication") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-publication.html "PostgreSQL devel - 52.40. pg_publication") Unsupported versions: [13](https://www.postgresql.org/docs/13/catalog-pg-publication.html "PostgreSQL 13 - 52.40. pg_publication") / [12](https://www.postgresql.org/docs/12/catalog-pg-publication.html "PostgreSQL 12 - 52.40. pg_publication") / [11](https://www.postgresql.org/docs/11/catalog-pg-publication.html "PostgreSQL 11 - 52.40. pg_publication") / [10](https://www.postgresql.org/docs/10/catalog-pg-publication.html "PostgreSQL 10 - 52.40. pg_publication") | 52.40. `pg_publication` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/catalog-pg-proc.html "52.39. pg_proc") | [Up](https://www.postgresql.org/docs/18/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/catalog-pg-publication-namespace.html "52.41. pg_publication_namespace") | * * * 52.40. `pg_publication` [#](https://www.postgresql.org/docs/18/catalog-pg-publication.html#CATALOG-PG-PUBLICATION) ------------------------------------------------------------------------------------------------------------------- The catalog `pg_publication` contains all publications created in the database. For more on publications see [Section 29.1](https://www.postgresql.org/docs/18/logical-replication-publication.html "29.1. Publication") . **Table 52.40. `pg_publication` Columns** | Column Type

Description | | --- | | `oid` `oid`

Row identifier | | `pubname` `name`

Name of the publication | | `pubowner` `oid` (references [`pg_authid`](https://www.postgresql.org/docs/18/catalog-pg-authid.html "52.8. pg_authid")
.`oid`)

Owner of the publication | | `puballtables` `bool`

If true, this publication automatically includes all tables in the database, including any that will be created in the future. | | `pubinsert` `bool`

If true, [INSERT](https://www.postgresql.org/docs/18/sql-insert.html "INSERT")
operations are replicated for tables in the publication. | | `pubupdate` `bool`

If true, [UPDATE](https://www.postgresql.org/docs/18/sql-update.html "UPDATE")
operations are replicated for tables in the publication. | | `pubdelete` `bool`

If true, [DELETE](https://www.postgresql.org/docs/18/sql-delete.html "DELETE")
operations are replicated for tables in the publication. | | `pubtruncate` `bool`

If true, [TRUNCATE](https://www.postgresql.org/docs/18/sql-truncate.html "TRUNCATE")
operations are replicated for tables in the publication. | | `pubviaroot` `bool`

If true, operations on a leaf partition are replicated using the identity and schema of its topmost partitioned ancestor mentioned in the publication instead of its own. | | `pubgencols` `char`

Controls how to handle generated column replication when there is no publication column list: `n` = generated columns in the tables associated with the publication should not be replicated, `s` = stored generated columns in the tables associated with the publication should be replicated. | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/catalog-pg-proc.html "52.39. pg_proc") | [Up](https://www.postgresql.org/docs/18/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/18/catalog-pg-publication-namespace.html "52.41. pg_publication_namespace") | | 52.39. `pg_proc` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 52.41. `pg_publication_namespace` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/catalog-pg-publication.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 66.6. Database Page Layout November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/storage-page-layout.html "PostgreSQL 18 - 66.6. Database Page Layout") ([18](https://www.postgresql.org/docs/18/storage-page-layout.html "PostgreSQL 18 - 66.6. Database Page Layout") ) / [17](https://www.postgresql.org/docs/17/storage-page-layout.html "PostgreSQL 17 - 66.6. Database Page Layout") / [16](https://www.postgresql.org/docs/16/storage-page-layout.html "PostgreSQL 16 - 66.6. Database Page Layout") / [15](https://www.postgresql.org/docs/15/storage-page-layout.html "PostgreSQL 15 - 66.6. Database Page Layout") / [14](https://www.postgresql.org/docs/14/storage-page-layout.html "PostgreSQL 14 - 66.6. Database Page Layout") Development Versions: [devel](https://www.postgresql.org/docs/devel/storage-page-layout.html "PostgreSQL devel - 66.6. Database Page Layout") Unsupported versions: [13](https://www.postgresql.org/docs/13/storage-page-layout.html "PostgreSQL 13 - 66.6. Database Page Layout") / [12](https://www.postgresql.org/docs/12/storage-page-layout.html "PostgreSQL 12 - 66.6. Database Page Layout") / [11](https://www.postgresql.org/docs/11/storage-page-layout.html "PostgreSQL 11 - 66.6. Database Page Layout") / [10](https://www.postgresql.org/docs/10/storage-page-layout.html "PostgreSQL 10 - 66.6. Database Page Layout") / [9.6](https://www.postgresql.org/docs/9.6/storage-page-layout.html "PostgreSQL 9.6 - 66.6. Database Page Layout") / [9.5](https://www.postgresql.org/docs/9.5/storage-page-layout.html "PostgreSQL 9.5 - 66.6. Database Page Layout") / [9.4](https://www.postgresql.org/docs/9.4/storage-page-layout.html "PostgreSQL 9.4 - 66.6. Database Page Layout") / [9.3](https://www.postgresql.org/docs/9.3/storage-page-layout.html "PostgreSQL 9.3 - 66.6. Database Page Layout") / [9.2](https://www.postgresql.org/docs/9.2/storage-page-layout.html "PostgreSQL 9.2 - 66.6. Database Page Layout") / [9.1](https://www.postgresql.org/docs/9.1/storage-page-layout.html "PostgreSQL 9.1 - 66.6. Database Page Layout") / [9.0](https://www.postgresql.org/docs/9.0/storage-page-layout.html "PostgreSQL 9.0 - 66.6. Database Page Layout") / [8.4](https://www.postgresql.org/docs/8.4/storage-page-layout.html "PostgreSQL 8.4 - 66.6. Database Page Layout") / [8.3](https://www.postgresql.org/docs/8.3/storage-page-layout.html "PostgreSQL 8.3 - 66.6. Database Page Layout") / [8.2](https://www.postgresql.org/docs/8.2/storage-page-layout.html "PostgreSQL 8.2 - 66.6. Database Page Layout") / [8.1](https://www.postgresql.org/docs/8.1/storage-page-layout.html "PostgreSQL 8.1 - 66.6. Database Page Layout") / [8.0](https://www.postgresql.org/docs/8.0/storage-page-layout.html "PostgreSQL 8.0 - 66.6. Database Page Layout") | 66.6. Database Page Layout | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/storage-init.html "66.5. The Initialization Fork") | [Up](https://www.postgresql.org/docs/current/storage.html "Chapter 66. Database Physical Storage") | Chapter 66. Database Physical Storage | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/storage-hot.html "66.7. Heap-Only Tuples (HOT)") | * * * 66.6. Database Page Layout [#](https://www.postgresql.org/docs/current/storage-page-layout.html#STORAGE-PAGE-LAYOUT) --------------------------------------------------------------------------------------------------------------------- [66.6.1. Table Row Layout](https://www.postgresql.org/docs/current/storage-page-layout.html#STORAGE-TUPLE-LAYOUT) This section provides an overview of the page format used within PostgreSQL tables and indexes.[\[19\]](https://www.postgresql.org/docs/current/storage-page-layout.html#ftn.id-1.10.18.8.2.2) Sequences and TOAST tables are formatted just like a regular table. In the following explanation, a _byte_ is assumed to contain 8 bits. In addition, the term _item_ refers to an individual data value that is stored on a page. In a table, an item is a row; in an index, an item is an index entry. Every table and index is stored as an array of _pages_ of a fixed size (usually 8 kB, although a different page size can be selected when compiling the server). In a table, all the pages are logically equivalent, so a particular item (row) can be stored in any page. In indexes, the first page is generally reserved as a _metapage_ holding control information, and there can be different types of pages within the index, depending on the index access method. [Table 66.2](https://www.postgresql.org/docs/current/storage-page-layout.html#PAGE-TABLE "Table 66.2. Overall Page Layout") shows the overall layout of a page. There are five parts to each page. **Table 66.2. Overall Page Layout** | Item | Description | | --- | --- | | PageHeaderData | 24 bytes long. Contains general information about the page, including free space pointers. | | ItemIdData | Array of item identifiers pointing to the actual items. Each entry is an (offset,length) pair. 4 bytes per item. | | Free space | The unallocated space. New item identifiers are allocated from the start of this area, new items from the end. | | Items | The actual items themselves. | | Special space | Index access method specific data. Different methods store different data. Empty in ordinary tables. | The first 24 bytes of each page consists of a page header (`PageHeaderData`). Its format is detailed in [Table 66.3](https://www.postgresql.org/docs/current/storage-page-layout.html#PAGEHEADERDATA-TABLE "Table 66.3. PageHeaderData Layout") . The first field tracks the most recent WAL entry related to this page. The second field contains the page checksum if [`-k`](https://www.postgresql.org/docs/current/app-initdb.html#APP-INITDB-DATA-CHECKSUMS) are enabled. Next is a 2-byte field containing flag bits. This is followed by three 2-byte integer fields (`pd_lower`, `pd_upper`, and `pd_special`). These contain byte offsets from the page start to the start of unallocated space, to the end of unallocated space, and to the start of the special space. The next 2 bytes of the page header, `pd_pagesize_version`, store both the page size and a version indicator. Beginning with PostgreSQL 8.3 the version number is 4; PostgreSQL 8.1 and 8.2 used version number 3; PostgreSQL 8.0 used version number 2; PostgreSQL 7.3 and 7.4 used version number 1; prior releases used version number 0. (The basic page layout and header format has not changed in most of these versions, but the layout of heap row headers has.) The page size is basically only present as a cross-check; there is no support for having more than one page size in an installation. The last field is a hint that shows whether pruning the page is likely to be profitable: it tracks the oldest un-pruned XMAX on the page. **Table 66.3. PageHeaderData Layout** | Field | Type | Length | Description | | --- | --- | --- | --- | | pd\_lsn | PageXLogRecPtr | 8 bytes | LSN: next byte after last byte of WAL record for last change to this page | | pd\_checksum | uint16 | 2 bytes | Page checksum | | pd\_flags | uint16 | 2 bytes | Flag bits | | pd\_lower | LocationIndex | 2 bytes | Offset to start of free space | | pd\_upper | LocationIndex | 2 bytes | Offset to end of free space | | pd\_special | LocationIndex | 2 bytes | Offset to start of special space | | pd\_pagesize\_version | uint16 | 2 bytes | Page size and layout version number information | | pd\_prune\_xid | TransactionId | 4 bytes | Oldest unpruned XMAX on page, or zero if none | All the details can be found in `src/include/storage/bufpage.h`. Following the page header are item identifiers (`ItemIdData`), each requiring four bytes. An item identifier contains a byte-offset to the start of an item, its length in bytes, and a few attribute bits which affect its interpretation. New item identifiers are allocated as needed from the beginning of the unallocated space. The number of item identifiers present can be determined by looking at `pd_lower`, which is increased to allocate a new identifier. Because an item identifier is never moved until it is freed, its index can be used on a long-term basis to reference an item, even when the item itself is moved around on the page to compact free space. In fact, every pointer to an item (`ItemPointer`, also known as `CTID`) created by PostgreSQL consists of a page number and the index of an item identifier. The items themselves are stored in space allocated backwards from the end of unallocated space. The exact structure varies depending on what the table is to contain. Tables and sequences both use a structure named `HeapTupleHeaderData`, described below. The final section is the “special section” which can contain anything the access method wishes to store. For example, b-tree indexes store links to the page's left and right siblings, as well as some other data relevant to the index structure. Ordinary tables do not use a special section at all (indicated by setting `pd_special` to equal the page size). [Figure 66.1](https://www.postgresql.org/docs/current/storage-page-layout.html#STORAGE-PAGE-LAYOUT-FIGURE "Figure 66.1. Page Layout") illustrates how these parts are laid out in a page. **Figure 66.1. Page Layout** ### 66.6.1. Table Row Layout [#](https://www.postgresql.org/docs/current/storage-page-layout.html#STORAGE-TUPLE-LAYOUT) All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in [Table 66.4](https://www.postgresql.org/docs/current/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE "Table 66.4. HeapTupleHeaderData Layout") . The actual user data (columns of the row) begins at the offset indicated by `t_hoff`, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the _HEAP\_HASNULL_ bit is set in `t_infomask`. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in `t_infomask2`). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the _HEAP\_HASOID\_OLD_ bit is set in `t_infomask`. If present, it appears just before the `t_hoff` boundary. Any padding needed to make `t_hoff` a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.) **Table 66.4. HeapTupleHeaderData Layout** | Field | Type | Length | Description | | --- | --- | --- | --- | | t\_xmin | TransactionId | 4 bytes | insert XID stamp | | t\_xmax | TransactionId | 4 bytes | delete XID stamp | | t\_cid | CommandId | 4 bytes | insert and/or delete CID stamp (overlays with t\_xvac) | | t\_xvac | TransactionId | 4 bytes | XID for VACUUM operation moving a row version | | t\_ctid | ItemPointerData | 6 bytes | current TID of this or newer row version | | t\_infomask2 | uint16 | 2 bytes | number of attributes, plus various flag bits | | t\_infomask | uint16 | 2 bytes | various flag bits | | t\_hoff | uint8 | 1 byte | offset to user data | All the details can be found in `src/include/access/htup_details.h`. Interpreting the actual data can only be done with information obtained from other tables, mostly `pg_attribute`. The key values needed to identify field locations are `attlen` and `attalign`. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions _heap\_getattr_, _fastgetattr_ and _heap\_getsysattr_. To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure `struct varlena`, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see [Section 66.2](https://www.postgresql.org/docs/current/storage-toast.html "66.2. TOAST") ). * * * [\[19\]](https://www.postgresql.org/docs/current/storage-page-layout.html#id-1.10.18.8.2.2) Actually, use of this page format is not required for either table or index access methods. The `heap` table access method always uses this format. All the existing index methods also use the basic format, but the data kept on index metapages usually doesn't follow the item layout rules. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/storage-init.html "66.5. The Initialization Fork") | [Up](https://www.postgresql.org/docs/current/storage.html "Chapter 66. Database Physical Storage") | [Next](https://www.postgresql.org/docs/current/storage-hot.html "66.7. Heap-Only Tuples (HOT)") | | 66.5. The Initialization Fork | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 66.7. Heap-Only Tuples (HOT) | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/storage-page-layout.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 21.4. Dropping Roles November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/role-removal.html "PostgreSQL 18 - 21.4. Dropping Roles") ([18](https://www.postgresql.org/docs/18/role-removal.html "PostgreSQL 18 - 21.4. Dropping Roles") ) / [17](https://www.postgresql.org/docs/17/role-removal.html "PostgreSQL 17 - 21.4. Dropping Roles") / [16](https://www.postgresql.org/docs/16/role-removal.html "PostgreSQL 16 - 21.4. Dropping Roles") / [15](https://www.postgresql.org/docs/15/role-removal.html "PostgreSQL 15 - 21.4. Dropping Roles") / [14](https://www.postgresql.org/docs/14/role-removal.html "PostgreSQL 14 - 21.4. Dropping Roles") Development Versions: [devel](https://www.postgresql.org/docs/devel/role-removal.html "PostgreSQL devel - 21.4. Dropping Roles") Unsupported versions: [13](https://www.postgresql.org/docs/13/role-removal.html "PostgreSQL 13 - 21.4. Dropping Roles") / [12](https://www.postgresql.org/docs/12/role-removal.html "PostgreSQL 12 - 21.4. Dropping Roles") / [11](https://www.postgresql.org/docs/11/role-removal.html "PostgreSQL 11 - 21.4. Dropping Roles") / [10](https://www.postgresql.org/docs/10/role-removal.html "PostgreSQL 10 - 21.4. Dropping Roles") / [9.6](https://www.postgresql.org/docs/9.6/role-removal.html "PostgreSQL 9.6 - 21.4. Dropping Roles") / [9.5](https://www.postgresql.org/docs/9.5/role-removal.html "PostgreSQL 9.5 - 21.4. Dropping Roles") / [9.4](https://www.postgresql.org/docs/9.4/role-removal.html "PostgreSQL 9.4 - 21.4. Dropping Roles") / [9.3](https://www.postgresql.org/docs/9.3/role-removal.html "PostgreSQL 9.3 - 21.4. Dropping Roles") / [9.2](https://www.postgresql.org/docs/9.2/role-removal.html "PostgreSQL 9.2 - 21.4. Dropping Roles") / [9.1](https://www.postgresql.org/docs/9.1/role-removal.html "PostgreSQL 9.1 - 21.4. Dropping Roles") | 21.4. Dropping Roles | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/role-membership.html "21.3. Role Membership") | [Up](https://www.postgresql.org/docs/18/user-manag.html "Chapter 21. Database Roles") | Chapter 21. Database Roles | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/predefined-roles.html "21.5. Predefined Roles") | * * * 21.4. Dropping Roles [#](https://www.postgresql.org/docs/18/role-removal.html#ROLE-REMOVAL) -------------------------------------------------------------------------------------------- Because roles can own database objects and can hold privileges to access other objects, dropping a role is often not just a matter of a quick [`DROP ROLE`](https://www.postgresql.org/docs/18/sql-droprole.html "DROP ROLE") . Any objects owned by the role must first be dropped or reassigned to other owners; and any permissions granted to the role must be revoked. Ownership of objects can be transferred one at a time using `ALTER` commands, for example: ALTER TABLE bobs\_table OWNER TO alice; Alternatively, the [`REASSIGN OWNED`](https://www.postgresql.org/docs/18/sql-reassign-owned.html "REASSIGN OWNED") command can be used to reassign ownership of all objects owned by the role-to-be-dropped to a single other role. Because `REASSIGN OWNED` cannot access objects in other databases, it is necessary to run it in each database that contains objects owned by the role. (Note that the first such `REASSIGN OWNED` will change the ownership of any shared-across-databases objects, that is databases or tablespaces, that are owned by the role-to-be-dropped.) Once any valuable objects have been transferred to new owners, any remaining objects owned by the role-to-be-dropped can be dropped with the [`DROP OWNED`](https://www.postgresql.org/docs/18/sql-drop-owned.html "DROP OWNED") command. Again, this command cannot access objects in other databases, so it is necessary to run it in each database that contains objects owned by the role. Also, `DROP OWNED` will not drop entire databases or tablespaces, so it is necessary to do that manually if the role owns any databases or tablespaces that have not been transferred to new owners. `DROP OWNED` also takes care of removing any privileges granted to the target role for objects that do not belong to it. Because `REASSIGN OWNED` does not touch such objects, it's typically necessary to run both `REASSIGN OWNED` and `DROP OWNED` (in that order!) to fully remove the dependencies of a role to be dropped. In short then, the most general recipe for removing a role that has been used to own objects is: REASSIGN OWNED BY doomed\_role TO successor\_role; DROP OWNED BY doomed\_role; -- repeat the above commands in each database of the cluster DROP ROLE doomed\_role; When not all owned objects are to be transferred to the same successor owner, it's best to handle the exceptions manually and then perform the above steps to mop up. If `DROP ROLE` is attempted while dependent objects still remain, it will issue messages identifying which objects need to be reassigned or dropped. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/role-membership.html "21.3. Role Membership") | [Up](https://www.postgresql.org/docs/18/user-manag.html "Chapter 21. Database Roles") | [Next](https://www.postgresql.org/docs/18/predefined-roles.html "21.5. Predefined Roles") | | 21.3. Role Membership | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 21.5. Predefined Roles | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/role-removal.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.14. earthdistance — calculate great-circle distances November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/earthdistance.html "PostgreSQL 18 - F.14. earthdistance — calculate great-circle distances") ([18](https://www.postgresql.org/docs/18/earthdistance.html "PostgreSQL 18 - F.14. earthdistance — calculate great-circle distances") ) / [17](https://www.postgresql.org/docs/17/earthdistance.html "PostgreSQL 17 - F.14. earthdistance — calculate great-circle distances") / [16](https://www.postgresql.org/docs/16/earthdistance.html "PostgreSQL 16 - F.14. earthdistance — calculate great-circle distances") / [15](https://www.postgresql.org/docs/15/earthdistance.html "PostgreSQL 15 - F.14. earthdistance — calculate great-circle distances") / [14](https://www.postgresql.org/docs/14/earthdistance.html "PostgreSQL 14 - F.14. earthdistance — calculate great-circle distances") Development Versions: [devel](https://www.postgresql.org/docs/devel/earthdistance.html "PostgreSQL devel - F.14. earthdistance — calculate great-circle distances") Unsupported versions: [13](https://www.postgresql.org/docs/13/earthdistance.html "PostgreSQL 13 - F.14. earthdistance — calculate great-circle distances") / [12](https://www.postgresql.org/docs/12/earthdistance.html "PostgreSQL 12 - F.14. earthdistance — calculate great-circle distances") / [11](https://www.postgresql.org/docs/11/earthdistance.html "PostgreSQL 11 - F.14. earthdistance — calculate great-circle distances") / [10](https://www.postgresql.org/docs/10/earthdistance.html "PostgreSQL 10 - F.14. earthdistance — calculate great-circle distances") / [9.6](https://www.postgresql.org/docs/9.6/earthdistance.html "PostgreSQL 9.6 - F.14. earthdistance — calculate great-circle distances") / [9.5](https://www.postgresql.org/docs/9.5/earthdistance.html "PostgreSQL 9.5 - F.14. earthdistance — calculate great-circle distances") / [9.4](https://www.postgresql.org/docs/9.4/earthdistance.html "PostgreSQL 9.4 - F.14. earthdistance — calculate great-circle distances") / [9.3](https://www.postgresql.org/docs/9.3/earthdistance.html "PostgreSQL 9.3 - F.14. earthdistance — calculate great-circle distances") / [9.2](https://www.postgresql.org/docs/9.2/earthdistance.html "PostgreSQL 9.2 - F.14. earthdistance — calculate great-circle distances") / [9.1](https://www.postgresql.org/docs/9.1/earthdistance.html "PostgreSQL 9.1 - F.14. earthdistance — calculate great-circle distances") / [9.0](https://www.postgresql.org/docs/9.0/earthdistance.html "PostgreSQL 9.0 - F.14. earthdistance — calculate great-circle distances") / [8.4](https://www.postgresql.org/docs/8.4/earthdistance.html "PostgreSQL 8.4 - F.14. earthdistance — calculate great-circle distances") / [8.3](https://www.postgresql.org/docs/8.3/earthdistance.html "PostgreSQL 8.3 - F.14. earthdistance — calculate great-circle distances") | F.14. earthdistance — calculate great-circle distances | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/dict-xsyn.html "F.13. dict_xsyn — example synonym full-text search dictionary") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/file-fdw.html "F.15. file_fdw — access data files in the server's file system") | * * * F.14. earthdistance — calculate great-circle distances [#](https://www.postgresql.org/docs/18/earthdistance.html#EARTHDISTANCE) -------------------------------------------------------------------------------------------------------------------------------- [F.14.1. Cube-Based Earth Distances](https://www.postgresql.org/docs/18/earthdistance.html#EARTHDISTANCE-CUBE-BASED) [F.14.2. Point-Based Earth Distances](https://www.postgresql.org/docs/18/earthdistance.html#EARTHDISTANCE-POINT-BASED) The `earthdistance` module provides two different approaches to calculating great circle distances on the surface of the Earth. The one described first depends on the `cube` module. The second one is based on the built-in `point` data type, using longitude and latitude for the coordinates. In this module, the Earth is assumed to be perfectly spherical. (If that's too inaccurate for you, you might want to look at the [PostGIS](https://postgis.net/) project.) The `cube` module must be installed before `earthdistance` can be installed (although you can use the `CASCADE` option of `CREATE EXTENSION` to install both in one command). ### Caution It is strongly recommended that `earthdistance` and `cube` be installed in the same schema, and that that schema be one for which CREATE privilege has not been and will not be granted to any untrusted users. Otherwise there are installation-time security hazards if `earthdistance`'s schema contains objects defined by a hostile user. Furthermore, when using `earthdistance`'s functions after installation, the entire search path should contain only trusted schemas. ### F.14.1. Cube-Based Earth Distances [#](https://www.postgresql.org/docs/18/earthdistance.html#EARTHDISTANCE-CUBE-BASED) Data is stored in cubes that are points (both corners are the same) using 3 coordinates representing the x, y, and z distance from the center of the Earth. A [](https://www.postgresql.org/docs/18/glossary.html#GLOSSARY-DOMAIN) [domain](https://www.postgresql.org/docs/18/glossary.html#GLOSSARY-DOMAIN "Domain") `earth` over type `cube` is provided, which includes constraint checks that the value meets these restrictions and is reasonably close to the actual surface of the Earth. The radius of the Earth is obtained from the `earth()` function. It is given in meters. But by changing this one function you can change the module to use some other units, or to use a different value of the radius that you feel is more appropriate. This package has applications to astronomical databases as well. Astronomers will probably want to change `earth()` to return a radius of `180/pi()` so that distances are in degrees. Functions are provided to support input in latitude and longitude (in degrees), to support output of latitude and longitude, to calculate the great circle distance between two points and to easily specify a bounding box usable for index searches. The provided functions are shown in [Table F.4](https://www.postgresql.org/docs/18/earthdistance.html#EARTHDISTANCE-CUBE-FUNCTIONS "Table F.4. Cube-Based Earthdistance Functions") . **Table F.4. Cube-Based Earthdistance Functions** | Function

Description | | --- | | `earth` () → `float8`

Returns the assumed radius of the Earth. | | `sec_to_gc` ( `float8` ) → `float8`

Converts the normal straight line (secant) distance between two points on the surface of the Earth to the great circle distance between them. | | `gc_to_sec` ( `float8` ) → `float8`

Converts the great circle distance between two points on the surface of the Earth to the normal straight line (secant) distance between them. | | `ll_to_earth` ( `float8`, `float8` ) → `earth`

Returns the location of a point on the surface of the Earth given its latitude (argument 1) and longitude (argument 2) in degrees. | | `latitude` ( `earth` ) → `float8`

Returns the latitude in degrees of a point on the surface of the Earth. | | `longitude` ( `earth` ) → `float8`

Returns the longitude in degrees of a point on the surface of the Earth. | | `earth_distance` ( `earth`, `earth` ) → `float8`

Returns the great circle distance between two points on the surface of the Earth. | | `earth_box` ( `earth`, `float8` ) → `cube`

Returns a box suitable for an indexed search using the `cube` `@>` operator for points within a given great circle distance of a location. Some points in this box are further than the specified great circle distance from the location, so a second check using `earth_distance` should be included in the query. | ### F.14.2. Point-Based Earth Distances [#](https://www.postgresql.org/docs/18/earthdistance.html#EARTHDISTANCE-POINT-BASED) The second part of the module relies on representing Earth locations as values of type `point`, in which the first component is taken to represent longitude in degrees, and the second component is taken to represent latitude in degrees. Points are taken as (longitude, latitude) and not vice versa because longitude is closer to the intuitive idea of x-axis and latitude to y-axis. A single operator is provided, shown in [Table F.5](https://www.postgresql.org/docs/18/earthdistance.html#EARTHDISTANCE-POINT-OPERATORS "Table F.5. Point-Based Earthdistance Operators") . **Table F.5. Point-Based Earthdistance Operators** | Operator

Description | | --- | | `point` `<@>` `point` → `float8`

Computes the distance in statute miles between two points on the Earth's surface. | Note that unlike the `cube`\-based part of the module, units are hardwired here: changing the `earth()` function will not affect the results of this operator. One disadvantage of the longitude/latitude representation is that you need to be careful about the edge conditions near the poles and near +/- 180 degrees of longitude. The `cube`\-based representation avoids these discontinuities. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/dict-xsyn.html "F.13. dict_xsyn — example synonym full-text search dictionary") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/18/file-fdw.html "F.15. file_fdw — access data files in the server's file system") | | F.13. dict\_xsyn — example synonym full-text search dictionary | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | F.15. file\_fdw — access data files in the server's file system | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/earthdistance.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 52.40. pg_publication November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-publication.html "PostgreSQL 18 - 52.40. pg_publication") ([18](https://www.postgresql.org/docs/18/catalog-pg-publication.html "PostgreSQL 18 - 52.40. pg_publication") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-publication.html "PostgreSQL 17 - 52.40. pg_publication") / [16](https://www.postgresql.org/docs/16/catalog-pg-publication.html "PostgreSQL 16 - 52.40. pg_publication") / [15](https://www.postgresql.org/docs/15/catalog-pg-publication.html "PostgreSQL 15 - 52.40. pg_publication") / [14](https://www.postgresql.org/docs/14/catalog-pg-publication.html "PostgreSQL 14 - 52.40. pg_publication") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-publication.html "PostgreSQL devel - 52.40. pg_publication") Unsupported versions: [13](https://www.postgresql.org/docs/13/catalog-pg-publication.html "PostgreSQL 13 - 52.40. pg_publication") / [12](https://www.postgresql.org/docs/12/catalog-pg-publication.html "PostgreSQL 12 - 52.40. pg_publication") / [11](https://www.postgresql.org/docs/11/catalog-pg-publication.html "PostgreSQL 11 - 52.40. pg_publication") / [10](https://www.postgresql.org/docs/10/catalog-pg-publication.html "PostgreSQL 10 - 52.40. pg_publication") | 52.40. `pg_publication` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-proc.html "52.39. pg_proc") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/catalog-pg-publication-namespace.html "52.41. pg_publication_namespace") | * * * 52.40. `pg_publication` [#](https://www.postgresql.org/docs/current/catalog-pg-publication.html#CATALOG-PG-PUBLICATION) ------------------------------------------------------------------------------------------------------------------------ The catalog `pg_publication` contains all publications created in the database. For more on publications see [Section 29.1](https://www.postgresql.org/docs/current/logical-replication-publication.html "29.1. Publication") . **Table 52.40. `pg_publication` Columns** | Column Type

Description | | --- | | `oid` `oid`

Row identifier | | `pubname` `name`

Name of the publication | | `pubowner` `oid` (references [`pg_authid`](https://www.postgresql.org/docs/current/catalog-pg-authid.html "52.8. pg_authid")
.`oid`)

Owner of the publication | | `puballtables` `bool`

If true, this publication automatically includes all tables in the database, including any that will be created in the future. | | `pubinsert` `bool`

If true, [INSERT](https://www.postgresql.org/docs/current/sql-insert.html "INSERT")
operations are replicated for tables in the publication. | | `pubupdate` `bool`

If true, [UPDATE](https://www.postgresql.org/docs/current/sql-update.html "UPDATE")
operations are replicated for tables in the publication. | | `pubdelete` `bool`

If true, [DELETE](https://www.postgresql.org/docs/current/sql-delete.html "DELETE")
operations are replicated for tables in the publication. | | `pubtruncate` `bool`

If true, [TRUNCATE](https://www.postgresql.org/docs/current/sql-truncate.html "TRUNCATE")
operations are replicated for tables in the publication. | | `pubviaroot` `bool`

If true, operations on a leaf partition are replicated using the identity and schema of its topmost partitioned ancestor mentioned in the publication instead of its own. | | `pubgencols` `char`

Controls how to handle generated column replication when there is no publication column list: `n` = generated columns in the tables associated with the publication should not be replicated, `s` = stored generated columns in the tables associated with the publication should be replicated. | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-proc.html "52.39. pg_proc") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/current/catalog-pg-publication-namespace.html "52.41. pg_publication_namespace") | | 52.39. `pg_proc` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 52.41. `pg_publication_namespace` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/catalog-pg-publication.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: SPI_scroll_cursor_fetch November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/spi-spi-scroll-cursor-fetch.html "PostgreSQL 18 - SPI_scroll_cursor_fetch") ([18](https://www.postgresql.org/docs/18/spi-spi-scroll-cursor-fetch.html "PostgreSQL 18 - SPI_scroll_cursor_fetch") ) / [17](https://www.postgresql.org/docs/17/spi-spi-scroll-cursor-fetch.html "PostgreSQL 17 - SPI_scroll_cursor_fetch") / [16](https://www.postgresql.org/docs/16/spi-spi-scroll-cursor-fetch.html "PostgreSQL 16 - SPI_scroll_cursor_fetch") / [15](https://www.postgresql.org/docs/15/spi-spi-scroll-cursor-fetch.html "PostgreSQL 15 - SPI_scroll_cursor_fetch") / [14](https://www.postgresql.org/docs/14/spi-spi-scroll-cursor-fetch.html "PostgreSQL 14 - SPI_scroll_cursor_fetch") Development Versions: [devel](https://www.postgresql.org/docs/devel/spi-spi-scroll-cursor-fetch.html "PostgreSQL devel - SPI_scroll_cursor_fetch") Unsupported versions: [13](https://www.postgresql.org/docs/13/spi-spi-scroll-cursor-fetch.html "PostgreSQL 13 - SPI_scroll_cursor_fetch") / [12](https://www.postgresql.org/docs/12/spi-spi-scroll-cursor-fetch.html "PostgreSQL 12 - SPI_scroll_cursor_fetch") / [11](https://www.postgresql.org/docs/11/spi-spi-scroll-cursor-fetch.html "PostgreSQL 11 - SPI_scroll_cursor_fetch") / [10](https://www.postgresql.org/docs/10/spi-spi-scroll-cursor-fetch.html "PostgreSQL 10 - SPI_scroll_cursor_fetch") / [9.6](https://www.postgresql.org/docs/9.6/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.6 - SPI_scroll_cursor_fetch") / [9.5](https://www.postgresql.org/docs/9.5/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.5 - SPI_scroll_cursor_fetch") / [9.4](https://www.postgresql.org/docs/9.4/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.4 - SPI_scroll_cursor_fetch") / [9.3](https://www.postgresql.org/docs/9.3/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.3 - SPI_scroll_cursor_fetch") / [9.2](https://www.postgresql.org/docs/9.2/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.2 - SPI_scroll_cursor_fetch") / [9.1](https://www.postgresql.org/docs/9.1/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.1 - SPI_scroll_cursor_fetch") / [9.0](https://www.postgresql.org/docs/9.0/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.0 - SPI_scroll_cursor_fetch") / [8.4](https://www.postgresql.org/docs/8.4/spi-spi-scroll-cursor-fetch.html "PostgreSQL 8.4 - SPI_scroll_cursor_fetch") / [8.3](https://www.postgresql.org/docs/8.3/spi-spi-scroll-cursor-fetch.html "PostgreSQL 8.3 - SPI_scroll_cursor_fetch") | SPI\_scroll\_cursor\_fetch | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-cursor-move.html "SPI_cursor_move") | [Up](https://www.postgresql.org/docs/18/spi-interface.html "45.1. Interface Functions") | 45.1. Interface Functions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/spi-spi-scroll-cursor-move.html "SPI_scroll_cursor_move") | * * * SPI\_scroll\_cursor\_fetch -------------------------- SPI\_scroll\_cursor\_fetch — fetch some rows from a cursor Synopsis -------- void SPI\_scroll\_cursor\_fetch(Portal _`portal`_, FetchDirection _`direction`_, long _`count`_) Description ----------- `SPI_scroll_cursor_fetch` fetches some rows from a cursor. This is equivalent to the SQL command `FETCH`. Arguments --------- ``Portal _`portal`_`` portal containing the cursor ``FetchDirection _`direction`_`` one of `FETCH_FORWARD`, `FETCH_BACKWARD`, `FETCH_ABSOLUTE` or `FETCH_RELATIVE` ``long _`count`_`` number of rows to fetch for `FETCH_FORWARD` or `FETCH_BACKWARD`; absolute row number to fetch for `FETCH_ABSOLUTE`; or relative row number to fetch for `FETCH_RELATIVE` Return Value ------------ `SPI_processed` and `SPI_tuptable` are set as in `SPI_execute` if successful. Notes ----- See the SQL [FETCH](https://www.postgresql.org/docs/18/sql-fetch.html "FETCH") command for details of the interpretation of the _`direction`_ and _`count`_ parameters. Direction values other than `FETCH_FORWARD` may fail if the cursor's plan was not created with the `CURSOR_OPT_SCROLL` option. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-cursor-move.html "SPI_cursor_move") | [Up](https://www.postgresql.org/docs/18/spi-interface.html "45.1. Interface Functions") | [Next](https://www.postgresql.org/docs/18/spi-spi-scroll-cursor-move.html "SPI_scroll_cursor_move") | | SPI\_cursor\_move | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | SPI\_scroll\_cursor\_move | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/spi-spi-scroll-cursor-fetch.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 21.4. Dropping Roles November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/role-removal.html "PostgreSQL 18 - 21.4. Dropping Roles") ([18](https://www.postgresql.org/docs/18/role-removal.html "PostgreSQL 18 - 21.4. Dropping Roles") ) / [17](https://www.postgresql.org/docs/17/role-removal.html "PostgreSQL 17 - 21.4. Dropping Roles") / [16](https://www.postgresql.org/docs/16/role-removal.html "PostgreSQL 16 - 21.4. Dropping Roles") / [15](https://www.postgresql.org/docs/15/role-removal.html "PostgreSQL 15 - 21.4. Dropping Roles") / [14](https://www.postgresql.org/docs/14/role-removal.html "PostgreSQL 14 - 21.4. Dropping Roles") Development Versions: [devel](https://www.postgresql.org/docs/devel/role-removal.html "PostgreSQL devel - 21.4. Dropping Roles") Unsupported versions: [13](https://www.postgresql.org/docs/13/role-removal.html "PostgreSQL 13 - 21.4. Dropping Roles") / [12](https://www.postgresql.org/docs/12/role-removal.html "PostgreSQL 12 - 21.4. Dropping Roles") / [11](https://www.postgresql.org/docs/11/role-removal.html "PostgreSQL 11 - 21.4. Dropping Roles") / [10](https://www.postgresql.org/docs/10/role-removal.html "PostgreSQL 10 - 21.4. Dropping Roles") / [9.6](https://www.postgresql.org/docs/9.6/role-removal.html "PostgreSQL 9.6 - 21.4. Dropping Roles") / [9.5](https://www.postgresql.org/docs/9.5/role-removal.html "PostgreSQL 9.5 - 21.4. Dropping Roles") / [9.4](https://www.postgresql.org/docs/9.4/role-removal.html "PostgreSQL 9.4 - 21.4. Dropping Roles") / [9.3](https://www.postgresql.org/docs/9.3/role-removal.html "PostgreSQL 9.3 - 21.4. Dropping Roles") / [9.2](https://www.postgresql.org/docs/9.2/role-removal.html "PostgreSQL 9.2 - 21.4. Dropping Roles") / [9.1](https://www.postgresql.org/docs/9.1/role-removal.html "PostgreSQL 9.1 - 21.4. Dropping Roles") | 21.4. Dropping Roles | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/role-membership.html "21.3. Role Membership") | [Up](https://www.postgresql.org/docs/current/user-manag.html "Chapter 21. Database Roles") | Chapter 21. Database Roles | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/predefined-roles.html "21.5. Predefined Roles") | * * * 21.4. Dropping Roles [#](https://www.postgresql.org/docs/current/role-removal.html#ROLE-REMOVAL) ------------------------------------------------------------------------------------------------- Because roles can own database objects and can hold privileges to access other objects, dropping a role is often not just a matter of a quick [`DROP ROLE`](https://www.postgresql.org/docs/current/sql-droprole.html "DROP ROLE") . Any objects owned by the role must first be dropped or reassigned to other owners; and any permissions granted to the role must be revoked. Ownership of objects can be transferred one at a time using `ALTER` commands, for example: ALTER TABLE bobs\_table OWNER TO alice; Alternatively, the [`REASSIGN OWNED`](https://www.postgresql.org/docs/current/sql-reassign-owned.html "REASSIGN OWNED") command can be used to reassign ownership of all objects owned by the role-to-be-dropped to a single other role. Because `REASSIGN OWNED` cannot access objects in other databases, it is necessary to run it in each database that contains objects owned by the role. (Note that the first such `REASSIGN OWNED` will change the ownership of any shared-across-databases objects, that is databases or tablespaces, that are owned by the role-to-be-dropped.) Once any valuable objects have been transferred to new owners, any remaining objects owned by the role-to-be-dropped can be dropped with the [`DROP OWNED`](https://www.postgresql.org/docs/current/sql-drop-owned.html "DROP OWNED") command. Again, this command cannot access objects in other databases, so it is necessary to run it in each database that contains objects owned by the role. Also, `DROP OWNED` will not drop entire databases or tablespaces, so it is necessary to do that manually if the role owns any databases or tablespaces that have not been transferred to new owners. `DROP OWNED` also takes care of removing any privileges granted to the target role for objects that do not belong to it. Because `REASSIGN OWNED` does not touch such objects, it's typically necessary to run both `REASSIGN OWNED` and `DROP OWNED` (in that order!) to fully remove the dependencies of a role to be dropped. In short then, the most general recipe for removing a role that has been used to own objects is: REASSIGN OWNED BY doomed\_role TO successor\_role; DROP OWNED BY doomed\_role; -- repeat the above commands in each database of the cluster DROP ROLE doomed\_role; When not all owned objects are to be transferred to the same successor owner, it's best to handle the exceptions manually and then perform the above steps to mop up. If `DROP ROLE` is attempted while dependent objects still remain, it will issue messages identifying which objects need to be reassigned or dropped. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/role-membership.html "21.3. Role Membership") | [Up](https://www.postgresql.org/docs/current/user-manag.html "Chapter 21. Database Roles") | [Next](https://www.postgresql.org/docs/current/predefined-roles.html "21.5. Predefined Roles") | | 21.3. Role Membership | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 21.5. Predefined Roles | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/role-removal.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.8. btree_gist — GiST operator classes with B-tree behavior November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/btree-gist.html "PostgreSQL 18 - F.8. btree_gist — GiST operator classes with B-tree behavior") ([18](https://www.postgresql.org/docs/18/btree-gist.html "PostgreSQL 18 - F.8. btree_gist — GiST operator classes with B-tree behavior") ) / [17](https://www.postgresql.org/docs/17/btree-gist.html "PostgreSQL 17 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [16](https://www.postgresql.org/docs/16/btree-gist.html "PostgreSQL 16 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [15](https://www.postgresql.org/docs/15/btree-gist.html "PostgreSQL 15 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [14](https://www.postgresql.org/docs/14/btree-gist.html "PostgreSQL 14 - F.8. btree_gist — GiST operator classes with B-tree behavior") Development Versions: [devel](https://www.postgresql.org/docs/devel/btree-gist.html "PostgreSQL devel - F.8. btree_gist — GiST operator classes with B-tree behavior") Unsupported versions: [13](https://www.postgresql.org/docs/13/btree-gist.html "PostgreSQL 13 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [12](https://www.postgresql.org/docs/12/btree-gist.html "PostgreSQL 12 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [11](https://www.postgresql.org/docs/11/btree-gist.html "PostgreSQL 11 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [10](https://www.postgresql.org/docs/10/btree-gist.html "PostgreSQL 10 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.6](https://www.postgresql.org/docs/9.6/btree-gist.html "PostgreSQL 9.6 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.5](https://www.postgresql.org/docs/9.5/btree-gist.html "PostgreSQL 9.5 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.4](https://www.postgresql.org/docs/9.4/btree-gist.html "PostgreSQL 9.4 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.3](https://www.postgresql.org/docs/9.3/btree-gist.html "PostgreSQL 9.3 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.2](https://www.postgresql.org/docs/9.2/btree-gist.html "PostgreSQL 9.2 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.1](https://www.postgresql.org/docs/9.1/btree-gist.html "PostgreSQL 9.1 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.0](https://www.postgresql.org/docs/9.0/btree-gist.html "PostgreSQL 9.0 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [8.4](https://www.postgresql.org/docs/8.4/btree-gist.html "PostgreSQL 8.4 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [8.3](https://www.postgresql.org/docs/8.3/btree-gist.html "PostgreSQL 8.3 - F.8. btree_gist — GiST operator classes with B-tree behavior") | F.8. btree\_gist — GiST operator classes with B-tree behavior | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/btree-gin.html "F.7. btree_gin — GIN operator classes with B-tree behavior") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/citext.html "F.9. citext — a case-insensitive character string type") | * * * F.8. btree\_gist — GiST operator classes with B-tree behavior [#](https://www.postgresql.org/docs/current/btree-gist.html#BTREE-GIST) -------------------------------------------------------------------------------------------------------------------------------------- [F.8.1. Example Usage](https://www.postgresql.org/docs/current/btree-gist.html#BTREE-GIST-EXAMPLE-USAGE) [F.8.2. Authors](https://www.postgresql.org/docs/current/btree-gist.html#BTREE-GIST-AUTHORS) `btree_gist` provides GiST index operator classes that implement B-tree equivalent behavior for the data types `int2`, `int4`, `int8`, `float4`, `float8`, `numeric`, `timestamp with time zone`, `timestamp without time zone`, `time with time zone`, `time without time zone`, `date`, `interval`, `oid`, `money`, `char`, `varchar`, `text`, `bytea`, `bit`, `varbit`, `macaddr`, `macaddr8`, `inet`, `cidr`, `uuid`, `bool` and all `enum` types. In general, these operator classes will not outperform the equivalent standard B-tree index methods, and they lack one major feature of the standard B-tree code: the ability to enforce uniqueness. However, they provide some other features that are not available with a B-tree index, as described below. Also, these operator classes are useful when a multicolumn GiST index is needed, wherein some of the columns are of data types that are only indexable with GiST but other columns are just simple data types. Lastly, these operator classes are useful for GiST testing and as a base for developing other GiST operator classes. In addition to the typical B-tree search operators, `btree_gist` also provides index support for `<>` (“not equals”). This may be useful in combination with an [exclusion constraint](https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-EXCLUDE) , as described below. Also, for data types for which there is a natural distance metric, `btree_gist` defines a distance operator `<->`, and provides GiST index support for nearest-neighbor searches using this operator. Distance operators are provided for `int2`, `int4`, `int8`, `float4`, `float8`, `timestamp with time zone`, `timestamp without time zone`, `time without time zone`, `date`, `interval`, `oid`, and `money`. By default `btree_gist` builds GiST index with `sortsupport` in _sorted_ mode. This usually results in much faster index built speed. It is still possible to revert to buffered built strategy by using the `buffering` parameter when creating the index. This module is considered “trusted”, that is, it can be installed by non-superusers who have `CREATE` privilege on the current database. ### F.8.1. Example Usage [#](https://www.postgresql.org/docs/current/btree-gist.html#BTREE-GIST-EXAMPLE-USAGE) Simple example using `btree_gist` instead of `btree`: CREATE TABLE test (a int4); -- create index CREATE INDEX testidx ON test USING GIST (a); -- query SELECT \* FROM test WHERE a < 10; -- nearest-neighbor search: find the ten entries closest to "42" SELECT \*, a <-> 42 AS dist FROM test ORDER BY a <-> 42 LIMIT 10; Use an [exclusion constraint](https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-EXCLUDE) to enforce the rule that a cage at a zoo can contain only one kind of animal: \=> CREATE TABLE zoo ( cage INTEGER, animal TEXT, EXCLUDE USING GIST (cage WITH =, animal WITH <>) ); => INSERT INTO zoo VALUES(123, 'zebra'); INSERT 0 1 => INSERT INTO zoo VALUES(123, 'zebra'); INSERT 0 1 => INSERT INTO zoo VALUES(123, 'lion'); ERROR: conflicting key value violates exclusion constraint "zoo\_cage\_animal\_excl" DETAIL: Key (cage, animal)=(123, lion) conflicts with existing key (cage, animal)=(123, zebra). => INSERT INTO zoo VALUES(124, 'lion'); INSERT 0 1 ### F.8.2. Authors [#](https://www.postgresql.org/docs/current/btree-gist.html#BTREE-GIST-AUTHORS) Teodor Sigaev (`<[teodor@stack.net](mailto:teodor@stack.net) >`), Oleg Bartunov (`<[oleg@sai.msu.su](mailto:oleg@sai.msu.su) >`), Janko Richter (`<[jankorichter@yahoo.de](mailto:jankorichter@yahoo.de) >`), and Paul Jungwirth (`<[pj@illuminatedcomputing.com](mailto:pj@illuminatedcomputing.com) >`). See [http://www.sai.msu.su/~megera/postgres/gist/](http://www.sai.msu.su/~megera/postgres/gist/) for additional information. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/btree-gin.html "F.7. btree_gin — GIN operator classes with B-tree behavior") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/current/citext.html "F.9. citext — a case-insensitive character string type") | | F.7. btree\_gin — GIN operator classes with B-tree behavior | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | F.9. citext — a case-insensitive character string type | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/btree-gist.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 44.9. Utility Functions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plpython-util.html "PostgreSQL 18 - 44.9. Utility Functions") ([18](https://www.postgresql.org/docs/18/plpython-util.html "PostgreSQL 18 - 44.9. Utility Functions") ) / [17](https://www.postgresql.org/docs/17/plpython-util.html "PostgreSQL 17 - 44.9. Utility Functions") / [16](https://www.postgresql.org/docs/16/plpython-util.html "PostgreSQL 16 - 44.9. Utility Functions") / [15](https://www.postgresql.org/docs/15/plpython-util.html "PostgreSQL 15 - 44.9. Utility Functions") / [14](https://www.postgresql.org/docs/14/plpython-util.html "PostgreSQL 14 - 44.9. Utility Functions") Development Versions: [devel](https://www.postgresql.org/docs/devel/plpython-util.html "PostgreSQL devel - 44.9. Utility Functions") Unsupported versions: [13](https://www.postgresql.org/docs/13/plpython-util.html "PostgreSQL 13 - 44.9. Utility Functions") / [12](https://www.postgresql.org/docs/12/plpython-util.html "PostgreSQL 12 - 44.9. Utility Functions") / [11](https://www.postgresql.org/docs/11/plpython-util.html "PostgreSQL 11 - 44.9. Utility Functions") / [10](https://www.postgresql.org/docs/10/plpython-util.html "PostgreSQL 10 - 44.9. Utility Functions") / [9.6](https://www.postgresql.org/docs/9.6/plpython-util.html "PostgreSQL 9.6 - 44.9. Utility Functions") / [9.5](https://www.postgresql.org/docs/9.5/plpython-util.html "PostgreSQL 9.5 - 44.9. Utility Functions") / [9.4](https://www.postgresql.org/docs/9.4/plpython-util.html "PostgreSQL 9.4 - 44.9. Utility Functions") / [9.3](https://www.postgresql.org/docs/9.3/plpython-util.html "PostgreSQL 9.3 - 44.9. Utility Functions") / [9.2](https://www.postgresql.org/docs/9.2/plpython-util.html "PostgreSQL 9.2 - 44.9. Utility Functions") / [9.1](https://www.postgresql.org/docs/9.1/plpython-util.html "PostgreSQL 9.1 - 44.9. Utility Functions") / [9.0](https://www.postgresql.org/docs/9.0/plpython-util.html "PostgreSQL 9.0 - 44.9. Utility Functions") | 44.9. Utility Functions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/plpython-transactions.html "44.8. Transaction Management") | [Up](https://www.postgresql.org/docs/current/plpython.html "Chapter 44. PL/Python — Python Procedural Language") | Chapter 44. PL/Python — Python Procedural Language | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/plpython-python23.html "44.10. Python 2 vs. Python 3") | * * * 44.9. Utility Functions [#](https://www.postgresql.org/docs/current/plpython-util.html#PLPYTHON-UTIL) ------------------------------------------------------------------------------------------------------ The `plpy` module also provides the functions | | | --- | | ``plpy.debug(_`msg, **kwargs`_)`` | | ``plpy.log(_`msg, **kwargs`_)`` | | ``plpy.info(_`msg, **kwargs`_)`` | | ``plpy.notice(_`msg, **kwargs`_)`` | | ``plpy.warning(_`msg, **kwargs`_)`` | | ``plpy.error(_`msg, **kwargs`_)`` | | ``plpy.fatal(_`msg, **kwargs`_)`` | `plpy.error` and `plpy.fatal` actually raise a Python exception which, if uncaught, propagates out to the calling query, causing the current transaction or subtransaction to be aborted. ``raise plpy.Error(_`msg`_)`` and ``raise plpy.Fatal(_`msg`_)`` are equivalent to calling ``plpy.error(_`msg`_)`` and ``plpy.fatal(_`msg`_)``, respectively but the `raise` form does not allow passing keyword arguments. The other functions only generate messages of different priority levels. Whether messages of a particular priority are reported to the client, written to the server log, or both is controlled by the [log\_min\_messages](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-MESSAGES) and [client\_min\_messages](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-CLIENT-MIN-MESSAGES) configuration variables. See [Chapter 19](https://www.postgresql.org/docs/current/runtime-config.html "Chapter 19. Server Configuration") for more information. The _`msg`_ argument is given as a positional argument. For backward compatibility, more than one positional argument can be given. In that case, the string representation of the tuple of positional arguments becomes the message reported to the client. The following keyword-only arguments are accepted: | | | --- | | `detail` | | `hint` | | `sqlstate` | | `schema_name` | | `table_name` | | `column_name` | | `datatype_name` | | `constraint_name` | The string representation of the objects passed as keyword-only arguments is used to enrich the messages reported to the client. For example: CREATE FUNCTION raise\_custom\_exception() RETURNS void AS $$ plpy.error("custom exception message", detail="some info about exception", hint="hint for users") $$ LANGUAGE plpython3u; =# SELECT raise\_custom\_exception(); ERROR: plpy.Error: custom exception message DETAIL: some info about exception HINT: hint for users CONTEXT: Traceback (most recent call last): PL/Python function "raise\_custom\_exception", line 4, in hint="hint for users") PL/Python function "raise\_custom\_exception" Another set of utility functions are ``plpy.quote_literal(_`string`_)``, ``plpy.quote_nullable(_`string`_)``, and ``plpy.quote_ident(_`string`_)``. They are equivalent to the built-in quoting functions described in [Section 9.4](https://www.postgresql.org/docs/current/functions-string.html "9.4. String Functions and Operators") . They are useful when constructing ad-hoc queries. A PL/Python equivalent of dynamic SQL from [Example 41.1](https://www.postgresql.org/docs/current/plpgsql-statements.html#PLPGSQL-QUOTE-LITERAL-EXAMPLE "Example 41.1. Quoting Values in Dynamic Queries") would be: plpy.execute("UPDATE tbl SET %s = %s WHERE key = %s" % ( plpy.quote\_ident(colname), plpy.quote\_nullable(newvalue), plpy.quote\_literal(keyvalue))) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/plpython-transactions.html "44.8. Transaction Management") | [Up](https://www.postgresql.org/docs/current/plpython.html "Chapter 44. PL/Python — Python Procedural Language") | [Next](https://www.postgresql.org/docs/current/plpython-python23.html "44.10. Python 2 vs. Python 3") | | 44.8. Transaction Management | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 44.10. Python 2 vs. Python 3 | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/plpython-util.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 44.9. Utility Functions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plpython-util.html "PostgreSQL 18 - 44.9. Utility Functions") ([18](https://www.postgresql.org/docs/18/plpython-util.html "PostgreSQL 18 - 44.9. Utility Functions") ) / [17](https://www.postgresql.org/docs/17/plpython-util.html "PostgreSQL 17 - 44.9. Utility Functions") / [16](https://www.postgresql.org/docs/16/plpython-util.html "PostgreSQL 16 - 44.9. Utility Functions") / [15](https://www.postgresql.org/docs/15/plpython-util.html "PostgreSQL 15 - 44.9. Utility Functions") / [14](https://www.postgresql.org/docs/14/plpython-util.html "PostgreSQL 14 - 44.9. Utility Functions") Development Versions: [devel](https://www.postgresql.org/docs/devel/plpython-util.html "PostgreSQL devel - 44.9. Utility Functions") Unsupported versions: [13](https://www.postgresql.org/docs/13/plpython-util.html "PostgreSQL 13 - 44.9. Utility Functions") / [12](https://www.postgresql.org/docs/12/plpython-util.html "PostgreSQL 12 - 44.9. Utility Functions") / [11](https://www.postgresql.org/docs/11/plpython-util.html "PostgreSQL 11 - 44.9. Utility Functions") / [10](https://www.postgresql.org/docs/10/plpython-util.html "PostgreSQL 10 - 44.9. Utility Functions") / [9.6](https://www.postgresql.org/docs/9.6/plpython-util.html "PostgreSQL 9.6 - 44.9. Utility Functions") / [9.5](https://www.postgresql.org/docs/9.5/plpython-util.html "PostgreSQL 9.5 - 44.9. Utility Functions") / [9.4](https://www.postgresql.org/docs/9.4/plpython-util.html "PostgreSQL 9.4 - 44.9. Utility Functions") / [9.3](https://www.postgresql.org/docs/9.3/plpython-util.html "PostgreSQL 9.3 - 44.9. Utility Functions") / [9.2](https://www.postgresql.org/docs/9.2/plpython-util.html "PostgreSQL 9.2 - 44.9. Utility Functions") / [9.1](https://www.postgresql.org/docs/9.1/plpython-util.html "PostgreSQL 9.1 - 44.9. Utility Functions") / [9.0](https://www.postgresql.org/docs/9.0/plpython-util.html "PostgreSQL 9.0 - 44.9. Utility Functions") | 44.9. Utility Functions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/plpython-transactions.html "44.8. Transaction Management") | [Up](https://www.postgresql.org/docs/18/plpython.html "Chapter 44. PL/Python — Python Procedural Language") | Chapter 44. PL/Python — Python Procedural Language | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/plpython-python23.html "44.10. Python 2 vs. Python 3") | * * * 44.9. Utility Functions [#](https://www.postgresql.org/docs/18/plpython-util.html#PLPYTHON-UTIL) ------------------------------------------------------------------------------------------------- The `plpy` module also provides the functions | | | --- | | ``plpy.debug(_`msg, **kwargs`_)`` | | ``plpy.log(_`msg, **kwargs`_)`` | | ``plpy.info(_`msg, **kwargs`_)`` | | ``plpy.notice(_`msg, **kwargs`_)`` | | ``plpy.warning(_`msg, **kwargs`_)`` | | ``plpy.error(_`msg, **kwargs`_)`` | | ``plpy.fatal(_`msg, **kwargs`_)`` | `plpy.error` and `plpy.fatal` actually raise a Python exception which, if uncaught, propagates out to the calling query, causing the current transaction or subtransaction to be aborted. ``raise plpy.Error(_`msg`_)`` and ``raise plpy.Fatal(_`msg`_)`` are equivalent to calling ``plpy.error(_`msg`_)`` and ``plpy.fatal(_`msg`_)``, respectively but the `raise` form does not allow passing keyword arguments. The other functions only generate messages of different priority levels. Whether messages of a particular priority are reported to the client, written to the server log, or both is controlled by the [log\_min\_messages](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-MIN-MESSAGES) and [client\_min\_messages](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-CLIENT-MIN-MESSAGES) configuration variables. See [Chapter 19](https://www.postgresql.org/docs/18/runtime-config.html "Chapter 19. Server Configuration") for more information. The _`msg`_ argument is given as a positional argument. For backward compatibility, more than one positional argument can be given. In that case, the string representation of the tuple of positional arguments becomes the message reported to the client. The following keyword-only arguments are accepted: | | | --- | | `detail` | | `hint` | | `sqlstate` | | `schema_name` | | `table_name` | | `column_name` | | `datatype_name` | | `constraint_name` | The string representation of the objects passed as keyword-only arguments is used to enrich the messages reported to the client. For example: CREATE FUNCTION raise\_custom\_exception() RETURNS void AS $$ plpy.error("custom exception message", detail="some info about exception", hint="hint for users") $$ LANGUAGE plpython3u; =# SELECT raise\_custom\_exception(); ERROR: plpy.Error: custom exception message DETAIL: some info about exception HINT: hint for users CONTEXT: Traceback (most recent call last): PL/Python function "raise\_custom\_exception", line 4, in hint="hint for users") PL/Python function "raise\_custom\_exception" Another set of utility functions are ``plpy.quote_literal(_`string`_)``, ``plpy.quote_nullable(_`string`_)``, and ``plpy.quote_ident(_`string`_)``. They are equivalent to the built-in quoting functions described in [Section 9.4](https://www.postgresql.org/docs/18/functions-string.html "9.4. String Functions and Operators") . They are useful when constructing ad-hoc queries. A PL/Python equivalent of dynamic SQL from [Example 41.1](https://www.postgresql.org/docs/18/plpgsql-statements.html#PLPGSQL-QUOTE-LITERAL-EXAMPLE "Example 41.1. Quoting Values in Dynamic Queries") would be: plpy.execute("UPDATE tbl SET %s = %s WHERE key = %s" % ( plpy.quote\_ident(colname), plpy.quote\_nullable(newvalue), plpy.quote\_literal(keyvalue))) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/plpython-transactions.html "44.8. Transaction Management") | [Up](https://www.postgresql.org/docs/18/plpython.html "Chapter 44. PL/Python — Python Procedural Language") | [Next](https://www.postgresql.org/docs/18/plpython-python23.html "44.10. Python 2 vs. Python 3") | | 44.8. Transaction Management | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 44.10. Python 2 vs. Python 3 | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/plpython-util.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.8. btree_gist — GiST operator classes with B-tree behavior November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/btree-gist.html "PostgreSQL 18 - F.8. btree_gist — GiST operator classes with B-tree behavior") ([18](https://www.postgresql.org/docs/18/btree-gist.html "PostgreSQL 18 - F.8. btree_gist — GiST operator classes with B-tree behavior") ) / [17](https://www.postgresql.org/docs/17/btree-gist.html "PostgreSQL 17 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [16](https://www.postgresql.org/docs/16/btree-gist.html "PostgreSQL 16 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [15](https://www.postgresql.org/docs/15/btree-gist.html "PostgreSQL 15 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [14](https://www.postgresql.org/docs/14/btree-gist.html "PostgreSQL 14 - F.8. btree_gist — GiST operator classes with B-tree behavior") Development Versions: [devel](https://www.postgresql.org/docs/devel/btree-gist.html "PostgreSQL devel - F.8. btree_gist — GiST operator classes with B-tree behavior") Unsupported versions: [13](https://www.postgresql.org/docs/13/btree-gist.html "PostgreSQL 13 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [12](https://www.postgresql.org/docs/12/btree-gist.html "PostgreSQL 12 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [11](https://www.postgresql.org/docs/11/btree-gist.html "PostgreSQL 11 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [10](https://www.postgresql.org/docs/10/btree-gist.html "PostgreSQL 10 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.6](https://www.postgresql.org/docs/9.6/btree-gist.html "PostgreSQL 9.6 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.5](https://www.postgresql.org/docs/9.5/btree-gist.html "PostgreSQL 9.5 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.4](https://www.postgresql.org/docs/9.4/btree-gist.html "PostgreSQL 9.4 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.3](https://www.postgresql.org/docs/9.3/btree-gist.html "PostgreSQL 9.3 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.2](https://www.postgresql.org/docs/9.2/btree-gist.html "PostgreSQL 9.2 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.1](https://www.postgresql.org/docs/9.1/btree-gist.html "PostgreSQL 9.1 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [9.0](https://www.postgresql.org/docs/9.0/btree-gist.html "PostgreSQL 9.0 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [8.4](https://www.postgresql.org/docs/8.4/btree-gist.html "PostgreSQL 8.4 - F.8. btree_gist — GiST operator classes with B-tree behavior") / [8.3](https://www.postgresql.org/docs/8.3/btree-gist.html "PostgreSQL 8.3 - F.8. btree_gist — GiST operator classes with B-tree behavior") | F.8. btree\_gist — GiST operator classes with B-tree behavior | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/btree-gin.html "F.7. btree_gin — GIN operator classes with B-tree behavior") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/citext.html "F.9. citext — a case-insensitive character string type") | * * * F.8. btree\_gist — GiST operator classes with B-tree behavior [#](https://www.postgresql.org/docs/18/btree-gist.html#BTREE-GIST) --------------------------------------------------------------------------------------------------------------------------------- [F.8.1. Example Usage](https://www.postgresql.org/docs/18/btree-gist.html#BTREE-GIST-EXAMPLE-USAGE) [F.8.2. Authors](https://www.postgresql.org/docs/18/btree-gist.html#BTREE-GIST-AUTHORS) `btree_gist` provides GiST index operator classes that implement B-tree equivalent behavior for the data types `int2`, `int4`, `int8`, `float4`, `float8`, `numeric`, `timestamp with time zone`, `timestamp without time zone`, `time with time zone`, `time without time zone`, `date`, `interval`, `oid`, `money`, `char`, `varchar`, `text`, `bytea`, `bit`, `varbit`, `macaddr`, `macaddr8`, `inet`, `cidr`, `uuid`, `bool` and all `enum` types. In general, these operator classes will not outperform the equivalent standard B-tree index methods, and they lack one major feature of the standard B-tree code: the ability to enforce uniqueness. However, they provide some other features that are not available with a B-tree index, as described below. Also, these operator classes are useful when a multicolumn GiST index is needed, wherein some of the columns are of data types that are only indexable with GiST but other columns are just simple data types. Lastly, these operator classes are useful for GiST testing and as a base for developing other GiST operator classes. In addition to the typical B-tree search operators, `btree_gist` also provides index support for `<>` (“not equals”). This may be useful in combination with an [exclusion constraint](https://www.postgresql.org/docs/18/sql-createtable.html#SQL-CREATETABLE-EXCLUDE) , as described below. Also, for data types for which there is a natural distance metric, `btree_gist` defines a distance operator `<->`, and provides GiST index support for nearest-neighbor searches using this operator. Distance operators are provided for `int2`, `int4`, `int8`, `float4`, `float8`, `timestamp with time zone`, `timestamp without time zone`, `time without time zone`, `date`, `interval`, `oid`, and `money`. By default `btree_gist` builds GiST index with `sortsupport` in _sorted_ mode. This usually results in much faster index built speed. It is still possible to revert to buffered built strategy by using the `buffering` parameter when creating the index. This module is considered “trusted”, that is, it can be installed by non-superusers who have `CREATE` privilege on the current database. ### F.8.1. Example Usage [#](https://www.postgresql.org/docs/18/btree-gist.html#BTREE-GIST-EXAMPLE-USAGE) Simple example using `btree_gist` instead of `btree`: CREATE TABLE test (a int4); -- create index CREATE INDEX testidx ON test USING GIST (a); -- query SELECT \* FROM test WHERE a < 10; -- nearest-neighbor search: find the ten entries closest to "42" SELECT \*, a <-> 42 AS dist FROM test ORDER BY a <-> 42 LIMIT 10; Use an [exclusion constraint](https://www.postgresql.org/docs/18/sql-createtable.html#SQL-CREATETABLE-EXCLUDE) to enforce the rule that a cage at a zoo can contain only one kind of animal: \=> CREATE TABLE zoo ( cage INTEGER, animal TEXT, EXCLUDE USING GIST (cage WITH =, animal WITH <>) ); => INSERT INTO zoo VALUES(123, 'zebra'); INSERT 0 1 => INSERT INTO zoo VALUES(123, 'zebra'); INSERT 0 1 => INSERT INTO zoo VALUES(123, 'lion'); ERROR: conflicting key value violates exclusion constraint "zoo\_cage\_animal\_excl" DETAIL: Key (cage, animal)=(123, lion) conflicts with existing key (cage, animal)=(123, zebra). => INSERT INTO zoo VALUES(124, 'lion'); INSERT 0 1 ### F.8.2. Authors [#](https://www.postgresql.org/docs/18/btree-gist.html#BTREE-GIST-AUTHORS) Teodor Sigaev (`<[teodor@stack.net](mailto:teodor@stack.net) >`), Oleg Bartunov (`<[oleg@sai.msu.su](mailto:oleg@sai.msu.su) >`), Janko Richter (`<[jankorichter@yahoo.de](mailto:jankorichter@yahoo.de) >`), and Paul Jungwirth (`<[pj@illuminatedcomputing.com](mailto:pj@illuminatedcomputing.com) >`). See [http://www.sai.msu.su/~megera/postgres/gist/](http://www.sai.msu.su/~megera/postgres/gist/) for additional information. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/btree-gin.html "F.7. btree_gin — GIN operator classes with B-tree behavior") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/18/citext.html "F.9. citext — a case-insensitive character string type") | | F.7. btree\_gin — GIN operator classes with B-tree behavior | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | F.9. citext — a case-insensitive character string type | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/btree-gist.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.7. btree_gin — GIN operator classes with B-tree behavior November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/btree-gin.html "PostgreSQL 18 - F.7. btree_gin — GIN operator classes with B-tree behavior") ([18](https://www.postgresql.org/docs/18/btree-gin.html "PostgreSQL 18 - F.7. btree_gin — GIN operator classes with B-tree behavior") ) / [17](https://www.postgresql.org/docs/17/btree-gin.html "PostgreSQL 17 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [16](https://www.postgresql.org/docs/16/btree-gin.html "PostgreSQL 16 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [15](https://www.postgresql.org/docs/15/btree-gin.html "PostgreSQL 15 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [14](https://www.postgresql.org/docs/14/btree-gin.html "PostgreSQL 14 - F.7. btree_gin — GIN operator classes with B-tree behavior") Development Versions: [devel](https://www.postgresql.org/docs/devel/btree-gin.html "PostgreSQL devel - F.7. btree_gin — GIN operator classes with B-tree behavior") Unsupported versions: [13](https://www.postgresql.org/docs/13/btree-gin.html "PostgreSQL 13 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [12](https://www.postgresql.org/docs/12/btree-gin.html "PostgreSQL 12 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [11](https://www.postgresql.org/docs/11/btree-gin.html "PostgreSQL 11 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [10](https://www.postgresql.org/docs/10/btree-gin.html "PostgreSQL 10 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.6](https://www.postgresql.org/docs/9.6/btree-gin.html "PostgreSQL 9.6 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.5](https://www.postgresql.org/docs/9.5/btree-gin.html "PostgreSQL 9.5 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.4](https://www.postgresql.org/docs/9.4/btree-gin.html "PostgreSQL 9.4 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.3](https://www.postgresql.org/docs/9.3/btree-gin.html "PostgreSQL 9.3 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.2](https://www.postgresql.org/docs/9.2/btree-gin.html "PostgreSQL 9.2 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.1](https://www.postgresql.org/docs/9.1/btree-gin.html "PostgreSQL 9.1 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.0](https://www.postgresql.org/docs/9.0/btree-gin.html "PostgreSQL 9.0 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [8.4](https://www.postgresql.org/docs/8.4/btree-gin.html "PostgreSQL 8.4 - F.7. btree_gin — GIN operator classes with B-tree behavior") | F.7. btree\_gin — GIN operator classes with B-tree behavior | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/bloom.html "F.6. bloom — bloom filter index access method") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/btree-gist.html "F.8. btree_gist — GiST operator classes with B-tree behavior") | * * * F.7. btree\_gin — GIN operator classes with B-tree behavior [#](https://www.postgresql.org/docs/18/btree-gin.html#BTREE-GIN) ----------------------------------------------------------------------------------------------------------------------------- [F.7.1. Example Usage](https://www.postgresql.org/docs/18/btree-gin.html#BTREE-GIN-EXAMPLE-USAGE) [F.7.2. Authors](https://www.postgresql.org/docs/18/btree-gin.html#BTREE-GIN-AUTHORS) `btree_gin` provides GIN operator classes that implement B-tree equivalent behavior for the data types `int2`, `int4`, `int8`, `float4`, `float8`, `timestamp with time zone`, `timestamp without time zone`, `time with time zone`, `time without time zone`, `date`, `interval`, `oid`, `money`, `"char"`, `varchar`, `text`, `bytea`, `bit`, `varbit`, `macaddr`, `macaddr8`, `inet`, `cidr`, `uuid`, `name`, `bool`, `bpchar`, and all `enum` types. In general, these operator classes will not outperform the equivalent standard B-tree index methods, and they lack one major feature of the standard B-tree code: the ability to enforce uniqueness. However, they are useful for GIN testing and as a base for developing other GIN operator classes. Also, for queries that test both a GIN-indexable column and a B-tree-indexable column, it might be more efficient to create a multicolumn GIN index that uses one of these operator classes than to create two separate indexes that would have to be combined via bitmap ANDing. This module is considered “trusted”, that is, it can be installed by non-superusers who have `CREATE` privilege on the current database. ### F.7.1. Example Usage [#](https://www.postgresql.org/docs/18/btree-gin.html#BTREE-GIN-EXAMPLE-USAGE) CREATE TABLE test (a int4); -- create index CREATE INDEX testidx ON test USING GIN (a); -- query SELECT \* FROM test WHERE a < 10; ### F.7.2. Authors [#](https://www.postgresql.org/docs/18/btree-gin.html#BTREE-GIN-AUTHORS) Teodor Sigaev (`<[teodor@stack.net](mailto:teodor@stack.net) >`) and Oleg Bartunov (`<[oleg@sai.msu.su](mailto:oleg@sai.msu.su) >`). See [http://www.sai.msu.su/~megera/oddmuse/index.cgi/Gin](http://www.sai.msu.su/~megera/oddmuse/index.cgi/Gin) for additional information. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/bloom.html "F.6. bloom — bloom filter index access method") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/18/btree-gist.html "F.8. btree_gist — GiST operator classes with B-tree behavior") | | F.6. bloom — bloom filter index access method | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | F.8. btree\_gist — GiST operator classes with B-tree behavior | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/btree-gin.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: DISCONNECT November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/ecpg-sql-disconnect.html "PostgreSQL 18 - DISCONNECT") ([18](https://www.postgresql.org/docs/18/ecpg-sql-disconnect.html "PostgreSQL 18 - DISCONNECT") ) / [17](https://www.postgresql.org/docs/17/ecpg-sql-disconnect.html "PostgreSQL 17 - DISCONNECT") / [16](https://www.postgresql.org/docs/16/ecpg-sql-disconnect.html "PostgreSQL 16 - DISCONNECT") / [15](https://www.postgresql.org/docs/15/ecpg-sql-disconnect.html "PostgreSQL 15 - DISCONNECT") / [14](https://www.postgresql.org/docs/14/ecpg-sql-disconnect.html "PostgreSQL 14 - DISCONNECT") Development Versions: [devel](https://www.postgresql.org/docs/devel/ecpg-sql-disconnect.html "PostgreSQL devel - DISCONNECT") Unsupported versions: [13](https://www.postgresql.org/docs/13/ecpg-sql-disconnect.html "PostgreSQL 13 - DISCONNECT") / [12](https://www.postgresql.org/docs/12/ecpg-sql-disconnect.html "PostgreSQL 12 - DISCONNECT") / [11](https://www.postgresql.org/docs/11/ecpg-sql-disconnect.html "PostgreSQL 11 - DISCONNECT") / [10](https://www.postgresql.org/docs/10/ecpg-sql-disconnect.html "PostgreSQL 10 - DISCONNECT") / [9.6](https://www.postgresql.org/docs/9.6/ecpg-sql-disconnect.html "PostgreSQL 9.6 - DISCONNECT") / [9.5](https://www.postgresql.org/docs/9.5/ecpg-sql-disconnect.html "PostgreSQL 9.5 - DISCONNECT") / [9.4](https://www.postgresql.org/docs/9.4/ecpg-sql-disconnect.html "PostgreSQL 9.4 - DISCONNECT") / [9.3](https://www.postgresql.org/docs/9.3/ecpg-sql-disconnect.html "PostgreSQL 9.3 - DISCONNECT") / [9.2](https://www.postgresql.org/docs/9.2/ecpg-sql-disconnect.html "PostgreSQL 9.2 - DISCONNECT") / [9.1](https://www.postgresql.org/docs/9.1/ecpg-sql-disconnect.html "PostgreSQL 9.1 - DISCONNECT") | DISCONNECT | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/ecpg-sql-describe.html "DESCRIBE") | [Up](https://www.postgresql.org/docs/18/ecpg-sql-commands.html "34.14. Embedded SQL Commands") | 34.14. Embedded SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/ecpg-sql-execute-immediate.html "EXECUTE IMMEDIATE") | * * * DISCONNECT ---------- DISCONNECT — terminate a database connection Synopsis -------- DISCONNECT _`connection_name`_ DISCONNECT \[ CURRENT \] DISCONNECT ALL Description ----------- `DISCONNECT` closes a connection (or all connections) to the database. Parameters ---------- _`connection_name`_ [#](https://www.postgresql.org/docs/18/ecpg-sql-disconnect.html#ECPG-SQL-DISCONNECT-CONNECTION-NAME) A database connection name established by the `CONNECT` command. `CURRENT` [#](https://www.postgresql.org/docs/18/ecpg-sql-disconnect.html#ECPG-SQL-DISCONNECT-CURRENT) Close the “current” connection, which is either the most recently opened connection, or the connection set by the `SET CONNECTION` command. This is also the default if no argument is given to the `DISCONNECT` command. `ALL` [#](https://www.postgresql.org/docs/18/ecpg-sql-disconnect.html#ECPG-SQL-DISCONNECT-ALL) Close all open connections. Examples -------- int main(void) { EXEC SQL CONNECT TO testdb AS con1 USER testuser; EXEC SQL CONNECT TO testdb AS con2 USER testuser; EXEC SQL CONNECT TO testdb AS con3 USER testuser; EXEC SQL DISCONNECT CURRENT; /\* close con3 \*/ EXEC SQL DISCONNECT ALL; /\* close con2 and con1 \*/ return 0; } Compatibility ------------- `DISCONNECT` is specified in the SQL standard. See Also -------- [CONNECT](https://www.postgresql.org/docs/18/ecpg-sql-connect.html "CONNECT") , [SET CONNECTION](https://www.postgresql.org/docs/18/ecpg-sql-set-connection.html "SET CONNECTION") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/ecpg-sql-describe.html "DESCRIBE") | [Up](https://www.postgresql.org/docs/18/ecpg-sql-commands.html "34.14. Embedded SQL Commands") | [Next](https://www.postgresql.org/docs/18/ecpg-sql-execute-immediate.html "EXECUTE IMMEDIATE") | | DESCRIBE | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | EXECUTE IMMEDIATE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/ecpg-sql-disconnect.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: SPI_scroll_cursor_fetch November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/spi-spi-scroll-cursor-fetch.html "PostgreSQL 18 - SPI_scroll_cursor_fetch") ([18](https://www.postgresql.org/docs/18/spi-spi-scroll-cursor-fetch.html "PostgreSQL 18 - SPI_scroll_cursor_fetch") ) / [17](https://www.postgresql.org/docs/17/spi-spi-scroll-cursor-fetch.html "PostgreSQL 17 - SPI_scroll_cursor_fetch") / [16](https://www.postgresql.org/docs/16/spi-spi-scroll-cursor-fetch.html "PostgreSQL 16 - SPI_scroll_cursor_fetch") / [15](https://www.postgresql.org/docs/15/spi-spi-scroll-cursor-fetch.html "PostgreSQL 15 - SPI_scroll_cursor_fetch") / [14](https://www.postgresql.org/docs/14/spi-spi-scroll-cursor-fetch.html "PostgreSQL 14 - SPI_scroll_cursor_fetch") Development Versions: [devel](https://www.postgresql.org/docs/devel/spi-spi-scroll-cursor-fetch.html "PostgreSQL devel - SPI_scroll_cursor_fetch") Unsupported versions: [13](https://www.postgresql.org/docs/13/spi-spi-scroll-cursor-fetch.html "PostgreSQL 13 - SPI_scroll_cursor_fetch") / [12](https://www.postgresql.org/docs/12/spi-spi-scroll-cursor-fetch.html "PostgreSQL 12 - SPI_scroll_cursor_fetch") / [11](https://www.postgresql.org/docs/11/spi-spi-scroll-cursor-fetch.html "PostgreSQL 11 - SPI_scroll_cursor_fetch") / [10](https://www.postgresql.org/docs/10/spi-spi-scroll-cursor-fetch.html "PostgreSQL 10 - SPI_scroll_cursor_fetch") / [9.6](https://www.postgresql.org/docs/9.6/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.6 - SPI_scroll_cursor_fetch") / [9.5](https://www.postgresql.org/docs/9.5/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.5 - SPI_scroll_cursor_fetch") / [9.4](https://www.postgresql.org/docs/9.4/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.4 - SPI_scroll_cursor_fetch") / [9.3](https://www.postgresql.org/docs/9.3/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.3 - SPI_scroll_cursor_fetch") / [9.2](https://www.postgresql.org/docs/9.2/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.2 - SPI_scroll_cursor_fetch") / [9.1](https://www.postgresql.org/docs/9.1/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.1 - SPI_scroll_cursor_fetch") / [9.0](https://www.postgresql.org/docs/9.0/spi-spi-scroll-cursor-fetch.html "PostgreSQL 9.0 - SPI_scroll_cursor_fetch") / [8.4](https://www.postgresql.org/docs/8.4/spi-spi-scroll-cursor-fetch.html "PostgreSQL 8.4 - SPI_scroll_cursor_fetch") / [8.3](https://www.postgresql.org/docs/8.3/spi-spi-scroll-cursor-fetch.html "PostgreSQL 8.3 - SPI_scroll_cursor_fetch") | SPI\_scroll\_cursor\_fetch | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-cursor-move.html "SPI_cursor_move") | [Up](https://www.postgresql.org/docs/current/spi-interface.html "45.1. Interface Functions") | 45.1. Interface Functions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/spi-spi-scroll-cursor-move.html "SPI_scroll_cursor_move") | * * * SPI\_scroll\_cursor\_fetch -------------------------- SPI\_scroll\_cursor\_fetch — fetch some rows from a cursor Synopsis -------- void SPI\_scroll\_cursor\_fetch(Portal _`portal`_, FetchDirection _`direction`_, long _`count`_) Description ----------- `SPI_scroll_cursor_fetch` fetches some rows from a cursor. This is equivalent to the SQL command `FETCH`. Arguments --------- ``Portal _`portal`_`` portal containing the cursor ``FetchDirection _`direction`_`` one of `FETCH_FORWARD`, `FETCH_BACKWARD`, `FETCH_ABSOLUTE` or `FETCH_RELATIVE` ``long _`count`_`` number of rows to fetch for `FETCH_FORWARD` or `FETCH_BACKWARD`; absolute row number to fetch for `FETCH_ABSOLUTE`; or relative row number to fetch for `FETCH_RELATIVE` Return Value ------------ `SPI_processed` and `SPI_tuptable` are set as in `SPI_execute` if successful. Notes ----- See the SQL [FETCH](https://www.postgresql.org/docs/current/sql-fetch.html "FETCH") command for details of the interpretation of the _`direction`_ and _`count`_ parameters. Direction values other than `FETCH_FORWARD` may fail if the cursor's plan was not created with the `CURSOR_OPT_SCROLL` option. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-cursor-move.html "SPI_cursor_move") | [Up](https://www.postgresql.org/docs/current/spi-interface.html "45.1. Interface Functions") | [Next](https://www.postgresql.org/docs/current/spi-spi-scroll-cursor-move.html "SPI_scroll_cursor_move") | | SPI\_cursor\_move | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | SPI\_scroll\_cursor\_move | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/spi-spi-scroll-cursor-fetch.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.14. earthdistance — calculate great-circle distances November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/earthdistance.html "PostgreSQL 18 - F.14. earthdistance — calculate great-circle distances") ([18](https://www.postgresql.org/docs/18/earthdistance.html "PostgreSQL 18 - F.14. earthdistance — calculate great-circle distances") ) / [17](https://www.postgresql.org/docs/17/earthdistance.html "PostgreSQL 17 - F.14. earthdistance — calculate great-circle distances") / [16](https://www.postgresql.org/docs/16/earthdistance.html "PostgreSQL 16 - F.14. earthdistance — calculate great-circle distances") / [15](https://www.postgresql.org/docs/15/earthdistance.html "PostgreSQL 15 - F.14. earthdistance — calculate great-circle distances") / [14](https://www.postgresql.org/docs/14/earthdistance.html "PostgreSQL 14 - F.14. earthdistance — calculate great-circle distances") Development Versions: [devel](https://www.postgresql.org/docs/devel/earthdistance.html "PostgreSQL devel - F.14. earthdistance — calculate great-circle distances") Unsupported versions: [13](https://www.postgresql.org/docs/13/earthdistance.html "PostgreSQL 13 - F.14. earthdistance — calculate great-circle distances") / [12](https://www.postgresql.org/docs/12/earthdistance.html "PostgreSQL 12 - F.14. earthdistance — calculate great-circle distances") / [11](https://www.postgresql.org/docs/11/earthdistance.html "PostgreSQL 11 - F.14. earthdistance — calculate great-circle distances") / [10](https://www.postgresql.org/docs/10/earthdistance.html "PostgreSQL 10 - F.14. earthdistance — calculate great-circle distances") / [9.6](https://www.postgresql.org/docs/9.6/earthdistance.html "PostgreSQL 9.6 - F.14. earthdistance — calculate great-circle distances") / [9.5](https://www.postgresql.org/docs/9.5/earthdistance.html "PostgreSQL 9.5 - F.14. earthdistance — calculate great-circle distances") / [9.4](https://www.postgresql.org/docs/9.4/earthdistance.html "PostgreSQL 9.4 - F.14. earthdistance — calculate great-circle distances") / [9.3](https://www.postgresql.org/docs/9.3/earthdistance.html "PostgreSQL 9.3 - F.14. earthdistance — calculate great-circle distances") / [9.2](https://www.postgresql.org/docs/9.2/earthdistance.html "PostgreSQL 9.2 - F.14. earthdistance — calculate great-circle distances") / [9.1](https://www.postgresql.org/docs/9.1/earthdistance.html "PostgreSQL 9.1 - F.14. earthdistance — calculate great-circle distances") / [9.0](https://www.postgresql.org/docs/9.0/earthdistance.html "PostgreSQL 9.0 - F.14. earthdistance — calculate great-circle distances") / [8.4](https://www.postgresql.org/docs/8.4/earthdistance.html "PostgreSQL 8.4 - F.14. earthdistance — calculate great-circle distances") / [8.3](https://www.postgresql.org/docs/8.3/earthdistance.html "PostgreSQL 8.3 - F.14. earthdistance — calculate great-circle distances") | F.14. earthdistance — calculate great-circle distances | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/dict-xsyn.html "F.13. dict_xsyn — example synonym full-text search dictionary") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/file-fdw.html "F.15. file_fdw — access data files in the server's file system") | * * * F.14. earthdistance — calculate great-circle distances [#](https://www.postgresql.org/docs/current/earthdistance.html#EARTHDISTANCE) ------------------------------------------------------------------------------------------------------------------------------------- [F.14.1. Cube-Based Earth Distances](https://www.postgresql.org/docs/current/earthdistance.html#EARTHDISTANCE-CUBE-BASED) [F.14.2. Point-Based Earth Distances](https://www.postgresql.org/docs/current/earthdistance.html#EARTHDISTANCE-POINT-BASED) The `earthdistance` module provides two different approaches to calculating great circle distances on the surface of the Earth. The one described first depends on the `cube` module. The second one is based on the built-in `point` data type, using longitude and latitude for the coordinates. In this module, the Earth is assumed to be perfectly spherical. (If that's too inaccurate for you, you might want to look at the [PostGIS](https://postgis.net/) project.) The `cube` module must be installed before `earthdistance` can be installed (although you can use the `CASCADE` option of `CREATE EXTENSION` to install both in one command). ### Caution It is strongly recommended that `earthdistance` and `cube` be installed in the same schema, and that that schema be one for which CREATE privilege has not been and will not be granted to any untrusted users. Otherwise there are installation-time security hazards if `earthdistance`'s schema contains objects defined by a hostile user. Furthermore, when using `earthdistance`'s functions after installation, the entire search path should contain only trusted schemas. ### F.14.1. Cube-Based Earth Distances [#](https://www.postgresql.org/docs/current/earthdistance.html#EARTHDISTANCE-CUBE-BASED) Data is stored in cubes that are points (both corners are the same) using 3 coordinates representing the x, y, and z distance from the center of the Earth. A [](https://www.postgresql.org/docs/current/glossary.html#GLOSSARY-DOMAIN) [domain](https://www.postgresql.org/docs/current/glossary.html#GLOSSARY-DOMAIN "Domain") `earth` over type `cube` is provided, which includes constraint checks that the value meets these restrictions and is reasonably close to the actual surface of the Earth. The radius of the Earth is obtained from the `earth()` function. It is given in meters. But by changing this one function you can change the module to use some other units, or to use a different value of the radius that you feel is more appropriate. This package has applications to astronomical databases as well. Astronomers will probably want to change `earth()` to return a radius of `180/pi()` so that distances are in degrees. Functions are provided to support input in latitude and longitude (in degrees), to support output of latitude and longitude, to calculate the great circle distance between two points and to easily specify a bounding box usable for index searches. The provided functions are shown in [Table F.4](https://www.postgresql.org/docs/current/earthdistance.html#EARTHDISTANCE-CUBE-FUNCTIONS "Table F.4. Cube-Based Earthdistance Functions") . **Table F.4. Cube-Based Earthdistance Functions** | Function

Description | | --- | | `earth` () → `float8`

Returns the assumed radius of the Earth. | | `sec_to_gc` ( `float8` ) → `float8`

Converts the normal straight line (secant) distance between two points on the surface of the Earth to the great circle distance between them. | | `gc_to_sec` ( `float8` ) → `float8`

Converts the great circle distance between two points on the surface of the Earth to the normal straight line (secant) distance between them. | | `ll_to_earth` ( `float8`, `float8` ) → `earth`

Returns the location of a point on the surface of the Earth given its latitude (argument 1) and longitude (argument 2) in degrees. | | `latitude` ( `earth` ) → `float8`

Returns the latitude in degrees of a point on the surface of the Earth. | | `longitude` ( `earth` ) → `float8`

Returns the longitude in degrees of a point on the surface of the Earth. | | `earth_distance` ( `earth`, `earth` ) → `float8`

Returns the great circle distance between two points on the surface of the Earth. | | `earth_box` ( `earth`, `float8` ) → `cube`

Returns a box suitable for an indexed search using the `cube` `@>` operator for points within a given great circle distance of a location. Some points in this box are further than the specified great circle distance from the location, so a second check using `earth_distance` should be included in the query. | ### F.14.2. Point-Based Earth Distances [#](https://www.postgresql.org/docs/current/earthdistance.html#EARTHDISTANCE-POINT-BASED) The second part of the module relies on representing Earth locations as values of type `point`, in which the first component is taken to represent longitude in degrees, and the second component is taken to represent latitude in degrees. Points are taken as (longitude, latitude) and not vice versa because longitude is closer to the intuitive idea of x-axis and latitude to y-axis. A single operator is provided, shown in [Table F.5](https://www.postgresql.org/docs/current/earthdistance.html#EARTHDISTANCE-POINT-OPERATORS "Table F.5. Point-Based Earthdistance Operators") . **Table F.5. Point-Based Earthdistance Operators** | Operator

Description | | --- | | `point` `<@>` `point` → `float8`

Computes the distance in statute miles between two points on the Earth's surface. | Note that unlike the `cube`\-based part of the module, units are hardwired here: changing the `earth()` function will not affect the results of this operator. One disadvantage of the longitude/latitude representation is that you need to be careful about the edge conditions near the poles and near +/- 180 degrees of longitude. The `cube`\-based representation avoids these discontinuities. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/dict-xsyn.html "F.13. dict_xsyn — example synonym full-text search dictionary") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/current/file-fdw.html "F.15. file_fdw — access data files in the server's file system") | | F.13. dict\_xsyn — example synonym full-text search dictionary | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | F.15. file\_fdw — access data files in the server's file system | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/earthdistance.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.7. btree_gin — GIN operator classes with B-tree behavior November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/btree-gin.html "PostgreSQL 18 - F.7. btree_gin — GIN operator classes with B-tree behavior") ([18](https://www.postgresql.org/docs/18/btree-gin.html "PostgreSQL 18 - F.7. btree_gin — GIN operator classes with B-tree behavior") ) / [17](https://www.postgresql.org/docs/17/btree-gin.html "PostgreSQL 17 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [16](https://www.postgresql.org/docs/16/btree-gin.html "PostgreSQL 16 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [15](https://www.postgresql.org/docs/15/btree-gin.html "PostgreSQL 15 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [14](https://www.postgresql.org/docs/14/btree-gin.html "PostgreSQL 14 - F.7. btree_gin — GIN operator classes with B-tree behavior") Development Versions: [devel](https://www.postgresql.org/docs/devel/btree-gin.html "PostgreSQL devel - F.7. btree_gin — GIN operator classes with B-tree behavior") Unsupported versions: [13](https://www.postgresql.org/docs/13/btree-gin.html "PostgreSQL 13 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [12](https://www.postgresql.org/docs/12/btree-gin.html "PostgreSQL 12 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [11](https://www.postgresql.org/docs/11/btree-gin.html "PostgreSQL 11 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [10](https://www.postgresql.org/docs/10/btree-gin.html "PostgreSQL 10 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.6](https://www.postgresql.org/docs/9.6/btree-gin.html "PostgreSQL 9.6 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.5](https://www.postgresql.org/docs/9.5/btree-gin.html "PostgreSQL 9.5 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.4](https://www.postgresql.org/docs/9.4/btree-gin.html "PostgreSQL 9.4 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.3](https://www.postgresql.org/docs/9.3/btree-gin.html "PostgreSQL 9.3 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.2](https://www.postgresql.org/docs/9.2/btree-gin.html "PostgreSQL 9.2 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.1](https://www.postgresql.org/docs/9.1/btree-gin.html "PostgreSQL 9.1 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [9.0](https://www.postgresql.org/docs/9.0/btree-gin.html "PostgreSQL 9.0 - F.7. btree_gin — GIN operator classes with B-tree behavior") / [8.4](https://www.postgresql.org/docs/8.4/btree-gin.html "PostgreSQL 8.4 - F.7. btree_gin — GIN operator classes with B-tree behavior") | F.7. btree\_gin — GIN operator classes with B-tree behavior | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/bloom.html "F.6. bloom — bloom filter index access method") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/btree-gist.html "F.8. btree_gist — GiST operator classes with B-tree behavior") | * * * F.7. btree\_gin — GIN operator classes with B-tree behavior [#](https://www.postgresql.org/docs/current/btree-gin.html#BTREE-GIN) ---------------------------------------------------------------------------------------------------------------------------------- [F.7.1. Example Usage](https://www.postgresql.org/docs/current/btree-gin.html#BTREE-GIN-EXAMPLE-USAGE) [F.7.2. Authors](https://www.postgresql.org/docs/current/btree-gin.html#BTREE-GIN-AUTHORS) `btree_gin` provides GIN operator classes that implement B-tree equivalent behavior for the data types `int2`, `int4`, `int8`, `float4`, `float8`, `timestamp with time zone`, `timestamp without time zone`, `time with time zone`, `time without time zone`, `date`, `interval`, `oid`, `money`, `"char"`, `varchar`, `text`, `bytea`, `bit`, `varbit`, `macaddr`, `macaddr8`, `inet`, `cidr`, `uuid`, `name`, `bool`, `bpchar`, and all `enum` types. In general, these operator classes will not outperform the equivalent standard B-tree index methods, and they lack one major feature of the standard B-tree code: the ability to enforce uniqueness. However, they are useful for GIN testing and as a base for developing other GIN operator classes. Also, for queries that test both a GIN-indexable column and a B-tree-indexable column, it might be more efficient to create a multicolumn GIN index that uses one of these operator classes than to create two separate indexes that would have to be combined via bitmap ANDing. This module is considered “trusted”, that is, it can be installed by non-superusers who have `CREATE` privilege on the current database. ### F.7.1. Example Usage [#](https://www.postgresql.org/docs/current/btree-gin.html#BTREE-GIN-EXAMPLE-USAGE) CREATE TABLE test (a int4); -- create index CREATE INDEX testidx ON test USING GIN (a); -- query SELECT \* FROM test WHERE a < 10; ### F.7.2. Authors [#](https://www.postgresql.org/docs/current/btree-gin.html#BTREE-GIN-AUTHORS) Teodor Sigaev (`<[teodor@stack.net](mailto:teodor@stack.net) >`) and Oleg Bartunov (`<[oleg@sai.msu.su](mailto:oleg@sai.msu.su) >`). See [http://www.sai.msu.su/~megera/oddmuse/index.cgi/Gin](http://www.sai.msu.su/~megera/oddmuse/index.cgi/Gin) for additional information. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/bloom.html "F.6. bloom — bloom filter index access method") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/current/btree-gist.html "F.8. btree_gist — GiST operator classes with B-tree behavior") | | F.6. bloom — bloom filter index access method | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | F.8. btree\_gist — GiST operator classes with B-tree behavior | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/btree-gin.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: DISCONNECT November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/ecpg-sql-disconnect.html "PostgreSQL 18 - DISCONNECT") ([18](https://www.postgresql.org/docs/18/ecpg-sql-disconnect.html "PostgreSQL 18 - DISCONNECT") ) / [17](https://www.postgresql.org/docs/17/ecpg-sql-disconnect.html "PostgreSQL 17 - DISCONNECT") / [16](https://www.postgresql.org/docs/16/ecpg-sql-disconnect.html "PostgreSQL 16 - DISCONNECT") / [15](https://www.postgresql.org/docs/15/ecpg-sql-disconnect.html "PostgreSQL 15 - DISCONNECT") / [14](https://www.postgresql.org/docs/14/ecpg-sql-disconnect.html "PostgreSQL 14 - DISCONNECT") Development Versions: [devel](https://www.postgresql.org/docs/devel/ecpg-sql-disconnect.html "PostgreSQL devel - DISCONNECT") Unsupported versions: [13](https://www.postgresql.org/docs/13/ecpg-sql-disconnect.html "PostgreSQL 13 - DISCONNECT") / [12](https://www.postgresql.org/docs/12/ecpg-sql-disconnect.html "PostgreSQL 12 - DISCONNECT") / [11](https://www.postgresql.org/docs/11/ecpg-sql-disconnect.html "PostgreSQL 11 - DISCONNECT") / [10](https://www.postgresql.org/docs/10/ecpg-sql-disconnect.html "PostgreSQL 10 - DISCONNECT") / [9.6](https://www.postgresql.org/docs/9.6/ecpg-sql-disconnect.html "PostgreSQL 9.6 - DISCONNECT") / [9.5](https://www.postgresql.org/docs/9.5/ecpg-sql-disconnect.html "PostgreSQL 9.5 - DISCONNECT") / [9.4](https://www.postgresql.org/docs/9.4/ecpg-sql-disconnect.html "PostgreSQL 9.4 - DISCONNECT") / [9.3](https://www.postgresql.org/docs/9.3/ecpg-sql-disconnect.html "PostgreSQL 9.3 - DISCONNECT") / [9.2](https://www.postgresql.org/docs/9.2/ecpg-sql-disconnect.html "PostgreSQL 9.2 - DISCONNECT") / [9.1](https://www.postgresql.org/docs/9.1/ecpg-sql-disconnect.html "PostgreSQL 9.1 - DISCONNECT") | DISCONNECT | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/ecpg-sql-describe.html "DESCRIBE") | [Up](https://www.postgresql.org/docs/current/ecpg-sql-commands.html "34.14. Embedded SQL Commands") | 34.14. Embedded SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/ecpg-sql-execute-immediate.html "EXECUTE IMMEDIATE") | * * * DISCONNECT ---------- DISCONNECT — terminate a database connection Synopsis -------- DISCONNECT _`connection_name`_ DISCONNECT \[ CURRENT \] DISCONNECT ALL Description ----------- `DISCONNECT` closes a connection (or all connections) to the database. Parameters ---------- _`connection_name`_ [#](https://www.postgresql.org/docs/current/ecpg-sql-disconnect.html#ECPG-SQL-DISCONNECT-CONNECTION-NAME) A database connection name established by the `CONNECT` command. `CURRENT` [#](https://www.postgresql.org/docs/current/ecpg-sql-disconnect.html#ECPG-SQL-DISCONNECT-CURRENT) Close the “current” connection, which is either the most recently opened connection, or the connection set by the `SET CONNECTION` command. This is also the default if no argument is given to the `DISCONNECT` command. `ALL` [#](https://www.postgresql.org/docs/current/ecpg-sql-disconnect.html#ECPG-SQL-DISCONNECT-ALL) Close all open connections. Examples -------- int main(void) { EXEC SQL CONNECT TO testdb AS con1 USER testuser; EXEC SQL CONNECT TO testdb AS con2 USER testuser; EXEC SQL CONNECT TO testdb AS con3 USER testuser; EXEC SQL DISCONNECT CURRENT; /\* close con3 \*/ EXEC SQL DISCONNECT ALL; /\* close con2 and con1 \*/ return 0; } Compatibility ------------- `DISCONNECT` is specified in the SQL standard. See Also -------- [CONNECT](https://www.postgresql.org/docs/current/ecpg-sql-connect.html "CONNECT") , [SET CONNECTION](https://www.postgresql.org/docs/current/ecpg-sql-set-connection.html "SET CONNECTION") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/ecpg-sql-describe.html "DESCRIBE") | [Up](https://www.postgresql.org/docs/current/ecpg-sql-commands.html "34.14. Embedded SQL Commands") | [Next](https://www.postgresql.org/docs/current/ecpg-sql-execute-immediate.html "EXECUTE IMMEDIATE") | | DESCRIBE | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | EXECUTE IMMEDIATE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/ecpg-sql-disconnect.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: SPI_cursor_move November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/spi-spi-cursor-move.html "PostgreSQL 18 - SPI_cursor_move") ([18](https://www.postgresql.org/docs/18/spi-spi-cursor-move.html "PostgreSQL 18 - SPI_cursor_move") ) / [17](https://www.postgresql.org/docs/17/spi-spi-cursor-move.html "PostgreSQL 17 - SPI_cursor_move") / [16](https://www.postgresql.org/docs/16/spi-spi-cursor-move.html "PostgreSQL 16 - SPI_cursor_move") / [15](https://www.postgresql.org/docs/15/spi-spi-cursor-move.html "PostgreSQL 15 - SPI_cursor_move") / [14](https://www.postgresql.org/docs/14/spi-spi-cursor-move.html "PostgreSQL 14 - SPI_cursor_move") Development Versions: [devel](https://www.postgresql.org/docs/devel/spi-spi-cursor-move.html "PostgreSQL devel - SPI_cursor_move") Unsupported versions: [13](https://www.postgresql.org/docs/13/spi-spi-cursor-move.html "PostgreSQL 13 - SPI_cursor_move") / [12](https://www.postgresql.org/docs/12/spi-spi-cursor-move.html "PostgreSQL 12 - SPI_cursor_move") / [11](https://www.postgresql.org/docs/11/spi-spi-cursor-move.html "PostgreSQL 11 - SPI_cursor_move") / [10](https://www.postgresql.org/docs/10/spi-spi-cursor-move.html "PostgreSQL 10 - SPI_cursor_move") / [9.6](https://www.postgresql.org/docs/9.6/spi-spi-cursor-move.html "PostgreSQL 9.6 - SPI_cursor_move") / [9.5](https://www.postgresql.org/docs/9.5/spi-spi-cursor-move.html "PostgreSQL 9.5 - SPI_cursor_move") / [9.4](https://www.postgresql.org/docs/9.4/spi-spi-cursor-move.html "PostgreSQL 9.4 - SPI_cursor_move") / [9.3](https://www.postgresql.org/docs/9.3/spi-spi-cursor-move.html "PostgreSQL 9.3 - SPI_cursor_move") / [9.2](https://www.postgresql.org/docs/9.2/spi-spi-cursor-move.html "PostgreSQL 9.2 - SPI_cursor_move") / [9.1](https://www.postgresql.org/docs/9.1/spi-spi-cursor-move.html "PostgreSQL 9.1 - SPI_cursor_move") / [9.0](https://www.postgresql.org/docs/9.0/spi-spi-cursor-move.html "PostgreSQL 9.0 - SPI_cursor_move") / [8.4](https://www.postgresql.org/docs/8.4/spi-spi-cursor-move.html "PostgreSQL 8.4 - SPI_cursor_move") / [8.3](https://www.postgresql.org/docs/8.3/spi-spi-cursor-move.html "PostgreSQL 8.3 - SPI_cursor_move") / [8.2](https://www.postgresql.org/docs/8.2/spi-spi-cursor-move.html "PostgreSQL 8.2 - SPI_cursor_move") / [8.1](https://www.postgresql.org/docs/8.1/spi-spi-cursor-move.html "PostgreSQL 8.1 - SPI_cursor_move") / [8.0](https://www.postgresql.org/docs/8.0/spi-spi-cursor-move.html "PostgreSQL 8.0 - SPI_cursor_move") / [7.4](https://www.postgresql.org/docs/7.4/spi-spi-cursor-move.html "PostgreSQL 7.4 - SPI_cursor_move") | SPI\_cursor\_move | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-cursor-fetch.html "SPI_cursor_fetch") | [Up](https://www.postgresql.org/docs/18/spi-interface.html "45.1. Interface Functions") | 45.1. Interface Functions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/spi-spi-scroll-cursor-fetch.html "SPI_scroll_cursor_fetch") | * * * SPI\_cursor\_move ----------------- SPI\_cursor\_move — move a cursor Synopsis -------- void SPI\_cursor\_move(Portal _`portal`_, bool _`forward`_, long _`count`_) Description ----------- `SPI_cursor_move` skips over some number of rows in a cursor. This is equivalent to a subset of the SQL command `MOVE` (see `SPI_scroll_cursor_move` for more functionality). Arguments --------- ``Portal _`portal`_`` portal containing the cursor ``bool _`forward`_`` true for move forward, false for move backward ``long _`count`_`` maximum number of rows to move Notes ----- Moving backward may fail if the cursor's plan was not created with the `CURSOR_OPT_SCROLL` option. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-cursor-fetch.html "SPI_cursor_fetch") | [Up](https://www.postgresql.org/docs/18/spi-interface.html "45.1. Interface Functions") | [Next](https://www.postgresql.org/docs/18/spi-spi-scroll-cursor-fetch.html "SPI_scroll_cursor_fetch") | | SPI\_cursor\_fetch | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | SPI\_scroll\_cursor\_fetch | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/spi-spi-cursor-move.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE TEXT SEARCH PARSER November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createtsparser.html "PostgreSQL 18 - CREATE TEXT SEARCH PARSER") ([18](https://www.postgresql.org/docs/18/sql-createtsparser.html "PostgreSQL 18 - CREATE TEXT SEARCH PARSER") ) / [17](https://www.postgresql.org/docs/17/sql-createtsparser.html "PostgreSQL 17 - CREATE TEXT SEARCH PARSER") / [16](https://www.postgresql.org/docs/16/sql-createtsparser.html "PostgreSQL 16 - CREATE TEXT SEARCH PARSER") / [15](https://www.postgresql.org/docs/15/sql-createtsparser.html "PostgreSQL 15 - CREATE TEXT SEARCH PARSER") / [14](https://www.postgresql.org/docs/14/sql-createtsparser.html "PostgreSQL 14 - CREATE TEXT SEARCH PARSER") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createtsparser.html "PostgreSQL devel - CREATE TEXT SEARCH PARSER") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createtsparser.html "PostgreSQL 13 - CREATE TEXT SEARCH PARSER") / [12](https://www.postgresql.org/docs/12/sql-createtsparser.html "PostgreSQL 12 - CREATE TEXT SEARCH PARSER") / [11](https://www.postgresql.org/docs/11/sql-createtsparser.html "PostgreSQL 11 - CREATE TEXT SEARCH PARSER") / [10](https://www.postgresql.org/docs/10/sql-createtsparser.html "PostgreSQL 10 - CREATE TEXT SEARCH PARSER") / [9.6](https://www.postgresql.org/docs/9.6/sql-createtsparser.html "PostgreSQL 9.6 - CREATE TEXT SEARCH PARSER") / [9.5](https://www.postgresql.org/docs/9.5/sql-createtsparser.html "PostgreSQL 9.5 - CREATE TEXT SEARCH PARSER") / [9.4](https://www.postgresql.org/docs/9.4/sql-createtsparser.html "PostgreSQL 9.4 - CREATE TEXT SEARCH PARSER") / [9.3](https://www.postgresql.org/docs/9.3/sql-createtsparser.html "PostgreSQL 9.3 - CREATE TEXT SEARCH PARSER") / [9.2](https://www.postgresql.org/docs/9.2/sql-createtsparser.html "PostgreSQL 9.2 - CREATE TEXT SEARCH PARSER") / [9.1](https://www.postgresql.org/docs/9.1/sql-createtsparser.html "PostgreSQL 9.1 - CREATE TEXT SEARCH PARSER") / [9.0](https://www.postgresql.org/docs/9.0/sql-createtsparser.html "PostgreSQL 9.0 - CREATE TEXT SEARCH PARSER") / [8.4](https://www.postgresql.org/docs/8.4/sql-createtsparser.html "PostgreSQL 8.4 - CREATE TEXT SEARCH PARSER") / [8.3](https://www.postgresql.org/docs/8.3/sql-createtsparser.html "PostgreSQL 8.3 - CREATE TEXT SEARCH PARSER") | CREATE TEXT SEARCH PARSER | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createtsdictionary.html "CREATE TEXT SEARCH DICTIONARY") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-createtstemplate.html "CREATE TEXT SEARCH TEMPLATE") | * * * CREATE TEXT SEARCH PARSER ------------------------- CREATE TEXT SEARCH PARSER — define a new text search parser Synopsis -------- CREATE TEXT SEARCH PARSER _`name`_ ( START = _`start_function`_ , GETTOKEN = _`gettoken_function`_ , END = _`end_function`_ , LEXTYPES = _`lextypes_function`_ \[, HEADLINE = _`headline_function`_ \] ) Description ----------- `CREATE TEXT SEARCH PARSER` creates a new text search parser. A text search parser defines a method for splitting a text string into tokens and assigning types (categories) to the tokens. A parser is not particularly useful by itself, but must be bound into a text search configuration along with some text search dictionaries to be used for searching. If a schema name is given then the text search parser is created in the specified schema. Otherwise it is created in the current schema. You must be a superuser to use `CREATE TEXT SEARCH PARSER`. (This restriction is made because an erroneous text search parser definition could confuse or even crash the server.) Refer to [Chapter 12](https://www.postgresql.org/docs/18/textsearch.html "Chapter 12. Full Text Search") for further information. Parameters ---------- _`name`_ The name of the text search parser to be created. The name can be schema-qualified. _`start_function`_ The name of the start function for the parser. _`gettoken_function`_ The name of the get-next-token function for the parser. _`end_function`_ The name of the end function for the parser. _`lextypes_function`_ The name of the lextypes function for the parser (a function that returns information about the set of token types it produces). _`headline_function`_ The name of the headline function for the parser (a function that summarizes a set of tokens). The function names can be schema-qualified if necessary. Argument types are not given, since the argument list for each type of function is predetermined. All except the headline function are required. The arguments can appear in any order, not only the one shown above. Compatibility ------------- There is no `CREATE TEXT SEARCH PARSER` statement in the SQL standard. See Also -------- [ALTER TEXT SEARCH PARSER](https://www.postgresql.org/docs/18/sql-altertsparser.html "ALTER TEXT SEARCH PARSER") , [DROP TEXT SEARCH PARSER](https://www.postgresql.org/docs/18/sql-droptsparser.html "DROP TEXT SEARCH PARSER") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createtsdictionary.html "CREATE TEXT SEARCH DICTIONARY") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-createtstemplate.html "CREATE TEXT SEARCH TEMPLATE") | | CREATE TEXT SEARCH DICTIONARY | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | CREATE TEXT SEARCH TEMPLATE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createtsparser.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.5. applicable_roles November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-applicable-roles.html "PostgreSQL 18 - 35.5. applicable_roles") ([18](https://www.postgresql.org/docs/18/infoschema-applicable-roles.html "PostgreSQL 18 - 35.5. applicable_roles") ) / [17](https://www.postgresql.org/docs/17/infoschema-applicable-roles.html "PostgreSQL 17 - 35.5. applicable_roles") / [16](https://www.postgresql.org/docs/16/infoschema-applicable-roles.html "PostgreSQL 16 - 35.5. applicable_roles") / [15](https://www.postgresql.org/docs/15/infoschema-applicable-roles.html "PostgreSQL 15 - 35.5. applicable_roles") / [14](https://www.postgresql.org/docs/14/infoschema-applicable-roles.html "PostgreSQL 14 - 35.5. applicable_roles") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-applicable-roles.html "PostgreSQL devel - 35.5. applicable_roles") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-applicable-roles.html "PostgreSQL 13 - 35.5. applicable_roles") / [12](https://www.postgresql.org/docs/12/infoschema-applicable-roles.html "PostgreSQL 12 - 35.5. applicable_roles") / [11](https://www.postgresql.org/docs/11/infoschema-applicable-roles.html "PostgreSQL 11 - 35.5. applicable_roles") / [10](https://www.postgresql.org/docs/10/infoschema-applicable-roles.html "PostgreSQL 10 - 35.5. applicable_roles") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-applicable-roles.html "PostgreSQL 9.6 - 35.5. applicable_roles") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-applicable-roles.html "PostgreSQL 9.5 - 35.5. applicable_roles") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-applicable-roles.html "PostgreSQL 9.4 - 35.5. applicable_roles") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-applicable-roles.html "PostgreSQL 9.3 - 35.5. applicable_roles") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-applicable-roles.html "PostgreSQL 9.2 - 35.5. applicable_roles") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-applicable-roles.html "PostgreSQL 9.1 - 35.5. applicable_roles") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-applicable-roles.html "PostgreSQL 9.0 - 35.5. applicable_roles") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-applicable-roles.html "PostgreSQL 8.4 - 35.5. applicable_roles") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-applicable-roles.html "PostgreSQL 8.3 - 35.5. applicable_roles") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-applicable-roles.html "PostgreSQL 8.2 - 35.5. applicable_roles") / [8.1](https://www.postgresql.org/docs/8.1/infoschema-applicable-roles.html "PostgreSQL 8.1 - 35.5. applicable_roles") / [8.0](https://www.postgresql.org/docs/8.0/infoschema-applicable-roles.html "PostgreSQL 8.0 - 35.5. applicable_roles") / [7.4](https://www.postgresql.org/docs/7.4/infoschema-applicable-roles.html "PostgreSQL 7.4 - 35.5. applicable_roles") | 35.5. `applicable_roles` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-administrable-role-authorizations.html "35.4. administrable_role_​authorizations") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/infoschema-attributes.html "35.6. attributes") | * * * 35.5. `applicable_roles` [#](https://www.postgresql.org/docs/current/infoschema-applicable-roles.html#INFOSCHEMA-APPLICABLE-ROLES) ----------------------------------------------------------------------------------------------------------------------------------- The view `applicable_roles` identifies all roles whose privileges the current user can use. This means there is some chain of role grants from the current user to the role in question. The current user itself is also an applicable role. The set of applicable roles is generally used for permission checking. **Table 35.3. `applicable_roles` Columns** | Column Type

Description | | --- | | `grantee` `sql_identifier`

Name of the role to which this role membership was granted (can be the current user, or a different role in case of nested role memberships) | | `role_name` `sql_identifier`

Name of a role | | `is_grantable` `yes_or_no`

`YES` if the grantee has the admin option on the role, `NO` if not | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-administrable-role-authorizations.html "35.4. administrable_role_​authorizations") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/current/infoschema-attributes.html "35.6. attributes") | | 35.4. `administrable_role_​authorizations` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 35.6. `attributes` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-applicable-roles.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: SPI_cursor_move November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/spi-spi-cursor-move.html "PostgreSQL 18 - SPI_cursor_move") ([18](https://www.postgresql.org/docs/18/spi-spi-cursor-move.html "PostgreSQL 18 - SPI_cursor_move") ) / [17](https://www.postgresql.org/docs/17/spi-spi-cursor-move.html "PostgreSQL 17 - SPI_cursor_move") / [16](https://www.postgresql.org/docs/16/spi-spi-cursor-move.html "PostgreSQL 16 - SPI_cursor_move") / [15](https://www.postgresql.org/docs/15/spi-spi-cursor-move.html "PostgreSQL 15 - SPI_cursor_move") / [14](https://www.postgresql.org/docs/14/spi-spi-cursor-move.html "PostgreSQL 14 - SPI_cursor_move") Development Versions: [devel](https://www.postgresql.org/docs/devel/spi-spi-cursor-move.html "PostgreSQL devel - SPI_cursor_move") Unsupported versions: [13](https://www.postgresql.org/docs/13/spi-spi-cursor-move.html "PostgreSQL 13 - SPI_cursor_move") / [12](https://www.postgresql.org/docs/12/spi-spi-cursor-move.html "PostgreSQL 12 - SPI_cursor_move") / [11](https://www.postgresql.org/docs/11/spi-spi-cursor-move.html "PostgreSQL 11 - SPI_cursor_move") / [10](https://www.postgresql.org/docs/10/spi-spi-cursor-move.html "PostgreSQL 10 - SPI_cursor_move") / [9.6](https://www.postgresql.org/docs/9.6/spi-spi-cursor-move.html "PostgreSQL 9.6 - SPI_cursor_move") / [9.5](https://www.postgresql.org/docs/9.5/spi-spi-cursor-move.html "PostgreSQL 9.5 - SPI_cursor_move") / [9.4](https://www.postgresql.org/docs/9.4/spi-spi-cursor-move.html "PostgreSQL 9.4 - SPI_cursor_move") / [9.3](https://www.postgresql.org/docs/9.3/spi-spi-cursor-move.html "PostgreSQL 9.3 - SPI_cursor_move") / [9.2](https://www.postgresql.org/docs/9.2/spi-spi-cursor-move.html "PostgreSQL 9.2 - SPI_cursor_move") / [9.1](https://www.postgresql.org/docs/9.1/spi-spi-cursor-move.html "PostgreSQL 9.1 - SPI_cursor_move") / [9.0](https://www.postgresql.org/docs/9.0/spi-spi-cursor-move.html "PostgreSQL 9.0 - SPI_cursor_move") / [8.4](https://www.postgresql.org/docs/8.4/spi-spi-cursor-move.html "PostgreSQL 8.4 - SPI_cursor_move") / [8.3](https://www.postgresql.org/docs/8.3/spi-spi-cursor-move.html "PostgreSQL 8.3 - SPI_cursor_move") / [8.2](https://www.postgresql.org/docs/8.2/spi-spi-cursor-move.html "PostgreSQL 8.2 - SPI_cursor_move") / [8.1](https://www.postgresql.org/docs/8.1/spi-spi-cursor-move.html "PostgreSQL 8.1 - SPI_cursor_move") / [8.0](https://www.postgresql.org/docs/8.0/spi-spi-cursor-move.html "PostgreSQL 8.0 - SPI_cursor_move") / [7.4](https://www.postgresql.org/docs/7.4/spi-spi-cursor-move.html "PostgreSQL 7.4 - SPI_cursor_move") | SPI\_cursor\_move | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-cursor-fetch.html "SPI_cursor_fetch") | [Up](https://www.postgresql.org/docs/current/spi-interface.html "45.1. Interface Functions") | 45.1. Interface Functions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/spi-spi-scroll-cursor-fetch.html "SPI_scroll_cursor_fetch") | * * * SPI\_cursor\_move ----------------- SPI\_cursor\_move — move a cursor Synopsis -------- void SPI\_cursor\_move(Portal _`portal`_, bool _`forward`_, long _`count`_) Description ----------- `SPI_cursor_move` skips over some number of rows in a cursor. This is equivalent to a subset of the SQL command `MOVE` (see `SPI_scroll_cursor_move` for more functionality). Arguments --------- ``Portal _`portal`_`` portal containing the cursor ``bool _`forward`_`` true for move forward, false for move backward ``long _`count`_`` maximum number of rows to move Notes ----- Moving backward may fail if the cursor's plan was not created with the `CURSOR_OPT_SCROLL` option. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-cursor-fetch.html "SPI_cursor_fetch") | [Up](https://www.postgresql.org/docs/current/spi-interface.html "45.1. Interface Functions") | [Next](https://www.postgresql.org/docs/current/spi-spi-scroll-cursor-fetch.html "SPI_scroll_cursor_fetch") | | SPI\_cursor\_fetch | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | SPI\_scroll\_cursor\_fetch | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/spi-spi-cursor-move.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.4. administrable_role_​authorizations November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-administrable-role-authorizations.html "PostgreSQL 18 - 35.4. administrable_role_​authorizations") ([18](https://www.postgresql.org/docs/18/infoschema-administrable-role-authorizations.html "PostgreSQL 18 - 35.4. administrable_role_​authorizations") ) / [17](https://www.postgresql.org/docs/17/infoschema-administrable-role-authorizations.html "PostgreSQL 17 - 35.4. administrable_role_​authorizations") / [16](https://www.postgresql.org/docs/16/infoschema-administrable-role-authorizations.html "PostgreSQL 16 - 35.4. administrable_role_​authorizations") / [15](https://www.postgresql.org/docs/15/infoschema-administrable-role-authorizations.html "PostgreSQL 15 - 35.4. administrable_role_​authorizations") / [14](https://www.postgresql.org/docs/14/infoschema-administrable-role-authorizations.html "PostgreSQL 14 - 35.4. administrable_role_​authorizations") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-administrable-role-authorizations.html "PostgreSQL devel - 35.4. administrable_role_​authorizations") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-administrable-role-authorizations.html "PostgreSQL 13 - 35.4. administrable_role_​authorizations") / [12](https://www.postgresql.org/docs/12/infoschema-administrable-role-authorizations.html "PostgreSQL 12 - 35.4. administrable_role_​authorizations") / [11](https://www.postgresql.org/docs/11/infoschema-administrable-role-authorizations.html "PostgreSQL 11 - 35.4. administrable_role_​authorizations") / [10](https://www.postgresql.org/docs/10/infoschema-administrable-role-authorizations.html "PostgreSQL 10 - 35.4. administrable_role_​authorizations") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-administrable-role-authorizations.html "PostgreSQL 9.6 - 35.4. administrable_role_​authorizations") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-administrable-role-authorizations.html "PostgreSQL 9.5 - 35.4. administrable_role_​authorizations") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-administrable-role-authorizations.html "PostgreSQL 9.4 - 35.4. administrable_role_​authorizations") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-administrable-role-authorizations.html "PostgreSQL 9.3 - 35.4. administrable_role_​authorizations") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-administrable-role-authorizations.html "PostgreSQL 9.2 - 35.4. administrable_role_​authorizations") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-administrable-role-authorizations.html "PostgreSQL 9.1 - 35.4. administrable_role_​authorizations") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-administrable-role-authorizations.html "PostgreSQL 9.0 - 35.4. administrable_role_​authorizations") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-administrable-role-authorizations.html "PostgreSQL 8.4 - 35.4. administrable_role_​authorizations") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-administrable-role-authorizations.html "PostgreSQL 8.3 - 35.4. administrable_role_​authorizations") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-administrable-role-authorizations.html "PostgreSQL 8.2 - 35.4. administrable_role_​authorizations") | 35.4. `administrable_role_​authorizations` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-information-schema-catalog-name.html "35.3. information_schema_catalog_name") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/infoschema-applicable-roles.html "35.5. applicable_roles") | * * * 35.4. `administrable_role_​authorizations` [#](https://www.postgresql.org/docs/18/infoschema-administrable-role-authorizations.html#INFOSCHEMA-ADMINISTRABLE-ROLE-AUTHORIZATIONS) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The view `administrable_role_authorizations` identifies all roles that the current user has the admin option for. **Table 35.2. `administrable_role_authorizations` Columns** | Column Type

Description | | --- | | `grantee` `sql_identifier`

Name of the role to which this role membership was granted (can be the current user, or a different role in case of nested role memberships) | | `role_name` `sql_identifier`

Name of a role | | `is_grantable` `yes_or_no`

Always `YES` | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-information-schema-catalog-name.html "35.3. information_schema_catalog_name") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/18/infoschema-applicable-roles.html "35.5. applicable_roles") | | 35.3. `information_schema_catalog_name` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 35.5. `applicable_roles` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-administrable-role-authorizations.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.5. applicable_roles November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-applicable-roles.html "PostgreSQL 18 - 35.5. applicable_roles") ([18](https://www.postgresql.org/docs/18/infoschema-applicable-roles.html "PostgreSQL 18 - 35.5. applicable_roles") ) / [17](https://www.postgresql.org/docs/17/infoschema-applicable-roles.html "PostgreSQL 17 - 35.5. applicable_roles") / [16](https://www.postgresql.org/docs/16/infoschema-applicable-roles.html "PostgreSQL 16 - 35.5. applicable_roles") / [15](https://www.postgresql.org/docs/15/infoschema-applicable-roles.html "PostgreSQL 15 - 35.5. applicable_roles") / [14](https://www.postgresql.org/docs/14/infoschema-applicable-roles.html "PostgreSQL 14 - 35.5. applicable_roles") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-applicable-roles.html "PostgreSQL devel - 35.5. applicable_roles") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-applicable-roles.html "PostgreSQL 13 - 35.5. applicable_roles") / [12](https://www.postgresql.org/docs/12/infoschema-applicable-roles.html "PostgreSQL 12 - 35.5. applicable_roles") / [11](https://www.postgresql.org/docs/11/infoschema-applicable-roles.html "PostgreSQL 11 - 35.5. applicable_roles") / [10](https://www.postgresql.org/docs/10/infoschema-applicable-roles.html "PostgreSQL 10 - 35.5. applicable_roles") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-applicable-roles.html "PostgreSQL 9.6 - 35.5. applicable_roles") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-applicable-roles.html "PostgreSQL 9.5 - 35.5. applicable_roles") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-applicable-roles.html "PostgreSQL 9.4 - 35.5. applicable_roles") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-applicable-roles.html "PostgreSQL 9.3 - 35.5. applicable_roles") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-applicable-roles.html "PostgreSQL 9.2 - 35.5. applicable_roles") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-applicable-roles.html "PostgreSQL 9.1 - 35.5. applicable_roles") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-applicable-roles.html "PostgreSQL 9.0 - 35.5. applicable_roles") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-applicable-roles.html "PostgreSQL 8.4 - 35.5. applicable_roles") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-applicable-roles.html "PostgreSQL 8.3 - 35.5. applicable_roles") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-applicable-roles.html "PostgreSQL 8.2 - 35.5. applicable_roles") / [8.1](https://www.postgresql.org/docs/8.1/infoschema-applicable-roles.html "PostgreSQL 8.1 - 35.5. applicable_roles") / [8.0](https://www.postgresql.org/docs/8.0/infoschema-applicable-roles.html "PostgreSQL 8.0 - 35.5. applicable_roles") / [7.4](https://www.postgresql.org/docs/7.4/infoschema-applicable-roles.html "PostgreSQL 7.4 - 35.5. applicable_roles") | 35.5. `applicable_roles` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-administrable-role-authorizations.html "35.4. administrable_role_​authorizations") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/infoschema-attributes.html "35.6. attributes") | * * * 35.5. `applicable_roles` [#](https://www.postgresql.org/docs/18/infoschema-applicable-roles.html#INFOSCHEMA-APPLICABLE-ROLES) ------------------------------------------------------------------------------------------------------------------------------ The view `applicable_roles` identifies all roles whose privileges the current user can use. This means there is some chain of role grants from the current user to the role in question. The current user itself is also an applicable role. The set of applicable roles is generally used for permission checking. **Table 35.3. `applicable_roles` Columns** | Column Type

Description | | --- | | `grantee` `sql_identifier`

Name of the role to which this role membership was granted (can be the current user, or a different role in case of nested role memberships) | | `role_name` `sql_identifier`

Name of a role | | `is_grantable` `yes_or_no`

`YES` if the grantee has the admin option on the role, `NO` if not | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-administrable-role-authorizations.html "35.4. administrable_role_​authorizations") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/18/infoschema-attributes.html "35.6. attributes") | | 35.4. `administrable_role_​authorizations` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 35.6. `attributes` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-applicable-roles.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.4. administrable_role_​authorizations November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-administrable-role-authorizations.html "PostgreSQL 18 - 35.4. administrable_role_​authorizations") ([18](https://www.postgresql.org/docs/18/infoschema-administrable-role-authorizations.html "PostgreSQL 18 - 35.4. administrable_role_​authorizations") ) / [17](https://www.postgresql.org/docs/17/infoschema-administrable-role-authorizations.html "PostgreSQL 17 - 35.4. administrable_role_​authorizations") / [16](https://www.postgresql.org/docs/16/infoschema-administrable-role-authorizations.html "PostgreSQL 16 - 35.4. administrable_role_​authorizations") / [15](https://www.postgresql.org/docs/15/infoschema-administrable-role-authorizations.html "PostgreSQL 15 - 35.4. administrable_role_​authorizations") / [14](https://www.postgresql.org/docs/14/infoschema-administrable-role-authorizations.html "PostgreSQL 14 - 35.4. administrable_role_​authorizations") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-administrable-role-authorizations.html "PostgreSQL devel - 35.4. administrable_role_​authorizations") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-administrable-role-authorizations.html "PostgreSQL 13 - 35.4. administrable_role_​authorizations") / [12](https://www.postgresql.org/docs/12/infoschema-administrable-role-authorizations.html "PostgreSQL 12 - 35.4. administrable_role_​authorizations") / [11](https://www.postgresql.org/docs/11/infoschema-administrable-role-authorizations.html "PostgreSQL 11 - 35.4. administrable_role_​authorizations") / [10](https://www.postgresql.org/docs/10/infoschema-administrable-role-authorizations.html "PostgreSQL 10 - 35.4. administrable_role_​authorizations") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-administrable-role-authorizations.html "PostgreSQL 9.6 - 35.4. administrable_role_​authorizations") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-administrable-role-authorizations.html "PostgreSQL 9.5 - 35.4. administrable_role_​authorizations") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-administrable-role-authorizations.html "PostgreSQL 9.4 - 35.4. administrable_role_​authorizations") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-administrable-role-authorizations.html "PostgreSQL 9.3 - 35.4. administrable_role_​authorizations") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-administrable-role-authorizations.html "PostgreSQL 9.2 - 35.4. administrable_role_​authorizations") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-administrable-role-authorizations.html "PostgreSQL 9.1 - 35.4. administrable_role_​authorizations") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-administrable-role-authorizations.html "PostgreSQL 9.0 - 35.4. administrable_role_​authorizations") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-administrable-role-authorizations.html "PostgreSQL 8.4 - 35.4. administrable_role_​authorizations") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-administrable-role-authorizations.html "PostgreSQL 8.3 - 35.4. administrable_role_​authorizations") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-administrable-role-authorizations.html "PostgreSQL 8.2 - 35.4. administrable_role_​authorizations") | 35.4. `administrable_role_​authorizations` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-information-schema-catalog-name.html "35.3. information_schema_catalog_name") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/infoschema-applicable-roles.html "35.5. applicable_roles") | * * * 35.4. `administrable_role_​authorizations` [#](https://www.postgresql.org/docs/current/infoschema-administrable-role-authorizations.html#INFOSCHEMA-ADMINISTRABLE-ROLE-AUTHORIZATIONS) --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The view `administrable_role_authorizations` identifies all roles that the current user has the admin option for. **Table 35.2. `administrable_role_authorizations` Columns** | Column Type

Description | | --- | | `grantee` `sql_identifier`

Name of the role to which this role membership was granted (can be the current user, or a different role in case of nested role memberships) | | `role_name` `sql_identifier`

Name of a role | | `is_grantable` `yes_or_no`

Always `YES` | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-information-schema-catalog-name.html "35.3. information_schema_catalog_name") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/current/infoschema-applicable-roles.html "35.5. applicable_roles") | | 35.3. `information_schema_catalog_name` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 35.5. `applicable_roles` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-administrable-role-authorizations.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: H.4. Extensions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/external-extensions.html "PostgreSQL 18 - H.4. Extensions") ([18](https://www.postgresql.org/docs/18/external-extensions.html "PostgreSQL 18 - H.4. Extensions") ) / [17](https://www.postgresql.org/docs/17/external-extensions.html "PostgreSQL 17 - H.4. Extensions") / [16](https://www.postgresql.org/docs/16/external-extensions.html "PostgreSQL 16 - H.4. Extensions") / [15](https://www.postgresql.org/docs/15/external-extensions.html "PostgreSQL 15 - H.4. Extensions") / [14](https://www.postgresql.org/docs/14/external-extensions.html "PostgreSQL 14 - H.4. Extensions") Development Versions: [devel](https://www.postgresql.org/docs/devel/external-extensions.html "PostgreSQL devel - H.4. Extensions") Unsupported versions: [13](https://www.postgresql.org/docs/13/external-extensions.html "PostgreSQL 13 - H.4. Extensions") / [12](https://www.postgresql.org/docs/12/external-extensions.html "PostgreSQL 12 - H.4. Extensions") / [11](https://www.postgresql.org/docs/11/external-extensions.html "PostgreSQL 11 - H.4. Extensions") / [10](https://www.postgresql.org/docs/10/external-extensions.html "PostgreSQL 10 - H.4. Extensions") / [9.6](https://www.postgresql.org/docs/9.6/external-extensions.html "PostgreSQL 9.6 - H.4. Extensions") / [9.5](https://www.postgresql.org/docs/9.5/external-extensions.html "PostgreSQL 9.5 - H.4. Extensions") / [9.4](https://www.postgresql.org/docs/9.4/external-extensions.html "PostgreSQL 9.4 - H.4. Extensions") / [9.3](https://www.postgresql.org/docs/9.3/external-extensions.html "PostgreSQL 9.3 - H.4. Extensions") / [9.2](https://www.postgresql.org/docs/9.2/external-extensions.html "PostgreSQL 9.2 - H.4. Extensions") / [9.1](https://www.postgresql.org/docs/9.1/external-extensions.html "PostgreSQL 9.1 - H.4. Extensions") / [9.0](https://www.postgresql.org/docs/9.0/external-extensions.html "PostgreSQL 9.0 - H.4. Extensions") / [8.4](https://www.postgresql.org/docs/8.4/external-extensions.html "PostgreSQL 8.4 - H.4. Extensions") / [8.3](https://www.postgresql.org/docs/8.3/external-extensions.html "PostgreSQL 8.3 - H.4. Extensions") / [8.2](https://www.postgresql.org/docs/8.2/external-extensions.html "PostgreSQL 8.2 - H.4. Extensions") / [8.1](https://www.postgresql.org/docs/8.1/external-extensions.html "PostgreSQL 8.1 - H.4. Extensions") / [8.0](https://www.postgresql.org/docs/8.0/external-extensions.html "PostgreSQL 8.0 - H.4. Extensions") | H.4. Extensions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/external-pl.html "H.3. Procedural Languages") | [Up](https://www.postgresql.org/docs/current/external-projects.html "Appendix H. External Projects") | Appendix H. External Projects | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sourcerepo.html "Appendix I. The Source Code Repository") | * * * H.4. Extensions [#](https://www.postgresql.org/docs/current/external-extensions.html#EXTERNAL-EXTENSIONS) ---------------------------------------------------------------------------------------------------------- PostgreSQL is designed to be easily extensible. For this reason, extensions loaded into the database can function just like features that are built in. The `contrib/` directory shipped with the source code contains several extensions, which are described in [Appendix F](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") . Other extensions are developed independently, like [PostGIS](https://postgis.net/) . Even PostgreSQL replication solutions can be developed externally. For example, [Slony-I](https://www.slony.info/) is a popular primary/standby replication solution that is developed independently from the core project. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/external-pl.html "H.3. Procedural Languages") | [Up](https://www.postgresql.org/docs/current/external-projects.html "Appendix H. External Projects") | [Next](https://www.postgresql.org/docs/current/sourcerepo.html "Appendix I. The Source Code Repository") | | H.3. Procedural Languages | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Appendix I. The Source Code Repository | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/external-extensions.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.52. table_constraints November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-table-constraints.html "PostgreSQL 18 - 35.52. table_constraints") ([18](https://www.postgresql.org/docs/18/infoschema-table-constraints.html "PostgreSQL 18 - 35.52. table_constraints") ) / [17](https://www.postgresql.org/docs/17/infoschema-table-constraints.html "PostgreSQL 17 - 35.52. table_constraints") / [16](https://www.postgresql.org/docs/16/infoschema-table-constraints.html "PostgreSQL 16 - 35.52. table_constraints") / [15](https://www.postgresql.org/docs/15/infoschema-table-constraints.html "PostgreSQL 15 - 35.52. table_constraints") / [14](https://www.postgresql.org/docs/14/infoschema-table-constraints.html "PostgreSQL 14 - 35.52. table_constraints") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-table-constraints.html "PostgreSQL devel - 35.52. table_constraints") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-table-constraints.html "PostgreSQL 13 - 35.52. table_constraints") / [12](https://www.postgresql.org/docs/12/infoschema-table-constraints.html "PostgreSQL 12 - 35.52. table_constraints") / [11](https://www.postgresql.org/docs/11/infoschema-table-constraints.html "PostgreSQL 11 - 35.52. table_constraints") / [10](https://www.postgresql.org/docs/10/infoschema-table-constraints.html "PostgreSQL 10 - 35.52. table_constraints") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-table-constraints.html "PostgreSQL 9.6 - 35.52. table_constraints") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-table-constraints.html "PostgreSQL 9.5 - 35.52. table_constraints") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-table-constraints.html "PostgreSQL 9.4 - 35.52. table_constraints") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-table-constraints.html "PostgreSQL 9.3 - 35.52. table_constraints") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-table-constraints.html "PostgreSQL 9.2 - 35.52. table_constraints") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-table-constraints.html "PostgreSQL 9.1 - 35.52. table_constraints") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-table-constraints.html "PostgreSQL 9.0 - 35.52. table_constraints") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-table-constraints.html "PostgreSQL 8.4 - 35.52. table_constraints") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-table-constraints.html "PostgreSQL 8.3 - 35.52. table_constraints") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-table-constraints.html "PostgreSQL 8.2 - 35.52. table_constraints") / [8.1](https://www.postgresql.org/docs/8.1/infoschema-table-constraints.html "PostgreSQL 8.1 - 35.52. table_constraints") / [8.0](https://www.postgresql.org/docs/8.0/infoschema-table-constraints.html "PostgreSQL 8.0 - 35.52. table_constraints") / [7.4](https://www.postgresql.org/docs/7.4/infoschema-table-constraints.html "PostgreSQL 7.4 - 35.52. table_constraints") | 35.52. `table_constraints` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-sql-sizing.html "35.51. sql_sizing") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/infoschema-table-privileges.html "35.53. table_privileges") | * * * 35.52. `table_constraints` [#](https://www.postgresql.org/docs/18/infoschema-table-constraints.html#INFOSCHEMA-TABLE-CONSTRAINTS) ---------------------------------------------------------------------------------------------------------------------------------- The view `table_constraints` contains all constraints belonging to tables that the current user owns or has some privilege other than `SELECT` on. **Table 35.50. `table_constraints` Columns** | Column Type

Description | | --- | | `constraint_catalog` `sql_identifier`

Name of the database that contains the constraint (always the current database) | | `constraint_schema` `sql_identifier`

Name of the schema that contains the constraint | | `constraint_name` `sql_identifier`

Name of the constraint | | `table_catalog` `sql_identifier`

Name of the database that contains the table (always the current database) | | `table_schema` `sql_identifier`

Name of the schema that contains the table | | `table_name` `sql_identifier`

Name of the table | | `constraint_type` `character_data`

Type of the constraint: `CHECK` (includes not-null constraints), `FOREIGN KEY`, `PRIMARY KEY`, or `UNIQUE` | | `is_deferrable` `yes_or_no`

`YES` if the constraint is deferrable, `NO` if not | | `initially_deferred` `yes_or_no`

`YES` if the constraint is deferrable and initially deferred, `NO` if not | | `enforced` `yes_or_no`

`YES` if the constraint is enforced, `NO` if not | | `nulls_distinct` `yes_or_no`

If the constraint is a unique constraint, then `YES` if the constraint treats nulls as distinct or `NO` if it treats nulls as not distinct, otherwise null for other types of constraints. | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-sql-sizing.html "35.51. sql_sizing") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/18/infoschema-table-privileges.html "35.53. table_privileges") | | 35.51. `sql_sizing` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 35.53. `table_privileges` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-table-constraints.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE TEXT SEARCH DICTIONARY November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createtsdictionary.html "PostgreSQL 18 - CREATE TEXT SEARCH DICTIONARY") ([18](https://www.postgresql.org/docs/18/sql-createtsdictionary.html "PostgreSQL 18 - CREATE TEXT SEARCH DICTIONARY") ) / [17](https://www.postgresql.org/docs/17/sql-createtsdictionary.html "PostgreSQL 17 - CREATE TEXT SEARCH DICTIONARY") / [16](https://www.postgresql.org/docs/16/sql-createtsdictionary.html "PostgreSQL 16 - CREATE TEXT SEARCH DICTIONARY") / [15](https://www.postgresql.org/docs/15/sql-createtsdictionary.html "PostgreSQL 15 - CREATE TEXT SEARCH DICTIONARY") / [14](https://www.postgresql.org/docs/14/sql-createtsdictionary.html "PostgreSQL 14 - CREATE TEXT SEARCH DICTIONARY") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createtsdictionary.html "PostgreSQL devel - CREATE TEXT SEARCH DICTIONARY") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createtsdictionary.html "PostgreSQL 13 - CREATE TEXT SEARCH DICTIONARY") / [12](https://www.postgresql.org/docs/12/sql-createtsdictionary.html "PostgreSQL 12 - CREATE TEXT SEARCH DICTIONARY") / [11](https://www.postgresql.org/docs/11/sql-createtsdictionary.html "PostgreSQL 11 - CREATE TEXT SEARCH DICTIONARY") / [10](https://www.postgresql.org/docs/10/sql-createtsdictionary.html "PostgreSQL 10 - CREATE TEXT SEARCH DICTIONARY") / [9.6](https://www.postgresql.org/docs/9.6/sql-createtsdictionary.html "PostgreSQL 9.6 - CREATE TEXT SEARCH DICTIONARY") / [9.5](https://www.postgresql.org/docs/9.5/sql-createtsdictionary.html "PostgreSQL 9.5 - CREATE TEXT SEARCH DICTIONARY") / [9.4](https://www.postgresql.org/docs/9.4/sql-createtsdictionary.html "PostgreSQL 9.4 - CREATE TEXT SEARCH DICTIONARY") / [9.3](https://www.postgresql.org/docs/9.3/sql-createtsdictionary.html "PostgreSQL 9.3 - CREATE TEXT SEARCH DICTIONARY") / [9.2](https://www.postgresql.org/docs/9.2/sql-createtsdictionary.html "PostgreSQL 9.2 - CREATE TEXT SEARCH DICTIONARY") / [9.1](https://www.postgresql.org/docs/9.1/sql-createtsdictionary.html "PostgreSQL 9.1 - CREATE TEXT SEARCH DICTIONARY") / [9.0](https://www.postgresql.org/docs/9.0/sql-createtsdictionary.html "PostgreSQL 9.0 - CREATE TEXT SEARCH DICTIONARY") / [8.4](https://www.postgresql.org/docs/8.4/sql-createtsdictionary.html "PostgreSQL 8.4 - CREATE TEXT SEARCH DICTIONARY") / [8.3](https://www.postgresql.org/docs/8.3/sql-createtsdictionary.html "PostgreSQL 8.3 - CREATE TEXT SEARCH DICTIONARY") | CREATE TEXT SEARCH DICTIONARY | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createtsconfig.html "CREATE TEXT SEARCH CONFIGURATION") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-createtsparser.html "CREATE TEXT SEARCH PARSER") | * * * CREATE TEXT SEARCH DICTIONARY ----------------------------- CREATE TEXT SEARCH DICTIONARY — define a new text search dictionary Synopsis -------- CREATE TEXT SEARCH DICTIONARY _`name`_ ( TEMPLATE = _`template`_ \[, _`option`_ = _`value`_ \[, ... \]\] ) Description ----------- `CREATE TEXT SEARCH DICTIONARY` creates a new text search dictionary. A text search dictionary specifies a way of recognizing interesting or uninteresting words for searching. A dictionary depends on a text search template, which specifies the functions that actually perform the work. Typically the dictionary provides some options that control the detailed behavior of the template's functions. If a schema name is given then the text search dictionary is created in the specified schema. Otherwise it is created in the current schema. The user who defines a text search dictionary becomes its owner. Refer to [Chapter 12](https://www.postgresql.org/docs/current/textsearch.html "Chapter 12. Full Text Search") for further information. Parameters ---------- _`name`_ The name of the text search dictionary to be created. The name can be schema-qualified. _`template`_ The name of the text search template that will define the basic behavior of this dictionary. _`option`_ The name of a template-specific option to be set for this dictionary. _`value`_ The value to use for a template-specific option. If the value is not a simple identifier or number, it must be quoted (but you can always quote it, if you wish). The options can appear in any order. Examples -------- The following example command creates a Snowball-based dictionary with a nonstandard list of stop words. CREATE TEXT SEARCH DICTIONARY my\_russian ( template = snowball, language = russian, stopwords = myrussian ); Compatibility ------------- There is no `CREATE TEXT SEARCH DICTIONARY` statement in the SQL standard. See Also -------- [ALTER TEXT SEARCH DICTIONARY](https://www.postgresql.org/docs/current/sql-altertsdictionary.html "ALTER TEXT SEARCH DICTIONARY") , [DROP TEXT SEARCH DICTIONARY](https://www.postgresql.org/docs/current/sql-droptsdictionary.html "DROP TEXT SEARCH DICTIONARY") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createtsconfig.html "CREATE TEXT SEARCH CONFIGURATION") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-createtsparser.html "CREATE TEXT SEARCH PARSER") | | CREATE TEXT SEARCH CONFIGURATION | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | CREATE TEXT SEARCH PARSER | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createtsdictionary.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.52. table_constraints November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-table-constraints.html "PostgreSQL 18 - 35.52. table_constraints") ([18](https://www.postgresql.org/docs/18/infoschema-table-constraints.html "PostgreSQL 18 - 35.52. table_constraints") ) / [17](https://www.postgresql.org/docs/17/infoschema-table-constraints.html "PostgreSQL 17 - 35.52. table_constraints") / [16](https://www.postgresql.org/docs/16/infoschema-table-constraints.html "PostgreSQL 16 - 35.52. table_constraints") / [15](https://www.postgresql.org/docs/15/infoschema-table-constraints.html "PostgreSQL 15 - 35.52. table_constraints") / [14](https://www.postgresql.org/docs/14/infoschema-table-constraints.html "PostgreSQL 14 - 35.52. table_constraints") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-table-constraints.html "PostgreSQL devel - 35.52. table_constraints") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-table-constraints.html "PostgreSQL 13 - 35.52. table_constraints") / [12](https://www.postgresql.org/docs/12/infoschema-table-constraints.html "PostgreSQL 12 - 35.52. table_constraints") / [11](https://www.postgresql.org/docs/11/infoschema-table-constraints.html "PostgreSQL 11 - 35.52. table_constraints") / [10](https://www.postgresql.org/docs/10/infoschema-table-constraints.html "PostgreSQL 10 - 35.52. table_constraints") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-table-constraints.html "PostgreSQL 9.6 - 35.52. table_constraints") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-table-constraints.html "PostgreSQL 9.5 - 35.52. table_constraints") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-table-constraints.html "PostgreSQL 9.4 - 35.52. table_constraints") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-table-constraints.html "PostgreSQL 9.3 - 35.52. table_constraints") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-table-constraints.html "PostgreSQL 9.2 - 35.52. table_constraints") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-table-constraints.html "PostgreSQL 9.1 - 35.52. table_constraints") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-table-constraints.html "PostgreSQL 9.0 - 35.52. table_constraints") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-table-constraints.html "PostgreSQL 8.4 - 35.52. table_constraints") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-table-constraints.html "PostgreSQL 8.3 - 35.52. table_constraints") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-table-constraints.html "PostgreSQL 8.2 - 35.52. table_constraints") / [8.1](https://www.postgresql.org/docs/8.1/infoschema-table-constraints.html "PostgreSQL 8.1 - 35.52. table_constraints") / [8.0](https://www.postgresql.org/docs/8.0/infoschema-table-constraints.html "PostgreSQL 8.0 - 35.52. table_constraints") / [7.4](https://www.postgresql.org/docs/7.4/infoschema-table-constraints.html "PostgreSQL 7.4 - 35.52. table_constraints") | 35.52. `table_constraints` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-sql-sizing.html "35.51. sql_sizing") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/infoschema-table-privileges.html "35.53. table_privileges") | * * * 35.52. `table_constraints` [#](https://www.postgresql.org/docs/current/infoschema-table-constraints.html#INFOSCHEMA-TABLE-CONSTRAINTS) --------------------------------------------------------------------------------------------------------------------------------------- The view `table_constraints` contains all constraints belonging to tables that the current user owns or has some privilege other than `SELECT` on. **Table 35.50. `table_constraints` Columns** | Column Type

Description | | --- | | `constraint_catalog` `sql_identifier`

Name of the database that contains the constraint (always the current database) | | `constraint_schema` `sql_identifier`

Name of the schema that contains the constraint | | `constraint_name` `sql_identifier`

Name of the constraint | | `table_catalog` `sql_identifier`

Name of the database that contains the table (always the current database) | | `table_schema` `sql_identifier`

Name of the schema that contains the table | | `table_name` `sql_identifier`

Name of the table | | `constraint_type` `character_data`

Type of the constraint: `CHECK` (includes not-null constraints), `FOREIGN KEY`, `PRIMARY KEY`, or `UNIQUE` | | `is_deferrable` `yes_or_no`

`YES` if the constraint is deferrable, `NO` if not | | `initially_deferred` `yes_or_no`

`YES` if the constraint is deferrable and initially deferred, `NO` if not | | `enforced` `yes_or_no`

`YES` if the constraint is enforced, `NO` if not | | `nulls_distinct` `yes_or_no`

If the constraint is a unique constraint, then `YES` if the constraint treats nulls as distinct or `NO` if it treats nulls as not distinct, otherwise null for other types of constraints. | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-sql-sizing.html "35.51. sql_sizing") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/current/infoschema-table-privileges.html "35.53. table_privileges") | | 35.51. `sql_sizing` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 35.53. `table_privileges` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-table-constraints.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: SPI_cursor_open November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/spi-spi-cursor-open.html "PostgreSQL 18 - SPI_cursor_open") ([18](https://www.postgresql.org/docs/18/spi-spi-cursor-open.html "PostgreSQL 18 - SPI_cursor_open") ) / [17](https://www.postgresql.org/docs/17/spi-spi-cursor-open.html "PostgreSQL 17 - SPI_cursor_open") / [16](https://www.postgresql.org/docs/16/spi-spi-cursor-open.html "PostgreSQL 16 - SPI_cursor_open") / [15](https://www.postgresql.org/docs/15/spi-spi-cursor-open.html "PostgreSQL 15 - SPI_cursor_open") / [14](https://www.postgresql.org/docs/14/spi-spi-cursor-open.html "PostgreSQL 14 - SPI_cursor_open") Development Versions: [devel](https://www.postgresql.org/docs/devel/spi-spi-cursor-open.html "PostgreSQL devel - SPI_cursor_open") Unsupported versions: [13](https://www.postgresql.org/docs/13/spi-spi-cursor-open.html "PostgreSQL 13 - SPI_cursor_open") / [12](https://www.postgresql.org/docs/12/spi-spi-cursor-open.html "PostgreSQL 12 - SPI_cursor_open") / [11](https://www.postgresql.org/docs/11/spi-spi-cursor-open.html "PostgreSQL 11 - SPI_cursor_open") / [10](https://www.postgresql.org/docs/10/spi-spi-cursor-open.html "PostgreSQL 10 - SPI_cursor_open") / [9.6](https://www.postgresql.org/docs/9.6/spi-spi-cursor-open.html "PostgreSQL 9.6 - SPI_cursor_open") / [9.5](https://www.postgresql.org/docs/9.5/spi-spi-cursor-open.html "PostgreSQL 9.5 - SPI_cursor_open") / [9.4](https://www.postgresql.org/docs/9.4/spi-spi-cursor-open.html "PostgreSQL 9.4 - SPI_cursor_open") / [9.3](https://www.postgresql.org/docs/9.3/spi-spi-cursor-open.html "PostgreSQL 9.3 - SPI_cursor_open") / [9.2](https://www.postgresql.org/docs/9.2/spi-spi-cursor-open.html "PostgreSQL 9.2 - SPI_cursor_open") / [9.1](https://www.postgresql.org/docs/9.1/spi-spi-cursor-open.html "PostgreSQL 9.1 - SPI_cursor_open") / [9.0](https://www.postgresql.org/docs/9.0/spi-spi-cursor-open.html "PostgreSQL 9.0 - SPI_cursor_open") / [8.4](https://www.postgresql.org/docs/8.4/spi-spi-cursor-open.html "PostgreSQL 8.4 - SPI_cursor_open") / [8.3](https://www.postgresql.org/docs/8.3/spi-spi-cursor-open.html "PostgreSQL 8.3 - SPI_cursor_open") / [8.2](https://www.postgresql.org/docs/8.2/spi-spi-cursor-open.html "PostgreSQL 8.2 - SPI_cursor_open") / [8.1](https://www.postgresql.org/docs/8.1/spi-spi-cursor-open.html "PostgreSQL 8.1 - SPI_cursor_open") / [8.0](https://www.postgresql.org/docs/8.0/spi-spi-cursor-open.html "PostgreSQL 8.0 - SPI_cursor_open") / [7.4](https://www.postgresql.org/docs/7.4/spi-spi-cursor-open.html "PostgreSQL 7.4 - SPI_cursor_open") | SPI\_cursor\_open | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-execp.html "SPI_execp") | [Up](https://www.postgresql.org/docs/current/spi-interface.html "45.1. Interface Functions") | 45.1. Interface Functions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/spi-spi-cursor-open-with-args.html "SPI_cursor_open_with_args") | * * * SPI\_cursor\_open ----------------- SPI\_cursor\_open — set up a cursor using a statement created with `SPI_prepare` Synopsis -------- Portal SPI\_cursor\_open(const char \* _`name`_, SPIPlanPtr _`plan`_, Datum \* _`values`_, const char \* _`nulls`_, bool _`read_only`_) Description ----------- `SPI_cursor_open` sets up a cursor (internally, a portal) that will execute a statement prepared by `SPI_prepare`. The parameters have the same meanings as the corresponding parameters to `SPI_execute_plan`. Using a cursor instead of executing the statement directly has two benefits. First, the result rows can be retrieved a few at a time, avoiding memory overrun for queries that return many rows. Second, a portal can outlive the current C function (it can, in fact, live to the end of the current transaction). Returning the portal name to the C function's caller provides a way of returning a row set as result. The passed-in parameter data will be copied into the cursor's portal, so it can be freed while the cursor still exists. Arguments --------- ``const char * _`name`_`` name for portal, or `NULL` to let the system select a name ``SPIPlanPtr _`plan`_`` prepared statement (returned by `SPI_prepare`) ``Datum * _`values`_`` An array of actual parameter values. Must have same length as the statement's number of arguments. ``const char * _`nulls`_`` An array describing which parameters are null. Must have same length as the statement's number of arguments. If _`nulls`_ is `NULL` then `SPI_cursor_open` assumes that no parameters are null. Otherwise, each entry of the _`nulls`_ array should be `' '` if the corresponding parameter value is non-null, or `'n'` if the corresponding parameter value is null. (In the latter case, the actual value in the corresponding _`values`_ entry doesn't matter.) Note that _`nulls`_ is not a text string, just an array: it does not need a `'\0'` terminator. ``bool _`read_only`_`` `true` for read-only execution Return Value ------------ Pointer to portal containing the cursor. Note there is no error return convention; any error will be reported via `elog`. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-execp.html "SPI_execp") | [Up](https://www.postgresql.org/docs/current/spi-interface.html "45.1. Interface Functions") | [Next](https://www.postgresql.org/docs/current/spi-spi-cursor-open-with-args.html "SPI_cursor_open_with_args") | | SPI\_execp | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | SPI\_cursor\_open\_with\_args | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/spi-spi-cursor-open.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 5.2. Default Values November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/ddl-default.html "PostgreSQL 18 - 5.2. Default Values") ([18](https://www.postgresql.org/docs/18/ddl-default.html "PostgreSQL 18 - 5.2. Default Values") ) / [17](https://www.postgresql.org/docs/17/ddl-default.html "PostgreSQL 17 - 5.2. Default Values") / [16](https://www.postgresql.org/docs/16/ddl-default.html "PostgreSQL 16 - 5.2. Default Values") / [15](https://www.postgresql.org/docs/15/ddl-default.html "PostgreSQL 15 - 5.2. Default Values") / [14](https://www.postgresql.org/docs/14/ddl-default.html "PostgreSQL 14 - 5.2. Default Values") Development Versions: [devel](https://www.postgresql.org/docs/devel/ddl-default.html "PostgreSQL devel - 5.2. Default Values") Unsupported versions: [13](https://www.postgresql.org/docs/13/ddl-default.html "PostgreSQL 13 - 5.2. Default Values") / [12](https://www.postgresql.org/docs/12/ddl-default.html "PostgreSQL 12 - 5.2. Default Values") / [11](https://www.postgresql.org/docs/11/ddl-default.html "PostgreSQL 11 - 5.2. Default Values") / [10](https://www.postgresql.org/docs/10/ddl-default.html "PostgreSQL 10 - 5.2. Default Values") / [9.6](https://www.postgresql.org/docs/9.6/ddl-default.html "PostgreSQL 9.6 - 5.2. Default Values") / [9.5](https://www.postgresql.org/docs/9.5/ddl-default.html "PostgreSQL 9.5 - 5.2. Default Values") / [9.4](https://www.postgresql.org/docs/9.4/ddl-default.html "PostgreSQL 9.4 - 5.2. Default Values") / [9.3](https://www.postgresql.org/docs/9.3/ddl-default.html "PostgreSQL 9.3 - 5.2. Default Values") / [9.2](https://www.postgresql.org/docs/9.2/ddl-default.html "PostgreSQL 9.2 - 5.2. Default Values") / [9.1](https://www.postgresql.org/docs/9.1/ddl-default.html "PostgreSQL 9.1 - 5.2. Default Values") / [9.0](https://www.postgresql.org/docs/9.0/ddl-default.html "PostgreSQL 9.0 - 5.2. Default Values") / [8.4](https://www.postgresql.org/docs/8.4/ddl-default.html "PostgreSQL 8.4 - 5.2. Default Values") / [8.3](https://www.postgresql.org/docs/8.3/ddl-default.html "PostgreSQL 8.3 - 5.2. Default Values") / [8.2](https://www.postgresql.org/docs/8.2/ddl-default.html "PostgreSQL 8.2 - 5.2. Default Values") / [8.1](https://www.postgresql.org/docs/8.1/ddl-default.html "PostgreSQL 8.1 - 5.2. Default Values") / [8.0](https://www.postgresql.org/docs/8.0/ddl-default.html "PostgreSQL 8.0 - 5.2. Default Values") / [7.4](https://www.postgresql.org/docs/7.4/ddl-default.html "PostgreSQL 7.4 - 5.2. Default Values") | 5.2. Default Values | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/ddl-basics.html "5.1. Table Basics") | [Up](https://www.postgresql.org/docs/18/ddl.html "Chapter 5. Data Definition") | Chapter 5. Data Definition | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/ddl-identity-columns.html "5.3. Identity Columns") | * * * 5.2. Default Values [#](https://www.postgresql.org/docs/18/ddl-default.html#DDL-DEFAULT) ----------------------------------------------------------------------------------------- A column can be assigned a default value. When a new row is created and no values are specified for some of the columns, those columns will be filled with their respective default values. A data manipulation command can also request explicitly that a column be set to its default value, without having to know what that value is. (Details about data manipulation commands are in [Chapter 6](https://www.postgresql.org/docs/18/dml.html "Chapter 6. Data Manipulation") .) If no default value is declared explicitly, the default value is the null value. This usually makes sense because a null value can be considered to represent unknown data. In a table definition, default values are listed after the column data type. For example: CREATE TABLE products ( product\_no integer, name text, price numeric **DEFAULT 9.99** ); The default value can be an expression, which will be evaluated whenever the default value is inserted (_not_ when the table is created). A common example is for a `timestamp` column to have a default of `CURRENT_TIMESTAMP`, so that it gets set to the time of row insertion. Another common example is generating a “serial number” for each row. In PostgreSQL this is typically done by something like: CREATE TABLE products ( product\_no integer **DEFAULT nextval('products\_product\_no\_seq')**, ... ); where the `nextval()` function supplies successive values from a _sequence object_ (see [Section 9.17](https://www.postgresql.org/docs/18/functions-sequence.html "9.17. Sequence Manipulation Functions") ). This arrangement is sufficiently common that there's a special shorthand for it: CREATE TABLE products ( product\_no **SERIAL**, ... ); The `SERIAL` shorthand is discussed further in [Section 8.1.4](https://www.postgresql.org/docs/18/datatype-numeric.html#DATATYPE-SERIAL "8.1.4. Serial Types") . * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/ddl-basics.html "5.1. Table Basics") | [Up](https://www.postgresql.org/docs/18/ddl.html "Chapter 5. Data Definition") | [Next](https://www.postgresql.org/docs/18/ddl-identity-columns.html "5.3. Identity Columns") | | 5.1. Table Basics | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 5.3. Identity Columns | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/ddl-default.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 43.2. Data Values in PL/Perl November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plperl-data.html "PostgreSQL 18 - 43.2. Data Values in PL/Perl") ([18](https://www.postgresql.org/docs/18/plperl-data.html "PostgreSQL 18 - 43.2. Data Values in PL/Perl") ) / [17](https://www.postgresql.org/docs/17/plperl-data.html "PostgreSQL 17 - 43.2. Data Values in PL/Perl") / [16](https://www.postgresql.org/docs/16/plperl-data.html "PostgreSQL 16 - 43.2. Data Values in PL/Perl") / [15](https://www.postgresql.org/docs/15/plperl-data.html "PostgreSQL 15 - 43.2. Data Values in PL/Perl") / [14](https://www.postgresql.org/docs/14/plperl-data.html "PostgreSQL 14 - 43.2. Data Values in PL/Perl") Development Versions: [devel](https://www.postgresql.org/docs/devel/plperl-data.html "PostgreSQL devel - 43.2. Data Values in PL/Perl") Unsupported versions: [13](https://www.postgresql.org/docs/13/plperl-data.html "PostgreSQL 13 - 43.2. Data Values in PL/Perl") / [12](https://www.postgresql.org/docs/12/plperl-data.html "PostgreSQL 12 - 43.2. Data Values in PL/Perl") / [11](https://www.postgresql.org/docs/11/plperl-data.html "PostgreSQL 11 - 43.2. Data Values in PL/Perl") / [10](https://www.postgresql.org/docs/10/plperl-data.html "PostgreSQL 10 - 43.2. Data Values in PL/Perl") / [9.6](https://www.postgresql.org/docs/9.6/plperl-data.html "PostgreSQL 9.6 - 43.2. Data Values in PL/Perl") / [9.5](https://www.postgresql.org/docs/9.5/plperl-data.html "PostgreSQL 9.5 - 43.2. Data Values in PL/Perl") / [9.4](https://www.postgresql.org/docs/9.4/plperl-data.html "PostgreSQL 9.4 - 43.2. Data Values in PL/Perl") / [9.3](https://www.postgresql.org/docs/9.3/plperl-data.html "PostgreSQL 9.3 - 43.2. Data Values in PL/Perl") / [9.2](https://www.postgresql.org/docs/9.2/plperl-data.html "PostgreSQL 9.2 - 43.2. Data Values in PL/Perl") / [9.1](https://www.postgresql.org/docs/9.1/plperl-data.html "PostgreSQL 9.1 - 43.2. Data Values in PL/Perl") / [9.0](https://www.postgresql.org/docs/9.0/plperl-data.html "PostgreSQL 9.0 - 43.2. Data Values in PL/Perl") / [8.4](https://www.postgresql.org/docs/8.4/plperl-data.html "PostgreSQL 8.4 - 43.2. Data Values in PL/Perl") / [8.3](https://www.postgresql.org/docs/8.3/plperl-data.html "PostgreSQL 8.3 - 43.2. Data Values in PL/Perl") / [8.2](https://www.postgresql.org/docs/8.2/plperl-data.html "PostgreSQL 8.2 - 43.2. Data Values in PL/Perl") / [8.1](https://www.postgresql.org/docs/8.1/plperl-data.html "PostgreSQL 8.1 - 43.2. Data Values in PL/Perl") / [8.0](https://www.postgresql.org/docs/8.0/plperl-data.html "PostgreSQL 8.0 - 43.2. Data Values in PL/Perl") / [7.4](https://www.postgresql.org/docs/7.4/plperl-data.html "PostgreSQL 7.4 - 43.2. Data Values in PL/Perl") / [7.3](https://www.postgresql.org/docs/7.3/plperl-data.html "PostgreSQL 7.3 - 43.2. Data Values in PL/Perl") | 43.2. Data Values in PL/Perl | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/plperl-funcs.html "43.1. PL/Perl Functions and Arguments") | [Up](https://www.postgresql.org/docs/current/plperl.html "Chapter 43. PL/Perl — Perl Procedural Language") | Chapter 43. PL/Perl — Perl Procedural Language | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/plperl-builtins.html "43.3. Built-in Functions") | * * * 43.2. Data Values in PL/Perl [#](https://www.postgresql.org/docs/current/plperl-data.html#PLPERL-DATA) ------------------------------------------------------------------------------------------------------- The argument values supplied to a PL/Perl function's code are simply the input arguments converted to text form (just as if they had been displayed by a `SELECT` statement). Conversely, the `return` and `return_next` commands will accept any string that is acceptable input format for the function's declared return type. If this behavior is inconvenient for a particular case, it can be improved by using a transform, as already illustrated for `bool` values. Several examples of transform modules are included in the PostgreSQL distribution. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/plperl-funcs.html "43.1. PL/Perl Functions and Arguments") | [Up](https://www.postgresql.org/docs/current/plperl.html "Chapter 43. PL/Perl — Perl Procedural Language") | [Next](https://www.postgresql.org/docs/current/plperl-builtins.html "43.3. Built-in Functions") | | 43.1. PL/Perl Functions and Arguments | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 43.3. Built-in Functions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/plperl-data.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: pg_controldata November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/app-pgcontroldata.html "PostgreSQL 18 - pg_controldata") ([18](https://www.postgresql.org/docs/18/app-pgcontroldata.html "PostgreSQL 18 - pg_controldata") ) / [17](https://www.postgresql.org/docs/17/app-pgcontroldata.html "PostgreSQL 17 - pg_controldata") / [16](https://www.postgresql.org/docs/16/app-pgcontroldata.html "PostgreSQL 16 - pg_controldata") / [15](https://www.postgresql.org/docs/15/app-pgcontroldata.html "PostgreSQL 15 - pg_controldata") / [14](https://www.postgresql.org/docs/14/app-pgcontroldata.html "PostgreSQL 14 - pg_controldata") Development Versions: [devel](https://www.postgresql.org/docs/devel/app-pgcontroldata.html "PostgreSQL devel - pg_controldata") Unsupported versions: [13](https://www.postgresql.org/docs/13/app-pgcontroldata.html "PostgreSQL 13 - pg_controldata") / [12](https://www.postgresql.org/docs/12/app-pgcontroldata.html "PostgreSQL 12 - pg_controldata") / [11](https://www.postgresql.org/docs/11/app-pgcontroldata.html "PostgreSQL 11 - pg_controldata") / [10](https://www.postgresql.org/docs/10/app-pgcontroldata.html "PostgreSQL 10 - pg_controldata") / [9.6](https://www.postgresql.org/docs/9.6/app-pgcontroldata.html "PostgreSQL 9.6 - pg_controldata") / [9.5](https://www.postgresql.org/docs/9.5/app-pgcontroldata.html "PostgreSQL 9.5 - pg_controldata") / [9.4](https://www.postgresql.org/docs/9.4/app-pgcontroldata.html "PostgreSQL 9.4 - pg_controldata") / [9.3](https://www.postgresql.org/docs/9.3/app-pgcontroldata.html "PostgreSQL 9.3 - pg_controldata") / [9.2](https://www.postgresql.org/docs/9.2/app-pgcontroldata.html "PostgreSQL 9.2 - pg_controldata") / [9.1](https://www.postgresql.org/docs/9.1/app-pgcontroldata.html "PostgreSQL 9.1 - pg_controldata") / [9.0](https://www.postgresql.org/docs/9.0/app-pgcontroldata.html "PostgreSQL 9.0 - pg_controldata") / [8.4](https://www.postgresql.org/docs/8.4/app-pgcontroldata.html "PostgreSQL 8.4 - pg_controldata") / [8.3](https://www.postgresql.org/docs/8.3/app-pgcontroldata.html "PostgreSQL 8.3 - pg_controldata") / [8.2](https://www.postgresql.org/docs/8.2/app-pgcontroldata.html "PostgreSQL 8.2 - pg_controldata") / [8.1](https://www.postgresql.org/docs/8.1/app-pgcontroldata.html "PostgreSQL 8.1 - pg_controldata") / [8.0](https://www.postgresql.org/docs/8.0/app-pgcontroldata.html "PostgreSQL 8.0 - pg_controldata") / [7.4](https://www.postgresql.org/docs/7.4/app-pgcontroldata.html "PostgreSQL 7.4 - pg_controldata") / [7.3](https://www.postgresql.org/docs/7.3/app-pgcontroldata.html "PostgreSQL 7.3 - pg_controldata") | pg\_controldata | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/app-pgchecksums.html "pg_checksums") | [Up](https://www.postgresql.org/docs/current/reference-server.html "PostgreSQL Server Applications") | PostgreSQL Server Applications | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/app-pgcreatesubscriber.html "pg_createsubscriber") | * * * pg\_controldata --------------- pg\_controldata — display control information of a PostgreSQL database cluster Synopsis -------- `pg_controldata` \[_`option`_\] \[\[ `-D` | `--pgdata` \]_`datadir`_\] Description ----------- `pg_controldata` prints information initialized during `initdb`, such as the catalog version. It also shows information about write-ahead logging and checkpoint processing. This information is cluster-wide, and not specific to any one database. This utility can only be run by the user who initialized the cluster because it requires read access to the data directory. You can specify the data directory on the command line, or use the environment variable `PGDATA`. This utility supports the options `-V` and `--version`, which print the pg\_controldata version and exit. It also supports options `-?` and `--help`, which output the supported arguments. Environment ----------- `PGDATA` Default data directory location `PG_COLOR` Specifies whether to use color in diagnostic messages. Possible values are `always`, `auto` and `never`. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/app-pgchecksums.html "pg_checksums") | [Up](https://www.postgresql.org/docs/current/reference-server.html "PostgreSQL Server Applications") | [Next](https://www.postgresql.org/docs/current/app-pgcreatesubscriber.html "pg_createsubscriber") | | pg\_checksums | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | pg\_createsubscriber | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/app-pgcontroldata.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: DROP ROLE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-droprole.html "PostgreSQL 18 - DROP ROLE") ([18](https://www.postgresql.org/docs/18/sql-droprole.html "PostgreSQL 18 - DROP ROLE") ) / [17](https://www.postgresql.org/docs/17/sql-droprole.html "PostgreSQL 17 - DROP ROLE") / [16](https://www.postgresql.org/docs/16/sql-droprole.html "PostgreSQL 16 - DROP ROLE") / [15](https://www.postgresql.org/docs/15/sql-droprole.html "PostgreSQL 15 - DROP ROLE") / [14](https://www.postgresql.org/docs/14/sql-droprole.html "PostgreSQL 14 - DROP ROLE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-droprole.html "PostgreSQL devel - DROP ROLE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-droprole.html "PostgreSQL 13 - DROP ROLE") / [12](https://www.postgresql.org/docs/12/sql-droprole.html "PostgreSQL 12 - DROP ROLE") / [11](https://www.postgresql.org/docs/11/sql-droprole.html "PostgreSQL 11 - DROP ROLE") / [10](https://www.postgresql.org/docs/10/sql-droprole.html "PostgreSQL 10 - DROP ROLE") / [9.6](https://www.postgresql.org/docs/9.6/sql-droprole.html "PostgreSQL 9.6 - DROP ROLE") / [9.5](https://www.postgresql.org/docs/9.5/sql-droprole.html "PostgreSQL 9.5 - DROP ROLE") / [9.4](https://www.postgresql.org/docs/9.4/sql-droprole.html "PostgreSQL 9.4 - DROP ROLE") / [9.3](https://www.postgresql.org/docs/9.3/sql-droprole.html "PostgreSQL 9.3 - DROP ROLE") / [9.2](https://www.postgresql.org/docs/9.2/sql-droprole.html "PostgreSQL 9.2 - DROP ROLE") / [9.1](https://www.postgresql.org/docs/9.1/sql-droprole.html "PostgreSQL 9.1 - DROP ROLE") / [9.0](https://www.postgresql.org/docs/9.0/sql-droprole.html "PostgreSQL 9.0 - DROP ROLE") / [8.4](https://www.postgresql.org/docs/8.4/sql-droprole.html "PostgreSQL 8.4 - DROP ROLE") / [8.3](https://www.postgresql.org/docs/8.3/sql-droprole.html "PostgreSQL 8.3 - DROP ROLE") / [8.2](https://www.postgresql.org/docs/8.2/sql-droprole.html "PostgreSQL 8.2 - DROP ROLE") / [8.1](https://www.postgresql.org/docs/8.1/sql-droprole.html "PostgreSQL 8.1 - DROP ROLE") | DROP ROLE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-droppublication.html "DROP PUBLICATION") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-droproutine.html "DROP ROUTINE") | * * * DROP ROLE --------- DROP ROLE — remove a database role Synopsis -------- DROP ROLE \[ IF EXISTS \] _`name`_ \[, ...\] Description ----------- `DROP ROLE` removes the specified role(s). To drop a superuser role, you must be a superuser yourself; to drop non-superuser roles, you must have `CREATEROLE` privilege and have been granted `ADMIN OPTION` on the role. A role cannot be removed if it is still referenced in any database of the cluster; an error will be raised if so. Before dropping the role, you must drop all the objects it owns (or reassign their ownership) and revoke any privileges the role has been granted on other objects. The [`REASSIGN OWNED`](https://www.postgresql.org/docs/18/sql-reassign-owned.html "REASSIGN OWNED") and [`DROP OWNED`](https://www.postgresql.org/docs/18/sql-drop-owned.html "DROP OWNED") commands can be useful for this purpose; see [Section 21.4](https://www.postgresql.org/docs/18/role-removal.html "21.4. Dropping Roles") for more discussion. However, it is not necessary to remove role memberships involving the role; `DROP ROLE` automatically revokes any memberships of the target role in other roles, and of other roles in the target role. The other roles are not dropped nor otherwise affected. Parameters ---------- `IF EXISTS` Do not throw an error if the role does not exist. A notice is issued in this case. _`name`_ The name of the role to remove. Notes ----- PostgreSQL includes a program [dropuser](https://www.postgresql.org/docs/18/app-dropuser.html "dropuser") that has the same functionality as this command (in fact, it calls this command) but can be run from the command shell. Examples -------- To drop a role: DROP ROLE jonathan; Compatibility ------------- The SQL standard defines `DROP ROLE`, but it allows only one role to be dropped at a time, and it specifies different privilege requirements than PostgreSQL uses. See Also -------- [CREATE ROLE](https://www.postgresql.org/docs/18/sql-createrole.html "CREATE ROLE") , [ALTER ROLE](https://www.postgresql.org/docs/18/sql-alterrole.html "ALTER ROLE") , [SET ROLE](https://www.postgresql.org/docs/18/sql-set-role.html "SET ROLE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-droppublication.html "DROP PUBLICATION") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-droproutine.html "DROP ROUTINE") | | DROP PUBLICATION | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | DROP ROUTINE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-droprole.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 5.2. Default Values November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/ddl-default.html "PostgreSQL 18 - 5.2. Default Values") ([18](https://www.postgresql.org/docs/18/ddl-default.html "PostgreSQL 18 - 5.2. Default Values") ) / [17](https://www.postgresql.org/docs/17/ddl-default.html "PostgreSQL 17 - 5.2. Default Values") / [16](https://www.postgresql.org/docs/16/ddl-default.html "PostgreSQL 16 - 5.2. Default Values") / [15](https://www.postgresql.org/docs/15/ddl-default.html "PostgreSQL 15 - 5.2. Default Values") / [14](https://www.postgresql.org/docs/14/ddl-default.html "PostgreSQL 14 - 5.2. Default Values") Development Versions: [devel](https://www.postgresql.org/docs/devel/ddl-default.html "PostgreSQL devel - 5.2. Default Values") Unsupported versions: [13](https://www.postgresql.org/docs/13/ddl-default.html "PostgreSQL 13 - 5.2. Default Values") / [12](https://www.postgresql.org/docs/12/ddl-default.html "PostgreSQL 12 - 5.2. Default Values") / [11](https://www.postgresql.org/docs/11/ddl-default.html "PostgreSQL 11 - 5.2. Default Values") / [10](https://www.postgresql.org/docs/10/ddl-default.html "PostgreSQL 10 - 5.2. Default Values") / [9.6](https://www.postgresql.org/docs/9.6/ddl-default.html "PostgreSQL 9.6 - 5.2. Default Values") / [9.5](https://www.postgresql.org/docs/9.5/ddl-default.html "PostgreSQL 9.5 - 5.2. Default Values") / [9.4](https://www.postgresql.org/docs/9.4/ddl-default.html "PostgreSQL 9.4 - 5.2. Default Values") / [9.3](https://www.postgresql.org/docs/9.3/ddl-default.html "PostgreSQL 9.3 - 5.2. Default Values") / [9.2](https://www.postgresql.org/docs/9.2/ddl-default.html "PostgreSQL 9.2 - 5.2. Default Values") / [9.1](https://www.postgresql.org/docs/9.1/ddl-default.html "PostgreSQL 9.1 - 5.2. Default Values") / [9.0](https://www.postgresql.org/docs/9.0/ddl-default.html "PostgreSQL 9.0 - 5.2. Default Values") / [8.4](https://www.postgresql.org/docs/8.4/ddl-default.html "PostgreSQL 8.4 - 5.2. Default Values") / [8.3](https://www.postgresql.org/docs/8.3/ddl-default.html "PostgreSQL 8.3 - 5.2. Default Values") / [8.2](https://www.postgresql.org/docs/8.2/ddl-default.html "PostgreSQL 8.2 - 5.2. Default Values") / [8.1](https://www.postgresql.org/docs/8.1/ddl-default.html "PostgreSQL 8.1 - 5.2. Default Values") / [8.0](https://www.postgresql.org/docs/8.0/ddl-default.html "PostgreSQL 8.0 - 5.2. Default Values") / [7.4](https://www.postgresql.org/docs/7.4/ddl-default.html "PostgreSQL 7.4 - 5.2. Default Values") | 5.2. Default Values | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/ddl-basics.html "5.1. Table Basics") | [Up](https://www.postgresql.org/docs/current/ddl.html "Chapter 5. Data Definition") | Chapter 5. Data Definition | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/ddl-identity-columns.html "5.3. Identity Columns") | * * * 5.2. Default Values [#](https://www.postgresql.org/docs/current/ddl-default.html#DDL-DEFAULT) ---------------------------------------------------------------------------------------------- A column can be assigned a default value. When a new row is created and no values are specified for some of the columns, those columns will be filled with their respective default values. A data manipulation command can also request explicitly that a column be set to its default value, without having to know what that value is. (Details about data manipulation commands are in [Chapter 6](https://www.postgresql.org/docs/current/dml.html "Chapter 6. Data Manipulation") .) If no default value is declared explicitly, the default value is the null value. This usually makes sense because a null value can be considered to represent unknown data. In a table definition, default values are listed after the column data type. For example: CREATE TABLE products ( product\_no integer, name text, price numeric **DEFAULT 9.99** ); The default value can be an expression, which will be evaluated whenever the default value is inserted (_not_ when the table is created). A common example is for a `timestamp` column to have a default of `CURRENT_TIMESTAMP`, so that it gets set to the time of row insertion. Another common example is generating a “serial number” for each row. In PostgreSQL this is typically done by something like: CREATE TABLE products ( product\_no integer **DEFAULT nextval('products\_product\_no\_seq')**, ... ); where the `nextval()` function supplies successive values from a _sequence object_ (see [Section 9.17](https://www.postgresql.org/docs/current/functions-sequence.html "9.17. Sequence Manipulation Functions") ). This arrangement is sufficiently common that there's a special shorthand for it: CREATE TABLE products ( product\_no **SERIAL**, ... ); The `SERIAL` shorthand is discussed further in [Section 8.1.4](https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-SERIAL "8.1.4. Serial Types") . * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/ddl-basics.html "5.1. Table Basics") | [Up](https://www.postgresql.org/docs/current/ddl.html "Chapter 5. Data Definition") | [Next](https://www.postgresql.org/docs/current/ddl-identity-columns.html "5.3. Identity Columns") | | 5.1. Table Basics | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 5.3. Identity Columns | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/ddl-default.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 42.5. Database Access from PL/Tcl November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/pltcl-dbaccess.html "PostgreSQL 18 - 42.5. Database Access from PL/Tcl") ([18](https://www.postgresql.org/docs/18/pltcl-dbaccess.html "PostgreSQL 18 - 42.5. Database Access from PL/Tcl") ) / [17](https://www.postgresql.org/docs/17/pltcl-dbaccess.html "PostgreSQL 17 - 42.5. Database Access from PL/Tcl") / [16](https://www.postgresql.org/docs/16/pltcl-dbaccess.html "PostgreSQL 16 - 42.5. Database Access from PL/Tcl") / [15](https://www.postgresql.org/docs/15/pltcl-dbaccess.html "PostgreSQL 15 - 42.5. Database Access from PL/Tcl") / [14](https://www.postgresql.org/docs/14/pltcl-dbaccess.html "PostgreSQL 14 - 42.5. Database Access from PL/Tcl") Development Versions: [devel](https://www.postgresql.org/docs/devel/pltcl-dbaccess.html "PostgreSQL devel - 42.5. Database Access from PL/Tcl") Unsupported versions: [13](https://www.postgresql.org/docs/13/pltcl-dbaccess.html "PostgreSQL 13 - 42.5. Database Access from PL/Tcl") / [12](https://www.postgresql.org/docs/12/pltcl-dbaccess.html "PostgreSQL 12 - 42.5. Database Access from PL/Tcl") / [11](https://www.postgresql.org/docs/11/pltcl-dbaccess.html "PostgreSQL 11 - 42.5. Database Access from PL/Tcl") / [10](https://www.postgresql.org/docs/10/pltcl-dbaccess.html "PostgreSQL 10 - 42.5. Database Access from PL/Tcl") / [9.6](https://www.postgresql.org/docs/9.6/pltcl-dbaccess.html "PostgreSQL 9.6 - 42.5. Database Access from PL/Tcl") / [9.5](https://www.postgresql.org/docs/9.5/pltcl-dbaccess.html "PostgreSQL 9.5 - 42.5. Database Access from PL/Tcl") / [9.4](https://www.postgresql.org/docs/9.4/pltcl-dbaccess.html "PostgreSQL 9.4 - 42.5. Database Access from PL/Tcl") / [9.3](https://www.postgresql.org/docs/9.3/pltcl-dbaccess.html "PostgreSQL 9.3 - 42.5. Database Access from PL/Tcl") / [9.2](https://www.postgresql.org/docs/9.2/pltcl-dbaccess.html "PostgreSQL 9.2 - 42.5. Database Access from PL/Tcl") / [9.1](https://www.postgresql.org/docs/9.1/pltcl-dbaccess.html "PostgreSQL 9.1 - 42.5. Database Access from PL/Tcl") / [9.0](https://www.postgresql.org/docs/9.0/pltcl-dbaccess.html "PostgreSQL 9.0 - 42.5. Database Access from PL/Tcl") / [8.4](https://www.postgresql.org/docs/8.4/pltcl-dbaccess.html "PostgreSQL 8.4 - 42.5. Database Access from PL/Tcl") / [8.3](https://www.postgresql.org/docs/8.3/pltcl-dbaccess.html "PostgreSQL 8.3 - 42.5. Database Access from PL/Tcl") / [8.2](https://www.postgresql.org/docs/8.2/pltcl-dbaccess.html "PostgreSQL 8.2 - 42.5. Database Access from PL/Tcl") / [8.1](https://www.postgresql.org/docs/8.1/pltcl-dbaccess.html "PostgreSQL 8.1 - 42.5. Database Access from PL/Tcl") / [8.0](https://www.postgresql.org/docs/8.0/pltcl-dbaccess.html "PostgreSQL 8.0 - 42.5. Database Access from PL/Tcl") / [7.4](https://www.postgresql.org/docs/7.4/pltcl-dbaccess.html "PostgreSQL 7.4 - 42.5. Database Access from PL/Tcl") | 42.5. Database Access from PL/Tcl | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/pltcl-global.html "42.4. Global Data in PL/Tcl") | [Up](https://www.postgresql.org/docs/18/pltcl.html "Chapter 42. PL/Tcl — Tcl Procedural Language") | Chapter 42. PL/Tcl — Tcl Procedural Language | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/pltcl-trigger.html "42.6. Trigger Functions in PL/Tcl") | * * * 42.5. Database Access from PL/Tcl [#](https://www.postgresql.org/docs/18/pltcl-dbaccess.html#PLTCL-DBACCESS) ------------------------------------------------------------------------------------------------------------- In this section, we follow the usual Tcl convention of using question marks, rather than brackets, to indicate an optional element in a syntax synopsis. The following commands are available to access the database from the body of a PL/Tcl function: `` `spi_exec` ?-count _`n`_? ?-array _`name`_? _`command`_ ?_`loop-body`_? `` Executes an SQL command given as a string. An error in the command causes an error to be raised. Otherwise, the return value of `spi_exec` is the number of rows processed (selected, inserted, updated, or deleted) by the command, or zero if the command is a utility statement. In addition, if the command is a `SELECT` statement, the values of the selected columns are placed in Tcl variables as described below. The optional `-count` value tells `spi_exec` to stop once _`n`_ rows have been retrieved, much as if the query included a `LIMIT` clause. If _`n`_ is zero, the query is run to completion, the same as when `-count` is omitted. If the command is a `SELECT` statement, the values of the result columns are placed into Tcl variables named after the columns. If the `-array` option is given, the column values are instead stored into elements of the named associative array, with the column names used as array indexes. In addition, the current row number within the result (counting from zero) is stored into the array element named “`.tupno`”, unless that name is in use as a column name in the result. If the command is a `SELECT` statement and no _`loop-body`_ script is given, then only the first row of results are stored into Tcl variables or array elements; remaining rows, if any, are ignored. No storing occurs if the query returns no rows. (This case can be detected by checking the result of `spi_exec`.) For example: spi\_exec "SELECT count(\*) AS cnt FROM pg\_proc" will set the Tcl variable `$cnt` to the number of rows in the `pg_proc` system catalog. If the optional _`loop-body`_ argument is given, it is a piece of Tcl script that is executed once for each row in the query result. (_`loop-body`_ is ignored if the given command is not a `SELECT`.) The values of the current row's columns are stored into Tcl variables or array elements before each iteration. For example: spi\_exec -array C "SELECT \* FROM pg\_class" { elog DEBUG "have table $C(relname)" } will print a log message for every row of `pg_class`. This feature works similarly to other Tcl looping constructs; in particular `continue` and `break` work in the usual way inside the loop body. If a column of a query result is null, the target variable for it is “unset” rather than being set. `spi_prepare` _`query`_ _`typelist`_ Prepares and saves a query plan for later execution. The saved plan will be retained for the life of the current session. The query can use parameters, that is, placeholders for values to be supplied whenever the plan is actually executed. In the query string, refer to parameters by the symbols `$1` ... ``$_`n`_``. If the query uses parameters, the names of the parameter types must be given as a Tcl list. (Write an empty list for _`typelist`_ if no parameters are used.) The return value from `spi_prepare` is a query ID to be used in subsequent calls to `spi_execp`. See `spi_execp` for an example. `` `spi_execp` ?-count _`n`_? ?-array _`name`_? ?-nulls _`string`_? _`queryid`_ ?_`value-list`_? ?_`loop-body`_? `` Executes a query previously prepared with `spi_prepare`. _`queryid`_ is the ID returned by `spi_prepare`. If the query references parameters, a _`value-list`_ must be supplied. This is a Tcl list of actual values for the parameters. The list must be the same length as the parameter type list previously given to `spi_prepare`. Omit _`value-list`_ if the query has no parameters. The optional value for `-nulls` is a string of spaces and `'n'` characters telling `spi_execp` which of the parameters are null values. If given, it must have exactly the same length as the _`value-list`_. If it is not given, all the parameter values are nonnull. Except for the way in which the query and its parameters are specified, `spi_execp` works just like `spi_exec`. The `-count`, `-array`, and _`loop-body`_ options are the same, and so is the result value. Here's an example of a PL/Tcl function using a prepared plan: CREATE FUNCTION t1\_count(integer, integer) RETURNS integer AS $$ if {!\[ info exists GD(plan) \]} { # prepare the saved plan on the first call set GD(plan) \[ spi\_prepare \\\ "SELECT count(\*) AS cnt FROM t1 WHERE num >= \\$1 AND num <= \\$2" \\\ \[ list int4 int4 \] \] } spi\_execp -count 1 $GD(plan) \[ list $1 $2 \] return $cnt $$ LANGUAGE pltcl; We need backslashes inside the query string given to `spi_prepare` to ensure that the ``$_`n`_`` markers will be passed through to `spi_prepare` as-is, and not replaced by Tcl variable substitution. `subtransaction` _`command`_ The Tcl script contained in _`command`_ is executed within an SQL subtransaction. If the script returns an error, that entire subtransaction is rolled back before returning the error out to the surrounding Tcl code. See [Section 42.9](https://www.postgresql.org/docs/18/pltcl-subtransactions.html "42.9. Explicit Subtransactions in PL/Tcl") for more details and an example. `quote` _`string`_ Doubles all occurrences of single quote and backslash characters in the given string. This can be used to safely quote strings that are to be inserted into SQL commands given to `spi_exec` or `spi_prepare`. For example, think about an SQL command string like: "SELECT '$val' AS ret" where the Tcl variable `val` actually contains `doesn't`. This would result in the final command string: SELECT 'doesn't' AS ret which would cause a parse error during `spi_exec` or `spi_prepare`. To work properly, the submitted command should contain: SELECT 'doesn''t' AS ret which can be formed in PL/Tcl using: "SELECT '\[ quote $val \]' AS ret" One advantage of `spi_execp` is that you don't have to quote parameter values like this, since the parameters are never parsed as part of an SQL command string. `elog` _`level`_ _`msg`_ Emits a log or error message. Possible levels are `DEBUG`, `LOG`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, and `FATAL`. `ERROR` raises an error condition; if this is not trapped by the surrounding Tcl code, the error propagates out to the calling query, causing the current transaction or subtransaction to be aborted. This is effectively the same as the Tcl `error` command. `FATAL` aborts the transaction and causes the current session to shut down. (There is probably no good reason to use this error level in PL/Tcl functions, but it's provided for completeness.) The other levels only generate messages of different priority levels. Whether messages of a particular priority are reported to the client, written to the server log, or both is controlled by the [log\_min\_messages](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-MIN-MESSAGES) and [client\_min\_messages](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-CLIENT-MIN-MESSAGES) configuration variables. See [Chapter 19](https://www.postgresql.org/docs/18/runtime-config.html "Chapter 19. Server Configuration") and [Section 42.8](https://www.postgresql.org/docs/18/pltcl-error-handling.html "42.8. Error Handling in PL/Tcl") for more information. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/pltcl-global.html "42.4. Global Data in PL/Tcl") | [Up](https://www.postgresql.org/docs/18/pltcl.html "Chapter 42. PL/Tcl — Tcl Procedural Language") | [Next](https://www.postgresql.org/docs/18/pltcl-trigger.html "42.6. Trigger Functions in PL/Tcl") | | 42.4. Global Data in PL/Tcl | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 42.6. Trigger Functions in PL/Tcl | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/pltcl-dbaccess.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 10.5. UNION, CASE, and Related Constructs November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/typeconv-union-case.html "PostgreSQL 18 - 10.5. UNION, CASE, and Related Constructs") ([18](https://www.postgresql.org/docs/18/typeconv-union-case.html "PostgreSQL 18 - 10.5. UNION, CASE, and Related Constructs") ) / [17](https://www.postgresql.org/docs/17/typeconv-union-case.html "PostgreSQL 17 - 10.5. UNION, CASE, and Related Constructs") / [16](https://www.postgresql.org/docs/16/typeconv-union-case.html "PostgreSQL 16 - 10.5. UNION, CASE, and Related Constructs") / [15](https://www.postgresql.org/docs/15/typeconv-union-case.html "PostgreSQL 15 - 10.5. UNION, CASE, and Related Constructs") / [14](https://www.postgresql.org/docs/14/typeconv-union-case.html "PostgreSQL 14 - 10.5. UNION, CASE, and Related Constructs") Development Versions: [devel](https://www.postgresql.org/docs/devel/typeconv-union-case.html "PostgreSQL devel - 10.5. UNION, CASE, and Related Constructs") Unsupported versions: [13](https://www.postgresql.org/docs/13/typeconv-union-case.html "PostgreSQL 13 - 10.5. UNION, CASE, and Related Constructs") / [12](https://www.postgresql.org/docs/12/typeconv-union-case.html "PostgreSQL 12 - 10.5. UNION, CASE, and Related Constructs") / [11](https://www.postgresql.org/docs/11/typeconv-union-case.html "PostgreSQL 11 - 10.5. UNION, CASE, and Related Constructs") / [10](https://www.postgresql.org/docs/10/typeconv-union-case.html "PostgreSQL 10 - 10.5. UNION, CASE, and Related Constructs") / [9.6](https://www.postgresql.org/docs/9.6/typeconv-union-case.html "PostgreSQL 9.6 - 10.5. UNION, CASE, and Related Constructs") / [9.5](https://www.postgresql.org/docs/9.5/typeconv-union-case.html "PostgreSQL 9.5 - 10.5. UNION, CASE, and Related Constructs") / [9.4](https://www.postgresql.org/docs/9.4/typeconv-union-case.html "PostgreSQL 9.4 - 10.5. UNION, CASE, and Related Constructs") / [9.3](https://www.postgresql.org/docs/9.3/typeconv-union-case.html "PostgreSQL 9.3 - 10.5. UNION, CASE, and Related Constructs") / [9.2](https://www.postgresql.org/docs/9.2/typeconv-union-case.html "PostgreSQL 9.2 - 10.5. UNION, CASE, and Related Constructs") / [9.1](https://www.postgresql.org/docs/9.1/typeconv-union-case.html "PostgreSQL 9.1 - 10.5. UNION, CASE, and Related Constructs") / [9.0](https://www.postgresql.org/docs/9.0/typeconv-union-case.html "PostgreSQL 9.0 - 10.5. UNION, CASE, and Related Constructs") / [8.4](https://www.postgresql.org/docs/8.4/typeconv-union-case.html "PostgreSQL 8.4 - 10.5. UNION, CASE, and Related Constructs") / [8.3](https://www.postgresql.org/docs/8.3/typeconv-union-case.html "PostgreSQL 8.3 - 10.5. UNION, CASE, and Related Constructs") / [8.2](https://www.postgresql.org/docs/8.2/typeconv-union-case.html "PostgreSQL 8.2 - 10.5. UNION, CASE, and Related Constructs") / [8.1](https://www.postgresql.org/docs/8.1/typeconv-union-case.html "PostgreSQL 8.1 - 10.5. UNION, CASE, and Related Constructs") / [8.0](https://www.postgresql.org/docs/8.0/typeconv-union-case.html "PostgreSQL 8.0 - 10.5. UNION, CASE, and Related Constructs") / [7.4](https://www.postgresql.org/docs/7.4/typeconv-union-case.html "PostgreSQL 7.4 - 10.5. UNION, CASE, and Related Constructs") / [7.3](https://www.postgresql.org/docs/7.3/typeconv-union-case.html "PostgreSQL 7.3 - 10.5. UNION, CASE, and Related Constructs") / [7.2](https://www.postgresql.org/docs/7.2/typeconv-union-case.html "PostgreSQL 7.2 - 10.5. UNION, CASE, and Related Constructs") / [7.1](https://www.postgresql.org/docs/7.1/typeconv-union-case.html "PostgreSQL 7.1 - 10.5. UNION, CASE, and Related Constructs") | 10.5. `UNION`, `CASE`, and Related Constructs | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/typeconv-query.html "10.4. Value Storage") | [Up](https://www.postgresql.org/docs/current/typeconv.html "Chapter 10. Type Conversion") | Chapter 10. Type Conversion | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/typeconv-select.html "10.6. SELECT Output Columns") | * * * 10.5. `UNION`, `CASE`, and Related Constructs [#](https://www.postgresql.org/docs/current/typeconv-union-case.html#TYPECONV-UNION-CASE) ---------------------------------------------------------------------------------------------------------------------------------------- SQL `UNION` constructs must match up possibly dissimilar types to become a single result set. The resolution algorithm is applied separately to each output column of a union query. The `INTERSECT` and `EXCEPT` constructs resolve dissimilar types in the same way as `UNION`. Some other constructs, including `CASE`, `ARRAY`, `VALUES`, and the `GREATEST` and `LEAST` functions, use the identical algorithm to match up their component expressions and select a result data type. **Type Resolution for `UNION`, `CASE`, and Related Constructs** 1. If all inputs are of the same type, and it is not `unknown`, resolve as that type. 2. If any input is of a domain type, treat it as being of the domain's base type for all subsequent steps. [\[12\]](https://www.postgresql.org/docs/current/typeconv-union-case.html#ftn.id-1.5.9.10.9.3.1.1) 3. If all inputs are of type `unknown`, resolve as type `text` (the preferred type of the string category). Otherwise, `unknown` inputs are ignored for the purposes of the remaining rules. 4. If the non-unknown inputs are not all of the same type category, fail. 5. Select the first non-unknown input type as the candidate type, then consider each other non-unknown input type, left to right. [\[13\]](https://www.postgresql.org/docs/current/typeconv-union-case.html#ftn.id-1.5.9.10.9.6.1.1) If the candidate type can be implicitly converted to the other type, but not vice-versa, select the other type as the new candidate type. Then continue considering the remaining inputs. If, at any stage of this process, a preferred type is selected, stop considering additional inputs. 6. Convert all inputs to the final candidate type. Fail if there is not an implicit conversion from a given input type to the candidate type. Some examples follow. **Example 10.10. Type Resolution with Underspecified Types in a Union** SELECT text 'a' AS "text" UNION SELECT 'b'; text ------ a b (2 rows) Here, the unknown-type literal `'b'` will be resolved to type `text`. **Example 10.11. Type Resolution in a Simple Union** SELECT 1.2 AS "numeric" UNION SELECT 1; numeric --------- 1 1.2 (2 rows) The literal `1.2` is of type `numeric`, and the `integer` value `1` can be cast implicitly to `numeric`, so that type is used. **Example 10.12. Type Resolution in a Transposed Union** SELECT 1 AS "real" UNION SELECT CAST('2.2' AS REAL); real ------ 1 2.2 (2 rows) Here, since type `real` cannot be implicitly cast to `integer`, but `integer` can be implicitly cast to `real`, the union result type is resolved as `real`. **Example 10.13. Type Resolution in a Nested Union** SELECT NULL UNION SELECT NULL UNION SELECT 1; ERROR: UNION types text and integer cannot be matched This failure occurs because PostgreSQL treats multiple `UNION`s as a nest of pairwise operations; that is, this input is the same as (SELECT NULL UNION SELECT NULL) UNION SELECT 1; The inner `UNION` is resolved as emitting type `text`, according to the rules given above. Then the outer `UNION` has inputs of types `text` and `integer`, leading to the observed error. The problem can be fixed by ensuring that the leftmost `UNION` has at least one input of the desired result type. `INTERSECT` and `EXCEPT` operations are likewise resolved pairwise. However, the other constructs described in this section consider all of their inputs in one resolution step. * * * [\[12\]](https://www.postgresql.org/docs/current/typeconv-union-case.html#id-1.5.9.10.9.3.1.1) Somewhat like the treatment of domain inputs for operators and functions, this behavior allows a domain type to be preserved through a `UNION` or similar construct, so long as the user is careful to ensure that all inputs are implicitly or explicitly of that exact type. Otherwise the domain's base type will be used. [\[13\]](https://www.postgresql.org/docs/current/typeconv-union-case.html#id-1.5.9.10.9.6.1.1) For historical reasons, `CASE` treats its `ELSE` clause (if any) as the “first” input, with the `THEN` clauses(s) considered after that. In all other cases, “left to right” means the order in which the expressions appear in the query text. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/typeconv-query.html "10.4. Value Storage") | [Up](https://www.postgresql.org/docs/current/typeconv.html "Chapter 10. Type Conversion") | [Next](https://www.postgresql.org/docs/current/typeconv-select.html "10.6. SELECT Output Columns") | | 10.4. Value Storage | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 10.6. `SELECT` Output Columns | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/typeconv-union-case.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 42.5. Database Access from PL/Tcl November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/pltcl-dbaccess.html "PostgreSQL 18 - 42.5. Database Access from PL/Tcl") ([18](https://www.postgresql.org/docs/18/pltcl-dbaccess.html "PostgreSQL 18 - 42.5. Database Access from PL/Tcl") ) / [17](https://www.postgresql.org/docs/17/pltcl-dbaccess.html "PostgreSQL 17 - 42.5. Database Access from PL/Tcl") / [16](https://www.postgresql.org/docs/16/pltcl-dbaccess.html "PostgreSQL 16 - 42.5. Database Access from PL/Tcl") / [15](https://www.postgresql.org/docs/15/pltcl-dbaccess.html "PostgreSQL 15 - 42.5. Database Access from PL/Tcl") / [14](https://www.postgresql.org/docs/14/pltcl-dbaccess.html "PostgreSQL 14 - 42.5. Database Access from PL/Tcl") Development Versions: [devel](https://www.postgresql.org/docs/devel/pltcl-dbaccess.html "PostgreSQL devel - 42.5. Database Access from PL/Tcl") Unsupported versions: [13](https://www.postgresql.org/docs/13/pltcl-dbaccess.html "PostgreSQL 13 - 42.5. Database Access from PL/Tcl") / [12](https://www.postgresql.org/docs/12/pltcl-dbaccess.html "PostgreSQL 12 - 42.5. Database Access from PL/Tcl") / [11](https://www.postgresql.org/docs/11/pltcl-dbaccess.html "PostgreSQL 11 - 42.5. Database Access from PL/Tcl") / [10](https://www.postgresql.org/docs/10/pltcl-dbaccess.html "PostgreSQL 10 - 42.5. Database Access from PL/Tcl") / [9.6](https://www.postgresql.org/docs/9.6/pltcl-dbaccess.html "PostgreSQL 9.6 - 42.5. Database Access from PL/Tcl") / [9.5](https://www.postgresql.org/docs/9.5/pltcl-dbaccess.html "PostgreSQL 9.5 - 42.5. Database Access from PL/Tcl") / [9.4](https://www.postgresql.org/docs/9.4/pltcl-dbaccess.html "PostgreSQL 9.4 - 42.5. Database Access from PL/Tcl") / [9.3](https://www.postgresql.org/docs/9.3/pltcl-dbaccess.html "PostgreSQL 9.3 - 42.5. Database Access from PL/Tcl") / [9.2](https://www.postgresql.org/docs/9.2/pltcl-dbaccess.html "PostgreSQL 9.2 - 42.5. Database Access from PL/Tcl") / [9.1](https://www.postgresql.org/docs/9.1/pltcl-dbaccess.html "PostgreSQL 9.1 - 42.5. Database Access from PL/Tcl") / [9.0](https://www.postgresql.org/docs/9.0/pltcl-dbaccess.html "PostgreSQL 9.0 - 42.5. Database Access from PL/Tcl") / [8.4](https://www.postgresql.org/docs/8.4/pltcl-dbaccess.html "PostgreSQL 8.4 - 42.5. Database Access from PL/Tcl") / [8.3](https://www.postgresql.org/docs/8.3/pltcl-dbaccess.html "PostgreSQL 8.3 - 42.5. Database Access from PL/Tcl") / [8.2](https://www.postgresql.org/docs/8.2/pltcl-dbaccess.html "PostgreSQL 8.2 - 42.5. Database Access from PL/Tcl") / [8.1](https://www.postgresql.org/docs/8.1/pltcl-dbaccess.html "PostgreSQL 8.1 - 42.5. Database Access from PL/Tcl") / [8.0](https://www.postgresql.org/docs/8.0/pltcl-dbaccess.html "PostgreSQL 8.0 - 42.5. Database Access from PL/Tcl") / [7.4](https://www.postgresql.org/docs/7.4/pltcl-dbaccess.html "PostgreSQL 7.4 - 42.5. Database Access from PL/Tcl") | 42.5. Database Access from PL/Tcl | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/pltcl-global.html "42.4. Global Data in PL/Tcl") | [Up](https://www.postgresql.org/docs/current/pltcl.html "Chapter 42. PL/Tcl — Tcl Procedural Language") | Chapter 42. PL/Tcl — Tcl Procedural Language | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/pltcl-trigger.html "42.6. Trigger Functions in PL/Tcl") | * * * 42.5. Database Access from PL/Tcl [#](https://www.postgresql.org/docs/current/pltcl-dbaccess.html#PLTCL-DBACCESS) ------------------------------------------------------------------------------------------------------------------ In this section, we follow the usual Tcl convention of using question marks, rather than brackets, to indicate an optional element in a syntax synopsis. The following commands are available to access the database from the body of a PL/Tcl function: `` `spi_exec` ?-count _`n`_? ?-array _`name`_? _`command`_ ?_`loop-body`_? `` Executes an SQL command given as a string. An error in the command causes an error to be raised. Otherwise, the return value of `spi_exec` is the number of rows processed (selected, inserted, updated, or deleted) by the command, or zero if the command is a utility statement. In addition, if the command is a `SELECT` statement, the values of the selected columns are placed in Tcl variables as described below. The optional `-count` value tells `spi_exec` to stop once _`n`_ rows have been retrieved, much as if the query included a `LIMIT` clause. If _`n`_ is zero, the query is run to completion, the same as when `-count` is omitted. If the command is a `SELECT` statement, the values of the result columns are placed into Tcl variables named after the columns. If the `-array` option is given, the column values are instead stored into elements of the named associative array, with the column names used as array indexes. In addition, the current row number within the result (counting from zero) is stored into the array element named “`.tupno`”, unless that name is in use as a column name in the result. If the command is a `SELECT` statement and no _`loop-body`_ script is given, then only the first row of results are stored into Tcl variables or array elements; remaining rows, if any, are ignored. No storing occurs if the query returns no rows. (This case can be detected by checking the result of `spi_exec`.) For example: spi\_exec "SELECT count(\*) AS cnt FROM pg\_proc" will set the Tcl variable `$cnt` to the number of rows in the `pg_proc` system catalog. If the optional _`loop-body`_ argument is given, it is a piece of Tcl script that is executed once for each row in the query result. (_`loop-body`_ is ignored if the given command is not a `SELECT`.) The values of the current row's columns are stored into Tcl variables or array elements before each iteration. For example: spi\_exec -array C "SELECT \* FROM pg\_class" { elog DEBUG "have table $C(relname)" } will print a log message for every row of `pg_class`. This feature works similarly to other Tcl looping constructs; in particular `continue` and `break` work in the usual way inside the loop body. If a column of a query result is null, the target variable for it is “unset” rather than being set. `spi_prepare` _`query`_ _`typelist`_ Prepares and saves a query plan for later execution. The saved plan will be retained for the life of the current session. The query can use parameters, that is, placeholders for values to be supplied whenever the plan is actually executed. In the query string, refer to parameters by the symbols `$1` ... ``$_`n`_``. If the query uses parameters, the names of the parameter types must be given as a Tcl list. (Write an empty list for _`typelist`_ if no parameters are used.) The return value from `spi_prepare` is a query ID to be used in subsequent calls to `spi_execp`. See `spi_execp` for an example. `` `spi_execp` ?-count _`n`_? ?-array _`name`_? ?-nulls _`string`_? _`queryid`_ ?_`value-list`_? ?_`loop-body`_? `` Executes a query previously prepared with `spi_prepare`. _`queryid`_ is the ID returned by `spi_prepare`. If the query references parameters, a _`value-list`_ must be supplied. This is a Tcl list of actual values for the parameters. The list must be the same length as the parameter type list previously given to `spi_prepare`. Omit _`value-list`_ if the query has no parameters. The optional value for `-nulls` is a string of spaces and `'n'` characters telling `spi_execp` which of the parameters are null values. If given, it must have exactly the same length as the _`value-list`_. If it is not given, all the parameter values are nonnull. Except for the way in which the query and its parameters are specified, `spi_execp` works just like `spi_exec`. The `-count`, `-array`, and _`loop-body`_ options are the same, and so is the result value. Here's an example of a PL/Tcl function using a prepared plan: CREATE FUNCTION t1\_count(integer, integer) RETURNS integer AS $$ if {!\[ info exists GD(plan) \]} { # prepare the saved plan on the first call set GD(plan) \[ spi\_prepare \\\ "SELECT count(\*) AS cnt FROM t1 WHERE num >= \\$1 AND num <= \\$2" \\\ \[ list int4 int4 \] \] } spi\_execp -count 1 $GD(plan) \[ list $1 $2 \] return $cnt $$ LANGUAGE pltcl; We need backslashes inside the query string given to `spi_prepare` to ensure that the ``$_`n`_`` markers will be passed through to `spi_prepare` as-is, and not replaced by Tcl variable substitution. `subtransaction` _`command`_ The Tcl script contained in _`command`_ is executed within an SQL subtransaction. If the script returns an error, that entire subtransaction is rolled back before returning the error out to the surrounding Tcl code. See [Section 42.9](https://www.postgresql.org/docs/current/pltcl-subtransactions.html "42.9. Explicit Subtransactions in PL/Tcl") for more details and an example. `quote` _`string`_ Doubles all occurrences of single quote and backslash characters in the given string. This can be used to safely quote strings that are to be inserted into SQL commands given to `spi_exec` or `spi_prepare`. For example, think about an SQL command string like: "SELECT '$val' AS ret" where the Tcl variable `val` actually contains `doesn't`. This would result in the final command string: SELECT 'doesn't' AS ret which would cause a parse error during `spi_exec` or `spi_prepare`. To work properly, the submitted command should contain: SELECT 'doesn''t' AS ret which can be formed in PL/Tcl using: "SELECT '\[ quote $val \]' AS ret" One advantage of `spi_execp` is that you don't have to quote parameter values like this, since the parameters are never parsed as part of an SQL command string. `elog` _`level`_ _`msg`_ Emits a log or error message. Possible levels are `DEBUG`, `LOG`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, and `FATAL`. `ERROR` raises an error condition; if this is not trapped by the surrounding Tcl code, the error propagates out to the calling query, causing the current transaction or subtransaction to be aborted. This is effectively the same as the Tcl `error` command. `FATAL` aborts the transaction and causes the current session to shut down. (There is probably no good reason to use this error level in PL/Tcl functions, but it's provided for completeness.) The other levels only generate messages of different priority levels. Whether messages of a particular priority are reported to the client, written to the server log, or both is controlled by the [log\_min\_messages](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-MESSAGES) and [client\_min\_messages](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-CLIENT-MIN-MESSAGES) configuration variables. See [Chapter 19](https://www.postgresql.org/docs/current/runtime-config.html "Chapter 19. Server Configuration") and [Section 42.8](https://www.postgresql.org/docs/current/pltcl-error-handling.html "42.8. Error Handling in PL/Tcl") for more information. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/pltcl-global.html "42.4. Global Data in PL/Tcl") | [Up](https://www.postgresql.org/docs/current/pltcl.html "Chapter 42. PL/Tcl — Tcl Procedural Language") | [Next](https://www.postgresql.org/docs/current/pltcl-trigger.html "42.6. Trigger Functions in PL/Tcl") | | 42.4. Global Data in PL/Tcl | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 42.6. Trigger Functions in PL/Tcl | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/pltcl-dbaccess.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Preface November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/preface.html "PostgreSQL 18 - Preface") ([18](https://www.postgresql.org/docs/18/preface.html "PostgreSQL 18 - Preface") ) / [17](https://www.postgresql.org/docs/17/preface.html "PostgreSQL 17 - Preface") / [16](https://www.postgresql.org/docs/16/preface.html "PostgreSQL 16 - Preface") / [15](https://www.postgresql.org/docs/15/preface.html "PostgreSQL 15 - Preface") / [14](https://www.postgresql.org/docs/14/preface.html "PostgreSQL 14 - Preface") Development Versions: [devel](https://www.postgresql.org/docs/devel/preface.html "PostgreSQL devel - Preface") Unsupported versions: [13](https://www.postgresql.org/docs/13/preface.html "PostgreSQL 13 - Preface") / [12](https://www.postgresql.org/docs/12/preface.html "PostgreSQL 12 - Preface") / [11](https://www.postgresql.org/docs/11/preface.html "PostgreSQL 11 - Preface") / [10](https://www.postgresql.org/docs/10/preface.html "PostgreSQL 10 - Preface") / [9.6](https://www.postgresql.org/docs/9.6/preface.html "PostgreSQL 9.6 - Preface") / [9.5](https://www.postgresql.org/docs/9.5/preface.html "PostgreSQL 9.5 - Preface") / [9.4](https://www.postgresql.org/docs/9.4/preface.html "PostgreSQL 9.4 - Preface") / [9.3](https://www.postgresql.org/docs/9.3/preface.html "PostgreSQL 9.3 - Preface") / [9.2](https://www.postgresql.org/docs/9.2/preface.html "PostgreSQL 9.2 - Preface") / [9.1](https://www.postgresql.org/docs/9.1/preface.html "PostgreSQL 9.1 - Preface") / [9.0](https://www.postgresql.org/docs/9.0/preface.html "PostgreSQL 9.0 - Preface") / [8.4](https://www.postgresql.org/docs/8.4/preface.html "PostgreSQL 8.4 - Preface") / [8.3](https://www.postgresql.org/docs/8.3/preface.html "PostgreSQL 8.3 - Preface") / [8.2](https://www.postgresql.org/docs/8.2/preface.html "PostgreSQL 8.2 - Preface") / [8.1](https://www.postgresql.org/docs/8.1/preface.html "PostgreSQL 8.1 - Preface") / [8.0](https://www.postgresql.org/docs/8.0/preface.html "PostgreSQL 8.0 - Preface") / [7.4](https://www.postgresql.org/docs/7.4/preface.html "PostgreSQL 7.4 - Preface") / [7.2](https://www.postgresql.org/docs/7.2/preface.html "PostgreSQL 7.2 - Preface") / [7.1](https://www.postgresql.org/docs/7.1/preface.html "PostgreSQL 7.1 - Preface") | Preface | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Up](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | PostgreSQL 18.1 Documentation | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/intro-whatis.html "1.  What Is PostgreSQL?") | * * * Preface ======= **Table of Contents** [1\. What Is PostgreSQL?](https://www.postgresql.org/docs/current/intro-whatis.html) [2\. A Brief History of PostgreSQL](https://www.postgresql.org/docs/current/history.html) [2.1. The Berkeley POSTGRES Project](https://www.postgresql.org/docs/current/history.html#HISTORY-BERKELEY) [2.2. Postgres95](https://www.postgresql.org/docs/current/history.html#HISTORY-POSTGRES95) [2.3. PostgreSQL](https://www.postgresql.org/docs/current/history.html#HISTORY-POSTGRESQL) [3\. Conventions](https://www.postgresql.org/docs/current/notation.html) [4\. Further Information](https://www.postgresql.org/docs/current/resources.html) [5\. Bug Reporting Guidelines](https://www.postgresql.org/docs/current/bug-reporting.html) [5.1. Identifying Bugs](https://www.postgresql.org/docs/current/bug-reporting.html#BUG-REPORTING-IDENTIFYING-BUGS) [5.2. What to Report](https://www.postgresql.org/docs/current/bug-reporting.html#BUG-REPORTING-WHAT-TO-REPORT) [5.3. Where to Report Bugs](https://www.postgresql.org/docs/current/bug-reporting.html#BUG-REPORTING-WHERE-TO-REPORT-BUGS) This book is the official documentation of PostgreSQL. It has been written by the PostgreSQL developers and other volunteers in parallel to the development of the PostgreSQL software. It describes all the functionality that the current version of PostgreSQL officially supports. To make the large amount of information about PostgreSQL manageable, this book has been organized in several parts. Each part is targeted at a different class of users, or at users in different stages of their PostgreSQL experience: * [Part I](https://www.postgresql.org/docs/current/tutorial.html "Part I. Tutorial") is an informal introduction for new users. * [Part II](https://www.postgresql.org/docs/current/sql.html "Part II. The SQL Language") documents the SQL query language environment, including data types and functions, as well as user-level performance tuning. Every PostgreSQL user should read this. * [Part III](https://www.postgresql.org/docs/current/admin.html "Part III. Server Administration") describes the installation and administration of the server. Everyone who runs a PostgreSQL server, be it for private use or for others, should read this part. * [Part IV](https://www.postgresql.org/docs/current/client-interfaces.html "Part IV. Client Interfaces") describes the programming interfaces for PostgreSQL client programs. * [Part V](https://www.postgresql.org/docs/current/server-programming.html "Part V. Server Programming") contains information for advanced users about the extensibility capabilities of the server. Topics include user-defined data types and functions. * [Part VI](https://www.postgresql.org/docs/current/reference.html "Part VI. Reference") contains reference information about SQL commands, client and server programs. This part supports the other parts with structured information sorted by command or program. * [Part VII](https://www.postgresql.org/docs/current/internals.html "Part VII. Internals") contains assorted information that might be of use to PostgreSQL developers. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Up](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/intro-whatis.html "1.  What Is PostgreSQL?") | | PostgreSQL 18.1 Documentation | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 1.  What Is PostgreSQL? | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/preface.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CHECKPOINT November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-checkpoint.html "PostgreSQL 18 - CHECKPOINT") ([18](https://www.postgresql.org/docs/18/sql-checkpoint.html "PostgreSQL 18 - CHECKPOINT") ) / [17](https://www.postgresql.org/docs/17/sql-checkpoint.html "PostgreSQL 17 - CHECKPOINT") / [16](https://www.postgresql.org/docs/16/sql-checkpoint.html "PostgreSQL 16 - CHECKPOINT") / [15](https://www.postgresql.org/docs/15/sql-checkpoint.html "PostgreSQL 15 - CHECKPOINT") / [14](https://www.postgresql.org/docs/14/sql-checkpoint.html "PostgreSQL 14 - CHECKPOINT") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-checkpoint.html "PostgreSQL devel - CHECKPOINT") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-checkpoint.html "PostgreSQL 13 - CHECKPOINT") / [12](https://www.postgresql.org/docs/12/sql-checkpoint.html "PostgreSQL 12 - CHECKPOINT") / [11](https://www.postgresql.org/docs/11/sql-checkpoint.html "PostgreSQL 11 - CHECKPOINT") / [10](https://www.postgresql.org/docs/10/sql-checkpoint.html "PostgreSQL 10 - CHECKPOINT") / [9.6](https://www.postgresql.org/docs/9.6/sql-checkpoint.html "PostgreSQL 9.6 - CHECKPOINT") / [9.5](https://www.postgresql.org/docs/9.5/sql-checkpoint.html "PostgreSQL 9.5 - CHECKPOINT") / [9.4](https://www.postgresql.org/docs/9.4/sql-checkpoint.html "PostgreSQL 9.4 - CHECKPOINT") / [9.3](https://www.postgresql.org/docs/9.3/sql-checkpoint.html "PostgreSQL 9.3 - CHECKPOINT") / [9.2](https://www.postgresql.org/docs/9.2/sql-checkpoint.html "PostgreSQL 9.2 - CHECKPOINT") / [9.1](https://www.postgresql.org/docs/9.1/sql-checkpoint.html "PostgreSQL 9.1 - CHECKPOINT") / [9.0](https://www.postgresql.org/docs/9.0/sql-checkpoint.html "PostgreSQL 9.0 - CHECKPOINT") / [8.4](https://www.postgresql.org/docs/8.4/sql-checkpoint.html "PostgreSQL 8.4 - CHECKPOINT") / [8.3](https://www.postgresql.org/docs/8.3/sql-checkpoint.html "PostgreSQL 8.3 - CHECKPOINT") / [8.2](https://www.postgresql.org/docs/8.2/sql-checkpoint.html "PostgreSQL 8.2 - CHECKPOINT") / [8.1](https://www.postgresql.org/docs/8.1/sql-checkpoint.html "PostgreSQL 8.1 - CHECKPOINT") / [8.0](https://www.postgresql.org/docs/8.0/sql-checkpoint.html "PostgreSQL 8.0 - CHECKPOINT") / [7.4](https://www.postgresql.org/docs/7.4/sql-checkpoint.html "PostgreSQL 7.4 - CHECKPOINT") / [7.3](https://www.postgresql.org/docs/7.3/sql-checkpoint.html "PostgreSQL 7.3 - CHECKPOINT") / [7.2](https://www.postgresql.org/docs/7.2/sql-checkpoint.html "PostgreSQL 7.2 - CHECKPOINT") / [7.1](https://www.postgresql.org/docs/7.1/sql-checkpoint.html "PostgreSQL 7.1 - CHECKPOINT") | CHECKPOINT | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-call.html "CALL") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-close.html "CLOSE") | * * * CHECKPOINT ---------- CHECKPOINT — force a write-ahead log checkpoint Synopsis -------- CHECKPOINT Description ----------- A checkpoint is a point in the write-ahead log sequence at which all data files have been updated to reflect the information in the log. All data files will be flushed to disk. Refer to [Section 28.5](https://www.postgresql.org/docs/current/wal-configuration.html "28.5. WAL Configuration") for more details about what happens during a checkpoint. The `CHECKPOINT` command forces an immediate checkpoint when the command is issued, without waiting for a regular checkpoint scheduled by the system (controlled by the settings in [Section 19.5.2](https://www.postgresql.org/docs/current/runtime-config-wal.html#RUNTIME-CONFIG-WAL-CHECKPOINTS "19.5.2. Checkpoints") ). `CHECKPOINT` is not intended for use during normal operation. If executed during recovery, the `CHECKPOINT` command will force a restartpoint (see [Section 28.5](https://www.postgresql.org/docs/current/wal-configuration.html "28.5. WAL Configuration") ) rather than writing a new checkpoint. Only superusers or users with the privileges of the [pg\_checkpoint](https://www.postgresql.org/docs/current/predefined-roles.html#PREDEFINED-ROLE-PG-CHECKPOINT) role can call `CHECKPOINT`. Compatibility ------------- The `CHECKPOINT` command is a PostgreSQL language extension. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-call.html "CALL") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-close.html "CLOSE") | | CALL | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | CLOSE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-checkpoint.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: DROP RULE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-droprule.html "PostgreSQL 18 - DROP RULE") ([18](https://www.postgresql.org/docs/18/sql-droprule.html "PostgreSQL 18 - DROP RULE") ) / [17](https://www.postgresql.org/docs/17/sql-droprule.html "PostgreSQL 17 - DROP RULE") / [16](https://www.postgresql.org/docs/16/sql-droprule.html "PostgreSQL 16 - DROP RULE") / [15](https://www.postgresql.org/docs/15/sql-droprule.html "PostgreSQL 15 - DROP RULE") / [14](https://www.postgresql.org/docs/14/sql-droprule.html "PostgreSQL 14 - DROP RULE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-droprule.html "PostgreSQL devel - DROP RULE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-droprule.html "PostgreSQL 13 - DROP RULE") / [12](https://www.postgresql.org/docs/12/sql-droprule.html "PostgreSQL 12 - DROP RULE") / [11](https://www.postgresql.org/docs/11/sql-droprule.html "PostgreSQL 11 - DROP RULE") / [10](https://www.postgresql.org/docs/10/sql-droprule.html "PostgreSQL 10 - DROP RULE") / [9.6](https://www.postgresql.org/docs/9.6/sql-droprule.html "PostgreSQL 9.6 - DROP RULE") / [9.5](https://www.postgresql.org/docs/9.5/sql-droprule.html "PostgreSQL 9.5 - DROP RULE") / [9.4](https://www.postgresql.org/docs/9.4/sql-droprule.html "PostgreSQL 9.4 - DROP RULE") / [9.3](https://www.postgresql.org/docs/9.3/sql-droprule.html "PostgreSQL 9.3 - DROP RULE") / [9.2](https://www.postgresql.org/docs/9.2/sql-droprule.html "PostgreSQL 9.2 - DROP RULE") / [9.1](https://www.postgresql.org/docs/9.1/sql-droprule.html "PostgreSQL 9.1 - DROP RULE") / [9.0](https://www.postgresql.org/docs/9.0/sql-droprule.html "PostgreSQL 9.0 - DROP RULE") / [8.4](https://www.postgresql.org/docs/8.4/sql-droprule.html "PostgreSQL 8.4 - DROP RULE") / [8.3](https://www.postgresql.org/docs/8.3/sql-droprule.html "PostgreSQL 8.3 - DROP RULE") / [8.2](https://www.postgresql.org/docs/8.2/sql-droprule.html "PostgreSQL 8.2 - DROP RULE") / [8.1](https://www.postgresql.org/docs/8.1/sql-droprule.html "PostgreSQL 8.1 - DROP RULE") / [8.0](https://www.postgresql.org/docs/8.0/sql-droprule.html "PostgreSQL 8.0 - DROP RULE") / [7.4](https://www.postgresql.org/docs/7.4/sql-droprule.html "PostgreSQL 7.4 - DROP RULE") / [7.3](https://www.postgresql.org/docs/7.3/sql-droprule.html "PostgreSQL 7.3 - DROP RULE") / [7.2](https://www.postgresql.org/docs/7.2/sql-droprule.html "PostgreSQL 7.2 - DROP RULE") / [7.1](https://www.postgresql.org/docs/7.1/sql-droprule.html "PostgreSQL 7.1 - DROP RULE") | DROP RULE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-droproutine.html "DROP ROUTINE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-dropschema.html "DROP SCHEMA") | * * * DROP RULE --------- DROP RULE — remove a rewrite rule Synopsis -------- DROP RULE \[ IF EXISTS \] _`name`_ ON _`table_name`_ \[ CASCADE | RESTRICT \] Description ----------- `DROP RULE` drops a rewrite rule. Parameters ---------- `IF EXISTS` Do not throw an error if the rule does not exist. A notice is issued in this case. _`name`_ The name of the rule to drop. _`table_name`_ The name (optionally schema-qualified) of the table or view that the rule applies to. `CASCADE` Automatically drop objects that depend on the rule, and in turn all objects that depend on those objects (see [Section 5.15](https://www.postgresql.org/docs/current/ddl-depend.html "5.15. Dependency Tracking") ). `RESTRICT` Refuse to drop the rule if any objects depend on it. This is the default. Examples -------- To drop the rewrite rule `newrule`: DROP RULE newrule ON mytable; Compatibility ------------- `DROP RULE` is a PostgreSQL language extension, as is the entire query rewrite system. See Also -------- [CREATE RULE](https://www.postgresql.org/docs/current/sql-createrule.html "CREATE RULE") , [ALTER RULE](https://www.postgresql.org/docs/current/sql-alterrule.html "ALTER RULE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-droproutine.html "DROP ROUTINE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-dropschema.html "DROP SCHEMA") | | DROP ROUTINE | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | DROP SCHEMA | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-droprule.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 5.5. Constraints November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/ddl-constraints.html "PostgreSQL 18 - 5.5. Constraints") ([18](https://www.postgresql.org/docs/18/ddl-constraints.html "PostgreSQL 18 - 5.5. Constraints") ) / [17](https://www.postgresql.org/docs/17/ddl-constraints.html "PostgreSQL 17 - 5.5. Constraints") / [16](https://www.postgresql.org/docs/16/ddl-constraints.html "PostgreSQL 16 - 5.5. Constraints") / [15](https://www.postgresql.org/docs/15/ddl-constraints.html "PostgreSQL 15 - 5.5. Constraints") / [14](https://www.postgresql.org/docs/14/ddl-constraints.html "PostgreSQL 14 - 5.5. Constraints") Development Versions: [devel](https://www.postgresql.org/docs/devel/ddl-constraints.html "PostgreSQL devel - 5.5. Constraints") Unsupported versions: [13](https://www.postgresql.org/docs/13/ddl-constraints.html "PostgreSQL 13 - 5.5. Constraints") / [12](https://www.postgresql.org/docs/12/ddl-constraints.html "PostgreSQL 12 - 5.5. Constraints") / [11](https://www.postgresql.org/docs/11/ddl-constraints.html "PostgreSQL 11 - 5.5. Constraints") / [10](https://www.postgresql.org/docs/10/ddl-constraints.html "PostgreSQL 10 - 5.5. Constraints") / [9.6](https://www.postgresql.org/docs/9.6/ddl-constraints.html "PostgreSQL 9.6 - 5.5. Constraints") / [9.5](https://www.postgresql.org/docs/9.5/ddl-constraints.html "PostgreSQL 9.5 - 5.5. Constraints") / [9.4](https://www.postgresql.org/docs/9.4/ddl-constraints.html "PostgreSQL 9.4 - 5.5. Constraints") / [9.3](https://www.postgresql.org/docs/9.3/ddl-constraints.html "PostgreSQL 9.3 - 5.5. Constraints") / [9.2](https://www.postgresql.org/docs/9.2/ddl-constraints.html "PostgreSQL 9.2 - 5.5. Constraints") / [9.1](https://www.postgresql.org/docs/9.1/ddl-constraints.html "PostgreSQL 9.1 - 5.5. Constraints") / [9.0](https://www.postgresql.org/docs/9.0/ddl-constraints.html "PostgreSQL 9.0 - 5.5. Constraints") / [8.4](https://www.postgresql.org/docs/8.4/ddl-constraints.html "PostgreSQL 8.4 - 5.5. Constraints") / [8.3](https://www.postgresql.org/docs/8.3/ddl-constraints.html "PostgreSQL 8.3 - 5.5. Constraints") / [8.2](https://www.postgresql.org/docs/8.2/ddl-constraints.html "PostgreSQL 8.2 - 5.5. Constraints") / [8.1](https://www.postgresql.org/docs/8.1/ddl-constraints.html "PostgreSQL 8.1 - 5.5. Constraints") / [8.0](https://www.postgresql.org/docs/8.0/ddl-constraints.html "PostgreSQL 8.0 - 5.5. Constraints") / [7.4](https://www.postgresql.org/docs/7.4/ddl-constraints.html "PostgreSQL 7.4 - 5.5. Constraints") / [7.3](https://www.postgresql.org/docs/7.3/ddl-constraints.html "PostgreSQL 7.3 - 5.5. Constraints") | 5.5. Constraints | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/ddl-generated-columns.html "5.4. Generated Columns") | [Up](https://www.postgresql.org/docs/current/ddl.html "Chapter 5. Data Definition") | Chapter 5. Data Definition | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/ddl-system-columns.html "5.6. System Columns") | * * * 5.5. Constraints [#](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS) --------------------------------------------------------------------------------------------------- [5.5.1. Check Constraints](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-CHECK-CONSTRAINTS) [5.5.2. Not-Null Constraints](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-NOT-NULL) [5.5.3. Unique Constraints](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-UNIQUE-CONSTRAINTS) [5.5.4. Primary Keys](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-PRIMARY-KEYS) [5.5.5. Foreign Keys](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-FK) [5.5.6. Exclusion Constraints](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-EXCLUSION) Data types are a way to limit the kind of data that can be stored in a table. For many applications, however, the constraint they provide is too coarse. For example, a column containing a product price should probably only accept positive values. But there is no standard data type that accepts only positive numbers. Another issue is that you might want to constrain column data with respect to other columns or rows. For example, in a table containing product information, there should be only one row for each product number. To that end, SQL allows you to define constraints on columns and tables. Constraints give you as much control over the data in your tables as you wish. If a user attempts to store data in a column that would violate a constraint, an error is raised. This applies even if the value came from the default value definition. ### 5.5.1. Check Constraints [#](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-CHECK-CONSTRAINTS) A check constraint is the most generic constraint type. It allows you to specify that the value in a certain column must satisfy a Boolean (truth-value) expression. For instance, to require positive product prices, you could use: CREATE TABLE products ( product\_no integer, name text, price numeric **CHECK (price > 0)** ); As you see, the constraint definition comes after the data type, just like default value definitions. Default values and constraints can be listed in any order. A check constraint consists of the key word `CHECK` followed by an expression in parentheses. The check constraint expression should involve the column thus constrained, otherwise the constraint would not make too much sense. You can also give the constraint a separate name. This clarifies error messages and allows you to refer to the constraint when you need to change it. The syntax is: CREATE TABLE products ( product\_no integer, name text, price numeric **CONSTRAINT positive\_price** CHECK (price > 0) ); So, to specify a named constraint, use the key word `CONSTRAINT` followed by an identifier followed by the constraint definition. (If you don't specify a constraint name in this way, the system chooses a name for you.) A check constraint can also refer to several columns. Say you store a regular price and a discounted price, and you want to ensure that the discounted price is lower than the regular price: CREATE TABLE products ( product\_no integer, name text, price numeric CHECK (price > 0), discounted\_price numeric CHECK (discounted\_price > 0), **CHECK (price > discounted\_price)** ); The first two constraints should look familiar. The third one uses a new syntax. It is not attached to a particular column, instead it appears as a separate item in the comma-separated column list. Column definitions and these constraint definitions can be listed in mixed order. We say that the first two constraints are column constraints, whereas the third one is a table constraint because it is written separately from any one column definition. Column constraints can also be written as table constraints, while the reverse is not necessarily possible, since a column constraint is supposed to refer to only the column it is attached to. (PostgreSQL doesn't enforce that rule, but you should follow it if you want your table definitions to work with other database systems.) The above example could also be written as: CREATE TABLE products ( product\_no integer, name text, price numeric, CHECK (price > 0), discounted\_price numeric, CHECK (discounted\_price > 0), CHECK (price > discounted\_price) ); or even: CREATE TABLE products ( product\_no integer, name text, price numeric CHECK (price > 0), discounted\_price numeric, CHECK (discounted\_price > 0 AND price > discounted\_price) ); It's a matter of taste. Names can be assigned to table constraints in the same way as column constraints: CREATE TABLE products ( product\_no integer, name text, price numeric, CHECK (price > 0), discounted\_price numeric, CHECK (discounted\_price > 0), **CONSTRAINT valid\_discount** CHECK (price > discounted\_price) ); It should be noted that a check constraint is satisfied if the check expression evaluates to true or the null value. Since most expressions will evaluate to the null value if any operand is null, they will not prevent null values in the constrained columns. To ensure that a column does not contain null values, the not-null constraint described in the next section can be used. ### Note PostgreSQL does not support `CHECK` constraints that reference table data other than the new or updated row being checked. While a `CHECK` constraint that violates this rule may appear to work in simple tests, it cannot guarantee that the database will not reach a state in which the constraint condition is false (due to subsequent changes of the other row(s) involved). This would cause a database dump and restore to fail. The restore could fail even when the complete database state is consistent with the constraint, due to rows not being loaded in an order that will satisfy the constraint. If possible, use `UNIQUE`, `EXCLUDE`, or `FOREIGN KEY` constraints to express cross-row and cross-table restrictions. If what you desire is a one-time check against other rows at row insertion, rather than a continuously-maintained consistency guarantee, a custom [trigger](https://www.postgresql.org/docs/current/triggers.html "Chapter 37. Triggers") can be used to implement that. (This approach avoids the dump/restore problem because pg\_dump does not reinstall triggers until after restoring data, so that the check will not be enforced during a dump/restore.) ### Note PostgreSQL assumes that `CHECK` constraints' conditions are immutable, that is, they will always give the same result for the same input row. This assumption is what justifies examining `CHECK` constraints only when rows are inserted or updated, and not at other times. (The warning above about not referencing other table data is really a special case of this restriction.) An example of a common way to break this assumption is to reference a user-defined function in a `CHECK` expression, and then change the behavior of that function. PostgreSQL does not disallow that, but it will not notice if there are rows in the table that now violate the `CHECK` constraint. That would cause a subsequent database dump and restore to fail. The recommended way to handle such a change is to drop the constraint (using `ALTER TABLE`), adjust the function definition, and re-add the constraint, thereby rechecking it against all table rows. ### 5.5.2. Not-Null Constraints [#](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-NOT-NULL) A not-null constraint simply specifies that a column must not assume the null value. A syntax example: CREATE TABLE products ( product\_no integer **NOT NULL**, name text **NOT NULL**, price numeric ); An explicit constraint name can also be specified, for example: CREATE TABLE products ( product\_no integer NOT NULL, name text **CONSTRAINT products\_name\_not\_null** NOT NULL, price numeric ); A not-null constraint is usually written as a column constraint. The syntax for writing it as a table constraint is CREATE TABLE products ( product\_no integer, name text, price numeric, **NOT NULL product\_no**, **NOT NULL name** ); But this syntax is not standard and mainly intended for use by pg\_dump. A not-null constraint is functionally equivalent to creating a check constraint ``CHECK (_`column_name`_ IS NOT NULL)``, but in PostgreSQL creating an explicit not-null constraint is more efficient. Of course, a column can have more than one constraint. Just write the constraints one after another: CREATE TABLE products ( product\_no integer NOT NULL, name text NOT NULL, price numeric NOT NULL CHECK (price > 0) ); The order doesn't matter. It does not necessarily determine in which order the constraints are checked. However, a column can have at most one explicit not-null constraint. The `NOT NULL` constraint has an inverse: the `NULL` constraint. This does not mean that the column must be null, which would surely be useless. Instead, this simply selects the default behavior that the column might be null. The `NULL` constraint is not present in the SQL standard and should not be used in portable applications. (It was only added to PostgreSQL to be compatible with some other database systems.) Some users, however, like it because it makes it easy to toggle the constraint in a script file. For example, you could start with: CREATE TABLE products ( product\_no integer NULL, name text NULL, price numeric NULL ); and then insert the `NOT` key word where desired. ### Tip In most database designs the majority of columns should be marked not null. ### 5.5.3. Unique Constraints [#](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-UNIQUE-CONSTRAINTS) Unique constraints ensure that the data contained in a column, or a group of columns, is unique among all the rows in the table. The syntax is: CREATE TABLE products ( product\_no integer **UNIQUE**, name text, price numeric ); when written as a column constraint, and: CREATE TABLE products ( product\_no integer, name text, price numeric, **UNIQUE (product\_no)** ); when written as a table constraint. To define a unique constraint for a group of columns, write it as a table constraint with the column names separated by commas: CREATE TABLE example ( a integer, b integer, c integer, **UNIQUE (a, c)** ); This specifies that the combination of values in the indicated columns is unique across the whole table, though any one of the columns need not be (and ordinarily isn't) unique. You can assign your own name for a unique constraint, in the usual way: CREATE TABLE products ( product\_no integer **CONSTRAINT must\_be\_different** UNIQUE, name text, price numeric ); Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint. A uniqueness restriction covering only some rows cannot be written as a unique constraint, but it is possible to enforce such a restriction by creating a unique [partial index](https://www.postgresql.org/docs/current/indexes-partial.html "11.8. Partial Indexes") . In general, a unique constraint is violated if there is more than one row in the table where the values of all of the columns included in the constraint are equal. By default, two null values are not considered equal in this comparison. That means even in the presence of a unique constraint it is possible to store duplicate rows that contain a null value in at least one of the constrained columns. This behavior can be changed by adding the clause `NULLS NOT DISTINCT`, like CREATE TABLE products ( product\_no integer UNIQUE **NULLS NOT DISTINCT**, name text, price numeric ); or CREATE TABLE products ( product\_no integer, name text, price numeric, UNIQUE **NULLS NOT DISTINCT** (product\_no) ); The default behavior can be specified explicitly using `NULLS DISTINCT`. The default null treatment in unique constraints is implementation-defined according to the SQL standard, and other implementations have a different behavior. So be careful when developing applications that are intended to be portable. ### 5.5.4. Primary Keys [#](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-PRIMARY-KEYS) A primary key constraint indicates that a column, or group of columns, can be used as a unique identifier for rows in the table. This requires that the values be both unique and not null. So, the following two table definitions accept the same data: CREATE TABLE products ( product\_no integer UNIQUE NOT NULL, name text, price numeric ); CREATE TABLE products ( product\_no integer **PRIMARY KEY**, name text, price numeric ); Primary keys can span more than one column; the syntax is similar to unique constraints: CREATE TABLE example ( a integer, b integer, c integer, **PRIMARY KEY (a, c)** ); Adding a primary key will automatically create a unique B-tree index on the column or group of columns listed in the primary key, and will force the column(s) to be marked `NOT NULL`. A table can have at most one primary key. (There can be any number of unique constraints, which combined with not-null constraints are functionally almost the same thing, but only one can be identified as the primary key.) Relational database theory dictates that every table must have a primary key. This rule is not enforced by PostgreSQL, but it is usually best to follow it. Primary keys are useful both for documentation purposes and for client applications. For example, a GUI application that allows modifying row values probably needs to know the primary key of a table to be able to identify rows uniquely. There are also various ways in which the database system makes use of a primary key if one has been declared; for example, the primary key defines the default target column(s) for foreign keys referencing its table. ### 5.5.5. Foreign Keys [#](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-FK) A foreign key constraint specifies that the values in a column (or a group of columns) must match the values appearing in some row of another table. We say this maintains the _referential integrity_ between two related tables. Say you have the product table that we have used several times already: CREATE TABLE products ( product\_no integer PRIMARY KEY, name text, price numeric ); Let's also assume you have a table storing orders of those products. We want to ensure that the orders table only contains orders of products that actually exist. So we define a foreign key constraint in the orders table that references the products table: CREATE TABLE orders ( order\_id integer PRIMARY KEY, product\_no integer **REFERENCES products (product\_no)**, quantity integer ); Now it is impossible to create orders with non-NULL `product_no` entries that do not appear in the products table. We say that in this situation the orders table is the _referencing_ table and the products table is the _referenced_ table. Similarly, there are referencing and referenced columns. You can also shorten the above command to: CREATE TABLE orders ( order\_id integer PRIMARY KEY, product\_no integer **REFERENCES products**, quantity integer ); because in absence of a column list the primary key of the referenced table is used as the referenced column(s). You can assign your own name for a foreign key constraint, in the usual way. A foreign key can also constrain and reference a group of columns. As usual, it then needs to be written in table constraint form. Here is a contrived syntax example: CREATE TABLE t1 ( a integer PRIMARY KEY, b integer, c integer, **FOREIGN KEY (b, c) REFERENCES other\_table (c1, c2)** ); Of course, the number and type of the constrained columns need to match the number and type of the referenced columns. Sometimes it is useful for the “other table” of a foreign key constraint to be the same table; this is called a _self-referential_ foreign key. For example, if you want rows of a table to represent nodes of a tree structure, you could write CREATE TABLE tree ( node\_id integer PRIMARY KEY, parent\_id integer REFERENCES tree, name text, ... ); A top-level node would have NULL `parent_id`, while non-NULL `parent_id` entries would be constrained to reference valid rows of the table. A table can have more than one foreign key constraint. This is used to implement many-to-many relationships between tables. Say you have tables about products and orders, but now you want to allow one order to contain possibly many products (which the structure above did not allow). You could use this table structure: CREATE TABLE products ( product\_no integer PRIMARY KEY, name text, price numeric ); CREATE TABLE orders ( order\_id integer PRIMARY KEY, shipping\_address text, ... ); CREATE TABLE order\_items ( product\_no integer REFERENCES products, order\_id integer REFERENCES orders, quantity integer, PRIMARY KEY (product\_no, order\_id) ); Notice that the primary key overlaps with the foreign keys in the last table. We know that the foreign keys disallow creation of orders that do not relate to any products. But what if a product is removed after an order is created that references it? SQL allows you to handle that as well. Intuitively, we have a few options: * Disallow deleting a referenced product * Delete the orders as well * Something else? To illustrate this, let's implement the following policy on the many-to-many relationship example above: when someone wants to remove a product that is still referenced by an order (via `order_items`), we disallow it. If someone removes an order, the order items are removed as well: CREATE TABLE products ( product\_no integer PRIMARY KEY, name text, price numeric ); CREATE TABLE orders ( order\_id integer PRIMARY KEY, shipping\_address text, ... ); CREATE TABLE order\_items ( product\_no integer REFERENCES products **ON DELETE RESTRICT**, order\_id integer REFERENCES orders **ON DELETE CASCADE**, quantity integer, PRIMARY KEY (product\_no, order\_id) ); The default `ON DELETE` action is `ON DELETE NO ACTION`; this does not need to be specified. This means that the deletion in the referenced table is allowed to proceed. But the foreign-key constraint is still required to be satisfied, so this operation will usually result in an error. But checking of foreign-key constraints can also be deferred to later in the transaction (not covered in this chapter). In that case, the `NO ACTION` setting would allow other commands to “fix” the situation before the constraint is checked, for example by inserting another suitable row into the referenced table or by deleting the now-dangling rows from the referencing table. `RESTRICT` is a stricter setting than `NO ACTION`. It prevents deletion of a referenced row. `RESTRICT` does not allow the check to be deferred until later in the transaction. `CASCADE` specifies that when a referenced row is deleted, row(s) referencing it should be automatically deleted as well. There are two other options: `SET NULL` and `SET DEFAULT`. These cause the referencing column(s) in the referencing row(s) to be set to nulls or their default values, respectively, when the referenced row is deleted. Note that these do not excuse you from observing any constraints. For example, if an action specifies `SET DEFAULT` but the default value would not satisfy the foreign key constraint, the operation will fail. The appropriate choice of `ON DELETE` action depends on what kinds of objects the related tables represent. When the referencing table represents something that is a component of what is represented by the referenced table and cannot exist independently, then `CASCADE` could be appropriate. If the two tables represent independent objects, then `RESTRICT` or `NO ACTION` is more appropriate; an application that actually wants to delete both objects would then have to be explicit about this and run two delete commands. In the above example, order items are part of an order, and it is convenient if they are deleted automatically if an order is deleted. But products and orders are different things, and so making a deletion of a product automatically cause the deletion of some order items could be considered problematic. The actions `SET NULL` or `SET DEFAULT` can be appropriate if a foreign-key relationship represents optional information. For example, if the products table contained a reference to a product manager, and the product manager entry gets deleted, then setting the product's product manager to null or a default might be useful. The actions `SET NULL` and `SET DEFAULT` can take a column list to specify which columns to set. Normally, all columns of the foreign-key constraint are set; setting only a subset is useful in some special cases. Consider the following example: CREATE TABLE tenants ( tenant\_id integer PRIMARY KEY ); CREATE TABLE users ( tenant\_id integer REFERENCES tenants ON DELETE CASCADE, user\_id integer NOT NULL, PRIMARY KEY (tenant\_id, user\_id) ); CREATE TABLE posts ( tenant\_id integer REFERENCES tenants ON DELETE CASCADE, post\_id integer NOT NULL, author\_id integer, PRIMARY KEY (tenant\_id, post\_id), FOREIGN KEY (tenant\_id, author\_id) REFERENCES users ON DELETE SET NULL **(author\_id)** ); Without the specification of the column, the foreign key would also set the column `tenant_id` to null, but that column is still required as part of the primary key. Analogous to `ON DELETE` there is also `ON UPDATE` which is invoked when a referenced column is changed (updated). The possible actions are the same, except that column lists cannot be specified for `SET NULL` and `SET DEFAULT`. In this case, `CASCADE` means that the updated values of the referenced column(s) should be copied into the referencing row(s). There is also a noticeable difference between `ON UPDATE NO ACTION` (the default) and `ON UPDATE RESTRICT`. The former will allow the update to proceed and the foreign-key constraint will be checked against the state after the update. The latter will prevent the update to run even if the state after the update would still satisfy the constraint. This prevents updating a referenced row to a value that is distinct but compares as equal (for example, a character string with a different case variant, if a character string type with a case-insensitive collation is used). Normally, a referencing row need not satisfy the foreign key constraint if any of its referencing columns are null. If `MATCH FULL` is added to the foreign key declaration, a referencing row escapes satisfying the constraint only if all its referencing columns are null (so a mix of null and non-null values is guaranteed to fail a `MATCH FULL` constraint). If you don't want referencing rows to be able to avoid satisfying the foreign key constraint, declare the referencing column(s) as `NOT NULL`. A foreign key must reference columns that either are a primary key or form a unique constraint, or are columns from a non-partial unique index. This means that the referenced columns always have an index to allow efficient lookups on whether a referencing row has a match. Since a `DELETE` of a row from the referenced table or an `UPDATE` of a referenced column will require a scan of the referencing table for rows matching the old value, it is often a good idea to index the referencing columns too. Because this is not always needed, and there are many choices available on how to index, the declaration of a foreign key constraint does not automatically create an index on the referencing columns. More information about updating and deleting data is in [Chapter 6](https://www.postgresql.org/docs/current/dml.html "Chapter 6. Data Manipulation") . Also see the description of foreign key constraint syntax in the reference documentation for [CREATE TABLE](https://www.postgresql.org/docs/current/sql-createtable.html "CREATE TABLE") . ### 5.5.6. Exclusion Constraints [#](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-EXCLUSION) Exclusion constraints ensure that if any two rows are compared on the specified columns or expressions using the specified operators, at least one of these operator comparisons will return false or null. The syntax is: CREATE TABLE circles ( c circle, EXCLUDE USING gist (c WITH &&) ); See also [`CREATE TABLE ... CONSTRAINT ... EXCLUDE`](https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-EXCLUDE) for details. Adding an exclusion constraint will automatically create an index of the type specified in the constraint declaration. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/ddl-generated-columns.html "5.4. Generated Columns") | [Up](https://www.postgresql.org/docs/current/ddl.html "Chapter 5. Data Definition") | [Next](https://www.postgresql.org/docs/current/ddl-system-columns.html "5.6. System Columns") | | 5.4. Generated Columns | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 5.6. System Columns | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/ddl-constraints.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.25. pg_settings November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-settings.html "PostgreSQL 18 - 53.25. pg_settings") ([18](https://www.postgresql.org/docs/18/view-pg-settings.html "PostgreSQL 18 - 53.25. pg_settings") ) / [17](https://www.postgresql.org/docs/17/view-pg-settings.html "PostgreSQL 17 - 53.25. pg_settings") / [16](https://www.postgresql.org/docs/16/view-pg-settings.html "PostgreSQL 16 - 53.25. pg_settings") / [15](https://www.postgresql.org/docs/15/view-pg-settings.html "PostgreSQL 15 - 53.25. pg_settings") / [14](https://www.postgresql.org/docs/14/view-pg-settings.html "PostgreSQL 14 - 53.25. pg_settings") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-settings.html "PostgreSQL devel - 53.25. pg_settings") Unsupported versions: [13](https://www.postgresql.org/docs/13/view-pg-settings.html "PostgreSQL 13 - 53.25. pg_settings") / [12](https://www.postgresql.org/docs/12/view-pg-settings.html "PostgreSQL 12 - 53.25. pg_settings") / [11](https://www.postgresql.org/docs/11/view-pg-settings.html "PostgreSQL 11 - 53.25. pg_settings") / [10](https://www.postgresql.org/docs/10/view-pg-settings.html "PostgreSQL 10 - 53.25. pg_settings") / [9.6](https://www.postgresql.org/docs/9.6/view-pg-settings.html "PostgreSQL 9.6 - 53.25. pg_settings") / [9.5](https://www.postgresql.org/docs/9.5/view-pg-settings.html "PostgreSQL 9.5 - 53.25. pg_settings") / [9.4](https://www.postgresql.org/docs/9.4/view-pg-settings.html "PostgreSQL 9.4 - 53.25. pg_settings") / [9.3](https://www.postgresql.org/docs/9.3/view-pg-settings.html "PostgreSQL 9.3 - 53.25. pg_settings") / [9.2](https://www.postgresql.org/docs/9.2/view-pg-settings.html "PostgreSQL 9.2 - 53.25. pg_settings") / [9.1](https://www.postgresql.org/docs/9.1/view-pg-settings.html "PostgreSQL 9.1 - 53.25. pg_settings") / [9.0](https://www.postgresql.org/docs/9.0/view-pg-settings.html "PostgreSQL 9.0 - 53.25. pg_settings") / [8.4](https://www.postgresql.org/docs/8.4/view-pg-settings.html "PostgreSQL 8.4 - 53.25. pg_settings") / [8.3](https://www.postgresql.org/docs/8.3/view-pg-settings.html "PostgreSQL 8.3 - 53.25. pg_settings") / [8.2](https://www.postgresql.org/docs/8.2/view-pg-settings.html "PostgreSQL 8.2 - 53.25. pg_settings") / [8.1](https://www.postgresql.org/docs/8.1/view-pg-settings.html "PostgreSQL 8.1 - 53.25. pg_settings") / [8.0](https://www.postgresql.org/docs/8.0/view-pg-settings.html "PostgreSQL 8.0 - 53.25. pg_settings") / [7.4](https://www.postgresql.org/docs/7.4/view-pg-settings.html "PostgreSQL 7.4 - 53.25. pg_settings") | 53.25. `pg_settings` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-sequences.html "53.24. pg_sequences") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/view-pg-shadow.html "53.26. pg_shadow") | * * * 53.25. `pg_settings` [#](https://www.postgresql.org/docs/18/view-pg-settings.html#VIEW-PG-SETTINGS) ---------------------------------------------------------------------------------------------------- The view `pg_settings` provides access to run-time parameters of the server. It is essentially an alternative interface to the [`SHOW`](https://www.postgresql.org/docs/18/sql-show.html "SHOW") and [`SET`](https://www.postgresql.org/docs/18/sql-set.html "SET") commands. It also provides access to some facts about each parameter that are not directly available from [`SHOW`](https://www.postgresql.org/docs/18/sql-show.html "SHOW") , such as minimum and maximum values. **Table 53.25. `pg_settings` Columns** | Column Type

Description | | --- | | `name` `text`

Run-time configuration parameter name | | `setting` `text`

Current value of the parameter | | `unit` `text`

Implicit unit of the parameter | | `category` `text`

Logical group of the parameter | | `short_desc` `text`

A brief description of the parameter | | `extra_desc` `text`

Additional, more detailed, description of the parameter | | `context` `text`

Context required to set the parameter's value (see below) | | `vartype` `text`

Parameter type (`bool`, `enum`, `integer`, `real`, or `string`) | | `source` `text`

Source of the current parameter value | | `min_val` `text`

Minimum allowed value of the parameter (null for non-numeric values) | | `max_val` `text`

Maximum allowed value of the parameter (null for non-numeric values) | | `enumvals` `text[]`

Allowed values of an enum parameter (null for non-enum values) | | `boot_val` `text`

Parameter value assumed at server startup if the parameter is not otherwise set | | `reset_val` `text`

Value that [`RESET`](https://www.postgresql.org/docs/18/sql-reset.html "RESET")
would reset the parameter to in the current session | | `sourcefile` `text`

Configuration file the current value was set in (null for values set from sources other than configuration files, or when examined by a user who neither is a superuser nor has privileges of `pg_read_all_settings`); helpful when using `include` directives in configuration files | | `sourceline` `int4`

Line number within the configuration file the current value was set at (null for values set from sources other than configuration files, or when examined by a user who neither is a superuser nor has privileges of `pg_read_all_settings`). | | `pending_restart` `bool`

`true` if the value has been changed in the configuration file but needs a restart; or `false` otherwise. | There are several possible values of `context`. In order of decreasing difficulty of changing the setting, they are: `internal` These settings cannot be changed directly; they reflect internally determined values. Some of them may be adjustable by rebuilding the server with different configuration options, or by changing options supplied to initdb. `postmaster` These settings can only be applied when the server starts, so any change requires restarting the server. Values for these settings are typically stored in the `postgresql.conf` file, or passed on the command line when starting the server. Of course, settings with any of the lower `context` types can also be set at server start time. `sighup` Changes to these settings can be made in `postgresql.conf` without restarting the server. Send a SIGHUP signal to the postmaster to cause it to re-read `postgresql.conf` and apply the changes. The postmaster will also forward the SIGHUP signal to its child processes so that they all pick up the new value. `superuser-backend` Changes to these settings can be made in `postgresql.conf` without restarting the server. They can also be set for a particular session in the connection request packet (for example, via libpq's `PGOPTIONS` environment variable), but only if the connecting user is a superuser or has been granted the appropriate `SET` privilege. However, these settings never change in a session after it is started. If you change them in `postgresql.conf`, send a SIGHUP signal to the postmaster to cause it to re-read `postgresql.conf`. The new values will only affect subsequently-launched sessions. `backend` Changes to these settings can be made in `postgresql.conf` without restarting the server. They can also be set for a particular session in the connection request packet (for example, via libpq's `PGOPTIONS` environment variable); any user can make such a change for their session. However, these settings never change in a session after it is started. If you change them in `postgresql.conf`, send a SIGHUP signal to the postmaster to cause it to re-read `postgresql.conf`. The new values will only affect subsequently-launched sessions. `superuser` These settings can be set from `postgresql.conf`, or within a session via the `SET` command; but only superusers and users with the appropriate `SET` privilege can change them via `SET`. Changes in `postgresql.conf` will affect existing sessions only if no session-local value has been established with `SET`. `user` These settings can be set from `postgresql.conf`, or within a session via the `SET` command. Any user is allowed to change their session-local value. Changes in `postgresql.conf` will affect existing sessions only if no session-local value has been established with `SET`. See [Section 19.1](https://www.postgresql.org/docs/18/config-setting.html "19.1. Setting Parameters") for more information about the various ways to change these parameters. This view cannot be inserted into or deleted from, but it can be updated. An `UPDATE` applied to a row of `pg_settings` is equivalent to executing the `SET` command on that named parameter. The change only affects the value used by the current session. If an `UPDATE` is issued within a transaction that is later aborted, the effects of the `UPDATE` command disappear when the transaction is rolled back. Once the surrounding transaction is committed, the effects will persist until the end of the session, unless overridden by another `UPDATE` or `SET`. This view does not display [customized options](https://www.postgresql.org/docs/18/runtime-config-custom.html "19.16. Customized Options") unless the extension module that defines them has been loaded by the backend process executing the query (e.g., via a mention in [shared\_preload\_libraries](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES) , a call to a C function in the extension, or the [`LOAD`](https://www.postgresql.org/docs/18/sql-load.html "LOAD") command). For example, since [archive modules](https://www.postgresql.org/docs/18/archive-modules.html "Chapter 49. Archive Modules") are normally loaded only by the archiver process not regular sessions, this view will not display any customized options defined by such modules unless special action is taken to load them into the backend process executing the query. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-sequences.html "53.24. pg_sequences") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/18/view-pg-shadow.html "53.26. pg_shadow") | | 53.24. `pg_sequences` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 53.26. `pg_shadow` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-settings.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.25. pg_settings November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-settings.html "PostgreSQL 18 - 53.25. pg_settings") ([18](https://www.postgresql.org/docs/18/view-pg-settings.html "PostgreSQL 18 - 53.25. pg_settings") ) / [17](https://www.postgresql.org/docs/17/view-pg-settings.html "PostgreSQL 17 - 53.25. pg_settings") / [16](https://www.postgresql.org/docs/16/view-pg-settings.html "PostgreSQL 16 - 53.25. pg_settings") / [15](https://www.postgresql.org/docs/15/view-pg-settings.html "PostgreSQL 15 - 53.25. pg_settings") / [14](https://www.postgresql.org/docs/14/view-pg-settings.html "PostgreSQL 14 - 53.25. pg_settings") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-settings.html "PostgreSQL devel - 53.25. pg_settings") Unsupported versions: [13](https://www.postgresql.org/docs/13/view-pg-settings.html "PostgreSQL 13 - 53.25. pg_settings") / [12](https://www.postgresql.org/docs/12/view-pg-settings.html "PostgreSQL 12 - 53.25. pg_settings") / [11](https://www.postgresql.org/docs/11/view-pg-settings.html "PostgreSQL 11 - 53.25. pg_settings") / [10](https://www.postgresql.org/docs/10/view-pg-settings.html "PostgreSQL 10 - 53.25. pg_settings") / [9.6](https://www.postgresql.org/docs/9.6/view-pg-settings.html "PostgreSQL 9.6 - 53.25. pg_settings") / [9.5](https://www.postgresql.org/docs/9.5/view-pg-settings.html "PostgreSQL 9.5 - 53.25. pg_settings") / [9.4](https://www.postgresql.org/docs/9.4/view-pg-settings.html "PostgreSQL 9.4 - 53.25. pg_settings") / [9.3](https://www.postgresql.org/docs/9.3/view-pg-settings.html "PostgreSQL 9.3 - 53.25. pg_settings") / [9.2](https://www.postgresql.org/docs/9.2/view-pg-settings.html "PostgreSQL 9.2 - 53.25. pg_settings") / [9.1](https://www.postgresql.org/docs/9.1/view-pg-settings.html "PostgreSQL 9.1 - 53.25. pg_settings") / [9.0](https://www.postgresql.org/docs/9.0/view-pg-settings.html "PostgreSQL 9.0 - 53.25. pg_settings") / [8.4](https://www.postgresql.org/docs/8.4/view-pg-settings.html "PostgreSQL 8.4 - 53.25. pg_settings") / [8.3](https://www.postgresql.org/docs/8.3/view-pg-settings.html "PostgreSQL 8.3 - 53.25. pg_settings") / [8.2](https://www.postgresql.org/docs/8.2/view-pg-settings.html "PostgreSQL 8.2 - 53.25. pg_settings") / [8.1](https://www.postgresql.org/docs/8.1/view-pg-settings.html "PostgreSQL 8.1 - 53.25. pg_settings") / [8.0](https://www.postgresql.org/docs/8.0/view-pg-settings.html "PostgreSQL 8.0 - 53.25. pg_settings") / [7.4](https://www.postgresql.org/docs/7.4/view-pg-settings.html "PostgreSQL 7.4 - 53.25. pg_settings") | 53.25. `pg_settings` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-sequences.html "53.24. pg_sequences") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/view-pg-shadow.html "53.26. pg_shadow") | * * * 53.25. `pg_settings` [#](https://www.postgresql.org/docs/current/view-pg-settings.html#VIEW-PG-SETTINGS) --------------------------------------------------------------------------------------------------------- The view `pg_settings` provides access to run-time parameters of the server. It is essentially an alternative interface to the [`SHOW`](https://www.postgresql.org/docs/current/sql-show.html "SHOW") and [`SET`](https://www.postgresql.org/docs/current/sql-set.html "SET") commands. It also provides access to some facts about each parameter that are not directly available from [`SHOW`](https://www.postgresql.org/docs/current/sql-show.html "SHOW") , such as minimum and maximum values. **Table 53.25. `pg_settings` Columns** | Column Type

Description | | --- | | `name` `text`

Run-time configuration parameter name | | `setting` `text`

Current value of the parameter | | `unit` `text`

Implicit unit of the parameter | | `category` `text`

Logical group of the parameter | | `short_desc` `text`

A brief description of the parameter | | `extra_desc` `text`

Additional, more detailed, description of the parameter | | `context` `text`

Context required to set the parameter's value (see below) | | `vartype` `text`

Parameter type (`bool`, `enum`, `integer`, `real`, or `string`) | | `source` `text`

Source of the current parameter value | | `min_val` `text`

Minimum allowed value of the parameter (null for non-numeric values) | | `max_val` `text`

Maximum allowed value of the parameter (null for non-numeric values) | | `enumvals` `text[]`

Allowed values of an enum parameter (null for non-enum values) | | `boot_val` `text`

Parameter value assumed at server startup if the parameter is not otherwise set | | `reset_val` `text`

Value that [`RESET`](https://www.postgresql.org/docs/current/sql-reset.html "RESET")
would reset the parameter to in the current session | | `sourcefile` `text`

Configuration file the current value was set in (null for values set from sources other than configuration files, or when examined by a user who neither is a superuser nor has privileges of `pg_read_all_settings`); helpful when using `include` directives in configuration files | | `sourceline` `int4`

Line number within the configuration file the current value was set at (null for values set from sources other than configuration files, or when examined by a user who neither is a superuser nor has privileges of `pg_read_all_settings`). | | `pending_restart` `bool`

`true` if the value has been changed in the configuration file but needs a restart; or `false` otherwise. | There are several possible values of `context`. In order of decreasing difficulty of changing the setting, they are: `internal` These settings cannot be changed directly; they reflect internally determined values. Some of them may be adjustable by rebuilding the server with different configuration options, or by changing options supplied to initdb. `postmaster` These settings can only be applied when the server starts, so any change requires restarting the server. Values for these settings are typically stored in the `postgresql.conf` file, or passed on the command line when starting the server. Of course, settings with any of the lower `context` types can also be set at server start time. `sighup` Changes to these settings can be made in `postgresql.conf` without restarting the server. Send a SIGHUP signal to the postmaster to cause it to re-read `postgresql.conf` and apply the changes. The postmaster will also forward the SIGHUP signal to its child processes so that they all pick up the new value. `superuser-backend` Changes to these settings can be made in `postgresql.conf` without restarting the server. They can also be set for a particular session in the connection request packet (for example, via libpq's `PGOPTIONS` environment variable), but only if the connecting user is a superuser or has been granted the appropriate `SET` privilege. However, these settings never change in a session after it is started. If you change them in `postgresql.conf`, send a SIGHUP signal to the postmaster to cause it to re-read `postgresql.conf`. The new values will only affect subsequently-launched sessions. `backend` Changes to these settings can be made in `postgresql.conf` without restarting the server. They can also be set for a particular session in the connection request packet (for example, via libpq's `PGOPTIONS` environment variable); any user can make such a change for their session. However, these settings never change in a session after it is started. If you change them in `postgresql.conf`, send a SIGHUP signal to the postmaster to cause it to re-read `postgresql.conf`. The new values will only affect subsequently-launched sessions. `superuser` These settings can be set from `postgresql.conf`, or within a session via the `SET` command; but only superusers and users with the appropriate `SET` privilege can change them via `SET`. Changes in `postgresql.conf` will affect existing sessions only if no session-local value has been established with `SET`. `user` These settings can be set from `postgresql.conf`, or within a session via the `SET` command. Any user is allowed to change their session-local value. Changes in `postgresql.conf` will affect existing sessions only if no session-local value has been established with `SET`. See [Section 19.1](https://www.postgresql.org/docs/current/config-setting.html "19.1. Setting Parameters") for more information about the various ways to change these parameters. This view cannot be inserted into or deleted from, but it can be updated. An `UPDATE` applied to a row of `pg_settings` is equivalent to executing the `SET` command on that named parameter. The change only affects the value used by the current session. If an `UPDATE` is issued within a transaction that is later aborted, the effects of the `UPDATE` command disappear when the transaction is rolled back. Once the surrounding transaction is committed, the effects will persist until the end of the session, unless overridden by another `UPDATE` or `SET`. This view does not display [customized options](https://www.postgresql.org/docs/current/runtime-config-custom.html "19.16. Customized Options") unless the extension module that defines them has been loaded by the backend process executing the query (e.g., via a mention in [shared\_preload\_libraries](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES) , a call to a C function in the extension, or the [`LOAD`](https://www.postgresql.org/docs/current/sql-load.html "LOAD") command). For example, since [archive modules](https://www.postgresql.org/docs/current/archive-modules.html "Chapter 49. Archive Modules") are normally loaded only by the archiver process not regular sessions, this view will not display any customized options defined by such modules unless special action is taken to load them into the backend process executing the query. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-sequences.html "53.24. pg_sequences") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/current/view-pg-shadow.html "53.26. pg_shadow") | | 53.24. `pg_sequences` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 53.26. `pg_shadow` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-settings.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 19.8. Error Reporting and Logging November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/runtime-config-logging.html "PostgreSQL 18 - 19.8. Error Reporting and Logging") ([18](https://www.postgresql.org/docs/18/runtime-config-logging.html "PostgreSQL 18 - 19.8. Error Reporting and Logging") ) / [17](https://www.postgresql.org/docs/17/runtime-config-logging.html "PostgreSQL 17 - 19.8. Error Reporting and Logging") / [16](https://www.postgresql.org/docs/16/runtime-config-logging.html "PostgreSQL 16 - 19.8. Error Reporting and Logging") / [15](https://www.postgresql.org/docs/15/runtime-config-logging.html "PostgreSQL 15 - 19.8. Error Reporting and Logging") / [14](https://www.postgresql.org/docs/14/runtime-config-logging.html "PostgreSQL 14 - 19.8. Error Reporting and Logging") Development Versions: [devel](https://www.postgresql.org/docs/devel/runtime-config-logging.html "PostgreSQL devel - 19.8. Error Reporting and Logging") Unsupported versions: [13](https://www.postgresql.org/docs/13/runtime-config-logging.html "PostgreSQL 13 - 19.8. Error Reporting and Logging") / [12](https://www.postgresql.org/docs/12/runtime-config-logging.html "PostgreSQL 12 - 19.8. Error Reporting and Logging") / [11](https://www.postgresql.org/docs/11/runtime-config-logging.html "PostgreSQL 11 - 19.8. Error Reporting and Logging") / [10](https://www.postgresql.org/docs/10/runtime-config-logging.html "PostgreSQL 10 - 19.8. Error Reporting and Logging") / [9.6](https://www.postgresql.org/docs/9.6/runtime-config-logging.html "PostgreSQL 9.6 - 19.8. Error Reporting and Logging") / [9.5](https://www.postgresql.org/docs/9.5/runtime-config-logging.html "PostgreSQL 9.5 - 19.8. Error Reporting and Logging") / [9.4](https://www.postgresql.org/docs/9.4/runtime-config-logging.html "PostgreSQL 9.4 - 19.8. Error Reporting and Logging") / [9.3](https://www.postgresql.org/docs/9.3/runtime-config-logging.html "PostgreSQL 9.3 - 19.8. Error Reporting and Logging") / [9.2](https://www.postgresql.org/docs/9.2/runtime-config-logging.html "PostgreSQL 9.2 - 19.8. Error Reporting and Logging") / [9.1](https://www.postgresql.org/docs/9.1/runtime-config-logging.html "PostgreSQL 9.1 - 19.8. Error Reporting and Logging") / [9.0](https://www.postgresql.org/docs/9.0/runtime-config-logging.html "PostgreSQL 9.0 - 19.8. Error Reporting and Logging") / [8.4](https://www.postgresql.org/docs/8.4/runtime-config-logging.html "PostgreSQL 8.4 - 19.8. Error Reporting and Logging") / [8.3](https://www.postgresql.org/docs/8.3/runtime-config-logging.html "PostgreSQL 8.3 - 19.8. Error Reporting and Logging") / [8.2](https://www.postgresql.org/docs/8.2/runtime-config-logging.html "PostgreSQL 8.2 - 19.8. Error Reporting and Logging") / [8.1](https://www.postgresql.org/docs/8.1/runtime-config-logging.html "PostgreSQL 8.1 - 19.8. Error Reporting and Logging") | 19.8. Error Reporting and Logging | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/runtime-config-query.html "19.7. Query Planning") | [Up](https://www.postgresql.org/docs/18/runtime-config.html "Chapter 19. Server Configuration") | Chapter 19. Server Configuration | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/runtime-config-statistics.html "19.9. Run-time Statistics") | * * * 19.8. Error Reporting and Logging [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING) ----------------------------------------------------------------------------------------------------------------------------- [19.8.1. Where to Log](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHERE) [19.8.2. When to Log](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHEN) [19.8.3. What to Log](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHAT) [19.8.4. Using CSV-Format Log Output](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-CSVLOG) [19.8.5. Using JSON-Format Log Output](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-JSONLOG) [19.8.6. Process Title](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-PROC-TITLE) ### 19.8.1. Where to Log [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHERE) `log_destination` (`string`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-DESTINATION) PostgreSQL supports several methods for logging server messages, including stderr, csvlog, jsonlog, and syslog. On Windows, eventlog is also supported. Set this parameter to a list of desired log destinations separated by commas. The default is to log to stderr only. This parameter can only be set in the `postgresql.conf` file or on the server command line. If csvlog is included in `log_destination`, log entries are output in “comma-separated value” (CSV) format, which is convenient for loading logs into programs. See [Section 19.8.4](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-CSVLOG "19.8.4. Using CSV-Format Log Output") for details. [logging\_collector](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOGGING-COLLECTOR) must be enabled to generate CSV-format log output. If jsonlog is included in `log_destination`, log entries are output in JSON format, which is convenient for loading logs into programs. See [Section 19.8.5](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-JSONLOG "19.8.5. Using JSON-Format Log Output") for details. [logging\_collector](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOGGING-COLLECTOR) must be enabled to generate JSON-format log output. When either stderr, csvlog or jsonlog are included, the file `current_logfiles` is created to record the location of the log file(s) currently in use by the logging collector and the associated logging destination. This provides a convenient way to find the logs currently in use by the instance. Here is an example of this file's content: stderr log/postgresql.log csvlog log/postgresql.csv jsonlog log/postgresql.json `current_logfiles` is recreated when a new log file is created as an effect of rotation, and when `log_destination` is reloaded. It is removed when none of stderr, csvlog or jsonlog are included in `log_destination`, and when the logging collector is disabled. ### Note On most Unix systems, you will need to alter the configuration of your system's syslog daemon in order to make use of the syslog option for `log_destination`. PostgreSQL can log to syslog facilities `LOCAL0` through `LOCAL7` (see [syslog\_facility](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-SYSLOG-FACILITY) ), but the default syslog configuration on most platforms will discard all such messages. You will need to add something like: local0.\* /var/log/postgresql to the syslog daemon's configuration file to make it work. On Windows, when you use the `eventlog` option for `log_destination`, you should register an event source and its library with the operating system so that the Windows Event Viewer can display event log messages cleanly. See [Section 18.12](https://www.postgresql.org/docs/18/event-log-registration.html "18.12. Registering Event Log on Windows") for details. `logging_collector` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOGGING-COLLECTOR) This parameter enables the _logging collector_, which is a background process that captures log messages sent to stderr and redirects them into log files. This approach is often more useful than logging to syslog, since some types of messages might not appear in syslog output. (One common example is dynamic-linker failure messages; another is error messages produced by scripts such as `archive_command`.) This parameter can only be set at server start. ### Note It is possible to log to stderr without using the logging collector; the log messages will just go to wherever the server's stderr is directed. However, that method is only suitable for low log volumes, since it provides no convenient way to rotate log files. Also, on some platforms not using the logging collector can result in lost or garbled log output, because multiple processes writing concurrently to the same log file can overwrite each other's output. ### Note The logging collector is designed to never lose messages. This means that in case of extremely high load, server processes could be blocked while trying to send additional log messages when the collector has fallen behind. In contrast, syslog prefers to drop messages if it cannot write them, which means it may fail to log some messages in such cases but it will not block the rest of the system. `log_directory` (`string`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-DIRECTORY) When `logging_collector` is enabled, this parameter determines the directory in which log files will be created. It can be specified as an absolute path, or relative to the cluster data directory. This parameter can only be set in the `postgresql.conf` file or on the server command line. The default is `log`. `log_filename` (`string`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-FILENAME) When `logging_collector` is enabled, this parameter sets the file names of the created log files. The value is treated as a `strftime` pattern, so `%`\-escapes can be used to specify time-varying file names. (Note that if there are any time-zone-dependent `%`\-escapes, the computation is done in the zone specified by [log\_timezone](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-TIMEZONE) .) The supported `%`\-escapes are similar to those listed in the Open Group's [strftime](https://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html) specification. Note that the system's `strftime` is not used directly, so platform-specific (nonstandard) extensions do not work. The default is `postgresql-%Y-%m-%d_%H%M%S.log`. If you specify a file name without escapes, you should plan to use a log rotation utility to avoid eventually filling the entire disk. In releases prior to 8.4, if no `%` escapes were present, PostgreSQL would append the epoch of the new log file's creation time, but this is no longer the case. If CSV-format output is enabled in `log_destination`, `.csv` will be appended to the timestamped log file name to create the file name for CSV-format output. (If `log_filename` ends in `.log`, the suffix is replaced instead.) If JSON-format output is enabled in `log_destination`, `.json` will be appended to the timestamped log file name to create the file name for JSON-format output. (If `log_filename` ends in `.log`, the suffix is replaced instead.) This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_file_mode` (`integer`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-FILE-MODE) On Unix systems this parameter sets the permissions for log files when `logging_collector` is enabled. (On Microsoft Windows this parameter is ignored.) The parameter value is expected to be a numeric mode specified in the format accepted by the `chmod` and `umask` system calls. (To use the customary octal format the number must start with a `0` (zero).) The default permissions are `0600`, meaning only the server owner can read or write the log files. The other commonly useful setting is `0640`, allowing members of the owner's group to read the files. Note however that to make use of such a setting, you'll need to alter [log\_directory](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-DIRECTORY) to store the files somewhere outside the cluster data directory. In any case, it's unwise to make the log files world-readable, since they might contain sensitive data. This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_rotation_age` (`integer`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-ROTATION-AGE) When `logging_collector` is enabled, this parameter determines the maximum amount of time to use an individual log file, after which a new log file will be created. If this value is specified without units, it is taken as minutes. The default is 24 hours. Set to zero to disable time-based creation of new log files. This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_rotation_size` (`integer`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-ROTATION-SIZE) When `logging_collector` is enabled, this parameter determines the maximum size of an individual log file. After this amount of data has been emitted into a log file, a new log file will be created. If this value is specified without units, it is taken as kilobytes. The default is 10 megabytes. Set to zero to disable size-based creation of new log files. This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_truncate_on_rotation` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-TRUNCATE-ON-ROTATION) When `logging_collector` is enabled, this parameter will cause PostgreSQL to truncate (overwrite), rather than append to, any existing log file of the same name. However, truncation will occur only when a new file is being opened due to time-based rotation, not during server startup or size-based rotation. When off, pre-existing files will be appended to in all cases. For example, using this setting in combination with a `log_filename` like `postgresql-%H.log` would result in generating twenty-four hourly log files and then cyclically overwriting them. This parameter can only be set in the `postgresql.conf` file or on the server command line. Example: To keep 7 days of logs, one log file per day named `server_log.Mon`, `server_log.Tue`, etc., and automatically overwrite last week's log with this week's log, set `log_filename` to `server_log.%a`, `log_truncate_on_rotation` to `on`, and `log_rotation_age` to `1440`. Example: To keep 24 hours of logs, one log file per hour, but also rotate sooner if the log file size exceeds 1GB, set `log_filename` to `server_log.%H%M`, `log_truncate_on_rotation` to `on`, `log_rotation_age` to `60`, and `log_rotation_size` to `1000000`. Including `%M` in `log_filename` allows any size-driven rotations that might occur to select a file name different from the hour's initial file name. `syslog_facility` (`enum`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-SYSLOG-FACILITY) When logging to syslog is enabled, this parameter determines the syslog “facility” to be used. You can choose from `LOCAL0`, `LOCAL1`, `LOCAL2`, `LOCAL3`, `LOCAL4`, `LOCAL5`, `LOCAL6`, `LOCAL7`; the default is `LOCAL0`. See also the documentation of your system's syslog daemon. This parameter can only be set in the `postgresql.conf` file or on the server command line. `syslog_ident` (`string`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-SYSLOG-IDENT) When logging to syslog is enabled, this parameter determines the program name used to identify PostgreSQL messages in syslog logs. The default is `postgres`. This parameter can only be set in the `postgresql.conf` file or on the server command line. `syslog_sequence_numbers` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-SYSLOG-SEQUENCE-NUMBERS) When logging to syslog and this is on (the default), then each message will be prefixed by an increasing sequence number (such as `[2]`). This circumvents the “\--- last message repeated N times ---” suppression that many syslog implementations perform by default. In more modern syslog implementations, repeated message suppression can be configured (for example, `$RepeatedMsgReduction` in rsyslog), so this might not be necessary. Also, you could turn this off if you actually want to suppress repeated messages. This parameter can only be set in the `postgresql.conf` file or on the server command line. `syslog_split_messages` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-SYSLOG-SPLIT-MESSAGES) When logging to syslog is enabled, this parameter determines how messages are delivered to syslog. When on (the default), messages are split by lines, and long lines are split so that they will fit into 1024 bytes, which is a typical size limit for traditional syslog implementations. When off, PostgreSQL server log messages are delivered to the syslog service as is, and it is up to the syslog service to cope with the potentially bulky messages. If syslog is ultimately logging to a text file, then the effect will be the same either way, and it is best to leave the setting on, since most syslog implementations either cannot handle large messages or would need to be specially configured to handle them. But if syslog is ultimately writing into some other medium, it might be necessary or more useful to keep messages logically together. This parameter can only be set in the `postgresql.conf` file or on the server command line. `event_source` (`string`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-EVENT-SOURCE) When logging to event log is enabled, this parameter determines the program name used to identify PostgreSQL messages in the log. The default is `PostgreSQL`. This parameter can only be set at server start. ### 19.8.2. When to Log [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHEN) `log_min_messages` (`enum`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-MIN-MESSAGES) Controls which [message levels](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-SEVERITY-LEVELS "Table 19.2. Message Severity Levels") are written to the server log. Valid values are `DEBUG5`, `DEBUG4`, `DEBUG3`, `DEBUG2`, `DEBUG1`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, `LOG`, `FATAL`, and `PANIC`. Each level includes all the levels that follow it. The later the level, the fewer messages are sent to the log. The default is `WARNING`. Note that `LOG` has a different rank here than in [client\_min\_messages](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-CLIENT-MIN-MESSAGES) . Only superusers and users with the appropriate `SET` privilege can change this setting. `log_min_error_statement` (`enum`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-MIN-ERROR-STATEMENT) Controls which SQL statements that cause an error condition are recorded in the server log. The current SQL statement is included in the log entry for any message of the specified [severity](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-SEVERITY-LEVELS "Table 19.2. Message Severity Levels") or higher. Valid values are `DEBUG5`, `DEBUG4`, `DEBUG3`, `DEBUG2`, `DEBUG1`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, `LOG`, `FATAL`, and `PANIC`. The default is `ERROR`, which means statements causing errors, log messages, fatal errors, or panics will be logged. To effectively turn off logging of failing statements, set this parameter to `PANIC`. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_min_duration_statement` (`integer`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-MIN-DURATION-STATEMENT) Causes the duration of each completed statement to be logged if the statement ran for at least the specified amount of time. For example, if you set it to `250ms` then all SQL statements that run 250ms or longer will be logged. Enabling this parameter can be helpful in tracking down unoptimized queries in your applications. If this value is specified without units, it is taken as milliseconds. Setting this to zero prints all statement durations. `-1` (the default) disables logging statement durations. Only superusers and users with the appropriate `SET` privilege can change this setting. This overrides [log\_min\_duration\_sample](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-MIN-DURATION-SAMPLE) , meaning that queries with duration exceeding this setting are not subject to sampling and are always logged. For clients using extended query protocol, durations of the Parse, Bind, and Execute steps are logged independently. ### Note When using this option together with [log\_statement](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-STATEMENT) , the text of statements that are logged because of `log_statement` will not be repeated in the duration log message. If you are not using syslog, it is recommended that you log the PID or session ID using [log\_line\_prefix](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-LINE-PREFIX) so that you can link the statement message to the later duration message using the process ID or session ID. `log_min_duration_sample` (`integer`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-MIN-DURATION-SAMPLE) Allows sampling the duration of completed statements that ran for at least the specified amount of time. This produces the same kind of log entries as [log\_min\_duration\_statement](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-MIN-DURATION-STATEMENT) , but only for a subset of the executed statements, with sample rate controlled by [log\_statement\_sample\_rate](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-STATEMENT-SAMPLE-RATE) . For example, if you set it to `100ms` then all SQL statements that run 100ms or longer will be considered for sampling. Enabling this parameter can be helpful when the traffic is too high to log all queries. If this value is specified without units, it is taken as milliseconds. Setting this to zero samples all statement durations. `-1` (the default) disables sampling statement durations. Only superusers and users with the appropriate `SET` privilege can change this setting. This setting has lower priority than `log_min_duration_statement`, meaning that statements with durations exceeding `log_min_duration_statement` are not subject to sampling and are always logged. Other notes for `log_min_duration_statement` apply also to this setting. `log_statement_sample_rate` (`floating point`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-STATEMENT-SAMPLE-RATE) Determines the fraction of statements with duration exceeding [log\_min\_duration\_sample](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-MIN-DURATION-SAMPLE) that will be logged. Sampling is stochastic, for example `0.5` means there is statistically one chance in two that any given statement will be logged. The default is `1.0`, meaning to log all sampled statements. Setting this to zero disables sampled statement-duration logging, the same as setting `log_min_duration_sample` to `-1`. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_transaction_sample_rate` (`floating point`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-TRANSACTION-SAMPLE-RATE) Sets the fraction of transactions whose statements are all logged, in addition to statements logged for other reasons. It applies to each new transaction regardless of its statements' durations. Sampling is stochastic, for example `0.1` means there is statistically one chance in ten that any given transaction will be logged. `log_transaction_sample_rate` can be helpful to construct a sample of transactions. The default is `0`, meaning not to log statements from any additional transactions. Setting this to `1` logs all statements of all transactions. Only superusers and users with the appropriate `SET` privilege can change this setting. ### Note Like all statement-logging options, this option can add significant overhead. `log_startup_progress_interval` (`integer`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-STARTUP-PROGRESS-INTERVAL) Sets the amount of time after which the startup process will log a message about a long-running operation that is still in progress, as well as the interval between further progress messages for that operation. The default is 10 seconds. A setting of `0` disables the feature. If this value is specified without units, it is taken as milliseconds. This setting is applied separately to each operation. This parameter can only be set in the `postgresql.conf` file or on the server command line. For example, if syncing the data directory takes 25 seconds and thereafter resetting unlogged relations takes 8 seconds, and if this setting has the default value of 10 seconds, then a messages will be logged for syncing the data directory after it has been in progress for 10 seconds and again after it has been in progress for 20 seconds, but nothing will be logged for resetting unlogged relations. [Table 19.2](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-SEVERITY-LEVELS "Table 19.2. Message Severity Levels") explains the message severity levels used by PostgreSQL. If logging output is sent to syslog or Windows' eventlog, the severity levels are translated as shown in the table. **Table 19.2. Message Severity Levels** | Severity | Usage | syslog | eventlog | | --- | --- | --- | --- | | `DEBUG1 .. DEBUG5` | Provides successively-more-detailed information for use by developers. | `DEBUG` | `INFORMATION` | | `INFO` | Provides information implicitly requested by the user, e.g., output from `VACUUM VERBOSE`. | `INFO` | `INFORMATION` | | `NOTICE` | Provides information that might be helpful to users, e.g., notice of truncation of long identifiers. | `NOTICE` | `INFORMATION` | | `WARNING` | Provides warnings of likely problems, e.g., `COMMIT` outside a transaction block. | `NOTICE` | `WARNING` | | `ERROR` | Reports an error that caused the current command to abort. | `WARNING` | `ERROR` | | `LOG` | Reports information of interest to administrators, e.g., checkpoint activity. | `INFO` | `INFORMATION` | | `FATAL` | Reports an error that caused the current session to abort. | `ERR` | `ERROR` | | `PANIC` | Reports an error that caused all database sessions to abort. | `CRIT` | `ERROR` | ### 19.8.3. What to Log [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHAT) ### Note What you choose to log can have security implications; see [Section 24.3](https://www.postgresql.org/docs/18/logfile-maintenance.html "24.3. Log File Maintenance") . `application_name` (`string`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-APPLICATION-NAME) The `application_name` can be any string of less than `NAMEDATALEN` characters (64 characters in a standard build). It is typically set by an application upon connection to the server. The name will be displayed in the `pg_stat_activity` view and included in CSV log entries. It can also be included in regular log entries via the [log\_line\_prefix](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-LINE-PREFIX) parameter. Only printable ASCII characters may be used in the `application_name` value. Other characters are replaced with [C-style hexadecimal escapes](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE "4.1.2.2. String Constants with C-Style Escapes") . `debug_print_parse` (`boolean`) `debug_print_rewritten` (`boolean`) `debug_print_plan` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-DEBUG-PRINT-PARSE) These parameters enable various debugging output to be emitted. When set, they print the resulting parse tree, the query rewriter output, or the execution plan for each executed query. These messages are emitted at `LOG` message level, so by default they will appear in the server log but will not be sent to the client. You can change that by adjusting [client\_min\_messages](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-CLIENT-MIN-MESSAGES) and/or [log\_min\_messages](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-MIN-MESSAGES) . These parameters are off by default. `debug_pretty_print` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-DEBUG-PRETTY-PRINT) When set, `debug_pretty_print` indents the messages produced by `debug_print_parse`, `debug_print_rewritten`, or `debug_print_plan`. This results in more readable but much longer output than the “compact” format used when it is off. It is on by default. `log_autovacuum_min_duration` (`integer`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-AUTOVACUUM-MIN-DURATION) Causes each action executed by autovacuum to be logged if it ran for at least the specified amount of time. Setting this to zero logs all autovacuum actions. `-1` disables logging autovacuum actions. If this value is specified without units, it is taken as milliseconds. For example, if you set this to `250ms` then all automatic vacuums and analyzes that run 250ms or longer will be logged. In addition, when this parameter is set to any value other than `-1`, a message will be logged if an autovacuum action is skipped due to a conflicting lock or a concurrently dropped relation. The default is `10min`. Enabling this parameter can be helpful in tracking autovacuum activity. This parameter can only be set in the `postgresql.conf` file or on the server command line; but the setting can be overridden for individual tables by changing table storage parameters. `log_checkpoints` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-CHECKPOINTS) Causes checkpoints and restartpoints to be logged in the server log. Some statistics are included in the log messages, including the number of buffers written and the time spent writing them. This parameter can only be set in the `postgresql.conf` file or on the server command line. The default is on. `log_connections` (`string`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-CONNECTIONS) Causes aspects of each connection to the server to be logged. The default is the empty string, `''`, which disables all connection logging. The following options may be specified alone or in a comma-separated list: **Table 19.3. Log Connection Options** | Name | Description | | --- | --- | | `receipt` | Logs receipt of a connection. | | `authentication` | Logs the original identity used by an authentication method to identify a user. In most cases, the identity string matches the PostgreSQL username, but some third-party authentication methods may alter the original user identifier before the server stores it. Failed authentication is always logged regardless of the value of this setting. | | `authorization` | Logs successful completion of authorization. At this point the connection has been established but the backend is not yet fully set up. The log message includes the authorized username as well as the database name and application name, if applicable. | | `setup_durations` | Logs the time spent establishing the connection and setting up the backend until the connection is ready to execute its first query. The log message includes three durations: the total setup duration (starting from the postmaster accepting the incoming connection and ending when the connection is ready for query), the time it took to fork the new backend, and the time it took to authenticate the user. | | `all` | A convenience alias equivalent to specifying all options. If `all` is specified in a list of other options, all connection aspects will be logged. | Disconnection logging is separately controlled by [log\_disconnections](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-DISCONNECTIONS) . For the purposes of backwards compatibility, `on`, `off`, `true`, `false`, `yes`, `no`, `1`, and `0` are still supported. The positive values are equivalent to specifying the `receipt`, `authentication`, and `authorization` options. Only superusers and users with the appropriate `SET` privilege can change this parameter at session start, and it cannot be changed at all within a session. ### Note Some client programs, like psql, attempt to connect twice while determining if a password is required, so duplicate “connection received” messages do not necessarily indicate a problem. `log_disconnections` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-DISCONNECTIONS) Causes session terminations to be logged. The log output provides information similar to `log_connections`, plus the duration of the session. Only superusers and users with the appropriate `SET` privilege can change this parameter at session start, and it cannot be changed at all within a session. The default is `off`. `log_duration` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-DURATION) Causes the duration of every completed statement to be logged. The default is `off`. Only superusers and users with the appropriate `SET` privilege can change this setting. For clients using extended query protocol, durations of the Parse, Bind, and Execute steps are logged independently. ### Note The difference between enabling `log_duration` and setting [log\_min\_duration\_statement](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-MIN-DURATION-STATEMENT) to zero is that exceeding `log_min_duration_statement` forces the text of the query to be logged, but this option doesn't. Thus, if `log_duration` is `on` and `log_min_duration_statement` has a positive value, all durations are logged but the query text is included only for statements exceeding the threshold. This behavior can be useful for gathering statistics in high-load installations. `log_error_verbosity` (`enum`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-ERROR-VERBOSITY) Controls the amount of detail written in the server log for each message that is logged. Valid values are `TERSE`, `DEFAULT`, and `VERBOSE`, each adding more fields to displayed messages. `TERSE` excludes the logging of `DETAIL`, `HINT`, `QUERY`, and `CONTEXT` error information. `VERBOSE` output includes the `SQLSTATE` error code (see also [Appendix A](https://www.postgresql.org/docs/18/errcodes-appendix.html "Appendix A. PostgreSQL Error Codes") ) and the source code file name, function name, and line number that generated the error. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_hostname` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-HOSTNAME) By default, connection log messages only show the IP address of the connecting host. Turning this parameter on causes logging of the host name as well. Note that depending on your host name resolution setup this might impose a non-negligible performance penalty. This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_line_prefix` (`string`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-LINE-PREFIX) This is a `printf`\-style string that is output at the beginning of each log line. `%` characters begin “escape sequences” that are replaced with status information as outlined below. Unrecognized escapes are ignored. Other characters are copied straight to the log line. Some escapes are only recognized by session processes, and will be treated as empty by background processes such as the main server process. Status information may be aligned either left or right by specifying a numeric literal after the % and before the option. A negative value will cause the status information to be padded on the right with spaces to give it a minimum width, whereas a positive value will pad on the left. Padding can be useful to aid human readability in log files. This parameter can only be set in the `postgresql.conf` file or on the server command line. The default is `'%m [%p] '` which logs a time stamp and the process ID. | Escape | Effect | Session only | | --- | --- | --- | | `%a` | Application name | yes | | `%u` | User name | yes | | `%d` | Database name | yes | | `%r` | Remote host name or IP address, and remote port | yes | | `%h` | Remote host name or IP address | yes | | `%L` | Local address (the IP address on the server that the client connected to) | yes | | `%b` | Backend type | no | | `%p` | Process ID | no | | `%P` | Process ID of the parallel group leader, if this process is a parallel query worker | no | | `%t` | Time stamp without milliseconds | no | | `%m` | Time stamp with milliseconds | no | | `%n` | Time stamp with milliseconds (as a Unix epoch) | no | | `%i` | Command tag: type of session's current command | yes | | `%e` | SQLSTATE error code | no | | `%c` | Session ID: see below | no | | `%l` | Number of the log line for each session or process, starting at 1 | no | | `%s` | Process start time stamp | no | | `%v` | Virtual transaction ID (procNumber/localXID); see [Section 67.1](https://www.postgresql.org/docs/18/transaction-id.html "67.1. Transactions and Identifiers") | no | | `%x` | Transaction ID (0 if none is assigned); see [Section 67.1](https://www.postgresql.org/docs/18/transaction-id.html "67.1. Transactions and Identifiers") | no | | `%q` | Produces no output, but tells non-session processes to stop at this point in the string; ignored by session processes | no | | `%Q` | Query identifier of the current query. Query identifiers are not computed by default, so this field will be zero unless [compute\_query\_id](https://www.postgresql.org/docs/18/runtime-config-statistics.html#GUC-COMPUTE-QUERY-ID)
parameter is enabled or a third-party module that computes query identifiers is configured. | yes | | `%%` | Literal `%` | no | The backend type corresponds to the column `backend_type` in the view [`pg_stat_activity`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW "27.2.3. pg_stat_activity") , but additional types can appear in the log that don't show in that view. The `%c` escape prints a quasi-unique session identifier, consisting of two 4-byte hexadecimal numbers (without leading zeros) separated by a dot. The numbers are the process start time and the process ID, so `%c` can also be used as a space saving way of printing those items. For example, to generate the session identifier from `pg_stat_activity`, use this query: SELECT to\_hex(trunc(EXTRACT(EPOCH FROM backend\_start))::integer) || '.' || to\_hex(pid) FROM pg\_stat\_activity; ### Tip If you set a nonempty value for `log_line_prefix`, you should usually make its last character be a space, to provide visual separation from the rest of the log line. A punctuation character can be used too. ### Tip Syslog produces its own time stamp and process ID information, so you probably do not want to include those escapes if you are logging to syslog. ### Tip The `%q` escape is useful when including information that is only available in session (backend) context like user or database name. For example: log\_line\_prefix = '%m \[%p\] %q%u@%d/%a ' ### Note The `%Q` escape always reports a zero identifier for lines output by [log\_statement](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-STATEMENT) because `log_statement` generates output before an identifier can be calculated, including invalid statements for which an identifier cannot be calculated. `log_lock_waits` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-LOCK-WAITS) Controls whether a log message is produced when a session waits longer than [deadlock\_timeout](https://www.postgresql.org/docs/18/runtime-config-locks.html#GUC-DEADLOCK-TIMEOUT) to acquire a lock. This is useful in determining if lock waits are causing poor performance. The default is `off`. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_lock_failures` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-LOCK-FAILURES) Controls whether a detailed log message is produced when a lock acquisition fails. This is useful for analyzing the causes of lock failures. Currently, only lock failures due to `SELECT NOWAIT` is supported. The default is `off`. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_recovery_conflict_waits` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-RECOVERY-CONFLICT-WAITS) Controls whether a log message is produced when the startup process waits longer than `deadlock_timeout` for recovery conflicts. This is useful in determining if recovery conflicts prevent the recovery from applying WAL. The default is `off`. This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_parameter_max_length` (`integer`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-PARAMETER-MAX-LENGTH) If greater than zero, each bind parameter value logged with a non-error statement-logging message is trimmed to this many bytes. Zero disables logging of bind parameters for non-error statement logs. `-1` (the default) allows bind parameters to be logged in full. If this value is specified without units, it is taken as bytes. Only superusers and users with the appropriate `SET` privilege can change this setting. This setting only affects log messages printed as a result of [log\_statement](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-STATEMENT) , [log\_duration](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-DURATION) , and related settings. Non-zero values of this setting add some overhead, particularly if parameters are sent in binary form, since then conversion to text is required. `log_parameter_max_length_on_error` (`integer`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-PARAMETER-MAX-LENGTH-ON-ERROR) If greater than zero, each bind parameter value reported in error messages is trimmed to this many bytes. Zero (the default) disables including bind parameters in error messages. `-1` allows bind parameters to be printed in full. If this value is specified without units, it is taken as bytes. Non-zero values of this setting add overhead, as PostgreSQL will need to store textual representations of parameter values in memory at the start of each statement, whether or not an error eventually occurs. The overhead is greater when bind parameters are sent in binary form than when they are sent as text, since the former case requires data conversion while the latter only requires copying the string. `log_statement` (`enum`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-STATEMENT) Controls which SQL statements are logged. Valid values are `none` (off), `ddl`, `mod`, and `all` (all statements). `ddl` logs all data definition statements, such as `CREATE`, `ALTER`, and `DROP` statements. `mod` logs all `ddl` statements, plus data-modifying statements such as `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`, and `COPY FROM`. `PREPARE`, `EXECUTE`, and `EXPLAIN ANALYZE` statements are also logged if their contained command is of an appropriate type. For clients using extended query protocol, logging occurs when an Execute message is received, and values of the Bind parameters are included (with any embedded single-quote marks doubled). The default is `none`. Only superusers and users with the appropriate `SET` privilege can change this setting. ### Note Statements that contain simple syntax errors are not logged even by the `log_statement` = `all` setting, because the log message is emitted only after basic parsing has been done to determine the statement type. In the case of extended query protocol, this setting likewise does not log statements that fail before the Execute phase (i.e., during parse analysis or planning). Set `log_min_error_statement` to `ERROR` (or lower) to log such statements. Logged statements might reveal sensitive data and even contain plaintext passwords. `log_replication_commands` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-REPLICATION-COMMANDS) Causes each replication command and `walsender` process's replication slot acquisition/release to be logged in the server log. See [Section 54.4](https://www.postgresql.org/docs/18/protocol-replication.html "54.4. Streaming Replication Protocol") for more information about replication command. The default value is `off`. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_temp_files` (`integer`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-TEMP-FILES) Controls logging of temporary file names and sizes. Temporary files can be created for sorts, hashes, and temporary query results. If enabled by this setting, a log entry is emitted for each temporary file, with the file size specified in bytes, when it is deleted. A value of zero logs all temporary file information, while positive values log only files whose size is greater than or equal to the specified amount of data. If this value is specified without units, it is taken as kilobytes. The default setting is -1, which disables such logging. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_timezone` (`string`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-LOG-TIMEZONE) Sets the time zone used for timestamps written in the server log. Unlike [TimeZone](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-TIMEZONE) , this value is cluster-wide, so that all sessions will report timestamps consistently. The built-in default is `GMT`, but that is typically overridden in `postgresql.conf`; initdb will install a setting there corresponding to its system environment. See [Section 8.5.3](https://www.postgresql.org/docs/18/datatype-datetime.html#DATATYPE-TIMEZONES "8.5.3. Time Zones") for more information. This parameter can only be set in the `postgresql.conf` file or on the server command line. ### 19.8.4. Using CSV-Format Log Output [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-CSVLOG) Including `csvlog` in the `log_destination` list provides a convenient way to import log files into a database table. This option emits log lines in comma-separated-values (CSV) format, with these columns: time stamp with milliseconds, user name, database name, process ID, client host:port number, session ID, per-session line number, command tag, session start time, virtual transaction ID, regular transaction ID, error severity, SQLSTATE code, error message, error message detail, hint, internal query that led to the error (if any), character count of the error position therein, error context, user query that led to the error (if any and enabled by `log_min_error_statement`), character count of the error position therein, location of the error in the PostgreSQL source code (if `log_error_verbosity` is set to `verbose`), application name, backend type, process ID of parallel group leader, and query id. Here is a sample table definition for storing CSV-format log output: CREATE TABLE postgres\_log ( log\_time timestamp(3) with time zone, user\_name text, database\_name text, process\_id integer, connection\_from text, session\_id text, session\_line\_num bigint, command\_tag text, session\_start\_time timestamp with time zone, virtual\_transaction\_id text, transaction\_id bigint, error\_severity text, sql\_state\_code text, message text, detail text, hint text, internal\_query text, internal\_query\_pos integer, context text, query text, query\_pos integer, location text, application\_name text, backend\_type text, leader\_pid integer, query\_id bigint, PRIMARY KEY (session\_id, session\_line\_num) ); To import a log file into this table, use the `COPY FROM` command: COPY postgres\_log FROM '/full/path/to/logfile.csv' WITH csv; It is also possible to access the file as a foreign table, using the supplied [file\_fdw](https://www.postgresql.org/docs/18/file-fdw.html "F.15. file_fdw — access data files in the server's file system") module. There are a few things you need to do to simplify importing CSV log files: 1. Set `log_filename` and `log_rotation_age` to provide a consistent, predictable naming scheme for your log files. This lets you predict what the file name will be and know when an individual log file is complete and therefore ready to be imported. 2. Set `log_rotation_size` to 0 to disable size-based log rotation, as it makes the log file name difficult to predict. 3. Set `log_truncate_on_rotation` to `on` so that old log data isn't mixed with the new in the same file. 4. The table definition above includes a primary key specification. This is useful to protect against accidentally importing the same information twice. The `COPY` command commits all of the data it imports at one time, so any error will cause the entire import to fail. If you import a partial log file and later import the file again when it is complete, the primary key violation will cause the import to fail. Wait until the log is complete and closed before importing. This procedure will also protect against accidentally importing a partial line that hasn't been completely written, which would also cause `COPY` to fail. ### 19.8.5. Using JSON-Format Log Output [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-JSONLOG) Including `jsonlog` in the `log_destination` list provides a convenient way to import log files into many different programs. This option emits log lines in JSON format. String fields with null values are excluded from output. Additional fields may be added in the future. User applications that process `jsonlog` output should ignore unknown fields. Each log line is serialized as a JSON object with the set of keys and their associated values shown in [Table 19.4](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-JSONLOG-KEYS-VALUES "Table 19.4. Keys and Values of JSON Log Entries") . **Table 19.4. Keys and Values of JSON Log Entries** | Key name | Type | Description | | --- | --- | --- | | `timestamp` | string | Time stamp with milliseconds | | `user` | string | User name | | `dbname` | string | Database name | | `pid` | number | Process ID | | `remote_host` | string | Client host | | `remote_port` | number | Client port | | `session_id` | string | Session ID | | `line_num` | number | Per-session line number | | `ps` | string | Current ps display | | `session_start` | string | Session start time | | `vxid` | string | Virtual transaction ID | | `txid` | string | Regular transaction ID | | `error_severity` | string | Error severity | | `state_code` | string | SQLSTATE code | | `message` | string | Error message | | `detail` | string | Error message detail | | `hint` | string | Error message hint | | `internal_query` | string | Internal query that led to the error | | `internal_position` | number | Cursor index into internal query | | `context` | string | Error context | | `statement` | string | Client-supplied query string | | `cursor_position` | number | Cursor index into query string | | `func_name` | string | Error location function name | | `file_name` | string | File name of error location | | `file_line_num` | number | File line number of the error location | | `application_name` | string | Client application name | | `backend_type` | string | Type of backend | | `leader_pid` | number | Process ID of leader for active parallel workers | | `query_id` | number | Query ID | ### 19.8.6. Process Title [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-PROC-TITLE) These settings control how process titles of server processes are modified. Process titles are typically viewed using programs like ps or, on Windows, Process Explorer. See [Section 27.1](https://www.postgresql.org/docs/18/monitoring-ps.html "27.1. Standard Unix Tools") for details. `cluster_name` (`string`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-CLUSTER-NAME) Sets a name that identifies this database cluster (instance) for various purposes. The cluster name appears in the process title for all server processes in this cluster. Moreover, it is the default application name for a standby connection (see [synchronous\_standby\_names](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-SYNCHRONOUS-STANDBY-NAMES) ). The name can be any string of less than `NAMEDATALEN` characters (64 characters in a standard build). Only printable ASCII characters may be used in the `cluster_name` value. Other characters are replaced with [C-style hexadecimal escapes](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE "4.1.2.2. String Constants with C-Style Escapes") . No name is shown if this parameter is set to the empty string `''` (which is the default). This parameter can only be set at server start. `update_process_title` (`boolean`) [#](https://www.postgresql.org/docs/18/runtime-config-logging.html#GUC-UPDATE-PROCESS-TITLE) Enables updating of the process title every time a new SQL command is received by the server. This setting defaults to `on` on most platforms, but it defaults to `off` on Windows due to that platform's larger overhead for updating the process title. Only superusers and users with the appropriate `SET` privilege can change this setting. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/runtime-config-query.html "19.7. Query Planning") | [Up](https://www.postgresql.org/docs/18/runtime-config.html "Chapter 19. Server Configuration") | [Next](https://www.postgresql.org/docs/18/runtime-config-statistics.html "19.9. Run-time Statistics") | | 19.7. Query Planning | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 19.9. Run-time Statistics | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/runtime-config-logging.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 52.34. pg_operator November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-operator.html "PostgreSQL 18 - 52.34. pg_operator") ([18](https://www.postgresql.org/docs/18/catalog-pg-operator.html "PostgreSQL 18 - 52.34. pg_operator") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-operator.html "PostgreSQL 17 - 52.34. pg_operator") / [16](https://www.postgresql.org/docs/16/catalog-pg-operator.html "PostgreSQL 16 - 52.34. pg_operator") / [15](https://www.postgresql.org/docs/15/catalog-pg-operator.html "PostgreSQL 15 - 52.34. pg_operator") / [14](https://www.postgresql.org/docs/14/catalog-pg-operator.html "PostgreSQL 14 - 52.34. pg_operator") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-operator.html "PostgreSQL devel - 52.34. pg_operator") Unsupported versions: [13](https://www.postgresql.org/docs/13/catalog-pg-operator.html "PostgreSQL 13 - 52.34. pg_operator") / [12](https://www.postgresql.org/docs/12/catalog-pg-operator.html "PostgreSQL 12 - 52.34. pg_operator") / [11](https://www.postgresql.org/docs/11/catalog-pg-operator.html "PostgreSQL 11 - 52.34. pg_operator") / [10](https://www.postgresql.org/docs/10/catalog-pg-operator.html "PostgreSQL 10 - 52.34. pg_operator") / [9.6](https://www.postgresql.org/docs/9.6/catalog-pg-operator.html "PostgreSQL 9.6 - 52.34. pg_operator") / [9.5](https://www.postgresql.org/docs/9.5/catalog-pg-operator.html "PostgreSQL 9.5 - 52.34. pg_operator") / [9.4](https://www.postgresql.org/docs/9.4/catalog-pg-operator.html "PostgreSQL 9.4 - 52.34. pg_operator") / [9.3](https://www.postgresql.org/docs/9.3/catalog-pg-operator.html "PostgreSQL 9.3 - 52.34. pg_operator") / [9.2](https://www.postgresql.org/docs/9.2/catalog-pg-operator.html "PostgreSQL 9.2 - 52.34. pg_operator") / [9.1](https://www.postgresql.org/docs/9.1/catalog-pg-operator.html "PostgreSQL 9.1 - 52.34. pg_operator") / [9.0](https://www.postgresql.org/docs/9.0/catalog-pg-operator.html "PostgreSQL 9.0 - 52.34. pg_operator") / [8.4](https://www.postgresql.org/docs/8.4/catalog-pg-operator.html "PostgreSQL 8.4 - 52.34. pg_operator") / [8.3](https://www.postgresql.org/docs/8.3/catalog-pg-operator.html "PostgreSQL 8.3 - 52.34. pg_operator") / [8.2](https://www.postgresql.org/docs/8.2/catalog-pg-operator.html "PostgreSQL 8.2 - 52.34. pg_operator") / [8.1](https://www.postgresql.org/docs/8.1/catalog-pg-operator.html "PostgreSQL 8.1 - 52.34. pg_operator") / [8.0](https://www.postgresql.org/docs/8.0/catalog-pg-operator.html "PostgreSQL 8.0 - 52.34. pg_operator") / [7.4](https://www.postgresql.org/docs/7.4/catalog-pg-operator.html "PostgreSQL 7.4 - 52.34. pg_operator") / [7.3](https://www.postgresql.org/docs/7.3/catalog-pg-operator.html "PostgreSQL 7.3 - 52.34. pg_operator") / [7.2](https://www.postgresql.org/docs/7.2/catalog-pg-operator.html "PostgreSQL 7.2 - 52.34. pg_operator") / [7.1](https://www.postgresql.org/docs/7.1/catalog-pg-operator.html "PostgreSQL 7.1 - 52.34. pg_operator") | 52.34. `pg_operator` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-opclass.html "52.33. pg_opclass") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/catalog-pg-opfamily.html "52.35. pg_opfamily") | * * * 52.34. `pg_operator` [#](https://www.postgresql.org/docs/current/catalog-pg-operator.html#CATALOG-PG-OPERATOR) --------------------------------------------------------------------------------------------------------------- The catalog `pg_operator` stores information about operators. See [CREATE OPERATOR](https://www.postgresql.org/docs/current/sql-createoperator.html "CREATE OPERATOR") and [Section 36.14](https://www.postgresql.org/docs/current/xoper.html "36.14. User-Defined Operators") for more information. **Table 52.34. `pg_operator` Columns** | Column Type

Description | | --- | | `oid` `oid`

Row identifier | | `oprname` `name`

Name of the operator | | `oprnamespace` `oid` (references [`pg_namespace`](https://www.postgresql.org/docs/current/catalog-pg-namespace.html "52.32. pg_namespace")
.`oid`)

The OID of the namespace that contains this operator | | `oprowner` `oid` (references [`pg_authid`](https://www.postgresql.org/docs/current/catalog-pg-authid.html "52.8. pg_authid")
.`oid`)

Owner of the operator | | `oprkind` `char`

`b` = infix operator (“both”), or `l` = prefix operator (“left”) | | `oprcanmerge` `bool`

This operator supports merge joins | | `oprcanhash` `bool`

This operator supports hash joins | | `oprleft` `oid` (references [`pg_type`](https://www.postgresql.org/docs/current/catalog-pg-type.html "52.64. pg_type")
.`oid`)

Type of the left operand (zero for a prefix operator) | | `oprright` `oid` (references [`pg_type`](https://www.postgresql.org/docs/current/catalog-pg-type.html "52.64. pg_type")
.`oid`)

Type of the right operand | | `oprresult` `oid` (references [`pg_type`](https://www.postgresql.org/docs/current/catalog-pg-type.html "52.64. pg_type")
.`oid`)

Type of the result (zero for a not-yet-defined “shell” operator) | | `oprcom` `oid` (references [`pg_operator`](https://www.postgresql.org/docs/current/catalog-pg-operator.html "52.34. pg_operator")
.`oid`)

Commutator of this operator (zero if none) | | `oprnegate` `oid` (references [`pg_operator`](https://www.postgresql.org/docs/current/catalog-pg-operator.html "52.34. pg_operator")
.`oid`)

Negator of this operator (zero if none) | | `oprcode` `regproc` (references [`pg_proc`](https://www.postgresql.org/docs/current/catalog-pg-proc.html "52.39. pg_proc")
.`oid`)

Function that implements this operator (zero for a not-yet-defined “shell” operator) | | `oprrest` `regproc` (references [`pg_proc`](https://www.postgresql.org/docs/current/catalog-pg-proc.html "52.39. pg_proc")
.`oid`)

Restriction selectivity estimation function for this operator (zero if none) | | `oprjoin` `regproc` (references [`pg_proc`](https://www.postgresql.org/docs/current/catalog-pg-proc.html "52.39. pg_proc")
.`oid`)

Join selectivity estimation function for this operator (zero if none) | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-opclass.html "52.33. pg_opclass") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/current/catalog-pg-opfamily.html "52.35. pg_opfamily") | | 52.33. `pg_opclass` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 52.35. `pg_opfamily` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/catalog-pg-operator.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 18.7. Preventing Server Spoofing November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/preventing-server-spoofing.html "PostgreSQL 18 - 18.7. Preventing Server Spoofing") ([18](https://www.postgresql.org/docs/18/preventing-server-spoofing.html "PostgreSQL 18 - 18.7. Preventing Server Spoofing") ) / [17](https://www.postgresql.org/docs/17/preventing-server-spoofing.html "PostgreSQL 17 - 18.7. Preventing Server Spoofing") / [16](https://www.postgresql.org/docs/16/preventing-server-spoofing.html "PostgreSQL 16 - 18.7. Preventing Server Spoofing") / [15](https://www.postgresql.org/docs/15/preventing-server-spoofing.html "PostgreSQL 15 - 18.7. Preventing Server Spoofing") / [14](https://www.postgresql.org/docs/14/preventing-server-spoofing.html "PostgreSQL 14 - 18.7. Preventing Server Spoofing") Development Versions: [devel](https://www.postgresql.org/docs/devel/preventing-server-spoofing.html "PostgreSQL devel - 18.7. Preventing Server Spoofing") Unsupported versions: [13](https://www.postgresql.org/docs/13/preventing-server-spoofing.html "PostgreSQL 13 - 18.7. Preventing Server Spoofing") / [12](https://www.postgresql.org/docs/12/preventing-server-spoofing.html "PostgreSQL 12 - 18.7. Preventing Server Spoofing") / [11](https://www.postgresql.org/docs/11/preventing-server-spoofing.html "PostgreSQL 11 - 18.7. Preventing Server Spoofing") / [10](https://www.postgresql.org/docs/10/preventing-server-spoofing.html "PostgreSQL 10 - 18.7. Preventing Server Spoofing") / [9.6](https://www.postgresql.org/docs/9.6/preventing-server-spoofing.html "PostgreSQL 9.6 - 18.7. Preventing Server Spoofing") / [9.5](https://www.postgresql.org/docs/9.5/preventing-server-spoofing.html "PostgreSQL 9.5 - 18.7. Preventing Server Spoofing") / [9.4](https://www.postgresql.org/docs/9.4/preventing-server-spoofing.html "PostgreSQL 9.4 - 18.7. Preventing Server Spoofing") / [9.3](https://www.postgresql.org/docs/9.3/preventing-server-spoofing.html "PostgreSQL 9.3 - 18.7. Preventing Server Spoofing") / [9.2](https://www.postgresql.org/docs/9.2/preventing-server-spoofing.html "PostgreSQL 9.2 - 18.7. Preventing Server Spoofing") / [9.1](https://www.postgresql.org/docs/9.1/preventing-server-spoofing.html "PostgreSQL 9.1 - 18.7. Preventing Server Spoofing") / [9.0](https://www.postgresql.org/docs/9.0/preventing-server-spoofing.html "PostgreSQL 9.0 - 18.7. Preventing Server Spoofing") / [8.4](https://www.postgresql.org/docs/8.4/preventing-server-spoofing.html "PostgreSQL 8.4 - 18.7. Preventing Server Spoofing") / [8.3](https://www.postgresql.org/docs/8.3/preventing-server-spoofing.html "PostgreSQL 8.3 - 18.7. Preventing Server Spoofing") | 18.7. Preventing Server Spoofing | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/upgrading.html "18.6. Upgrading a PostgreSQL Cluster") | [Up](https://www.postgresql.org/docs/current/runtime.html "Chapter 18. Server Setup and Operation") | Chapter 18. Server Setup and Operation | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/encryption-options.html "18.8. Encryption Options") | * * * 18.7. Preventing Server Spoofing [#](https://www.postgresql.org/docs/current/preventing-server-spoofing.html#PREVENTING-SERVER-SPOOFING) ----------------------------------------------------------------------------------------------------------------------------------------- While the server is running, it is not possible for a malicious user to take the place of the normal database server. However, when the server is down, it is possible for a local user to spoof the normal server by starting their own server. The spoof server could read passwords and queries sent by clients, but could not return any data because the `PGDATA` directory would still be secure because of directory permissions. Spoofing is possible because any user can start a database server; a client cannot identify an invalid server unless it is specially configured. One way to prevent spoofing of `local` connections is to use a Unix domain socket directory ([unix\_socket\_directories](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-UNIX-SOCKET-DIRECTORIES) ) that has write permission only for a trusted local user. This prevents a malicious user from creating their own socket file in that directory. If you are concerned that some applications might still reference `/tmp` for the socket file and hence be vulnerable to spoofing, during operating system startup create a symbolic link `/tmp/.s.PGSQL.5432` that points to the relocated socket file. You also might need to modify your `/tmp` cleanup script to prevent removal of the symbolic link. Another option for `local` connections is for clients to use [`requirepeer`](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-REQUIREPEER) to specify the required owner of the server process connected to the socket. To prevent spoofing on TCP connections, either use SSL certificates and make sure that clients check the server's certificate, or use GSSAPI encryption (or both, if they're on separate connections). To prevent spoofing with SSL, the server must be configured to accept only `hostssl` connections ([Section 20.1](https://www.postgresql.org/docs/current/auth-pg-hba-conf.html "20.1. The pg_hba.conf File") ) and have SSL key and certificate files ([Section 18.9](https://www.postgresql.org/docs/current/ssl-tcp.html "18.9. Secure TCP/IP Connections with SSL") ). The TCP client must connect using `sslmode=verify-ca` or `verify-full` and have the appropriate root certificate file installed ([Section 32.19.1](https://www.postgresql.org/docs/current/libpq-ssl.html#LIBQ-SSL-CERTIFICATES "32.19.1. Client Verification of Server Certificates") ). Alternatively the [system CA pool](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-SSLROOTCERT) , as defined by the SSL implementation, can be used using `sslrootcert=system`; in this case, `sslmode=verify-full` is forced for safety, since it is generally trivial to obtain certificates which are signed by a public CA. To prevent server spoofing from occurring when using [scram-sha-256](https://www.postgresql.org/docs/current/auth-password.html "20.5. Password Authentication") password authentication over a network, you should ensure that you connect to the server using SSL and with one of the anti-spoofing methods described in the previous paragraph. Additionally, the SCRAM implementation in libpq cannot protect the entire authentication exchange, but using the `channel_binding=require` connection parameter provides a mitigation against server spoofing. An attacker that uses a rogue server to intercept a SCRAM exchange can use offline analysis to potentially determine the hashed password from the client. To prevent spoofing with GSSAPI, the server must be configured to accept only `hostgssenc` connections ([Section 20.1](https://www.postgresql.org/docs/current/auth-pg-hba-conf.html "20.1. The pg_hba.conf File") ) and use `gss` authentication with them. The TCP client must connect using `gssencmode=require`. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/upgrading.html "18.6. Upgrading a PostgreSQL Cluster") | [Up](https://www.postgresql.org/docs/current/runtime.html "Chapter 18. Server Setup and Operation") | [Next](https://www.postgresql.org/docs/current/encryption-options.html "18.8. Encryption Options") | | 18.6. Upgrading a PostgreSQL Cluster | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 18.8. Encryption Options | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/preventing-server-spoofing.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE TEXT SEARCH PARSER November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createtsparser.html "PostgreSQL 18 - CREATE TEXT SEARCH PARSER") ([18](https://www.postgresql.org/docs/18/sql-createtsparser.html "PostgreSQL 18 - CREATE TEXT SEARCH PARSER") ) / [17](https://www.postgresql.org/docs/17/sql-createtsparser.html "PostgreSQL 17 - CREATE TEXT SEARCH PARSER") / [16](https://www.postgresql.org/docs/16/sql-createtsparser.html "PostgreSQL 16 - CREATE TEXT SEARCH PARSER") / [15](https://www.postgresql.org/docs/15/sql-createtsparser.html "PostgreSQL 15 - CREATE TEXT SEARCH PARSER") / [14](https://www.postgresql.org/docs/14/sql-createtsparser.html "PostgreSQL 14 - CREATE TEXT SEARCH PARSER") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createtsparser.html "PostgreSQL devel - CREATE TEXT SEARCH PARSER") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createtsparser.html "PostgreSQL 13 - CREATE TEXT SEARCH PARSER") / [12](https://www.postgresql.org/docs/12/sql-createtsparser.html "PostgreSQL 12 - CREATE TEXT SEARCH PARSER") / [11](https://www.postgresql.org/docs/11/sql-createtsparser.html "PostgreSQL 11 - CREATE TEXT SEARCH PARSER") / [10](https://www.postgresql.org/docs/10/sql-createtsparser.html "PostgreSQL 10 - CREATE TEXT SEARCH PARSER") / [9.6](https://www.postgresql.org/docs/9.6/sql-createtsparser.html "PostgreSQL 9.6 - CREATE TEXT SEARCH PARSER") / [9.5](https://www.postgresql.org/docs/9.5/sql-createtsparser.html "PostgreSQL 9.5 - CREATE TEXT SEARCH PARSER") / [9.4](https://www.postgresql.org/docs/9.4/sql-createtsparser.html "PostgreSQL 9.4 - CREATE TEXT SEARCH PARSER") / [9.3](https://www.postgresql.org/docs/9.3/sql-createtsparser.html "PostgreSQL 9.3 - CREATE TEXT SEARCH PARSER") / [9.2](https://www.postgresql.org/docs/9.2/sql-createtsparser.html "PostgreSQL 9.2 - CREATE TEXT SEARCH PARSER") / [9.1](https://www.postgresql.org/docs/9.1/sql-createtsparser.html "PostgreSQL 9.1 - CREATE TEXT SEARCH PARSER") / [9.0](https://www.postgresql.org/docs/9.0/sql-createtsparser.html "PostgreSQL 9.0 - CREATE TEXT SEARCH PARSER") / [8.4](https://www.postgresql.org/docs/8.4/sql-createtsparser.html "PostgreSQL 8.4 - CREATE TEXT SEARCH PARSER") / [8.3](https://www.postgresql.org/docs/8.3/sql-createtsparser.html "PostgreSQL 8.3 - CREATE TEXT SEARCH PARSER") | CREATE TEXT SEARCH PARSER | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createtsdictionary.html "CREATE TEXT SEARCH DICTIONARY") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-createtstemplate.html "CREATE TEXT SEARCH TEMPLATE") | * * * CREATE TEXT SEARCH PARSER ------------------------- CREATE TEXT SEARCH PARSER — define a new text search parser Synopsis -------- CREATE TEXT SEARCH PARSER _`name`_ ( START = _`start_function`_ , GETTOKEN = _`gettoken_function`_ , END = _`end_function`_ , LEXTYPES = _`lextypes_function`_ \[, HEADLINE = _`headline_function`_ \] ) Description ----------- `CREATE TEXT SEARCH PARSER` creates a new text search parser. A text search parser defines a method for splitting a text string into tokens and assigning types (categories) to the tokens. A parser is not particularly useful by itself, but must be bound into a text search configuration along with some text search dictionaries to be used for searching. If a schema name is given then the text search parser is created in the specified schema. Otherwise it is created in the current schema. You must be a superuser to use `CREATE TEXT SEARCH PARSER`. (This restriction is made because an erroneous text search parser definition could confuse or even crash the server.) Refer to [Chapter 12](https://www.postgresql.org/docs/current/textsearch.html "Chapter 12. Full Text Search") for further information. Parameters ---------- _`name`_ The name of the text search parser to be created. The name can be schema-qualified. _`start_function`_ The name of the start function for the parser. _`gettoken_function`_ The name of the get-next-token function for the parser. _`end_function`_ The name of the end function for the parser. _`lextypes_function`_ The name of the lextypes function for the parser (a function that returns information about the set of token types it produces). _`headline_function`_ The name of the headline function for the parser (a function that summarizes a set of tokens). The function names can be schema-qualified if necessary. Argument types are not given, since the argument list for each type of function is predetermined. All except the headline function are required. The arguments can appear in any order, not only the one shown above. Compatibility ------------- There is no `CREATE TEXT SEARCH PARSER` statement in the SQL standard. See Also -------- [ALTER TEXT SEARCH PARSER](https://www.postgresql.org/docs/current/sql-altertsparser.html "ALTER TEXT SEARCH PARSER") , [DROP TEXT SEARCH PARSER](https://www.postgresql.org/docs/current/sql-droptsparser.html "DROP TEXT SEARCH PARSER") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createtsdictionary.html "CREATE TEXT SEARCH DICTIONARY") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-createtstemplate.html "CREATE TEXT SEARCH TEMPLATE") | | CREATE TEXT SEARCH DICTIONARY | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | CREATE TEXT SEARCH TEMPLATE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createtsparser.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: H.4. Extensions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/external-extensions.html "PostgreSQL 18 - H.4. Extensions") ([18](https://www.postgresql.org/docs/18/external-extensions.html "PostgreSQL 18 - H.4. Extensions") ) / [17](https://www.postgresql.org/docs/17/external-extensions.html "PostgreSQL 17 - H.4. Extensions") / [16](https://www.postgresql.org/docs/16/external-extensions.html "PostgreSQL 16 - H.4. Extensions") / [15](https://www.postgresql.org/docs/15/external-extensions.html "PostgreSQL 15 - H.4. Extensions") / [14](https://www.postgresql.org/docs/14/external-extensions.html "PostgreSQL 14 - H.4. Extensions") Development Versions: [devel](https://www.postgresql.org/docs/devel/external-extensions.html "PostgreSQL devel - H.4. Extensions") Unsupported versions: [13](https://www.postgresql.org/docs/13/external-extensions.html "PostgreSQL 13 - H.4. Extensions") / [12](https://www.postgresql.org/docs/12/external-extensions.html "PostgreSQL 12 - H.4. Extensions") / [11](https://www.postgresql.org/docs/11/external-extensions.html "PostgreSQL 11 - H.4. Extensions") / [10](https://www.postgresql.org/docs/10/external-extensions.html "PostgreSQL 10 - H.4. Extensions") / [9.6](https://www.postgresql.org/docs/9.6/external-extensions.html "PostgreSQL 9.6 - H.4. Extensions") / [9.5](https://www.postgresql.org/docs/9.5/external-extensions.html "PostgreSQL 9.5 - H.4. Extensions") / [9.4](https://www.postgresql.org/docs/9.4/external-extensions.html "PostgreSQL 9.4 - H.4. Extensions") / [9.3](https://www.postgresql.org/docs/9.3/external-extensions.html "PostgreSQL 9.3 - H.4. Extensions") / [9.2](https://www.postgresql.org/docs/9.2/external-extensions.html "PostgreSQL 9.2 - H.4. Extensions") / [9.1](https://www.postgresql.org/docs/9.1/external-extensions.html "PostgreSQL 9.1 - H.4. Extensions") / [9.0](https://www.postgresql.org/docs/9.0/external-extensions.html "PostgreSQL 9.0 - H.4. Extensions") / [8.4](https://www.postgresql.org/docs/8.4/external-extensions.html "PostgreSQL 8.4 - H.4. Extensions") / [8.3](https://www.postgresql.org/docs/8.3/external-extensions.html "PostgreSQL 8.3 - H.4. Extensions") / [8.2](https://www.postgresql.org/docs/8.2/external-extensions.html "PostgreSQL 8.2 - H.4. Extensions") / [8.1](https://www.postgresql.org/docs/8.1/external-extensions.html "PostgreSQL 8.1 - H.4. Extensions") / [8.0](https://www.postgresql.org/docs/8.0/external-extensions.html "PostgreSQL 8.0 - H.4. Extensions") | H.4. Extensions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/external-pl.html "H.3. Procedural Languages") | [Up](https://www.postgresql.org/docs/18/external-projects.html "Appendix H. External Projects") | Appendix H. External Projects | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sourcerepo.html "Appendix I. The Source Code Repository") | * * * H.4. Extensions [#](https://www.postgresql.org/docs/18/external-extensions.html#EXTERNAL-EXTENSIONS) ----------------------------------------------------------------------------------------------------- PostgreSQL is designed to be easily extensible. For this reason, extensions loaded into the database can function just like features that are built in. The `contrib/` directory shipped with the source code contains several extensions, which are described in [Appendix F](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") . Other extensions are developed independently, like [PostGIS](https://postgis.net/) . Even PostgreSQL replication solutions can be developed externally. For example, [Slony-I](https://www.slony.info/) is a popular primary/standby replication solution that is developed independently from the core project. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/external-pl.html "H.3. Procedural Languages") | [Up](https://www.postgresql.org/docs/18/external-projects.html "Appendix H. External Projects") | [Next](https://www.postgresql.org/docs/18/sourcerepo.html "Appendix I. The Source Code Repository") | | H.3. Procedural Languages | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | Appendix I. The Source Code Repository | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/external-extensions.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 18.7. Preventing Server Spoofing November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/preventing-server-spoofing.html "PostgreSQL 18 - 18.7. Preventing Server Spoofing") ([18](https://www.postgresql.org/docs/18/preventing-server-spoofing.html "PostgreSQL 18 - 18.7. Preventing Server Spoofing") ) / [17](https://www.postgresql.org/docs/17/preventing-server-spoofing.html "PostgreSQL 17 - 18.7. Preventing Server Spoofing") / [16](https://www.postgresql.org/docs/16/preventing-server-spoofing.html "PostgreSQL 16 - 18.7. Preventing Server Spoofing") / [15](https://www.postgresql.org/docs/15/preventing-server-spoofing.html "PostgreSQL 15 - 18.7. Preventing Server Spoofing") / [14](https://www.postgresql.org/docs/14/preventing-server-spoofing.html "PostgreSQL 14 - 18.7. Preventing Server Spoofing") Development Versions: [devel](https://www.postgresql.org/docs/devel/preventing-server-spoofing.html "PostgreSQL devel - 18.7. Preventing Server Spoofing") Unsupported versions: [13](https://www.postgresql.org/docs/13/preventing-server-spoofing.html "PostgreSQL 13 - 18.7. Preventing Server Spoofing") / [12](https://www.postgresql.org/docs/12/preventing-server-spoofing.html "PostgreSQL 12 - 18.7. Preventing Server Spoofing") / [11](https://www.postgresql.org/docs/11/preventing-server-spoofing.html "PostgreSQL 11 - 18.7. Preventing Server Spoofing") / [10](https://www.postgresql.org/docs/10/preventing-server-spoofing.html "PostgreSQL 10 - 18.7. Preventing Server Spoofing") / [9.6](https://www.postgresql.org/docs/9.6/preventing-server-spoofing.html "PostgreSQL 9.6 - 18.7. Preventing Server Spoofing") / [9.5](https://www.postgresql.org/docs/9.5/preventing-server-spoofing.html "PostgreSQL 9.5 - 18.7. Preventing Server Spoofing") / [9.4](https://www.postgresql.org/docs/9.4/preventing-server-spoofing.html "PostgreSQL 9.4 - 18.7. Preventing Server Spoofing") / [9.3](https://www.postgresql.org/docs/9.3/preventing-server-spoofing.html "PostgreSQL 9.3 - 18.7. Preventing Server Spoofing") / [9.2](https://www.postgresql.org/docs/9.2/preventing-server-spoofing.html "PostgreSQL 9.2 - 18.7. Preventing Server Spoofing") / [9.1](https://www.postgresql.org/docs/9.1/preventing-server-spoofing.html "PostgreSQL 9.1 - 18.7. Preventing Server Spoofing") / [9.0](https://www.postgresql.org/docs/9.0/preventing-server-spoofing.html "PostgreSQL 9.0 - 18.7. Preventing Server Spoofing") / [8.4](https://www.postgresql.org/docs/8.4/preventing-server-spoofing.html "PostgreSQL 8.4 - 18.7. Preventing Server Spoofing") / [8.3](https://www.postgresql.org/docs/8.3/preventing-server-spoofing.html "PostgreSQL 8.3 - 18.7. Preventing Server Spoofing") | 18.7. Preventing Server Spoofing | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/upgrading.html "18.6. Upgrading a PostgreSQL Cluster") | [Up](https://www.postgresql.org/docs/18/runtime.html "Chapter 18. Server Setup and Operation") | Chapter 18. Server Setup and Operation | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/encryption-options.html "18.8. Encryption Options") | * * * 18.7. Preventing Server Spoofing [#](https://www.postgresql.org/docs/18/preventing-server-spoofing.html#PREVENTING-SERVER-SPOOFING) ------------------------------------------------------------------------------------------------------------------------------------ While the server is running, it is not possible for a malicious user to take the place of the normal database server. However, when the server is down, it is possible for a local user to spoof the normal server by starting their own server. The spoof server could read passwords and queries sent by clients, but could not return any data because the `PGDATA` directory would still be secure because of directory permissions. Spoofing is possible because any user can start a database server; a client cannot identify an invalid server unless it is specially configured. One way to prevent spoofing of `local` connections is to use a Unix domain socket directory ([unix\_socket\_directories](https://www.postgresql.org/docs/18/runtime-config-connection.html#GUC-UNIX-SOCKET-DIRECTORIES) ) that has write permission only for a trusted local user. This prevents a malicious user from creating their own socket file in that directory. If you are concerned that some applications might still reference `/tmp` for the socket file and hence be vulnerable to spoofing, during operating system startup create a symbolic link `/tmp/.s.PGSQL.5432` that points to the relocated socket file. You also might need to modify your `/tmp` cleanup script to prevent removal of the symbolic link. Another option for `local` connections is for clients to use [`requirepeer`](https://www.postgresql.org/docs/18/libpq-connect.html#LIBPQ-CONNECT-REQUIREPEER) to specify the required owner of the server process connected to the socket. To prevent spoofing on TCP connections, either use SSL certificates and make sure that clients check the server's certificate, or use GSSAPI encryption (or both, if they're on separate connections). To prevent spoofing with SSL, the server must be configured to accept only `hostssl` connections ([Section 20.1](https://www.postgresql.org/docs/18/auth-pg-hba-conf.html "20.1. The pg_hba.conf File") ) and have SSL key and certificate files ([Section 18.9](https://www.postgresql.org/docs/18/ssl-tcp.html "18.9. Secure TCP/IP Connections with SSL") ). The TCP client must connect using `sslmode=verify-ca` or `verify-full` and have the appropriate root certificate file installed ([Section 32.19.1](https://www.postgresql.org/docs/18/libpq-ssl.html#LIBQ-SSL-CERTIFICATES "32.19.1. Client Verification of Server Certificates") ). Alternatively the [system CA pool](https://www.postgresql.org/docs/18/libpq-connect.html#LIBPQ-CONNECT-SSLROOTCERT) , as defined by the SSL implementation, can be used using `sslrootcert=system`; in this case, `sslmode=verify-full` is forced for safety, since it is generally trivial to obtain certificates which are signed by a public CA. To prevent server spoofing from occurring when using [scram-sha-256](https://www.postgresql.org/docs/18/auth-password.html "20.5. Password Authentication") password authentication over a network, you should ensure that you connect to the server using SSL and with one of the anti-spoofing methods described in the previous paragraph. Additionally, the SCRAM implementation in libpq cannot protect the entire authentication exchange, but using the `channel_binding=require` connection parameter provides a mitigation against server spoofing. An attacker that uses a rogue server to intercept a SCRAM exchange can use offline analysis to potentially determine the hashed password from the client. To prevent spoofing with GSSAPI, the server must be configured to accept only `hostgssenc` connections ([Section 20.1](https://www.postgresql.org/docs/18/auth-pg-hba-conf.html "20.1. The pg_hba.conf File") ) and use `gss` authentication with them. The TCP client must connect using `gssencmode=require`. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/upgrading.html "18.6. Upgrading a PostgreSQL Cluster") | [Up](https://www.postgresql.org/docs/18/runtime.html "Chapter 18. Server Setup and Operation") | [Next](https://www.postgresql.org/docs/18/encryption-options.html "18.8. Encryption Options") | | 18.6. Upgrading a PostgreSQL Cluster | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 18.8. Encryption Options | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/preventing-server-spoofing.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 52.32. pg_namespace November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-namespace.html "PostgreSQL 18 - 52.32. pg_namespace") ([18](https://www.postgresql.org/docs/18/catalog-pg-namespace.html "PostgreSQL 18 - 52.32. pg_namespace") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-namespace.html "PostgreSQL 17 - 52.32. pg_namespace") / [16](https://www.postgresql.org/docs/16/catalog-pg-namespace.html "PostgreSQL 16 - 52.32. pg_namespace") / [15](https://www.postgresql.org/docs/15/catalog-pg-namespace.html "PostgreSQL 15 - 52.32. pg_namespace") / [14](https://www.postgresql.org/docs/14/catalog-pg-namespace.html "PostgreSQL 14 - 52.32. pg_namespace") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-namespace.html "PostgreSQL devel - 52.32. pg_namespace") Unsupported versions: [13](https://www.postgresql.org/docs/13/catalog-pg-namespace.html "PostgreSQL 13 - 52.32. pg_namespace") / [12](https://www.postgresql.org/docs/12/catalog-pg-namespace.html "PostgreSQL 12 - 52.32. pg_namespace") / [11](https://www.postgresql.org/docs/11/catalog-pg-namespace.html "PostgreSQL 11 - 52.32. pg_namespace") / [10](https://www.postgresql.org/docs/10/catalog-pg-namespace.html "PostgreSQL 10 - 52.32. pg_namespace") / [9.6](https://www.postgresql.org/docs/9.6/catalog-pg-namespace.html "PostgreSQL 9.6 - 52.32. pg_namespace") / [9.5](https://www.postgresql.org/docs/9.5/catalog-pg-namespace.html "PostgreSQL 9.5 - 52.32. pg_namespace") / [9.4](https://www.postgresql.org/docs/9.4/catalog-pg-namespace.html "PostgreSQL 9.4 - 52.32. pg_namespace") / [9.3](https://www.postgresql.org/docs/9.3/catalog-pg-namespace.html "PostgreSQL 9.3 - 52.32. pg_namespace") / [9.2](https://www.postgresql.org/docs/9.2/catalog-pg-namespace.html "PostgreSQL 9.2 - 52.32. pg_namespace") / [9.1](https://www.postgresql.org/docs/9.1/catalog-pg-namespace.html "PostgreSQL 9.1 - 52.32. pg_namespace") / [9.0](https://www.postgresql.org/docs/9.0/catalog-pg-namespace.html "PostgreSQL 9.0 - 52.32. pg_namespace") / [8.4](https://www.postgresql.org/docs/8.4/catalog-pg-namespace.html "PostgreSQL 8.4 - 52.32. pg_namespace") / [8.3](https://www.postgresql.org/docs/8.3/catalog-pg-namespace.html "PostgreSQL 8.3 - 52.32. pg_namespace") / [8.2](https://www.postgresql.org/docs/8.2/catalog-pg-namespace.html "PostgreSQL 8.2 - 52.32. pg_namespace") / [8.1](https://www.postgresql.org/docs/8.1/catalog-pg-namespace.html "PostgreSQL 8.1 - 52.32. pg_namespace") / [8.0](https://www.postgresql.org/docs/8.0/catalog-pg-namespace.html "PostgreSQL 8.0 - 52.32. pg_namespace") / [7.4](https://www.postgresql.org/docs/7.4/catalog-pg-namespace.html "PostgreSQL 7.4 - 52.32. pg_namespace") / [7.3](https://www.postgresql.org/docs/7.3/catalog-pg-namespace.html "PostgreSQL 7.3 - 52.32. pg_namespace") | 52.32. `pg_namespace` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/catalog-pg-largeobject-metadata.html "52.31. pg_largeobject_metadata") | [Up](https://www.postgresql.org/docs/18/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/catalog-pg-opclass.html "52.33. pg_opclass") | * * * 52.32. `pg_namespace` [#](https://www.postgresql.org/docs/18/catalog-pg-namespace.html#CATALOG-PG-NAMESPACE) ------------------------------------------------------------------------------------------------------------- The catalog `pg_namespace` stores namespaces. A namespace is the structure underlying SQL schemas: each namespace can have a separate collection of relations, types, etc. without name conflicts. **Table 52.32. `pg_namespace` Columns** | Column Type

Description | | --- | | `oid` `oid`

Row identifier | | `nspname` `name`

Name of the namespace | | `nspowner` `oid` (references [`pg_authid`](https://www.postgresql.org/docs/18/catalog-pg-authid.html "52.8. pg_authid")
.`oid`)

Owner of the namespace | | `nspacl` `aclitem[]`

Access privileges; see [Section 5.8](https://www.postgresql.org/docs/18/ddl-priv.html "5.8. Privileges")
for details | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/catalog-pg-largeobject-metadata.html "52.31. pg_largeobject_metadata") | [Up](https://www.postgresql.org/docs/18/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/18/catalog-pg-opclass.html "52.33. pg_opclass") | | 52.31. `pg_largeobject_metadata` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 52.33. `pg_opclass` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/catalog-pg-namespace.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.17. hstore — hstore key/value datatype November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/hstore.html "PostgreSQL 18 - F.17. hstore — hstore key/value datatype") ([18](https://www.postgresql.org/docs/18/hstore.html "PostgreSQL 18 - F.17. hstore — hstore key/value datatype") ) / [17](https://www.postgresql.org/docs/17/hstore.html "PostgreSQL 17 - F.17. hstore — hstore key/value datatype") / [16](https://www.postgresql.org/docs/16/hstore.html "PostgreSQL 16 - F.17. hstore — hstore key/value datatype") / [15](https://www.postgresql.org/docs/15/hstore.html "PostgreSQL 15 - F.17. hstore — hstore key/value datatype") / [14](https://www.postgresql.org/docs/14/hstore.html "PostgreSQL 14 - F.17. hstore — hstore key/value datatype") Development Versions: [devel](https://www.postgresql.org/docs/devel/hstore.html "PostgreSQL devel - F.17. hstore — hstore key/value datatype") Unsupported versions: [13](https://www.postgresql.org/docs/13/hstore.html "PostgreSQL 13 - F.17. hstore — hstore key/value datatype") / [12](https://www.postgresql.org/docs/12/hstore.html "PostgreSQL 12 - F.17. hstore — hstore key/value datatype") / [11](https://www.postgresql.org/docs/11/hstore.html "PostgreSQL 11 - F.17. hstore — hstore key/value datatype") / [10](https://www.postgresql.org/docs/10/hstore.html "PostgreSQL 10 - F.17. hstore — hstore key/value datatype") / [9.6](https://www.postgresql.org/docs/9.6/hstore.html "PostgreSQL 9.6 - F.17. hstore — hstore key/value datatype") / [9.5](https://www.postgresql.org/docs/9.5/hstore.html "PostgreSQL 9.5 - F.17. hstore — hstore key/value datatype") / [9.4](https://www.postgresql.org/docs/9.4/hstore.html "PostgreSQL 9.4 - F.17. hstore — hstore key/value datatype") / [9.3](https://www.postgresql.org/docs/9.3/hstore.html "PostgreSQL 9.3 - F.17. hstore — hstore key/value datatype") / [9.2](https://www.postgresql.org/docs/9.2/hstore.html "PostgreSQL 9.2 - F.17. hstore — hstore key/value datatype") / [9.1](https://www.postgresql.org/docs/9.1/hstore.html "PostgreSQL 9.1 - F.17. hstore — hstore key/value datatype") / [9.0](https://www.postgresql.org/docs/9.0/hstore.html "PostgreSQL 9.0 - F.17. hstore — hstore key/value datatype") / [8.4](https://www.postgresql.org/docs/8.4/hstore.html "PostgreSQL 8.4 - F.17. hstore — hstore key/value datatype") / [8.3](https://www.postgresql.org/docs/8.3/hstore.html "PostgreSQL 8.3 - F.17. hstore — hstore key/value datatype") | F.17. hstore — hstore key/value datatype | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/fuzzystrmatch.html "F.16. fuzzystrmatch — determine string similarities and distance") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/intagg.html "F.18. intagg — integer aggregator and enumerator") | * * * F.17. hstore — hstore key/value datatype [#](https://www.postgresql.org/docs/18/hstore.html#HSTORE) ---------------------------------------------------------------------------------------------------- [F.17.1. `hstore` External Representation](https://www.postgresql.org/docs/18/hstore.html#HSTORE-EXTERNAL-REP) [F.17.2. `hstore` Operators and Functions](https://www.postgresql.org/docs/18/hstore.html#HSTORE-OPS-FUNCS) [F.17.3. Indexes](https://www.postgresql.org/docs/18/hstore.html#HSTORE-INDEXES) [F.17.4. Examples](https://www.postgresql.org/docs/18/hstore.html#HSTORE-EXAMPLES) [F.17.5. Statistics](https://www.postgresql.org/docs/18/hstore.html#HSTORE-STATISTICS) [F.17.6. Compatibility](https://www.postgresql.org/docs/18/hstore.html#HSTORE-COMPATIBILITY) [F.17.7. Transforms](https://www.postgresql.org/docs/18/hstore.html#HSTORE-TRANSFORMS) [F.17.8. Authors](https://www.postgresql.org/docs/18/hstore.html#HSTORE-AUTHORS) This module implements the `hstore` data type for storing sets of key/value pairs within a single PostgreSQL value. This can be useful in various scenarios, such as rows with many attributes that are rarely examined, or semi-structured data. Keys and values are simply text strings. This module is considered “trusted”, that is, it can be installed by non-superusers who have `CREATE` privilege on the current database. ### F.17.1. `hstore` External Representation [#](https://www.postgresql.org/docs/18/hstore.html#HSTORE-EXTERNAL-REP) The text representation of an `hstore`, used for input and output, includes zero or more _`key`_ `=>` _`value`_ pairs separated by commas. Some examples: k => v foo => bar, baz => whatever "1-a" => "anything at all" The order of the pairs is not significant (and may not be reproduced on output). Whitespace between pairs or around the `=>` sign is ignored. Double-quote keys and values that include whitespace, commas, `=`s or `>`s. To include a double quote or a backslash in a key or value, escape it with a backslash. Each key in an `hstore` is unique. If you declare an `hstore` with duplicate keys, only one will be stored in the `hstore` and there is no guarantee as to which will be kept: SELECT 'a=>1,a=>2'::hstore; hstore ---------- "a"=>"1" A value (but not a key) can be an SQL `NULL`. For example: key => NULL The `NULL` keyword is case-insensitive. Double-quote the `NULL` to treat it as the ordinary string “NULL”. ### Note Keep in mind that the `hstore` text format, when used for input, applies _before_ any required quoting or escaping. If you are passing an `hstore` literal via a parameter, then no additional processing is needed. But if you're passing it as a quoted literal constant, then any single-quote characters and (depending on the setting of the `standard_conforming_strings` configuration parameter) backslash characters need to be escaped correctly. See [Section 4.1.2.1](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS "4.1.2.1. String Constants") for more on the handling of string constants. On output, double quotes always surround keys and values, even when it's not strictly necessary. ### F.17.2. `hstore` Operators and Functions [#](https://www.postgresql.org/docs/18/hstore.html#HSTORE-OPS-FUNCS) The operators provided by the `hstore` module are shown in [Table F.6](https://www.postgresql.org/docs/18/hstore.html#HSTORE-OP-TABLE "Table F.6. hstore Operators") , the functions in [Table F.7](https://www.postgresql.org/docs/18/hstore.html#HSTORE-FUNC-TABLE "Table F.7. hstore Functions") . **Table F.6. `hstore` Operators** | Operator

Description

Example(s) | | --- | | `hstore` `->` `text` → `text`

Returns value associated with given key, or `NULL` if not present.

`'a=>x, b=>y'::hstore -> 'a'` → `x` | | `hstore` `->` `text[]` → `text[]`

Returns values associated with given keys, or `NULL` if not present.

`'a=>x, b=>y, c=>z'::hstore -> ARRAY['c','a']` → `{"z","x"}` | | `hstore` `\|` `hstore` → `hstore`

Concatenates two `hstore`s.

`'a=>b, c=>d'::hstore \| 'c=>x, d=>q'::hstore` → `"a"=>"b", "c"=>"x", "d"=>"q"` | | `hstore` `?` `text` → `boolean`

Does `hstore` contain key?

`'a=>1'::hstore ? 'a'` → `t` | | `hstore` `?&` `text[]` → `boolean`

Does `hstore` contain all the specified keys?

`'a=>1,b=>2'::hstore ?& ARRAY['a','b']` → `t` | | `hstore` `?\|` `text[]` → `boolean`

Does `hstore` contain any of the specified keys?

`'a=>1,b=>2'::hstore ?\| ARRAY['b','c']` → `t` | | `hstore` `@>` `hstore` → `boolean`

Does left operand contain right?

`'a=>b, b=>1, c=>NULL'::hstore @> 'b=>1'` → `t` | | `hstore` `<@` `hstore` → `boolean`

Is left operand contained in right?

`'a=>c'::hstore <@ 'a=>b, b=>1, c=>NULL'` → `f` | | `hstore` `-` `text` → `hstore`

Deletes key from left operand.

`'a=>1, b=>2, c=>3'::hstore - 'b'::text` → `"a"=>"1", "c"=>"3"` | | `hstore` `-` `text[]` → `hstore`

Deletes keys from left operand.

`'a=>1, b=>2, c=>3'::hstore - ARRAY['a','b']` → `"c"=>"3"` | | `hstore` `-` `hstore` → `hstore`

Deletes pairs from left operand that match pairs in the right operand.

`'a=>1, b=>2, c=>3'::hstore - 'a=>4, b=>2'::hstore` → `"a"=>"1", "c"=>"3"` | | `anyelement` `#=` `hstore` → `anyelement`

Replaces fields in the left operand (which must be a composite type) with matching values from `hstore`.

`ROW(1,3) #= 'f1=>11'::hstore` → `(11,3)` | | `%%` `hstore` → `text[]`

Converts `hstore` to an array of alternating keys and values.

`%% 'a=>foo, b=>bar'::hstore` → `{a,foo,b,bar}` | | `%#` `hstore` → `text[]`

Converts `hstore` to a two-dimensional key/value array.

`%# 'a=>foo, b=>bar'::hstore` → `{{a,foo},{b,bar}}` | **Table F.7. `hstore` Functions** | Function

Description

Example(s) | | --- | | `hstore` ( `record` ) → `hstore`

Constructs an `hstore` from a record or row.

`hstore(ROW(1,2))` → `"f1"=>"1", "f2"=>"2"` | | `hstore` ( `text[]` ) → `hstore`

Constructs an `hstore` from an array, which may be either a key/value array, or a two-dimensional array.

`hstore(ARRAY['a','1','b','2'])` → `"a"=>"1", "b"=>"2"`

`hstore(ARRAY[['c','3'],['d','4']])` → `"c"=>"3", "d"=>"4"` | | `hstore` ( `text[]`, `text[]` ) → `hstore`

Constructs an `hstore` from separate key and value arrays.

`hstore(ARRAY['a','b'], ARRAY['1','2'])` → `"a"=>"1", "b"=>"2"` | | `hstore` ( `text`, `text` ) → `hstore`

Makes a single-item `hstore`.

`hstore('a', 'b')` → `"a"=>"b"` | | `akeys` ( `hstore` ) → `text[]`

Extracts an `hstore`'s keys as an array.

`akeys('a=>1,b=>2')` → `{a,b}` | | `skeys` ( `hstore` ) → `setof text`

Extracts an `hstore`'s keys as a set.

`skeys('a=>1,b=>2')` →

a
b | | `avals` ( `hstore` ) → `text[]`

Extracts an `hstore`'s values as an array.

`avals('a=>1,b=>2')` → `{1,2}` | | `svals` ( `hstore` ) → `setof text`

Extracts an `hstore`'s values as a set.

`svals('a=>1,b=>2')` →

1
2 | | `hstore_to_array` ( `hstore` ) → `text[]`

Extracts an `hstore`'s keys and values as an array of alternating keys and values.

`hstore_to_array('a=>1,b=>2')` → `{a,1,b,2}` | | `hstore_to_matrix` ( `hstore` ) → `text[]`

Extracts an `hstore`'s keys and values as a two-dimensional array.

`hstore_to_matrix('a=>1,b=>2')` → `{{a,1},{b,2}}` | | `hstore_to_json` ( `hstore` ) → `json`

Converts an `hstore` to a `json` value, converting all non-null values to JSON strings.

This function is used implicitly when an `hstore` value is cast to `json`.

`hstore_to_json('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": "1", "b": "t", "c": null, "d": "12345", "e": "012345", "f": "1.234", "g": "2.345e+4"}` | | `hstore_to_jsonb` ( `hstore` ) → `jsonb`

Converts an `hstore` to a `jsonb` value, converting all non-null values to JSON strings.

This function is used implicitly when an `hstore` value is cast to `jsonb`.

`hstore_to_jsonb('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": "1", "b": "t", "c": null, "d": "12345", "e": "012345", "f": "1.234", "g": "2.345e+4"}` | | `hstore_to_json_loose` ( `hstore` ) → `json`

Converts an `hstore` to a `json` value, but attempts to distinguish numerical and Boolean values so they are unquoted in the JSON.

`hstore_to_json_loose('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": 1, "b": true, "c": null, "d": 12345, "e": "012345", "f": 1.234, "g": 2.345e+4}` | | `hstore_to_jsonb_loose` ( `hstore` ) → `jsonb`

Converts an `hstore` to a `jsonb` value, but attempts to distinguish numerical and Boolean values so they are unquoted in the JSON.

`hstore_to_jsonb_loose('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": 1, "b": true, "c": null, "d": 12345, "e": "012345", "f": 1.234, "g": 2.345e+4}` | | `slice` ( `hstore`, `text[]` ) → `hstore`

Extracts a subset of an `hstore` containing only the specified keys.

`slice('a=>1,b=>2,c=>3'::hstore, ARRAY['b','c','x'])` → `"b"=>"2", "c"=>"3"` | | `each` ( `hstore` ) → `setof record` ( _`key`_ `text`, _`value`_ `text` )

Extracts an `hstore`'s keys and values as a set of records.

`select * from each('a=>1,b=>2')` →

key \| value
-----+-------
a \| 1
b \| 2 | | `exist` ( `hstore`, `text` ) → `boolean`

Does `hstore` contain key?

`exist('a=>1', 'a')` → `t` | | `defined` ( `hstore`, `text` ) → `boolean`

Does `hstore` contain a non-`NULL` value for key?

`defined('a=>NULL', 'a')` → `f` | | `delete` ( `hstore`, `text` ) → `hstore`

Deletes pair with matching key.

`delete('a=>1,b=>2', 'b')` → `"a"=>"1"` | | `delete` ( `hstore`, `text[]` ) → `hstore`

Deletes pairs with matching keys.

`delete('a=>1,b=>2,c=>3', ARRAY['a','b'])` → `"c"=>"3"` | | `delete` ( `hstore`, `hstore` ) → `hstore`

Deletes pairs matching those in the second argument.

`delete('a=>1,b=>2', 'a=>4,b=>2'::hstore)` → `"a"=>"1"` | | `populate_record` ( `anyelement`, `hstore` ) → `anyelement`

Replaces fields in the left operand (which must be a composite type) with matching values from `hstore`.

`populate_record(ROW(1,2), 'f1=>42'::hstore)` → `(42,2)` | In addition to these operators and functions, values of the `hstore` type can be subscripted, allowing them to act like associative arrays. Only a single subscript of type `text` can be specified; it is interpreted as a key and the corresponding value is fetched or stored. For example, CREATE TABLE mytable (h hstore); INSERT INTO mytable VALUES ('a=>b, c=>d'); SELECT h\['a'\] FROM mytable; h --- b (1 row) UPDATE mytable SET h\['c'\] = 'new'; SELECT h FROM mytable; h ---------------------- "a"=>"b", "c"=>"new" (1 row) A subscripted fetch returns `NULL` if the subscript is `NULL` or that key does not exist in the `hstore`. (Thus, a subscripted fetch is not greatly different from the `->` operator.) A subscripted update fails if the subscript is `NULL`; otherwise, it replaces the value for that key, adding an entry to the `hstore` if the key does not already exist. ### F.17.3. Indexes [#](https://www.postgresql.org/docs/18/hstore.html#HSTORE-INDEXES) `hstore` has GiST and GIN index support for the `@>`, `?`, `?&` and `?|` operators. For example: CREATE INDEX hidx ON testhstore USING GIST (h); CREATE INDEX hidx ON testhstore USING GIN (h); `gist_hstore_ops` GiST opclass approximates a set of key/value pairs as a bitmap signature. Its optional integer parameter `siglen` determines the signature length in bytes. The default length is 16 bytes. Valid values of signature length are between 1 and 2024 bytes. Longer signatures lead to a more precise search (scanning a smaller fraction of the index and fewer heap pages), at the cost of a larger index. Example of creating such an index with a signature length of 32 bytes: CREATE INDEX hidx ON testhstore USING GIST (h gist\_hstore\_ops(siglen=32)); `hstore` also supports `btree` or `hash` indexes for the `=` operator. This allows `hstore` columns to be declared `UNIQUE`, or to be used in `GROUP BY`, `ORDER BY` or `DISTINCT` expressions. The sort ordering for `hstore` values is not particularly useful, but these indexes may be useful for equivalence lookups. Create indexes for `=` comparisons as follows: CREATE INDEX hidx ON testhstore USING BTREE (h); CREATE INDEX hidx ON testhstore USING HASH (h); ### F.17.4. Examples [#](https://www.postgresql.org/docs/18/hstore.html#HSTORE-EXAMPLES) Add a key, or update an existing key with a new value: UPDATE tab SET h\['c'\] = '3'; Another way to do the same thing is: UPDATE tab SET h = h || hstore('c', '3'); If multiple keys are to be added or changed in one operation, the concatenation approach is more efficient than subscripting: UPDATE tab SET h = h || hstore(array\['q', 'w'\], array\['11', '12'\]); Delete a key: UPDATE tab SET h = delete(h, 'k1'); Convert a `record` to an `hstore`: CREATE TABLE test (col1 integer, col2 text, col3 text); INSERT INTO test VALUES (123, 'foo', 'bar'); SELECT hstore(t) FROM test AS t; hstore --------------------------------------------- "col1"=>"123", "col2"=>"foo", "col3"=>"bar" (1 row) Convert an `hstore` to a predefined `record` type: CREATE TABLE test (col1 integer, col2 text, col3 text); SELECT \* FROM populate\_record(null::test, '"col1"=>"456", "col2"=>"zzz"'); col1 | col2 | col3 ------+------+------ 456 | zzz | (1 row) Modify an existing record using the values from an `hstore`: CREATE TABLE test (col1 integer, col2 text, col3 text); INSERT INTO test VALUES (123, 'foo', 'bar'); SELECT (r).\* FROM (SELECT t #= '"col3"=>"baz"' AS r FROM test t) s; col1 | col2 | col3 ------+------+------ 123 | foo | baz (1 row) ### F.17.5. Statistics [#](https://www.postgresql.org/docs/18/hstore.html#HSTORE-STATISTICS) The `hstore` type, because of its intrinsic liberality, could contain a lot of different keys. Checking for valid keys is the task of the application. The following examples demonstrate several techniques for checking keys and obtaining statistics. Simple example: SELECT \* FROM each('aaa=>bq, b=>NULL, ""=>1'); Using a table: CREATE TABLE stat AS SELECT (each(h)).key, (each(h)).value FROM testhstore; Online statistics: SELECT key, count(\*) FROM (SELECT (each(h)).key FROM testhstore) AS stat GROUP BY key ORDER BY count DESC, key; key | count -----------+------- line | 883 query | 207 pos | 203 node | 202 space | 197 status | 195 public | 194 title | 190 org | 189 ................... ### F.17.6. Compatibility [#](https://www.postgresql.org/docs/18/hstore.html#HSTORE-COMPATIBILITY) As of PostgreSQL 9.0, `hstore` uses a different internal representation than previous versions. This presents no obstacle for dump/restore upgrades since the text representation (used in the dump) is unchanged. In the event of a binary upgrade, upward compatibility is maintained by having the new code recognize old-format data. This will entail a slight performance penalty when processing data that has not yet been modified by the new code. It is possible to force an upgrade of all values in a table column by doing an `UPDATE` statement as follows: UPDATE tablename SET hstorecol = hstorecol || ''; Another way to do it is: ALTER TABLE tablename ALTER hstorecol TYPE hstore USING hstorecol || ''; The `ALTER TABLE` method requires an `ACCESS EXCLUSIVE` lock on the table, but does not result in bloating the table with old row versions. ### F.17.7. Transforms [#](https://www.postgresql.org/docs/18/hstore.html#HSTORE-TRANSFORMS) Additional extensions are available that implement transforms for the `hstore` type for the languages PL/Perl and PL/Python. The extensions for PL/Perl are called `hstore_plperl` and `hstore_plperlu`, for trusted and untrusted PL/Perl. If you install these transforms and specify them when creating a function, `hstore` values are mapped to Perl hashes. The extension for PL/Python is called `hstore_plpython3u`. If you use it, `hstore` values are mapped to Python dictionaries. ### F.17.8. Authors [#](https://www.postgresql.org/docs/18/hstore.html#HSTORE-AUTHORS) Oleg Bartunov `<[oleg@sai.msu.su](mailto:oleg@sai.msu.su) >`, Moscow, Moscow University, Russia Teodor Sigaev `<[teodor@sigaev.ru](mailto:teodor@sigaev.ru) >`, Moscow, Delta-Soft Ltd., Russia Additional enhancements by Andrew Gierth `<[andrew@tao11.riddles.org.uk](mailto:andrew@tao11.riddles.org.uk) >`, United Kingdom * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/fuzzystrmatch.html "F.16. fuzzystrmatch — determine string similarities and distance") | [Up](https://www.postgresql.org/docs/18/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/18/intagg.html "F.18. intagg — integer aggregator and enumerator") | | F.16. fuzzystrmatch — determine string similarities and distance | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | F.18. intagg — integer aggregator and enumerator | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/hstore.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 43.2. Data Values in PL/Perl November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plperl-data.html "PostgreSQL 18 - 43.2. Data Values in PL/Perl") ([18](https://www.postgresql.org/docs/18/plperl-data.html "PostgreSQL 18 - 43.2. Data Values in PL/Perl") ) / [17](https://www.postgresql.org/docs/17/plperl-data.html "PostgreSQL 17 - 43.2. Data Values in PL/Perl") / [16](https://www.postgresql.org/docs/16/plperl-data.html "PostgreSQL 16 - 43.2. Data Values in PL/Perl") / [15](https://www.postgresql.org/docs/15/plperl-data.html "PostgreSQL 15 - 43.2. Data Values in PL/Perl") / [14](https://www.postgresql.org/docs/14/plperl-data.html "PostgreSQL 14 - 43.2. Data Values in PL/Perl") Development Versions: [devel](https://www.postgresql.org/docs/devel/plperl-data.html "PostgreSQL devel - 43.2. Data Values in PL/Perl") Unsupported versions: [13](https://www.postgresql.org/docs/13/plperl-data.html "PostgreSQL 13 - 43.2. Data Values in PL/Perl") / [12](https://www.postgresql.org/docs/12/plperl-data.html "PostgreSQL 12 - 43.2. Data Values in PL/Perl") / [11](https://www.postgresql.org/docs/11/plperl-data.html "PostgreSQL 11 - 43.2. Data Values in PL/Perl") / [10](https://www.postgresql.org/docs/10/plperl-data.html "PostgreSQL 10 - 43.2. Data Values in PL/Perl") / [9.6](https://www.postgresql.org/docs/9.6/plperl-data.html "PostgreSQL 9.6 - 43.2. Data Values in PL/Perl") / [9.5](https://www.postgresql.org/docs/9.5/plperl-data.html "PostgreSQL 9.5 - 43.2. Data Values in PL/Perl") / [9.4](https://www.postgresql.org/docs/9.4/plperl-data.html "PostgreSQL 9.4 - 43.2. Data Values in PL/Perl") / [9.3](https://www.postgresql.org/docs/9.3/plperl-data.html "PostgreSQL 9.3 - 43.2. Data Values in PL/Perl") / [9.2](https://www.postgresql.org/docs/9.2/plperl-data.html "PostgreSQL 9.2 - 43.2. Data Values in PL/Perl") / [9.1](https://www.postgresql.org/docs/9.1/plperl-data.html "PostgreSQL 9.1 - 43.2. Data Values in PL/Perl") / [9.0](https://www.postgresql.org/docs/9.0/plperl-data.html "PostgreSQL 9.0 - 43.2. Data Values in PL/Perl") / [8.4](https://www.postgresql.org/docs/8.4/plperl-data.html "PostgreSQL 8.4 - 43.2. Data Values in PL/Perl") / [8.3](https://www.postgresql.org/docs/8.3/plperl-data.html "PostgreSQL 8.3 - 43.2. Data Values in PL/Perl") / [8.2](https://www.postgresql.org/docs/8.2/plperl-data.html "PostgreSQL 8.2 - 43.2. Data Values in PL/Perl") / [8.1](https://www.postgresql.org/docs/8.1/plperl-data.html "PostgreSQL 8.1 - 43.2. Data Values in PL/Perl") / [8.0](https://www.postgresql.org/docs/8.0/plperl-data.html "PostgreSQL 8.0 - 43.2. Data Values in PL/Perl") / [7.4](https://www.postgresql.org/docs/7.4/plperl-data.html "PostgreSQL 7.4 - 43.2. Data Values in PL/Perl") / [7.3](https://www.postgresql.org/docs/7.3/plperl-data.html "PostgreSQL 7.3 - 43.2. Data Values in PL/Perl") | 43.2. Data Values in PL/Perl | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/plperl-funcs.html "43.1. PL/Perl Functions and Arguments") | [Up](https://www.postgresql.org/docs/18/plperl.html "Chapter 43. PL/Perl — Perl Procedural Language") | Chapter 43. PL/Perl — Perl Procedural Language | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/plperl-builtins.html "43.3. Built-in Functions") | * * * 43.2. Data Values in PL/Perl [#](https://www.postgresql.org/docs/18/plperl-data.html#PLPERL-DATA) -------------------------------------------------------------------------------------------------- The argument values supplied to a PL/Perl function's code are simply the input arguments converted to text form (just as if they had been displayed by a `SELECT` statement). Conversely, the `return` and `return_next` commands will accept any string that is acceptable input format for the function's declared return type. If this behavior is inconvenient for a particular case, it can be improved by using a transform, as already illustrated for `bool` values. Several examples of transform modules are included in the PostgreSQL distribution. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/plperl-funcs.html "43.1. PL/Perl Functions and Arguments") | [Up](https://www.postgresql.org/docs/18/plperl.html "Chapter 43. PL/Perl — Perl Procedural Language") | [Next](https://www.postgresql.org/docs/18/plperl-builtins.html "43.3. Built-in Functions") | | 43.1. PL/Perl Functions and Arguments | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 43.3. Built-in Functions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/plperl-data.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: pg_controldata November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/app-pgcontroldata.html "PostgreSQL 18 - pg_controldata") ([18](https://www.postgresql.org/docs/18/app-pgcontroldata.html "PostgreSQL 18 - pg_controldata") ) / [17](https://www.postgresql.org/docs/17/app-pgcontroldata.html "PostgreSQL 17 - pg_controldata") / [16](https://www.postgresql.org/docs/16/app-pgcontroldata.html "PostgreSQL 16 - pg_controldata") / [15](https://www.postgresql.org/docs/15/app-pgcontroldata.html "PostgreSQL 15 - pg_controldata") / [14](https://www.postgresql.org/docs/14/app-pgcontroldata.html "PostgreSQL 14 - pg_controldata") Development Versions: [devel](https://www.postgresql.org/docs/devel/app-pgcontroldata.html "PostgreSQL devel - pg_controldata") Unsupported versions: [13](https://www.postgresql.org/docs/13/app-pgcontroldata.html "PostgreSQL 13 - pg_controldata") / [12](https://www.postgresql.org/docs/12/app-pgcontroldata.html "PostgreSQL 12 - pg_controldata") / [11](https://www.postgresql.org/docs/11/app-pgcontroldata.html "PostgreSQL 11 - pg_controldata") / [10](https://www.postgresql.org/docs/10/app-pgcontroldata.html "PostgreSQL 10 - pg_controldata") / [9.6](https://www.postgresql.org/docs/9.6/app-pgcontroldata.html "PostgreSQL 9.6 - pg_controldata") / [9.5](https://www.postgresql.org/docs/9.5/app-pgcontroldata.html "PostgreSQL 9.5 - pg_controldata") / [9.4](https://www.postgresql.org/docs/9.4/app-pgcontroldata.html "PostgreSQL 9.4 - pg_controldata") / [9.3](https://www.postgresql.org/docs/9.3/app-pgcontroldata.html "PostgreSQL 9.3 - pg_controldata") / [9.2](https://www.postgresql.org/docs/9.2/app-pgcontroldata.html "PostgreSQL 9.2 - pg_controldata") / [9.1](https://www.postgresql.org/docs/9.1/app-pgcontroldata.html "PostgreSQL 9.1 - pg_controldata") / [9.0](https://www.postgresql.org/docs/9.0/app-pgcontroldata.html "PostgreSQL 9.0 - pg_controldata") / [8.4](https://www.postgresql.org/docs/8.4/app-pgcontroldata.html "PostgreSQL 8.4 - pg_controldata") / [8.3](https://www.postgresql.org/docs/8.3/app-pgcontroldata.html "PostgreSQL 8.3 - pg_controldata") / [8.2](https://www.postgresql.org/docs/8.2/app-pgcontroldata.html "PostgreSQL 8.2 - pg_controldata") / [8.1](https://www.postgresql.org/docs/8.1/app-pgcontroldata.html "PostgreSQL 8.1 - pg_controldata") / [8.0](https://www.postgresql.org/docs/8.0/app-pgcontroldata.html "PostgreSQL 8.0 - pg_controldata") / [7.4](https://www.postgresql.org/docs/7.4/app-pgcontroldata.html "PostgreSQL 7.4 - pg_controldata") / [7.3](https://www.postgresql.org/docs/7.3/app-pgcontroldata.html "PostgreSQL 7.3 - pg_controldata") | pg\_controldata | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/app-pgchecksums.html "pg_checksums") | [Up](https://www.postgresql.org/docs/18/reference-server.html "PostgreSQL Server Applications") | PostgreSQL Server Applications | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/app-pgcreatesubscriber.html "pg_createsubscriber") | * * * pg\_controldata --------------- pg\_controldata — display control information of a PostgreSQL database cluster Synopsis -------- `pg_controldata` \[_`option`_\] \[\[ `-D` | `--pgdata` \]_`datadir`_\] Description ----------- `pg_controldata` prints information initialized during `initdb`, such as the catalog version. It also shows information about write-ahead logging and checkpoint processing. This information is cluster-wide, and not specific to any one database. This utility can only be run by the user who initialized the cluster because it requires read access to the data directory. You can specify the data directory on the command line, or use the environment variable `PGDATA`. This utility supports the options `-V` and `--version`, which print the pg\_controldata version and exit. It also supports options `-?` and `--help`, which output the supported arguments. Environment ----------- `PGDATA` Default data directory location `PG_COLOR` Specifies whether to use color in diagnostic messages. Possible values are `always`, `auto` and `never`. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/app-pgchecksums.html "pg_checksums") | [Up](https://www.postgresql.org/docs/18/reference-server.html "PostgreSQL Server Applications") | [Next](https://www.postgresql.org/docs/18/app-pgcreatesubscriber.html "pg_createsubscriber") | | pg\_checksums | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | pg\_createsubscriber | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/app-pgcontroldata.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: F.17. hstore — hstore key/value datatype November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/hstore.html "PostgreSQL 18 - F.17. hstore — hstore key/value datatype") ([18](https://www.postgresql.org/docs/18/hstore.html "PostgreSQL 18 - F.17. hstore — hstore key/value datatype") ) / [17](https://www.postgresql.org/docs/17/hstore.html "PostgreSQL 17 - F.17. hstore — hstore key/value datatype") / [16](https://www.postgresql.org/docs/16/hstore.html "PostgreSQL 16 - F.17. hstore — hstore key/value datatype") / [15](https://www.postgresql.org/docs/15/hstore.html "PostgreSQL 15 - F.17. hstore — hstore key/value datatype") / [14](https://www.postgresql.org/docs/14/hstore.html "PostgreSQL 14 - F.17. hstore — hstore key/value datatype") Development Versions: [devel](https://www.postgresql.org/docs/devel/hstore.html "PostgreSQL devel - F.17. hstore — hstore key/value datatype") Unsupported versions: [13](https://www.postgresql.org/docs/13/hstore.html "PostgreSQL 13 - F.17. hstore — hstore key/value datatype") / [12](https://www.postgresql.org/docs/12/hstore.html "PostgreSQL 12 - F.17. hstore — hstore key/value datatype") / [11](https://www.postgresql.org/docs/11/hstore.html "PostgreSQL 11 - F.17. hstore — hstore key/value datatype") / [10](https://www.postgresql.org/docs/10/hstore.html "PostgreSQL 10 - F.17. hstore — hstore key/value datatype") / [9.6](https://www.postgresql.org/docs/9.6/hstore.html "PostgreSQL 9.6 - F.17. hstore — hstore key/value datatype") / [9.5](https://www.postgresql.org/docs/9.5/hstore.html "PostgreSQL 9.5 - F.17. hstore — hstore key/value datatype") / [9.4](https://www.postgresql.org/docs/9.4/hstore.html "PostgreSQL 9.4 - F.17. hstore — hstore key/value datatype") / [9.3](https://www.postgresql.org/docs/9.3/hstore.html "PostgreSQL 9.3 - F.17. hstore — hstore key/value datatype") / [9.2](https://www.postgresql.org/docs/9.2/hstore.html "PostgreSQL 9.2 - F.17. hstore — hstore key/value datatype") / [9.1](https://www.postgresql.org/docs/9.1/hstore.html "PostgreSQL 9.1 - F.17. hstore — hstore key/value datatype") / [9.0](https://www.postgresql.org/docs/9.0/hstore.html "PostgreSQL 9.0 - F.17. hstore — hstore key/value datatype") / [8.4](https://www.postgresql.org/docs/8.4/hstore.html "PostgreSQL 8.4 - F.17. hstore — hstore key/value datatype") / [8.3](https://www.postgresql.org/docs/8.3/hstore.html "PostgreSQL 8.3 - F.17. hstore — hstore key/value datatype") | F.17. hstore — hstore key/value datatype | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/fuzzystrmatch.html "F.16. fuzzystrmatch — determine string similarities and distance") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | Appendix F. Additional Supplied Modules and Extensions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/intagg.html "F.18. intagg — integer aggregator and enumerator") | * * * F.17. hstore — hstore key/value datatype [#](https://www.postgresql.org/docs/current/hstore.html#HSTORE) --------------------------------------------------------------------------------------------------------- [F.17.1. `hstore` External Representation](https://www.postgresql.org/docs/current/hstore.html#HSTORE-EXTERNAL-REP) [F.17.2. `hstore` Operators and Functions](https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS) [F.17.3. Indexes](https://www.postgresql.org/docs/current/hstore.html#HSTORE-INDEXES) [F.17.4. Examples](https://www.postgresql.org/docs/current/hstore.html#HSTORE-EXAMPLES) [F.17.5. Statistics](https://www.postgresql.org/docs/current/hstore.html#HSTORE-STATISTICS) [F.17.6. Compatibility](https://www.postgresql.org/docs/current/hstore.html#HSTORE-COMPATIBILITY) [F.17.7. Transforms](https://www.postgresql.org/docs/current/hstore.html#HSTORE-TRANSFORMS) [F.17.8. Authors](https://www.postgresql.org/docs/current/hstore.html#HSTORE-AUTHORS) This module implements the `hstore` data type for storing sets of key/value pairs within a single PostgreSQL value. This can be useful in various scenarios, such as rows with many attributes that are rarely examined, or semi-structured data. Keys and values are simply text strings. This module is considered “trusted”, that is, it can be installed by non-superusers who have `CREATE` privilege on the current database. ### F.17.1. `hstore` External Representation [#](https://www.postgresql.org/docs/current/hstore.html#HSTORE-EXTERNAL-REP) The text representation of an `hstore`, used for input and output, includes zero or more _`key`_ `=>` _`value`_ pairs separated by commas. Some examples: k => v foo => bar, baz => whatever "1-a" => "anything at all" The order of the pairs is not significant (and may not be reproduced on output). Whitespace between pairs or around the `=>` sign is ignored. Double-quote keys and values that include whitespace, commas, `=`s or `>`s. To include a double quote or a backslash in a key or value, escape it with a backslash. Each key in an `hstore` is unique. If you declare an `hstore` with duplicate keys, only one will be stored in the `hstore` and there is no guarantee as to which will be kept: SELECT 'a=>1,a=>2'::hstore; hstore ---------- "a"=>"1" A value (but not a key) can be an SQL `NULL`. For example: key => NULL The `NULL` keyword is case-insensitive. Double-quote the `NULL` to treat it as the ordinary string “NULL”. ### Note Keep in mind that the `hstore` text format, when used for input, applies _before_ any required quoting or escaping. If you are passing an `hstore` literal via a parameter, then no additional processing is needed. But if you're passing it as a quoted literal constant, then any single-quote characters and (depending on the setting of the `standard_conforming_strings` configuration parameter) backslash characters need to be escaped correctly. See [Section 4.1.2.1](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS "4.1.2.1. String Constants") for more on the handling of string constants. On output, double quotes always surround keys and values, even when it's not strictly necessary. ### F.17.2. `hstore` Operators and Functions [#](https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS) The operators provided by the `hstore` module are shown in [Table F.6](https://www.postgresql.org/docs/current/hstore.html#HSTORE-OP-TABLE "Table F.6. hstore Operators") , the functions in [Table F.7](https://www.postgresql.org/docs/current/hstore.html#HSTORE-FUNC-TABLE "Table F.7. hstore Functions") . **Table F.6. `hstore` Operators** | Operator

Description

Example(s) | | --- | | `hstore` `->` `text` → `text`

Returns value associated with given key, or `NULL` if not present.

`'a=>x, b=>y'::hstore -> 'a'` → `x` | | `hstore` `->` `text[]` → `text[]`

Returns values associated with given keys, or `NULL` if not present.

`'a=>x, b=>y, c=>z'::hstore -> ARRAY['c','a']` → `{"z","x"}` | | `hstore` `\|` `hstore` → `hstore`

Concatenates two `hstore`s.

`'a=>b, c=>d'::hstore \| 'c=>x, d=>q'::hstore` → `"a"=>"b", "c"=>"x", "d"=>"q"` | | `hstore` `?` `text` → `boolean`

Does `hstore` contain key?

`'a=>1'::hstore ? 'a'` → `t` | | `hstore` `?&` `text[]` → `boolean`

Does `hstore` contain all the specified keys?

`'a=>1,b=>2'::hstore ?& ARRAY['a','b']` → `t` | | `hstore` `?\|` `text[]` → `boolean`

Does `hstore` contain any of the specified keys?

`'a=>1,b=>2'::hstore ?\| ARRAY['b','c']` → `t` | | `hstore` `@>` `hstore` → `boolean`

Does left operand contain right?

`'a=>b, b=>1, c=>NULL'::hstore @> 'b=>1'` → `t` | | `hstore` `<@` `hstore` → `boolean`

Is left operand contained in right?

`'a=>c'::hstore <@ 'a=>b, b=>1, c=>NULL'` → `f` | | `hstore` `-` `text` → `hstore`

Deletes key from left operand.

`'a=>1, b=>2, c=>3'::hstore - 'b'::text` → `"a"=>"1", "c"=>"3"` | | `hstore` `-` `text[]` → `hstore`

Deletes keys from left operand.

`'a=>1, b=>2, c=>3'::hstore - ARRAY['a','b']` → `"c"=>"3"` | | `hstore` `-` `hstore` → `hstore`

Deletes pairs from left operand that match pairs in the right operand.

`'a=>1, b=>2, c=>3'::hstore - 'a=>4, b=>2'::hstore` → `"a"=>"1", "c"=>"3"` | | `anyelement` `#=` `hstore` → `anyelement`

Replaces fields in the left operand (which must be a composite type) with matching values from `hstore`.

`ROW(1,3) #= 'f1=>11'::hstore` → `(11,3)` | | `%%` `hstore` → `text[]`

Converts `hstore` to an array of alternating keys and values.

`%% 'a=>foo, b=>bar'::hstore` → `{a,foo,b,bar}` | | `%#` `hstore` → `text[]`

Converts `hstore` to a two-dimensional key/value array.

`%# 'a=>foo, b=>bar'::hstore` → `{{a,foo},{b,bar}}` | **Table F.7. `hstore` Functions** | Function

Description

Example(s) | | --- | | `hstore` ( `record` ) → `hstore`

Constructs an `hstore` from a record or row.

`hstore(ROW(1,2))` → `"f1"=>"1", "f2"=>"2"` | | `hstore` ( `text[]` ) → `hstore`

Constructs an `hstore` from an array, which may be either a key/value array, or a two-dimensional array.

`hstore(ARRAY['a','1','b','2'])` → `"a"=>"1", "b"=>"2"`

`hstore(ARRAY[['c','3'],['d','4']])` → `"c"=>"3", "d"=>"4"` | | `hstore` ( `text[]`, `text[]` ) → `hstore`

Constructs an `hstore` from separate key and value arrays.

`hstore(ARRAY['a','b'], ARRAY['1','2'])` → `"a"=>"1", "b"=>"2"` | | `hstore` ( `text`, `text` ) → `hstore`

Makes a single-item `hstore`.

`hstore('a', 'b')` → `"a"=>"b"` | | `akeys` ( `hstore` ) → `text[]`

Extracts an `hstore`'s keys as an array.

`akeys('a=>1,b=>2')` → `{a,b}` | | `skeys` ( `hstore` ) → `setof text`

Extracts an `hstore`'s keys as a set.

`skeys('a=>1,b=>2')` →

a
b | | `avals` ( `hstore` ) → `text[]`

Extracts an `hstore`'s values as an array.

`avals('a=>1,b=>2')` → `{1,2}` | | `svals` ( `hstore` ) → `setof text`

Extracts an `hstore`'s values as a set.

`svals('a=>1,b=>2')` →

1
2 | | `hstore_to_array` ( `hstore` ) → `text[]`

Extracts an `hstore`'s keys and values as an array of alternating keys and values.

`hstore_to_array('a=>1,b=>2')` → `{a,1,b,2}` | | `hstore_to_matrix` ( `hstore` ) → `text[]`

Extracts an `hstore`'s keys and values as a two-dimensional array.

`hstore_to_matrix('a=>1,b=>2')` → `{{a,1},{b,2}}` | | `hstore_to_json` ( `hstore` ) → `json`

Converts an `hstore` to a `json` value, converting all non-null values to JSON strings.

This function is used implicitly when an `hstore` value is cast to `json`.

`hstore_to_json('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": "1", "b": "t", "c": null, "d": "12345", "e": "012345", "f": "1.234", "g": "2.345e+4"}` | | `hstore_to_jsonb` ( `hstore` ) → `jsonb`

Converts an `hstore` to a `jsonb` value, converting all non-null values to JSON strings.

This function is used implicitly when an `hstore` value is cast to `jsonb`.

`hstore_to_jsonb('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": "1", "b": "t", "c": null, "d": "12345", "e": "012345", "f": "1.234", "g": "2.345e+4"}` | | `hstore_to_json_loose` ( `hstore` ) → `json`

Converts an `hstore` to a `json` value, but attempts to distinguish numerical and Boolean values so they are unquoted in the JSON.

`hstore_to_json_loose('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": 1, "b": true, "c": null, "d": 12345, "e": "012345", "f": 1.234, "g": 2.345e+4}` | | `hstore_to_jsonb_loose` ( `hstore` ) → `jsonb`

Converts an `hstore` to a `jsonb` value, but attempts to distinguish numerical and Boolean values so they are unquoted in the JSON.

`hstore_to_jsonb_loose('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": 1, "b": true, "c": null, "d": 12345, "e": "012345", "f": 1.234, "g": 2.345e+4}` | | `slice` ( `hstore`, `text[]` ) → `hstore`

Extracts a subset of an `hstore` containing only the specified keys.

`slice('a=>1,b=>2,c=>3'::hstore, ARRAY['b','c','x'])` → `"b"=>"2", "c"=>"3"` | | `each` ( `hstore` ) → `setof record` ( _`key`_ `text`, _`value`_ `text` )

Extracts an `hstore`'s keys and values as a set of records.

`select * from each('a=>1,b=>2')` →

key \| value
-----+-------
a \| 1
b \| 2 | | `exist` ( `hstore`, `text` ) → `boolean`

Does `hstore` contain key?

`exist('a=>1', 'a')` → `t` | | `defined` ( `hstore`, `text` ) → `boolean`

Does `hstore` contain a non-`NULL` value for key?

`defined('a=>NULL', 'a')` → `f` | | `delete` ( `hstore`, `text` ) → `hstore`

Deletes pair with matching key.

`delete('a=>1,b=>2', 'b')` → `"a"=>"1"` | | `delete` ( `hstore`, `text[]` ) → `hstore`

Deletes pairs with matching keys.

`delete('a=>1,b=>2,c=>3', ARRAY['a','b'])` → `"c"=>"3"` | | `delete` ( `hstore`, `hstore` ) → `hstore`

Deletes pairs matching those in the second argument.

`delete('a=>1,b=>2', 'a=>4,b=>2'::hstore)` → `"a"=>"1"` | | `populate_record` ( `anyelement`, `hstore` ) → `anyelement`

Replaces fields in the left operand (which must be a composite type) with matching values from `hstore`.

`populate_record(ROW(1,2), 'f1=>42'::hstore)` → `(42,2)` | In addition to these operators and functions, values of the `hstore` type can be subscripted, allowing them to act like associative arrays. Only a single subscript of type `text` can be specified; it is interpreted as a key and the corresponding value is fetched or stored. For example, CREATE TABLE mytable (h hstore); INSERT INTO mytable VALUES ('a=>b, c=>d'); SELECT h\['a'\] FROM mytable; h --- b (1 row) UPDATE mytable SET h\['c'\] = 'new'; SELECT h FROM mytable; h ---------------------- "a"=>"b", "c"=>"new" (1 row) A subscripted fetch returns `NULL` if the subscript is `NULL` or that key does not exist in the `hstore`. (Thus, a subscripted fetch is not greatly different from the `->` operator.) A subscripted update fails if the subscript is `NULL`; otherwise, it replaces the value for that key, adding an entry to the `hstore` if the key does not already exist. ### F.17.3. Indexes [#](https://www.postgresql.org/docs/current/hstore.html#HSTORE-INDEXES) `hstore` has GiST and GIN index support for the `@>`, `?`, `?&` and `?|` operators. For example: CREATE INDEX hidx ON testhstore USING GIST (h); CREATE INDEX hidx ON testhstore USING GIN (h); `gist_hstore_ops` GiST opclass approximates a set of key/value pairs as a bitmap signature. Its optional integer parameter `siglen` determines the signature length in bytes. The default length is 16 bytes. Valid values of signature length are between 1 and 2024 bytes. Longer signatures lead to a more precise search (scanning a smaller fraction of the index and fewer heap pages), at the cost of a larger index. Example of creating such an index with a signature length of 32 bytes: CREATE INDEX hidx ON testhstore USING GIST (h gist\_hstore\_ops(siglen=32)); `hstore` also supports `btree` or `hash` indexes for the `=` operator. This allows `hstore` columns to be declared `UNIQUE`, or to be used in `GROUP BY`, `ORDER BY` or `DISTINCT` expressions. The sort ordering for `hstore` values is not particularly useful, but these indexes may be useful for equivalence lookups. Create indexes for `=` comparisons as follows: CREATE INDEX hidx ON testhstore USING BTREE (h); CREATE INDEX hidx ON testhstore USING HASH (h); ### F.17.4. Examples [#](https://www.postgresql.org/docs/current/hstore.html#HSTORE-EXAMPLES) Add a key, or update an existing key with a new value: UPDATE tab SET h\['c'\] = '3'; Another way to do the same thing is: UPDATE tab SET h = h || hstore('c', '3'); If multiple keys are to be added or changed in one operation, the concatenation approach is more efficient than subscripting: UPDATE tab SET h = h || hstore(array\['q', 'w'\], array\['11', '12'\]); Delete a key: UPDATE tab SET h = delete(h, 'k1'); Convert a `record` to an `hstore`: CREATE TABLE test (col1 integer, col2 text, col3 text); INSERT INTO test VALUES (123, 'foo', 'bar'); SELECT hstore(t) FROM test AS t; hstore --------------------------------------------- "col1"=>"123", "col2"=>"foo", "col3"=>"bar" (1 row) Convert an `hstore` to a predefined `record` type: CREATE TABLE test (col1 integer, col2 text, col3 text); SELECT \* FROM populate\_record(null::test, '"col1"=>"456", "col2"=>"zzz"'); col1 | col2 | col3 ------+------+------ 456 | zzz | (1 row) Modify an existing record using the values from an `hstore`: CREATE TABLE test (col1 integer, col2 text, col3 text); INSERT INTO test VALUES (123, 'foo', 'bar'); SELECT (r).\* FROM (SELECT t #= '"col3"=>"baz"' AS r FROM test t) s; col1 | col2 | col3 ------+------+------ 123 | foo | baz (1 row) ### F.17.5. Statistics [#](https://www.postgresql.org/docs/current/hstore.html#HSTORE-STATISTICS) The `hstore` type, because of its intrinsic liberality, could contain a lot of different keys. Checking for valid keys is the task of the application. The following examples demonstrate several techniques for checking keys and obtaining statistics. Simple example: SELECT \* FROM each('aaa=>bq, b=>NULL, ""=>1'); Using a table: CREATE TABLE stat AS SELECT (each(h)).key, (each(h)).value FROM testhstore; Online statistics: SELECT key, count(\*) FROM (SELECT (each(h)).key FROM testhstore) AS stat GROUP BY key ORDER BY count DESC, key; key | count -----------+------- line | 883 query | 207 pos | 203 node | 202 space | 197 status | 195 public | 194 title | 190 org | 189 ................... ### F.17.6. Compatibility [#](https://www.postgresql.org/docs/current/hstore.html#HSTORE-COMPATIBILITY) As of PostgreSQL 9.0, `hstore` uses a different internal representation than previous versions. This presents no obstacle for dump/restore upgrades since the text representation (used in the dump) is unchanged. In the event of a binary upgrade, upward compatibility is maintained by having the new code recognize old-format data. This will entail a slight performance penalty when processing data that has not yet been modified by the new code. It is possible to force an upgrade of all values in a table column by doing an `UPDATE` statement as follows: UPDATE tablename SET hstorecol = hstorecol || ''; Another way to do it is: ALTER TABLE tablename ALTER hstorecol TYPE hstore USING hstorecol || ''; The `ALTER TABLE` method requires an `ACCESS EXCLUSIVE` lock on the table, but does not result in bloating the table with old row versions. ### F.17.7. Transforms [#](https://www.postgresql.org/docs/current/hstore.html#HSTORE-TRANSFORMS) Additional extensions are available that implement transforms for the `hstore` type for the languages PL/Perl and PL/Python. The extensions for PL/Perl are called `hstore_plperl` and `hstore_plperlu`, for trusted and untrusted PL/Perl. If you install these transforms and specify them when creating a function, `hstore` values are mapped to Perl hashes. The extension for PL/Python is called `hstore_plpython3u`. If you use it, `hstore` values are mapped to Python dictionaries. ### F.17.8. Authors [#](https://www.postgresql.org/docs/current/hstore.html#HSTORE-AUTHORS) Oleg Bartunov `<[oleg@sai.msu.su](mailto:oleg@sai.msu.su) >`, Moscow, Moscow University, Russia Teodor Sigaev `<[teodor@sigaev.ru](mailto:teodor@sigaev.ru) >`, Moscow, Delta-Soft Ltd., Russia Additional enhancements by Andrew Gierth `<[andrew@tao11.riddles.org.uk](mailto:andrew@tao11.riddles.org.uk) >`, United Kingdom * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/fuzzystrmatch.html "F.16. fuzzystrmatch — determine string similarities and distance") | [Up](https://www.postgresql.org/docs/current/contrib.html "Appendix F. Additional Supplied Modules and Extensions") | [Next](https://www.postgresql.org/docs/current/intagg.html "F.18. intagg — integer aggregator and enumerator") | | F.16. fuzzystrmatch — determine string similarities and distance | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | F.18. intagg — integer aggregator and enumerator | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/hstore.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: SPI_cursor_open November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/spi-spi-cursor-open.html "PostgreSQL 18 - SPI_cursor_open") ([18](https://www.postgresql.org/docs/18/spi-spi-cursor-open.html "PostgreSQL 18 - SPI_cursor_open") ) / [17](https://www.postgresql.org/docs/17/spi-spi-cursor-open.html "PostgreSQL 17 - SPI_cursor_open") / [16](https://www.postgresql.org/docs/16/spi-spi-cursor-open.html "PostgreSQL 16 - SPI_cursor_open") / [15](https://www.postgresql.org/docs/15/spi-spi-cursor-open.html "PostgreSQL 15 - SPI_cursor_open") / [14](https://www.postgresql.org/docs/14/spi-spi-cursor-open.html "PostgreSQL 14 - SPI_cursor_open") Development Versions: [devel](https://www.postgresql.org/docs/devel/spi-spi-cursor-open.html "PostgreSQL devel - SPI_cursor_open") Unsupported versions: [13](https://www.postgresql.org/docs/13/spi-spi-cursor-open.html "PostgreSQL 13 - SPI_cursor_open") / [12](https://www.postgresql.org/docs/12/spi-spi-cursor-open.html "PostgreSQL 12 - SPI_cursor_open") / [11](https://www.postgresql.org/docs/11/spi-spi-cursor-open.html "PostgreSQL 11 - SPI_cursor_open") / [10](https://www.postgresql.org/docs/10/spi-spi-cursor-open.html "PostgreSQL 10 - SPI_cursor_open") / [9.6](https://www.postgresql.org/docs/9.6/spi-spi-cursor-open.html "PostgreSQL 9.6 - SPI_cursor_open") / [9.5](https://www.postgresql.org/docs/9.5/spi-spi-cursor-open.html "PostgreSQL 9.5 - SPI_cursor_open") / [9.4](https://www.postgresql.org/docs/9.4/spi-spi-cursor-open.html "PostgreSQL 9.4 - SPI_cursor_open") / [9.3](https://www.postgresql.org/docs/9.3/spi-spi-cursor-open.html "PostgreSQL 9.3 - SPI_cursor_open") / [9.2](https://www.postgresql.org/docs/9.2/spi-spi-cursor-open.html "PostgreSQL 9.2 - SPI_cursor_open") / [9.1](https://www.postgresql.org/docs/9.1/spi-spi-cursor-open.html "PostgreSQL 9.1 - SPI_cursor_open") / [9.0](https://www.postgresql.org/docs/9.0/spi-spi-cursor-open.html "PostgreSQL 9.0 - SPI_cursor_open") / [8.4](https://www.postgresql.org/docs/8.4/spi-spi-cursor-open.html "PostgreSQL 8.4 - SPI_cursor_open") / [8.3](https://www.postgresql.org/docs/8.3/spi-spi-cursor-open.html "PostgreSQL 8.3 - SPI_cursor_open") / [8.2](https://www.postgresql.org/docs/8.2/spi-spi-cursor-open.html "PostgreSQL 8.2 - SPI_cursor_open") / [8.1](https://www.postgresql.org/docs/8.1/spi-spi-cursor-open.html "PostgreSQL 8.1 - SPI_cursor_open") / [8.0](https://www.postgresql.org/docs/8.0/spi-spi-cursor-open.html "PostgreSQL 8.0 - SPI_cursor_open") / [7.4](https://www.postgresql.org/docs/7.4/spi-spi-cursor-open.html "PostgreSQL 7.4 - SPI_cursor_open") | SPI\_cursor\_open | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-execp.html "SPI_execp") | [Up](https://www.postgresql.org/docs/18/spi-interface.html "45.1. Interface Functions") | 45.1. Interface Functions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/spi-spi-cursor-open-with-args.html "SPI_cursor_open_with_args") | * * * SPI\_cursor\_open ----------------- SPI\_cursor\_open — set up a cursor using a statement created with `SPI_prepare` Synopsis -------- Portal SPI\_cursor\_open(const char \* _`name`_, SPIPlanPtr _`plan`_, Datum \* _`values`_, const char \* _`nulls`_, bool _`read_only`_) Description ----------- `SPI_cursor_open` sets up a cursor (internally, a portal) that will execute a statement prepared by `SPI_prepare`. The parameters have the same meanings as the corresponding parameters to `SPI_execute_plan`. Using a cursor instead of executing the statement directly has two benefits. First, the result rows can be retrieved a few at a time, avoiding memory overrun for queries that return many rows. Second, a portal can outlive the current C function (it can, in fact, live to the end of the current transaction). Returning the portal name to the C function's caller provides a way of returning a row set as result. The passed-in parameter data will be copied into the cursor's portal, so it can be freed while the cursor still exists. Arguments --------- ``const char * _`name`_`` name for portal, or `NULL` to let the system select a name ``SPIPlanPtr _`plan`_`` prepared statement (returned by `SPI_prepare`) ``Datum * _`values`_`` An array of actual parameter values. Must have same length as the statement's number of arguments. ``const char * _`nulls`_`` An array describing which parameters are null. Must have same length as the statement's number of arguments. If _`nulls`_ is `NULL` then `SPI_cursor_open` assumes that no parameters are null. Otherwise, each entry of the _`nulls`_ array should be `' '` if the corresponding parameter value is non-null, or `'n'` if the corresponding parameter value is null. (In the latter case, the actual value in the corresponding _`values`_ entry doesn't matter.) Note that _`nulls`_ is not a text string, just an array: it does not need a `'\0'` terminator. ``bool _`read_only`_`` `true` for read-only execution Return Value ------------ Pointer to portal containing the cursor. Note there is no error return convention; any error will be reported via `elog`. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/spi-spi-execp.html "SPI_execp") | [Up](https://www.postgresql.org/docs/18/spi-interface.html "45.1. Interface Functions") | [Next](https://www.postgresql.org/docs/18/spi-spi-cursor-open-with-args.html "SPI_cursor_open_with_args") | | SPI\_execp | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | SPI\_cursor\_open\_with\_args | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/spi-spi-cursor-open.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 52.32. pg_namespace November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-namespace.html "PostgreSQL 18 - 52.32. pg_namespace") ([18](https://www.postgresql.org/docs/18/catalog-pg-namespace.html "PostgreSQL 18 - 52.32. pg_namespace") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-namespace.html "PostgreSQL 17 - 52.32. pg_namespace") / [16](https://www.postgresql.org/docs/16/catalog-pg-namespace.html "PostgreSQL 16 - 52.32. pg_namespace") / [15](https://www.postgresql.org/docs/15/catalog-pg-namespace.html "PostgreSQL 15 - 52.32. pg_namespace") / [14](https://www.postgresql.org/docs/14/catalog-pg-namespace.html "PostgreSQL 14 - 52.32. pg_namespace") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-namespace.html "PostgreSQL devel - 52.32. pg_namespace") Unsupported versions: [13](https://www.postgresql.org/docs/13/catalog-pg-namespace.html "PostgreSQL 13 - 52.32. pg_namespace") / [12](https://www.postgresql.org/docs/12/catalog-pg-namespace.html "PostgreSQL 12 - 52.32. pg_namespace") / [11](https://www.postgresql.org/docs/11/catalog-pg-namespace.html "PostgreSQL 11 - 52.32. pg_namespace") / [10](https://www.postgresql.org/docs/10/catalog-pg-namespace.html "PostgreSQL 10 - 52.32. pg_namespace") / [9.6](https://www.postgresql.org/docs/9.6/catalog-pg-namespace.html "PostgreSQL 9.6 - 52.32. pg_namespace") / [9.5](https://www.postgresql.org/docs/9.5/catalog-pg-namespace.html "PostgreSQL 9.5 - 52.32. pg_namespace") / [9.4](https://www.postgresql.org/docs/9.4/catalog-pg-namespace.html "PostgreSQL 9.4 - 52.32. pg_namespace") / [9.3](https://www.postgresql.org/docs/9.3/catalog-pg-namespace.html "PostgreSQL 9.3 - 52.32. pg_namespace") / [9.2](https://www.postgresql.org/docs/9.2/catalog-pg-namespace.html "PostgreSQL 9.2 - 52.32. pg_namespace") / [9.1](https://www.postgresql.org/docs/9.1/catalog-pg-namespace.html "PostgreSQL 9.1 - 52.32. pg_namespace") / [9.0](https://www.postgresql.org/docs/9.0/catalog-pg-namespace.html "PostgreSQL 9.0 - 52.32. pg_namespace") / [8.4](https://www.postgresql.org/docs/8.4/catalog-pg-namespace.html "PostgreSQL 8.4 - 52.32. pg_namespace") / [8.3](https://www.postgresql.org/docs/8.3/catalog-pg-namespace.html "PostgreSQL 8.3 - 52.32. pg_namespace") / [8.2](https://www.postgresql.org/docs/8.2/catalog-pg-namespace.html "PostgreSQL 8.2 - 52.32. pg_namespace") / [8.1](https://www.postgresql.org/docs/8.1/catalog-pg-namespace.html "PostgreSQL 8.1 - 52.32. pg_namespace") / [8.0](https://www.postgresql.org/docs/8.0/catalog-pg-namespace.html "PostgreSQL 8.0 - 52.32. pg_namespace") / [7.4](https://www.postgresql.org/docs/7.4/catalog-pg-namespace.html "PostgreSQL 7.4 - 52.32. pg_namespace") / [7.3](https://www.postgresql.org/docs/7.3/catalog-pg-namespace.html "PostgreSQL 7.3 - 52.32. pg_namespace") | 52.32. `pg_namespace` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-largeobject-metadata.html "52.31. pg_largeobject_metadata") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/catalog-pg-opclass.html "52.33. pg_opclass") | * * * 52.32. `pg_namespace` [#](https://www.postgresql.org/docs/current/catalog-pg-namespace.html#CATALOG-PG-NAMESPACE) ------------------------------------------------------------------------------------------------------------------ The catalog `pg_namespace` stores namespaces. A namespace is the structure underlying SQL schemas: each namespace can have a separate collection of relations, types, etc. without name conflicts. **Table 52.32. `pg_namespace` Columns** | Column Type

Description | | --- | | `oid` `oid`

Row identifier | | `nspname` `name`

Name of the namespace | | `nspowner` `oid` (references [`pg_authid`](https://www.postgresql.org/docs/current/catalog-pg-authid.html "52.8. pg_authid")
.`oid`)

Owner of the namespace | | `nspacl` `aclitem[]`

Access privileges; see [Section 5.8](https://www.postgresql.org/docs/current/ddl-priv.html "5.8. Privileges")
for details | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-largeobject-metadata.html "52.31. pg_largeobject_metadata") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/current/catalog-pg-opclass.html "52.33. pg_opclass") | | 52.31. `pg_largeobject_metadata` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 52.33. `pg_opclass` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/catalog-pg-namespace.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 5.1. Table Basics November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/ddl-basics.html "PostgreSQL 18 - 5.1. Table Basics") ([18](https://www.postgresql.org/docs/18/ddl-basics.html "PostgreSQL 18 - 5.1. Table Basics") ) / [17](https://www.postgresql.org/docs/17/ddl-basics.html "PostgreSQL 17 - 5.1. Table Basics") / [16](https://www.postgresql.org/docs/16/ddl-basics.html "PostgreSQL 16 - 5.1. Table Basics") / [15](https://www.postgresql.org/docs/15/ddl-basics.html "PostgreSQL 15 - 5.1. Table Basics") / [14](https://www.postgresql.org/docs/14/ddl-basics.html "PostgreSQL 14 - 5.1. Table Basics") Development Versions: [devel](https://www.postgresql.org/docs/devel/ddl-basics.html "PostgreSQL devel - 5.1. Table Basics") Unsupported versions: [13](https://www.postgresql.org/docs/13/ddl-basics.html "PostgreSQL 13 - 5.1. Table Basics") / [12](https://www.postgresql.org/docs/12/ddl-basics.html "PostgreSQL 12 - 5.1. Table Basics") / [11](https://www.postgresql.org/docs/11/ddl-basics.html "PostgreSQL 11 - 5.1. Table Basics") / [10](https://www.postgresql.org/docs/10/ddl-basics.html "PostgreSQL 10 - 5.1. Table Basics") / [9.6](https://www.postgresql.org/docs/9.6/ddl-basics.html "PostgreSQL 9.6 - 5.1. Table Basics") / [9.5](https://www.postgresql.org/docs/9.5/ddl-basics.html "PostgreSQL 9.5 - 5.1. Table Basics") / [9.4](https://www.postgresql.org/docs/9.4/ddl-basics.html "PostgreSQL 9.4 - 5.1. Table Basics") / [9.3](https://www.postgresql.org/docs/9.3/ddl-basics.html "PostgreSQL 9.3 - 5.1. Table Basics") / [9.2](https://www.postgresql.org/docs/9.2/ddl-basics.html "PostgreSQL 9.2 - 5.1. Table Basics") / [9.1](https://www.postgresql.org/docs/9.1/ddl-basics.html "PostgreSQL 9.1 - 5.1. Table Basics") / [9.0](https://www.postgresql.org/docs/9.0/ddl-basics.html "PostgreSQL 9.0 - 5.1. Table Basics") / [8.4](https://www.postgresql.org/docs/8.4/ddl-basics.html "PostgreSQL 8.4 - 5.1. Table Basics") / [8.3](https://www.postgresql.org/docs/8.3/ddl-basics.html "PostgreSQL 8.3 - 5.1. Table Basics") / [8.2](https://www.postgresql.org/docs/8.2/ddl-basics.html "PostgreSQL 8.2 - 5.1. Table Basics") | 5.1. Table Basics | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/ddl.html "Chapter 5. Data Definition") | [Up](https://www.postgresql.org/docs/18/ddl.html "Chapter 5. Data Definition") | Chapter 5. Data Definition | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/ddl-default.html "5.2. Default Values") | * * * 5.1. Table Basics [#](https://www.postgresql.org/docs/18/ddl-basics.html#DDL-BASICS) ------------------------------------------------------------------------------------- A table in a relational database is much like a table on paper: It consists of rows and columns. The number and order of the columns is fixed, and each column has a name. The number of rows is variable — it reflects how much data is stored at a given moment. SQL does not make any guarantees about the order of the rows in a table. When a table is read, the rows will appear in an unspecified order, unless sorting is explicitly requested. This is covered in [Chapter 7](https://www.postgresql.org/docs/18/queries.html "Chapter 7. Queries") . Furthermore, SQL does not assign unique identifiers to rows, so it is possible to have several completely identical rows in a table. This is a consequence of the mathematical model that underlies SQL but is usually not desirable. Later in this chapter we will see how to deal with this issue. Each column has a data type. The data type constrains the set of possible values that can be assigned to a column and assigns semantics to the data stored in the column so that it can be used for computations. For instance, a column declared to be of a numerical type will not accept arbitrary text strings, and the data stored in such a column can be used for mathematical computations. By contrast, a column declared to be of a character string type will accept almost any kind of data but it does not lend itself to mathematical calculations, although other operations such as string concatenation are available. PostgreSQL includes a sizable set of built-in data types that fit many applications. Users can also define their own data types. Most built-in data types have obvious names and semantics, so we defer a detailed explanation to [Chapter 8](https://www.postgresql.org/docs/18/datatype.html "Chapter 8. Data Types") . Some of the frequently used data types are `integer` for whole numbers, `numeric` for possibly fractional numbers, `text` for character strings, `date` for dates, `time` for time-of-day values, and `timestamp` for values containing both date and time. To create a table, you use the aptly named [CREATE TABLE](https://www.postgresql.org/docs/18/sql-createtable.html "CREATE TABLE") command. In this command you specify at least a name for the new table, the names of the columns and the data type of each column. For example: CREATE TABLE my\_first\_table ( first\_column text, second\_column integer ); This creates a table named `my_first_table` with two columns. The first column is named `first_column` and has a data type of `text`; the second column has the name `second_column` and the type `integer`. The table and column names follow the identifier syntax explained in [Section 4.1.1](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS "4.1.1. Identifiers and Key Words") . The type names are usually also identifiers, but there are some exceptions. Note that the column list is comma-separated and surrounded by parentheses. Of course, the previous example was heavily contrived. Normally, you would give names to your tables and columns that convey what kind of data they store. So let's look at a more realistic example: CREATE TABLE products ( product\_no integer, name text, price numeric ); (The `numeric` type can store fractional components, as would be typical of monetary amounts.) ### Tip When you create many interrelated tables it is wise to choose a consistent naming pattern for the tables and columns. For instance, there is a choice of using singular or plural nouns for table names, both of which are favored by some theorist or other. There is a limit on how many columns a table can contain. Depending on the column types, it is between 250 and 1600. However, defining a table with anywhere near this many columns is highly unusual and often a questionable design. If you no longer need a table, you can remove it using the [DROP TABLE](https://www.postgresql.org/docs/18/sql-droptable.html "DROP TABLE") command. For example: DROP TABLE my\_first\_table; DROP TABLE products; Attempting to drop a table that does not exist is an error. Nevertheless, it is common in SQL script files to unconditionally try to drop each table before creating it, ignoring any error messages, so that the script works whether or not the table exists. (If you like, you can use the `DROP TABLE IF EXISTS` variant to avoid the error messages, but this is not standard SQL.) If you need to modify a table that already exists, see [Section 5.7](https://www.postgresql.org/docs/18/ddl-alter.html "5.7. Modifying Tables") later in this chapter. With the tools discussed so far you can create fully functional tables. The remainder of this chapter is concerned with adding features to the table definition to ensure data integrity, security, or convenience. If you are eager to fill your tables with data now you can skip ahead to [Chapter 6](https://www.postgresql.org/docs/18/dml.html "Chapter 6. Data Manipulation") and read the rest of this chapter later. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/ddl.html "Chapter 5. Data Definition") | [Up](https://www.postgresql.org/docs/18/ddl.html "Chapter 5. Data Definition") | [Next](https://www.postgresql.org/docs/18/ddl-default.html "5.2. Default Values") | | Chapter 5. Data Definition | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 5.2. Default Values | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/ddl-basics.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 33.3. Client Interfaces November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/lo-interfaces.html "PostgreSQL 18 - 33.3. Client Interfaces") ([18](https://www.postgresql.org/docs/18/lo-interfaces.html "PostgreSQL 18 - 33.3. Client Interfaces") ) / [17](https://www.postgresql.org/docs/17/lo-interfaces.html "PostgreSQL 17 - 33.3. Client Interfaces") / [16](https://www.postgresql.org/docs/16/lo-interfaces.html "PostgreSQL 16 - 33.3. Client Interfaces") / [15](https://www.postgresql.org/docs/15/lo-interfaces.html "PostgreSQL 15 - 33.3. Client Interfaces") / [14](https://www.postgresql.org/docs/14/lo-interfaces.html "PostgreSQL 14 - 33.3. Client Interfaces") Development Versions: [devel](https://www.postgresql.org/docs/devel/lo-interfaces.html "PostgreSQL devel - 33.3. Client Interfaces") Unsupported versions: [13](https://www.postgresql.org/docs/13/lo-interfaces.html "PostgreSQL 13 - 33.3. Client Interfaces") / [12](https://www.postgresql.org/docs/12/lo-interfaces.html "PostgreSQL 12 - 33.3. Client Interfaces") / [11](https://www.postgresql.org/docs/11/lo-interfaces.html "PostgreSQL 11 - 33.3. Client Interfaces") / [10](https://www.postgresql.org/docs/10/lo-interfaces.html "PostgreSQL 10 - 33.3. Client Interfaces") / [9.6](https://www.postgresql.org/docs/9.6/lo-interfaces.html "PostgreSQL 9.6 - 33.3. Client Interfaces") / [9.5](https://www.postgresql.org/docs/9.5/lo-interfaces.html "PostgreSQL 9.5 - 33.3. Client Interfaces") / [9.4](https://www.postgresql.org/docs/9.4/lo-interfaces.html "PostgreSQL 9.4 - 33.3. Client Interfaces") / [9.3](https://www.postgresql.org/docs/9.3/lo-interfaces.html "PostgreSQL 9.3 - 33.3. Client Interfaces") / [9.2](https://www.postgresql.org/docs/9.2/lo-interfaces.html "PostgreSQL 9.2 - 33.3. Client Interfaces") / [9.1](https://www.postgresql.org/docs/9.1/lo-interfaces.html "PostgreSQL 9.1 - 33.3. Client Interfaces") / [9.0](https://www.postgresql.org/docs/9.0/lo-interfaces.html "PostgreSQL 9.0 - 33.3. Client Interfaces") / [8.4](https://www.postgresql.org/docs/8.4/lo-interfaces.html "PostgreSQL 8.4 - 33.3. Client Interfaces") / [8.3](https://www.postgresql.org/docs/8.3/lo-interfaces.html "PostgreSQL 8.3 - 33.3. Client Interfaces") / [8.2](https://www.postgresql.org/docs/8.2/lo-interfaces.html "PostgreSQL 8.2 - 33.3. Client Interfaces") / [8.1](https://www.postgresql.org/docs/8.1/lo-interfaces.html "PostgreSQL 8.1 - 33.3. Client Interfaces") / [8.0](https://www.postgresql.org/docs/8.0/lo-interfaces.html "PostgreSQL 8.0 - 33.3. Client Interfaces") / [7.4](https://www.postgresql.org/docs/7.4/lo-interfaces.html "PostgreSQL 7.4 - 33.3. Client Interfaces") / [7.3](https://www.postgresql.org/docs/7.3/lo-interfaces.html "PostgreSQL 7.3 - 33.3. Client Interfaces") / [7.2](https://www.postgresql.org/docs/7.2/lo-interfaces.html "PostgreSQL 7.2 - 33.3. Client Interfaces") / [7.1](https://www.postgresql.org/docs/7.1/lo-interfaces.html "PostgreSQL 7.1 - 33.3. Client Interfaces") | 33.3. Client Interfaces | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/lo-implementation.html "33.2. Implementation Features") | [Up](https://www.postgresql.org/docs/current/largeobjects.html "Chapter 33. Large Objects") | Chapter 33. Large Objects | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/lo-funcs.html "33.4. Server-Side Functions") | * * * 33.3. Client Interfaces [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-INTERFACES) ------------------------------------------------------------------------------------------------------ [33.3.1. Creating a Large Object](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-CREATE) [33.3.2. Importing a Large Object](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-IMPORT) [33.3.3. Exporting a Large Object](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-EXPORT) [33.3.4. Opening an Existing Large Object](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-OPEN) [33.3.5. Writing Data to a Large Object](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-WRITE) [33.3.6. Reading Data from a Large Object](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-READ) [33.3.7. Seeking in a Large Object](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-SEEK) [33.3.8. Obtaining the Seek Position of a Large Object](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-TELL) [33.3.9. Truncating a Large Object](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-TRUNCATE) [33.3.10. Closing a Large Object Descriptor](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-CLOSE) [33.3.11. Removing a Large Object](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-UNLINK) This section describes the facilities that PostgreSQL's libpq client interface library provides for accessing large objects. The PostgreSQL large object interface is modeled after the Unix file-system interface, with analogues of `open`, `read`, `write`, `lseek`, etc. All large object manipulation using these functions _must_ take place within an SQL transaction block, since large object file descriptors are only valid for the duration of a transaction. Write operations, including `lo_open` with the `INV_WRITE` mode, are not allowed in a read-only transaction. If an error occurs while executing any one of these functions, the function will return an otherwise-impossible value, typically 0 or -1. A message describing the error is stored in the connection object and can be retrieved with [`PQerrorMessage`](https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQERRORMESSAGE) . Client applications that use these functions should include the header file `libpq/libpq-fs.h` and link with the libpq library. Client applications cannot use these functions while a libpq connection is in pipeline mode. ### 33.3.1. Creating a Large Object [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-CREATE) The function Oid lo\_create(PGconn \*conn, Oid lobjId); creates a new large object. The OID to be assigned can be specified by _`lobjId`_; if so, failure occurs if that OID is already in use for some large object. If _`lobjId`_ is `InvalidOid` (zero) then `lo_create` assigns an unused OID. The return value is the OID that was assigned to the new large object, or `InvalidOid` (zero) on failure. An example: inv\_oid = lo\_create(conn, desired\_oid); The older function Oid lo\_creat(PGconn \*conn, int mode); also creates a new large object, always assigning an unused OID. The return value is the OID that was assigned to the new large object, or `InvalidOid` (zero) on failure. In PostgreSQL releases 8.1 and later, the _`mode`_ is ignored, so that `lo_creat` is exactly equivalent to `lo_create` with a zero second argument. However, there is little reason to use `lo_creat` unless you need to work with servers older than 8.1. To work with such an old server, you must use `lo_creat` not `lo_create`, and you must set _`mode`_ to one of `INV_READ`, `INV_WRITE`, or `INV_READ` `|` `INV_WRITE`. (These symbolic constants are defined in the header file `libpq/libpq-fs.h`.) An example: inv\_oid = lo\_creat(conn, INV\_READ|INV\_WRITE); ### 33.3.2. Importing a Large Object [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-IMPORT) To import an operating system file as a large object, call Oid lo\_import(PGconn \*conn, const char \*filename); _`filename`_ specifies the operating system name of the file to be imported as a large object. The return value is the OID that was assigned to the new large object, or `InvalidOid` (zero) on failure. Note that the file is read by the client interface library, not by the server; so it must exist in the client file system and be readable by the client application. The function Oid lo\_import\_with\_oid(PGconn \*conn, const char \*filename, Oid lobjId); also imports a new large object. The OID to be assigned can be specified by _`lobjId`_; if so, failure occurs if that OID is already in use for some large object. If _`lobjId`_ is `InvalidOid` (zero) then `lo_import_with_oid` assigns an unused OID (this is the same behavior as `lo_import`). The return value is the OID that was assigned to the new large object, or `InvalidOid` (zero) on failure. `lo_import_with_oid` is new as of PostgreSQL 8.4 and uses `lo_create` internally which is new in 8.1; if this function is run against 8.0 or before, it will fail and return `InvalidOid`. ### 33.3.3. Exporting a Large Object [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-EXPORT) To export a large object into an operating system file, call int lo\_export(PGconn \*conn, Oid lobjId, const char \*filename); The _`lobjId`_ argument specifies the OID of the large object to export and the _`filename`_ argument specifies the operating system name of the file. Note that the file is written by the client interface library, not by the server. Returns 1 on success, -1 on failure. ### 33.3.4. Opening an Existing Large Object [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-OPEN) To open an existing large object for reading or writing, call int lo\_open(PGconn \*conn, Oid lobjId, int mode); The _`lobjId`_ argument specifies the OID of the large object to open. The _`mode`_ bits control whether the object is opened for reading (`INV_READ`), writing (`INV_WRITE`), or both. (These symbolic constants are defined in the header file `libpq/libpq-fs.h`.) `lo_open` returns a (non-negative) large object descriptor for later use in `lo_read`, `lo_write`, `lo_lseek`, `lo_lseek64`, `lo_tell`, `lo_tell64`, `lo_truncate`, `lo_truncate64`, and `lo_close`. The descriptor is only valid for the duration of the current transaction. On failure, -1 is returned. The server currently does not distinguish between modes `INV_WRITE` and `INV_READ` `|` `INV_WRITE`: you are allowed to read from the descriptor in either case. However there is a significant difference between these modes and `INV_READ` alone: with `INV_READ` you cannot write on the descriptor, and the data read from it will reflect the contents of the large object at the time of the transaction snapshot that was active when `lo_open` was executed, regardless of later writes by this or other transactions. Reading from a descriptor opened with `INV_WRITE` returns data that reflects all writes of other committed transactions as well as writes of the current transaction. This is similar to the behavior of `REPEATABLE READ` versus `READ COMMITTED` transaction modes for ordinary SQL `SELECT` commands. `lo_open` will fail if `SELECT` privilege is not available for the large object, or if `INV_WRITE` is specified and `UPDATE` privilege is not available. (Prior to PostgreSQL 11, these privilege checks were instead performed at the first actual read or write call using the descriptor.) These privilege checks can be disabled with the [lo\_compat\_privileges](https://www.postgresql.org/docs/current/runtime-config-compatible.html#GUC-LO-COMPAT-PRIVILEGES) run-time parameter. An example: inv\_fd = lo\_open(conn, inv\_oid, INV\_READ|INV\_WRITE); ### 33.3.5. Writing Data to a Large Object [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-WRITE) The function int lo\_write(PGconn \*conn, int fd, const char \*buf, size\_t len); writes _`len`_ bytes from _`buf`_ (which must be of size _`len`_) to large object descriptor _`fd`_. The _`fd`_ argument must have been returned by a previous `lo_open`. The number of bytes actually written is returned (in the current implementation, this will always equal _`len`_ unless there is an error). In the event of an error, the return value is -1. Although the _`len`_ parameter is declared as `size_t`, this function will reject length values larger than `INT_MAX`. In practice, it's best to transfer data in chunks of at most a few megabytes anyway. ### 33.3.6. Reading Data from a Large Object [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-READ) The function int lo\_read(PGconn \*conn, int fd, char \*buf, size\_t len); reads up to _`len`_ bytes from large object descriptor _`fd`_ into _`buf`_ (which must be of size _`len`_). The _`fd`_ argument must have been returned by a previous `lo_open`. The number of bytes actually read is returned; this will be less than _`len`_ if the end of the large object is reached first. In the event of an error, the return value is -1. Although the _`len`_ parameter is declared as `size_t`, this function will reject length values larger than `INT_MAX`. In practice, it's best to transfer data in chunks of at most a few megabytes anyway. ### 33.3.7. Seeking in a Large Object [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-SEEK) To change the current read or write location associated with a large object descriptor, call int lo\_lseek(PGconn \*conn, int fd, int offset, int whence); This function moves the current location pointer for the large object descriptor identified by _`fd`_ to the new location specified by _`offset`_. The valid values for _`whence`_ are `SEEK_SET` (seek from object start), `SEEK_CUR` (seek from current position), and `SEEK_END` (seek from object end). The return value is the new location pointer, or -1 on error. When dealing with large objects that might exceed 2GB in size, instead use int64\_t lo\_lseek64(PGconn \*conn, int fd, int64\_t offset, int whence); This function has the same behavior as `lo_lseek`, but it can accept an _`offset`_ larger than 2GB and/or deliver a result larger than 2GB. Note that `lo_lseek` will fail if the new location pointer would be greater than 2GB. `lo_lseek64` is new as of PostgreSQL 9.3. If this function is run against an older server version, it will fail and return -1. ### 33.3.8. Obtaining the Seek Position of a Large Object [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-TELL) To obtain the current read or write location of a large object descriptor, call int lo\_tell(PGconn \*conn, int fd); If there is an error, the return value is -1. When dealing with large objects that might exceed 2GB in size, instead use int64\_t lo\_tell64(PGconn \*conn, int fd); This function has the same behavior as `lo_tell`, but it can deliver a result larger than 2GB. Note that `lo_tell` will fail if the current read/write location is greater than 2GB. `lo_tell64` is new as of PostgreSQL 9.3. If this function is run against an older server version, it will fail and return -1. ### 33.3.9. Truncating a Large Object [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-TRUNCATE) To truncate a large object to a given length, call int lo\_truncate(PGconn \*conn, int fd, size\_t len); This function truncates the large object descriptor _`fd`_ to length _`len`_. The _`fd`_ argument must have been returned by a previous `lo_open`. If _`len`_ is greater than the large object's current length, the large object is extended to the specified length with null bytes ('\\0'). On success, `lo_truncate` returns zero. On error, the return value is -1. The read/write location associated with the descriptor _`fd`_ is not changed. Although the _`len`_ parameter is declared as `size_t`, `lo_truncate` will reject length values larger than `INT_MAX`. When dealing with large objects that might exceed 2GB in size, instead use int lo\_truncate64(PGconn \*conn, int fd, int64\_t len); This function has the same behavior as `lo_truncate`, but it can accept a _`len`_ value exceeding 2GB. `lo_truncate` is new as of PostgreSQL 8.3; if this function is run against an older server version, it will fail and return -1. `lo_truncate64` is new as of PostgreSQL 9.3; if this function is run against an older server version, it will fail and return -1. ### 33.3.10. Closing a Large Object Descriptor [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-CLOSE) A large object descriptor can be closed by calling int lo\_close(PGconn \*conn, int fd); where _`fd`_ is a large object descriptor returned by `lo_open`. On success, `lo_close` returns zero. On error, the return value is -1. Any large object descriptors that remain open at the end of a transaction will be closed automatically. ### 33.3.11. Removing a Large Object [#](https://www.postgresql.org/docs/current/lo-interfaces.html#LO-UNLINK) To remove a large object from the database, call int lo\_unlink(PGconn \*conn, Oid lobjId); The _`lobjId`_ argument specifies the OID of the large object to remove. Returns 1 if successful, -1 on failure. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/lo-implementation.html "33.2. Implementation Features") | [Up](https://www.postgresql.org/docs/current/largeobjects.html "Chapter 33. Large Objects") | [Next](https://www.postgresql.org/docs/current/lo-funcs.html "33.4. Server-Side Functions") | | 33.2. Implementation Features | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 33.4. Server-Side Functions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/lo-interfaces.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 33.3. Client Interfaces November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/lo-interfaces.html "PostgreSQL 18 - 33.3. Client Interfaces") ([18](https://www.postgresql.org/docs/18/lo-interfaces.html "PostgreSQL 18 - 33.3. Client Interfaces") ) / [17](https://www.postgresql.org/docs/17/lo-interfaces.html "PostgreSQL 17 - 33.3. Client Interfaces") / [16](https://www.postgresql.org/docs/16/lo-interfaces.html "PostgreSQL 16 - 33.3. Client Interfaces") / [15](https://www.postgresql.org/docs/15/lo-interfaces.html "PostgreSQL 15 - 33.3. Client Interfaces") / [14](https://www.postgresql.org/docs/14/lo-interfaces.html "PostgreSQL 14 - 33.3. Client Interfaces") Development Versions: [devel](https://www.postgresql.org/docs/devel/lo-interfaces.html "PostgreSQL devel - 33.3. Client Interfaces") Unsupported versions: [13](https://www.postgresql.org/docs/13/lo-interfaces.html "PostgreSQL 13 - 33.3. Client Interfaces") / [12](https://www.postgresql.org/docs/12/lo-interfaces.html "PostgreSQL 12 - 33.3. Client Interfaces") / [11](https://www.postgresql.org/docs/11/lo-interfaces.html "PostgreSQL 11 - 33.3. Client Interfaces") / [10](https://www.postgresql.org/docs/10/lo-interfaces.html "PostgreSQL 10 - 33.3. Client Interfaces") / [9.6](https://www.postgresql.org/docs/9.6/lo-interfaces.html "PostgreSQL 9.6 - 33.3. Client Interfaces") / [9.5](https://www.postgresql.org/docs/9.5/lo-interfaces.html "PostgreSQL 9.5 - 33.3. Client Interfaces") / [9.4](https://www.postgresql.org/docs/9.4/lo-interfaces.html "PostgreSQL 9.4 - 33.3. Client Interfaces") / [9.3](https://www.postgresql.org/docs/9.3/lo-interfaces.html "PostgreSQL 9.3 - 33.3. Client Interfaces") / [9.2](https://www.postgresql.org/docs/9.2/lo-interfaces.html "PostgreSQL 9.2 - 33.3. Client Interfaces") / [9.1](https://www.postgresql.org/docs/9.1/lo-interfaces.html "PostgreSQL 9.1 - 33.3. Client Interfaces") / [9.0](https://www.postgresql.org/docs/9.0/lo-interfaces.html "PostgreSQL 9.0 - 33.3. Client Interfaces") / [8.4](https://www.postgresql.org/docs/8.4/lo-interfaces.html "PostgreSQL 8.4 - 33.3. Client Interfaces") / [8.3](https://www.postgresql.org/docs/8.3/lo-interfaces.html "PostgreSQL 8.3 - 33.3. Client Interfaces") / [8.2](https://www.postgresql.org/docs/8.2/lo-interfaces.html "PostgreSQL 8.2 - 33.3. Client Interfaces") / [8.1](https://www.postgresql.org/docs/8.1/lo-interfaces.html "PostgreSQL 8.1 - 33.3. Client Interfaces") / [8.0](https://www.postgresql.org/docs/8.0/lo-interfaces.html "PostgreSQL 8.0 - 33.3. Client Interfaces") / [7.4](https://www.postgresql.org/docs/7.4/lo-interfaces.html "PostgreSQL 7.4 - 33.3. Client Interfaces") / [7.3](https://www.postgresql.org/docs/7.3/lo-interfaces.html "PostgreSQL 7.3 - 33.3. Client Interfaces") / [7.2](https://www.postgresql.org/docs/7.2/lo-interfaces.html "PostgreSQL 7.2 - 33.3. Client Interfaces") / [7.1](https://www.postgresql.org/docs/7.1/lo-interfaces.html "PostgreSQL 7.1 - 33.3. Client Interfaces") | 33.3. Client Interfaces | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/lo-implementation.html "33.2. Implementation Features") | [Up](https://www.postgresql.org/docs/18/largeobjects.html "Chapter 33. Large Objects") | Chapter 33. Large Objects | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/lo-funcs.html "33.4. Server-Side Functions") | * * * 33.3. Client Interfaces [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-INTERFACES) ------------------------------------------------------------------------------------------------- [33.3.1. Creating a Large Object](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-CREATE) [33.3.2. Importing a Large Object](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-IMPORT) [33.3.3. Exporting a Large Object](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-EXPORT) [33.3.4. Opening an Existing Large Object](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-OPEN) [33.3.5. Writing Data to a Large Object](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-WRITE) [33.3.6. Reading Data from a Large Object](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-READ) [33.3.7. Seeking in a Large Object](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-SEEK) [33.3.8. Obtaining the Seek Position of a Large Object](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-TELL) [33.3.9. Truncating a Large Object](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-TRUNCATE) [33.3.10. Closing a Large Object Descriptor](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-CLOSE) [33.3.11. Removing a Large Object](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-UNLINK) This section describes the facilities that PostgreSQL's libpq client interface library provides for accessing large objects. The PostgreSQL large object interface is modeled after the Unix file-system interface, with analogues of `open`, `read`, `write`, `lseek`, etc. All large object manipulation using these functions _must_ take place within an SQL transaction block, since large object file descriptors are only valid for the duration of a transaction. Write operations, including `lo_open` with the `INV_WRITE` mode, are not allowed in a read-only transaction. If an error occurs while executing any one of these functions, the function will return an otherwise-impossible value, typically 0 or -1. A message describing the error is stored in the connection object and can be retrieved with [`PQerrorMessage`](https://www.postgresql.org/docs/18/libpq-status.html#LIBPQ-PQERRORMESSAGE) . Client applications that use these functions should include the header file `libpq/libpq-fs.h` and link with the libpq library. Client applications cannot use these functions while a libpq connection is in pipeline mode. ### 33.3.1. Creating a Large Object [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-CREATE) The function Oid lo\_create(PGconn \*conn, Oid lobjId); creates a new large object. The OID to be assigned can be specified by _`lobjId`_; if so, failure occurs if that OID is already in use for some large object. If _`lobjId`_ is `InvalidOid` (zero) then `lo_create` assigns an unused OID. The return value is the OID that was assigned to the new large object, or `InvalidOid` (zero) on failure. An example: inv\_oid = lo\_create(conn, desired\_oid); The older function Oid lo\_creat(PGconn \*conn, int mode); also creates a new large object, always assigning an unused OID. The return value is the OID that was assigned to the new large object, or `InvalidOid` (zero) on failure. In PostgreSQL releases 8.1 and later, the _`mode`_ is ignored, so that `lo_creat` is exactly equivalent to `lo_create` with a zero second argument. However, there is little reason to use `lo_creat` unless you need to work with servers older than 8.1. To work with such an old server, you must use `lo_creat` not `lo_create`, and you must set _`mode`_ to one of `INV_READ`, `INV_WRITE`, or `INV_READ` `|` `INV_WRITE`. (These symbolic constants are defined in the header file `libpq/libpq-fs.h`.) An example: inv\_oid = lo\_creat(conn, INV\_READ|INV\_WRITE); ### 33.3.2. Importing a Large Object [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-IMPORT) To import an operating system file as a large object, call Oid lo\_import(PGconn \*conn, const char \*filename); _`filename`_ specifies the operating system name of the file to be imported as a large object. The return value is the OID that was assigned to the new large object, or `InvalidOid` (zero) on failure. Note that the file is read by the client interface library, not by the server; so it must exist in the client file system and be readable by the client application. The function Oid lo\_import\_with\_oid(PGconn \*conn, const char \*filename, Oid lobjId); also imports a new large object. The OID to be assigned can be specified by _`lobjId`_; if so, failure occurs if that OID is already in use for some large object. If _`lobjId`_ is `InvalidOid` (zero) then `lo_import_with_oid` assigns an unused OID (this is the same behavior as `lo_import`). The return value is the OID that was assigned to the new large object, or `InvalidOid` (zero) on failure. `lo_import_with_oid` is new as of PostgreSQL 8.4 and uses `lo_create` internally which is new in 8.1; if this function is run against 8.0 or before, it will fail and return `InvalidOid`. ### 33.3.3. Exporting a Large Object [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-EXPORT) To export a large object into an operating system file, call int lo\_export(PGconn \*conn, Oid lobjId, const char \*filename); The _`lobjId`_ argument specifies the OID of the large object to export and the _`filename`_ argument specifies the operating system name of the file. Note that the file is written by the client interface library, not by the server. Returns 1 on success, -1 on failure. ### 33.3.4. Opening an Existing Large Object [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-OPEN) To open an existing large object for reading or writing, call int lo\_open(PGconn \*conn, Oid lobjId, int mode); The _`lobjId`_ argument specifies the OID of the large object to open. The _`mode`_ bits control whether the object is opened for reading (`INV_READ`), writing (`INV_WRITE`), or both. (These symbolic constants are defined in the header file `libpq/libpq-fs.h`.) `lo_open` returns a (non-negative) large object descriptor for later use in `lo_read`, `lo_write`, `lo_lseek`, `lo_lseek64`, `lo_tell`, `lo_tell64`, `lo_truncate`, `lo_truncate64`, and `lo_close`. The descriptor is only valid for the duration of the current transaction. On failure, -1 is returned. The server currently does not distinguish between modes `INV_WRITE` and `INV_READ` `|` `INV_WRITE`: you are allowed to read from the descriptor in either case. However there is a significant difference between these modes and `INV_READ` alone: with `INV_READ` you cannot write on the descriptor, and the data read from it will reflect the contents of the large object at the time of the transaction snapshot that was active when `lo_open` was executed, regardless of later writes by this or other transactions. Reading from a descriptor opened with `INV_WRITE` returns data that reflects all writes of other committed transactions as well as writes of the current transaction. This is similar to the behavior of `REPEATABLE READ` versus `READ COMMITTED` transaction modes for ordinary SQL `SELECT` commands. `lo_open` will fail if `SELECT` privilege is not available for the large object, or if `INV_WRITE` is specified and `UPDATE` privilege is not available. (Prior to PostgreSQL 11, these privilege checks were instead performed at the first actual read or write call using the descriptor.) These privilege checks can be disabled with the [lo\_compat\_privileges](https://www.postgresql.org/docs/18/runtime-config-compatible.html#GUC-LO-COMPAT-PRIVILEGES) run-time parameter. An example: inv\_fd = lo\_open(conn, inv\_oid, INV\_READ|INV\_WRITE); ### 33.3.5. Writing Data to a Large Object [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-WRITE) The function int lo\_write(PGconn \*conn, int fd, const char \*buf, size\_t len); writes _`len`_ bytes from _`buf`_ (which must be of size _`len`_) to large object descriptor _`fd`_. The _`fd`_ argument must have been returned by a previous `lo_open`. The number of bytes actually written is returned (in the current implementation, this will always equal _`len`_ unless there is an error). In the event of an error, the return value is -1. Although the _`len`_ parameter is declared as `size_t`, this function will reject length values larger than `INT_MAX`. In practice, it's best to transfer data in chunks of at most a few megabytes anyway. ### 33.3.6. Reading Data from a Large Object [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-READ) The function int lo\_read(PGconn \*conn, int fd, char \*buf, size\_t len); reads up to _`len`_ bytes from large object descriptor _`fd`_ into _`buf`_ (which must be of size _`len`_). The _`fd`_ argument must have been returned by a previous `lo_open`. The number of bytes actually read is returned; this will be less than _`len`_ if the end of the large object is reached first. In the event of an error, the return value is -1. Although the _`len`_ parameter is declared as `size_t`, this function will reject length values larger than `INT_MAX`. In practice, it's best to transfer data in chunks of at most a few megabytes anyway. ### 33.3.7. Seeking in a Large Object [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-SEEK) To change the current read or write location associated with a large object descriptor, call int lo\_lseek(PGconn \*conn, int fd, int offset, int whence); This function moves the current location pointer for the large object descriptor identified by _`fd`_ to the new location specified by _`offset`_. The valid values for _`whence`_ are `SEEK_SET` (seek from object start), `SEEK_CUR` (seek from current position), and `SEEK_END` (seek from object end). The return value is the new location pointer, or -1 on error. When dealing with large objects that might exceed 2GB in size, instead use int64\_t lo\_lseek64(PGconn \*conn, int fd, int64\_t offset, int whence); This function has the same behavior as `lo_lseek`, but it can accept an _`offset`_ larger than 2GB and/or deliver a result larger than 2GB. Note that `lo_lseek` will fail if the new location pointer would be greater than 2GB. `lo_lseek64` is new as of PostgreSQL 9.3. If this function is run against an older server version, it will fail and return -1. ### 33.3.8. Obtaining the Seek Position of a Large Object [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-TELL) To obtain the current read or write location of a large object descriptor, call int lo\_tell(PGconn \*conn, int fd); If there is an error, the return value is -1. When dealing with large objects that might exceed 2GB in size, instead use int64\_t lo\_tell64(PGconn \*conn, int fd); This function has the same behavior as `lo_tell`, but it can deliver a result larger than 2GB. Note that `lo_tell` will fail if the current read/write location is greater than 2GB. `lo_tell64` is new as of PostgreSQL 9.3. If this function is run against an older server version, it will fail and return -1. ### 33.3.9. Truncating a Large Object [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-TRUNCATE) To truncate a large object to a given length, call int lo\_truncate(PGconn \*conn, int fd, size\_t len); This function truncates the large object descriptor _`fd`_ to length _`len`_. The _`fd`_ argument must have been returned by a previous `lo_open`. If _`len`_ is greater than the large object's current length, the large object is extended to the specified length with null bytes ('\\0'). On success, `lo_truncate` returns zero. On error, the return value is -1. The read/write location associated with the descriptor _`fd`_ is not changed. Although the _`len`_ parameter is declared as `size_t`, `lo_truncate` will reject length values larger than `INT_MAX`. When dealing with large objects that might exceed 2GB in size, instead use int lo\_truncate64(PGconn \*conn, int fd, int64\_t len); This function has the same behavior as `lo_truncate`, but it can accept a _`len`_ value exceeding 2GB. `lo_truncate` is new as of PostgreSQL 8.3; if this function is run against an older server version, it will fail and return -1. `lo_truncate64` is new as of PostgreSQL 9.3; if this function is run against an older server version, it will fail and return -1. ### 33.3.10. Closing a Large Object Descriptor [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-CLOSE) A large object descriptor can be closed by calling int lo\_close(PGconn \*conn, int fd); where _`fd`_ is a large object descriptor returned by `lo_open`. On success, `lo_close` returns zero. On error, the return value is -1. Any large object descriptors that remain open at the end of a transaction will be closed automatically. ### 33.3.11. Removing a Large Object [#](https://www.postgresql.org/docs/18/lo-interfaces.html#LO-UNLINK) To remove a large object from the database, call int lo\_unlink(PGconn \*conn, Oid lobjId); The _`lobjId`_ argument specifies the OID of the large object to remove. Returns 1 if successful, -1 on failure. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/lo-implementation.html "33.2. Implementation Features") | [Up](https://www.postgresql.org/docs/18/largeobjects.html "Chapter 33. Large Objects") | [Next](https://www.postgresql.org/docs/18/lo-funcs.html "33.4. Server-Side Functions") | | 33.2. Implementation Features | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 33.4. Server-Side Functions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/lo-interfaces.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 5.1. Table Basics November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/ddl-basics.html "PostgreSQL 18 - 5.1. Table Basics") ([18](https://www.postgresql.org/docs/18/ddl-basics.html "PostgreSQL 18 - 5.1. Table Basics") ) / [17](https://www.postgresql.org/docs/17/ddl-basics.html "PostgreSQL 17 - 5.1. Table Basics") / [16](https://www.postgresql.org/docs/16/ddl-basics.html "PostgreSQL 16 - 5.1. Table Basics") / [15](https://www.postgresql.org/docs/15/ddl-basics.html "PostgreSQL 15 - 5.1. Table Basics") / [14](https://www.postgresql.org/docs/14/ddl-basics.html "PostgreSQL 14 - 5.1. Table Basics") Development Versions: [devel](https://www.postgresql.org/docs/devel/ddl-basics.html "PostgreSQL devel - 5.1. Table Basics") Unsupported versions: [13](https://www.postgresql.org/docs/13/ddl-basics.html "PostgreSQL 13 - 5.1. Table Basics") / [12](https://www.postgresql.org/docs/12/ddl-basics.html "PostgreSQL 12 - 5.1. Table Basics") / [11](https://www.postgresql.org/docs/11/ddl-basics.html "PostgreSQL 11 - 5.1. Table Basics") / [10](https://www.postgresql.org/docs/10/ddl-basics.html "PostgreSQL 10 - 5.1. Table Basics") / [9.6](https://www.postgresql.org/docs/9.6/ddl-basics.html "PostgreSQL 9.6 - 5.1. Table Basics") / [9.5](https://www.postgresql.org/docs/9.5/ddl-basics.html "PostgreSQL 9.5 - 5.1. Table Basics") / [9.4](https://www.postgresql.org/docs/9.4/ddl-basics.html "PostgreSQL 9.4 - 5.1. Table Basics") / [9.3](https://www.postgresql.org/docs/9.3/ddl-basics.html "PostgreSQL 9.3 - 5.1. Table Basics") / [9.2](https://www.postgresql.org/docs/9.2/ddl-basics.html "PostgreSQL 9.2 - 5.1. Table Basics") / [9.1](https://www.postgresql.org/docs/9.1/ddl-basics.html "PostgreSQL 9.1 - 5.1. Table Basics") / [9.0](https://www.postgresql.org/docs/9.0/ddl-basics.html "PostgreSQL 9.0 - 5.1. Table Basics") / [8.4](https://www.postgresql.org/docs/8.4/ddl-basics.html "PostgreSQL 8.4 - 5.1. Table Basics") / [8.3](https://www.postgresql.org/docs/8.3/ddl-basics.html "PostgreSQL 8.3 - 5.1. Table Basics") / [8.2](https://www.postgresql.org/docs/8.2/ddl-basics.html "PostgreSQL 8.2 - 5.1. Table Basics") | 5.1. Table Basics | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/ddl.html "Chapter 5. Data Definition") | [Up](https://www.postgresql.org/docs/current/ddl.html "Chapter 5. Data Definition") | Chapter 5. Data Definition | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/ddl-default.html "5.2. Default Values") | * * * 5.1. Table Basics [#](https://www.postgresql.org/docs/current/ddl-basics.html#DDL-BASICS) ------------------------------------------------------------------------------------------ A table in a relational database is much like a table on paper: It consists of rows and columns. The number and order of the columns is fixed, and each column has a name. The number of rows is variable — it reflects how much data is stored at a given moment. SQL does not make any guarantees about the order of the rows in a table. When a table is read, the rows will appear in an unspecified order, unless sorting is explicitly requested. This is covered in [Chapter 7](https://www.postgresql.org/docs/current/queries.html "Chapter 7. Queries") . Furthermore, SQL does not assign unique identifiers to rows, so it is possible to have several completely identical rows in a table. This is a consequence of the mathematical model that underlies SQL but is usually not desirable. Later in this chapter we will see how to deal with this issue. Each column has a data type. The data type constrains the set of possible values that can be assigned to a column and assigns semantics to the data stored in the column so that it can be used for computations. For instance, a column declared to be of a numerical type will not accept arbitrary text strings, and the data stored in such a column can be used for mathematical computations. By contrast, a column declared to be of a character string type will accept almost any kind of data but it does not lend itself to mathematical calculations, although other operations such as string concatenation are available. PostgreSQL includes a sizable set of built-in data types that fit many applications. Users can also define their own data types. Most built-in data types have obvious names and semantics, so we defer a detailed explanation to [Chapter 8](https://www.postgresql.org/docs/current/datatype.html "Chapter 8. Data Types") . Some of the frequently used data types are `integer` for whole numbers, `numeric` for possibly fractional numbers, `text` for character strings, `date` for dates, `time` for time-of-day values, and `timestamp` for values containing both date and time. To create a table, you use the aptly named [CREATE TABLE](https://www.postgresql.org/docs/current/sql-createtable.html "CREATE TABLE") command. In this command you specify at least a name for the new table, the names of the columns and the data type of each column. For example: CREATE TABLE my\_first\_table ( first\_column text, second\_column integer ); This creates a table named `my_first_table` with two columns. The first column is named `first_column` and has a data type of `text`; the second column has the name `second_column` and the type `integer`. The table and column names follow the identifier syntax explained in [Section 4.1.1](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS "4.1.1. Identifiers and Key Words") . The type names are usually also identifiers, but there are some exceptions. Note that the column list is comma-separated and surrounded by parentheses. Of course, the previous example was heavily contrived. Normally, you would give names to your tables and columns that convey what kind of data they store. So let's look at a more realistic example: CREATE TABLE products ( product\_no integer, name text, price numeric ); (The `numeric` type can store fractional components, as would be typical of monetary amounts.) ### Tip When you create many interrelated tables it is wise to choose a consistent naming pattern for the tables and columns. For instance, there is a choice of using singular or plural nouns for table names, both of which are favored by some theorist or other. There is a limit on how many columns a table can contain. Depending on the column types, it is between 250 and 1600. However, defining a table with anywhere near this many columns is highly unusual and often a questionable design. If you no longer need a table, you can remove it using the [DROP TABLE](https://www.postgresql.org/docs/current/sql-droptable.html "DROP TABLE") command. For example: DROP TABLE my\_first\_table; DROP TABLE products; Attempting to drop a table that does not exist is an error. Nevertheless, it is common in SQL script files to unconditionally try to drop each table before creating it, ignoring any error messages, so that the script works whether or not the table exists. (If you like, you can use the `DROP TABLE IF EXISTS` variant to avoid the error messages, but this is not standard SQL.) If you need to modify a table that already exists, see [Section 5.7](https://www.postgresql.org/docs/current/ddl-alter.html "5.7. Modifying Tables") later in this chapter. With the tools discussed so far you can create fully functional tables. The remainder of this chapter is concerned with adding features to the table definition to ensure data integrity, security, or convenience. If you are eager to fill your tables with data now you can skip ahead to [Chapter 6](https://www.postgresql.org/docs/current/dml.html "Chapter 6. Data Manipulation") and read the rest of this chapter later. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/ddl.html "Chapter 5. Data Definition") | [Up](https://www.postgresql.org/docs/current/ddl.html "Chapter 5. Data Definition") | [Next](https://www.postgresql.org/docs/current/ddl-default.html "5.2. Default Values") | | Chapter 5. Data Definition | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 5.2. Default Values | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/ddl-basics.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 10.5. UNION, CASE, and Related Constructs November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/typeconv-union-case.html "PostgreSQL 18 - 10.5. UNION, CASE, and Related Constructs") ([18](https://www.postgresql.org/docs/18/typeconv-union-case.html "PostgreSQL 18 - 10.5. UNION, CASE, and Related Constructs") ) / [17](https://www.postgresql.org/docs/17/typeconv-union-case.html "PostgreSQL 17 - 10.5. UNION, CASE, and Related Constructs") / [16](https://www.postgresql.org/docs/16/typeconv-union-case.html "PostgreSQL 16 - 10.5. UNION, CASE, and Related Constructs") / [15](https://www.postgresql.org/docs/15/typeconv-union-case.html "PostgreSQL 15 - 10.5. UNION, CASE, and Related Constructs") / [14](https://www.postgresql.org/docs/14/typeconv-union-case.html "PostgreSQL 14 - 10.5. UNION, CASE, and Related Constructs") Development Versions: [devel](https://www.postgresql.org/docs/devel/typeconv-union-case.html "PostgreSQL devel - 10.5. UNION, CASE, and Related Constructs") Unsupported versions: [13](https://www.postgresql.org/docs/13/typeconv-union-case.html "PostgreSQL 13 - 10.5. UNION, CASE, and Related Constructs") / [12](https://www.postgresql.org/docs/12/typeconv-union-case.html "PostgreSQL 12 - 10.5. UNION, CASE, and Related Constructs") / [11](https://www.postgresql.org/docs/11/typeconv-union-case.html "PostgreSQL 11 - 10.5. UNION, CASE, and Related Constructs") / [10](https://www.postgresql.org/docs/10/typeconv-union-case.html "PostgreSQL 10 - 10.5. UNION, CASE, and Related Constructs") / [9.6](https://www.postgresql.org/docs/9.6/typeconv-union-case.html "PostgreSQL 9.6 - 10.5. UNION, CASE, and Related Constructs") / [9.5](https://www.postgresql.org/docs/9.5/typeconv-union-case.html "PostgreSQL 9.5 - 10.5. UNION, CASE, and Related Constructs") / [9.4](https://www.postgresql.org/docs/9.4/typeconv-union-case.html "PostgreSQL 9.4 - 10.5. UNION, CASE, and Related Constructs") / [9.3](https://www.postgresql.org/docs/9.3/typeconv-union-case.html "PostgreSQL 9.3 - 10.5. UNION, CASE, and Related Constructs") / [9.2](https://www.postgresql.org/docs/9.2/typeconv-union-case.html "PostgreSQL 9.2 - 10.5. UNION, CASE, and Related Constructs") / [9.1](https://www.postgresql.org/docs/9.1/typeconv-union-case.html "PostgreSQL 9.1 - 10.5. UNION, CASE, and Related Constructs") / [9.0](https://www.postgresql.org/docs/9.0/typeconv-union-case.html "PostgreSQL 9.0 - 10.5. UNION, CASE, and Related Constructs") / [8.4](https://www.postgresql.org/docs/8.4/typeconv-union-case.html "PostgreSQL 8.4 - 10.5. UNION, CASE, and Related Constructs") / [8.3](https://www.postgresql.org/docs/8.3/typeconv-union-case.html "PostgreSQL 8.3 - 10.5. UNION, CASE, and Related Constructs") / [8.2](https://www.postgresql.org/docs/8.2/typeconv-union-case.html "PostgreSQL 8.2 - 10.5. UNION, CASE, and Related Constructs") / [8.1](https://www.postgresql.org/docs/8.1/typeconv-union-case.html "PostgreSQL 8.1 - 10.5. UNION, CASE, and Related Constructs") / [8.0](https://www.postgresql.org/docs/8.0/typeconv-union-case.html "PostgreSQL 8.0 - 10.5. UNION, CASE, and Related Constructs") / [7.4](https://www.postgresql.org/docs/7.4/typeconv-union-case.html "PostgreSQL 7.4 - 10.5. UNION, CASE, and Related Constructs") / [7.3](https://www.postgresql.org/docs/7.3/typeconv-union-case.html "PostgreSQL 7.3 - 10.5. UNION, CASE, and Related Constructs") / [7.2](https://www.postgresql.org/docs/7.2/typeconv-union-case.html "PostgreSQL 7.2 - 10.5. UNION, CASE, and Related Constructs") / [7.1](https://www.postgresql.org/docs/7.1/typeconv-union-case.html "PostgreSQL 7.1 - 10.5. UNION, CASE, and Related Constructs") | 10.5. `UNION`, `CASE`, and Related Constructs | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/typeconv-query.html "10.4. Value Storage") | [Up](https://www.postgresql.org/docs/18/typeconv.html "Chapter 10. Type Conversion") | Chapter 10. Type Conversion | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/typeconv-select.html "10.6. SELECT Output Columns") | * * * 10.5. `UNION`, `CASE`, and Related Constructs [#](https://www.postgresql.org/docs/18/typeconv-union-case.html#TYPECONV-UNION-CASE) ----------------------------------------------------------------------------------------------------------------------------------- SQL `UNION` constructs must match up possibly dissimilar types to become a single result set. The resolution algorithm is applied separately to each output column of a union query. The `INTERSECT` and `EXCEPT` constructs resolve dissimilar types in the same way as `UNION`. Some other constructs, including `CASE`, `ARRAY`, `VALUES`, and the `GREATEST` and `LEAST` functions, use the identical algorithm to match up their component expressions and select a result data type. **Type Resolution for `UNION`, `CASE`, and Related Constructs** 1. If all inputs are of the same type, and it is not `unknown`, resolve as that type. 2. If any input is of a domain type, treat it as being of the domain's base type for all subsequent steps. [\[12\]](https://www.postgresql.org/docs/18/typeconv-union-case.html#ftn.id-1.5.9.10.9.3.1.1) 3. If all inputs are of type `unknown`, resolve as type `text` (the preferred type of the string category). Otherwise, `unknown` inputs are ignored for the purposes of the remaining rules. 4. If the non-unknown inputs are not all of the same type category, fail. 5. Select the first non-unknown input type as the candidate type, then consider each other non-unknown input type, left to right. [\[13\]](https://www.postgresql.org/docs/18/typeconv-union-case.html#ftn.id-1.5.9.10.9.6.1.1) If the candidate type can be implicitly converted to the other type, but not vice-versa, select the other type as the new candidate type. Then continue considering the remaining inputs. If, at any stage of this process, a preferred type is selected, stop considering additional inputs. 6. Convert all inputs to the final candidate type. Fail if there is not an implicit conversion from a given input type to the candidate type. Some examples follow. **Example 10.10. Type Resolution with Underspecified Types in a Union** SELECT text 'a' AS "text" UNION SELECT 'b'; text ------ a b (2 rows) Here, the unknown-type literal `'b'` will be resolved to type `text`. **Example 10.11. Type Resolution in a Simple Union** SELECT 1.2 AS "numeric" UNION SELECT 1; numeric --------- 1 1.2 (2 rows) The literal `1.2` is of type `numeric`, and the `integer` value `1` can be cast implicitly to `numeric`, so that type is used. **Example 10.12. Type Resolution in a Transposed Union** SELECT 1 AS "real" UNION SELECT CAST('2.2' AS REAL); real ------ 1 2.2 (2 rows) Here, since type `real` cannot be implicitly cast to `integer`, but `integer` can be implicitly cast to `real`, the union result type is resolved as `real`. **Example 10.13. Type Resolution in a Nested Union** SELECT NULL UNION SELECT NULL UNION SELECT 1; ERROR: UNION types text and integer cannot be matched This failure occurs because PostgreSQL treats multiple `UNION`s as a nest of pairwise operations; that is, this input is the same as (SELECT NULL UNION SELECT NULL) UNION SELECT 1; The inner `UNION` is resolved as emitting type `text`, according to the rules given above. Then the outer `UNION` has inputs of types `text` and `integer`, leading to the observed error. The problem can be fixed by ensuring that the leftmost `UNION` has at least one input of the desired result type. `INTERSECT` and `EXCEPT` operations are likewise resolved pairwise. However, the other constructs described in this section consider all of their inputs in one resolution step. * * * [\[12\]](https://www.postgresql.org/docs/18/typeconv-union-case.html#id-1.5.9.10.9.3.1.1) Somewhat like the treatment of domain inputs for operators and functions, this behavior allows a domain type to be preserved through a `UNION` or similar construct, so long as the user is careful to ensure that all inputs are implicitly or explicitly of that exact type. Otherwise the domain's base type will be used. [\[13\]](https://www.postgresql.org/docs/18/typeconv-union-case.html#id-1.5.9.10.9.6.1.1) For historical reasons, `CASE` treats its `ELSE` clause (if any) as the “first” input, with the `THEN` clauses(s) considered after that. In all other cases, “left to right” means the order in which the expressions appear in the query text. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/typeconv-query.html "10.4. Value Storage") | [Up](https://www.postgresql.org/docs/18/typeconv.html "Chapter 10. Type Conversion") | [Next](https://www.postgresql.org/docs/18/typeconv-select.html "10.6. SELECT Output Columns") | | 10.4. Value Storage | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 10.6. `SELECT` Output Columns | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/typeconv-union-case.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Preface November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/preface.html "PostgreSQL 18 - Preface") ([18](https://www.postgresql.org/docs/18/preface.html "PostgreSQL 18 - Preface") ) / [17](https://www.postgresql.org/docs/17/preface.html "PostgreSQL 17 - Preface") / [16](https://www.postgresql.org/docs/16/preface.html "PostgreSQL 16 - Preface") / [15](https://www.postgresql.org/docs/15/preface.html "PostgreSQL 15 - Preface") / [14](https://www.postgresql.org/docs/14/preface.html "PostgreSQL 14 - Preface") Development Versions: [devel](https://www.postgresql.org/docs/devel/preface.html "PostgreSQL devel - Preface") Unsupported versions: [13](https://www.postgresql.org/docs/13/preface.html "PostgreSQL 13 - Preface") / [12](https://www.postgresql.org/docs/12/preface.html "PostgreSQL 12 - Preface") / [11](https://www.postgresql.org/docs/11/preface.html "PostgreSQL 11 - Preface") / [10](https://www.postgresql.org/docs/10/preface.html "PostgreSQL 10 - Preface") / [9.6](https://www.postgresql.org/docs/9.6/preface.html "PostgreSQL 9.6 - Preface") / [9.5](https://www.postgresql.org/docs/9.5/preface.html "PostgreSQL 9.5 - Preface") / [9.4](https://www.postgresql.org/docs/9.4/preface.html "PostgreSQL 9.4 - Preface") / [9.3](https://www.postgresql.org/docs/9.3/preface.html "PostgreSQL 9.3 - Preface") / [9.2](https://www.postgresql.org/docs/9.2/preface.html "PostgreSQL 9.2 - Preface") / [9.1](https://www.postgresql.org/docs/9.1/preface.html "PostgreSQL 9.1 - Preface") / [9.0](https://www.postgresql.org/docs/9.0/preface.html "PostgreSQL 9.0 - Preface") / [8.4](https://www.postgresql.org/docs/8.4/preface.html "PostgreSQL 8.4 - Preface") / [8.3](https://www.postgresql.org/docs/8.3/preface.html "PostgreSQL 8.3 - Preface") / [8.2](https://www.postgresql.org/docs/8.2/preface.html "PostgreSQL 8.2 - Preface") / [8.1](https://www.postgresql.org/docs/8.1/preface.html "PostgreSQL 8.1 - Preface") / [8.0](https://www.postgresql.org/docs/8.0/preface.html "PostgreSQL 8.0 - Preface") / [7.4](https://www.postgresql.org/docs/7.4/preface.html "PostgreSQL 7.4 - Preface") / [7.2](https://www.postgresql.org/docs/7.2/preface.html "PostgreSQL 7.2 - Preface") / [7.1](https://www.postgresql.org/docs/7.1/preface.html "PostgreSQL 7.1 - Preface") | Preface | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Up](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | PostgreSQL 18.1 Documentation | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/intro-whatis.html "1.  What Is PostgreSQL?") | * * * Preface ======= **Table of Contents** [1\. What Is PostgreSQL?](https://www.postgresql.org/docs/18/intro-whatis.html) [2\. A Brief History of PostgreSQL](https://www.postgresql.org/docs/18/history.html) [2.1. The Berkeley POSTGRES Project](https://www.postgresql.org/docs/18/history.html#HISTORY-BERKELEY) [2.2. Postgres95](https://www.postgresql.org/docs/18/history.html#HISTORY-POSTGRES95) [2.3. PostgreSQL](https://www.postgresql.org/docs/18/history.html#HISTORY-POSTGRESQL) [3\. Conventions](https://www.postgresql.org/docs/18/notation.html) [4\. Further Information](https://www.postgresql.org/docs/18/resources.html) [5\. Bug Reporting Guidelines](https://www.postgresql.org/docs/18/bug-reporting.html) [5.1. Identifying Bugs](https://www.postgresql.org/docs/18/bug-reporting.html#BUG-REPORTING-IDENTIFYING-BUGS) [5.2. What to Report](https://www.postgresql.org/docs/18/bug-reporting.html#BUG-REPORTING-WHAT-TO-REPORT) [5.3. Where to Report Bugs](https://www.postgresql.org/docs/18/bug-reporting.html#BUG-REPORTING-WHERE-TO-REPORT-BUGS) This book is the official documentation of PostgreSQL. It has been written by the PostgreSQL developers and other volunteers in parallel to the development of the PostgreSQL software. It describes all the functionality that the current version of PostgreSQL officially supports. To make the large amount of information about PostgreSQL manageable, this book has been organized in several parts. Each part is targeted at a different class of users, or at users in different stages of their PostgreSQL experience: * [Part I](https://www.postgresql.org/docs/18/tutorial.html "Part I. Tutorial") is an informal introduction for new users. * [Part II](https://www.postgresql.org/docs/18/sql.html "Part II. The SQL Language") documents the SQL query language environment, including data types and functions, as well as user-level performance tuning. Every PostgreSQL user should read this. * [Part III](https://www.postgresql.org/docs/18/admin.html "Part III. Server Administration") describes the installation and administration of the server. Everyone who runs a PostgreSQL server, be it for private use or for others, should read this part. * [Part IV](https://www.postgresql.org/docs/18/client-interfaces.html "Part IV. Client Interfaces") describes the programming interfaces for PostgreSQL client programs. * [Part V](https://www.postgresql.org/docs/18/server-programming.html "Part V. Server Programming") contains information for advanced users about the extensibility capabilities of the server. Topics include user-defined data types and functions. * [Part VI](https://www.postgresql.org/docs/18/reference.html "Part VI. Reference") contains reference information about SQL commands, client and server programs. This part supports the other parts with structured information sorted by command or program. * [Part VII](https://www.postgresql.org/docs/18/internals.html "Part VII. Internals") contains assorted information that might be of use to PostgreSQL developers. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Up](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/intro-whatis.html "1.  What Is PostgreSQL?") | | PostgreSQL 18.1 Documentation | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 1.  What Is PostgreSQL? | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/preface.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: DROP ROLE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-droprole.html "PostgreSQL 18 - DROP ROLE") ([18](https://www.postgresql.org/docs/18/sql-droprole.html "PostgreSQL 18 - DROP ROLE") ) / [17](https://www.postgresql.org/docs/17/sql-droprole.html "PostgreSQL 17 - DROP ROLE") / [16](https://www.postgresql.org/docs/16/sql-droprole.html "PostgreSQL 16 - DROP ROLE") / [15](https://www.postgresql.org/docs/15/sql-droprole.html "PostgreSQL 15 - DROP ROLE") / [14](https://www.postgresql.org/docs/14/sql-droprole.html "PostgreSQL 14 - DROP ROLE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-droprole.html "PostgreSQL devel - DROP ROLE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-droprole.html "PostgreSQL 13 - DROP ROLE") / [12](https://www.postgresql.org/docs/12/sql-droprole.html "PostgreSQL 12 - DROP ROLE") / [11](https://www.postgresql.org/docs/11/sql-droprole.html "PostgreSQL 11 - DROP ROLE") / [10](https://www.postgresql.org/docs/10/sql-droprole.html "PostgreSQL 10 - DROP ROLE") / [9.6](https://www.postgresql.org/docs/9.6/sql-droprole.html "PostgreSQL 9.6 - DROP ROLE") / [9.5](https://www.postgresql.org/docs/9.5/sql-droprole.html "PostgreSQL 9.5 - DROP ROLE") / [9.4](https://www.postgresql.org/docs/9.4/sql-droprole.html "PostgreSQL 9.4 - DROP ROLE") / [9.3](https://www.postgresql.org/docs/9.3/sql-droprole.html "PostgreSQL 9.3 - DROP ROLE") / [9.2](https://www.postgresql.org/docs/9.2/sql-droprole.html "PostgreSQL 9.2 - DROP ROLE") / [9.1](https://www.postgresql.org/docs/9.1/sql-droprole.html "PostgreSQL 9.1 - DROP ROLE") / [9.0](https://www.postgresql.org/docs/9.0/sql-droprole.html "PostgreSQL 9.0 - DROP ROLE") / [8.4](https://www.postgresql.org/docs/8.4/sql-droprole.html "PostgreSQL 8.4 - DROP ROLE") / [8.3](https://www.postgresql.org/docs/8.3/sql-droprole.html "PostgreSQL 8.3 - DROP ROLE") / [8.2](https://www.postgresql.org/docs/8.2/sql-droprole.html "PostgreSQL 8.2 - DROP ROLE") / [8.1](https://www.postgresql.org/docs/8.1/sql-droprole.html "PostgreSQL 8.1 - DROP ROLE") | DROP ROLE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-droppublication.html "DROP PUBLICATION") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-droproutine.html "DROP ROUTINE") | * * * DROP ROLE --------- DROP ROLE — remove a database role Synopsis -------- DROP ROLE \[ IF EXISTS \] _`name`_ \[, ...\] Description ----------- `DROP ROLE` removes the specified role(s). To drop a superuser role, you must be a superuser yourself; to drop non-superuser roles, you must have `CREATEROLE` privilege and have been granted `ADMIN OPTION` on the role. A role cannot be removed if it is still referenced in any database of the cluster; an error will be raised if so. Before dropping the role, you must drop all the objects it owns (or reassign their ownership) and revoke any privileges the role has been granted on other objects. The [`REASSIGN OWNED`](https://www.postgresql.org/docs/current/sql-reassign-owned.html "REASSIGN OWNED") and [`DROP OWNED`](https://www.postgresql.org/docs/current/sql-drop-owned.html "DROP OWNED") commands can be useful for this purpose; see [Section 21.4](https://www.postgresql.org/docs/current/role-removal.html "21.4. Dropping Roles") for more discussion. However, it is not necessary to remove role memberships involving the role; `DROP ROLE` automatically revokes any memberships of the target role in other roles, and of other roles in the target role. The other roles are not dropped nor otherwise affected. Parameters ---------- `IF EXISTS` Do not throw an error if the role does not exist. A notice is issued in this case. _`name`_ The name of the role to remove. Notes ----- PostgreSQL includes a program [dropuser](https://www.postgresql.org/docs/current/app-dropuser.html "dropuser") that has the same functionality as this command (in fact, it calls this command) but can be run from the command shell. Examples -------- To drop a role: DROP ROLE jonathan; Compatibility ------------- The SQL standard defines `DROP ROLE`, but it allows only one role to be dropped at a time, and it specifies different privilege requirements than PostgreSQL uses. See Also -------- [CREATE ROLE](https://www.postgresql.org/docs/current/sql-createrole.html "CREATE ROLE") , [ALTER ROLE](https://www.postgresql.org/docs/current/sql-alterrole.html "ALTER ROLE") , [SET ROLE](https://www.postgresql.org/docs/current/sql-set-role.html "SET ROLE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-droppublication.html "DROP PUBLICATION") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-droproutine.html "DROP ROUTINE") | | DROP PUBLICATION | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | DROP ROUTINE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-droprole.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CHECKPOINT November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-checkpoint.html "PostgreSQL 18 - CHECKPOINT") ([18](https://www.postgresql.org/docs/18/sql-checkpoint.html "PostgreSQL 18 - CHECKPOINT") ) / [17](https://www.postgresql.org/docs/17/sql-checkpoint.html "PostgreSQL 17 - CHECKPOINT") / [16](https://www.postgresql.org/docs/16/sql-checkpoint.html "PostgreSQL 16 - CHECKPOINT") / [15](https://www.postgresql.org/docs/15/sql-checkpoint.html "PostgreSQL 15 - CHECKPOINT") / [14](https://www.postgresql.org/docs/14/sql-checkpoint.html "PostgreSQL 14 - CHECKPOINT") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-checkpoint.html "PostgreSQL devel - CHECKPOINT") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-checkpoint.html "PostgreSQL 13 - CHECKPOINT") / [12](https://www.postgresql.org/docs/12/sql-checkpoint.html "PostgreSQL 12 - CHECKPOINT") / [11](https://www.postgresql.org/docs/11/sql-checkpoint.html "PostgreSQL 11 - CHECKPOINT") / [10](https://www.postgresql.org/docs/10/sql-checkpoint.html "PostgreSQL 10 - CHECKPOINT") / [9.6](https://www.postgresql.org/docs/9.6/sql-checkpoint.html "PostgreSQL 9.6 - CHECKPOINT") / [9.5](https://www.postgresql.org/docs/9.5/sql-checkpoint.html "PostgreSQL 9.5 - CHECKPOINT") / [9.4](https://www.postgresql.org/docs/9.4/sql-checkpoint.html "PostgreSQL 9.4 - CHECKPOINT") / [9.3](https://www.postgresql.org/docs/9.3/sql-checkpoint.html "PostgreSQL 9.3 - CHECKPOINT") / [9.2](https://www.postgresql.org/docs/9.2/sql-checkpoint.html "PostgreSQL 9.2 - CHECKPOINT") / [9.1](https://www.postgresql.org/docs/9.1/sql-checkpoint.html "PostgreSQL 9.1 - CHECKPOINT") / [9.0](https://www.postgresql.org/docs/9.0/sql-checkpoint.html "PostgreSQL 9.0 - CHECKPOINT") / [8.4](https://www.postgresql.org/docs/8.4/sql-checkpoint.html "PostgreSQL 8.4 - CHECKPOINT") / [8.3](https://www.postgresql.org/docs/8.3/sql-checkpoint.html "PostgreSQL 8.3 - CHECKPOINT") / [8.2](https://www.postgresql.org/docs/8.2/sql-checkpoint.html "PostgreSQL 8.2 - CHECKPOINT") / [8.1](https://www.postgresql.org/docs/8.1/sql-checkpoint.html "PostgreSQL 8.1 - CHECKPOINT") / [8.0](https://www.postgresql.org/docs/8.0/sql-checkpoint.html "PostgreSQL 8.0 - CHECKPOINT") / [7.4](https://www.postgresql.org/docs/7.4/sql-checkpoint.html "PostgreSQL 7.4 - CHECKPOINT") / [7.3](https://www.postgresql.org/docs/7.3/sql-checkpoint.html "PostgreSQL 7.3 - CHECKPOINT") / [7.2](https://www.postgresql.org/docs/7.2/sql-checkpoint.html "PostgreSQL 7.2 - CHECKPOINT") / [7.1](https://www.postgresql.org/docs/7.1/sql-checkpoint.html "PostgreSQL 7.1 - CHECKPOINT") | CHECKPOINT | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-call.html "CALL") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-close.html "CLOSE") | * * * CHECKPOINT ---------- CHECKPOINT — force a write-ahead log checkpoint Synopsis -------- CHECKPOINT Description ----------- A checkpoint is a point in the write-ahead log sequence at which all data files have been updated to reflect the information in the log. All data files will be flushed to disk. Refer to [Section 28.5](https://www.postgresql.org/docs/18/wal-configuration.html "28.5. WAL Configuration") for more details about what happens during a checkpoint. The `CHECKPOINT` command forces an immediate checkpoint when the command is issued, without waiting for a regular checkpoint scheduled by the system (controlled by the settings in [Section 19.5.2](https://www.postgresql.org/docs/18/runtime-config-wal.html#RUNTIME-CONFIG-WAL-CHECKPOINTS "19.5.2. Checkpoints") ). `CHECKPOINT` is not intended for use during normal operation. If executed during recovery, the `CHECKPOINT` command will force a restartpoint (see [Section 28.5](https://www.postgresql.org/docs/18/wal-configuration.html "28.5. WAL Configuration") ) rather than writing a new checkpoint. Only superusers or users with the privileges of the [pg\_checkpoint](https://www.postgresql.org/docs/18/predefined-roles.html#PREDEFINED-ROLE-PG-CHECKPOINT) role can call `CHECKPOINT`. Compatibility ------------- The `CHECKPOINT` command is a PostgreSQL language extension. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-call.html "CALL") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-close.html "CLOSE") | | CALL | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | CLOSE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-checkpoint.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 36.16. Interfacing Extensions to Indexes November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/xindex.html "PostgreSQL 18 - 36.16. Interfacing Extensions to Indexes") ([18](https://www.postgresql.org/docs/18/xindex.html "PostgreSQL 18 - 36.16. Interfacing Extensions to Indexes") ) / [17](https://www.postgresql.org/docs/17/xindex.html "PostgreSQL 17 - 36.16. Interfacing Extensions to Indexes") / [16](https://www.postgresql.org/docs/16/xindex.html "PostgreSQL 16 - 36.16. Interfacing Extensions to Indexes") / [15](https://www.postgresql.org/docs/15/xindex.html "PostgreSQL 15 - 36.16. Interfacing Extensions to Indexes") / [14](https://www.postgresql.org/docs/14/xindex.html "PostgreSQL 14 - 36.16. Interfacing Extensions to Indexes") Development Versions: [devel](https://www.postgresql.org/docs/devel/xindex.html "PostgreSQL devel - 36.16. Interfacing Extensions to Indexes") Unsupported versions: [13](https://www.postgresql.org/docs/13/xindex.html "PostgreSQL 13 - 36.16. Interfacing Extensions to Indexes") / [12](https://www.postgresql.org/docs/12/xindex.html "PostgreSQL 12 - 36.16. Interfacing Extensions to Indexes") / [11](https://www.postgresql.org/docs/11/xindex.html "PostgreSQL 11 - 36.16. Interfacing Extensions to Indexes") / [10](https://www.postgresql.org/docs/10/xindex.html "PostgreSQL 10 - 36.16. Interfacing Extensions to Indexes") / [9.6](https://www.postgresql.org/docs/9.6/xindex.html "PostgreSQL 9.6 - 36.16. Interfacing Extensions to Indexes") / [9.5](https://www.postgresql.org/docs/9.5/xindex.html "PostgreSQL 9.5 - 36.16. Interfacing Extensions to Indexes") / [9.4](https://www.postgresql.org/docs/9.4/xindex.html "PostgreSQL 9.4 - 36.16. Interfacing Extensions to Indexes") / [9.3](https://www.postgresql.org/docs/9.3/xindex.html "PostgreSQL 9.3 - 36.16. Interfacing Extensions to Indexes") / [9.2](https://www.postgresql.org/docs/9.2/xindex.html "PostgreSQL 9.2 - 36.16. Interfacing Extensions to Indexes") / [9.1](https://www.postgresql.org/docs/9.1/xindex.html "PostgreSQL 9.1 - 36.16. Interfacing Extensions to Indexes") / [9.0](https://www.postgresql.org/docs/9.0/xindex.html "PostgreSQL 9.0 - 36.16. Interfacing Extensions to Indexes") / [8.4](https://www.postgresql.org/docs/8.4/xindex.html "PostgreSQL 8.4 - 36.16. Interfacing Extensions to Indexes") / [8.3](https://www.postgresql.org/docs/8.3/xindex.html "PostgreSQL 8.3 - 36.16. Interfacing Extensions to Indexes") / [8.2](https://www.postgresql.org/docs/8.2/xindex.html "PostgreSQL 8.2 - 36.16. Interfacing Extensions to Indexes") / [8.1](https://www.postgresql.org/docs/8.1/xindex.html "PostgreSQL 8.1 - 36.16. Interfacing Extensions to Indexes") / [8.0](https://www.postgresql.org/docs/8.0/xindex.html "PostgreSQL 8.0 - 36.16. Interfacing Extensions to Indexes") / [7.4](https://www.postgresql.org/docs/7.4/xindex.html "PostgreSQL 7.4 - 36.16. Interfacing Extensions to Indexes") / [7.3](https://www.postgresql.org/docs/7.3/xindex.html "PostgreSQL 7.3 - 36.16. Interfacing Extensions to Indexes") / [7.2](https://www.postgresql.org/docs/7.2/xindex.html "PostgreSQL 7.2 - 36.16. Interfacing Extensions to Indexes") / [7.1](https://www.postgresql.org/docs/7.1/xindex.html "PostgreSQL 7.1 - 36.16. Interfacing Extensions to Indexes") | 36.16. Interfacing Extensions to Indexes | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/xoper-optimization.html "36.15. Operator Optimization Information") | [Up](https://www.postgresql.org/docs/18/extend.html "Chapter 36. Extending SQL") | Chapter 36. Extending SQL | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/extend-extensions.html "36.17. Packaging Related Objects into an Extension") | * * * 36.16. Interfacing Extensions to Indexes [#](https://www.postgresql.org/docs/18/xindex.html#XINDEX) ---------------------------------------------------------------------------------------------------- [36.16.1. Index Methods and Operator Classes](https://www.postgresql.org/docs/18/xindex.html#XINDEX-OPCLASS) [36.16.2. Index Method Strategies](https://www.postgresql.org/docs/18/xindex.html#XINDEX-STRATEGIES) [36.16.3. Index Method Support Routines](https://www.postgresql.org/docs/18/xindex.html#XINDEX-SUPPORT) [36.16.4. An Example](https://www.postgresql.org/docs/18/xindex.html#XINDEX-EXAMPLE) [36.16.5. Operator Classes and Operator Families](https://www.postgresql.org/docs/18/xindex.html#XINDEX-OPFAMILY) [36.16.6. System Dependencies on Operator Classes](https://www.postgresql.org/docs/18/xindex.html#XINDEX-OPCLASS-DEPENDENCIES) [36.16.7. Ordering Operators](https://www.postgresql.org/docs/18/xindex.html#XINDEX-ORDERING-OPS) [36.16.8. Special Features of Operator Classes](https://www.postgresql.org/docs/18/xindex.html#XINDEX-OPCLASS-FEATURES) The procedures described thus far let you define new types, new functions, and new operators. However, we cannot yet define an index on a column of a new data type. To do this, we must define an _operator class_ for the new data type. Later in this section, we will illustrate this concept in an example: a new operator class for the B-tree index method that stores and sorts complex numbers in ascending absolute value order. Operator classes can be grouped into _operator families_ to show the relationships between semantically compatible classes. When only a single data type is involved, an operator class is sufficient, so we'll focus on that case first and then return to operator families. ### 36.16.1. Index Methods and Operator Classes [#](https://www.postgresql.org/docs/18/xindex.html#XINDEX-OPCLASS) Operator classes are associated with an index access method, such as [B-Tree](https://www.postgresql.org/docs/18/btree.html "65.1. B-Tree Indexes") or [GIN](https://www.postgresql.org/docs/18/gin.html "65.4. GIN Indexes") . Custom index access method may be defined with [CREATE ACCESS METHOD](https://www.postgresql.org/docs/18/sql-create-access-method.html "CREATE ACCESS METHOD") . See [Chapter 63](https://www.postgresql.org/docs/18/indexam.html "Chapter 63. Index Access Method Interface Definition") for details. The routines for an index method do not directly know anything about the data types that the index method will operate on. Instead, an _operator class_ identifies the set of operations that the index method needs to use to work with a particular data type. Operator classes are so called because one thing they specify is the set of `WHERE`\-clause operators that can be used with an index (i.e., can be converted into an index-scan qualification). An operator class can also specify some _support function_ that are needed by the internal operations of the index method, but do not directly correspond to any `WHERE`\-clause operator that can be used with the index. It is possible to define multiple operator classes for the same data type and index method. By doing this, multiple sets of indexing semantics can be defined for a single data type. For example, a B-tree index requires a sort ordering to be defined for each data type it works on. It might be useful for a complex-number data type to have one B-tree operator class that sorts the data by complex absolute value, another that sorts by real part, and so on. Typically, one of the operator classes will be deemed most commonly useful and will be marked as the default operator class for that data type and index method. The same operator class name can be used for several different index methods (for example, both B-tree and hash index methods have operator classes named `int4_ops`), but each such class is an independent entity and must be defined separately. ### 36.16.2. Index Method Strategies [#](https://www.postgresql.org/docs/18/xindex.html#XINDEX-STRATEGIES) The operators associated with an operator class are identified by “strategy numbers”, which serve to identify the semantics of each operator within the context of its operator class. For example, B-trees impose a strict ordering on keys, lesser to greater, and so operators like “less than” and “greater than or equal to” are interesting with respect to a B-tree. Because PostgreSQL allows the user to define operators, PostgreSQL cannot look at the name of an operator (e.g., `<` or `>=`) and tell what kind of comparison it is. Instead, the index method defines a set of “strategies”, which can be thought of as generalized operators. Each operator class specifies which actual operator corresponds to each strategy for a particular data type and interpretation of the index semantics. The B-tree index method defines five strategies, shown in [Table 36.3](https://www.postgresql.org/docs/18/xindex.html#XINDEX-BTREE-STRAT-TABLE "Table 36.3. B-Tree Strategies") . **Table 36.3. B-Tree Strategies** | Operation | Strategy Number | | --- | --- | | less than | 1 | | less than or equal | 2 | | equal | 3 | | greater than or equal | 4 | | greater than | 5 | Hash indexes support only equality comparisons, and so they use only one strategy, shown in [Table 36.4](https://www.postgresql.org/docs/18/xindex.html#XINDEX-HASH-STRAT-TABLE "Table 36.4. Hash Strategies") . **Table 36.4. Hash Strategies** | Operation | Strategy Number | | --- | --- | | equal | 1 | GiST indexes are more flexible: they do not have a fixed set of strategies at all. Instead, the “consistency” support routine of each particular GiST operator class interprets the strategy numbers however it likes. As an example, several of the built-in GiST index operator classes index two-dimensional geometric objects, providing the “R-tree” strategies shown in [Table 36.5](https://www.postgresql.org/docs/18/xindex.html#XINDEX-RTREE-STRAT-TABLE "Table 36.5. GiST Two-Dimensional “R-tree” Strategies") . Four of these are true two-dimensional tests (overlaps, same, contains, contained by); four of them consider only the X direction; and the other four provide the same tests in the Y direction. **Table 36.5. GiST Two-Dimensional “R-tree” Strategies** | Operation | Strategy Number | | --- | --- | | strictly left of | 1 | | does not extend to right of | 2 | | overlaps | 3 | | does not extend to left of | 4 | | strictly right of | 5 | | same | 6 | | contains | 7 | | contained by | 8 | | does not extend above | 9 | | strictly below | 10 | | strictly above | 11 | | does not extend below | 12 | SP-GiST indexes are similar to GiST indexes in flexibility: they don't have a fixed set of strategies. Instead the support routines of each operator class interpret the strategy numbers according to the operator class's definition. As an example, the strategy numbers used by the built-in operator classes for points are shown in [Table 36.6](https://www.postgresql.org/docs/18/xindex.html#XINDEX-SPGIST-POINT-STRAT-TABLE "Table 36.6. SP-GiST Point Strategies") . **Table 36.6. SP-GiST Point Strategies** | Operation | Strategy Number | | --- | --- | | strictly left of | 1 | | strictly right of | 5 | | same | 6 | | contained by | 8 | | strictly below | 10 | | strictly above | 11 | GIN indexes are similar to GiST and SP-GiST indexes, in that they don't have a fixed set of strategies either. Instead the support routines of each operator class interpret the strategy numbers according to the operator class's definition. As an example, the strategy numbers used by the built-in operator class for arrays are shown in [Table 36.7](https://www.postgresql.org/docs/18/xindex.html#XINDEX-GIN-ARRAY-STRAT-TABLE "Table 36.7. GIN Array Strategies") . **Table 36.7. GIN Array Strategies** | Operation | Strategy Number | | --- | --- | | overlap | 1 | | contains | 2 | | is contained by | 3 | | equal | 4 | BRIN indexes are similar to GiST, SP-GiST and GIN indexes in that they don't have a fixed set of strategies either. Instead the support routines of each operator class interpret the strategy numbers according to the operator class's definition. As an example, the strategy numbers used by the built-in `Minmax` operator classes are shown in [Table 36.8](https://www.postgresql.org/docs/18/xindex.html#XINDEX-BRIN-MINMAX-STRAT-TABLE "Table 36.8. BRIN Minmax Strategies") . **Table 36.8. BRIN Minmax Strategies** | Operation | Strategy Number | | --- | --- | | less than | 1 | | less than or equal | 2 | | equal | 3 | | greater than or equal | 4 | | greater than | 5 | Notice that all the operators listed above return Boolean values. In practice, all operators defined as index method search operators must return type `boolean`, since they must appear at the top level of a `WHERE` clause to be used with an index. (Some index access methods also support _ordering operators_, which typically don't return Boolean values; that feature is discussed in [Section 36.16.7](https://www.postgresql.org/docs/18/xindex.html#XINDEX-ORDERING-OPS "36.16.7. Ordering Operators") .) ### 36.16.3. Index Method Support Routines [#](https://www.postgresql.org/docs/18/xindex.html#XINDEX-SUPPORT) Strategies aren't usually enough information for the system to figure out how to use an index. In practice, the index methods require additional support routines in order to work. For example, the B-tree index method must be able to compare two keys and determine whether one is greater than, equal to, or less than the other. Similarly, the hash index method must be able to compute hash codes for key values. These operations do not correspond to operators used in qualifications in SQL commands; they are administrative routines used by the index methods, internally. Just as with strategies, the operator class identifies which specific functions should play each of these roles for a given data type and semantic interpretation. The index method defines the set of functions it needs, and the operator class identifies the correct functions to use by assigning them to the “support function numbers” specified by the index method. Additionally, some opclasses allow users to specify parameters which control their behavior. Each builtin index access method has an optional `options` support function, which defines a set of opclass-specific parameters. B-trees require a comparison support function, and allow four additional support functions to be supplied at the operator class author's option, as shown in [Table 36.9](https://www.postgresql.org/docs/18/xindex.html#XINDEX-BTREE-SUPPORT-TABLE "Table 36.9. B-Tree Support Functions") . The requirements for these support functions are explained further in [Section 65.1.3](https://www.postgresql.org/docs/18/btree.html#BTREE-SUPPORT-FUNCS "65.1.3. B-Tree Support Functions") . **Table 36.9. B-Tree Support Functions** | Function | Support Number | | --- | --- | | Compare two keys and return an integer less than zero, zero, or greater than zero, indicating whether the first key is less than, equal to, or greater than the second | 1 | | Return the addresses of C-callable sort support function(s) (optional) | 2 | | Compare a test value to a base value plus/minus an offset, and return true or false according to the comparison result (optional) | 3 | | Determine if it is safe for indexes that use the operator class to apply the btree deduplication optimization (optional) | 4 | | Define options that are specific to this operator class (optional) | 5 | | Return the addresses of C-callable skip support function(s) (optional) | 6 | Hash indexes require one support function, and allow two additional ones to be supplied at the operator class author's option, as shown in [Table 36.10](https://www.postgresql.org/docs/18/xindex.html#XINDEX-HASH-SUPPORT-TABLE "Table 36.10. Hash Support Functions") . **Table 36.10. Hash Support Functions** | Function | Support Number | | --- | --- | | Compute the 32-bit hash value for a key | 1 | | Compute the 64-bit hash value for a key given a 64-bit salt; if the salt is 0, the low 32 bits of the result must match the value that would have been computed by function 1 (optional) | 2 | | Define options that are specific to this operator class (optional) | 3 | GiST indexes have twelve support functions, seven of which are optional, as shown in [Table 36.11](https://www.postgresql.org/docs/18/xindex.html#XINDEX-GIST-SUPPORT-TABLE "Table 36.11. GiST Support Functions") . (For more information see [Section 65.2](https://www.postgresql.org/docs/18/gist.html "65.2. GiST Indexes") .) **Table 36.11. GiST Support Functions** | Function | Description | Support Number | | --- | --- | --- | | `consistent` | determine whether key satisfies the query qualifier | 1 | | `union` | compute union of a set of keys | 2 | | `compress` | compute a compressed representation of a key or value to be indexed (optional) | 3 | | `decompress` | compute a decompressed representation of a compressed key (optional) | 4 | | `penalty` | compute penalty for inserting new key into subtree with given subtree's key | 5 | | `picksplit` | determine which entries of a page are to be moved to the new page and compute the union keys for resulting pages | 6 | | `same` | compare two keys and return true if they are equal | 7 | | `distance` | determine distance from key to query value (optional) | 8 | | `fetch` | compute original representation of a compressed key for index-only scans (optional) | 9 | | `options` | define options that are specific to this operator class (optional) | 10 | | `sortsupport` | provide a sort comparator to be used in fast index builds (optional) | 11 | | `translate_cmptype` | translate compare types to strategy numbers used by the operator class (optional) | 12 | SP-GiST indexes have six support functions, one of which is optional, as shown in [Table 36.12](https://www.postgresql.org/docs/18/xindex.html#XINDEX-SPGIST-SUPPORT-TABLE "Table 36.12. SP-GiST Support Functions") . (For more information see [Section 65.3](https://www.postgresql.org/docs/18/spgist.html "65.3. SP-GiST Indexes") .) **Table 36.12. SP-GiST Support Functions** | Function | Description | Support Number | | --- | --- | --- | | `config` | provide basic information about the operator class | 1 | | `choose` | determine how to insert a new value into an inner tuple | 2 | | `picksplit` | determine how to partition a set of values | 3 | | `inner_consistent` | determine which sub-partitions need to be searched for a query | 4 | | `leaf_consistent` | determine whether key satisfies the query qualifier | 5 | | `options` | define options that are specific to this operator class (optional) | 6 | GIN indexes have seven support functions, four of which are optional, as shown in [Table 36.13](https://www.postgresql.org/docs/18/xindex.html#XINDEX-GIN-SUPPORT-TABLE "Table 36.13. GIN Support Functions") . (For more information see [Section 65.4](https://www.postgresql.org/docs/18/gin.html "65.4. GIN Indexes") .) **Table 36.13. GIN Support Functions** | Function | Description | Support Number | | --- | --- | --- | | `compare` | compare two keys and return an integer less than zero, zero, or greater than zero, indicating whether the first key is less than, equal to, or greater than the second | 1 | | `extractValue` | extract keys from a value to be indexed | 2 | | `extractQuery` | extract keys from a query condition | 3 | | `consistent` | determine whether value matches query condition (Boolean variant) (optional if support function 6 is present) | 4 | | `comparePartial` | compare partial key from query and key from index, and return an integer less than zero, zero, or greater than zero, indicating whether GIN should ignore this index entry, treat the entry as a match, or stop the index scan (optional) | 5 | | `triConsistent` | determine whether value matches query condition (ternary variant) (optional if support function 4 is present) | 6 | | `options` | define options that are specific to this operator class (optional) | 7 | BRIN indexes have five basic support functions, one of which is optional, as shown in [Table 36.14](https://www.postgresql.org/docs/18/xindex.html#XINDEX-BRIN-SUPPORT-TABLE "Table 36.14. BRIN Support Functions") . Some versions of the basic functions require additional support functions to be provided. (For more information see [Section 65.5.3](https://www.postgresql.org/docs/18/brin.html#BRIN-EXTENSIBILITY "65.5.3. Extensibility") .) **Table 36.14. BRIN Support Functions** | Function | Description | Support Number | | --- | --- | --- | | `opcInfo` | return internal information describing the indexed columns' summary data | 1 | | `add_value` | add a new value to an existing summary index tuple | 2 | | `consistent` | determine whether value matches query condition | 3 | | `union` | compute union of two summary tuples | 4 | | `options` | define options that are specific to this operator class (optional) | 5 | Unlike search operators, support functions return whichever data type the particular index method expects; for example in the case of the comparison function for B-trees, a signed integer. The number and types of the arguments to each support function are likewise dependent on the index method. For B-tree and hash the comparison and hashing support functions take the same input data types as do the operators included in the operator class, but this is not the case for most GiST, SP-GiST, GIN, and BRIN support functions. ### 36.16.4. An Example [#](https://www.postgresql.org/docs/18/xindex.html#XINDEX-EXAMPLE) Now that we have seen the ideas, here is the promised example of creating a new operator class. (You can find a working copy of this example in `src/tutorial/complex.c` and `src/tutorial/complex.sql` in the source distribution.) The operator class encapsulates operators that sort complex numbers in absolute value order, so we choose the name `complex_abs_ops`. First, we need a set of operators. The procedure for defining operators was discussed in [Section 36.14](https://www.postgresql.org/docs/18/xoper.html "36.14. User-Defined Operators") . For an operator class on B-trees, the operators we require are: * absolute-value less-than (strategy 1) * absolute-value less-than-or-equal (strategy 2) * absolute-value equal (strategy 3) * absolute-value greater-than-or-equal (strategy 4) * absolute-value greater-than (strategy 5) The least error-prone way to define a related set of comparison operators is to write the B-tree comparison support function first, and then write the other functions as one-line wrappers around the support function. This reduces the odds of getting inconsistent results for corner cases. Following this approach, we first write: #define Mag(c) ((c)->x\*(c)->x + (c)->y\*(c)->y) static int complex\_abs\_cmp\_internal(Complex \*a, Complex \*b) { double amag = Mag(a), bmag = Mag(b); if (amag < bmag) return -1; if (amag > bmag) return 1; return 0; } Now the less-than function looks like: PG\_FUNCTION\_INFO\_V1(complex\_abs\_lt); Datum complex\_abs\_lt(PG\_FUNCTION\_ARGS) { Complex \*a = (Complex \*) PG\_GETARG\_POINTER(0); Complex \*b = (Complex \*) PG\_GETARG\_POINTER(1); PG\_RETURN\_BOOL(complex\_abs\_cmp\_internal(a, b) < 0); } The other four functions differ only in how they compare the internal function's result to zero. Next we declare the functions and the operators based on the functions to SQL: CREATE FUNCTION complex\_abs\_lt(complex, complex) RETURNS bool AS '_`filename`_', 'complex\_abs\_lt' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR < ( leftarg = complex, rightarg = complex, procedure = complex\_abs\_lt, commutator = > , negator = >= , restrict = scalarltsel, join = scalarltjoinsel ); It is important to specify the correct commutator and negator operators, as well as suitable restriction and join selectivity functions, otherwise the optimizer will be unable to make effective use of the index. Other things worth noting are happening here: * There can only be one operator named, say, `=` and taking type `complex` for both operands. In this case we don't have any other operator `=` for `complex`, but if we were building a practical data type we'd probably want `=` to be the ordinary equality operation for complex numbers (and not the equality of the absolute values). In that case, we'd need to use some other operator name for `complex_abs_eq`. * Although PostgreSQL can cope with functions having the same SQL name as long as they have different argument data types, C can only cope with one global function having a given name. So we shouldn't name the C function something simple like `abs_eq`. Usually it's a good practice to include the data type name in the C function name, so as not to conflict with functions for other data types. * We could have made the SQL name of the function `abs_eq`, relying on PostgreSQL to distinguish it by argument data types from any other SQL function of the same name. To keep the example simple, we make the function have the same names at the C level and SQL level. The next step is the registration of the support routine required by B-trees. The example C code that implements this is in the same file that contains the operator functions. This is how we declare the function: CREATE FUNCTION complex\_abs\_cmp(complex, complex) RETURNS integer AS '_`filename`_' LANGUAGE C IMMUTABLE STRICT; Now that we have the required operators and support routine, we can finally create the operator class: CREATE OPERATOR CLASS complex\_abs\_ops DEFAULT FOR TYPE complex USING btree AS OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 complex\_abs\_cmp(complex, complex); And we're done! It should now be possible to create and use B-tree indexes on `complex` columns. We could have written the operator entries more verbosely, as in: OPERATOR 1 < (complex, complex) , but there is no need to do so when the operators take the same data type we are defining the operator class for. The above example assumes that you want to make this new operator class the default B-tree operator class for the `complex` data type. If you don't, just leave out the word `DEFAULT`. ### 36.16.5. Operator Classes and Operator Families [#](https://www.postgresql.org/docs/18/xindex.html#XINDEX-OPFAMILY) So far we have implicitly assumed that an operator class deals with only one data type. While there certainly can be only one data type in a particular index column, it is often useful to index operations that compare an indexed column to a value of a different data type. Also, if there is use for a cross-data-type operator in connection with an operator class, it is often the case that the other data type has a related operator class of its own. It is helpful to make the connections between related classes explicit, because this can aid the planner in optimizing SQL queries (particularly for B-tree operator classes, since the planner contains a great deal of knowledge about how to work with them). To handle these needs, PostgreSQL uses the concept of an _operator family_. An operator family contains one or more operator classes, and can also contain indexable operators and corresponding support functions that belong to the family as a whole but not to any single class within the family. We say that such operators and functions are “loose” within the family, as opposed to being bound into a specific class. Typically each operator class contains single-data-type operators while cross-data-type operators are loose in the family. All the operators and functions in an operator family must have compatible semantics, where the compatibility requirements are set by the index method. You might therefore wonder why bother to single out particular subsets of the family as operator classes; and indeed for many purposes the class divisions are irrelevant and the family is the only interesting grouping. The reason for defining operator classes is that they specify how much of the family is needed to support any particular index. If there is an index using an operator class, then that operator class cannot be dropped without dropping the index — but other parts of the operator family, namely other operator classes and loose operators, could be dropped. Thus, an operator class should be specified to contain the minimum set of operators and functions that are reasonably needed to work with an index on a specific data type, and then related but non-essential operators can be added as loose members of the operator family. As an example, PostgreSQL has a built-in B-tree operator family `integer_ops`, which includes operator classes `int8_ops`, `int4_ops`, and `int2_ops` for indexes on `bigint` (`int8`), `integer` (`int4`), and `smallint` (`int2`) columns respectively. The family also contains cross-data-type comparison operators allowing any two of these types to be compared, so that an index on one of these types can be searched using a comparison value of another type. The family could be duplicated by these definitions: CREATE OPERATOR FAMILY integer\_ops USING btree; CREATE OPERATOR CLASS int8\_ops DEFAULT FOR TYPE int8 USING btree FAMILY integer\_ops AS -- standard int8 comparisons OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 btint8cmp(int8, int8) , FUNCTION 2 btint8sortsupport(internal) , FUNCTION 3 in\_range(int8, int8, int8, boolean, boolean) , FUNCTION 4 btequalimage(oid) , FUNCTION 6 btint8skipsupport(internal) ; CREATE OPERATOR CLASS int4\_ops DEFAULT FOR TYPE int4 USING btree FAMILY integer\_ops AS -- standard int4 comparisons OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 btint4cmp(int4, int4) , FUNCTION 2 btint4sortsupport(internal) , FUNCTION 3 in\_range(int4, int4, int4, boolean, boolean) , FUNCTION 4 btequalimage(oid) , FUNCTION 6 btint4skipsupport(internal) ; CREATE OPERATOR CLASS int2\_ops DEFAULT FOR TYPE int2 USING btree FAMILY integer\_ops AS -- standard int2 comparisons OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 btint2cmp(int2, int2) , FUNCTION 2 btint2sortsupport(internal) , FUNCTION 3 in\_range(int2, int2, int2, boolean, boolean) , FUNCTION 4 btequalimage(oid) , FUNCTION 6 btint2skipsupport(internal) ; ALTER OPERATOR FAMILY integer\_ops USING btree ADD -- cross-type comparisons int8 vs int2 OPERATOR 1 < (int8, int2) , OPERATOR 2 <= (int8, int2) , OPERATOR 3 = (int8, int2) , OPERATOR 4 >= (int8, int2) , OPERATOR 5 > (int8, int2) , FUNCTION 1 btint82cmp(int8, int2) , -- cross-type comparisons int8 vs int4 OPERATOR 1 < (int8, int4) , OPERATOR 2 <= (int8, int4) , OPERATOR 3 = (int8, int4) , OPERATOR 4 >= (int8, int4) , OPERATOR 5 > (int8, int4) , FUNCTION 1 btint84cmp(int8, int4) , -- cross-type comparisons int4 vs int2 OPERATOR 1 < (int4, int2) , OPERATOR 2 <= (int4, int2) , OPERATOR 3 = (int4, int2) , OPERATOR 4 >= (int4, int2) , OPERATOR 5 > (int4, int2) , FUNCTION 1 btint42cmp(int4, int2) , -- cross-type comparisons int4 vs int8 OPERATOR 1 < (int4, int8) , OPERATOR 2 <= (int4, int8) , OPERATOR 3 = (int4, int8) , OPERATOR 4 >= (int4, int8) , OPERATOR 5 > (int4, int8) , FUNCTION 1 btint48cmp(int4, int8) , -- cross-type comparisons int2 vs int8 OPERATOR 1 < (int2, int8) , OPERATOR 2 <= (int2, int8) , OPERATOR 3 = (int2, int8) , OPERATOR 4 >= (int2, int8) , OPERATOR 5 > (int2, int8) , FUNCTION 1 btint28cmp(int2, int8) , -- cross-type comparisons int2 vs int4 OPERATOR 1 < (int2, int4) , OPERATOR 2 <= (int2, int4) , OPERATOR 3 = (int2, int4) , OPERATOR 4 >= (int2, int4) , OPERATOR 5 > (int2, int4) , FUNCTION 1 btint24cmp(int2, int4) , -- cross-type in\_range functions FUNCTION 3 in\_range(int4, int4, int8, boolean, boolean) , FUNCTION 3 in\_range(int4, int4, int2, boolean, boolean) , FUNCTION 3 in\_range(int2, int2, int8, boolean, boolean) , FUNCTION 3 in\_range(int2, int2, int4, boolean, boolean) ; Notice that this definition “overloads” the operator strategy and support function numbers: each number occurs multiple times within the family. This is allowed so long as each instance of a particular number has distinct input data types. The instances that have both input types equal to an operator class's input type are the primary operators and support functions for that operator class, and in most cases should be declared as part of the operator class rather than as loose members of the family. In a B-tree operator family, all the operators in the family must sort compatibly, as is specified in detail in [Section 65.1.2](https://www.postgresql.org/docs/18/btree.html#BTREE-BEHAVIOR "65.1.2. Behavior of B-Tree Operator Classes") . For each operator in the family there must be a support function having the same two input data types as the operator. It is recommended that a family be complete, i.e., for each combination of data types, all operators are included. Each operator class should include just the non-cross-type operators and support function for its data type. To build a multiple-data-type hash operator family, compatible hash support functions must be created for each data type supported by the family. Here compatibility means that the functions are guaranteed to return the same hash code for any two values that are considered equal by the family's equality operators, even when the values are of different types. This is usually difficult to accomplish when the types have different physical representations, but it can be done in some cases. Furthermore, casting a value from one data type represented in the operator family to another data type also represented in the operator family via an implicit or binary coercion cast must not change the computed hash value. Notice that there is only one support function per data type, not one per equality operator. It is recommended that a family be complete, i.e., provide an equality operator for each combination of data types. Each operator class should include just the non-cross-type equality operator and the support function for its data type. GiST, SP-GiST, and GIN indexes do not have any explicit notion of cross-data-type operations. The set of operators supported is just whatever the primary support functions for a given operator class can handle. In BRIN, the requirements depends on the framework that provides the operator classes. For operator classes based on `minmax`, the behavior required is the same as for B-tree operator families: all the operators in the family must sort compatibly, and casts must not change the associated sort ordering. ### Note Prior to PostgreSQL 8.3, there was no concept of operator families, and so any cross-data-type operators intended to be used with an index had to be bound directly into the index's operator class. While this approach still works, it is deprecated because it makes an index's dependencies too broad, and because the planner can handle cross-data-type comparisons more effectively when both data types have operators in the same operator family. ### 36.16.6. System Dependencies on Operator Classes [#](https://www.postgresql.org/docs/18/xindex.html#XINDEX-OPCLASS-DEPENDENCIES) PostgreSQL uses operator classes to infer the properties of operators in more ways than just whether they can be used with indexes. Therefore, you might want to create operator classes even if you have no intention of indexing any columns of your data type. In particular, there are SQL features such as `ORDER BY` and `DISTINCT` that require comparison and sorting of values. To implement these features on a user-defined data type, PostgreSQL looks for the default B-tree operator class for the data type. The “equals” member of this operator class defines the system's notion of equality of values for `GROUP BY` and `DISTINCT`, and the sort ordering imposed by the operator class defines the default `ORDER BY` ordering. If there is no default B-tree operator class for a data type, the system will look for a default hash operator class. But since that kind of operator class only provides equality, it is only able to support grouping not sorting. When there is no default operator class for a data type, you will get errors like “could not identify an ordering operator” if you try to use these SQL features with the data type. ### Note In PostgreSQL versions before 7.4, sorting and grouping operations would implicitly use operators named `=`, `<`, and `>`. The new behavior of relying on default operator classes avoids having to make any assumption about the behavior of operators with particular names. Sorting by a non-default B-tree operator class is possible by specifying the class's less-than operator in a `USING` option, for example SELECT \* FROM mytable ORDER BY somecol USING ~<~; Alternatively, specifying the class's greater-than operator in `USING` selects a descending-order sort. Comparison of arrays of a user-defined type also relies on the semantics defined by the type's default B-tree operator class. If there is no default B-tree operator class, but there is a default hash operator class, then array equality is supported, but not ordering comparisons. Another SQL feature that requires even more data-type-specific knowledge is the `RANGE` _`offset`_ `PRECEDING`/`FOLLOWING` framing option for window functions (see [Section 4.2.8](https://www.postgresql.org/docs/18/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS "4.2.8. Window Function Calls") ). For a query such as SELECT sum(x) OVER (ORDER BY x RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING) FROM mytable; it is not sufficient to know how to order by `x`; the database must also understand how to “subtract 5” or “add 10” to the current row's value of `x` to identify the bounds of the current window frame. Comparing the resulting bounds to other rows' values of `x` is possible using the comparison operators provided by the B-tree operator class that defines the `ORDER BY` ordering — but addition and subtraction operators are not part of the operator class, so which ones should be used? Hard-wiring that choice would be undesirable, because different sort orders (different B-tree operator classes) might need different behavior. Therefore, a B-tree operator class can specify an _in\_range_ support function that encapsulates the addition and subtraction behaviors that make sense for its sort order. It can even provide more than one in\_range support function, in case there is more than one data type that makes sense to use as the offset in `RANGE` clauses. If the B-tree operator class associated with the window's `ORDER BY` clause does not have a matching in\_range support function, the `RANGE` _`offset`_ `PRECEDING`/`FOLLOWING` option is not supported. Another important point is that an equality operator that appears in a hash operator family is a candidate for hash joins, hash aggregation, and related optimizations. The hash operator family is essential here since it identifies the hash function(s) to use. ### 36.16.7. Ordering Operators [#](https://www.postgresql.org/docs/18/xindex.html#XINDEX-ORDERING-OPS) Some index access methods (currently, only GiST and SP-GiST) support the concept of _ordering operators_. What we have been discussing so far are _search operators_. A search operator is one for which the index can be searched to find all rows satisfying `WHERE` _`indexed_column`_ _`operator`_ _`constant`_. Note that nothing is promised about the order in which the matching rows will be returned. In contrast, an ordering operator does not restrict the set of rows that can be returned, but instead determines their order. An ordering operator is one for which the index can be scanned to return rows in the order represented by `ORDER BY` _`indexed_column`_ _`operator`_ _`constant`_. The reason for defining ordering operators that way is that it supports nearest-neighbor searches, if the operator is one that measures distance. For example, a query like SELECT \* FROM places ORDER BY location <-> point '(101,456)' LIMIT 10; finds the ten places closest to a given target point. A GiST index on the location column can do this efficiently because `<->` is an ordering operator. While search operators have to return Boolean results, ordering operators usually return some other type, such as float or numeric for distances. This type is normally not the same as the data type being indexed. To avoid hard-wiring assumptions about the behavior of different data types, the definition of an ordering operator is required to name a B-tree operator family that specifies the sort ordering of the result data type. As was stated in the previous section, B-tree operator families define PostgreSQL's notion of ordering, so this is a natural representation. Since the point `<->` operator returns `float8`, it could be specified in an operator class creation command like this: OPERATOR 15 <-> (point, point) FOR ORDER BY float\_ops where `float_ops` is the built-in operator family that includes operations on `float8`. This declaration states that the index is able to return rows in order of increasing values of the `<->` operator. ### 36.16.8. Special Features of Operator Classes [#](https://www.postgresql.org/docs/18/xindex.html#XINDEX-OPCLASS-FEATURES) There are two special features of operator classes that we have not discussed yet, mainly because they are not useful with the most commonly used index methods. Normally, declaring an operator as a member of an operator class (or family) means that the index method can retrieve exactly the set of rows that satisfy a `WHERE` condition using the operator. For example: SELECT \* FROM table WHERE integer\_column < 4; can be satisfied exactly by a B-tree index on the integer column. But there are cases where an index is useful as an inexact guide to the matching rows. For example, if a GiST index stores only bounding boxes for geometric objects, then it cannot exactly satisfy a `WHERE` condition that tests overlap between nonrectangular objects such as polygons. Yet we could use the index to find objects whose bounding box overlaps the bounding box of the target object, and then do the exact overlap test only on the objects found by the index. If this scenario applies, the index is said to be “lossy” for the operator. Lossy index searches are implemented by having the index method return a _recheck_ flag when a row might or might not really satisfy the query condition. The core system will then test the original query condition on the retrieved row to see whether it should be returned as a valid match. This approach works if the index is guaranteed to return all the required rows, plus perhaps some additional rows, which can be eliminated by performing the original operator invocation. The index methods that support lossy searches (currently, GiST, SP-GiST and GIN) allow the support functions of individual operator classes to set the recheck flag, and so this is essentially an operator-class feature. Consider again the situation where we are storing in the index only the bounding box of a complex object such as a polygon. In this case there's not much value in storing the whole polygon in the index entry — we might as well store just a simpler object of type `box`. This situation is expressed by the `STORAGE` option in `CREATE OPERATOR CLASS`: we'd write something like: CREATE OPERATOR CLASS polygon\_ops DEFAULT FOR TYPE polygon USING gist AS ... STORAGE box; At present, only the GiST, SP-GiST, GIN and BRIN index methods support a `STORAGE` type that's different from the column data type. The GiST `compress` and `decompress` support routines must deal with data-type conversion when `STORAGE` is used. SP-GiST likewise requires a `compress` support function to convert to the storage type, when that is different; if an SP-GiST opclass also supports retrieving data, the reverse conversion must be handled by the `consistent` function. In GIN, the `STORAGE` type identifies the type of the “key” values, which normally is different from the type of the indexed column — for example, an operator class for integer-array columns might have keys that are just integers. The GIN `extractValue` and `extractQuery` support routines are responsible for extracting keys from indexed values. BRIN is similar to GIN: the `STORAGE` type identifies the type of the stored summary values, and operator classes' support procedures are responsible for interpreting the summary values correctly. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/xoper-optimization.html "36.15. Operator Optimization Information") | [Up](https://www.postgresql.org/docs/18/extend.html "Chapter 36. Extending SQL") | [Next](https://www.postgresql.org/docs/18/extend-extensions.html "36.17. Packaging Related Objects into an Extension") | | 36.15. Operator Optimization Information | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 36.17. Packaging Related Objects into an Extension | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/xindex.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: DROP RULE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-droprule.html "PostgreSQL 18 - DROP RULE") ([18](https://www.postgresql.org/docs/18/sql-droprule.html "PostgreSQL 18 - DROP RULE") ) / [17](https://www.postgresql.org/docs/17/sql-droprule.html "PostgreSQL 17 - DROP RULE") / [16](https://www.postgresql.org/docs/16/sql-droprule.html "PostgreSQL 16 - DROP RULE") / [15](https://www.postgresql.org/docs/15/sql-droprule.html "PostgreSQL 15 - DROP RULE") / [14](https://www.postgresql.org/docs/14/sql-droprule.html "PostgreSQL 14 - DROP RULE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-droprule.html "PostgreSQL devel - DROP RULE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-droprule.html "PostgreSQL 13 - DROP RULE") / [12](https://www.postgresql.org/docs/12/sql-droprule.html "PostgreSQL 12 - DROP RULE") / [11](https://www.postgresql.org/docs/11/sql-droprule.html "PostgreSQL 11 - DROP RULE") / [10](https://www.postgresql.org/docs/10/sql-droprule.html "PostgreSQL 10 - DROP RULE") / [9.6](https://www.postgresql.org/docs/9.6/sql-droprule.html "PostgreSQL 9.6 - DROP RULE") / [9.5](https://www.postgresql.org/docs/9.5/sql-droprule.html "PostgreSQL 9.5 - DROP RULE") / [9.4](https://www.postgresql.org/docs/9.4/sql-droprule.html "PostgreSQL 9.4 - DROP RULE") / [9.3](https://www.postgresql.org/docs/9.3/sql-droprule.html "PostgreSQL 9.3 - DROP RULE") / [9.2](https://www.postgresql.org/docs/9.2/sql-droprule.html "PostgreSQL 9.2 - DROP RULE") / [9.1](https://www.postgresql.org/docs/9.1/sql-droprule.html "PostgreSQL 9.1 - DROP RULE") / [9.0](https://www.postgresql.org/docs/9.0/sql-droprule.html "PostgreSQL 9.0 - DROP RULE") / [8.4](https://www.postgresql.org/docs/8.4/sql-droprule.html "PostgreSQL 8.4 - DROP RULE") / [8.3](https://www.postgresql.org/docs/8.3/sql-droprule.html "PostgreSQL 8.3 - DROP RULE") / [8.2](https://www.postgresql.org/docs/8.2/sql-droprule.html "PostgreSQL 8.2 - DROP RULE") / [8.1](https://www.postgresql.org/docs/8.1/sql-droprule.html "PostgreSQL 8.1 - DROP RULE") / [8.0](https://www.postgresql.org/docs/8.0/sql-droprule.html "PostgreSQL 8.0 - DROP RULE") / [7.4](https://www.postgresql.org/docs/7.4/sql-droprule.html "PostgreSQL 7.4 - DROP RULE") / [7.3](https://www.postgresql.org/docs/7.3/sql-droprule.html "PostgreSQL 7.3 - DROP RULE") / [7.2](https://www.postgresql.org/docs/7.2/sql-droprule.html "PostgreSQL 7.2 - DROP RULE") / [7.1](https://www.postgresql.org/docs/7.1/sql-droprule.html "PostgreSQL 7.1 - DROP RULE") | DROP RULE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-droproutine.html "DROP ROUTINE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-dropschema.html "DROP SCHEMA") | * * * DROP RULE --------- DROP RULE — remove a rewrite rule Synopsis -------- DROP RULE \[ IF EXISTS \] _`name`_ ON _`table_name`_ \[ CASCADE | RESTRICT \] Description ----------- `DROP RULE` drops a rewrite rule. Parameters ---------- `IF EXISTS` Do not throw an error if the rule does not exist. A notice is issued in this case. _`name`_ The name of the rule to drop. _`table_name`_ The name (optionally schema-qualified) of the table or view that the rule applies to. `CASCADE` Automatically drop objects that depend on the rule, and in turn all objects that depend on those objects (see [Section 5.15](https://www.postgresql.org/docs/18/ddl-depend.html "5.15. Dependency Tracking") ). `RESTRICT` Refuse to drop the rule if any objects depend on it. This is the default. Examples -------- To drop the rewrite rule `newrule`: DROP RULE newrule ON mytable; Compatibility ------------- `DROP RULE` is a PostgreSQL language extension, as is the entire query rewrite system. See Also -------- [CREATE RULE](https://www.postgresql.org/docs/18/sql-createrule.html "CREATE RULE") , [ALTER RULE](https://www.postgresql.org/docs/18/sql-alterrule.html "ALTER RULE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-droproutine.html "DROP ROUTINE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-dropschema.html "DROP SCHEMA") | | DROP ROUTINE | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | DROP SCHEMA | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-droprule.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 5.5. Constraints November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/ddl-constraints.html "PostgreSQL 18 - 5.5. Constraints") ([18](https://www.postgresql.org/docs/18/ddl-constraints.html "PostgreSQL 18 - 5.5. Constraints") ) / [17](https://www.postgresql.org/docs/17/ddl-constraints.html "PostgreSQL 17 - 5.5. Constraints") / [16](https://www.postgresql.org/docs/16/ddl-constraints.html "PostgreSQL 16 - 5.5. Constraints") / [15](https://www.postgresql.org/docs/15/ddl-constraints.html "PostgreSQL 15 - 5.5. Constraints") / [14](https://www.postgresql.org/docs/14/ddl-constraints.html "PostgreSQL 14 - 5.5. Constraints") Development Versions: [devel](https://www.postgresql.org/docs/devel/ddl-constraints.html "PostgreSQL devel - 5.5. Constraints") Unsupported versions: [13](https://www.postgresql.org/docs/13/ddl-constraints.html "PostgreSQL 13 - 5.5. Constraints") / [12](https://www.postgresql.org/docs/12/ddl-constraints.html "PostgreSQL 12 - 5.5. Constraints") / [11](https://www.postgresql.org/docs/11/ddl-constraints.html "PostgreSQL 11 - 5.5. Constraints") / [10](https://www.postgresql.org/docs/10/ddl-constraints.html "PostgreSQL 10 - 5.5. Constraints") / [9.6](https://www.postgresql.org/docs/9.6/ddl-constraints.html "PostgreSQL 9.6 - 5.5. Constraints") / [9.5](https://www.postgresql.org/docs/9.5/ddl-constraints.html "PostgreSQL 9.5 - 5.5. Constraints") / [9.4](https://www.postgresql.org/docs/9.4/ddl-constraints.html "PostgreSQL 9.4 - 5.5. Constraints") / [9.3](https://www.postgresql.org/docs/9.3/ddl-constraints.html "PostgreSQL 9.3 - 5.5. Constraints") / [9.2](https://www.postgresql.org/docs/9.2/ddl-constraints.html "PostgreSQL 9.2 - 5.5. Constraints") / [9.1](https://www.postgresql.org/docs/9.1/ddl-constraints.html "PostgreSQL 9.1 - 5.5. Constraints") / [9.0](https://www.postgresql.org/docs/9.0/ddl-constraints.html "PostgreSQL 9.0 - 5.5. Constraints") / [8.4](https://www.postgresql.org/docs/8.4/ddl-constraints.html "PostgreSQL 8.4 - 5.5. Constraints") / [8.3](https://www.postgresql.org/docs/8.3/ddl-constraints.html "PostgreSQL 8.3 - 5.5. Constraints") / [8.2](https://www.postgresql.org/docs/8.2/ddl-constraints.html "PostgreSQL 8.2 - 5.5. Constraints") / [8.1](https://www.postgresql.org/docs/8.1/ddl-constraints.html "PostgreSQL 8.1 - 5.5. Constraints") / [8.0](https://www.postgresql.org/docs/8.0/ddl-constraints.html "PostgreSQL 8.0 - 5.5. Constraints") / [7.4](https://www.postgresql.org/docs/7.4/ddl-constraints.html "PostgreSQL 7.4 - 5.5. Constraints") / [7.3](https://www.postgresql.org/docs/7.3/ddl-constraints.html "PostgreSQL 7.3 - 5.5. Constraints") | 5.5. Constraints | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/ddl-generated-columns.html "5.4. Generated Columns") | [Up](https://www.postgresql.org/docs/18/ddl.html "Chapter 5. Data Definition") | Chapter 5. Data Definition | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/ddl-system-columns.html "5.6. System Columns") | * * * 5.5. Constraints [#](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS) ---------------------------------------------------------------------------------------------- [5.5.1. Check Constraints](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-CHECK-CONSTRAINTS) [5.5.2. Not-Null Constraints](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-NOT-NULL) [5.5.3. Unique Constraints](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-UNIQUE-CONSTRAINTS) [5.5.4. Primary Keys](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-PRIMARY-KEYS) [5.5.5. Foreign Keys](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-FK) [5.5.6. Exclusion Constraints](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-EXCLUSION) Data types are a way to limit the kind of data that can be stored in a table. For many applications, however, the constraint they provide is too coarse. For example, a column containing a product price should probably only accept positive values. But there is no standard data type that accepts only positive numbers. Another issue is that you might want to constrain column data with respect to other columns or rows. For example, in a table containing product information, there should be only one row for each product number. To that end, SQL allows you to define constraints on columns and tables. Constraints give you as much control over the data in your tables as you wish. If a user attempts to store data in a column that would violate a constraint, an error is raised. This applies even if the value came from the default value definition. ### 5.5.1. Check Constraints [#](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-CHECK-CONSTRAINTS) A check constraint is the most generic constraint type. It allows you to specify that the value in a certain column must satisfy a Boolean (truth-value) expression. For instance, to require positive product prices, you could use: CREATE TABLE products ( product\_no integer, name text, price numeric **CHECK (price > 0)** ); As you see, the constraint definition comes after the data type, just like default value definitions. Default values and constraints can be listed in any order. A check constraint consists of the key word `CHECK` followed by an expression in parentheses. The check constraint expression should involve the column thus constrained, otherwise the constraint would not make too much sense. You can also give the constraint a separate name. This clarifies error messages and allows you to refer to the constraint when you need to change it. The syntax is: CREATE TABLE products ( product\_no integer, name text, price numeric **CONSTRAINT positive\_price** CHECK (price > 0) ); So, to specify a named constraint, use the key word `CONSTRAINT` followed by an identifier followed by the constraint definition. (If you don't specify a constraint name in this way, the system chooses a name for you.) A check constraint can also refer to several columns. Say you store a regular price and a discounted price, and you want to ensure that the discounted price is lower than the regular price: CREATE TABLE products ( product\_no integer, name text, price numeric CHECK (price > 0), discounted\_price numeric CHECK (discounted\_price > 0), **CHECK (price > discounted\_price)** ); The first two constraints should look familiar. The third one uses a new syntax. It is not attached to a particular column, instead it appears as a separate item in the comma-separated column list. Column definitions and these constraint definitions can be listed in mixed order. We say that the first two constraints are column constraints, whereas the third one is a table constraint because it is written separately from any one column definition. Column constraints can also be written as table constraints, while the reverse is not necessarily possible, since a column constraint is supposed to refer to only the column it is attached to. (PostgreSQL doesn't enforce that rule, but you should follow it if you want your table definitions to work with other database systems.) The above example could also be written as: CREATE TABLE products ( product\_no integer, name text, price numeric, CHECK (price > 0), discounted\_price numeric, CHECK (discounted\_price > 0), CHECK (price > discounted\_price) ); or even: CREATE TABLE products ( product\_no integer, name text, price numeric CHECK (price > 0), discounted\_price numeric, CHECK (discounted\_price > 0 AND price > discounted\_price) ); It's a matter of taste. Names can be assigned to table constraints in the same way as column constraints: CREATE TABLE products ( product\_no integer, name text, price numeric, CHECK (price > 0), discounted\_price numeric, CHECK (discounted\_price > 0), **CONSTRAINT valid\_discount** CHECK (price > discounted\_price) ); It should be noted that a check constraint is satisfied if the check expression evaluates to true or the null value. Since most expressions will evaluate to the null value if any operand is null, they will not prevent null values in the constrained columns. To ensure that a column does not contain null values, the not-null constraint described in the next section can be used. ### Note PostgreSQL does not support `CHECK` constraints that reference table data other than the new or updated row being checked. While a `CHECK` constraint that violates this rule may appear to work in simple tests, it cannot guarantee that the database will not reach a state in which the constraint condition is false (due to subsequent changes of the other row(s) involved). This would cause a database dump and restore to fail. The restore could fail even when the complete database state is consistent with the constraint, due to rows not being loaded in an order that will satisfy the constraint. If possible, use `UNIQUE`, `EXCLUDE`, or `FOREIGN KEY` constraints to express cross-row and cross-table restrictions. If what you desire is a one-time check against other rows at row insertion, rather than a continuously-maintained consistency guarantee, a custom [trigger](https://www.postgresql.org/docs/18/triggers.html "Chapter 37. Triggers") can be used to implement that. (This approach avoids the dump/restore problem because pg\_dump does not reinstall triggers until after restoring data, so that the check will not be enforced during a dump/restore.) ### Note PostgreSQL assumes that `CHECK` constraints' conditions are immutable, that is, they will always give the same result for the same input row. This assumption is what justifies examining `CHECK` constraints only when rows are inserted or updated, and not at other times. (The warning above about not referencing other table data is really a special case of this restriction.) An example of a common way to break this assumption is to reference a user-defined function in a `CHECK` expression, and then change the behavior of that function. PostgreSQL does not disallow that, but it will not notice if there are rows in the table that now violate the `CHECK` constraint. That would cause a subsequent database dump and restore to fail. The recommended way to handle such a change is to drop the constraint (using `ALTER TABLE`), adjust the function definition, and re-add the constraint, thereby rechecking it against all table rows. ### 5.5.2. Not-Null Constraints [#](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-NOT-NULL) A not-null constraint simply specifies that a column must not assume the null value. A syntax example: CREATE TABLE products ( product\_no integer **NOT NULL**, name text **NOT NULL**, price numeric ); An explicit constraint name can also be specified, for example: CREATE TABLE products ( product\_no integer NOT NULL, name text **CONSTRAINT products\_name\_not\_null** NOT NULL, price numeric ); A not-null constraint is usually written as a column constraint. The syntax for writing it as a table constraint is CREATE TABLE products ( product\_no integer, name text, price numeric, **NOT NULL product\_no**, **NOT NULL name** ); But this syntax is not standard and mainly intended for use by pg\_dump. A not-null constraint is functionally equivalent to creating a check constraint ``CHECK (_`column_name`_ IS NOT NULL)``, but in PostgreSQL creating an explicit not-null constraint is more efficient. Of course, a column can have more than one constraint. Just write the constraints one after another: CREATE TABLE products ( product\_no integer NOT NULL, name text NOT NULL, price numeric NOT NULL CHECK (price > 0) ); The order doesn't matter. It does not necessarily determine in which order the constraints are checked. However, a column can have at most one explicit not-null constraint. The `NOT NULL` constraint has an inverse: the `NULL` constraint. This does not mean that the column must be null, which would surely be useless. Instead, this simply selects the default behavior that the column might be null. The `NULL` constraint is not present in the SQL standard and should not be used in portable applications. (It was only added to PostgreSQL to be compatible with some other database systems.) Some users, however, like it because it makes it easy to toggle the constraint in a script file. For example, you could start with: CREATE TABLE products ( product\_no integer NULL, name text NULL, price numeric NULL ); and then insert the `NOT` key word where desired. ### Tip In most database designs the majority of columns should be marked not null. ### 5.5.3. Unique Constraints [#](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-UNIQUE-CONSTRAINTS) Unique constraints ensure that the data contained in a column, or a group of columns, is unique among all the rows in the table. The syntax is: CREATE TABLE products ( product\_no integer **UNIQUE**, name text, price numeric ); when written as a column constraint, and: CREATE TABLE products ( product\_no integer, name text, price numeric, **UNIQUE (product\_no)** ); when written as a table constraint. To define a unique constraint for a group of columns, write it as a table constraint with the column names separated by commas: CREATE TABLE example ( a integer, b integer, c integer, **UNIQUE (a, c)** ); This specifies that the combination of values in the indicated columns is unique across the whole table, though any one of the columns need not be (and ordinarily isn't) unique. You can assign your own name for a unique constraint, in the usual way: CREATE TABLE products ( product\_no integer **CONSTRAINT must\_be\_different** UNIQUE, name text, price numeric ); Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint. A uniqueness restriction covering only some rows cannot be written as a unique constraint, but it is possible to enforce such a restriction by creating a unique [partial index](https://www.postgresql.org/docs/18/indexes-partial.html "11.8. Partial Indexes") . In general, a unique constraint is violated if there is more than one row in the table where the values of all of the columns included in the constraint are equal. By default, two null values are not considered equal in this comparison. That means even in the presence of a unique constraint it is possible to store duplicate rows that contain a null value in at least one of the constrained columns. This behavior can be changed by adding the clause `NULLS NOT DISTINCT`, like CREATE TABLE products ( product\_no integer UNIQUE **NULLS NOT DISTINCT**, name text, price numeric ); or CREATE TABLE products ( product\_no integer, name text, price numeric, UNIQUE **NULLS NOT DISTINCT** (product\_no) ); The default behavior can be specified explicitly using `NULLS DISTINCT`. The default null treatment in unique constraints is implementation-defined according to the SQL standard, and other implementations have a different behavior. So be careful when developing applications that are intended to be portable. ### 5.5.4. Primary Keys [#](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-PRIMARY-KEYS) A primary key constraint indicates that a column, or group of columns, can be used as a unique identifier for rows in the table. This requires that the values be both unique and not null. So, the following two table definitions accept the same data: CREATE TABLE products ( product\_no integer UNIQUE NOT NULL, name text, price numeric ); CREATE TABLE products ( product\_no integer **PRIMARY KEY**, name text, price numeric ); Primary keys can span more than one column; the syntax is similar to unique constraints: CREATE TABLE example ( a integer, b integer, c integer, **PRIMARY KEY (a, c)** ); Adding a primary key will automatically create a unique B-tree index on the column or group of columns listed in the primary key, and will force the column(s) to be marked `NOT NULL`. A table can have at most one primary key. (There can be any number of unique constraints, which combined with not-null constraints are functionally almost the same thing, but only one can be identified as the primary key.) Relational database theory dictates that every table must have a primary key. This rule is not enforced by PostgreSQL, but it is usually best to follow it. Primary keys are useful both for documentation purposes and for client applications. For example, a GUI application that allows modifying row values probably needs to know the primary key of a table to be able to identify rows uniquely. There are also various ways in which the database system makes use of a primary key if one has been declared; for example, the primary key defines the default target column(s) for foreign keys referencing its table. ### 5.5.5. Foreign Keys [#](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-FK) A foreign key constraint specifies that the values in a column (or a group of columns) must match the values appearing in some row of another table. We say this maintains the _referential integrity_ between two related tables. Say you have the product table that we have used several times already: CREATE TABLE products ( product\_no integer PRIMARY KEY, name text, price numeric ); Let's also assume you have a table storing orders of those products. We want to ensure that the orders table only contains orders of products that actually exist. So we define a foreign key constraint in the orders table that references the products table: CREATE TABLE orders ( order\_id integer PRIMARY KEY, product\_no integer **REFERENCES products (product\_no)**, quantity integer ); Now it is impossible to create orders with non-NULL `product_no` entries that do not appear in the products table. We say that in this situation the orders table is the _referencing_ table and the products table is the _referenced_ table. Similarly, there are referencing and referenced columns. You can also shorten the above command to: CREATE TABLE orders ( order\_id integer PRIMARY KEY, product\_no integer **REFERENCES products**, quantity integer ); because in absence of a column list the primary key of the referenced table is used as the referenced column(s). You can assign your own name for a foreign key constraint, in the usual way. A foreign key can also constrain and reference a group of columns. As usual, it then needs to be written in table constraint form. Here is a contrived syntax example: CREATE TABLE t1 ( a integer PRIMARY KEY, b integer, c integer, **FOREIGN KEY (b, c) REFERENCES other\_table (c1, c2)** ); Of course, the number and type of the constrained columns need to match the number and type of the referenced columns. Sometimes it is useful for the “other table” of a foreign key constraint to be the same table; this is called a _self-referential_ foreign key. For example, if you want rows of a table to represent nodes of a tree structure, you could write CREATE TABLE tree ( node\_id integer PRIMARY KEY, parent\_id integer REFERENCES tree, name text, ... ); A top-level node would have NULL `parent_id`, while non-NULL `parent_id` entries would be constrained to reference valid rows of the table. A table can have more than one foreign key constraint. This is used to implement many-to-many relationships between tables. Say you have tables about products and orders, but now you want to allow one order to contain possibly many products (which the structure above did not allow). You could use this table structure: CREATE TABLE products ( product\_no integer PRIMARY KEY, name text, price numeric ); CREATE TABLE orders ( order\_id integer PRIMARY KEY, shipping\_address text, ... ); CREATE TABLE order\_items ( product\_no integer REFERENCES products, order\_id integer REFERENCES orders, quantity integer, PRIMARY KEY (product\_no, order\_id) ); Notice that the primary key overlaps with the foreign keys in the last table. We know that the foreign keys disallow creation of orders that do not relate to any products. But what if a product is removed after an order is created that references it? SQL allows you to handle that as well. Intuitively, we have a few options: * Disallow deleting a referenced product * Delete the orders as well * Something else? To illustrate this, let's implement the following policy on the many-to-many relationship example above: when someone wants to remove a product that is still referenced by an order (via `order_items`), we disallow it. If someone removes an order, the order items are removed as well: CREATE TABLE products ( product\_no integer PRIMARY KEY, name text, price numeric ); CREATE TABLE orders ( order\_id integer PRIMARY KEY, shipping\_address text, ... ); CREATE TABLE order\_items ( product\_no integer REFERENCES products **ON DELETE RESTRICT**, order\_id integer REFERENCES orders **ON DELETE CASCADE**, quantity integer, PRIMARY KEY (product\_no, order\_id) ); The default `ON DELETE` action is `ON DELETE NO ACTION`; this does not need to be specified. This means that the deletion in the referenced table is allowed to proceed. But the foreign-key constraint is still required to be satisfied, so this operation will usually result in an error. But checking of foreign-key constraints can also be deferred to later in the transaction (not covered in this chapter). In that case, the `NO ACTION` setting would allow other commands to “fix” the situation before the constraint is checked, for example by inserting another suitable row into the referenced table or by deleting the now-dangling rows from the referencing table. `RESTRICT` is a stricter setting than `NO ACTION`. It prevents deletion of a referenced row. `RESTRICT` does not allow the check to be deferred until later in the transaction. `CASCADE` specifies that when a referenced row is deleted, row(s) referencing it should be automatically deleted as well. There are two other options: `SET NULL` and `SET DEFAULT`. These cause the referencing column(s) in the referencing row(s) to be set to nulls or their default values, respectively, when the referenced row is deleted. Note that these do not excuse you from observing any constraints. For example, if an action specifies `SET DEFAULT` but the default value would not satisfy the foreign key constraint, the operation will fail. The appropriate choice of `ON DELETE` action depends on what kinds of objects the related tables represent. When the referencing table represents something that is a component of what is represented by the referenced table and cannot exist independently, then `CASCADE` could be appropriate. If the two tables represent independent objects, then `RESTRICT` or `NO ACTION` is more appropriate; an application that actually wants to delete both objects would then have to be explicit about this and run two delete commands. In the above example, order items are part of an order, and it is convenient if they are deleted automatically if an order is deleted. But products and orders are different things, and so making a deletion of a product automatically cause the deletion of some order items could be considered problematic. The actions `SET NULL` or `SET DEFAULT` can be appropriate if a foreign-key relationship represents optional information. For example, if the products table contained a reference to a product manager, and the product manager entry gets deleted, then setting the product's product manager to null or a default might be useful. The actions `SET NULL` and `SET DEFAULT` can take a column list to specify which columns to set. Normally, all columns of the foreign-key constraint are set; setting only a subset is useful in some special cases. Consider the following example: CREATE TABLE tenants ( tenant\_id integer PRIMARY KEY ); CREATE TABLE users ( tenant\_id integer REFERENCES tenants ON DELETE CASCADE, user\_id integer NOT NULL, PRIMARY KEY (tenant\_id, user\_id) ); CREATE TABLE posts ( tenant\_id integer REFERENCES tenants ON DELETE CASCADE, post\_id integer NOT NULL, author\_id integer, PRIMARY KEY (tenant\_id, post\_id), FOREIGN KEY (tenant\_id, author\_id) REFERENCES users ON DELETE SET NULL **(author\_id)** ); Without the specification of the column, the foreign key would also set the column `tenant_id` to null, but that column is still required as part of the primary key. Analogous to `ON DELETE` there is also `ON UPDATE` which is invoked when a referenced column is changed (updated). The possible actions are the same, except that column lists cannot be specified for `SET NULL` and `SET DEFAULT`. In this case, `CASCADE` means that the updated values of the referenced column(s) should be copied into the referencing row(s). There is also a noticeable difference between `ON UPDATE NO ACTION` (the default) and `ON UPDATE RESTRICT`. The former will allow the update to proceed and the foreign-key constraint will be checked against the state after the update. The latter will prevent the update to run even if the state after the update would still satisfy the constraint. This prevents updating a referenced row to a value that is distinct but compares as equal (for example, a character string with a different case variant, if a character string type with a case-insensitive collation is used). Normally, a referencing row need not satisfy the foreign key constraint if any of its referencing columns are null. If `MATCH FULL` is added to the foreign key declaration, a referencing row escapes satisfying the constraint only if all its referencing columns are null (so a mix of null and non-null values is guaranteed to fail a `MATCH FULL` constraint). If you don't want referencing rows to be able to avoid satisfying the foreign key constraint, declare the referencing column(s) as `NOT NULL`. A foreign key must reference columns that either are a primary key or form a unique constraint, or are columns from a non-partial unique index. This means that the referenced columns always have an index to allow efficient lookups on whether a referencing row has a match. Since a `DELETE` of a row from the referenced table or an `UPDATE` of a referenced column will require a scan of the referencing table for rows matching the old value, it is often a good idea to index the referencing columns too. Because this is not always needed, and there are many choices available on how to index, the declaration of a foreign key constraint does not automatically create an index on the referencing columns. More information about updating and deleting data is in [Chapter 6](https://www.postgresql.org/docs/18/dml.html "Chapter 6. Data Manipulation") . Also see the description of foreign key constraint syntax in the reference documentation for [CREATE TABLE](https://www.postgresql.org/docs/18/sql-createtable.html "CREATE TABLE") . ### 5.5.6. Exclusion Constraints [#](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-EXCLUSION) Exclusion constraints ensure that if any two rows are compared on the specified columns or expressions using the specified operators, at least one of these operator comparisons will return false or null. The syntax is: CREATE TABLE circles ( c circle, EXCLUDE USING gist (c WITH &&) ); See also [`CREATE TABLE ... CONSTRAINT ... EXCLUDE`](https://www.postgresql.org/docs/18/sql-createtable.html#SQL-CREATETABLE-EXCLUDE) for details. Adding an exclusion constraint will automatically create an index of the type specified in the constraint declaration. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/ddl-generated-columns.html "5.4. Generated Columns") | [Up](https://www.postgresql.org/docs/18/ddl.html "Chapter 5. Data Definition") | [Next](https://www.postgresql.org/docs/18/ddl-system-columns.html "5.6. System Columns") | | 5.4. Generated Columns | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 5.6. System Columns | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/ddl-constraints.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 36.16. Interfacing Extensions to Indexes November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/xindex.html "PostgreSQL 18 - 36.16. Interfacing Extensions to Indexes") ([18](https://www.postgresql.org/docs/18/xindex.html "PostgreSQL 18 - 36.16. Interfacing Extensions to Indexes") ) / [17](https://www.postgresql.org/docs/17/xindex.html "PostgreSQL 17 - 36.16. Interfacing Extensions to Indexes") / [16](https://www.postgresql.org/docs/16/xindex.html "PostgreSQL 16 - 36.16. Interfacing Extensions to Indexes") / [15](https://www.postgresql.org/docs/15/xindex.html "PostgreSQL 15 - 36.16. Interfacing Extensions to Indexes") / [14](https://www.postgresql.org/docs/14/xindex.html "PostgreSQL 14 - 36.16. Interfacing Extensions to Indexes") Development Versions: [devel](https://www.postgresql.org/docs/devel/xindex.html "PostgreSQL devel - 36.16. Interfacing Extensions to Indexes") Unsupported versions: [13](https://www.postgresql.org/docs/13/xindex.html "PostgreSQL 13 - 36.16. Interfacing Extensions to Indexes") / [12](https://www.postgresql.org/docs/12/xindex.html "PostgreSQL 12 - 36.16. Interfacing Extensions to Indexes") / [11](https://www.postgresql.org/docs/11/xindex.html "PostgreSQL 11 - 36.16. Interfacing Extensions to Indexes") / [10](https://www.postgresql.org/docs/10/xindex.html "PostgreSQL 10 - 36.16. Interfacing Extensions to Indexes") / [9.6](https://www.postgresql.org/docs/9.6/xindex.html "PostgreSQL 9.6 - 36.16. Interfacing Extensions to Indexes") / [9.5](https://www.postgresql.org/docs/9.5/xindex.html "PostgreSQL 9.5 - 36.16. Interfacing Extensions to Indexes") / [9.4](https://www.postgresql.org/docs/9.4/xindex.html "PostgreSQL 9.4 - 36.16. Interfacing Extensions to Indexes") / [9.3](https://www.postgresql.org/docs/9.3/xindex.html "PostgreSQL 9.3 - 36.16. Interfacing Extensions to Indexes") / [9.2](https://www.postgresql.org/docs/9.2/xindex.html "PostgreSQL 9.2 - 36.16. Interfacing Extensions to Indexes") / [9.1](https://www.postgresql.org/docs/9.1/xindex.html "PostgreSQL 9.1 - 36.16. Interfacing Extensions to Indexes") / [9.0](https://www.postgresql.org/docs/9.0/xindex.html "PostgreSQL 9.0 - 36.16. Interfacing Extensions to Indexes") / [8.4](https://www.postgresql.org/docs/8.4/xindex.html "PostgreSQL 8.4 - 36.16. Interfacing Extensions to Indexes") / [8.3](https://www.postgresql.org/docs/8.3/xindex.html "PostgreSQL 8.3 - 36.16. Interfacing Extensions to Indexes") / [8.2](https://www.postgresql.org/docs/8.2/xindex.html "PostgreSQL 8.2 - 36.16. Interfacing Extensions to Indexes") / [8.1](https://www.postgresql.org/docs/8.1/xindex.html "PostgreSQL 8.1 - 36.16. Interfacing Extensions to Indexes") / [8.0](https://www.postgresql.org/docs/8.0/xindex.html "PostgreSQL 8.0 - 36.16. Interfacing Extensions to Indexes") / [7.4](https://www.postgresql.org/docs/7.4/xindex.html "PostgreSQL 7.4 - 36.16. Interfacing Extensions to Indexes") / [7.3](https://www.postgresql.org/docs/7.3/xindex.html "PostgreSQL 7.3 - 36.16. Interfacing Extensions to Indexes") / [7.2](https://www.postgresql.org/docs/7.2/xindex.html "PostgreSQL 7.2 - 36.16. Interfacing Extensions to Indexes") / [7.1](https://www.postgresql.org/docs/7.1/xindex.html "PostgreSQL 7.1 - 36.16. Interfacing Extensions to Indexes") | 36.16. Interfacing Extensions to Indexes | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/xoper-optimization.html "36.15. Operator Optimization Information") | [Up](https://www.postgresql.org/docs/current/extend.html "Chapter 36. Extending SQL") | Chapter 36. Extending SQL | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/extend-extensions.html "36.17. Packaging Related Objects into an Extension") | * * * 36.16. Interfacing Extensions to Indexes [#](https://www.postgresql.org/docs/current/xindex.html#XINDEX) --------------------------------------------------------------------------------------------------------- [36.16.1. Index Methods and Operator Classes](https://www.postgresql.org/docs/current/xindex.html#XINDEX-OPCLASS) [36.16.2. Index Method Strategies](https://www.postgresql.org/docs/current/xindex.html#XINDEX-STRATEGIES) [36.16.3. Index Method Support Routines](https://www.postgresql.org/docs/current/xindex.html#XINDEX-SUPPORT) [36.16.4. An Example](https://www.postgresql.org/docs/current/xindex.html#XINDEX-EXAMPLE) [36.16.5. Operator Classes and Operator Families](https://www.postgresql.org/docs/current/xindex.html#XINDEX-OPFAMILY) [36.16.6. System Dependencies on Operator Classes](https://www.postgresql.org/docs/current/xindex.html#XINDEX-OPCLASS-DEPENDENCIES) [36.16.7. Ordering Operators](https://www.postgresql.org/docs/current/xindex.html#XINDEX-ORDERING-OPS) [36.16.8. Special Features of Operator Classes](https://www.postgresql.org/docs/current/xindex.html#XINDEX-OPCLASS-FEATURES) The procedures described thus far let you define new types, new functions, and new operators. However, we cannot yet define an index on a column of a new data type. To do this, we must define an _operator class_ for the new data type. Later in this section, we will illustrate this concept in an example: a new operator class for the B-tree index method that stores and sorts complex numbers in ascending absolute value order. Operator classes can be grouped into _operator families_ to show the relationships between semantically compatible classes. When only a single data type is involved, an operator class is sufficient, so we'll focus on that case first and then return to operator families. ### 36.16.1. Index Methods and Operator Classes [#](https://www.postgresql.org/docs/current/xindex.html#XINDEX-OPCLASS) Operator classes are associated with an index access method, such as [B-Tree](https://www.postgresql.org/docs/current/btree.html "65.1. B-Tree Indexes") or [GIN](https://www.postgresql.org/docs/current/gin.html "65.4. GIN Indexes") . Custom index access method may be defined with [CREATE ACCESS METHOD](https://www.postgresql.org/docs/current/sql-create-access-method.html "CREATE ACCESS METHOD") . See [Chapter 63](https://www.postgresql.org/docs/current/indexam.html "Chapter 63. Index Access Method Interface Definition") for details. The routines for an index method do not directly know anything about the data types that the index method will operate on. Instead, an _operator class_ identifies the set of operations that the index method needs to use to work with a particular data type. Operator classes are so called because one thing they specify is the set of `WHERE`\-clause operators that can be used with an index (i.e., can be converted into an index-scan qualification). An operator class can also specify some _support function_ that are needed by the internal operations of the index method, but do not directly correspond to any `WHERE`\-clause operator that can be used with the index. It is possible to define multiple operator classes for the same data type and index method. By doing this, multiple sets of indexing semantics can be defined for a single data type. For example, a B-tree index requires a sort ordering to be defined for each data type it works on. It might be useful for a complex-number data type to have one B-tree operator class that sorts the data by complex absolute value, another that sorts by real part, and so on. Typically, one of the operator classes will be deemed most commonly useful and will be marked as the default operator class for that data type and index method. The same operator class name can be used for several different index methods (for example, both B-tree and hash index methods have operator classes named `int4_ops`), but each such class is an independent entity and must be defined separately. ### 36.16.2. Index Method Strategies [#](https://www.postgresql.org/docs/current/xindex.html#XINDEX-STRATEGIES) The operators associated with an operator class are identified by “strategy numbers”, which serve to identify the semantics of each operator within the context of its operator class. For example, B-trees impose a strict ordering on keys, lesser to greater, and so operators like “less than” and “greater than or equal to” are interesting with respect to a B-tree. Because PostgreSQL allows the user to define operators, PostgreSQL cannot look at the name of an operator (e.g., `<` or `>=`) and tell what kind of comparison it is. Instead, the index method defines a set of “strategies”, which can be thought of as generalized operators. Each operator class specifies which actual operator corresponds to each strategy for a particular data type and interpretation of the index semantics. The B-tree index method defines five strategies, shown in [Table 36.3](https://www.postgresql.org/docs/current/xindex.html#XINDEX-BTREE-STRAT-TABLE "Table 36.3. B-Tree Strategies") . **Table 36.3. B-Tree Strategies** | Operation | Strategy Number | | --- | --- | | less than | 1 | | less than or equal | 2 | | equal | 3 | | greater than or equal | 4 | | greater than | 5 | Hash indexes support only equality comparisons, and so they use only one strategy, shown in [Table 36.4](https://www.postgresql.org/docs/current/xindex.html#XINDEX-HASH-STRAT-TABLE "Table 36.4. Hash Strategies") . **Table 36.4. Hash Strategies** | Operation | Strategy Number | | --- | --- | | equal | 1 | GiST indexes are more flexible: they do not have a fixed set of strategies at all. Instead, the “consistency” support routine of each particular GiST operator class interprets the strategy numbers however it likes. As an example, several of the built-in GiST index operator classes index two-dimensional geometric objects, providing the “R-tree” strategies shown in [Table 36.5](https://www.postgresql.org/docs/current/xindex.html#XINDEX-RTREE-STRAT-TABLE "Table 36.5. GiST Two-Dimensional “R-tree” Strategies") . Four of these are true two-dimensional tests (overlaps, same, contains, contained by); four of them consider only the X direction; and the other four provide the same tests in the Y direction. **Table 36.5. GiST Two-Dimensional “R-tree” Strategies** | Operation | Strategy Number | | --- | --- | | strictly left of | 1 | | does not extend to right of | 2 | | overlaps | 3 | | does not extend to left of | 4 | | strictly right of | 5 | | same | 6 | | contains | 7 | | contained by | 8 | | does not extend above | 9 | | strictly below | 10 | | strictly above | 11 | | does not extend below | 12 | SP-GiST indexes are similar to GiST indexes in flexibility: they don't have a fixed set of strategies. Instead the support routines of each operator class interpret the strategy numbers according to the operator class's definition. As an example, the strategy numbers used by the built-in operator classes for points are shown in [Table 36.6](https://www.postgresql.org/docs/current/xindex.html#XINDEX-SPGIST-POINT-STRAT-TABLE "Table 36.6. SP-GiST Point Strategies") . **Table 36.6. SP-GiST Point Strategies** | Operation | Strategy Number | | --- | --- | | strictly left of | 1 | | strictly right of | 5 | | same | 6 | | contained by | 8 | | strictly below | 10 | | strictly above | 11 | GIN indexes are similar to GiST and SP-GiST indexes, in that they don't have a fixed set of strategies either. Instead the support routines of each operator class interpret the strategy numbers according to the operator class's definition. As an example, the strategy numbers used by the built-in operator class for arrays are shown in [Table 36.7](https://www.postgresql.org/docs/current/xindex.html#XINDEX-GIN-ARRAY-STRAT-TABLE "Table 36.7. GIN Array Strategies") . **Table 36.7. GIN Array Strategies** | Operation | Strategy Number | | --- | --- | | overlap | 1 | | contains | 2 | | is contained by | 3 | | equal | 4 | BRIN indexes are similar to GiST, SP-GiST and GIN indexes in that they don't have a fixed set of strategies either. Instead the support routines of each operator class interpret the strategy numbers according to the operator class's definition. As an example, the strategy numbers used by the built-in `Minmax` operator classes are shown in [Table 36.8](https://www.postgresql.org/docs/current/xindex.html#XINDEX-BRIN-MINMAX-STRAT-TABLE "Table 36.8. BRIN Minmax Strategies") . **Table 36.8. BRIN Minmax Strategies** | Operation | Strategy Number | | --- | --- | | less than | 1 | | less than or equal | 2 | | equal | 3 | | greater than or equal | 4 | | greater than | 5 | Notice that all the operators listed above return Boolean values. In practice, all operators defined as index method search operators must return type `boolean`, since they must appear at the top level of a `WHERE` clause to be used with an index. (Some index access methods also support _ordering operators_, which typically don't return Boolean values; that feature is discussed in [Section 36.16.7](https://www.postgresql.org/docs/current/xindex.html#XINDEX-ORDERING-OPS "36.16.7. Ordering Operators") .) ### 36.16.3. Index Method Support Routines [#](https://www.postgresql.org/docs/current/xindex.html#XINDEX-SUPPORT) Strategies aren't usually enough information for the system to figure out how to use an index. In practice, the index methods require additional support routines in order to work. For example, the B-tree index method must be able to compare two keys and determine whether one is greater than, equal to, or less than the other. Similarly, the hash index method must be able to compute hash codes for key values. These operations do not correspond to operators used in qualifications in SQL commands; they are administrative routines used by the index methods, internally. Just as with strategies, the operator class identifies which specific functions should play each of these roles for a given data type and semantic interpretation. The index method defines the set of functions it needs, and the operator class identifies the correct functions to use by assigning them to the “support function numbers” specified by the index method. Additionally, some opclasses allow users to specify parameters which control their behavior. Each builtin index access method has an optional `options` support function, which defines a set of opclass-specific parameters. B-trees require a comparison support function, and allow four additional support functions to be supplied at the operator class author's option, as shown in [Table 36.9](https://www.postgresql.org/docs/current/xindex.html#XINDEX-BTREE-SUPPORT-TABLE "Table 36.9. B-Tree Support Functions") . The requirements for these support functions are explained further in [Section 65.1.3](https://www.postgresql.org/docs/current/btree.html#BTREE-SUPPORT-FUNCS "65.1.3. B-Tree Support Functions") . **Table 36.9. B-Tree Support Functions** | Function | Support Number | | --- | --- | | Compare two keys and return an integer less than zero, zero, or greater than zero, indicating whether the first key is less than, equal to, or greater than the second | 1 | | Return the addresses of C-callable sort support function(s) (optional) | 2 | | Compare a test value to a base value plus/minus an offset, and return true or false according to the comparison result (optional) | 3 | | Determine if it is safe for indexes that use the operator class to apply the btree deduplication optimization (optional) | 4 | | Define options that are specific to this operator class (optional) | 5 | | Return the addresses of C-callable skip support function(s) (optional) | 6 | Hash indexes require one support function, and allow two additional ones to be supplied at the operator class author's option, as shown in [Table 36.10](https://www.postgresql.org/docs/current/xindex.html#XINDEX-HASH-SUPPORT-TABLE "Table 36.10. Hash Support Functions") . **Table 36.10. Hash Support Functions** | Function | Support Number | | --- | --- | | Compute the 32-bit hash value for a key | 1 | | Compute the 64-bit hash value for a key given a 64-bit salt; if the salt is 0, the low 32 bits of the result must match the value that would have been computed by function 1 (optional) | 2 | | Define options that are specific to this operator class (optional) | 3 | GiST indexes have twelve support functions, seven of which are optional, as shown in [Table 36.11](https://www.postgresql.org/docs/current/xindex.html#XINDEX-GIST-SUPPORT-TABLE "Table 36.11. GiST Support Functions") . (For more information see [Section 65.2](https://www.postgresql.org/docs/current/gist.html "65.2. GiST Indexes") .) **Table 36.11. GiST Support Functions** | Function | Description | Support Number | | --- | --- | --- | | `consistent` | determine whether key satisfies the query qualifier | 1 | | `union` | compute union of a set of keys | 2 | | `compress` | compute a compressed representation of a key or value to be indexed (optional) | 3 | | `decompress` | compute a decompressed representation of a compressed key (optional) | 4 | | `penalty` | compute penalty for inserting new key into subtree with given subtree's key | 5 | | `picksplit` | determine which entries of a page are to be moved to the new page and compute the union keys for resulting pages | 6 | | `same` | compare two keys and return true if they are equal | 7 | | `distance` | determine distance from key to query value (optional) | 8 | | `fetch` | compute original representation of a compressed key for index-only scans (optional) | 9 | | `options` | define options that are specific to this operator class (optional) | 10 | | `sortsupport` | provide a sort comparator to be used in fast index builds (optional) | 11 | | `translate_cmptype` | translate compare types to strategy numbers used by the operator class (optional) | 12 | SP-GiST indexes have six support functions, one of which is optional, as shown in [Table 36.12](https://www.postgresql.org/docs/current/xindex.html#XINDEX-SPGIST-SUPPORT-TABLE "Table 36.12. SP-GiST Support Functions") . (For more information see [Section 65.3](https://www.postgresql.org/docs/current/spgist.html "65.3. SP-GiST Indexes") .) **Table 36.12. SP-GiST Support Functions** | Function | Description | Support Number | | --- | --- | --- | | `config` | provide basic information about the operator class | 1 | | `choose` | determine how to insert a new value into an inner tuple | 2 | | `picksplit` | determine how to partition a set of values | 3 | | `inner_consistent` | determine which sub-partitions need to be searched for a query | 4 | | `leaf_consistent` | determine whether key satisfies the query qualifier | 5 | | `options` | define options that are specific to this operator class (optional) | 6 | GIN indexes have seven support functions, four of which are optional, as shown in [Table 36.13](https://www.postgresql.org/docs/current/xindex.html#XINDEX-GIN-SUPPORT-TABLE "Table 36.13. GIN Support Functions") . (For more information see [Section 65.4](https://www.postgresql.org/docs/current/gin.html "65.4. GIN Indexes") .) **Table 36.13. GIN Support Functions** | Function | Description | Support Number | | --- | --- | --- | | `compare` | compare two keys and return an integer less than zero, zero, or greater than zero, indicating whether the first key is less than, equal to, or greater than the second | 1 | | `extractValue` | extract keys from a value to be indexed | 2 | | `extractQuery` | extract keys from a query condition | 3 | | `consistent` | determine whether value matches query condition (Boolean variant) (optional if support function 6 is present) | 4 | | `comparePartial` | compare partial key from query and key from index, and return an integer less than zero, zero, or greater than zero, indicating whether GIN should ignore this index entry, treat the entry as a match, or stop the index scan (optional) | 5 | | `triConsistent` | determine whether value matches query condition (ternary variant) (optional if support function 4 is present) | 6 | | `options` | define options that are specific to this operator class (optional) | 7 | BRIN indexes have five basic support functions, one of which is optional, as shown in [Table 36.14](https://www.postgresql.org/docs/current/xindex.html#XINDEX-BRIN-SUPPORT-TABLE "Table 36.14. BRIN Support Functions") . Some versions of the basic functions require additional support functions to be provided. (For more information see [Section 65.5.3](https://www.postgresql.org/docs/current/brin.html#BRIN-EXTENSIBILITY "65.5.3. Extensibility") .) **Table 36.14. BRIN Support Functions** | Function | Description | Support Number | | --- | --- | --- | | `opcInfo` | return internal information describing the indexed columns' summary data | 1 | | `add_value` | add a new value to an existing summary index tuple | 2 | | `consistent` | determine whether value matches query condition | 3 | | `union` | compute union of two summary tuples | 4 | | `options` | define options that are specific to this operator class (optional) | 5 | Unlike search operators, support functions return whichever data type the particular index method expects; for example in the case of the comparison function for B-trees, a signed integer. The number and types of the arguments to each support function are likewise dependent on the index method. For B-tree and hash the comparison and hashing support functions take the same input data types as do the operators included in the operator class, but this is not the case for most GiST, SP-GiST, GIN, and BRIN support functions. ### 36.16.4. An Example [#](https://www.postgresql.org/docs/current/xindex.html#XINDEX-EXAMPLE) Now that we have seen the ideas, here is the promised example of creating a new operator class. (You can find a working copy of this example in `src/tutorial/complex.c` and `src/tutorial/complex.sql` in the source distribution.) The operator class encapsulates operators that sort complex numbers in absolute value order, so we choose the name `complex_abs_ops`. First, we need a set of operators. The procedure for defining operators was discussed in [Section 36.14](https://www.postgresql.org/docs/current/xoper.html "36.14. User-Defined Operators") . For an operator class on B-trees, the operators we require are: * absolute-value less-than (strategy 1) * absolute-value less-than-or-equal (strategy 2) * absolute-value equal (strategy 3) * absolute-value greater-than-or-equal (strategy 4) * absolute-value greater-than (strategy 5) The least error-prone way to define a related set of comparison operators is to write the B-tree comparison support function first, and then write the other functions as one-line wrappers around the support function. This reduces the odds of getting inconsistent results for corner cases. Following this approach, we first write: #define Mag(c) ((c)->x\*(c)->x + (c)->y\*(c)->y) static int complex\_abs\_cmp\_internal(Complex \*a, Complex \*b) { double amag = Mag(a), bmag = Mag(b); if (amag < bmag) return -1; if (amag > bmag) return 1; return 0; } Now the less-than function looks like: PG\_FUNCTION\_INFO\_V1(complex\_abs\_lt); Datum complex\_abs\_lt(PG\_FUNCTION\_ARGS) { Complex \*a = (Complex \*) PG\_GETARG\_POINTER(0); Complex \*b = (Complex \*) PG\_GETARG\_POINTER(1); PG\_RETURN\_BOOL(complex\_abs\_cmp\_internal(a, b) < 0); } The other four functions differ only in how they compare the internal function's result to zero. Next we declare the functions and the operators based on the functions to SQL: CREATE FUNCTION complex\_abs\_lt(complex, complex) RETURNS bool AS '_`filename`_', 'complex\_abs\_lt' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR < ( leftarg = complex, rightarg = complex, procedure = complex\_abs\_lt, commutator = > , negator = >= , restrict = scalarltsel, join = scalarltjoinsel ); It is important to specify the correct commutator and negator operators, as well as suitable restriction and join selectivity functions, otherwise the optimizer will be unable to make effective use of the index. Other things worth noting are happening here: * There can only be one operator named, say, `=` and taking type `complex` for both operands. In this case we don't have any other operator `=` for `complex`, but if we were building a practical data type we'd probably want `=` to be the ordinary equality operation for complex numbers (and not the equality of the absolute values). In that case, we'd need to use some other operator name for `complex_abs_eq`. * Although PostgreSQL can cope with functions having the same SQL name as long as they have different argument data types, C can only cope with one global function having a given name. So we shouldn't name the C function something simple like `abs_eq`. Usually it's a good practice to include the data type name in the C function name, so as not to conflict with functions for other data types. * We could have made the SQL name of the function `abs_eq`, relying on PostgreSQL to distinguish it by argument data types from any other SQL function of the same name. To keep the example simple, we make the function have the same names at the C level and SQL level. The next step is the registration of the support routine required by B-trees. The example C code that implements this is in the same file that contains the operator functions. This is how we declare the function: CREATE FUNCTION complex\_abs\_cmp(complex, complex) RETURNS integer AS '_`filename`_' LANGUAGE C IMMUTABLE STRICT; Now that we have the required operators and support routine, we can finally create the operator class: CREATE OPERATOR CLASS complex\_abs\_ops DEFAULT FOR TYPE complex USING btree AS OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 complex\_abs\_cmp(complex, complex); And we're done! It should now be possible to create and use B-tree indexes on `complex` columns. We could have written the operator entries more verbosely, as in: OPERATOR 1 < (complex, complex) , but there is no need to do so when the operators take the same data type we are defining the operator class for. The above example assumes that you want to make this new operator class the default B-tree operator class for the `complex` data type. If you don't, just leave out the word `DEFAULT`. ### 36.16.5. Operator Classes and Operator Families [#](https://www.postgresql.org/docs/current/xindex.html#XINDEX-OPFAMILY) So far we have implicitly assumed that an operator class deals with only one data type. While there certainly can be only one data type in a particular index column, it is often useful to index operations that compare an indexed column to a value of a different data type. Also, if there is use for a cross-data-type operator in connection with an operator class, it is often the case that the other data type has a related operator class of its own. It is helpful to make the connections between related classes explicit, because this can aid the planner in optimizing SQL queries (particularly for B-tree operator classes, since the planner contains a great deal of knowledge about how to work with them). To handle these needs, PostgreSQL uses the concept of an _operator family_. An operator family contains one or more operator classes, and can also contain indexable operators and corresponding support functions that belong to the family as a whole but not to any single class within the family. We say that such operators and functions are “loose” within the family, as opposed to being bound into a specific class. Typically each operator class contains single-data-type operators while cross-data-type operators are loose in the family. All the operators and functions in an operator family must have compatible semantics, where the compatibility requirements are set by the index method. You might therefore wonder why bother to single out particular subsets of the family as operator classes; and indeed for many purposes the class divisions are irrelevant and the family is the only interesting grouping. The reason for defining operator classes is that they specify how much of the family is needed to support any particular index. If there is an index using an operator class, then that operator class cannot be dropped without dropping the index — but other parts of the operator family, namely other operator classes and loose operators, could be dropped. Thus, an operator class should be specified to contain the minimum set of operators and functions that are reasonably needed to work with an index on a specific data type, and then related but non-essential operators can be added as loose members of the operator family. As an example, PostgreSQL has a built-in B-tree operator family `integer_ops`, which includes operator classes `int8_ops`, `int4_ops`, and `int2_ops` for indexes on `bigint` (`int8`), `integer` (`int4`), and `smallint` (`int2`) columns respectively. The family also contains cross-data-type comparison operators allowing any two of these types to be compared, so that an index on one of these types can be searched using a comparison value of another type. The family could be duplicated by these definitions: CREATE OPERATOR FAMILY integer\_ops USING btree; CREATE OPERATOR CLASS int8\_ops DEFAULT FOR TYPE int8 USING btree FAMILY integer\_ops AS -- standard int8 comparisons OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 btint8cmp(int8, int8) , FUNCTION 2 btint8sortsupport(internal) , FUNCTION 3 in\_range(int8, int8, int8, boolean, boolean) , FUNCTION 4 btequalimage(oid) , FUNCTION 6 btint8skipsupport(internal) ; CREATE OPERATOR CLASS int4\_ops DEFAULT FOR TYPE int4 USING btree FAMILY integer\_ops AS -- standard int4 comparisons OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 btint4cmp(int4, int4) , FUNCTION 2 btint4sortsupport(internal) , FUNCTION 3 in\_range(int4, int4, int4, boolean, boolean) , FUNCTION 4 btequalimage(oid) , FUNCTION 6 btint4skipsupport(internal) ; CREATE OPERATOR CLASS int2\_ops DEFAULT FOR TYPE int2 USING btree FAMILY integer\_ops AS -- standard int2 comparisons OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 btint2cmp(int2, int2) , FUNCTION 2 btint2sortsupport(internal) , FUNCTION 3 in\_range(int2, int2, int2, boolean, boolean) , FUNCTION 4 btequalimage(oid) , FUNCTION 6 btint2skipsupport(internal) ; ALTER OPERATOR FAMILY integer\_ops USING btree ADD -- cross-type comparisons int8 vs int2 OPERATOR 1 < (int8, int2) , OPERATOR 2 <= (int8, int2) , OPERATOR 3 = (int8, int2) , OPERATOR 4 >= (int8, int2) , OPERATOR 5 > (int8, int2) , FUNCTION 1 btint82cmp(int8, int2) , -- cross-type comparisons int8 vs int4 OPERATOR 1 < (int8, int4) , OPERATOR 2 <= (int8, int4) , OPERATOR 3 = (int8, int4) , OPERATOR 4 >= (int8, int4) , OPERATOR 5 > (int8, int4) , FUNCTION 1 btint84cmp(int8, int4) , -- cross-type comparisons int4 vs int2 OPERATOR 1 < (int4, int2) , OPERATOR 2 <= (int4, int2) , OPERATOR 3 = (int4, int2) , OPERATOR 4 >= (int4, int2) , OPERATOR 5 > (int4, int2) , FUNCTION 1 btint42cmp(int4, int2) , -- cross-type comparisons int4 vs int8 OPERATOR 1 < (int4, int8) , OPERATOR 2 <= (int4, int8) , OPERATOR 3 = (int4, int8) , OPERATOR 4 >= (int4, int8) , OPERATOR 5 > (int4, int8) , FUNCTION 1 btint48cmp(int4, int8) , -- cross-type comparisons int2 vs int8 OPERATOR 1 < (int2, int8) , OPERATOR 2 <= (int2, int8) , OPERATOR 3 = (int2, int8) , OPERATOR 4 >= (int2, int8) , OPERATOR 5 > (int2, int8) , FUNCTION 1 btint28cmp(int2, int8) , -- cross-type comparisons int2 vs int4 OPERATOR 1 < (int2, int4) , OPERATOR 2 <= (int2, int4) , OPERATOR 3 = (int2, int4) , OPERATOR 4 >= (int2, int4) , OPERATOR 5 > (int2, int4) , FUNCTION 1 btint24cmp(int2, int4) , -- cross-type in\_range functions FUNCTION 3 in\_range(int4, int4, int8, boolean, boolean) , FUNCTION 3 in\_range(int4, int4, int2, boolean, boolean) , FUNCTION 3 in\_range(int2, int2, int8, boolean, boolean) , FUNCTION 3 in\_range(int2, int2, int4, boolean, boolean) ; Notice that this definition “overloads” the operator strategy and support function numbers: each number occurs multiple times within the family. This is allowed so long as each instance of a particular number has distinct input data types. The instances that have both input types equal to an operator class's input type are the primary operators and support functions for that operator class, and in most cases should be declared as part of the operator class rather than as loose members of the family. In a B-tree operator family, all the operators in the family must sort compatibly, as is specified in detail in [Section 65.1.2](https://www.postgresql.org/docs/current/btree.html#BTREE-BEHAVIOR "65.1.2. Behavior of B-Tree Operator Classes") . For each operator in the family there must be a support function having the same two input data types as the operator. It is recommended that a family be complete, i.e., for each combination of data types, all operators are included. Each operator class should include just the non-cross-type operators and support function for its data type. To build a multiple-data-type hash operator family, compatible hash support functions must be created for each data type supported by the family. Here compatibility means that the functions are guaranteed to return the same hash code for any two values that are considered equal by the family's equality operators, even when the values are of different types. This is usually difficult to accomplish when the types have different physical representations, but it can be done in some cases. Furthermore, casting a value from one data type represented in the operator family to another data type also represented in the operator family via an implicit or binary coercion cast must not change the computed hash value. Notice that there is only one support function per data type, not one per equality operator. It is recommended that a family be complete, i.e., provide an equality operator for each combination of data types. Each operator class should include just the non-cross-type equality operator and the support function for its data type. GiST, SP-GiST, and GIN indexes do not have any explicit notion of cross-data-type operations. The set of operators supported is just whatever the primary support functions for a given operator class can handle. In BRIN, the requirements depends on the framework that provides the operator classes. For operator classes based on `minmax`, the behavior required is the same as for B-tree operator families: all the operators in the family must sort compatibly, and casts must not change the associated sort ordering. ### Note Prior to PostgreSQL 8.3, there was no concept of operator families, and so any cross-data-type operators intended to be used with an index had to be bound directly into the index's operator class. While this approach still works, it is deprecated because it makes an index's dependencies too broad, and because the planner can handle cross-data-type comparisons more effectively when both data types have operators in the same operator family. ### 36.16.6. System Dependencies on Operator Classes [#](https://www.postgresql.org/docs/current/xindex.html#XINDEX-OPCLASS-DEPENDENCIES) PostgreSQL uses operator classes to infer the properties of operators in more ways than just whether they can be used with indexes. Therefore, you might want to create operator classes even if you have no intention of indexing any columns of your data type. In particular, there are SQL features such as `ORDER BY` and `DISTINCT` that require comparison and sorting of values. To implement these features on a user-defined data type, PostgreSQL looks for the default B-tree operator class for the data type. The “equals” member of this operator class defines the system's notion of equality of values for `GROUP BY` and `DISTINCT`, and the sort ordering imposed by the operator class defines the default `ORDER BY` ordering. If there is no default B-tree operator class for a data type, the system will look for a default hash operator class. But since that kind of operator class only provides equality, it is only able to support grouping not sorting. When there is no default operator class for a data type, you will get errors like “could not identify an ordering operator” if you try to use these SQL features with the data type. ### Note In PostgreSQL versions before 7.4, sorting and grouping operations would implicitly use operators named `=`, `<`, and `>`. The new behavior of relying on default operator classes avoids having to make any assumption about the behavior of operators with particular names. Sorting by a non-default B-tree operator class is possible by specifying the class's less-than operator in a `USING` option, for example SELECT \* FROM mytable ORDER BY somecol USING ~<~; Alternatively, specifying the class's greater-than operator in `USING` selects a descending-order sort. Comparison of arrays of a user-defined type also relies on the semantics defined by the type's default B-tree operator class. If there is no default B-tree operator class, but there is a default hash operator class, then array equality is supported, but not ordering comparisons. Another SQL feature that requires even more data-type-specific knowledge is the `RANGE` _`offset`_ `PRECEDING`/`FOLLOWING` framing option for window functions (see [Section 4.2.8](https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS "4.2.8. Window Function Calls") ). For a query such as SELECT sum(x) OVER (ORDER BY x RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING) FROM mytable; it is not sufficient to know how to order by `x`; the database must also understand how to “subtract 5” or “add 10” to the current row's value of `x` to identify the bounds of the current window frame. Comparing the resulting bounds to other rows' values of `x` is possible using the comparison operators provided by the B-tree operator class that defines the `ORDER BY` ordering — but addition and subtraction operators are not part of the operator class, so which ones should be used? Hard-wiring that choice would be undesirable, because different sort orders (different B-tree operator classes) might need different behavior. Therefore, a B-tree operator class can specify an _in\_range_ support function that encapsulates the addition and subtraction behaviors that make sense for its sort order. It can even provide more than one in\_range support function, in case there is more than one data type that makes sense to use as the offset in `RANGE` clauses. If the B-tree operator class associated with the window's `ORDER BY` clause does not have a matching in\_range support function, the `RANGE` _`offset`_ `PRECEDING`/`FOLLOWING` option is not supported. Another important point is that an equality operator that appears in a hash operator family is a candidate for hash joins, hash aggregation, and related optimizations. The hash operator family is essential here since it identifies the hash function(s) to use. ### 36.16.7. Ordering Operators [#](https://www.postgresql.org/docs/current/xindex.html#XINDEX-ORDERING-OPS) Some index access methods (currently, only GiST and SP-GiST) support the concept of _ordering operators_. What we have been discussing so far are _search operators_. A search operator is one for which the index can be searched to find all rows satisfying `WHERE` _`indexed_column`_ _`operator`_ _`constant`_. Note that nothing is promised about the order in which the matching rows will be returned. In contrast, an ordering operator does not restrict the set of rows that can be returned, but instead determines their order. An ordering operator is one for which the index can be scanned to return rows in the order represented by `ORDER BY` _`indexed_column`_ _`operator`_ _`constant`_. The reason for defining ordering operators that way is that it supports nearest-neighbor searches, if the operator is one that measures distance. For example, a query like SELECT \* FROM places ORDER BY location <-> point '(101,456)' LIMIT 10; finds the ten places closest to a given target point. A GiST index on the location column can do this efficiently because `<->` is an ordering operator. While search operators have to return Boolean results, ordering operators usually return some other type, such as float or numeric for distances. This type is normally not the same as the data type being indexed. To avoid hard-wiring assumptions about the behavior of different data types, the definition of an ordering operator is required to name a B-tree operator family that specifies the sort ordering of the result data type. As was stated in the previous section, B-tree operator families define PostgreSQL's notion of ordering, so this is a natural representation. Since the point `<->` operator returns `float8`, it could be specified in an operator class creation command like this: OPERATOR 15 <-> (point, point) FOR ORDER BY float\_ops where `float_ops` is the built-in operator family that includes operations on `float8`. This declaration states that the index is able to return rows in order of increasing values of the `<->` operator. ### 36.16.8. Special Features of Operator Classes [#](https://www.postgresql.org/docs/current/xindex.html#XINDEX-OPCLASS-FEATURES) There are two special features of operator classes that we have not discussed yet, mainly because they are not useful with the most commonly used index methods. Normally, declaring an operator as a member of an operator class (or family) means that the index method can retrieve exactly the set of rows that satisfy a `WHERE` condition using the operator. For example: SELECT \* FROM table WHERE integer\_column < 4; can be satisfied exactly by a B-tree index on the integer column. But there are cases where an index is useful as an inexact guide to the matching rows. For example, if a GiST index stores only bounding boxes for geometric objects, then it cannot exactly satisfy a `WHERE` condition that tests overlap between nonrectangular objects such as polygons. Yet we could use the index to find objects whose bounding box overlaps the bounding box of the target object, and then do the exact overlap test only on the objects found by the index. If this scenario applies, the index is said to be “lossy” for the operator. Lossy index searches are implemented by having the index method return a _recheck_ flag when a row might or might not really satisfy the query condition. The core system will then test the original query condition on the retrieved row to see whether it should be returned as a valid match. This approach works if the index is guaranteed to return all the required rows, plus perhaps some additional rows, which can be eliminated by performing the original operator invocation. The index methods that support lossy searches (currently, GiST, SP-GiST and GIN) allow the support functions of individual operator classes to set the recheck flag, and so this is essentially an operator-class feature. Consider again the situation where we are storing in the index only the bounding box of a complex object such as a polygon. In this case there's not much value in storing the whole polygon in the index entry — we might as well store just a simpler object of type `box`. This situation is expressed by the `STORAGE` option in `CREATE OPERATOR CLASS`: we'd write something like: CREATE OPERATOR CLASS polygon\_ops DEFAULT FOR TYPE polygon USING gist AS ... STORAGE box; At present, only the GiST, SP-GiST, GIN and BRIN index methods support a `STORAGE` type that's different from the column data type. The GiST `compress` and `decompress` support routines must deal with data-type conversion when `STORAGE` is used. SP-GiST likewise requires a `compress` support function to convert to the storage type, when that is different; if an SP-GiST opclass also supports retrieving data, the reverse conversion must be handled by the `consistent` function. In GIN, the `STORAGE` type identifies the type of the “key” values, which normally is different from the type of the indexed column — for example, an operator class for integer-array columns might have keys that are just integers. The GIN `extractValue` and `extractQuery` support routines are responsible for extracting keys from indexed values. BRIN is similar to GIN: the `STORAGE` type identifies the type of the stored summary values, and operator classes' support procedures are responsible for interpreting the summary values correctly. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/xoper-optimization.html "36.15. Operator Optimization Information") | [Up](https://www.postgresql.org/docs/current/extend.html "Chapter 36. Extending SQL") | [Next](https://www.postgresql.org/docs/current/extend-extensions.html "36.17. Packaging Related Objects into an Extension") | | 36.15. Operator Optimization Information | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 36.17. Packaging Related Objects into an Extension | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/xindex.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 52.34. pg_operator November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-operator.html "PostgreSQL 18 - 52.34. pg_operator") ([18](https://www.postgresql.org/docs/18/catalog-pg-operator.html "PostgreSQL 18 - 52.34. pg_operator") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-operator.html "PostgreSQL 17 - 52.34. pg_operator") / [16](https://www.postgresql.org/docs/16/catalog-pg-operator.html "PostgreSQL 16 - 52.34. pg_operator") / [15](https://www.postgresql.org/docs/15/catalog-pg-operator.html "PostgreSQL 15 - 52.34. pg_operator") / [14](https://www.postgresql.org/docs/14/catalog-pg-operator.html "PostgreSQL 14 - 52.34. pg_operator") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-operator.html "PostgreSQL devel - 52.34. pg_operator") Unsupported versions: [13](https://www.postgresql.org/docs/13/catalog-pg-operator.html "PostgreSQL 13 - 52.34. pg_operator") / [12](https://www.postgresql.org/docs/12/catalog-pg-operator.html "PostgreSQL 12 - 52.34. pg_operator") / [11](https://www.postgresql.org/docs/11/catalog-pg-operator.html "PostgreSQL 11 - 52.34. pg_operator") / [10](https://www.postgresql.org/docs/10/catalog-pg-operator.html "PostgreSQL 10 - 52.34. pg_operator") / [9.6](https://www.postgresql.org/docs/9.6/catalog-pg-operator.html "PostgreSQL 9.6 - 52.34. pg_operator") / [9.5](https://www.postgresql.org/docs/9.5/catalog-pg-operator.html "PostgreSQL 9.5 - 52.34. pg_operator") / [9.4](https://www.postgresql.org/docs/9.4/catalog-pg-operator.html "PostgreSQL 9.4 - 52.34. pg_operator") / [9.3](https://www.postgresql.org/docs/9.3/catalog-pg-operator.html "PostgreSQL 9.3 - 52.34. pg_operator") / [9.2](https://www.postgresql.org/docs/9.2/catalog-pg-operator.html "PostgreSQL 9.2 - 52.34. pg_operator") / [9.1](https://www.postgresql.org/docs/9.1/catalog-pg-operator.html "PostgreSQL 9.1 - 52.34. pg_operator") / [9.0](https://www.postgresql.org/docs/9.0/catalog-pg-operator.html "PostgreSQL 9.0 - 52.34. pg_operator") / [8.4](https://www.postgresql.org/docs/8.4/catalog-pg-operator.html "PostgreSQL 8.4 - 52.34. pg_operator") / [8.3](https://www.postgresql.org/docs/8.3/catalog-pg-operator.html "PostgreSQL 8.3 - 52.34. pg_operator") / [8.2](https://www.postgresql.org/docs/8.2/catalog-pg-operator.html "PostgreSQL 8.2 - 52.34. pg_operator") / [8.1](https://www.postgresql.org/docs/8.1/catalog-pg-operator.html "PostgreSQL 8.1 - 52.34. pg_operator") / [8.0](https://www.postgresql.org/docs/8.0/catalog-pg-operator.html "PostgreSQL 8.0 - 52.34. pg_operator") / [7.4](https://www.postgresql.org/docs/7.4/catalog-pg-operator.html "PostgreSQL 7.4 - 52.34. pg_operator") / [7.3](https://www.postgresql.org/docs/7.3/catalog-pg-operator.html "PostgreSQL 7.3 - 52.34. pg_operator") / [7.2](https://www.postgresql.org/docs/7.2/catalog-pg-operator.html "PostgreSQL 7.2 - 52.34. pg_operator") / [7.1](https://www.postgresql.org/docs/7.1/catalog-pg-operator.html "PostgreSQL 7.1 - 52.34. pg_operator") | 52.34. `pg_operator` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/catalog-pg-opclass.html "52.33. pg_opclass") | [Up](https://www.postgresql.org/docs/18/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/catalog-pg-opfamily.html "52.35. pg_opfamily") | * * * 52.34. `pg_operator` [#](https://www.postgresql.org/docs/18/catalog-pg-operator.html#CATALOG-PG-OPERATOR) ---------------------------------------------------------------------------------------------------------- The catalog `pg_operator` stores information about operators. See [CREATE OPERATOR](https://www.postgresql.org/docs/18/sql-createoperator.html "CREATE OPERATOR") and [Section 36.14](https://www.postgresql.org/docs/18/xoper.html "36.14. User-Defined Operators") for more information. **Table 52.34. `pg_operator` Columns** | Column Type

Description | | --- | | `oid` `oid`

Row identifier | | `oprname` `name`

Name of the operator | | `oprnamespace` `oid` (references [`pg_namespace`](https://www.postgresql.org/docs/18/catalog-pg-namespace.html "52.32. pg_namespace")
.`oid`)

The OID of the namespace that contains this operator | | `oprowner` `oid` (references [`pg_authid`](https://www.postgresql.org/docs/18/catalog-pg-authid.html "52.8. pg_authid")
.`oid`)

Owner of the operator | | `oprkind` `char`

`b` = infix operator (“both”), or `l` = prefix operator (“left”) | | `oprcanmerge` `bool`

This operator supports merge joins | | `oprcanhash` `bool`

This operator supports hash joins | | `oprleft` `oid` (references [`pg_type`](https://www.postgresql.org/docs/18/catalog-pg-type.html "52.64. pg_type")
.`oid`)

Type of the left operand (zero for a prefix operator) | | `oprright` `oid` (references [`pg_type`](https://www.postgresql.org/docs/18/catalog-pg-type.html "52.64. pg_type")
.`oid`)

Type of the right operand | | `oprresult` `oid` (references [`pg_type`](https://www.postgresql.org/docs/18/catalog-pg-type.html "52.64. pg_type")
.`oid`)

Type of the result (zero for a not-yet-defined “shell” operator) | | `oprcom` `oid` (references [`pg_operator`](https://www.postgresql.org/docs/18/catalog-pg-operator.html "52.34. pg_operator")
.`oid`)

Commutator of this operator (zero if none) | | `oprnegate` `oid` (references [`pg_operator`](https://www.postgresql.org/docs/18/catalog-pg-operator.html "52.34. pg_operator")
.`oid`)

Negator of this operator (zero if none) | | `oprcode` `regproc` (references [`pg_proc`](https://www.postgresql.org/docs/18/catalog-pg-proc.html "52.39. pg_proc")
.`oid`)

Function that implements this operator (zero for a not-yet-defined “shell” operator) | | `oprrest` `regproc` (references [`pg_proc`](https://www.postgresql.org/docs/18/catalog-pg-proc.html "52.39. pg_proc")
.`oid`)

Restriction selectivity estimation function for this operator (zero if none) | | `oprjoin` `regproc` (references [`pg_proc`](https://www.postgresql.org/docs/18/catalog-pg-proc.html "52.39. pg_proc")
.`oid`)

Join selectivity estimation function for this operator (zero if none) | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/catalog-pg-opclass.html "52.33. pg_opclass") | [Up](https://www.postgresql.org/docs/18/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/18/catalog-pg-opfamily.html "52.35. pg_opfamily") | | 52.33. `pg_opclass` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 52.35. `pg_opfamily` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/catalog-pg-operator.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 19.8. Error Reporting and Logging November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/runtime-config-logging.html "PostgreSQL 18 - 19.8. Error Reporting and Logging") ([18](https://www.postgresql.org/docs/18/runtime-config-logging.html "PostgreSQL 18 - 19.8. Error Reporting and Logging") ) / [17](https://www.postgresql.org/docs/17/runtime-config-logging.html "PostgreSQL 17 - 19.8. Error Reporting and Logging") / [16](https://www.postgresql.org/docs/16/runtime-config-logging.html "PostgreSQL 16 - 19.8. Error Reporting and Logging") / [15](https://www.postgresql.org/docs/15/runtime-config-logging.html "PostgreSQL 15 - 19.8. Error Reporting and Logging") / [14](https://www.postgresql.org/docs/14/runtime-config-logging.html "PostgreSQL 14 - 19.8. Error Reporting and Logging") Development Versions: [devel](https://www.postgresql.org/docs/devel/runtime-config-logging.html "PostgreSQL devel - 19.8. Error Reporting and Logging") Unsupported versions: [13](https://www.postgresql.org/docs/13/runtime-config-logging.html "PostgreSQL 13 - 19.8. Error Reporting and Logging") / [12](https://www.postgresql.org/docs/12/runtime-config-logging.html "PostgreSQL 12 - 19.8. Error Reporting and Logging") / [11](https://www.postgresql.org/docs/11/runtime-config-logging.html "PostgreSQL 11 - 19.8. Error Reporting and Logging") / [10](https://www.postgresql.org/docs/10/runtime-config-logging.html "PostgreSQL 10 - 19.8. Error Reporting and Logging") / [9.6](https://www.postgresql.org/docs/9.6/runtime-config-logging.html "PostgreSQL 9.6 - 19.8. Error Reporting and Logging") / [9.5](https://www.postgresql.org/docs/9.5/runtime-config-logging.html "PostgreSQL 9.5 - 19.8. Error Reporting and Logging") / [9.4](https://www.postgresql.org/docs/9.4/runtime-config-logging.html "PostgreSQL 9.4 - 19.8. Error Reporting and Logging") / [9.3](https://www.postgresql.org/docs/9.3/runtime-config-logging.html "PostgreSQL 9.3 - 19.8. Error Reporting and Logging") / [9.2](https://www.postgresql.org/docs/9.2/runtime-config-logging.html "PostgreSQL 9.2 - 19.8. Error Reporting and Logging") / [9.1](https://www.postgresql.org/docs/9.1/runtime-config-logging.html "PostgreSQL 9.1 - 19.8. Error Reporting and Logging") / [9.0](https://www.postgresql.org/docs/9.0/runtime-config-logging.html "PostgreSQL 9.0 - 19.8. Error Reporting and Logging") / [8.4](https://www.postgresql.org/docs/8.4/runtime-config-logging.html "PostgreSQL 8.4 - 19.8. Error Reporting and Logging") / [8.3](https://www.postgresql.org/docs/8.3/runtime-config-logging.html "PostgreSQL 8.3 - 19.8. Error Reporting and Logging") / [8.2](https://www.postgresql.org/docs/8.2/runtime-config-logging.html "PostgreSQL 8.2 - 19.8. Error Reporting and Logging") / [8.1](https://www.postgresql.org/docs/8.1/runtime-config-logging.html "PostgreSQL 8.1 - 19.8. Error Reporting and Logging") | 19.8. Error Reporting and Logging | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/runtime-config-query.html "19.7. Query Planning") | [Up](https://www.postgresql.org/docs/current/runtime-config.html "Chapter 19. Server Configuration") | Chapter 19. Server Configuration | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/runtime-config-statistics.html "19.9. Run-time Statistics") | * * * 19.8. Error Reporting and Logging [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING) ---------------------------------------------------------------------------------------------------------------------------------- [19.8.1. Where to Log](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHERE) [19.8.2. When to Log](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHEN) [19.8.3. What to Log](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHAT) [19.8.4. Using CSV-Format Log Output](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-CSVLOG) [19.8.5. Using JSON-Format Log Output](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-JSONLOG) [19.8.6. Process Title](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-PROC-TITLE) ### 19.8.1. Where to Log [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHERE) `log_destination` (`string`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-DESTINATION) PostgreSQL supports several methods for logging server messages, including stderr, csvlog, jsonlog, and syslog. On Windows, eventlog is also supported. Set this parameter to a list of desired log destinations separated by commas. The default is to log to stderr only. This parameter can only be set in the `postgresql.conf` file or on the server command line. If csvlog is included in `log_destination`, log entries are output in “comma-separated value” (CSV) format, which is convenient for loading logs into programs. See [Section 19.8.4](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-CSVLOG "19.8.4. Using CSV-Format Log Output") for details. [logging\_collector](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOGGING-COLLECTOR) must be enabled to generate CSV-format log output. If jsonlog is included in `log_destination`, log entries are output in JSON format, which is convenient for loading logs into programs. See [Section 19.8.5](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-JSONLOG "19.8.5. Using JSON-Format Log Output") for details. [logging\_collector](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOGGING-COLLECTOR) must be enabled to generate JSON-format log output. When either stderr, csvlog or jsonlog are included, the file `current_logfiles` is created to record the location of the log file(s) currently in use by the logging collector and the associated logging destination. This provides a convenient way to find the logs currently in use by the instance. Here is an example of this file's content: stderr log/postgresql.log csvlog log/postgresql.csv jsonlog log/postgresql.json `current_logfiles` is recreated when a new log file is created as an effect of rotation, and when `log_destination` is reloaded. It is removed when none of stderr, csvlog or jsonlog are included in `log_destination`, and when the logging collector is disabled. ### Note On most Unix systems, you will need to alter the configuration of your system's syslog daemon in order to make use of the syslog option for `log_destination`. PostgreSQL can log to syslog facilities `LOCAL0` through `LOCAL7` (see [syslog\_facility](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-SYSLOG-FACILITY) ), but the default syslog configuration on most platforms will discard all such messages. You will need to add something like: local0.\* /var/log/postgresql to the syslog daemon's configuration file to make it work. On Windows, when you use the `eventlog` option for `log_destination`, you should register an event source and its library with the operating system so that the Windows Event Viewer can display event log messages cleanly. See [Section 18.12](https://www.postgresql.org/docs/current/event-log-registration.html "18.12. Registering Event Log on Windows") for details. `logging_collector` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOGGING-COLLECTOR) This parameter enables the _logging collector_, which is a background process that captures log messages sent to stderr and redirects them into log files. This approach is often more useful than logging to syslog, since some types of messages might not appear in syslog output. (One common example is dynamic-linker failure messages; another is error messages produced by scripts such as `archive_command`.) This parameter can only be set at server start. ### Note It is possible to log to stderr without using the logging collector; the log messages will just go to wherever the server's stderr is directed. However, that method is only suitable for low log volumes, since it provides no convenient way to rotate log files. Also, on some platforms not using the logging collector can result in lost or garbled log output, because multiple processes writing concurrently to the same log file can overwrite each other's output. ### Note The logging collector is designed to never lose messages. This means that in case of extremely high load, server processes could be blocked while trying to send additional log messages when the collector has fallen behind. In contrast, syslog prefers to drop messages if it cannot write them, which means it may fail to log some messages in such cases but it will not block the rest of the system. `log_directory` (`string`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-DIRECTORY) When `logging_collector` is enabled, this parameter determines the directory in which log files will be created. It can be specified as an absolute path, or relative to the cluster data directory. This parameter can only be set in the `postgresql.conf` file or on the server command line. The default is `log`. `log_filename` (`string`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-FILENAME) When `logging_collector` is enabled, this parameter sets the file names of the created log files. The value is treated as a `strftime` pattern, so `%`\-escapes can be used to specify time-varying file names. (Note that if there are any time-zone-dependent `%`\-escapes, the computation is done in the zone specified by [log\_timezone](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-TIMEZONE) .) The supported `%`\-escapes are similar to those listed in the Open Group's [strftime](https://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html) specification. Note that the system's `strftime` is not used directly, so platform-specific (nonstandard) extensions do not work. The default is `postgresql-%Y-%m-%d_%H%M%S.log`. If you specify a file name without escapes, you should plan to use a log rotation utility to avoid eventually filling the entire disk. In releases prior to 8.4, if no `%` escapes were present, PostgreSQL would append the epoch of the new log file's creation time, but this is no longer the case. If CSV-format output is enabled in `log_destination`, `.csv` will be appended to the timestamped log file name to create the file name for CSV-format output. (If `log_filename` ends in `.log`, the suffix is replaced instead.) If JSON-format output is enabled in `log_destination`, `.json` will be appended to the timestamped log file name to create the file name for JSON-format output. (If `log_filename` ends in `.log`, the suffix is replaced instead.) This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_file_mode` (`integer`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-FILE-MODE) On Unix systems this parameter sets the permissions for log files when `logging_collector` is enabled. (On Microsoft Windows this parameter is ignored.) The parameter value is expected to be a numeric mode specified in the format accepted by the `chmod` and `umask` system calls. (To use the customary octal format the number must start with a `0` (zero).) The default permissions are `0600`, meaning only the server owner can read or write the log files. The other commonly useful setting is `0640`, allowing members of the owner's group to read the files. Note however that to make use of such a setting, you'll need to alter [log\_directory](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-DIRECTORY) to store the files somewhere outside the cluster data directory. In any case, it's unwise to make the log files world-readable, since they might contain sensitive data. This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_rotation_age` (`integer`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-ROTATION-AGE) When `logging_collector` is enabled, this parameter determines the maximum amount of time to use an individual log file, after which a new log file will be created. If this value is specified without units, it is taken as minutes. The default is 24 hours. Set to zero to disable time-based creation of new log files. This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_rotation_size` (`integer`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-ROTATION-SIZE) When `logging_collector` is enabled, this parameter determines the maximum size of an individual log file. After this amount of data has been emitted into a log file, a new log file will be created. If this value is specified without units, it is taken as kilobytes. The default is 10 megabytes. Set to zero to disable size-based creation of new log files. This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_truncate_on_rotation` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-TRUNCATE-ON-ROTATION) When `logging_collector` is enabled, this parameter will cause PostgreSQL to truncate (overwrite), rather than append to, any existing log file of the same name. However, truncation will occur only when a new file is being opened due to time-based rotation, not during server startup or size-based rotation. When off, pre-existing files will be appended to in all cases. For example, using this setting in combination with a `log_filename` like `postgresql-%H.log` would result in generating twenty-four hourly log files and then cyclically overwriting them. This parameter can only be set in the `postgresql.conf` file or on the server command line. Example: To keep 7 days of logs, one log file per day named `server_log.Mon`, `server_log.Tue`, etc., and automatically overwrite last week's log with this week's log, set `log_filename` to `server_log.%a`, `log_truncate_on_rotation` to `on`, and `log_rotation_age` to `1440`. Example: To keep 24 hours of logs, one log file per hour, but also rotate sooner if the log file size exceeds 1GB, set `log_filename` to `server_log.%H%M`, `log_truncate_on_rotation` to `on`, `log_rotation_age` to `60`, and `log_rotation_size` to `1000000`. Including `%M` in `log_filename` allows any size-driven rotations that might occur to select a file name different from the hour's initial file name. `syslog_facility` (`enum`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-SYSLOG-FACILITY) When logging to syslog is enabled, this parameter determines the syslog “facility” to be used. You can choose from `LOCAL0`, `LOCAL1`, `LOCAL2`, `LOCAL3`, `LOCAL4`, `LOCAL5`, `LOCAL6`, `LOCAL7`; the default is `LOCAL0`. See also the documentation of your system's syslog daemon. This parameter can only be set in the `postgresql.conf` file or on the server command line. `syslog_ident` (`string`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-SYSLOG-IDENT) When logging to syslog is enabled, this parameter determines the program name used to identify PostgreSQL messages in syslog logs. The default is `postgres`. This parameter can only be set in the `postgresql.conf` file or on the server command line. `syslog_sequence_numbers` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-SYSLOG-SEQUENCE-NUMBERS) When logging to syslog and this is on (the default), then each message will be prefixed by an increasing sequence number (such as `[2]`). This circumvents the “\--- last message repeated N times ---” suppression that many syslog implementations perform by default. In more modern syslog implementations, repeated message suppression can be configured (for example, `$RepeatedMsgReduction` in rsyslog), so this might not be necessary. Also, you could turn this off if you actually want to suppress repeated messages. This parameter can only be set in the `postgresql.conf` file or on the server command line. `syslog_split_messages` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-SYSLOG-SPLIT-MESSAGES) When logging to syslog is enabled, this parameter determines how messages are delivered to syslog. When on (the default), messages are split by lines, and long lines are split so that they will fit into 1024 bytes, which is a typical size limit for traditional syslog implementations. When off, PostgreSQL server log messages are delivered to the syslog service as is, and it is up to the syslog service to cope with the potentially bulky messages. If syslog is ultimately logging to a text file, then the effect will be the same either way, and it is best to leave the setting on, since most syslog implementations either cannot handle large messages or would need to be specially configured to handle them. But if syslog is ultimately writing into some other medium, it might be necessary or more useful to keep messages logically together. This parameter can only be set in the `postgresql.conf` file or on the server command line. `event_source` (`string`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-EVENT-SOURCE) When logging to event log is enabled, this parameter determines the program name used to identify PostgreSQL messages in the log. The default is `PostgreSQL`. This parameter can only be set at server start. ### 19.8.2. When to Log [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHEN) `log_min_messages` (`enum`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-MESSAGES) Controls which [message levels](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-SEVERITY-LEVELS "Table 19.2. Message Severity Levels") are written to the server log. Valid values are `DEBUG5`, `DEBUG4`, `DEBUG3`, `DEBUG2`, `DEBUG1`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, `LOG`, `FATAL`, and `PANIC`. Each level includes all the levels that follow it. The later the level, the fewer messages are sent to the log. The default is `WARNING`. Note that `LOG` has a different rank here than in [client\_min\_messages](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-CLIENT-MIN-MESSAGES) . Only superusers and users with the appropriate `SET` privilege can change this setting. `log_min_error_statement` (`enum`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-ERROR-STATEMENT) Controls which SQL statements that cause an error condition are recorded in the server log. The current SQL statement is included in the log entry for any message of the specified [severity](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-SEVERITY-LEVELS "Table 19.2. Message Severity Levels") or higher. Valid values are `DEBUG5`, `DEBUG4`, `DEBUG3`, `DEBUG2`, `DEBUG1`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, `LOG`, `FATAL`, and `PANIC`. The default is `ERROR`, which means statements causing errors, log messages, fatal errors, or panics will be logged. To effectively turn off logging of failing statements, set this parameter to `PANIC`. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_min_duration_statement` (`integer`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-DURATION-STATEMENT) Causes the duration of each completed statement to be logged if the statement ran for at least the specified amount of time. For example, if you set it to `250ms` then all SQL statements that run 250ms or longer will be logged. Enabling this parameter can be helpful in tracking down unoptimized queries in your applications. If this value is specified without units, it is taken as milliseconds. Setting this to zero prints all statement durations. `-1` (the default) disables logging statement durations. Only superusers and users with the appropriate `SET` privilege can change this setting. This overrides [log\_min\_duration\_sample](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-DURATION-SAMPLE) , meaning that queries with duration exceeding this setting are not subject to sampling and are always logged. For clients using extended query protocol, durations of the Parse, Bind, and Execute steps are logged independently. ### Note When using this option together with [log\_statement](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-STATEMENT) , the text of statements that are logged because of `log_statement` will not be repeated in the duration log message. If you are not using syslog, it is recommended that you log the PID or session ID using [log\_line\_prefix](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-LINE-PREFIX) so that you can link the statement message to the later duration message using the process ID or session ID. `log_min_duration_sample` (`integer`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-DURATION-SAMPLE) Allows sampling the duration of completed statements that ran for at least the specified amount of time. This produces the same kind of log entries as [log\_min\_duration\_statement](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-DURATION-STATEMENT) , but only for a subset of the executed statements, with sample rate controlled by [log\_statement\_sample\_rate](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-STATEMENT-SAMPLE-RATE) . For example, if you set it to `100ms` then all SQL statements that run 100ms or longer will be considered for sampling. Enabling this parameter can be helpful when the traffic is too high to log all queries. If this value is specified without units, it is taken as milliseconds. Setting this to zero samples all statement durations. `-1` (the default) disables sampling statement durations. Only superusers and users with the appropriate `SET` privilege can change this setting. This setting has lower priority than `log_min_duration_statement`, meaning that statements with durations exceeding `log_min_duration_statement` are not subject to sampling and are always logged. Other notes for `log_min_duration_statement` apply also to this setting. `log_statement_sample_rate` (`floating point`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-STATEMENT-SAMPLE-RATE) Determines the fraction of statements with duration exceeding [log\_min\_duration\_sample](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-DURATION-SAMPLE) that will be logged. Sampling is stochastic, for example `0.5` means there is statistically one chance in two that any given statement will be logged. The default is `1.0`, meaning to log all sampled statements. Setting this to zero disables sampled statement-duration logging, the same as setting `log_min_duration_sample` to `-1`. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_transaction_sample_rate` (`floating point`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-TRANSACTION-SAMPLE-RATE) Sets the fraction of transactions whose statements are all logged, in addition to statements logged for other reasons. It applies to each new transaction regardless of its statements' durations. Sampling is stochastic, for example `0.1` means there is statistically one chance in ten that any given transaction will be logged. `log_transaction_sample_rate` can be helpful to construct a sample of transactions. The default is `0`, meaning not to log statements from any additional transactions. Setting this to `1` logs all statements of all transactions. Only superusers and users with the appropriate `SET` privilege can change this setting. ### Note Like all statement-logging options, this option can add significant overhead. `log_startup_progress_interval` (`integer`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-STARTUP-PROGRESS-INTERVAL) Sets the amount of time after which the startup process will log a message about a long-running operation that is still in progress, as well as the interval between further progress messages for that operation. The default is 10 seconds. A setting of `0` disables the feature. If this value is specified without units, it is taken as milliseconds. This setting is applied separately to each operation. This parameter can only be set in the `postgresql.conf` file or on the server command line. For example, if syncing the data directory takes 25 seconds and thereafter resetting unlogged relations takes 8 seconds, and if this setting has the default value of 10 seconds, then a messages will be logged for syncing the data directory after it has been in progress for 10 seconds and again after it has been in progress for 20 seconds, but nothing will be logged for resetting unlogged relations. [Table 19.2](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-SEVERITY-LEVELS "Table 19.2. Message Severity Levels") explains the message severity levels used by PostgreSQL. If logging output is sent to syslog or Windows' eventlog, the severity levels are translated as shown in the table. **Table 19.2. Message Severity Levels** | Severity | Usage | syslog | eventlog | | --- | --- | --- | --- | | `DEBUG1 .. DEBUG5` | Provides successively-more-detailed information for use by developers. | `DEBUG` | `INFORMATION` | | `INFO` | Provides information implicitly requested by the user, e.g., output from `VACUUM VERBOSE`. | `INFO` | `INFORMATION` | | `NOTICE` | Provides information that might be helpful to users, e.g., notice of truncation of long identifiers. | `NOTICE` | `INFORMATION` | | `WARNING` | Provides warnings of likely problems, e.g., `COMMIT` outside a transaction block. | `NOTICE` | `WARNING` | | `ERROR` | Reports an error that caused the current command to abort. | `WARNING` | `ERROR` | | `LOG` | Reports information of interest to administrators, e.g., checkpoint activity. | `INFO` | `INFORMATION` | | `FATAL` | Reports an error that caused the current session to abort. | `ERR` | `ERROR` | | `PANIC` | Reports an error that caused all database sessions to abort. | `CRIT` | `ERROR` | ### 19.8.3. What to Log [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHAT) ### Note What you choose to log can have security implications; see [Section 24.3](https://www.postgresql.org/docs/current/logfile-maintenance.html "24.3. Log File Maintenance") . `application_name` (`string`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-APPLICATION-NAME) The `application_name` can be any string of less than `NAMEDATALEN` characters (64 characters in a standard build). It is typically set by an application upon connection to the server. The name will be displayed in the `pg_stat_activity` view and included in CSV log entries. It can also be included in regular log entries via the [log\_line\_prefix](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-LINE-PREFIX) parameter. Only printable ASCII characters may be used in the `application_name` value. Other characters are replaced with [C-style hexadecimal escapes](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE "4.1.2.2. String Constants with C-Style Escapes") . `debug_print_parse` (`boolean`) `debug_print_rewritten` (`boolean`) `debug_print_plan` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-DEBUG-PRINT-PARSE) These parameters enable various debugging output to be emitted. When set, they print the resulting parse tree, the query rewriter output, or the execution plan for each executed query. These messages are emitted at `LOG` message level, so by default they will appear in the server log but will not be sent to the client. You can change that by adjusting [client\_min\_messages](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-CLIENT-MIN-MESSAGES) and/or [log\_min\_messages](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-MESSAGES) . These parameters are off by default. `debug_pretty_print` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-DEBUG-PRETTY-PRINT) When set, `debug_pretty_print` indents the messages produced by `debug_print_parse`, `debug_print_rewritten`, or `debug_print_plan`. This results in more readable but much longer output than the “compact” format used when it is off. It is on by default. `log_autovacuum_min_duration` (`integer`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-AUTOVACUUM-MIN-DURATION) Causes each action executed by autovacuum to be logged if it ran for at least the specified amount of time. Setting this to zero logs all autovacuum actions. `-1` disables logging autovacuum actions. If this value is specified without units, it is taken as milliseconds. For example, if you set this to `250ms` then all automatic vacuums and analyzes that run 250ms or longer will be logged. In addition, when this parameter is set to any value other than `-1`, a message will be logged if an autovacuum action is skipped due to a conflicting lock or a concurrently dropped relation. The default is `10min`. Enabling this parameter can be helpful in tracking autovacuum activity. This parameter can only be set in the `postgresql.conf` file or on the server command line; but the setting can be overridden for individual tables by changing table storage parameters. `log_checkpoints` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-CHECKPOINTS) Causes checkpoints and restartpoints to be logged in the server log. Some statistics are included in the log messages, including the number of buffers written and the time spent writing them. This parameter can only be set in the `postgresql.conf` file or on the server command line. The default is on. `log_connections` (`string`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-CONNECTIONS) Causes aspects of each connection to the server to be logged. The default is the empty string, `''`, which disables all connection logging. The following options may be specified alone or in a comma-separated list: **Table 19.3. Log Connection Options** | Name | Description | | --- | --- | | `receipt` | Logs receipt of a connection. | | `authentication` | Logs the original identity used by an authentication method to identify a user. In most cases, the identity string matches the PostgreSQL username, but some third-party authentication methods may alter the original user identifier before the server stores it. Failed authentication is always logged regardless of the value of this setting. | | `authorization` | Logs successful completion of authorization. At this point the connection has been established but the backend is not yet fully set up. The log message includes the authorized username as well as the database name and application name, if applicable. | | `setup_durations` | Logs the time spent establishing the connection and setting up the backend until the connection is ready to execute its first query. The log message includes three durations: the total setup duration (starting from the postmaster accepting the incoming connection and ending when the connection is ready for query), the time it took to fork the new backend, and the time it took to authenticate the user. | | `all` | A convenience alias equivalent to specifying all options. If `all` is specified in a list of other options, all connection aspects will be logged. | Disconnection logging is separately controlled by [log\_disconnections](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-DISCONNECTIONS) . For the purposes of backwards compatibility, `on`, `off`, `true`, `false`, `yes`, `no`, `1`, and `0` are still supported. The positive values are equivalent to specifying the `receipt`, `authentication`, and `authorization` options. Only superusers and users with the appropriate `SET` privilege can change this parameter at session start, and it cannot be changed at all within a session. ### Note Some client programs, like psql, attempt to connect twice while determining if a password is required, so duplicate “connection received” messages do not necessarily indicate a problem. `log_disconnections` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-DISCONNECTIONS) Causes session terminations to be logged. The log output provides information similar to `log_connections`, plus the duration of the session. Only superusers and users with the appropriate `SET` privilege can change this parameter at session start, and it cannot be changed at all within a session. The default is `off`. `log_duration` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-DURATION) Causes the duration of every completed statement to be logged. The default is `off`. Only superusers and users with the appropriate `SET` privilege can change this setting. For clients using extended query protocol, durations of the Parse, Bind, and Execute steps are logged independently. ### Note The difference between enabling `log_duration` and setting [log\_min\_duration\_statement](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-DURATION-STATEMENT) to zero is that exceeding `log_min_duration_statement` forces the text of the query to be logged, but this option doesn't. Thus, if `log_duration` is `on` and `log_min_duration_statement` has a positive value, all durations are logged but the query text is included only for statements exceeding the threshold. This behavior can be useful for gathering statistics in high-load installations. `log_error_verbosity` (`enum`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-ERROR-VERBOSITY) Controls the amount of detail written in the server log for each message that is logged. Valid values are `TERSE`, `DEFAULT`, and `VERBOSE`, each adding more fields to displayed messages. `TERSE` excludes the logging of `DETAIL`, `HINT`, `QUERY`, and `CONTEXT` error information. `VERBOSE` output includes the `SQLSTATE` error code (see also [Appendix A](https://www.postgresql.org/docs/current/errcodes-appendix.html "Appendix A. PostgreSQL Error Codes") ) and the source code file name, function name, and line number that generated the error. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_hostname` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-HOSTNAME) By default, connection log messages only show the IP address of the connecting host. Turning this parameter on causes logging of the host name as well. Note that depending on your host name resolution setup this might impose a non-negligible performance penalty. This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_line_prefix` (`string`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-LINE-PREFIX) This is a `printf`\-style string that is output at the beginning of each log line. `%` characters begin “escape sequences” that are replaced with status information as outlined below. Unrecognized escapes are ignored. Other characters are copied straight to the log line. Some escapes are only recognized by session processes, and will be treated as empty by background processes such as the main server process. Status information may be aligned either left or right by specifying a numeric literal after the % and before the option. A negative value will cause the status information to be padded on the right with spaces to give it a minimum width, whereas a positive value will pad on the left. Padding can be useful to aid human readability in log files. This parameter can only be set in the `postgresql.conf` file or on the server command line. The default is `'%m [%p] '` which logs a time stamp and the process ID. | Escape | Effect | Session only | | --- | --- | --- | | `%a` | Application name | yes | | `%u` | User name | yes | | `%d` | Database name | yes | | `%r` | Remote host name or IP address, and remote port | yes | | `%h` | Remote host name or IP address | yes | | `%L` | Local address (the IP address on the server that the client connected to) | yes | | `%b` | Backend type | no | | `%p` | Process ID | no | | `%P` | Process ID of the parallel group leader, if this process is a parallel query worker | no | | `%t` | Time stamp without milliseconds | no | | `%m` | Time stamp with milliseconds | no | | `%n` | Time stamp with milliseconds (as a Unix epoch) | no | | `%i` | Command tag: type of session's current command | yes | | `%e` | SQLSTATE error code | no | | `%c` | Session ID: see below | no | | `%l` | Number of the log line for each session or process, starting at 1 | no | | `%s` | Process start time stamp | no | | `%v` | Virtual transaction ID (procNumber/localXID); see [Section 67.1](https://www.postgresql.org/docs/current/transaction-id.html "67.1. Transactions and Identifiers") | no | | `%x` | Transaction ID (0 if none is assigned); see [Section 67.1](https://www.postgresql.org/docs/current/transaction-id.html "67.1. Transactions and Identifiers") | no | | `%q` | Produces no output, but tells non-session processes to stop at this point in the string; ignored by session processes | no | | `%Q` | Query identifier of the current query. Query identifiers are not computed by default, so this field will be zero unless [compute\_query\_id](https://www.postgresql.org/docs/current/runtime-config-statistics.html#GUC-COMPUTE-QUERY-ID)
parameter is enabled or a third-party module that computes query identifiers is configured. | yes | | `%%` | Literal `%` | no | The backend type corresponds to the column `backend_type` in the view [`pg_stat_activity`](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW "27.2.3. pg_stat_activity") , but additional types can appear in the log that don't show in that view. The `%c` escape prints a quasi-unique session identifier, consisting of two 4-byte hexadecimal numbers (without leading zeros) separated by a dot. The numbers are the process start time and the process ID, so `%c` can also be used as a space saving way of printing those items. For example, to generate the session identifier from `pg_stat_activity`, use this query: SELECT to\_hex(trunc(EXTRACT(EPOCH FROM backend\_start))::integer) || '.' || to\_hex(pid) FROM pg\_stat\_activity; ### Tip If you set a nonempty value for `log_line_prefix`, you should usually make its last character be a space, to provide visual separation from the rest of the log line. A punctuation character can be used too. ### Tip Syslog produces its own time stamp and process ID information, so you probably do not want to include those escapes if you are logging to syslog. ### Tip The `%q` escape is useful when including information that is only available in session (backend) context like user or database name. For example: log\_line\_prefix = '%m \[%p\] %q%u@%d/%a ' ### Note The `%Q` escape always reports a zero identifier for lines output by [log\_statement](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-STATEMENT) because `log_statement` generates output before an identifier can be calculated, including invalid statements for which an identifier cannot be calculated. `log_lock_waits` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-LOCK-WAITS) Controls whether a log message is produced when a session waits longer than [deadlock\_timeout](https://www.postgresql.org/docs/current/runtime-config-locks.html#GUC-DEADLOCK-TIMEOUT) to acquire a lock. This is useful in determining if lock waits are causing poor performance. The default is `off`. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_lock_failures` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-LOCK-FAILURES) Controls whether a detailed log message is produced when a lock acquisition fails. This is useful for analyzing the causes of lock failures. Currently, only lock failures due to `SELECT NOWAIT` is supported. The default is `off`. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_recovery_conflict_waits` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-RECOVERY-CONFLICT-WAITS) Controls whether a log message is produced when the startup process waits longer than `deadlock_timeout` for recovery conflicts. This is useful in determining if recovery conflicts prevent the recovery from applying WAL. The default is `off`. This parameter can only be set in the `postgresql.conf` file or on the server command line. `log_parameter_max_length` (`integer`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-PARAMETER-MAX-LENGTH) If greater than zero, each bind parameter value logged with a non-error statement-logging message is trimmed to this many bytes. Zero disables logging of bind parameters for non-error statement logs. `-1` (the default) allows bind parameters to be logged in full. If this value is specified without units, it is taken as bytes. Only superusers and users with the appropriate `SET` privilege can change this setting. This setting only affects log messages printed as a result of [log\_statement](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-STATEMENT) , [log\_duration](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-DURATION) , and related settings. Non-zero values of this setting add some overhead, particularly if parameters are sent in binary form, since then conversion to text is required. `log_parameter_max_length_on_error` (`integer`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-PARAMETER-MAX-LENGTH-ON-ERROR) If greater than zero, each bind parameter value reported in error messages is trimmed to this many bytes. Zero (the default) disables including bind parameters in error messages. `-1` allows bind parameters to be printed in full. If this value is specified without units, it is taken as bytes. Non-zero values of this setting add overhead, as PostgreSQL will need to store textual representations of parameter values in memory at the start of each statement, whether or not an error eventually occurs. The overhead is greater when bind parameters are sent in binary form than when they are sent as text, since the former case requires data conversion while the latter only requires copying the string. `log_statement` (`enum`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-STATEMENT) Controls which SQL statements are logged. Valid values are `none` (off), `ddl`, `mod`, and `all` (all statements). `ddl` logs all data definition statements, such as `CREATE`, `ALTER`, and `DROP` statements. `mod` logs all `ddl` statements, plus data-modifying statements such as `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`, and `COPY FROM`. `PREPARE`, `EXECUTE`, and `EXPLAIN ANALYZE` statements are also logged if their contained command is of an appropriate type. For clients using extended query protocol, logging occurs when an Execute message is received, and values of the Bind parameters are included (with any embedded single-quote marks doubled). The default is `none`. Only superusers and users with the appropriate `SET` privilege can change this setting. ### Note Statements that contain simple syntax errors are not logged even by the `log_statement` = `all` setting, because the log message is emitted only after basic parsing has been done to determine the statement type. In the case of extended query protocol, this setting likewise does not log statements that fail before the Execute phase (i.e., during parse analysis or planning). Set `log_min_error_statement` to `ERROR` (or lower) to log such statements. Logged statements might reveal sensitive data and even contain plaintext passwords. `log_replication_commands` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-REPLICATION-COMMANDS) Causes each replication command and `walsender` process's replication slot acquisition/release to be logged in the server log. See [Section 54.4](https://www.postgresql.org/docs/current/protocol-replication.html "54.4. Streaming Replication Protocol") for more information about replication command. The default value is `off`. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_temp_files` (`integer`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-TEMP-FILES) Controls logging of temporary file names and sizes. Temporary files can be created for sorts, hashes, and temporary query results. If enabled by this setting, a log entry is emitted for each temporary file, with the file size specified in bytes, when it is deleted. A value of zero logs all temporary file information, while positive values log only files whose size is greater than or equal to the specified amount of data. If this value is specified without units, it is taken as kilobytes. The default setting is -1, which disables such logging. Only superusers and users with the appropriate `SET` privilege can change this setting. `log_timezone` (`string`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-TIMEZONE) Sets the time zone used for timestamps written in the server log. Unlike [TimeZone](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-TIMEZONE) , this value is cluster-wide, so that all sessions will report timestamps consistently. The built-in default is `GMT`, but that is typically overridden in `postgresql.conf`; initdb will install a setting there corresponding to its system environment. See [Section 8.5.3](https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-TIMEZONES "8.5.3. Time Zones") for more information. This parameter can only be set in the `postgresql.conf` file or on the server command line. ### 19.8.4. Using CSV-Format Log Output [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-CSVLOG) Including `csvlog` in the `log_destination` list provides a convenient way to import log files into a database table. This option emits log lines in comma-separated-values (CSV) format, with these columns: time stamp with milliseconds, user name, database name, process ID, client host:port number, session ID, per-session line number, command tag, session start time, virtual transaction ID, regular transaction ID, error severity, SQLSTATE code, error message, error message detail, hint, internal query that led to the error (if any), character count of the error position therein, error context, user query that led to the error (if any and enabled by `log_min_error_statement`), character count of the error position therein, location of the error in the PostgreSQL source code (if `log_error_verbosity` is set to `verbose`), application name, backend type, process ID of parallel group leader, and query id. Here is a sample table definition for storing CSV-format log output: CREATE TABLE postgres\_log ( log\_time timestamp(3) with time zone, user\_name text, database\_name text, process\_id integer, connection\_from text, session\_id text, session\_line\_num bigint, command\_tag text, session\_start\_time timestamp with time zone, virtual\_transaction\_id text, transaction\_id bigint, error\_severity text, sql\_state\_code text, message text, detail text, hint text, internal\_query text, internal\_query\_pos integer, context text, query text, query\_pos integer, location text, application\_name text, backend\_type text, leader\_pid integer, query\_id bigint, PRIMARY KEY (session\_id, session\_line\_num) ); To import a log file into this table, use the `COPY FROM` command: COPY postgres\_log FROM '/full/path/to/logfile.csv' WITH csv; It is also possible to access the file as a foreign table, using the supplied [file\_fdw](https://www.postgresql.org/docs/current/file-fdw.html "F.15. file_fdw — access data files in the server's file system") module. There are a few things you need to do to simplify importing CSV log files: 1. Set `log_filename` and `log_rotation_age` to provide a consistent, predictable naming scheme for your log files. This lets you predict what the file name will be and know when an individual log file is complete and therefore ready to be imported. 2. Set `log_rotation_size` to 0 to disable size-based log rotation, as it makes the log file name difficult to predict. 3. Set `log_truncate_on_rotation` to `on` so that old log data isn't mixed with the new in the same file. 4. The table definition above includes a primary key specification. This is useful to protect against accidentally importing the same information twice. The `COPY` command commits all of the data it imports at one time, so any error will cause the entire import to fail. If you import a partial log file and later import the file again when it is complete, the primary key violation will cause the import to fail. Wait until the log is complete and closed before importing. This procedure will also protect against accidentally importing a partial line that hasn't been completely written, which would also cause `COPY` to fail. ### 19.8.5. Using JSON-Format Log Output [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-JSONLOG) Including `jsonlog` in the `log_destination` list provides a convenient way to import log files into many different programs. This option emits log lines in JSON format. String fields with null values are excluded from output. Additional fields may be added in the future. User applications that process `jsonlog` output should ignore unknown fields. Each log line is serialized as a JSON object with the set of keys and their associated values shown in [Table 19.4](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-JSONLOG-KEYS-VALUES "Table 19.4. Keys and Values of JSON Log Entries") . **Table 19.4. Keys and Values of JSON Log Entries** | Key name | Type | Description | | --- | --- | --- | | `timestamp` | string | Time stamp with milliseconds | | `user` | string | User name | | `dbname` | string | Database name | | `pid` | number | Process ID | | `remote_host` | string | Client host | | `remote_port` | number | Client port | | `session_id` | string | Session ID | | `line_num` | number | Per-session line number | | `ps` | string | Current ps display | | `session_start` | string | Session start time | | `vxid` | string | Virtual transaction ID | | `txid` | string | Regular transaction ID | | `error_severity` | string | Error severity | | `state_code` | string | SQLSTATE code | | `message` | string | Error message | | `detail` | string | Error message detail | | `hint` | string | Error message hint | | `internal_query` | string | Internal query that led to the error | | `internal_position` | number | Cursor index into internal query | | `context` | string | Error context | | `statement` | string | Client-supplied query string | | `cursor_position` | number | Cursor index into query string | | `func_name` | string | Error location function name | | `file_name` | string | File name of error location | | `file_line_num` | number | File line number of the error location | | `application_name` | string | Client application name | | `backend_type` | string | Type of backend | | `leader_pid` | number | Process ID of leader for active parallel workers | | `query_id` | number | Query ID | ### 19.8.6. Process Title [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-PROC-TITLE) These settings control how process titles of server processes are modified. Process titles are typically viewed using programs like ps or, on Windows, Process Explorer. See [Section 27.1](https://www.postgresql.org/docs/current/monitoring-ps.html "27.1. Standard Unix Tools") for details. `cluster_name` (`string`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-CLUSTER-NAME) Sets a name that identifies this database cluster (instance) for various purposes. The cluster name appears in the process title for all server processes in this cluster. Moreover, it is the default application name for a standby connection (see [synchronous\_standby\_names](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-SYNCHRONOUS-STANDBY-NAMES) ). The name can be any string of less than `NAMEDATALEN` characters (64 characters in a standard build). Only printable ASCII characters may be used in the `cluster_name` value. Other characters are replaced with [C-style hexadecimal escapes](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE "4.1.2.2. String Constants with C-Style Escapes") . No name is shown if this parameter is set to the empty string `''` (which is the default). This parameter can only be set at server start. `update_process_title` (`boolean`) [#](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-UPDATE-PROCESS-TITLE) Enables updating of the process title every time a new SQL command is received by the server. This setting defaults to `on` on most platforms, but it defaults to `off` on Windows due to that platform's larger overhead for updating the process title. Only superusers and users with the appropriate `SET` privilege can change this setting. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/runtime-config-query.html "19.7. Query Planning") | [Up](https://www.postgresql.org/docs/current/runtime-config.html "Chapter 19. Server Configuration") | [Next](https://www.postgresql.org/docs/current/runtime-config-statistics.html "19.9. Run-time Statistics") | | 19.7. Query Planning | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 19.9. Run-time Statistics | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/runtime-config-logging.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: postgres November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/app-postgres.html "PostgreSQL 18 - postgres") ([18](https://www.postgresql.org/docs/18/app-postgres.html "PostgreSQL 18 - postgres") ) / [17](https://www.postgresql.org/docs/17/app-postgres.html "PostgreSQL 17 - postgres") / [16](https://www.postgresql.org/docs/16/app-postgres.html "PostgreSQL 16 - postgres") / [15](https://www.postgresql.org/docs/15/app-postgres.html "PostgreSQL 15 - postgres") / [14](https://www.postgresql.org/docs/14/app-postgres.html "PostgreSQL 14 - postgres") Development Versions: [devel](https://www.postgresql.org/docs/devel/app-postgres.html "PostgreSQL devel - postgres") Unsupported versions: [13](https://www.postgresql.org/docs/13/app-postgres.html "PostgreSQL 13 - postgres") / [12](https://www.postgresql.org/docs/12/app-postgres.html "PostgreSQL 12 - postgres") / [11](https://www.postgresql.org/docs/11/app-postgres.html "PostgreSQL 11 - postgres") / [10](https://www.postgresql.org/docs/10/app-postgres.html "PostgreSQL 10 - postgres") / [9.6](https://www.postgresql.org/docs/9.6/app-postgres.html "PostgreSQL 9.6 - postgres") / [9.5](https://www.postgresql.org/docs/9.5/app-postgres.html "PostgreSQL 9.5 - postgres") / [9.4](https://www.postgresql.org/docs/9.4/app-postgres.html "PostgreSQL 9.4 - postgres") / [9.3](https://www.postgresql.org/docs/9.3/app-postgres.html "PostgreSQL 9.3 - postgres") / [9.2](https://www.postgresql.org/docs/9.2/app-postgres.html "PostgreSQL 9.2 - postgres") / [9.1](https://www.postgresql.org/docs/9.1/app-postgres.html "PostgreSQL 9.1 - postgres") / [9.0](https://www.postgresql.org/docs/9.0/app-postgres.html "PostgreSQL 9.0 - postgres") / [8.4](https://www.postgresql.org/docs/8.4/app-postgres.html "PostgreSQL 8.4 - postgres") / [8.3](https://www.postgresql.org/docs/8.3/app-postgres.html "PostgreSQL 8.3 - postgres") / [8.2](https://www.postgresql.org/docs/8.2/app-postgres.html "PostgreSQL 8.2 - postgres") / [8.1](https://www.postgresql.org/docs/8.1/app-postgres.html "PostgreSQL 8.1 - postgres") / [8.0](https://www.postgresql.org/docs/8.0/app-postgres.html "PostgreSQL 8.0 - postgres") / [7.4](https://www.postgresql.org/docs/7.4/app-postgres.html "PostgreSQL 7.4 - postgres") / [7.3](https://www.postgresql.org/docs/7.3/app-postgres.html "PostgreSQL 7.3 - postgres") / [7.2](https://www.postgresql.org/docs/7.2/app-postgres.html "PostgreSQL 7.2 - postgres") / [7.1](https://www.postgresql.org/docs/7.1/app-postgres.html "PostgreSQL 7.1 - postgres") | postgres | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/app-pgwalsummary.html "pg_walsummary") | [Up](https://www.postgresql.org/docs/current/reference-server.html "PostgreSQL Server Applications") | PostgreSQL Server Applications | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/internals.html "Part VII. Internals") | * * * postgres -------- postgres — PostgreSQL database server Synopsis -------- `postgres` \[_`option`_...\] Description ----------- `postgres` is the PostgreSQL database server. In order for a client application to access a database it connects (over a network or locally) to a running `postgres` instance. The `postgres` instance then starts a separate server process to handle the connection. One `postgres` instance always manages the data of exactly one database cluster. A database cluster is a collection of databases that is stored at a common file system location (the “data area”). More than one `postgres` instance can run on a system at one time, so long as they use different data areas and different communication ports (see below). When `postgres` starts it needs to know the location of the data area. The location must be specified by the `-D` option or the `PGDATA` environment variable; there is no default. Typically, `-D` or `PGDATA` points directly to the data area directory created by [initdb](https://www.postgresql.org/docs/current/app-initdb.html "initdb") . Other possible file layouts are discussed in [Section 19.2](https://www.postgresql.org/docs/current/runtime-config-file-locations.html "19.2. File Locations") . By default `postgres` starts in the foreground and prints log messages to the standard error stream. In practical applications `postgres` should be started as a background process, perhaps at boot time. The `postgres` command can also be called in single-user mode. The primary use for this mode is during bootstrapping by [initdb](https://www.postgresql.org/docs/current/app-initdb.html "initdb") . Sometimes it is used for debugging or disaster recovery; note that running a single-user server is not truly suitable for debugging the server, since no realistic interprocess communication and locking will happen. When invoked in single-user mode from the shell, the user can enter queries and the results will be printed to the screen, but in a form that is more useful for developers than end users. In the single-user mode, the session user will be set to the user with ID 1, and implicit superuser powers are granted to this user. This user does not actually have to exist, so the single-user mode can be used to manually recover from certain kinds of accidental damage to the system catalogs. Options ------- `postgres` accepts the following command-line arguments. For a detailed discussion of the options consult [Chapter 19](https://www.postgresql.org/docs/current/runtime-config.html "Chapter 19. Server Configuration") . You can save typing most of these options by setting up a configuration file. Some (safe) options can also be set from the connecting client in an application-dependent way to apply only for that session. For example, if the environment variable `PGOPTIONS` is set, then libpq\-based clients will pass that string to the server, which will interpret it as `postgres` command-line options. ### General Purpose ``-B _`nbuffers`_`` Sets the number of shared buffers for use by the server processes. The default value of this parameter is chosen automatically by initdb. Specifying this option is equivalent to setting the [shared\_buffers](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-SHARED-BUFFERS) configuration parameter. ``-c _`name`_=_`value`_`` Sets a named run-time parameter. The configuration parameters supported by PostgreSQL are described in [Chapter 19](https://www.postgresql.org/docs/current/runtime-config.html "Chapter 19. Server Configuration") . Most of the other command line options are in fact short forms of such a parameter assignment. `-c` can appear multiple times to set multiple parameters. ``-C _`name`_`` Prints the value of the named run-time parameter, and exits. (See the `-c` option above for details.) This returns values from `postgresql.conf`, modified by any parameters supplied in this invocation. It does not reflect parameters supplied when the cluster was started. This can be used on a running server for most parameters. However, the server must be shut down for some runtime-computed parameters (e.g., [shared\_memory\_size](https://www.postgresql.org/docs/current/runtime-config-preset.html#GUC-SHARED-MEMORY-SIZE) , [shared\_memory\_size\_in\_huge\_pages](https://www.postgresql.org/docs/current/runtime-config-preset.html#GUC-SHARED-MEMORY-SIZE-IN-HUGE-PAGES) , and [wal\_segment\_size](https://www.postgresql.org/docs/current/runtime-config-preset.html#GUC-WAL-SEGMENT-SIZE) ). This option is meant for other programs that interact with a server instance, such as [pg\_ctl](https://www.postgresql.org/docs/current/app-pg-ctl.html "pg_ctl") , to query configuration parameter values. User-facing applications should instead use [`SHOW`](https://www.postgresql.org/docs/current/sql-show.html "SHOW") or the `pg_settings` view. ``-d _`debug-level`_`` Sets the debug level. The higher this value is set, the more debugging output is written to the server log. Values are from 1 to 5. It is also possible to pass `-d 0` for a specific session, which will prevent the server log level of the parent `postgres` process from being propagated to this session. ``-D _`datadir`_`` Specifies the file system location of the database configuration files. See [Section 19.2](https://www.postgresql.org/docs/current/runtime-config-file-locations.html "19.2. File Locations") for details. `-e` Sets the default date style to “European”, that is `DMY` ordering of input date fields. This also causes the day to be printed before the month in certain date output formats. See [Section 8.5](https://www.postgresql.org/docs/current/datatype-datetime.html "8.5. Date/Time Types") for more information. `-F` Disables `fsync` calls for improved performance, at the risk of data corruption in the event of a system crash. Specifying this option is equivalent to disabling the [fsync](https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-FSYNC) configuration parameter. Read the detailed documentation before using this! ``-h _`hostname`_`` Specifies the IP host name or address on which `postgres` is to listen for TCP/IP connections from client applications. The value can also be a comma-separated list of addresses, or `*` to specify listening on all available interfaces. An empty value specifies not listening on any IP addresses, in which case only Unix-domain sockets can be used to connect to the server. Defaults to listening only on localhost. Specifying this option is equivalent to setting the [listen\_addresses](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-LISTEN-ADDRESSES) configuration parameter. `-i` Allows remote clients to connect via TCP/IP (Internet domain) connections. Without this option, only local connections are accepted. This option is equivalent to setting `listen_addresses` to `*` in `postgresql.conf` or via `-h`. This option is deprecated since it does not allow access to the full functionality of [listen\_addresses](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-LISTEN-ADDRESSES) . It's usually better to set `listen_addresses` directly. ``-k _`directory`_`` Specifies the directory of the Unix-domain socket on which `postgres` is to listen for connections from client applications. The value can also be a comma-separated list of directories. An empty value specifies not listening on any Unix-domain sockets, in which case only TCP/IP sockets can be used to connect to the server. The default value is normally `/tmp`, but that can be changed at build time. Specifying this option is equivalent to setting the [unix\_socket\_directories](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-UNIX-SOCKET-DIRECTORIES) configuration parameter. `-l` Enables secure connections using SSL. PostgreSQL must have been compiled with support for SSL for this option to be available. For more information on using SSL, refer to [Section 18.9](https://www.postgresql.org/docs/current/ssl-tcp.html "18.9. Secure TCP/IP Connections with SSL") . ``-N _`max-connections`_`` Sets the maximum number of client connections that this server will accept. The default value of this parameter is chosen automatically by initdb. Specifying this option is equivalent to setting the [max\_connections](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-MAX-CONNECTIONS) configuration parameter. ``-p _`port`_`` Specifies the TCP/IP port or local Unix domain socket file extension on which `postgres` is to listen for connections from client applications. Defaults to the value of the `PGPORT` environment variable, or if `PGPORT` is not set, then defaults to the value established during compilation (normally 5432). If you specify a port other than the default port, then all client applications must specify the same port using either command-line options or `PGPORT`. `-s` Print time information and other statistics at the end of each command. This is useful for benchmarking or for use in tuning the number of buffers. `-S` _`work-mem`_ Specifies the base amount of memory to be used by sorts and hash tables before resorting to temporary disk files. See the description of the `work_mem` configuration parameter in [Section 19.4.1](https://www.postgresql.org/docs/current/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-MEMORY "19.4.1. Memory") . `-V` `--version` Print the postgres version and exit. ``--_`name`_=_`value`_`` Sets a named run-time parameter; a shorter form of `-c`. `--describe-config` This option dumps out the server's internal configuration variables, descriptions, and defaults in tab-delimited `COPY` format. It is designed primarily for use by administration tools. `-?` `--help` Show help about postgres command line arguments, and exit. ### Semi-Internal Options The options described here are used mainly for debugging purposes, and in some cases to assist with recovery of severely damaged databases. There should be no reason to use them in a production database setup. They are listed here only for use by PostgreSQL system developers. Furthermore, these options might change or be removed in a future release without notice. `-f` `{ s | i | o | b | t | n | m | h }` Forbids the use of particular scan and join methods: `s` and `i` disable sequential and index scans respectively, `o`, `b` and `t` disable index-only scans, bitmap index scans, and TID scans respectively, while `n`, `m`, and `h` disable nested-loop, merge and hash joins respectively. Neither sequential scans nor nested-loop joins can be disabled completely; the `-fs` and `-fn` options simply discourage the optimizer from using those plan types if it has any other alternative. `-O` Allows the structure of system tables to be modified. This is used by `initdb`. `-P` Ignore system indexes when reading system tables, but still update the indexes when modifying the tables. This is useful when recovering from damaged system indexes. `-t` `pa[rser] | pl[anner] | e[xecutor]` Print timing statistics for each query relating to each of the major system modules. This option cannot be used together with the `-s` option. `-T` This option is for debugging problems that cause a server process to die abnormally. The ordinary strategy in this situation is to notify all other server processes that they must terminate, by sending them SIGQUIT signals. With this option, SIGABRT will be sent instead, resulting in production of core dump files. `-v` _`protocol`_ Specifies the version number of the frontend/backend protocol to be used for a particular session. This option is for internal use only. `-W` _`seconds`_ A delay of this many seconds occurs when a new server process is started, after it conducts the authentication procedure. This is intended to give an opportunity to attach to the server process with a debugger. ### Options for Single-User Mode The following options only apply to the single-user mode (see [Single-User Mode](https://www.postgresql.org/docs/current/app-postgres.html#APP-POSTGRES-SINGLE-USER "Single-User Mode") below). `--single` Selects the single-user mode. This must be the first argument on the command line. _`database`_ Specifies the name of the database to be accessed. This must be the last argument on the command line. If it is omitted it defaults to the user name. `-E` Echo all commands to standard output before executing them. `-j` Use semicolon followed by two newlines, rather than just newline, as the command entry terminator. `-r` _`filename`_ Send all server log output to _`filename`_. This option is only honored when supplied as a command-line option. Environment ----------- `PGCLIENTENCODING` Default character encoding used by clients. (The clients can override this individually.) This value can also be set in the configuration file. `PGDATA` Default data directory location `PGDATESTYLE` Default value of the [DateStyle](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-DATESTYLE) run-time parameter. (The use of this environment variable is deprecated.) `PGPORT` Default port number (preferably set in the configuration file) Diagnostics ----------- A failure message mentioning `semget` or `shmget` probably indicates you need to configure your kernel to provide adequate shared memory and semaphores. For more discussion see [Section 18.4](https://www.postgresql.org/docs/current/kernel-resources.html "18.4. Managing Kernel Resources") . You might be able to postpone reconfiguring your kernel by decreasing [shared\_buffers](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-SHARED-BUFFERS) to reduce the shared memory consumption of PostgreSQL, and/or by reducing [max\_connections](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-MAX-CONNECTIONS) to reduce the semaphore consumption. A failure message suggesting that another server is already running should be checked carefully, for example by using the command $ or $ depending on your system. If you are certain that no conflicting server is running, you can remove the lock file mentioned in the message and try again. A failure message indicating inability to bind to a port might indicate that that port is already in use by some non-PostgreSQL process. You might also get this error if you terminate `postgres` and immediately restart it using the same port; in this case, you must simply wait a few seconds until the operating system closes the port before trying again. Finally, you might get this error if you specify a port number that your operating system considers to be reserved. For example, many versions of Unix consider port numbers under 1024 to be “trusted” and only permit the Unix superuser to access them. Notes ----- The utility command [pg\_ctl](https://www.postgresql.org/docs/current/app-pg-ctl.html "pg_ctl") can be used to start and shut down the `postgres` server safely and comfortably. If at all possible, _do not_ use `SIGKILL` to kill the main `postgres` server. Doing so will prevent `postgres` from freeing the system resources (e.g., shared memory and semaphores) that it holds before terminating. This might cause problems for starting a fresh `postgres` run. To terminate the `postgres` server normally, the signals `SIGTERM`, `SIGINT`, or `SIGQUIT` can be used. The first will wait for all clients to terminate before quitting, the second will forcefully disconnect all clients, and the third will quit immediately without proper shutdown, resulting in a recovery run during restart. The `SIGHUP` signal will reload the server configuration files. It is also possible to send `SIGHUP` to an individual server process, but that is usually not sensible. To cancel a running query, send the `SIGINT` signal to the process running that command. To terminate a backend process cleanly, send `SIGTERM` to that process. See also `pg_cancel_backend` and `pg_terminate_backend` in [Section 9.28.2](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL "9.28.2. Server Signaling Functions") for the SQL-callable equivalents of these two actions. The `postgres` server uses `SIGQUIT` to tell subordinate server processes to terminate without normal cleanup. This signal _should not_ be used by users. It is also unwise to send `SIGKILL` to a server process — the main `postgres` process will interpret this as a crash and will force all the sibling processes to quit as part of its standard crash-recovery procedure. Bugs ---- The `--` options will not work on FreeBSD or OpenBSD. Use `-c` instead. This is a bug in the affected operating systems; a future release of PostgreSQL will provide a workaround if this is not fixed. Single-User Mode ---------------- To start a single-user mode server, use a command like **``postgres --single -D /usr/local/pgsql/data _`other-options`_ my_database``** Provide the correct path to the database directory with `-D`, or make sure that the environment variable `PGDATA` is set. Also specify the name of the particular database you want to work in. Normally, the single-user mode server treats newline as the command entry terminator; there is no intelligence about semicolons, as there is in psql. To continue a command across multiple lines, you must type backslash just before each newline except the last one. The backslash and adjacent newline are both dropped from the input command. Note that this will happen even when within a string literal or comment. But if you use the `-j` command line switch, a single newline does not terminate command entry; instead, the sequence semicolon-newline-newline does. That is, type a semicolon immediately followed by a completely empty line. Backslash-newline is not treated specially in this mode. Again, there is no intelligence about such a sequence appearing within a string literal or comment. In either input mode, if you type a semicolon that is not just before or part of a command entry terminator, it is considered a command separator. When you do type a command entry terminator, the multiple statements you've entered will be executed as a single transaction. To quit the session, type EOF (**Control**+**D**, usually). If you've entered any text since the last command entry terminator, then EOF will be taken as a command entry terminator, and another EOF will be needed to exit. Note that the single-user mode server does not provide sophisticated line-editing features (no command history, for example). Single-user mode also does not do any background processing, such as automatic checkpoints or replication. Examples -------- To start `postgres` in the background using default values, type: $ To start `postgres` with a specific port, e.g., 1234: $ To connect to this server using psql, specify this port with the -p option: $ or set the environment variable `PGPORT`: $ Named run-time parameters can be set in either of these styles: $ Either form overrides whatever setting might exist for `work_mem` in `postgresql.conf`. Notice that underscores in parameter names can be written as either underscore or dash on the command line. Except for short-term experiments, it's probably better practice to edit the setting in `postgresql.conf` than to rely on a command-line switch to set a parameter. See Also -------- [initdb](https://www.postgresql.org/docs/current/app-initdb.html "initdb") , [pg\_ctl](https://www.postgresql.org/docs/current/app-pg-ctl.html "pg_ctl") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/app-pgwalsummary.html "pg_walsummary") | [Up](https://www.postgresql.org/docs/current/reference-server.html "PostgreSQL Server Applications") | [Next](https://www.postgresql.org/docs/current/internals.html "Part VII. Internals") | | pg\_walsummary | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Part VII. Internals | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/app-postgres.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: postgres November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/app-postgres.html "PostgreSQL 18 - postgres") ([18](https://www.postgresql.org/docs/18/app-postgres.html "PostgreSQL 18 - postgres") ) / [17](https://www.postgresql.org/docs/17/app-postgres.html "PostgreSQL 17 - postgres") / [16](https://www.postgresql.org/docs/16/app-postgres.html "PostgreSQL 16 - postgres") / [15](https://www.postgresql.org/docs/15/app-postgres.html "PostgreSQL 15 - postgres") / [14](https://www.postgresql.org/docs/14/app-postgres.html "PostgreSQL 14 - postgres") Development Versions: [devel](https://www.postgresql.org/docs/devel/app-postgres.html "PostgreSQL devel - postgres") Unsupported versions: [13](https://www.postgresql.org/docs/13/app-postgres.html "PostgreSQL 13 - postgres") / [12](https://www.postgresql.org/docs/12/app-postgres.html "PostgreSQL 12 - postgres") / [11](https://www.postgresql.org/docs/11/app-postgres.html "PostgreSQL 11 - postgres") / [10](https://www.postgresql.org/docs/10/app-postgres.html "PostgreSQL 10 - postgres") / [9.6](https://www.postgresql.org/docs/9.6/app-postgres.html "PostgreSQL 9.6 - postgres") / [9.5](https://www.postgresql.org/docs/9.5/app-postgres.html "PostgreSQL 9.5 - postgres") / [9.4](https://www.postgresql.org/docs/9.4/app-postgres.html "PostgreSQL 9.4 - postgres") / [9.3](https://www.postgresql.org/docs/9.3/app-postgres.html "PostgreSQL 9.3 - postgres") / [9.2](https://www.postgresql.org/docs/9.2/app-postgres.html "PostgreSQL 9.2 - postgres") / [9.1](https://www.postgresql.org/docs/9.1/app-postgres.html "PostgreSQL 9.1 - postgres") / [9.0](https://www.postgresql.org/docs/9.0/app-postgres.html "PostgreSQL 9.0 - postgres") / [8.4](https://www.postgresql.org/docs/8.4/app-postgres.html "PostgreSQL 8.4 - postgres") / [8.3](https://www.postgresql.org/docs/8.3/app-postgres.html "PostgreSQL 8.3 - postgres") / [8.2](https://www.postgresql.org/docs/8.2/app-postgres.html "PostgreSQL 8.2 - postgres") / [8.1](https://www.postgresql.org/docs/8.1/app-postgres.html "PostgreSQL 8.1 - postgres") / [8.0](https://www.postgresql.org/docs/8.0/app-postgres.html "PostgreSQL 8.0 - postgres") / [7.4](https://www.postgresql.org/docs/7.4/app-postgres.html "PostgreSQL 7.4 - postgres") / [7.3](https://www.postgresql.org/docs/7.3/app-postgres.html "PostgreSQL 7.3 - postgres") / [7.2](https://www.postgresql.org/docs/7.2/app-postgres.html "PostgreSQL 7.2 - postgres") / [7.1](https://www.postgresql.org/docs/7.1/app-postgres.html "PostgreSQL 7.1 - postgres") | postgres | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/app-pgwalsummary.html "pg_walsummary") | [Up](https://www.postgresql.org/docs/18/reference-server.html "PostgreSQL Server Applications") | PostgreSQL Server Applications | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/internals.html "Part VII. Internals") | * * * postgres -------- postgres — PostgreSQL database server Synopsis -------- `postgres` \[_`option`_...\] Description ----------- `postgres` is the PostgreSQL database server. In order for a client application to access a database it connects (over a network or locally) to a running `postgres` instance. The `postgres` instance then starts a separate server process to handle the connection. One `postgres` instance always manages the data of exactly one database cluster. A database cluster is a collection of databases that is stored at a common file system location (the “data area”). More than one `postgres` instance can run on a system at one time, so long as they use different data areas and different communication ports (see below). When `postgres` starts it needs to know the location of the data area. The location must be specified by the `-D` option or the `PGDATA` environment variable; there is no default. Typically, `-D` or `PGDATA` points directly to the data area directory created by [initdb](https://www.postgresql.org/docs/18/app-initdb.html "initdb") . Other possible file layouts are discussed in [Section 19.2](https://www.postgresql.org/docs/18/runtime-config-file-locations.html "19.2. File Locations") . By default `postgres` starts in the foreground and prints log messages to the standard error stream. In practical applications `postgres` should be started as a background process, perhaps at boot time. The `postgres` command can also be called in single-user mode. The primary use for this mode is during bootstrapping by [initdb](https://www.postgresql.org/docs/18/app-initdb.html "initdb") . Sometimes it is used for debugging or disaster recovery; note that running a single-user server is not truly suitable for debugging the server, since no realistic interprocess communication and locking will happen. When invoked in single-user mode from the shell, the user can enter queries and the results will be printed to the screen, but in a form that is more useful for developers than end users. In the single-user mode, the session user will be set to the user with ID 1, and implicit superuser powers are granted to this user. This user does not actually have to exist, so the single-user mode can be used to manually recover from certain kinds of accidental damage to the system catalogs. Options ------- `postgres` accepts the following command-line arguments. For a detailed discussion of the options consult [Chapter 19](https://www.postgresql.org/docs/18/runtime-config.html "Chapter 19. Server Configuration") . You can save typing most of these options by setting up a configuration file. Some (safe) options can also be set from the connecting client in an application-dependent way to apply only for that session. For example, if the environment variable `PGOPTIONS` is set, then libpq\-based clients will pass that string to the server, which will interpret it as `postgres` command-line options. ### General Purpose ``-B _`nbuffers`_`` Sets the number of shared buffers for use by the server processes. The default value of this parameter is chosen automatically by initdb. Specifying this option is equivalent to setting the [shared\_buffers](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-SHARED-BUFFERS) configuration parameter. ``-c _`name`_=_`value`_`` Sets a named run-time parameter. The configuration parameters supported by PostgreSQL are described in [Chapter 19](https://www.postgresql.org/docs/18/runtime-config.html "Chapter 19. Server Configuration") . Most of the other command line options are in fact short forms of such a parameter assignment. `-c` can appear multiple times to set multiple parameters. ``-C _`name`_`` Prints the value of the named run-time parameter, and exits. (See the `-c` option above for details.) This returns values from `postgresql.conf`, modified by any parameters supplied in this invocation. It does not reflect parameters supplied when the cluster was started. This can be used on a running server for most parameters. However, the server must be shut down for some runtime-computed parameters (e.g., [shared\_memory\_size](https://www.postgresql.org/docs/18/runtime-config-preset.html#GUC-SHARED-MEMORY-SIZE) , [shared\_memory\_size\_in\_huge\_pages](https://www.postgresql.org/docs/18/runtime-config-preset.html#GUC-SHARED-MEMORY-SIZE-IN-HUGE-PAGES) , and [wal\_segment\_size](https://www.postgresql.org/docs/18/runtime-config-preset.html#GUC-WAL-SEGMENT-SIZE) ). This option is meant for other programs that interact with a server instance, such as [pg\_ctl](https://www.postgresql.org/docs/18/app-pg-ctl.html "pg_ctl") , to query configuration parameter values. User-facing applications should instead use [`SHOW`](https://www.postgresql.org/docs/18/sql-show.html "SHOW") or the `pg_settings` view. ``-d _`debug-level`_`` Sets the debug level. The higher this value is set, the more debugging output is written to the server log. Values are from 1 to 5. It is also possible to pass `-d 0` for a specific session, which will prevent the server log level of the parent `postgres` process from being propagated to this session. ``-D _`datadir`_`` Specifies the file system location of the database configuration files. See [Section 19.2](https://www.postgresql.org/docs/18/runtime-config-file-locations.html "19.2. File Locations") for details. `-e` Sets the default date style to “European”, that is `DMY` ordering of input date fields. This also causes the day to be printed before the month in certain date output formats. See [Section 8.5](https://www.postgresql.org/docs/18/datatype-datetime.html "8.5. Date/Time Types") for more information. `-F` Disables `fsync` calls for improved performance, at the risk of data corruption in the event of a system crash. Specifying this option is equivalent to disabling the [fsync](https://www.postgresql.org/docs/18/runtime-config-wal.html#GUC-FSYNC) configuration parameter. Read the detailed documentation before using this! ``-h _`hostname`_`` Specifies the IP host name or address on which `postgres` is to listen for TCP/IP connections from client applications. The value can also be a comma-separated list of addresses, or `*` to specify listening on all available interfaces. An empty value specifies not listening on any IP addresses, in which case only Unix-domain sockets can be used to connect to the server. Defaults to listening only on localhost. Specifying this option is equivalent to setting the [listen\_addresses](https://www.postgresql.org/docs/18/runtime-config-connection.html#GUC-LISTEN-ADDRESSES) configuration parameter. `-i` Allows remote clients to connect via TCP/IP (Internet domain) connections. Without this option, only local connections are accepted. This option is equivalent to setting `listen_addresses` to `*` in `postgresql.conf` or via `-h`. This option is deprecated since it does not allow access to the full functionality of [listen\_addresses](https://www.postgresql.org/docs/18/runtime-config-connection.html#GUC-LISTEN-ADDRESSES) . It's usually better to set `listen_addresses` directly. ``-k _`directory`_`` Specifies the directory of the Unix-domain socket on which `postgres` is to listen for connections from client applications. The value can also be a comma-separated list of directories. An empty value specifies not listening on any Unix-domain sockets, in which case only TCP/IP sockets can be used to connect to the server. The default value is normally `/tmp`, but that can be changed at build time. Specifying this option is equivalent to setting the [unix\_socket\_directories](https://www.postgresql.org/docs/18/runtime-config-connection.html#GUC-UNIX-SOCKET-DIRECTORIES) configuration parameter. `-l` Enables secure connections using SSL. PostgreSQL must have been compiled with support for SSL for this option to be available. For more information on using SSL, refer to [Section 18.9](https://www.postgresql.org/docs/18/ssl-tcp.html "18.9. Secure TCP/IP Connections with SSL") . ``-N _`max-connections`_`` Sets the maximum number of client connections that this server will accept. The default value of this parameter is chosen automatically by initdb. Specifying this option is equivalent to setting the [max\_connections](https://www.postgresql.org/docs/18/runtime-config-connection.html#GUC-MAX-CONNECTIONS) configuration parameter. ``-p _`port`_`` Specifies the TCP/IP port or local Unix domain socket file extension on which `postgres` is to listen for connections from client applications. Defaults to the value of the `PGPORT` environment variable, or if `PGPORT` is not set, then defaults to the value established during compilation (normally 5432). If you specify a port other than the default port, then all client applications must specify the same port using either command-line options or `PGPORT`. `-s` Print time information and other statistics at the end of each command. This is useful for benchmarking or for use in tuning the number of buffers. `-S` _`work-mem`_ Specifies the base amount of memory to be used by sorts and hash tables before resorting to temporary disk files. See the description of the `work_mem` configuration parameter in [Section 19.4.1](https://www.postgresql.org/docs/18/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-MEMORY "19.4.1. Memory") . `-V` `--version` Print the postgres version and exit. ``--_`name`_=_`value`_`` Sets a named run-time parameter; a shorter form of `-c`. `--describe-config` This option dumps out the server's internal configuration variables, descriptions, and defaults in tab-delimited `COPY` format. It is designed primarily for use by administration tools. `-?` `--help` Show help about postgres command line arguments, and exit. ### Semi-Internal Options The options described here are used mainly for debugging purposes, and in some cases to assist with recovery of severely damaged databases. There should be no reason to use them in a production database setup. They are listed here only for use by PostgreSQL system developers. Furthermore, these options might change or be removed in a future release without notice. `-f` `{ s | i | o | b | t | n | m | h }` Forbids the use of particular scan and join methods: `s` and `i` disable sequential and index scans respectively, `o`, `b` and `t` disable index-only scans, bitmap index scans, and TID scans respectively, while `n`, `m`, and `h` disable nested-loop, merge and hash joins respectively. Neither sequential scans nor nested-loop joins can be disabled completely; the `-fs` and `-fn` options simply discourage the optimizer from using those plan types if it has any other alternative. `-O` Allows the structure of system tables to be modified. This is used by `initdb`. `-P` Ignore system indexes when reading system tables, but still update the indexes when modifying the tables. This is useful when recovering from damaged system indexes. `-t` `pa[rser] | pl[anner] | e[xecutor]` Print timing statistics for each query relating to each of the major system modules. This option cannot be used together with the `-s` option. `-T` This option is for debugging problems that cause a server process to die abnormally. The ordinary strategy in this situation is to notify all other server processes that they must terminate, by sending them SIGQUIT signals. With this option, SIGABRT will be sent instead, resulting in production of core dump files. `-v` _`protocol`_ Specifies the version number of the frontend/backend protocol to be used for a particular session. This option is for internal use only. `-W` _`seconds`_ A delay of this many seconds occurs when a new server process is started, after it conducts the authentication procedure. This is intended to give an opportunity to attach to the server process with a debugger. ### Options for Single-User Mode The following options only apply to the single-user mode (see [Single-User Mode](https://www.postgresql.org/docs/18/app-postgres.html#APP-POSTGRES-SINGLE-USER "Single-User Mode") below). `--single` Selects the single-user mode. This must be the first argument on the command line. _`database`_ Specifies the name of the database to be accessed. This must be the last argument on the command line. If it is omitted it defaults to the user name. `-E` Echo all commands to standard output before executing them. `-j` Use semicolon followed by two newlines, rather than just newline, as the command entry terminator. `-r` _`filename`_ Send all server log output to _`filename`_. This option is only honored when supplied as a command-line option. Environment ----------- `PGCLIENTENCODING` Default character encoding used by clients. (The clients can override this individually.) This value can also be set in the configuration file. `PGDATA` Default data directory location `PGDATESTYLE` Default value of the [DateStyle](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-DATESTYLE) run-time parameter. (The use of this environment variable is deprecated.) `PGPORT` Default port number (preferably set in the configuration file) Diagnostics ----------- A failure message mentioning `semget` or `shmget` probably indicates you need to configure your kernel to provide adequate shared memory and semaphores. For more discussion see [Section 18.4](https://www.postgresql.org/docs/18/kernel-resources.html "18.4. Managing Kernel Resources") . You might be able to postpone reconfiguring your kernel by decreasing [shared\_buffers](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-SHARED-BUFFERS) to reduce the shared memory consumption of PostgreSQL, and/or by reducing [max\_connections](https://www.postgresql.org/docs/18/runtime-config-connection.html#GUC-MAX-CONNECTIONS) to reduce the semaphore consumption. A failure message suggesting that another server is already running should be checked carefully, for example by using the command $ or $ depending on your system. If you are certain that no conflicting server is running, you can remove the lock file mentioned in the message and try again. A failure message indicating inability to bind to a port might indicate that that port is already in use by some non-PostgreSQL process. You might also get this error if you terminate `postgres` and immediately restart it using the same port; in this case, you must simply wait a few seconds until the operating system closes the port before trying again. Finally, you might get this error if you specify a port number that your operating system considers to be reserved. For example, many versions of Unix consider port numbers under 1024 to be “trusted” and only permit the Unix superuser to access them. Notes ----- The utility command [pg\_ctl](https://www.postgresql.org/docs/18/app-pg-ctl.html "pg_ctl") can be used to start and shut down the `postgres` server safely and comfortably. If at all possible, _do not_ use `SIGKILL` to kill the main `postgres` server. Doing so will prevent `postgres` from freeing the system resources (e.g., shared memory and semaphores) that it holds before terminating. This might cause problems for starting a fresh `postgres` run. To terminate the `postgres` server normally, the signals `SIGTERM`, `SIGINT`, or `SIGQUIT` can be used. The first will wait for all clients to terminate before quitting, the second will forcefully disconnect all clients, and the third will quit immediately without proper shutdown, resulting in a recovery run during restart. The `SIGHUP` signal will reload the server configuration files. It is also possible to send `SIGHUP` to an individual server process, but that is usually not sensible. To cancel a running query, send the `SIGINT` signal to the process running that command. To terminate a backend process cleanly, send `SIGTERM` to that process. See also `pg_cancel_backend` and `pg_terminate_backend` in [Section 9.28.2](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL "9.28.2. Server Signaling Functions") for the SQL-callable equivalents of these two actions. The `postgres` server uses `SIGQUIT` to tell subordinate server processes to terminate without normal cleanup. This signal _should not_ be used by users. It is also unwise to send `SIGKILL` to a server process — the main `postgres` process will interpret this as a crash and will force all the sibling processes to quit as part of its standard crash-recovery procedure. Bugs ---- The `--` options will not work on FreeBSD or OpenBSD. Use `-c` instead. This is a bug in the affected operating systems; a future release of PostgreSQL will provide a workaround if this is not fixed. Single-User Mode ---------------- To start a single-user mode server, use a command like **``postgres --single -D /usr/local/pgsql/data _`other-options`_ my_database``** Provide the correct path to the database directory with `-D`, or make sure that the environment variable `PGDATA` is set. Also specify the name of the particular database you want to work in. Normally, the single-user mode server treats newline as the command entry terminator; there is no intelligence about semicolons, as there is in psql. To continue a command across multiple lines, you must type backslash just before each newline except the last one. The backslash and adjacent newline are both dropped from the input command. Note that this will happen even when within a string literal or comment. But if you use the `-j` command line switch, a single newline does not terminate command entry; instead, the sequence semicolon-newline-newline does. That is, type a semicolon immediately followed by a completely empty line. Backslash-newline is not treated specially in this mode. Again, there is no intelligence about such a sequence appearing within a string literal or comment. In either input mode, if you type a semicolon that is not just before or part of a command entry terminator, it is considered a command separator. When you do type a command entry terminator, the multiple statements you've entered will be executed as a single transaction. To quit the session, type EOF (**Control**+**D**, usually). If you've entered any text since the last command entry terminator, then EOF will be taken as a command entry terminator, and another EOF will be needed to exit. Note that the single-user mode server does not provide sophisticated line-editing features (no command history, for example). Single-user mode also does not do any background processing, such as automatic checkpoints or replication. Examples -------- To start `postgres` in the background using default values, type: $ To start `postgres` with a specific port, e.g., 1234: $ To connect to this server using psql, specify this port with the -p option: $ or set the environment variable `PGPORT`: $ Named run-time parameters can be set in either of these styles: $ Either form overrides whatever setting might exist for `work_mem` in `postgresql.conf`. Notice that underscores in parameter names can be written as either underscore or dash on the command line. Except for short-term experiments, it's probably better practice to edit the setting in `postgresql.conf` than to rely on a command-line switch to set a parameter. See Also -------- [initdb](https://www.postgresql.org/docs/18/app-initdb.html "initdb") , [pg\_ctl](https://www.postgresql.org/docs/18/app-pg-ctl.html "pg_ctl") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/app-pgwalsummary.html "pg_walsummary") | [Up](https://www.postgresql.org/docs/18/reference-server.html "PostgreSQL Server Applications") | [Next](https://www.postgresql.org/docs/18/internals.html "Part VII. Internals") | | pg\_walsummary | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | Part VII. Internals | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/app-postgres.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE LANGUAGE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createlanguage.html "PostgreSQL 18 - CREATE LANGUAGE") ([18](https://www.postgresql.org/docs/18/sql-createlanguage.html "PostgreSQL 18 - CREATE LANGUAGE") ) / [17](https://www.postgresql.org/docs/17/sql-createlanguage.html "PostgreSQL 17 - CREATE LANGUAGE") / [16](https://www.postgresql.org/docs/16/sql-createlanguage.html "PostgreSQL 16 - CREATE LANGUAGE") / [15](https://www.postgresql.org/docs/15/sql-createlanguage.html "PostgreSQL 15 - CREATE LANGUAGE") / [14](https://www.postgresql.org/docs/14/sql-createlanguage.html "PostgreSQL 14 - CREATE LANGUAGE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createlanguage.html "PostgreSQL devel - CREATE LANGUAGE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createlanguage.html "PostgreSQL 13 - CREATE LANGUAGE") / [12](https://www.postgresql.org/docs/12/sql-createlanguage.html "PostgreSQL 12 - CREATE LANGUAGE") / [11](https://www.postgresql.org/docs/11/sql-createlanguage.html "PostgreSQL 11 - CREATE LANGUAGE") / [10](https://www.postgresql.org/docs/10/sql-createlanguage.html "PostgreSQL 10 - CREATE LANGUAGE") / [9.6](https://www.postgresql.org/docs/9.6/sql-createlanguage.html "PostgreSQL 9.6 - CREATE LANGUAGE") / [9.5](https://www.postgresql.org/docs/9.5/sql-createlanguage.html "PostgreSQL 9.5 - CREATE LANGUAGE") / [9.4](https://www.postgresql.org/docs/9.4/sql-createlanguage.html "PostgreSQL 9.4 - CREATE LANGUAGE") / [9.3](https://www.postgresql.org/docs/9.3/sql-createlanguage.html "PostgreSQL 9.3 - CREATE LANGUAGE") / [9.2](https://www.postgresql.org/docs/9.2/sql-createlanguage.html "PostgreSQL 9.2 - CREATE LANGUAGE") / [9.1](https://www.postgresql.org/docs/9.1/sql-createlanguage.html "PostgreSQL 9.1 - CREATE LANGUAGE") / [9.0](https://www.postgresql.org/docs/9.0/sql-createlanguage.html "PostgreSQL 9.0 - CREATE LANGUAGE") / [8.4](https://www.postgresql.org/docs/8.4/sql-createlanguage.html "PostgreSQL 8.4 - CREATE LANGUAGE") / [8.3](https://www.postgresql.org/docs/8.3/sql-createlanguage.html "PostgreSQL 8.3 - CREATE LANGUAGE") / [8.2](https://www.postgresql.org/docs/8.2/sql-createlanguage.html "PostgreSQL 8.2 - CREATE LANGUAGE") / [8.1](https://www.postgresql.org/docs/8.1/sql-createlanguage.html "PostgreSQL 8.1 - CREATE LANGUAGE") / [8.0](https://www.postgresql.org/docs/8.0/sql-createlanguage.html "PostgreSQL 8.0 - CREATE LANGUAGE") / [7.4](https://www.postgresql.org/docs/7.4/sql-createlanguage.html "PostgreSQL 7.4 - CREATE LANGUAGE") / [7.3](https://www.postgresql.org/docs/7.3/sql-createlanguage.html "PostgreSQL 7.3 - CREATE LANGUAGE") / [7.2](https://www.postgresql.org/docs/7.2/sql-createlanguage.html "PostgreSQL 7.2 - CREATE LANGUAGE") / [7.1](https://www.postgresql.org/docs/7.1/sql-createlanguage.html "PostgreSQL 7.1 - CREATE LANGUAGE") | CREATE LANGUAGE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createindex.html "CREATE INDEX") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-creatematerializedview.html "CREATE MATERIALIZED VIEW") | * * * CREATE LANGUAGE --------------- CREATE LANGUAGE — define a new procedural language Synopsis -------- CREATE \[ OR REPLACE \] \[ TRUSTED \] \[ PROCEDURAL \] LANGUAGE _`name`_ HANDLER _`call_handler`_ \[ INLINE _`inline_handler`_ \] \[ VALIDATOR _`valfunction`_ \] CREATE \[ OR REPLACE \] \[ TRUSTED \] \[ PROCEDURAL \] LANGUAGE _`name`_ Description ----------- `CREATE LANGUAGE` registers a new procedural language with a PostgreSQL database. Subsequently, functions and procedures can be defined in this new language. `CREATE LANGUAGE` effectively associates the language name with handler function(s) that are responsible for executing functions written in the language. Refer to [Chapter 57](https://www.postgresql.org/docs/18/plhandler.html "Chapter 57. Writing a Procedural Language Handler") for more information about language handlers. `CREATE OR REPLACE LANGUAGE` will either create a new language, or replace an existing definition. If the language already exists, its parameters are updated according to the command, but the language's ownership and permissions settings do not change, and any existing functions written in the language are assumed to still be valid. One must have the PostgreSQL superuser privilege to register a new language or change an existing language's parameters. However, once the language is created it is valid to assign ownership of it to a non-superuser, who may then drop it, change its permissions, rename it, or assign it to a new owner. (Do not, however, assign ownership of the underlying C functions to a non-superuser; that would create a privilege escalation path for that user.) The form of `CREATE LANGUAGE` that does not supply any handler function is obsolete. For backwards compatibility with old dump files, it is interpreted as `CREATE EXTENSION`. That will work if the language has been packaged into an extension of the same name, which is the conventional way to set up procedural languages. Parameters ---------- `TRUSTED` `TRUSTED` specifies that the language does not grant access to data that the user would not otherwise have. If this key word is omitted when registering the language, only users with the PostgreSQL superuser privilege can use this language to create new functions. `PROCEDURAL` This is a noise word. _`name`_ The name of the new procedural language. The name must be unique among the languages in the database. `HANDLER` _`call_handler`_ _`call_handler`_ is the name of a previously registered function that will be called to execute the procedural language's functions. The call handler for a procedural language must be written in a compiled language such as C with version 1 call convention and registered with PostgreSQL as a function taking no arguments and returning the `language_handler` type, a placeholder type that is simply used to identify the function as a call handler. `INLINE` _`inline_handler`_ _`inline_handler`_ is the name of a previously registered function that will be called to execute an anonymous code block ([`DO`](https://www.postgresql.org/docs/18/sql-do.html "DO") command) in this language. If no _`inline_handler`_ function is specified, the language does not support anonymous code blocks. The handler function must take one argument of type `internal`, which will be the `DO` command's internal representation, and it will typically return `void`. The return value of the handler is ignored. `VALIDATOR` _`valfunction`_ _`valfunction`_ is the name of a previously registered function that will be called when a new function in the language is created, to validate the new function. If no validator function is specified, then a new function will not be checked when it is created. The validator function must take one argument of type `oid`, which will be the OID of the to-be-created function, and will typically return `void`. A validator function would typically inspect the function body for syntactical correctness, but it can also look at other properties of the function, for example if the language cannot handle certain argument types. To signal an error, the validator function should use the `ereport()` function. The return value of the function is ignored. Notes ----- Use [`DROP LANGUAGE`](https://www.postgresql.org/docs/18/sql-droplanguage.html "DROP LANGUAGE") to drop procedural languages. The system catalog `pg_language` (see [Section 52.29](https://www.postgresql.org/docs/18/catalog-pg-language.html "52.29. pg_language") ) records information about the currently installed languages. Also, the psql command `\dL` lists the installed languages. To create functions in a procedural language, a user must have the `USAGE` privilege for the language. By default, `USAGE` is granted to `PUBLIC` (i.e., everyone) for trusted languages. This can be revoked if desired. Procedural languages are local to individual databases. However, a language can be installed into the `template1` database, which will cause it to be available automatically in all subsequently-created databases. Examples -------- A minimal sequence for creating a new procedural language is: CREATE FUNCTION plsample\_call\_handler() RETURNS language\_handler AS '$libdir/plsample' LANGUAGE C; CREATE LANGUAGE plsample HANDLER plsample\_call\_handler; Typically that would be written in an extension's creation script, and users would do this to install the extension: CREATE EXTENSION plsample; Compatibility ------------- `CREATE LANGUAGE` is a PostgreSQL extension. See Also -------- [ALTER LANGUAGE](https://www.postgresql.org/docs/18/sql-alterlanguage.html "ALTER LANGUAGE") , [CREATE FUNCTION](https://www.postgresql.org/docs/18/sql-createfunction.html "CREATE FUNCTION") , [DROP LANGUAGE](https://www.postgresql.org/docs/18/sql-droplanguage.html "DROP LANGUAGE") , [GRANT](https://www.postgresql.org/docs/18/sql-grant.html "GRANT") , [REVOKE](https://www.postgresql.org/docs/18/sql-revoke.html "REVOKE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createindex.html "CREATE INDEX") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-creatematerializedview.html "CREATE MATERIALIZED VIEW") | | CREATE INDEX | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | CREATE MATERIALIZED VIEW | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createlanguage.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE LANGUAGE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createlanguage.html "PostgreSQL 18 - CREATE LANGUAGE") ([18](https://www.postgresql.org/docs/18/sql-createlanguage.html "PostgreSQL 18 - CREATE LANGUAGE") ) / [17](https://www.postgresql.org/docs/17/sql-createlanguage.html "PostgreSQL 17 - CREATE LANGUAGE") / [16](https://www.postgresql.org/docs/16/sql-createlanguage.html "PostgreSQL 16 - CREATE LANGUAGE") / [15](https://www.postgresql.org/docs/15/sql-createlanguage.html "PostgreSQL 15 - CREATE LANGUAGE") / [14](https://www.postgresql.org/docs/14/sql-createlanguage.html "PostgreSQL 14 - CREATE LANGUAGE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createlanguage.html "PostgreSQL devel - CREATE LANGUAGE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createlanguage.html "PostgreSQL 13 - CREATE LANGUAGE") / [12](https://www.postgresql.org/docs/12/sql-createlanguage.html "PostgreSQL 12 - CREATE LANGUAGE") / [11](https://www.postgresql.org/docs/11/sql-createlanguage.html "PostgreSQL 11 - CREATE LANGUAGE") / [10](https://www.postgresql.org/docs/10/sql-createlanguage.html "PostgreSQL 10 - CREATE LANGUAGE") / [9.6](https://www.postgresql.org/docs/9.6/sql-createlanguage.html "PostgreSQL 9.6 - CREATE LANGUAGE") / [9.5](https://www.postgresql.org/docs/9.5/sql-createlanguage.html "PostgreSQL 9.5 - CREATE LANGUAGE") / [9.4](https://www.postgresql.org/docs/9.4/sql-createlanguage.html "PostgreSQL 9.4 - CREATE LANGUAGE") / [9.3](https://www.postgresql.org/docs/9.3/sql-createlanguage.html "PostgreSQL 9.3 - CREATE LANGUAGE") / [9.2](https://www.postgresql.org/docs/9.2/sql-createlanguage.html "PostgreSQL 9.2 - CREATE LANGUAGE") / [9.1](https://www.postgresql.org/docs/9.1/sql-createlanguage.html "PostgreSQL 9.1 - CREATE LANGUAGE") / [9.0](https://www.postgresql.org/docs/9.0/sql-createlanguage.html "PostgreSQL 9.0 - CREATE LANGUAGE") / [8.4](https://www.postgresql.org/docs/8.4/sql-createlanguage.html "PostgreSQL 8.4 - CREATE LANGUAGE") / [8.3](https://www.postgresql.org/docs/8.3/sql-createlanguage.html "PostgreSQL 8.3 - CREATE LANGUAGE") / [8.2](https://www.postgresql.org/docs/8.2/sql-createlanguage.html "PostgreSQL 8.2 - CREATE LANGUAGE") / [8.1](https://www.postgresql.org/docs/8.1/sql-createlanguage.html "PostgreSQL 8.1 - CREATE LANGUAGE") / [8.0](https://www.postgresql.org/docs/8.0/sql-createlanguage.html "PostgreSQL 8.0 - CREATE LANGUAGE") / [7.4](https://www.postgresql.org/docs/7.4/sql-createlanguage.html "PostgreSQL 7.4 - CREATE LANGUAGE") / [7.3](https://www.postgresql.org/docs/7.3/sql-createlanguage.html "PostgreSQL 7.3 - CREATE LANGUAGE") / [7.2](https://www.postgresql.org/docs/7.2/sql-createlanguage.html "PostgreSQL 7.2 - CREATE LANGUAGE") / [7.1](https://www.postgresql.org/docs/7.1/sql-createlanguage.html "PostgreSQL 7.1 - CREATE LANGUAGE") | CREATE LANGUAGE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createindex.html "CREATE INDEX") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-creatematerializedview.html "CREATE MATERIALIZED VIEW") | * * * CREATE LANGUAGE --------------- CREATE LANGUAGE — define a new procedural language Synopsis -------- CREATE \[ OR REPLACE \] \[ TRUSTED \] \[ PROCEDURAL \] LANGUAGE _`name`_ HANDLER _`call_handler`_ \[ INLINE _`inline_handler`_ \] \[ VALIDATOR _`valfunction`_ \] CREATE \[ OR REPLACE \] \[ TRUSTED \] \[ PROCEDURAL \] LANGUAGE _`name`_ Description ----------- `CREATE LANGUAGE` registers a new procedural language with a PostgreSQL database. Subsequently, functions and procedures can be defined in this new language. `CREATE LANGUAGE` effectively associates the language name with handler function(s) that are responsible for executing functions written in the language. Refer to [Chapter 57](https://www.postgresql.org/docs/current/plhandler.html "Chapter 57. Writing a Procedural Language Handler") for more information about language handlers. `CREATE OR REPLACE LANGUAGE` will either create a new language, or replace an existing definition. If the language already exists, its parameters are updated according to the command, but the language's ownership and permissions settings do not change, and any existing functions written in the language are assumed to still be valid. One must have the PostgreSQL superuser privilege to register a new language or change an existing language's parameters. However, once the language is created it is valid to assign ownership of it to a non-superuser, who may then drop it, change its permissions, rename it, or assign it to a new owner. (Do not, however, assign ownership of the underlying C functions to a non-superuser; that would create a privilege escalation path for that user.) The form of `CREATE LANGUAGE` that does not supply any handler function is obsolete. For backwards compatibility with old dump files, it is interpreted as `CREATE EXTENSION`. That will work if the language has been packaged into an extension of the same name, which is the conventional way to set up procedural languages. Parameters ---------- `TRUSTED` `TRUSTED` specifies that the language does not grant access to data that the user would not otherwise have. If this key word is omitted when registering the language, only users with the PostgreSQL superuser privilege can use this language to create new functions. `PROCEDURAL` This is a noise word. _`name`_ The name of the new procedural language. The name must be unique among the languages in the database. `HANDLER` _`call_handler`_ _`call_handler`_ is the name of a previously registered function that will be called to execute the procedural language's functions. The call handler for a procedural language must be written in a compiled language such as C with version 1 call convention and registered with PostgreSQL as a function taking no arguments and returning the `language_handler` type, a placeholder type that is simply used to identify the function as a call handler. `INLINE` _`inline_handler`_ _`inline_handler`_ is the name of a previously registered function that will be called to execute an anonymous code block ([`DO`](https://www.postgresql.org/docs/current/sql-do.html "DO") command) in this language. If no _`inline_handler`_ function is specified, the language does not support anonymous code blocks. The handler function must take one argument of type `internal`, which will be the `DO` command's internal representation, and it will typically return `void`. The return value of the handler is ignored. `VALIDATOR` _`valfunction`_ _`valfunction`_ is the name of a previously registered function that will be called when a new function in the language is created, to validate the new function. If no validator function is specified, then a new function will not be checked when it is created. The validator function must take one argument of type `oid`, which will be the OID of the to-be-created function, and will typically return `void`. A validator function would typically inspect the function body for syntactical correctness, but it can also look at other properties of the function, for example if the language cannot handle certain argument types. To signal an error, the validator function should use the `ereport()` function. The return value of the function is ignored. Notes ----- Use [`DROP LANGUAGE`](https://www.postgresql.org/docs/current/sql-droplanguage.html "DROP LANGUAGE") to drop procedural languages. The system catalog `pg_language` (see [Section 52.29](https://www.postgresql.org/docs/current/catalog-pg-language.html "52.29. pg_language") ) records information about the currently installed languages. Also, the psql command `\dL` lists the installed languages. To create functions in a procedural language, a user must have the `USAGE` privilege for the language. By default, `USAGE` is granted to `PUBLIC` (i.e., everyone) for trusted languages. This can be revoked if desired. Procedural languages are local to individual databases. However, a language can be installed into the `template1` database, which will cause it to be available automatically in all subsequently-created databases. Examples -------- A minimal sequence for creating a new procedural language is: CREATE FUNCTION plsample\_call\_handler() RETURNS language\_handler AS '$libdir/plsample' LANGUAGE C; CREATE LANGUAGE plsample HANDLER plsample\_call\_handler; Typically that would be written in an extension's creation script, and users would do this to install the extension: CREATE EXTENSION plsample; Compatibility ------------- `CREATE LANGUAGE` is a PostgreSQL extension. See Also -------- [ALTER LANGUAGE](https://www.postgresql.org/docs/current/sql-alterlanguage.html "ALTER LANGUAGE") , [CREATE FUNCTION](https://www.postgresql.org/docs/current/sql-createfunction.html "CREATE FUNCTION") , [DROP LANGUAGE](https://www.postgresql.org/docs/current/sql-droplanguage.html "DROP LANGUAGE") , [GRANT](https://www.postgresql.org/docs/current/sql-grant.html "GRANT") , [REVOKE](https://www.postgresql.org/docs/current/sql-revoke.html "REVOKE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createindex.html "CREATE INDEX") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-creatematerializedview.html "CREATE MATERIALIZED VIEW") | | CREATE INDEX | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | CREATE MATERIALIZED VIEW | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createlanguage.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 9.28. System Administration Functions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/functions-admin.html "PostgreSQL 18 - 9.28. System Administration Functions") ([18](https://www.postgresql.org/docs/18/functions-admin.html "PostgreSQL 18 - 9.28. System Administration Functions") ) / [17](https://www.postgresql.org/docs/17/functions-admin.html "PostgreSQL 17 - 9.28. System Administration Functions") / [16](https://www.postgresql.org/docs/16/functions-admin.html "PostgreSQL 16 - 9.28. System Administration Functions") / [15](https://www.postgresql.org/docs/15/functions-admin.html "PostgreSQL 15 - 9.28. System Administration Functions") / [14](https://www.postgresql.org/docs/14/functions-admin.html "PostgreSQL 14 - 9.28. System Administration Functions") Development Versions: [devel](https://www.postgresql.org/docs/devel/functions-admin.html "PostgreSQL devel - 9.28. System Administration Functions") Unsupported versions: [13](https://www.postgresql.org/docs/13/functions-admin.html "PostgreSQL 13 - 9.28. System Administration Functions") / [12](https://www.postgresql.org/docs/12/functions-admin.html "PostgreSQL 12 - 9.28. System Administration Functions") / [11](https://www.postgresql.org/docs/11/functions-admin.html "PostgreSQL 11 - 9.28. System Administration Functions") / [10](https://www.postgresql.org/docs/10/functions-admin.html "PostgreSQL 10 - 9.28. System Administration Functions") / [9.6](https://www.postgresql.org/docs/9.6/functions-admin.html "PostgreSQL 9.6 - 9.28. System Administration Functions") / [9.5](https://www.postgresql.org/docs/9.5/functions-admin.html "PostgreSQL 9.5 - 9.28. System Administration Functions") / [9.4](https://www.postgresql.org/docs/9.4/functions-admin.html "PostgreSQL 9.4 - 9.28. System Administration Functions") / [9.3](https://www.postgresql.org/docs/9.3/functions-admin.html "PostgreSQL 9.3 - 9.28. System Administration Functions") / [9.2](https://www.postgresql.org/docs/9.2/functions-admin.html "PostgreSQL 9.2 - 9.28. System Administration Functions") / [9.1](https://www.postgresql.org/docs/9.1/functions-admin.html "PostgreSQL 9.1 - 9.28. System Administration Functions") / [9.0](https://www.postgresql.org/docs/9.0/functions-admin.html "PostgreSQL 9.0 - 9.28. System Administration Functions") / [8.4](https://www.postgresql.org/docs/8.4/functions-admin.html "PostgreSQL 8.4 - 9.28. System Administration Functions") / [8.3](https://www.postgresql.org/docs/8.3/functions-admin.html "PostgreSQL 8.3 - 9.28. System Administration Functions") / [8.2](https://www.postgresql.org/docs/8.2/functions-admin.html "PostgreSQL 8.2 - 9.28. System Administration Functions") / [8.1](https://www.postgresql.org/docs/8.1/functions-admin.html "PostgreSQL 8.1 - 9.28. System Administration Functions") / [8.0](https://www.postgresql.org/docs/8.0/functions-admin.html "PostgreSQL 8.0 - 9.28. System Administration Functions") | 9.28. System Administration Functions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/functions-info.html "9.27. System Information Functions and Operators") | [Up](https://www.postgresql.org/docs/18/functions.html "Chapter 9. Functions and Operators") | Chapter 9. Functions and Operators | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/functions-trigger.html "9.29. Trigger Functions") | * * * 9.28. System Administration Functions [#](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN) ------------------------------------------------------------------------------------------------------------------- [9.28.1. Configuration Settings Functions](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-SET) [9.28.2. Server Signaling Functions](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL) [9.28.3. Backup Control Functions](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-BACKUP) [9.28.4. Recovery Control Functions](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-RECOVERY-CONTROL) [9.28.5. Snapshot Synchronization Functions](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-SNAPSHOT-SYNCHRONIZATION) [9.28.6. Replication Management Functions](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-REPLICATION) [9.28.7. Database Object Management Functions](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-DBOBJECT) [9.28.8. Index Maintenance Functions](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-INDEX) [9.28.9. Generic File Access Functions](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-GENFILE) [9.28.10. Advisory Lock Functions](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS) The functions described in this section are used to control and monitor a PostgreSQL installation. ### 9.28.1. Configuration Settings Functions [#](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-SET) [Table 9.95](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-SET-TABLE "Table 9.95. Configuration Settings Functions") shows the functions available to query and alter run-time configuration parameters. **Table 9.95. Configuration Settings Functions** | Function

Description

Example(s) | | --- | | `current_setting` ( _`setting_name`_ `text` \[, _`missing_ok`_ `boolean` \] ) → `text`

Returns the current value of the setting _`setting_name`_. If there is no such setting, `current_setting` throws an error unless _`missing_ok`_ is supplied and is `true` (in which case NULL is returned). This function corresponds to the SQL command [SHOW](https://www.postgresql.org/docs/18/sql-show.html "SHOW")
.

`current_setting('datestyle')` → `ISO, MDY` | | `set_config` ( _`setting_name`_ `text`, _`new_value`_ `text`, _`is_local`_ `boolean` ) → `text`

Sets the parameter _`setting_name`_ to _`new_value`_, and returns that value. If _`is_local`_ is `true`, the new value will only apply during the current transaction. If you want the new value to apply for the rest of the current session, use `false` instead. This function corresponds to the SQL command [SET](https://www.postgresql.org/docs/18/sql-set.html "SET")
.

`set_config` accepts the NULL value for _`new_value`_, but as settings cannot be null, it is interpreted as a request to reset the setting to its default value.

`set_config('log_statement_stats', 'off', false)` → `off` | ### 9.28.2. Server Signaling Functions [#](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL) The functions shown in [Table 9.96](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL-TABLE "Table 9.96. Server Signaling Functions") send control signals to other server processes. Use of these functions is restricted to superusers by default but access may be granted to others using `GRANT`, with noted exceptions. Each of these functions returns `true` if the signal was successfully sent and `false` if sending the signal failed. **Table 9.96. Server Signaling Functions** | Function

Description | | --- | | `pg_cancel_backend` ( _`pid`_ `integer` ) → `boolean`

Cancels the current query of the session whose backend process has the specified process ID. This is also allowed if the calling role is a member of the role whose backend is being canceled or the calling role has privileges of `pg_signal_backend`, however only superusers can cancel superuser backends. As an exception, roles with privileges of `pg_signal_autovacuum_worker` are permitted to cancel autovacuum worker processes, which are otherwise considered superuser backends. | | `pg_log_backend_memory_contexts` ( _`pid`_ `integer` ) → `boolean`

Requests to log the memory contexts of the backend with the specified process ID. This function can send the request to backends and auxiliary processes except logger. These memory contexts will be logged at `LOG` message level. They will appear in the server log based on the log configuration set (see [Section 19.8](https://www.postgresql.org/docs/18/runtime-config-logging.html "19.8. Error Reporting and Logging")
for more information), but will not be sent to the client regardless of [client\_min\_messages](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-CLIENT-MIN-MESSAGES)
. | | `pg_reload_conf` () → `boolean`

Causes all processes of the PostgreSQL server to reload their configuration files. (This is initiated by sending a SIGHUP signal to the postmaster process, which in turn sends SIGHUP to each of its children.) You can use the [`pg_file_settings`](https://www.postgresql.org/docs/18/view-pg-file-settings.html "53.8. pg_file_settings")
, [`pg_hba_file_rules`](https://www.postgresql.org/docs/18/view-pg-hba-file-rules.html "53.10. pg_hba_file_rules")
and [`pg_ident_file_mappings`](https://www.postgresql.org/docs/18/view-pg-ident-file-mappings.html "53.11. pg_ident_file_mappings")
views to check the configuration files for possible errors, before reloading. | | `pg_rotate_logfile` () → `boolean`

Signals the log-file manager to switch to a new output file immediately. This works only when the built-in log collector is running, since otherwise there is no log-file manager subprocess. | | `pg_terminate_backend` ( _`pid`_ `integer`, _`timeout`_ `bigint` `DEFAULT` `0` ) → `boolean`

Terminates the session whose backend process has the specified process ID. This is also allowed if the calling role is a member of the role whose backend is being terminated or the calling role has privileges of `pg_signal_backend`, however only superusers can terminate superuser backends. As an exception, roles with privileges of `pg_signal_autovacuum_worker` are permitted to terminate autovacuum worker processes, which are otherwise considered superuser backends.

If _`timeout`_ is not specified or zero, this function returns `true` whether the process actually terminates or not, indicating only that the sending of the signal was successful. If the _`timeout`_ is specified (in milliseconds) and greater than zero, the function waits until the process is actually terminated or until the given time has passed. If the process is terminated, the function returns `true`. On timeout, a warning is emitted and `false` is returned. | `pg_cancel_backend` and `pg_terminate_backend` send signals (SIGINT or SIGTERM respectively) to backend processes identified by process ID. The process ID of an active backend can be found from the `pid` column of the `pg_stat_activity` view, or by listing the `postgres` processes on the server (using ps on Unix or the Task Manager on Windows). The role of an active backend can be found from the `usename` column of the `pg_stat_activity` view. `pg_log_backend_memory_contexts` can be used to log the memory contexts of a backend process. For example: postgres=# SELECT pg\_log\_backend\_memory\_contexts(pg\_backend\_pid()); pg\_log\_backend\_memory\_contexts -------------------------------- t (1 row) One message for each memory context will be logged. For example: LOG: logging memory contexts of PID 10377 STATEMENT: SELECT pg\_log\_backend\_memory\_contexts(pg\_backend\_pid()); LOG: level: 1; TopMemoryContext: 80800 total in 6 blocks; 14432 free (5 chunks); 66368 used LOG: level: 2; pgstat TabStatusArray lookup hash table: 8192 total in 1 blocks; 1408 free (0 chunks); 6784 used LOG: level: 2; TopTransactionContext: 8192 total in 1 blocks; 7720 free (1 chunks); 472 used LOG: level: 2; RowDescriptionContext: 8192 total in 1 blocks; 6880 free (0 chunks); 1312 used LOG: level: 2; MessageContext: 16384 total in 2 blocks; 5152 free (0 chunks); 11232 used LOG: level: 2; Operator class cache: 8192 total in 1 blocks; 512 free (0 chunks); 7680 used LOG: level: 2; smgr relation table: 16384 total in 2 blocks; 4544 free (3 chunks); 11840 used LOG: level: 2; TransactionAbortContext: 32768 total in 1 blocks; 32504 free (0 chunks); 264 used ... LOG: level: 2; ErrorContext: 8192 total in 1 blocks; 7928 free (3 chunks); 264 used LOG: Grand total: 1651920 bytes in 201 blocks; 622360 free (88 chunks); 1029560 used If there are more than 100 child contexts under the same parent, the first 100 child contexts are logged, along with a summary of the remaining contexts. Note that frequent calls to this function could incur significant overhead, because it may generate a large number of log messages. ### 9.28.3. Backup Control Functions [#](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-BACKUP) The functions shown in [Table 9.97](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-BACKUP-TABLE "Table 9.97. Backup Control Functions") assist in making on-line backups. These functions cannot be executed during recovery (except `pg_backup_start`, `pg_backup_stop`, and `pg_wal_lsn_diff`). For details about proper usage of these functions, see [Section 25.3](https://www.postgresql.org/docs/18/continuous-archiving.html "25.3. Continuous Archiving and Point-in-Time Recovery (PITR)") . **Table 9.97. Backup Control Functions** | Function

Description | | --- | | `pg_create_restore_point` ( _`name`_ `text` ) → `pg_lsn`

Creates a named marker record in the write-ahead log that can later be used as a recovery target, and returns the corresponding write-ahead log location. The given name can then be used with [recovery\_target\_name](https://www.postgresql.org/docs/18/runtime-config-wal.html#GUC-RECOVERY-TARGET-NAME)
to specify the point up to which recovery will proceed. Avoid creating multiple restore points with the same name, since recovery will stop at the first one whose name matches the recovery target.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_current_wal_flush_lsn` () → `pg_lsn`

Returns the current write-ahead log flush location (see notes below). | | `pg_current_wal_insert_lsn` () → `pg_lsn`

Returns the current write-ahead log insert location (see notes below). | | `pg_current_wal_lsn` () → `pg_lsn`

Returns the current write-ahead log write location (see notes below). | | `pg_backup_start` ( _`label`_ `text` \[, _`fast`_ `boolean` \] ) → `pg_lsn`

Prepares the server to begin an on-line backup. The only required parameter is an arbitrary user-defined label for the backup. (Typically this would be the name under which the backup dump file will be stored.) If the optional second parameter is given as `true`, it specifies executing `pg_backup_start` as quickly as possible. This forces an immediate checkpoint which will cause a spike in I/O operations, slowing any concurrently executing queries.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_backup_stop` ( \[_`wait_for_archive`_ `boolean` \] ) → `record` ( _`lsn`_ `pg_lsn`, _`labelfile`_ `text`, _`spcmapfile`_ `text` )

Finishes performing an on-line backup. The desired contents of the backup label file and the tablespace map file are returned as part of the result of the function and must be written to files in the backup area. These files must not be written to the live data directory (doing so will cause PostgreSQL to fail to restart in the event of a crash).

There is an optional parameter of type `boolean`. If false, the function will return immediately after the backup is completed, without waiting for WAL to be archived. This behavior is only useful with backup software that independently monitors WAL archiving. Otherwise, WAL required to make the backup consistent might be missing and make the backup useless. By default or when this parameter is true, `pg_backup_stop` will wait for WAL to be archived when archiving is enabled. (On a standby, this means that it will wait only when `archive_mode` = `always`. If write activity on the primary is low, it may be useful to run `pg_switch_wal` on the primary in order to trigger an immediate segment switch.)

When executed on a primary, this function also creates a backup history file in the write-ahead log archive area. The history file includes the label given to `pg_backup_start`, the starting and ending write-ahead log locations for the backup, and the starting and ending times of the backup. After recording the ending location, the current write-ahead log insertion point is automatically advanced to the next write-ahead log file, so that the ending write-ahead log file can be archived immediately to complete the backup.

The result of the function is a single record. The _`lsn`_ column holds the backup's ending write-ahead log location (which again can be ignored). The second column returns the contents of the backup label file, and the third column returns the contents of the tablespace map file. These must be stored as part of the backup and are required as part of the restore process.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_switch_wal` () → `pg_lsn`

Forces the server to switch to a new write-ahead log file, which allows the current file to be archived (assuming you are using continuous archiving). The result is the ending write-ahead log location plus 1 within the just-completed write-ahead log file. If there has been no write-ahead log activity since the last write-ahead log switch, `pg_switch_wal` does nothing and returns the start location of the write-ahead log file currently in use.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_walfile_name` ( _`lsn`_ `pg_lsn` ) → `text`

Converts a write-ahead log location to the name of the WAL file holding that location. | | `pg_walfile_name_offset` ( _`lsn`_ `pg_lsn` ) → `record` ( _`file_name`_ `text`, _`file_offset`_ `integer` )

Converts a write-ahead log location to a WAL file name and byte offset within that file. | | `pg_split_walfile_name` ( _`file_name`_ `text` ) → `record` ( _`segment_number`_ `numeric`, _`timeline_id`_ `bigint` )

Extracts the sequence number and timeline ID from a WAL file name. | | `pg_wal_lsn_diff` ( _`lsn1`_ `pg_lsn`, _`lsn2`_ `pg_lsn` ) → `numeric`

Calculates the difference in bytes (_`lsn1`_ - _`lsn2`_) between two write-ahead log locations. This can be used with `pg_stat_replication` or some of the functions shown in [Table 9.97](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-BACKUP-TABLE "Table 9.97. Backup Control Functions")
to get the replication lag. | `pg_current_wal_lsn` displays the current write-ahead log write location in the same format used by the above functions. Similarly, `pg_current_wal_insert_lsn` displays the current write-ahead log insertion location and `pg_current_wal_flush_lsn` displays the current write-ahead log flush location. The insertion location is the “logical” end of the write-ahead log at any instant, while the write location is the end of what has actually been written out from the server's internal buffers, and the flush location is the last location known to be written to durable storage. The write location is the end of what can be examined from outside the server, and is usually what you want if you are interested in archiving partially-complete write-ahead log files. The insertion and flush locations are made available primarily for server debugging purposes. These are all read-only operations and do not require superuser permissions. You can use `pg_walfile_name_offset` to extract the corresponding write-ahead log file name and byte offset from a `pg_lsn` value. For example: postgres=# SELECT \* FROM pg\_walfile\_name\_offset((pg\_backup\_stop()).lsn); file\_name | file\_offset --------------------------+------------- 00000001000000000000000D | 4039624 (1 row) Similarly, `pg_walfile_name` extracts just the write-ahead log file name. `pg_split_walfile_name` is useful to compute a LSN from a file offset and WAL file name, for example: postgres=# \\set file\_name '000000010000000100C000AB' postgres=# \\set offset 256 postgres=# SELECT '0/0'::pg\_lsn + pd.segment\_number \* ps.setting::int + :offset AS lsn FROM pg\_split\_walfile\_name(:'file\_name') pd, pg\_show\_all\_settings() ps WHERE ps.name = 'wal\_segment\_size'; lsn --------------- C001/AB000100 (1 row) ### 9.28.4. Recovery Control Functions [#](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-RECOVERY-CONTROL) The functions shown in [Table 9.98](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-RECOVERY-INFO-TABLE "Table 9.98. Recovery Information Functions") provide information about the current status of a standby server. These functions may be executed both during recovery and in normal running. **Table 9.98. Recovery Information Functions** | Function

Description | | --- | | `pg_is_in_recovery` () → `boolean`

Returns true if recovery is still in progress. | | `pg_last_wal_receive_lsn` () → `pg_lsn`

Returns the last write-ahead log location that has been received and synced to disk by streaming replication. While streaming replication is in progress this will increase monotonically. If recovery has completed then this will remain static at the location of the last WAL record received and synced to disk during recovery. If streaming replication is disabled, or if it has not yet started, the function returns `NULL`. | | `pg_last_wal_replay_lsn` () → `pg_lsn`

Returns the last write-ahead log location that has been replayed during recovery. If recovery is still in progress this will increase monotonically. If recovery has completed then this will remain static at the location of the last WAL record applied during recovery. When the server has been started normally without recovery, the function returns `NULL`. | | `pg_last_xact_replay_timestamp` () → `timestamp with time zone`

Returns the time stamp of the last transaction replayed during recovery. This is the time at which the commit or abort WAL record for that transaction was generated on the primary. If no transactions have been replayed during recovery, the function returns `NULL`. Otherwise, if recovery is still in progress this will increase monotonically. If recovery has completed then this will remain static at the time of the last transaction applied during recovery. When the server has been started normally without recovery, the function returns `NULL`. | | `pg_get_wal_resource_managers` () → `setof record` ( _`rm_id`_ `integer`, _`rm_name`_ `text`, _`rm_builtin`_ `boolean` )

Returns the currently-loaded WAL resource managers in the system. The column _`rm_builtin`_ indicates whether it's a built-in resource manager, or a custom resource manager loaded by an extension. | The functions shown in [Table 9.99](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-RECOVERY-CONTROL-TABLE "Table 9.99. Recovery Control Functions") control the progress of recovery. These functions may be executed only during recovery. **Table 9.99. Recovery Control Functions** | Function

Description | | --- | | `pg_is_wal_replay_paused` () → `boolean`

Returns true if recovery pause is requested. | | `pg_get_wal_replay_pause_state` () → `text`

Returns recovery pause state. The return values are `not paused` if pause is not requested, `pause requested` if pause is requested but recovery is not yet paused, and `paused` if the recovery is actually paused. | | `pg_promote` ( _`wait`_ `boolean` `DEFAULT` `true`, _`wait_seconds`_ `integer` `DEFAULT` `60` ) → `boolean`

Promotes a standby server to primary status. With _`wait`_ set to `true` (the default), the function waits until promotion is completed or _`wait_seconds`_ seconds have passed, and returns `true` if promotion is successful and `false` otherwise. If _`wait`_ is set to `false`, the function returns `true` immediately after sending a `SIGUSR1` signal to the postmaster to trigger promotion.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_wal_replay_pause` () → `void`

Request to pause recovery. A request doesn't mean that recovery stops right away. If you want a guarantee that recovery is actually paused, you need to check for the recovery pause state returned by `pg_get_wal_replay_pause_state()`. Note that `pg_is_wal_replay_paused()` returns whether a request is made. While recovery is paused, no further database changes are applied. If hot standby is active, all new queries will see the same consistent snapshot of the database, and no further query conflicts will be generated until recovery is resumed.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_wal_replay_resume` () → `void`

Restarts recovery if it was paused.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | `pg_wal_replay_pause` and `pg_wal_replay_resume` cannot be executed while a promotion is ongoing. If a promotion is triggered while recovery is paused, the paused state ends and promotion continues. If streaming replication is disabled, the paused state may continue indefinitely without a problem. If streaming replication is in progress then WAL records will continue to be received, which will eventually fill available disk space, depending upon the duration of the pause, the rate of WAL generation and available disk space. ### 9.28.5. Snapshot Synchronization Functions [#](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-SNAPSHOT-SYNCHRONIZATION) PostgreSQL allows database sessions to synchronize their snapshots. A _snapshot_ determines which data is visible to the transaction that is using the snapshot. Synchronized snapshots are necessary when two or more sessions need to see identical content in the database. If two sessions just start their transactions independently, there is always a possibility that some third transaction commits between the executions of the two `START TRANSACTION` commands, so that one session sees the effects of that transaction and the other does not. To solve this problem, PostgreSQL allows a transaction to _export_ the snapshot it is using. As long as the exporting transaction remains open, other transactions can _import_ its snapshot, and thereby be guaranteed that they see exactly the same view of the database that the first transaction sees. But note that any database changes made by any one of these transactions remain invisible to the other transactions, as is usual for changes made by uncommitted transactions. So the transactions are synchronized with respect to pre-existing data, but act normally for changes they make themselves. Snapshots are exported with the `pg_export_snapshot` function, shown in [Table 9.100](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-SNAPSHOT-SYNCHRONIZATION-TABLE "Table 9.100. Snapshot Synchronization Functions") , and imported with the [SET TRANSACTION](https://www.postgresql.org/docs/18/sql-set-transaction.html "SET TRANSACTION") command. **Table 9.100. Snapshot Synchronization Functions** | Function

Description | | --- | | `pg_export_snapshot` () → `text`

Saves the transaction's current snapshot and returns a `text` string identifying the snapshot. This string must be passed (outside the database) to clients that want to import the snapshot. The snapshot is available for import only until the end of the transaction that exported it.

A transaction can export more than one snapshot, if needed. Note that doing so is only useful in `READ COMMITTED` transactions, since in `REPEATABLE READ` and higher isolation levels, transactions use the same snapshot throughout their lifetime. Once a transaction has exported any snapshots, it cannot be prepared with [PREPARE TRANSACTION](https://www.postgresql.org/docs/18/sql-prepare-transaction.html "PREPARE TRANSACTION")
. | | `pg_log_standby_snapshot` () → `pg_lsn`

Take a snapshot of running transactions and write it to WAL, without having to wait for bgwriter or checkpointer to log one. This is useful for logical decoding on standby, as logical slot creation has to wait until such a record is replayed on the standby. | ### 9.28.6. Replication Management Functions [#](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-REPLICATION) The functions shown in [Table 9.101](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-REPLICATION-TABLE "Table 9.101. Replication Management Functions") are for controlling and interacting with replication features. See [Section 26.2.5](https://www.postgresql.org/docs/18/warm-standby.html#STREAMING-REPLICATION "26.2.5. Streaming Replication") , [Section 26.2.6](https://www.postgresql.org/docs/18/warm-standby.html#STREAMING-REPLICATION-SLOTS "26.2.6. Replication Slots") , and [Chapter 48](https://www.postgresql.org/docs/18/replication-origins.html "Chapter 48. Replication Progress Tracking") for information about the underlying features. Use of functions for replication origin is only allowed to the superuser by default, but may be allowed to other users by using the `GRANT` command. Use of functions for replication slots is restricted to superusers and users having `REPLICATION` privilege. Many of these functions have equivalent commands in the replication protocol; see [Section 54.4](https://www.postgresql.org/docs/18/protocol-replication.html "54.4. Streaming Replication Protocol") . The functions described in [Section 9.28.3](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-BACKUP "9.28.3. Backup Control Functions") , [Section 9.28.4](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-RECOVERY-CONTROL "9.28.4. Recovery Control Functions") , and [Section 9.28.5](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-SNAPSHOT-SYNCHRONIZATION "9.28.5. Snapshot Synchronization Functions") are also relevant for replication. **Table 9.101. Replication Management Functions** | Function

Description | | --- | | `pg_create_physical_replication_slot` ( _`slot_name`_ `name` \[, _`immediately_reserve`_ `boolean`, _`temporary`_ `boolean` \] ) → `record` ( _`slot_name`_ `name`, _`lsn`_ `pg_lsn` )

Creates a new physical replication slot named _`slot_name`_. The optional second parameter, when `true`, specifies that the LSN for this replication slot be reserved immediately; otherwise the LSN is reserved on first connection from a streaming replication client. Streaming changes from a physical slot is only possible with the streaming-replication protocol — see [Section 54.4](https://www.postgresql.org/docs/18/protocol-replication.html "54.4. Streaming Replication Protocol")
. The optional third parameter, _`temporary`_, when set to true, specifies that the slot should not be permanently stored to disk and is only meant for use by the current session. Temporary slots are also released upon any error. This function corresponds to the replication protocol command `CREATE_REPLICATION_SLOT ... PHYSICAL`. | | `pg_drop_replication_slot` ( _`slot_name`_ `name` ) → `void`

Drops the physical or logical replication slot named _`slot_name`_. Same as replication protocol command `DROP_REPLICATION_SLOT`. | | `pg_create_logical_replication_slot` ( _`slot_name`_ `name`, _`plugin`_ `name` \[, _`temporary`_ `boolean`, _`twophase`_ `boolean`, _`failover`_ `boolean` \] ) → `record` ( _`slot_name`_ `name`, _`lsn`_ `pg_lsn` )

Creates a new logical (decoding) replication slot named _`slot_name`_ using the output plugin _`plugin`_. The optional third parameter, _`temporary`_, when set to true, specifies that the slot should not be permanently stored to disk and is only meant for use by the current session. Temporary slots are also released upon any error. The optional fourth parameter, _`twophase`_, when set to true, specifies that the decoding of prepared transactions is enabled for this slot. The optional fifth parameter, _`failover`_, when set to true, specifies that this slot is enabled to be synced to the standbys so that logical replication can be resumed after failover. A call to this function has the same effect as the replication protocol command `CREATE_REPLICATION_SLOT ... LOGICAL`. | | `pg_copy_physical_replication_slot` ( _`src_slot_name`_ `name`, _`dst_slot_name`_ `name` \[, _`temporary`_ `boolean` \] ) → `record` ( _`slot_name`_ `name`, _`lsn`_ `pg_lsn` )

Copies an existing physical replication slot named _`src_slot_name`_ to a physical replication slot named _`dst_slot_name`_. The copied physical slot starts to reserve WAL from the same LSN as the source slot. _`temporary`_ is optional. If _`temporary`_ is omitted, the same value as the source slot is used. Copy of an invalidated slot is not allowed. | | `pg_copy_logical_replication_slot` ( _`src_slot_name`_ `name`, _`dst_slot_name`_ `name` \[, _`temporary`_ `boolean` \[, _`plugin`_ `name` \]\] ) → `record` ( _`slot_name`_ `name`, _`lsn`_ `pg_lsn` )

Copies an existing logical replication slot named _`src_slot_name`_ to a logical replication slot named _`dst_slot_name`_, optionally changing the output plugin and persistence. The copied logical slot starts from the same LSN as the source logical slot. Both _`temporary`_ and _`plugin`_ are optional; if they are omitted, the values of the source slot are used. The `failover` option of the source logical slot is not copied and is set to `false` by default. This is to avoid the risk of being unable to continue logical replication after failover to standby where the slot is being synchronized. Copy of an invalidated slot is not allowed. | | `pg_logical_slot_get_changes` ( _`slot_name`_ `name`, _`upto_lsn`_ `pg_lsn`, _`upto_nchanges`_ `integer`, `VARIADIC` _`options`_ `text[]` ) → `setof record` ( _`lsn`_ `pg_lsn`, _`xid`_ `xid`, _`data`_ `text` )

Returns changes in the slot _`slot_name`_, starting from the point from which changes have been consumed last. If _`upto_lsn`_ and _`upto_nchanges`_ are NULL, logical decoding will continue until end of WAL. If _`upto_lsn`_ is non-NULL, decoding will include only those transactions which commit prior to the specified LSN. If _`upto_nchanges`_ is non-NULL, decoding will stop when the number of rows produced by decoding exceeds the specified value. Note, however, that the actual number of rows returned may be larger, since this limit is only checked after adding the rows produced when decoding each new transaction commit. If the specified slot is a logical failover slot then the function will not return until all physical slots specified in [`synchronized_standby_slots`](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-SYNCHRONIZED-STANDBY-SLOTS)
have confirmed WAL receipt. | | `pg_logical_slot_peek_changes` ( _`slot_name`_ `name`, _`upto_lsn`_ `pg_lsn`, _`upto_nchanges`_ `integer`, `VARIADIC` _`options`_ `text[]` ) → `setof record` ( _`lsn`_ `pg_lsn`, _`xid`_ `xid`, _`data`_ `text` )

Behaves just like the `pg_logical_slot_get_changes()` function, except that changes are not consumed; that is, they will be returned again on future calls. | | `pg_logical_slot_get_binary_changes` ( _`slot_name`_ `name`, _`upto_lsn`_ `pg_lsn`, _`upto_nchanges`_ `integer`, `VARIADIC` _`options`_ `text[]` ) → `setof record` ( _`lsn`_ `pg_lsn`, _`xid`_ `xid`, _`data`_ `bytea` )

Behaves just like the `pg_logical_slot_get_changes()` function, except that changes are returned as `bytea`. | | `pg_logical_slot_peek_binary_changes` ( _`slot_name`_ `name`, _`upto_lsn`_ `pg_lsn`, _`upto_nchanges`_ `integer`, `VARIADIC` _`options`_ `text[]` ) → `setof record` ( _`lsn`_ `pg_lsn`, _`xid`_ `xid`, _`data`_ `bytea` )

Behaves just like the `pg_logical_slot_peek_changes()` function, except that changes are returned as `bytea`. | | `pg_replication_slot_advance` ( _`slot_name`_ `name`, _`upto_lsn`_ `pg_lsn` ) → `record` ( _`slot_name`_ `name`, _`end_lsn`_ `pg_lsn` )

Advances the current confirmed position of a replication slot named _`slot_name`_. The slot will not be moved backwards, and it will not be moved beyond the current insert location. Returns the name of the slot and the actual position that it was advanced to. The updated slot position information is written out at the next checkpoint if any advancing is done. So in the event of a crash, the slot may return to an earlier position. If the specified slot is a logical failover slot then the function will not return until all physical slots specified in [`synchronized_standby_slots`](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-SYNCHRONIZED-STANDBY-SLOTS)
have confirmed WAL receipt. | | `pg_replication_origin_create` ( _`node_name`_ `text` ) → `oid`

Creates a replication origin with the given external name, and returns the internal ID assigned to it. The name must be no longer than 512 bytes. | | `pg_replication_origin_drop` ( _`node_name`_ `text` ) → `void`

Deletes a previously-created replication origin, including any associated replay progress. | | `pg_replication_origin_oid` ( _`node_name`_ `text` ) → `oid`

Looks up a replication origin by name and returns the internal ID. If no such replication origin is found, `NULL` is returned. | | `pg_replication_origin_session_setup` ( _`node_name`_ `text` ) → `void`

Marks the current session as replaying from the given origin, allowing replay progress to be tracked. Can only be used if no origin is currently selected. Use `pg_replication_origin_session_reset` to undo. | | `pg_replication_origin_session_reset` () → `void`

Cancels the effects of `pg_replication_origin_session_setup()`. | | `pg_replication_origin_session_is_setup` () → `boolean`

Returns true if a replication origin has been selected in the current session. | | `pg_replication_origin_session_progress` ( _`flush`_ `boolean` ) → `pg_lsn`

Returns the replay location for the replication origin selected in the current session. The parameter _`flush`_ determines whether the corresponding local transaction will be guaranteed to have been flushed to disk or not. | | `pg_replication_origin_xact_setup` ( _`origin_lsn`_ `pg_lsn`, _`origin_timestamp`_ `timestamp with time zone` ) → `void`

Marks the current transaction as replaying a transaction that has committed at the given LSN and timestamp. Can only be called when a replication origin has been selected using `pg_replication_origin_session_setup`. | | `pg_replication_origin_xact_reset` () → `void`

Cancels the effects of `pg_replication_origin_xact_setup()`. | | `pg_replication_origin_advance` ( _`node_name`_ `text`, _`lsn`_ `pg_lsn` ) → `void`

Sets replication progress for the given node to the given location. This is primarily useful for setting up the initial location, or setting a new location after configuration changes and similar. Be aware that careless use of this function can lead to inconsistently replicated data. | | `pg_replication_origin_progress` ( _`node_name`_ `text`, _`flush`_ `boolean` ) → `pg_lsn`

Returns the replay location for the given replication origin. The parameter _`flush`_ determines whether the corresponding local transaction will be guaranteed to have been flushed to disk or not. | | `pg_logical_emit_message` ( _`transactional`_ `boolean`, _`prefix`_ `text`, _`content`_ `text` \[, _`flush`_ `boolean` `DEFAULT` `false`\] ) → `pg_lsn`

`pg_logical_emit_message` ( _`transactional`_ `boolean`, _`prefix`_ `text`, _`content`_ `bytea` \[, _`flush`_ `boolean` `DEFAULT` `false`\] ) → `pg_lsn`

Emits a logical decoding message. This can be used to pass generic messages to logical decoding plugins through WAL. The _`transactional`_ parameter specifies if the message should be part of the current transaction, or if it should be written immediately and decoded as soon as the logical decoder reads the record. The _`prefix`_ parameter is a textual prefix that can be used by logical decoding plugins to easily recognize messages that are interesting for them. The _`content`_ parameter is the content of the message, given either in text or binary form. The _`flush`_ parameter (default set to `false`) controls if the message is immediately flushed to WAL or not. _`flush`_ has no effect with _`transactional`_, as the message's WAL record is flushed along with its transaction. | | `pg_sync_replication_slots` () → `void`

Synchronize the logical failover replication slots from the primary server to the standby server. This function can only be executed on the standby server. Temporary synced slots, if any, cannot be used for logical decoding and must be dropped after promotion. See [Section 47.2.3](https://www.postgresql.org/docs/18/logicaldecoding-explanation.html#LOGICALDECODING-REPLICATION-SLOTS-SYNCHRONIZATION "47.2.3. Replication Slot Synchronization")
for details. Note that this function is primarily intended for testing and debugging purposes and should be used with caution. Additionally, this function cannot be executed if [`sync_replication_slots`](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-SYNC-REPLICATION-SLOTS)
is enabled and the slotsync worker is already running to perform the synchronization of slots.

### Caution

If, after executing the function, [`hot_standby_feedback`](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-HOT-STANDBY-FEEDBACK)
is disabled on the standby or the physical slot configured in [`primary_slot_name`](https://www.postgresql.org/docs/18/runtime-config-replication.html#GUC-PRIMARY-SLOT-NAME)
is removed, then it is possible that the necessary rows of the synchronized slot will be removed by the VACUUM process on the primary server, resulting in the synchronized slot becoming invalidated. | ### 9.28.7. Database Object Management Functions [#](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-DBOBJECT) The functions shown in [Table 9.102](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-DBSIZE "Table 9.102. Database Object Size Functions") calculate the disk space usage of database objects, or assist in presentation or understanding of usage results. `bigint` results are measured in bytes. If an OID that does not represent an existing object is passed to one of these functions, `NULL` is returned. **Table 9.102. Database Object Size Functions** | Function

Description | | --- | | `pg_column_size` ( `"any"` ) → `integer`

Shows the number of bytes used to store any individual data value. If applied directly to a table column value, this reflects any compression that was done. | | `pg_column_compression` ( `"any"` ) → `text`

Shows the compression algorithm that was used to compress an individual variable-length value. Returns `NULL` if the value is not compressed. | | `pg_column_toast_chunk_id` ( `"any"` ) → `oid`

Shows the `chunk_id` of an on-disk TOASTed value. Returns `NULL` if the value is un-TOASTed or not on-disk. See [Section 66.2](https://www.postgresql.org/docs/18/storage-toast.html "66.2. TOAST")
for more information about TOAST. | | `pg_database_size` ( `name` ) → `bigint`

`pg_database_size` ( `oid` ) → `bigint`

Computes the total disk space used by the database with the specified name or OID. To use this function, you must have `CONNECT` privilege on the specified database (which is granted by default) or have privileges of the `pg_read_all_stats` role. | | `pg_indexes_size` ( `regclass` ) → `bigint`

Computes the total disk space used by indexes attached to the specified table. | | `pg_relation_size` ( _`relation`_ `regclass` \[, _`fork`_ `text` \] ) → `bigint`

Computes the disk space used by one “fork” of the specified relation. (Note that for most purposes it is more convenient to use the higher-level functions `pg_total_relation_size` or `pg_table_size`, which sum the sizes of all forks.) With one argument, this returns the size of the main data fork of the relation. The second argument can be provided to specify which fork to examine:

* `main` returns the size of the main data fork of the relation.

* `fsm` returns the size of the Free Space Map (see [Section 66.3](https://www.postgresql.org/docs/18/storage-fsm.html "66.3. Free Space Map")
) associated with the relation.

* `vm` returns the size of the Visibility Map (see [Section 66.4](https://www.postgresql.org/docs/18/storage-vm.html "66.4. Visibility Map")
) associated with the relation.

* `init` returns the size of the initialization fork, if any, associated with the relation. | | `pg_size_bytes` ( `text` ) → `bigint`

Converts a size in human-readable format (as returned by `pg_size_pretty`) into bytes. Valid units are `bytes`, `B`, `kB`, `MB`, `GB`, `TB`, and `PB`. | | `pg_size_pretty` ( `bigint` ) → `text`

`pg_size_pretty` ( `numeric` ) → `text`

Converts a size in bytes into a more easily human-readable format with size units (bytes, kB, MB, GB, TB, or PB as appropriate). Note that the units are powers of 2 rather than powers of 10, so 1kB is 1024 bytes, 1MB is 10242 = 1048576 bytes, and so on. | | `pg_table_size` ( `regclass` ) → `bigint`

Computes the disk space used by the specified table, excluding indexes (but including its TOAST table if any, free space map, and visibility map). | | `pg_tablespace_size` ( `name` ) → `bigint`

`pg_tablespace_size` ( `oid` ) → `bigint`

Computes the total disk space used in the tablespace with the specified name or OID. To use this function, you must have `CREATE` privilege on the specified tablespace or have privileges of the `pg_read_all_stats` role, unless it is the default tablespace for the current database. | | `pg_total_relation_size` ( `regclass` ) → `bigint`

Computes the total disk space used by the specified table, including all indexes and TOAST data. The result is equivalent to `pg_table_size` `+` `pg_indexes_size`. | The functions above that operate on tables or indexes accept a `regclass` argument, which is simply the OID of the table or index in the `pg_class` system catalog. You do not have to look up the OID by hand, however, since the `regclass` data type's input converter will do the work for you. See [Section 8.19](https://www.postgresql.org/docs/18/datatype-oid.html "8.19. Object Identifier Types") for details. The functions shown in [Table 9.103](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-DBLOCATION "Table 9.103. Database Object Location Functions") assist in identifying the specific disk files associated with database objects. **Table 9.103. Database Object Location Functions** | Function

Description | | --- | | `pg_relation_filenode` ( _`relation`_ `regclass` ) → `oid`

Returns the “filenode” number currently assigned to the specified relation. The filenode is the base component of the file name(s) used for the relation (see [Section 66.1](https://www.postgresql.org/docs/18/storage-file-layout.html "66.1. Database File Layout")
for more information). For most relations the result is the same as `pg_class`.`relfilenode`, but for certain system catalogs `relfilenode` is zero and this function must be used to get the correct value. The function returns NULL if passed a relation that does not have storage, such as a view. | | `pg_relation_filepath` ( _`relation`_ `regclass` ) → `text`

Returns the entire file path name (relative to the database cluster's data directory, `PGDATA`) of the relation. | | `pg_filenode_relation` ( _`tablespace`_ `oid`, _`filenode`_ `oid` ) → `regclass`

Returns a relation's OID given the tablespace OID and filenode it is stored under. This is essentially the inverse mapping of `pg_relation_filepath`. For a relation in the database's default tablespace, the tablespace can be specified as zero. Returns `NULL` if no relation in the current database is associated with the given values, or if dealing with a temporary relation. | [Table 9.104](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-COLLATION "Table 9.104. Collation Management Functions") lists functions used to manage collations. **Table 9.104. Collation Management Functions** | Function

Description | | --- | | `pg_collation_actual_version` ( `oid` ) → `text`

Returns the actual version of the collation object as it is currently installed in the operating system. If this is different from the value in `pg_collation`.`collversion`, then objects depending on the collation might need to be rebuilt. See also [ALTER COLLATION](https://www.postgresql.org/docs/18/sql-altercollation.html "ALTER COLLATION")
. | | `pg_database_collation_actual_version` ( `oid` ) → `text`

Returns the actual version of the database's collation as it is currently installed in the operating system. If this is different from the value in `pg_database`.`datcollversion`, then objects depending on the collation might need to be rebuilt. See also [ALTER DATABASE](https://www.postgresql.org/docs/18/sql-alterdatabase.html "ALTER DATABASE")
. | | `pg_import_system_collations` ( _`schema`_ `regnamespace` ) → `integer`

Adds collations to the system catalog `pg_collation` based on all the locales it finds in the operating system. This is what `initdb` uses; see [Section 23.2.2](https://www.postgresql.org/docs/18/collation.html#COLLATION-MANAGING "23.2.2. Managing Collations")
for more details. If additional locales are installed into the operating system later on, this function can be run again to add collations for the new locales. Locales that match existing entries in `pg_collation` will be skipped. (But collation objects based on locales that are no longer present in the operating system are not removed by this function.) The _`schema`_ parameter would typically be `pg_catalog`, but that is not a requirement; the collations could be installed into some other schema as well. The function returns the number of new collation objects it created. Use of this function is restricted to superusers. | [Table 9.105](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-STATSMOD "Table 9.105. Database Object Statistics Manipulation Functions") lists functions used to manipulate statistics. These functions cannot be executed during recovery. ### Warning Changes made by these statistics manipulation functions are likely to be overwritten by [autovacuum](https://www.postgresql.org/docs/18/routine-vacuuming.html#AUTOVACUUM "24.1.6. The Autovacuum Daemon") (or manual `VACUUM` or `ANALYZE`) and should be considered temporary. **Table 9.105. Database Object Statistics Manipulation Functions** | Function

Description | | --- | | `pg_restore_relation_stats` ( `VARIADIC` _`kwargs`_ `"any"` ) → `boolean`

Updates table-level statistics. Ordinarily, these statistics are collected automatically or updated as a part of [VACUUM](https://www.postgresql.org/docs/18/sql-vacuum.html "VACUUM")
or [ANALYZE](https://www.postgresql.org/docs/18/sql-analyze.html "ANALYZE")
, so it's not necessary to call this function. However, it is useful after a restore to enable the optimizer to choose better plans if `ANALYZE` has not been run yet.

The tracked statistics may change from version to version, so arguments are passed as pairs of _`argname`_ and _`argvalue`_ in the form:

SELECT pg\_restore\_relation\_stats(
'_`arg1name`_', '_`arg1value`_'::_`arg1type`_,
'_`arg2name`_', '_`arg2value`_'::_`arg2type`_,
'_`arg3name`_', '_`arg3value`_'::_`arg3type`_);

For example, to set the `relpages` and `reltuples` values for the table `mytable`:

SELECT pg\_restore\_relation\_stats(
'schemaname', 'myschema',
'relname', 'mytable',
'relpages', 173::integer,
'reltuples', 10000::real);

The arguments `schemaname` and `relname` are required, and specify the table. Other arguments are the names and values of statistics corresponding to certain columns in [`pg_class`](https://www.postgresql.org/docs/18/catalog-pg-class.html "52.11. pg_class")
. The currently-supported relation statistics are `relpages` with a value of type `integer`, `reltuples` with a value of type `real`, `relallvisible` with a value of type `integer`, and `relallfrozen` with a value of type `integer`.

Additionally, this function accepts argument name `version` of type `integer`, which specifies the server version from which the statistics originated. This is anticipated to be helpful in porting statistics from older versions of PostgreSQL.

Minor errors are reported as a `WARNING` and ignored, and remaining statistics will still be restored. If all specified statistics are successfully restored, returns `true`, otherwise `false`.

The caller must have the `MAINTAIN` privilege on the table or be the owner of the database. | | `pg_clear_relation_stats` ( _`schemaname`_ `text`, _`relname`_ `text` ) → `void`

Clears table-level statistics for the given relation, as though the table was newly created.

The caller must have the `MAINTAIN` privilege on the table or be the owner of the database. | | `pg_restore_attribute_stats` ( `VARIADIC` _`kwargs`_ `"any"` ) → `boolean`

Creates or updates column-level statistics. Ordinarily, these statistics are collected automatically or updated as a part of [VACUUM](https://www.postgresql.org/docs/18/sql-vacuum.html "VACUUM")
or [ANALYZE](https://www.postgresql.org/docs/18/sql-analyze.html "ANALYZE")
, so it's not necessary to call this function. However, it is useful after a restore to enable the optimizer to choose better plans if `ANALYZE` has not been run yet.

The tracked statistics may change from version to version, so arguments are passed as pairs of _`argname`_ and _`argvalue`_ in the form:

SELECT pg\_restore\_attribute\_stats(
'_`arg1name`_', '_`arg1value`_'::_`arg1type`_,
'_`arg2name`_', '_`arg2value`_'::_`arg2type`_,
'_`arg3name`_', '_`arg3value`_'::_`arg3type`_);

For example, to set the `avg_width` and `null_frac` values for the attribute `col1` of the table `mytable`:

SELECT pg\_restore\_attribute\_stats(
'schemaname', 'myschema',
'relname', 'mytable',
'attname', 'col1',
'inherited', false,
'avg\_width', 125::integer,
'null\_frac', 0.5::real);

The required arguments are `schemaname` and `relname` with a value of type `text` which specify the table; either `attname` with a value of type `text` or `attnum` with a value of type `smallint`, which specifies the column; and `inherited`, which specifies whether the statistics include values from child tables. Other arguments are the names and values of statistics corresponding to columns in [`pg_stats`](https://www.postgresql.org/docs/18/view-pg-stats.html "53.29. pg_stats")
.

Additionally, this function accepts argument name `version` of type `integer`, which specifies the server version from which the statistics originated. This is anticipated to be helpful in porting statistics from older versions of PostgreSQL.

Minor errors are reported as a `WARNING` and ignored, and remaining statistics will still be restored. If all specified statistics are successfully restored, returns `true`, otherwise `false`.

The caller must have the `MAINTAIN` privilege on the table or be the owner of the database. | | `pg_clear_attribute_stats` ( _`schemaname`_ `text`, _`relname`_ `text`, _`attname`_ `text`, _`inherited`_ `boolean` ) → `void`

Clears column-level statistics for the given relation and attribute, as though the table was newly created.

The caller must have the `MAINTAIN` privilege on the table or be the owner of the database. | [Table 9.106](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-INFO-PARTITION "Table 9.106. Partitioning Information Functions") lists functions that provide information about the structure of partitioned tables. **Table 9.106. Partitioning Information Functions** | Function

Description | | --- | | `pg_partition_tree` ( `regclass` ) → `setof record` ( _`relid`_ `regclass`, _`parentrelid`_ `regclass`, _`isleaf`_ `boolean`, _`level`_ `integer` )

Lists the tables or indexes in the partition tree of the given partitioned table or partitioned index, with one row for each partition. Information provided includes the OID of the partition, the OID of its immediate parent, a boolean value telling if the partition is a leaf, and an integer telling its level in the hierarchy. The level value is 0 for the input table or index, 1 for its immediate child partitions, 2 for their partitions, and so on. Returns no rows if the relation does not exist or is not a partition or partitioned table. | | `pg_partition_ancestors` ( `regclass` ) → `setof regclass`

Lists the ancestor relations of the given partition, including the relation itself. Returns no rows if the relation does not exist or is not a partition or partitioned table. | | `pg_partition_root` ( `regclass` ) → `regclass`

Returns the top-most parent of the partition tree to which the given relation belongs. Returns `NULL` if the relation does not exist or is not a partition or partitioned table. | For example, to check the total size of the data contained in a partitioned table `measurement`, one could use the following query: SELECT pg\_size\_pretty(sum(pg\_relation\_size(relid))) AS total\_size FROM pg\_partition\_tree('measurement'); ### 9.28.8. Index Maintenance Functions [#](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-INDEX) [Table 9.107](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-INDEX-TABLE "Table 9.107. Index Maintenance Functions") shows the functions available for index maintenance tasks. (Note that these maintenance tasks are normally done automatically by autovacuum; use of these functions is only required in special cases.) These functions cannot be executed during recovery. Use of these functions is restricted to superusers and the owner of the given index. **Table 9.107. Index Maintenance Functions** | Function

Description | | --- | | `brin_summarize_new_values` ( _`index`_ `regclass` ) → `integer`

Scans the specified BRIN index to find page ranges in the base table that are not currently summarized by the index; for any such range it creates a new summary index tuple by scanning those table pages. Returns the number of new page range summaries that were inserted into the index. | | `brin_summarize_range` ( _`index`_ `regclass`, _`blockNumber`_ `bigint` ) → `integer`

Summarizes the page range covering the given block, if not already summarized. This is like `brin_summarize_new_values` except that it only processes the page range that covers the given table block number. | | `brin_desummarize_range` ( _`index`_ `regclass`, _`blockNumber`_ `bigint` ) → `void`

Removes the BRIN index tuple that summarizes the page range covering the given table block, if there is one. | | `gin_clean_pending_list` ( _`index`_ `regclass` ) → `bigint`

Cleans up the “pending” list of the specified GIN index by moving entries in it, in bulk, to the main GIN data structure. Returns the number of pages removed from the pending list. If the argument is a GIN index built with the `fastupdate` option disabled, no cleanup happens and the result is zero, because the index doesn't have a pending list. See [Section 65.4.4.1](https://www.postgresql.org/docs/18/gin.html#GIN-FAST-UPDATE "65.4.4.1. GIN Fast Update Technique")
and [Section 65.4.5](https://www.postgresql.org/docs/18/gin.html#GIN-TIPS "65.4.5. GIN Tips and Tricks")
for details about the pending list and `fastupdate` option. | ### 9.28.9. Generic File Access Functions [#](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-GENFILE) The functions shown in [Table 9.108](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-GENFILE-TABLE "Table 9.108. Generic File Access Functions") provide native access to files on the machine hosting the server. Only files within the database cluster directory and the `log_directory` can be accessed, unless the user is a superuser or is granted the role `pg_read_server_files`. Use a relative path for files in the cluster directory, and a path matching the `log_directory` configuration setting for log files. Note that granting users the EXECUTE privilege on `pg_read_file()`, or related functions, allows them the ability to read any file on the server that the database server process can read; these functions bypass all in-database privilege checks. This means that, for example, a user with such access is able to read the contents of the `pg_authid` table where authentication information is stored, as well as read any table data in the database. Therefore, granting access to these functions should be carefully considered. When granting privilege on these functions, note that the table entries showing optional parameters are mostly implemented as several physical functions with different parameter lists. Privilege must be granted separately on each such function, if it is to be used. psql's `\df` command can be useful to check what the actual function signatures are. Some of these functions take an optional _`missing_ok`_ parameter, which specifies the behavior when the file or directory does not exist. If `true`, the function returns `NULL` or an empty result set, as appropriate. If `false`, an error is raised. (Failure conditions other than “file not found” are reported as errors in any case.) The default is `false`. **Table 9.108. Generic File Access Functions** | Function

Description | | --- | | `pg_ls_dir` ( _`dirname`_ `text` \[, _`missing_ok`_ `boolean`, _`include_dot_dirs`_ `boolean` \] ) → `setof text`

Returns the names of all files (and directories and other special files) in the specified directory. The _`include_dot_dirs`_ parameter indicates whether “.” and “..” are to be included in the result set; the default is to exclude them. Including them can be useful when _`missing_ok`_ is `true`, to distinguish an empty directory from a non-existent directory.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_logdir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's log directory. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and roles with privileges of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_waldir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's write-ahead log (WAL) directory. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and roles with privileges of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_logicalmapdir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's `pg_logical/mappings` directory. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_logicalsnapdir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's `pg_logical/snapshots` directory. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_replslotdir` ( _`slot_name`_ `text` ) → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's `pg_replslot/slot_name` directory, where _`slot_name`_ is the name of the replication slot provided as input of the function. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_summariesdir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's WAL summaries directory (`pg_wal/summaries`). Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_archive_statusdir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's WAL archive status directory (`pg_wal/archive_status`). Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_tmpdir` ( \[ _`tablespace`_ `oid` \] ) → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the temporary file directory for the specified _`tablespace`_. If _`tablespace`_ is not provided, the `pg_default` tablespace is examined. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_read_file` ( _`filename`_ `text` \[, _`offset`_ `bigint`, _`length`_ `bigint` \] \[, _`missing_ok`_ `boolean` \] ) → `text`

Returns all or part of a text file, starting at the given byte _`offset`_, returning at most _`length`_ bytes (less if the end of file is reached first). If _`offset`_ is negative, it is relative to the end of the file. If _`offset`_ and _`length`_ are omitted, the entire file is returned. The bytes read from the file are interpreted as a string in the database's encoding; an error is thrown if they are not valid in that encoding.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_read_binary_file` ( _`filename`_ `text` \[, _`offset`_ `bigint`, _`length`_ `bigint` \] \[, _`missing_ok`_ `boolean` \] ) → `bytea`

Returns all or part of a file. This function is identical to `pg_read_file` except that it can read arbitrary binary data, returning the result as `bytea` not `text`; accordingly, no encoding checks are performed.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function.

In combination with the `convert_from` function, this function can be used to read a text file in a specified encoding and convert to the database's encoding:

SELECT convert\_from(pg\_read\_binary\_file('file\_in\_utf8.txt'), 'UTF8'); | | `pg_stat_file` ( _`filename`_ `text` \[, _`missing_ok`_ `boolean` \] ) → `record` ( _`size`_ `bigint`, _`access`_ `timestamp with time zone`, _`modification`_ `timestamp with time zone`, _`change`_ `timestamp with time zone`, _`creation`_ `timestamp with time zone`, _`isdir`_ `boolean` )

Returns a record containing the file's size, last access time stamp, last modification time stamp, last file status change time stamp (Unix platforms only), file creation time stamp (Windows only), and a flag indicating if it is a directory.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | ### 9.28.10. Advisory Lock Functions [#](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS) The functions shown in [Table 9.109](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS-TABLE "Table 9.109. Advisory Lock Functions") manage advisory locks. For details about proper use of these functions, see [Section 13.3.5](https://www.postgresql.org/docs/18/explicit-locking.html#ADVISORY-LOCKS "13.3.5. Advisory Locks") . All these functions are intended to be used to lock application-defined resources, which can be identified either by a single 64-bit key value or two 32-bit key values (note that these two key spaces do not overlap). If another session already holds a conflicting lock on the same resource identifier, the functions will either wait until the resource becomes available, or return a `false` result, as appropriate for the function. Locks can be either shared or exclusive: a shared lock does not conflict with other shared locks on the same resource, only with exclusive locks. Locks can be taken at session level (so that they are held until released or the session ends) or at transaction level (so that they are held until the current transaction ends; there is no provision for manual release). Multiple session-level lock requests stack, so that if the same resource identifier is locked three times there must then be three unlock requests to release the resource in advance of session end. **Table 9.109. Advisory Lock Functions** | Function

Description | | --- | | `pg_advisory_lock` ( _`key`_ `bigint` ) → `void`

`pg_advisory_lock` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `void`

Obtains an exclusive session-level advisory lock, waiting if necessary. | | `pg_advisory_lock_shared` ( _`key`_ `bigint` ) → `void`

`pg_advisory_lock_shared` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `void`

Obtains a shared session-level advisory lock, waiting if necessary. | | `pg_advisory_unlock` ( _`key`_ `bigint` ) → `boolean`

`pg_advisory_unlock` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Releases a previously-acquired exclusive session-level advisory lock. Returns `true` if the lock is successfully released. If the lock was not held, `false` is returned, and in addition, an SQL warning will be reported by the server. | | `pg_advisory_unlock_all` () → `void`

Releases all session-level advisory locks held by the current session. (This function is implicitly invoked at session end, even if the client disconnects ungracefully.) | | `pg_advisory_unlock_shared` ( _`key`_ `bigint` ) → `boolean`

`pg_advisory_unlock_shared` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Releases a previously-acquired shared session-level advisory lock. Returns `true` if the lock is successfully released. If the lock was not held, `false` is returned, and in addition, an SQL warning will be reported by the server. | | `pg_advisory_xact_lock` ( _`key`_ `bigint` ) → `void`

`pg_advisory_xact_lock` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `void`

Obtains an exclusive transaction-level advisory lock, waiting if necessary. | | `pg_advisory_xact_lock_shared` ( _`key`_ `bigint` ) → `void`

`pg_advisory_xact_lock_shared` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `void`

Obtains a shared transaction-level advisory lock, waiting if necessary. | | `pg_try_advisory_lock` ( _`key`_ `bigint` ) → `boolean`

`pg_try_advisory_lock` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Obtains an exclusive session-level advisory lock if available. This will either obtain the lock immediately and return `true`, or return `false` without waiting if the lock cannot be acquired immediately. | | `pg_try_advisory_lock_shared` ( _`key`_ `bigint` ) → `boolean`

`pg_try_advisory_lock_shared` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Obtains a shared session-level advisory lock if available. This will either obtain the lock immediately and return `true`, or return `false` without waiting if the lock cannot be acquired immediately. | | `pg_try_advisory_xact_lock` ( _`key`_ `bigint` ) → `boolean`

`pg_try_advisory_xact_lock` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Obtains an exclusive transaction-level advisory lock if available. This will either obtain the lock immediately and return `true`, or return `false` without waiting if the lock cannot be acquired immediately. | | `pg_try_advisory_xact_lock_shared` ( _`key`_ `bigint` ) → `boolean`

`pg_try_advisory_xact_lock_shared` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Obtains a shared transaction-level advisory lock if available. This will either obtain the lock immediately and return `true`, or return `false` without waiting if the lock cannot be acquired immediately. | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/functions-info.html "9.27. System Information Functions and Operators") | [Up](https://www.postgresql.org/docs/18/functions.html "Chapter 9. Functions and Operators") | [Next](https://www.postgresql.org/docs/18/functions-trigger.html "9.29. Trigger Functions") | | 9.27. System Information Functions and Operators | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 9.29. Trigger Functions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/functions-admin.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.43. routine_sequence_usage November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-routine-sequence-usage.html "PostgreSQL 18 - 35.43. routine_sequence_usage") ([18](https://www.postgresql.org/docs/18/infoschema-routine-sequence-usage.html "PostgreSQL 18 - 35.43. routine_sequence_usage") ) / [17](https://www.postgresql.org/docs/17/infoschema-routine-sequence-usage.html "PostgreSQL 17 - 35.43. routine_sequence_usage") / [16](https://www.postgresql.org/docs/16/infoschema-routine-sequence-usage.html "PostgreSQL 16 - 35.43. routine_sequence_usage") / [15](https://www.postgresql.org/docs/15/infoschema-routine-sequence-usage.html "PostgreSQL 15 - 35.43. routine_sequence_usage") / [14](https://www.postgresql.org/docs/14/infoschema-routine-sequence-usage.html "PostgreSQL 14 - 35.43. routine_sequence_usage") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-routine-sequence-usage.html "PostgreSQL devel - 35.43. routine_sequence_usage") | 35.43. `routine_sequence_usage` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-routine-routine-usage.html "35.42. routine_routine_usage") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/infoschema-routine-table-usage.html "35.44. routine_table_usage") | * * * 35.43. `routine_sequence_usage` [#](https://www.postgresql.org/docs/current/infoschema-routine-sequence-usage.html#INFOSCHEMA-ROUTINE-SEQUENCE-USAGE) ------------------------------------------------------------------------------------------------------------------------------------------------------ The view `routine_sequence_usage` identifies all sequences that are used by a function or procedure, either in the SQL body or in parameter default expressions. (This only works for unquoted SQL bodies, not quoted bodies or functions in other languages.) A sequence is only included if that sequence is owned by a currently enabled role. **Table 35.41. `routine_sequence_usage` Columns** | Column Type

Description | | --- | | `specific_catalog` `sql_identifier`

Name of the database containing the function (always the current database) | | `specific_schema` `sql_identifier`

Name of the schema containing the function | | `specific_name` `sql_identifier`

The “specific name” of the function. See [Section 35.45](https://www.postgresql.org/docs/current/infoschema-routines.html "35.45. routines")
for more information. | | `routine_catalog` `sql_identifier`

Name of the database containing the function (always the current database) | | `routine_schema` `sql_identifier`

Name of the schema containing the function | | `routine_name` `sql_identifier`

Name of the function (might be duplicated in case of overloading) | | `schema_catalog` `sql_identifier`

Name of the database that contains the sequence that is used by the function (always the current database) | | `sequence_schema` `sql_identifier`

Name of the schema that contains the sequence that is used by the function | | `sequence_name` `sql_identifier`

Name of the sequence that is used by the function | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-routine-routine-usage.html "35.42. routine_routine_usage") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/current/infoschema-routine-table-usage.html "35.44. routine_table_usage") | | 35.42. `routine_routine_usage` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 35.44. `routine_table_usage` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-routine-sequence-usage.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 9.28. System Administration Functions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/functions-admin.html "PostgreSQL 18 - 9.28. System Administration Functions") ([18](https://www.postgresql.org/docs/18/functions-admin.html "PostgreSQL 18 - 9.28. System Administration Functions") ) / [17](https://www.postgresql.org/docs/17/functions-admin.html "PostgreSQL 17 - 9.28. System Administration Functions") / [16](https://www.postgresql.org/docs/16/functions-admin.html "PostgreSQL 16 - 9.28. System Administration Functions") / [15](https://www.postgresql.org/docs/15/functions-admin.html "PostgreSQL 15 - 9.28. System Administration Functions") / [14](https://www.postgresql.org/docs/14/functions-admin.html "PostgreSQL 14 - 9.28. System Administration Functions") Development Versions: [devel](https://www.postgresql.org/docs/devel/functions-admin.html "PostgreSQL devel - 9.28. System Administration Functions") Unsupported versions: [13](https://www.postgresql.org/docs/13/functions-admin.html "PostgreSQL 13 - 9.28. System Administration Functions") / [12](https://www.postgresql.org/docs/12/functions-admin.html "PostgreSQL 12 - 9.28. System Administration Functions") / [11](https://www.postgresql.org/docs/11/functions-admin.html "PostgreSQL 11 - 9.28. System Administration Functions") / [10](https://www.postgresql.org/docs/10/functions-admin.html "PostgreSQL 10 - 9.28. System Administration Functions") / [9.6](https://www.postgresql.org/docs/9.6/functions-admin.html "PostgreSQL 9.6 - 9.28. System Administration Functions") / [9.5](https://www.postgresql.org/docs/9.5/functions-admin.html "PostgreSQL 9.5 - 9.28. System Administration Functions") / [9.4](https://www.postgresql.org/docs/9.4/functions-admin.html "PostgreSQL 9.4 - 9.28. System Administration Functions") / [9.3](https://www.postgresql.org/docs/9.3/functions-admin.html "PostgreSQL 9.3 - 9.28. System Administration Functions") / [9.2](https://www.postgresql.org/docs/9.2/functions-admin.html "PostgreSQL 9.2 - 9.28. System Administration Functions") / [9.1](https://www.postgresql.org/docs/9.1/functions-admin.html "PostgreSQL 9.1 - 9.28. System Administration Functions") / [9.0](https://www.postgresql.org/docs/9.0/functions-admin.html "PostgreSQL 9.0 - 9.28. System Administration Functions") / [8.4](https://www.postgresql.org/docs/8.4/functions-admin.html "PostgreSQL 8.4 - 9.28. System Administration Functions") / [8.3](https://www.postgresql.org/docs/8.3/functions-admin.html "PostgreSQL 8.3 - 9.28. System Administration Functions") / [8.2](https://www.postgresql.org/docs/8.2/functions-admin.html "PostgreSQL 8.2 - 9.28. System Administration Functions") / [8.1](https://www.postgresql.org/docs/8.1/functions-admin.html "PostgreSQL 8.1 - 9.28. System Administration Functions") / [8.0](https://www.postgresql.org/docs/8.0/functions-admin.html "PostgreSQL 8.0 - 9.28. System Administration Functions") | 9.28. System Administration Functions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/functions-info.html "9.27. System Information Functions and Operators") | [Up](https://www.postgresql.org/docs/current/functions.html "Chapter 9. Functions and Operators") | Chapter 9. Functions and Operators | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/functions-trigger.html "9.29. Trigger Functions") | * * * 9.28. System Administration Functions [#](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN) ------------------------------------------------------------------------------------------------------------------------ [9.28.1. Configuration Settings Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SET) [9.28.2. Server Signaling Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL) [9.28.3. Backup Control Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-BACKUP) [9.28.4. Recovery Control Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-RECOVERY-CONTROL) [9.28.5. Snapshot Synchronization Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-SNAPSHOT-SYNCHRONIZATION) [9.28.6. Replication Management Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-REPLICATION) [9.28.7. Database Object Management Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-DBOBJECT) [9.28.8. Index Maintenance Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-INDEX) [9.28.9. Generic File Access Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-GENFILE) [9.28.10. Advisory Lock Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS) The functions described in this section are used to control and monitor a PostgreSQL installation. ### 9.28.1. Configuration Settings Functions [#](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SET) [Table 9.95](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SET-TABLE "Table 9.95. Configuration Settings Functions") shows the functions available to query and alter run-time configuration parameters. **Table 9.95. Configuration Settings Functions** | Function

Description

Example(s) | | --- | | `current_setting` ( _`setting_name`_ `text` \[, _`missing_ok`_ `boolean` \] ) → `text`

Returns the current value of the setting _`setting_name`_. If there is no such setting, `current_setting` throws an error unless _`missing_ok`_ is supplied and is `true` (in which case NULL is returned). This function corresponds to the SQL command [SHOW](https://www.postgresql.org/docs/current/sql-show.html "SHOW")
.

`current_setting('datestyle')` → `ISO, MDY` | | `set_config` ( _`setting_name`_ `text`, _`new_value`_ `text`, _`is_local`_ `boolean` ) → `text`

Sets the parameter _`setting_name`_ to _`new_value`_, and returns that value. If _`is_local`_ is `true`, the new value will only apply during the current transaction. If you want the new value to apply for the rest of the current session, use `false` instead. This function corresponds to the SQL command [SET](https://www.postgresql.org/docs/current/sql-set.html "SET")
.

`set_config` accepts the NULL value for _`new_value`_, but as settings cannot be null, it is interpreted as a request to reset the setting to its default value.

`set_config('log_statement_stats', 'off', false)` → `off` | ### 9.28.2. Server Signaling Functions [#](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL) The functions shown in [Table 9.96](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL-TABLE "Table 9.96. Server Signaling Functions") send control signals to other server processes. Use of these functions is restricted to superusers by default but access may be granted to others using `GRANT`, with noted exceptions. Each of these functions returns `true` if the signal was successfully sent and `false` if sending the signal failed. **Table 9.96. Server Signaling Functions** | Function

Description | | --- | | `pg_cancel_backend` ( _`pid`_ `integer` ) → `boolean`

Cancels the current query of the session whose backend process has the specified process ID. This is also allowed if the calling role is a member of the role whose backend is being canceled or the calling role has privileges of `pg_signal_backend`, however only superusers can cancel superuser backends. As an exception, roles with privileges of `pg_signal_autovacuum_worker` are permitted to cancel autovacuum worker processes, which are otherwise considered superuser backends. | | `pg_log_backend_memory_contexts` ( _`pid`_ `integer` ) → `boolean`

Requests to log the memory contexts of the backend with the specified process ID. This function can send the request to backends and auxiliary processes except logger. These memory contexts will be logged at `LOG` message level. They will appear in the server log based on the log configuration set (see [Section 19.8](https://www.postgresql.org/docs/current/runtime-config-logging.html "19.8. Error Reporting and Logging")
for more information), but will not be sent to the client regardless of [client\_min\_messages](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-CLIENT-MIN-MESSAGES)
. | | `pg_reload_conf` () → `boolean`

Causes all processes of the PostgreSQL server to reload their configuration files. (This is initiated by sending a SIGHUP signal to the postmaster process, which in turn sends SIGHUP to each of its children.) You can use the [`pg_file_settings`](https://www.postgresql.org/docs/current/view-pg-file-settings.html "53.8. pg_file_settings")
, [`pg_hba_file_rules`](https://www.postgresql.org/docs/current/view-pg-hba-file-rules.html "53.10. pg_hba_file_rules")
and [`pg_ident_file_mappings`](https://www.postgresql.org/docs/current/view-pg-ident-file-mappings.html "53.11. pg_ident_file_mappings")
views to check the configuration files for possible errors, before reloading. | | `pg_rotate_logfile` () → `boolean`

Signals the log-file manager to switch to a new output file immediately. This works only when the built-in log collector is running, since otherwise there is no log-file manager subprocess. | | `pg_terminate_backend` ( _`pid`_ `integer`, _`timeout`_ `bigint` `DEFAULT` `0` ) → `boolean`

Terminates the session whose backend process has the specified process ID. This is also allowed if the calling role is a member of the role whose backend is being terminated or the calling role has privileges of `pg_signal_backend`, however only superusers can terminate superuser backends. As an exception, roles with privileges of `pg_signal_autovacuum_worker` are permitted to terminate autovacuum worker processes, which are otherwise considered superuser backends.

If _`timeout`_ is not specified or zero, this function returns `true` whether the process actually terminates or not, indicating only that the sending of the signal was successful. If the _`timeout`_ is specified (in milliseconds) and greater than zero, the function waits until the process is actually terminated or until the given time has passed. If the process is terminated, the function returns `true`. On timeout, a warning is emitted and `false` is returned. | `pg_cancel_backend` and `pg_terminate_backend` send signals (SIGINT or SIGTERM respectively) to backend processes identified by process ID. The process ID of an active backend can be found from the `pid` column of the `pg_stat_activity` view, or by listing the `postgres` processes on the server (using ps on Unix or the Task Manager on Windows). The role of an active backend can be found from the `usename` column of the `pg_stat_activity` view. `pg_log_backend_memory_contexts` can be used to log the memory contexts of a backend process. For example: postgres=# SELECT pg\_log\_backend\_memory\_contexts(pg\_backend\_pid()); pg\_log\_backend\_memory\_contexts -------------------------------- t (1 row) One message for each memory context will be logged. For example: LOG: logging memory contexts of PID 10377 STATEMENT: SELECT pg\_log\_backend\_memory\_contexts(pg\_backend\_pid()); LOG: level: 1; TopMemoryContext: 80800 total in 6 blocks; 14432 free (5 chunks); 66368 used LOG: level: 2; pgstat TabStatusArray lookup hash table: 8192 total in 1 blocks; 1408 free (0 chunks); 6784 used LOG: level: 2; TopTransactionContext: 8192 total in 1 blocks; 7720 free (1 chunks); 472 used LOG: level: 2; RowDescriptionContext: 8192 total in 1 blocks; 6880 free (0 chunks); 1312 used LOG: level: 2; MessageContext: 16384 total in 2 blocks; 5152 free (0 chunks); 11232 used LOG: level: 2; Operator class cache: 8192 total in 1 blocks; 512 free (0 chunks); 7680 used LOG: level: 2; smgr relation table: 16384 total in 2 blocks; 4544 free (3 chunks); 11840 used LOG: level: 2; TransactionAbortContext: 32768 total in 1 blocks; 32504 free (0 chunks); 264 used ... LOG: level: 2; ErrorContext: 8192 total in 1 blocks; 7928 free (3 chunks); 264 used LOG: Grand total: 1651920 bytes in 201 blocks; 622360 free (88 chunks); 1029560 used If there are more than 100 child contexts under the same parent, the first 100 child contexts are logged, along with a summary of the remaining contexts. Note that frequent calls to this function could incur significant overhead, because it may generate a large number of log messages. ### 9.28.3. Backup Control Functions [#](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-BACKUP) The functions shown in [Table 9.97](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-BACKUP-TABLE "Table 9.97. Backup Control Functions") assist in making on-line backups. These functions cannot be executed during recovery (except `pg_backup_start`, `pg_backup_stop`, and `pg_wal_lsn_diff`). For details about proper usage of these functions, see [Section 25.3](https://www.postgresql.org/docs/current/continuous-archiving.html "25.3. Continuous Archiving and Point-in-Time Recovery (PITR)") . **Table 9.97. Backup Control Functions** | Function

Description | | --- | | `pg_create_restore_point` ( _`name`_ `text` ) → `pg_lsn`

Creates a named marker record in the write-ahead log that can later be used as a recovery target, and returns the corresponding write-ahead log location. The given name can then be used with [recovery\_target\_name](https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-RECOVERY-TARGET-NAME)
to specify the point up to which recovery will proceed. Avoid creating multiple restore points with the same name, since recovery will stop at the first one whose name matches the recovery target.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_current_wal_flush_lsn` () → `pg_lsn`

Returns the current write-ahead log flush location (see notes below). | | `pg_current_wal_insert_lsn` () → `pg_lsn`

Returns the current write-ahead log insert location (see notes below). | | `pg_current_wal_lsn` () → `pg_lsn`

Returns the current write-ahead log write location (see notes below). | | `pg_backup_start` ( _`label`_ `text` \[, _`fast`_ `boolean` \] ) → `pg_lsn`

Prepares the server to begin an on-line backup. The only required parameter is an arbitrary user-defined label for the backup. (Typically this would be the name under which the backup dump file will be stored.) If the optional second parameter is given as `true`, it specifies executing `pg_backup_start` as quickly as possible. This forces an immediate checkpoint which will cause a spike in I/O operations, slowing any concurrently executing queries.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_backup_stop` ( \[_`wait_for_archive`_ `boolean` \] ) → `record` ( _`lsn`_ `pg_lsn`, _`labelfile`_ `text`, _`spcmapfile`_ `text` )

Finishes performing an on-line backup. The desired contents of the backup label file and the tablespace map file are returned as part of the result of the function and must be written to files in the backup area. These files must not be written to the live data directory (doing so will cause PostgreSQL to fail to restart in the event of a crash).

There is an optional parameter of type `boolean`. If false, the function will return immediately after the backup is completed, without waiting for WAL to be archived. This behavior is only useful with backup software that independently monitors WAL archiving. Otherwise, WAL required to make the backup consistent might be missing and make the backup useless. By default or when this parameter is true, `pg_backup_stop` will wait for WAL to be archived when archiving is enabled. (On a standby, this means that it will wait only when `archive_mode` = `always`. If write activity on the primary is low, it may be useful to run `pg_switch_wal` on the primary in order to trigger an immediate segment switch.)

When executed on a primary, this function also creates a backup history file in the write-ahead log archive area. The history file includes the label given to `pg_backup_start`, the starting and ending write-ahead log locations for the backup, and the starting and ending times of the backup. After recording the ending location, the current write-ahead log insertion point is automatically advanced to the next write-ahead log file, so that the ending write-ahead log file can be archived immediately to complete the backup.

The result of the function is a single record. The _`lsn`_ column holds the backup's ending write-ahead log location (which again can be ignored). The second column returns the contents of the backup label file, and the third column returns the contents of the tablespace map file. These must be stored as part of the backup and are required as part of the restore process.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_switch_wal` () → `pg_lsn`

Forces the server to switch to a new write-ahead log file, which allows the current file to be archived (assuming you are using continuous archiving). The result is the ending write-ahead log location plus 1 within the just-completed write-ahead log file. If there has been no write-ahead log activity since the last write-ahead log switch, `pg_switch_wal` does nothing and returns the start location of the write-ahead log file currently in use.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_walfile_name` ( _`lsn`_ `pg_lsn` ) → `text`

Converts a write-ahead log location to the name of the WAL file holding that location. | | `pg_walfile_name_offset` ( _`lsn`_ `pg_lsn` ) → `record` ( _`file_name`_ `text`, _`file_offset`_ `integer` )

Converts a write-ahead log location to a WAL file name and byte offset within that file. | | `pg_split_walfile_name` ( _`file_name`_ `text` ) → `record` ( _`segment_number`_ `numeric`, _`timeline_id`_ `bigint` )

Extracts the sequence number and timeline ID from a WAL file name. | | `pg_wal_lsn_diff` ( _`lsn1`_ `pg_lsn`, _`lsn2`_ `pg_lsn` ) → `numeric`

Calculates the difference in bytes (_`lsn1`_ - _`lsn2`_) between two write-ahead log locations. This can be used with `pg_stat_replication` or some of the functions shown in [Table 9.97](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-BACKUP-TABLE "Table 9.97. Backup Control Functions")
to get the replication lag. | `pg_current_wal_lsn` displays the current write-ahead log write location in the same format used by the above functions. Similarly, `pg_current_wal_insert_lsn` displays the current write-ahead log insertion location and `pg_current_wal_flush_lsn` displays the current write-ahead log flush location. The insertion location is the “logical” end of the write-ahead log at any instant, while the write location is the end of what has actually been written out from the server's internal buffers, and the flush location is the last location known to be written to durable storage. The write location is the end of what can be examined from outside the server, and is usually what you want if you are interested in archiving partially-complete write-ahead log files. The insertion and flush locations are made available primarily for server debugging purposes. These are all read-only operations and do not require superuser permissions. You can use `pg_walfile_name_offset` to extract the corresponding write-ahead log file name and byte offset from a `pg_lsn` value. For example: postgres=# SELECT \* FROM pg\_walfile\_name\_offset((pg\_backup\_stop()).lsn); file\_name | file\_offset --------------------------+------------- 00000001000000000000000D | 4039624 (1 row) Similarly, `pg_walfile_name` extracts just the write-ahead log file name. `pg_split_walfile_name` is useful to compute a LSN from a file offset and WAL file name, for example: postgres=# \\set file\_name '000000010000000100C000AB' postgres=# \\set offset 256 postgres=# SELECT '0/0'::pg\_lsn + pd.segment\_number \* ps.setting::int + :offset AS lsn FROM pg\_split\_walfile\_name(:'file\_name') pd, pg\_show\_all\_settings() ps WHERE ps.name = 'wal\_segment\_size'; lsn --------------- C001/AB000100 (1 row) ### 9.28.4. Recovery Control Functions [#](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-RECOVERY-CONTROL) The functions shown in [Table 9.98](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-RECOVERY-INFO-TABLE "Table 9.98. Recovery Information Functions") provide information about the current status of a standby server. These functions may be executed both during recovery and in normal running. **Table 9.98. Recovery Information Functions** | Function

Description | | --- | | `pg_is_in_recovery` () → `boolean`

Returns true if recovery is still in progress. | | `pg_last_wal_receive_lsn` () → `pg_lsn`

Returns the last write-ahead log location that has been received and synced to disk by streaming replication. While streaming replication is in progress this will increase monotonically. If recovery has completed then this will remain static at the location of the last WAL record received and synced to disk during recovery. If streaming replication is disabled, or if it has not yet started, the function returns `NULL`. | | `pg_last_wal_replay_lsn` () → `pg_lsn`

Returns the last write-ahead log location that has been replayed during recovery. If recovery is still in progress this will increase monotonically. If recovery has completed then this will remain static at the location of the last WAL record applied during recovery. When the server has been started normally without recovery, the function returns `NULL`. | | `pg_last_xact_replay_timestamp` () → `timestamp with time zone`

Returns the time stamp of the last transaction replayed during recovery. This is the time at which the commit or abort WAL record for that transaction was generated on the primary. If no transactions have been replayed during recovery, the function returns `NULL`. Otherwise, if recovery is still in progress this will increase monotonically. If recovery has completed then this will remain static at the time of the last transaction applied during recovery. When the server has been started normally without recovery, the function returns `NULL`. | | `pg_get_wal_resource_managers` () → `setof record` ( _`rm_id`_ `integer`, _`rm_name`_ `text`, _`rm_builtin`_ `boolean` )

Returns the currently-loaded WAL resource managers in the system. The column _`rm_builtin`_ indicates whether it's a built-in resource manager, or a custom resource manager loaded by an extension. | The functions shown in [Table 9.99](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-RECOVERY-CONTROL-TABLE "Table 9.99. Recovery Control Functions") control the progress of recovery. These functions may be executed only during recovery. **Table 9.99. Recovery Control Functions** | Function

Description | | --- | | `pg_is_wal_replay_paused` () → `boolean`

Returns true if recovery pause is requested. | | `pg_get_wal_replay_pause_state` () → `text`

Returns recovery pause state. The return values are `not paused` if pause is not requested, `pause requested` if pause is requested but recovery is not yet paused, and `paused` if the recovery is actually paused. | | `pg_promote` ( _`wait`_ `boolean` `DEFAULT` `true`, _`wait_seconds`_ `integer` `DEFAULT` `60` ) → `boolean`

Promotes a standby server to primary status. With _`wait`_ set to `true` (the default), the function waits until promotion is completed or _`wait_seconds`_ seconds have passed, and returns `true` if promotion is successful and `false` otherwise. If _`wait`_ is set to `false`, the function returns `true` immediately after sending a `SIGUSR1` signal to the postmaster to trigger promotion.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_wal_replay_pause` () → `void`

Request to pause recovery. A request doesn't mean that recovery stops right away. If you want a guarantee that recovery is actually paused, you need to check for the recovery pause state returned by `pg_get_wal_replay_pause_state()`. Note that `pg_is_wal_replay_paused()` returns whether a request is made. While recovery is paused, no further database changes are applied. If hot standby is active, all new queries will see the same consistent snapshot of the database, and no further query conflicts will be generated until recovery is resumed.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_wal_replay_resume` () → `void`

Restarts recovery if it was paused.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | `pg_wal_replay_pause` and `pg_wal_replay_resume` cannot be executed while a promotion is ongoing. If a promotion is triggered while recovery is paused, the paused state ends and promotion continues. If streaming replication is disabled, the paused state may continue indefinitely without a problem. If streaming replication is in progress then WAL records will continue to be received, which will eventually fill available disk space, depending upon the duration of the pause, the rate of WAL generation and available disk space. ### 9.28.5. Snapshot Synchronization Functions [#](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-SNAPSHOT-SYNCHRONIZATION) PostgreSQL allows database sessions to synchronize their snapshots. A _snapshot_ determines which data is visible to the transaction that is using the snapshot. Synchronized snapshots are necessary when two or more sessions need to see identical content in the database. If two sessions just start their transactions independently, there is always a possibility that some third transaction commits between the executions of the two `START TRANSACTION` commands, so that one session sees the effects of that transaction and the other does not. To solve this problem, PostgreSQL allows a transaction to _export_ the snapshot it is using. As long as the exporting transaction remains open, other transactions can _import_ its snapshot, and thereby be guaranteed that they see exactly the same view of the database that the first transaction sees. But note that any database changes made by any one of these transactions remain invisible to the other transactions, as is usual for changes made by uncommitted transactions. So the transactions are synchronized with respect to pre-existing data, but act normally for changes they make themselves. Snapshots are exported with the `pg_export_snapshot` function, shown in [Table 9.100](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-SNAPSHOT-SYNCHRONIZATION-TABLE "Table 9.100. Snapshot Synchronization Functions") , and imported with the [SET TRANSACTION](https://www.postgresql.org/docs/current/sql-set-transaction.html "SET TRANSACTION") command. **Table 9.100. Snapshot Synchronization Functions** | Function

Description | | --- | | `pg_export_snapshot` () → `text`

Saves the transaction's current snapshot and returns a `text` string identifying the snapshot. This string must be passed (outside the database) to clients that want to import the snapshot. The snapshot is available for import only until the end of the transaction that exported it.

A transaction can export more than one snapshot, if needed. Note that doing so is only useful in `READ COMMITTED` transactions, since in `REPEATABLE READ` and higher isolation levels, transactions use the same snapshot throughout their lifetime. Once a transaction has exported any snapshots, it cannot be prepared with [PREPARE TRANSACTION](https://www.postgresql.org/docs/current/sql-prepare-transaction.html "PREPARE TRANSACTION")
. | | `pg_log_standby_snapshot` () → `pg_lsn`

Take a snapshot of running transactions and write it to WAL, without having to wait for bgwriter or checkpointer to log one. This is useful for logical decoding on standby, as logical slot creation has to wait until such a record is replayed on the standby. | ### 9.28.6. Replication Management Functions [#](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-REPLICATION) The functions shown in [Table 9.101](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-REPLICATION-TABLE "Table 9.101. Replication Management Functions") are for controlling and interacting with replication features. See [Section 26.2.5](https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION "26.2.5. Streaming Replication") , [Section 26.2.6](https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION-SLOTS "26.2.6. Replication Slots") , and [Chapter 48](https://www.postgresql.org/docs/current/replication-origins.html "Chapter 48. Replication Progress Tracking") for information about the underlying features. Use of functions for replication origin is only allowed to the superuser by default, but may be allowed to other users by using the `GRANT` command. Use of functions for replication slots is restricted to superusers and users having `REPLICATION` privilege. Many of these functions have equivalent commands in the replication protocol; see [Section 54.4](https://www.postgresql.org/docs/current/protocol-replication.html "54.4. Streaming Replication Protocol") . The functions described in [Section 9.28.3](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-BACKUP "9.28.3. Backup Control Functions") , [Section 9.28.4](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-RECOVERY-CONTROL "9.28.4. Recovery Control Functions") , and [Section 9.28.5](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-SNAPSHOT-SYNCHRONIZATION "9.28.5. Snapshot Synchronization Functions") are also relevant for replication. **Table 9.101. Replication Management Functions** | Function

Description | | --- | | `pg_create_physical_replication_slot` ( _`slot_name`_ `name` \[, _`immediately_reserve`_ `boolean`, _`temporary`_ `boolean` \] ) → `record` ( _`slot_name`_ `name`, _`lsn`_ `pg_lsn` )

Creates a new physical replication slot named _`slot_name`_. The optional second parameter, when `true`, specifies that the LSN for this replication slot be reserved immediately; otherwise the LSN is reserved on first connection from a streaming replication client. Streaming changes from a physical slot is only possible with the streaming-replication protocol — see [Section 54.4](https://www.postgresql.org/docs/current/protocol-replication.html "54.4. Streaming Replication Protocol")
. The optional third parameter, _`temporary`_, when set to true, specifies that the slot should not be permanently stored to disk and is only meant for use by the current session. Temporary slots are also released upon any error. This function corresponds to the replication protocol command `CREATE_REPLICATION_SLOT ... PHYSICAL`. | | `pg_drop_replication_slot` ( _`slot_name`_ `name` ) → `void`

Drops the physical or logical replication slot named _`slot_name`_. Same as replication protocol command `DROP_REPLICATION_SLOT`. | | `pg_create_logical_replication_slot` ( _`slot_name`_ `name`, _`plugin`_ `name` \[, _`temporary`_ `boolean`, _`twophase`_ `boolean`, _`failover`_ `boolean` \] ) → `record` ( _`slot_name`_ `name`, _`lsn`_ `pg_lsn` )

Creates a new logical (decoding) replication slot named _`slot_name`_ using the output plugin _`plugin`_. The optional third parameter, _`temporary`_, when set to true, specifies that the slot should not be permanently stored to disk and is only meant for use by the current session. Temporary slots are also released upon any error. The optional fourth parameter, _`twophase`_, when set to true, specifies that the decoding of prepared transactions is enabled for this slot. The optional fifth parameter, _`failover`_, when set to true, specifies that this slot is enabled to be synced to the standbys so that logical replication can be resumed after failover. A call to this function has the same effect as the replication protocol command `CREATE_REPLICATION_SLOT ... LOGICAL`. | | `pg_copy_physical_replication_slot` ( _`src_slot_name`_ `name`, _`dst_slot_name`_ `name` \[, _`temporary`_ `boolean` \] ) → `record` ( _`slot_name`_ `name`, _`lsn`_ `pg_lsn` )

Copies an existing physical replication slot named _`src_slot_name`_ to a physical replication slot named _`dst_slot_name`_. The copied physical slot starts to reserve WAL from the same LSN as the source slot. _`temporary`_ is optional. If _`temporary`_ is omitted, the same value as the source slot is used. Copy of an invalidated slot is not allowed. | | `pg_copy_logical_replication_slot` ( _`src_slot_name`_ `name`, _`dst_slot_name`_ `name` \[, _`temporary`_ `boolean` \[, _`plugin`_ `name` \]\] ) → `record` ( _`slot_name`_ `name`, _`lsn`_ `pg_lsn` )

Copies an existing logical replication slot named _`src_slot_name`_ to a logical replication slot named _`dst_slot_name`_, optionally changing the output plugin and persistence. The copied logical slot starts from the same LSN as the source logical slot. Both _`temporary`_ and _`plugin`_ are optional; if they are omitted, the values of the source slot are used. The `failover` option of the source logical slot is not copied and is set to `false` by default. This is to avoid the risk of being unable to continue logical replication after failover to standby where the slot is being synchronized. Copy of an invalidated slot is not allowed. | | `pg_logical_slot_get_changes` ( _`slot_name`_ `name`, _`upto_lsn`_ `pg_lsn`, _`upto_nchanges`_ `integer`, `VARIADIC` _`options`_ `text[]` ) → `setof record` ( _`lsn`_ `pg_lsn`, _`xid`_ `xid`, _`data`_ `text` )

Returns changes in the slot _`slot_name`_, starting from the point from which changes have been consumed last. If _`upto_lsn`_ and _`upto_nchanges`_ are NULL, logical decoding will continue until end of WAL. If _`upto_lsn`_ is non-NULL, decoding will include only those transactions which commit prior to the specified LSN. If _`upto_nchanges`_ is non-NULL, decoding will stop when the number of rows produced by decoding exceeds the specified value. Note, however, that the actual number of rows returned may be larger, since this limit is only checked after adding the rows produced when decoding each new transaction commit. If the specified slot is a logical failover slot then the function will not return until all physical slots specified in [`synchronized_standby_slots`](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-SYNCHRONIZED-STANDBY-SLOTS)
have confirmed WAL receipt. | | `pg_logical_slot_peek_changes` ( _`slot_name`_ `name`, _`upto_lsn`_ `pg_lsn`, _`upto_nchanges`_ `integer`, `VARIADIC` _`options`_ `text[]` ) → `setof record` ( _`lsn`_ `pg_lsn`, _`xid`_ `xid`, _`data`_ `text` )

Behaves just like the `pg_logical_slot_get_changes()` function, except that changes are not consumed; that is, they will be returned again on future calls. | | `pg_logical_slot_get_binary_changes` ( _`slot_name`_ `name`, _`upto_lsn`_ `pg_lsn`, _`upto_nchanges`_ `integer`, `VARIADIC` _`options`_ `text[]` ) → `setof record` ( _`lsn`_ `pg_lsn`, _`xid`_ `xid`, _`data`_ `bytea` )

Behaves just like the `pg_logical_slot_get_changes()` function, except that changes are returned as `bytea`. | | `pg_logical_slot_peek_binary_changes` ( _`slot_name`_ `name`, _`upto_lsn`_ `pg_lsn`, _`upto_nchanges`_ `integer`, `VARIADIC` _`options`_ `text[]` ) → `setof record` ( _`lsn`_ `pg_lsn`, _`xid`_ `xid`, _`data`_ `bytea` )

Behaves just like the `pg_logical_slot_peek_changes()` function, except that changes are returned as `bytea`. | | `pg_replication_slot_advance` ( _`slot_name`_ `name`, _`upto_lsn`_ `pg_lsn` ) → `record` ( _`slot_name`_ `name`, _`end_lsn`_ `pg_lsn` )

Advances the current confirmed position of a replication slot named _`slot_name`_. The slot will not be moved backwards, and it will not be moved beyond the current insert location. Returns the name of the slot and the actual position that it was advanced to. The updated slot position information is written out at the next checkpoint if any advancing is done. So in the event of a crash, the slot may return to an earlier position. If the specified slot is a logical failover slot then the function will not return until all physical slots specified in [`synchronized_standby_slots`](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-SYNCHRONIZED-STANDBY-SLOTS)
have confirmed WAL receipt. | | `pg_replication_origin_create` ( _`node_name`_ `text` ) → `oid`

Creates a replication origin with the given external name, and returns the internal ID assigned to it. The name must be no longer than 512 bytes. | | `pg_replication_origin_drop` ( _`node_name`_ `text` ) → `void`

Deletes a previously-created replication origin, including any associated replay progress. | | `pg_replication_origin_oid` ( _`node_name`_ `text` ) → `oid`

Looks up a replication origin by name and returns the internal ID. If no such replication origin is found, `NULL` is returned. | | `pg_replication_origin_session_setup` ( _`node_name`_ `text` ) → `void`

Marks the current session as replaying from the given origin, allowing replay progress to be tracked. Can only be used if no origin is currently selected. Use `pg_replication_origin_session_reset` to undo. | | `pg_replication_origin_session_reset` () → `void`

Cancels the effects of `pg_replication_origin_session_setup()`. | | `pg_replication_origin_session_is_setup` () → `boolean`

Returns true if a replication origin has been selected in the current session. | | `pg_replication_origin_session_progress` ( _`flush`_ `boolean` ) → `pg_lsn`

Returns the replay location for the replication origin selected in the current session. The parameter _`flush`_ determines whether the corresponding local transaction will be guaranteed to have been flushed to disk or not. | | `pg_replication_origin_xact_setup` ( _`origin_lsn`_ `pg_lsn`, _`origin_timestamp`_ `timestamp with time zone` ) → `void`

Marks the current transaction as replaying a transaction that has committed at the given LSN and timestamp. Can only be called when a replication origin has been selected using `pg_replication_origin_session_setup`. | | `pg_replication_origin_xact_reset` () → `void`

Cancels the effects of `pg_replication_origin_xact_setup()`. | | `pg_replication_origin_advance` ( _`node_name`_ `text`, _`lsn`_ `pg_lsn` ) → `void`

Sets replication progress for the given node to the given location. This is primarily useful for setting up the initial location, or setting a new location after configuration changes and similar. Be aware that careless use of this function can lead to inconsistently replicated data. | | `pg_replication_origin_progress` ( _`node_name`_ `text`, _`flush`_ `boolean` ) → `pg_lsn`

Returns the replay location for the given replication origin. The parameter _`flush`_ determines whether the corresponding local transaction will be guaranteed to have been flushed to disk or not. | | `pg_logical_emit_message` ( _`transactional`_ `boolean`, _`prefix`_ `text`, _`content`_ `text` \[, _`flush`_ `boolean` `DEFAULT` `false`\] ) → `pg_lsn`

`pg_logical_emit_message` ( _`transactional`_ `boolean`, _`prefix`_ `text`, _`content`_ `bytea` \[, _`flush`_ `boolean` `DEFAULT` `false`\] ) → `pg_lsn`

Emits a logical decoding message. This can be used to pass generic messages to logical decoding plugins through WAL. The _`transactional`_ parameter specifies if the message should be part of the current transaction, or if it should be written immediately and decoded as soon as the logical decoder reads the record. The _`prefix`_ parameter is a textual prefix that can be used by logical decoding plugins to easily recognize messages that are interesting for them. The _`content`_ parameter is the content of the message, given either in text or binary form. The _`flush`_ parameter (default set to `false`) controls if the message is immediately flushed to WAL or not. _`flush`_ has no effect with _`transactional`_, as the message's WAL record is flushed along with its transaction. | | `pg_sync_replication_slots` () → `void`

Synchronize the logical failover replication slots from the primary server to the standby server. This function can only be executed on the standby server. Temporary synced slots, if any, cannot be used for logical decoding and must be dropped after promotion. See [Section 47.2.3](https://www.postgresql.org/docs/current/logicaldecoding-explanation.html#LOGICALDECODING-REPLICATION-SLOTS-SYNCHRONIZATION "47.2.3. Replication Slot Synchronization")
for details. Note that this function is primarily intended for testing and debugging purposes and should be used with caution. Additionally, this function cannot be executed if [`sync_replication_slots`](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-SYNC-REPLICATION-SLOTS)
is enabled and the slotsync worker is already running to perform the synchronization of slots.

### Caution

If, after executing the function, [`hot_standby_feedback`](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-HOT-STANDBY-FEEDBACK)
is disabled on the standby or the physical slot configured in [`primary_slot_name`](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-PRIMARY-SLOT-NAME)
is removed, then it is possible that the necessary rows of the synchronized slot will be removed by the VACUUM process on the primary server, resulting in the synchronized slot becoming invalidated. | ### 9.28.7. Database Object Management Functions [#](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-DBOBJECT) The functions shown in [Table 9.102](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-DBSIZE "Table 9.102. Database Object Size Functions") calculate the disk space usage of database objects, or assist in presentation or understanding of usage results. `bigint` results are measured in bytes. If an OID that does not represent an existing object is passed to one of these functions, `NULL` is returned. **Table 9.102. Database Object Size Functions** | Function

Description | | --- | | `pg_column_size` ( `"any"` ) → `integer`

Shows the number of bytes used to store any individual data value. If applied directly to a table column value, this reflects any compression that was done. | | `pg_column_compression` ( `"any"` ) → `text`

Shows the compression algorithm that was used to compress an individual variable-length value. Returns `NULL` if the value is not compressed. | | `pg_column_toast_chunk_id` ( `"any"` ) → `oid`

Shows the `chunk_id` of an on-disk TOASTed value. Returns `NULL` if the value is un-TOASTed or not on-disk. See [Section 66.2](https://www.postgresql.org/docs/current/storage-toast.html "66.2. TOAST")
for more information about TOAST. | | `pg_database_size` ( `name` ) → `bigint`

`pg_database_size` ( `oid` ) → `bigint`

Computes the total disk space used by the database with the specified name or OID. To use this function, you must have `CONNECT` privilege on the specified database (which is granted by default) or have privileges of the `pg_read_all_stats` role. | | `pg_indexes_size` ( `regclass` ) → `bigint`

Computes the total disk space used by indexes attached to the specified table. | | `pg_relation_size` ( _`relation`_ `regclass` \[, _`fork`_ `text` \] ) → `bigint`

Computes the disk space used by one “fork” of the specified relation. (Note that for most purposes it is more convenient to use the higher-level functions `pg_total_relation_size` or `pg_table_size`, which sum the sizes of all forks.) With one argument, this returns the size of the main data fork of the relation. The second argument can be provided to specify which fork to examine:

* `main` returns the size of the main data fork of the relation.

* `fsm` returns the size of the Free Space Map (see [Section 66.3](https://www.postgresql.org/docs/current/storage-fsm.html "66.3. Free Space Map")
) associated with the relation.

* `vm` returns the size of the Visibility Map (see [Section 66.4](https://www.postgresql.org/docs/current/storage-vm.html "66.4. Visibility Map")
) associated with the relation.

* `init` returns the size of the initialization fork, if any, associated with the relation. | | `pg_size_bytes` ( `text` ) → `bigint`

Converts a size in human-readable format (as returned by `pg_size_pretty`) into bytes. Valid units are `bytes`, `B`, `kB`, `MB`, `GB`, `TB`, and `PB`. | | `pg_size_pretty` ( `bigint` ) → `text`

`pg_size_pretty` ( `numeric` ) → `text`

Converts a size in bytes into a more easily human-readable format with size units (bytes, kB, MB, GB, TB, or PB as appropriate). Note that the units are powers of 2 rather than powers of 10, so 1kB is 1024 bytes, 1MB is 10242 = 1048576 bytes, and so on. | | `pg_table_size` ( `regclass` ) → `bigint`

Computes the disk space used by the specified table, excluding indexes (but including its TOAST table if any, free space map, and visibility map). | | `pg_tablespace_size` ( `name` ) → `bigint`

`pg_tablespace_size` ( `oid` ) → `bigint`

Computes the total disk space used in the tablespace with the specified name or OID. To use this function, you must have `CREATE` privilege on the specified tablespace or have privileges of the `pg_read_all_stats` role, unless it is the default tablespace for the current database. | | `pg_total_relation_size` ( `regclass` ) → `bigint`

Computes the total disk space used by the specified table, including all indexes and TOAST data. The result is equivalent to `pg_table_size` `+` `pg_indexes_size`. | The functions above that operate on tables or indexes accept a `regclass` argument, which is simply the OID of the table or index in the `pg_class` system catalog. You do not have to look up the OID by hand, however, since the `regclass` data type's input converter will do the work for you. See [Section 8.19](https://www.postgresql.org/docs/current/datatype-oid.html "8.19. Object Identifier Types") for details. The functions shown in [Table 9.103](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-DBLOCATION "Table 9.103. Database Object Location Functions") assist in identifying the specific disk files associated with database objects. **Table 9.103. Database Object Location Functions** | Function

Description | | --- | | `pg_relation_filenode` ( _`relation`_ `regclass` ) → `oid`

Returns the “filenode” number currently assigned to the specified relation. The filenode is the base component of the file name(s) used for the relation (see [Section 66.1](https://www.postgresql.org/docs/current/storage-file-layout.html "66.1. Database File Layout")
for more information). For most relations the result is the same as `pg_class`.`relfilenode`, but for certain system catalogs `relfilenode` is zero and this function must be used to get the correct value. The function returns NULL if passed a relation that does not have storage, such as a view. | | `pg_relation_filepath` ( _`relation`_ `regclass` ) → `text`

Returns the entire file path name (relative to the database cluster's data directory, `PGDATA`) of the relation. | | `pg_filenode_relation` ( _`tablespace`_ `oid`, _`filenode`_ `oid` ) → `regclass`

Returns a relation's OID given the tablespace OID and filenode it is stored under. This is essentially the inverse mapping of `pg_relation_filepath`. For a relation in the database's default tablespace, the tablespace can be specified as zero. Returns `NULL` if no relation in the current database is associated with the given values, or if dealing with a temporary relation. | [Table 9.104](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-COLLATION "Table 9.104. Collation Management Functions") lists functions used to manage collations. **Table 9.104. Collation Management Functions** | Function

Description | | --- | | `pg_collation_actual_version` ( `oid` ) → `text`

Returns the actual version of the collation object as it is currently installed in the operating system. If this is different from the value in `pg_collation`.`collversion`, then objects depending on the collation might need to be rebuilt. See also [ALTER COLLATION](https://www.postgresql.org/docs/current/sql-altercollation.html "ALTER COLLATION")
. | | `pg_database_collation_actual_version` ( `oid` ) → `text`

Returns the actual version of the database's collation as it is currently installed in the operating system. If this is different from the value in `pg_database`.`datcollversion`, then objects depending on the collation might need to be rebuilt. See also [ALTER DATABASE](https://www.postgresql.org/docs/current/sql-alterdatabase.html "ALTER DATABASE")
. | | `pg_import_system_collations` ( _`schema`_ `regnamespace` ) → `integer`

Adds collations to the system catalog `pg_collation` based on all the locales it finds in the operating system. This is what `initdb` uses; see [Section 23.2.2](https://www.postgresql.org/docs/current/collation.html#COLLATION-MANAGING "23.2.2. Managing Collations")
for more details. If additional locales are installed into the operating system later on, this function can be run again to add collations for the new locales. Locales that match existing entries in `pg_collation` will be skipped. (But collation objects based on locales that are no longer present in the operating system are not removed by this function.) The _`schema`_ parameter would typically be `pg_catalog`, but that is not a requirement; the collations could be installed into some other schema as well. The function returns the number of new collation objects it created. Use of this function is restricted to superusers. | [Table 9.105](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-STATSMOD "Table 9.105. Database Object Statistics Manipulation Functions") lists functions used to manipulate statistics. These functions cannot be executed during recovery. ### Warning Changes made by these statistics manipulation functions are likely to be overwritten by [autovacuum](https://www.postgresql.org/docs/current/routine-vacuuming.html#AUTOVACUUM "24.1.6. The Autovacuum Daemon") (or manual `VACUUM` or `ANALYZE`) and should be considered temporary. **Table 9.105. Database Object Statistics Manipulation Functions** | Function

Description | | --- | | `pg_restore_relation_stats` ( `VARIADIC` _`kwargs`_ `"any"` ) → `boolean`

Updates table-level statistics. Ordinarily, these statistics are collected automatically or updated as a part of [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html "VACUUM")
or [ANALYZE](https://www.postgresql.org/docs/current/sql-analyze.html "ANALYZE")
, so it's not necessary to call this function. However, it is useful after a restore to enable the optimizer to choose better plans if `ANALYZE` has not been run yet.

The tracked statistics may change from version to version, so arguments are passed as pairs of _`argname`_ and _`argvalue`_ in the form:

SELECT pg\_restore\_relation\_stats(
'_`arg1name`_', '_`arg1value`_'::_`arg1type`_,
'_`arg2name`_', '_`arg2value`_'::_`arg2type`_,
'_`arg3name`_', '_`arg3value`_'::_`arg3type`_);

For example, to set the `relpages` and `reltuples` values for the table `mytable`:

SELECT pg\_restore\_relation\_stats(
'schemaname', 'myschema',
'relname', 'mytable',
'relpages', 173::integer,
'reltuples', 10000::real);

The arguments `schemaname` and `relname` are required, and specify the table. Other arguments are the names and values of statistics corresponding to certain columns in [`pg_class`](https://www.postgresql.org/docs/current/catalog-pg-class.html "52.11. pg_class")
. The currently-supported relation statistics are `relpages` with a value of type `integer`, `reltuples` with a value of type `real`, `relallvisible` with a value of type `integer`, and `relallfrozen` with a value of type `integer`.

Additionally, this function accepts argument name `version` of type `integer`, which specifies the server version from which the statistics originated. This is anticipated to be helpful in porting statistics from older versions of PostgreSQL.

Minor errors are reported as a `WARNING` and ignored, and remaining statistics will still be restored. If all specified statistics are successfully restored, returns `true`, otherwise `false`.

The caller must have the `MAINTAIN` privilege on the table or be the owner of the database. | | `pg_clear_relation_stats` ( _`schemaname`_ `text`, _`relname`_ `text` ) → `void`

Clears table-level statistics for the given relation, as though the table was newly created.

The caller must have the `MAINTAIN` privilege on the table or be the owner of the database. | | `pg_restore_attribute_stats` ( `VARIADIC` _`kwargs`_ `"any"` ) → `boolean`

Creates or updates column-level statistics. Ordinarily, these statistics are collected automatically or updated as a part of [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html "VACUUM")
or [ANALYZE](https://www.postgresql.org/docs/current/sql-analyze.html "ANALYZE")
, so it's not necessary to call this function. However, it is useful after a restore to enable the optimizer to choose better plans if `ANALYZE` has not been run yet.

The tracked statistics may change from version to version, so arguments are passed as pairs of _`argname`_ and _`argvalue`_ in the form:

SELECT pg\_restore\_attribute\_stats(
'_`arg1name`_', '_`arg1value`_'::_`arg1type`_,
'_`arg2name`_', '_`arg2value`_'::_`arg2type`_,
'_`arg3name`_', '_`arg3value`_'::_`arg3type`_);

For example, to set the `avg_width` and `null_frac` values for the attribute `col1` of the table `mytable`:

SELECT pg\_restore\_attribute\_stats(
'schemaname', 'myschema',
'relname', 'mytable',
'attname', 'col1',
'inherited', false,
'avg\_width', 125::integer,
'null\_frac', 0.5::real);

The required arguments are `schemaname` and `relname` with a value of type `text` which specify the table; either `attname` with a value of type `text` or `attnum` with a value of type `smallint`, which specifies the column; and `inherited`, which specifies whether the statistics include values from child tables. Other arguments are the names and values of statistics corresponding to columns in [`pg_stats`](https://www.postgresql.org/docs/current/view-pg-stats.html "53.29. pg_stats")
.

Additionally, this function accepts argument name `version` of type `integer`, which specifies the server version from which the statistics originated. This is anticipated to be helpful in porting statistics from older versions of PostgreSQL.

Minor errors are reported as a `WARNING` and ignored, and remaining statistics will still be restored. If all specified statistics are successfully restored, returns `true`, otherwise `false`.

The caller must have the `MAINTAIN` privilege on the table or be the owner of the database. | | `pg_clear_attribute_stats` ( _`schemaname`_ `text`, _`relname`_ `text`, _`attname`_ `text`, _`inherited`_ `boolean` ) → `void`

Clears column-level statistics for the given relation and attribute, as though the table was newly created.

The caller must have the `MAINTAIN` privilege on the table or be the owner of the database. | [Table 9.106](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-INFO-PARTITION "Table 9.106. Partitioning Information Functions") lists functions that provide information about the structure of partitioned tables. **Table 9.106. Partitioning Information Functions** | Function

Description | | --- | | `pg_partition_tree` ( `regclass` ) → `setof record` ( _`relid`_ `regclass`, _`parentrelid`_ `regclass`, _`isleaf`_ `boolean`, _`level`_ `integer` )

Lists the tables or indexes in the partition tree of the given partitioned table or partitioned index, with one row for each partition. Information provided includes the OID of the partition, the OID of its immediate parent, a boolean value telling if the partition is a leaf, and an integer telling its level in the hierarchy. The level value is 0 for the input table or index, 1 for its immediate child partitions, 2 for their partitions, and so on. Returns no rows if the relation does not exist or is not a partition or partitioned table. | | `pg_partition_ancestors` ( `regclass` ) → `setof regclass`

Lists the ancestor relations of the given partition, including the relation itself. Returns no rows if the relation does not exist or is not a partition or partitioned table. | | `pg_partition_root` ( `regclass` ) → `regclass`

Returns the top-most parent of the partition tree to which the given relation belongs. Returns `NULL` if the relation does not exist or is not a partition or partitioned table. | For example, to check the total size of the data contained in a partitioned table `measurement`, one could use the following query: SELECT pg\_size\_pretty(sum(pg\_relation\_size(relid))) AS total\_size FROM pg\_partition\_tree('measurement'); ### 9.28.8. Index Maintenance Functions [#](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-INDEX) [Table 9.107](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-INDEX-TABLE "Table 9.107. Index Maintenance Functions") shows the functions available for index maintenance tasks. (Note that these maintenance tasks are normally done automatically by autovacuum; use of these functions is only required in special cases.) These functions cannot be executed during recovery. Use of these functions is restricted to superusers and the owner of the given index. **Table 9.107. Index Maintenance Functions** | Function

Description | | --- | | `brin_summarize_new_values` ( _`index`_ `regclass` ) → `integer`

Scans the specified BRIN index to find page ranges in the base table that are not currently summarized by the index; for any such range it creates a new summary index tuple by scanning those table pages. Returns the number of new page range summaries that were inserted into the index. | | `brin_summarize_range` ( _`index`_ `regclass`, _`blockNumber`_ `bigint` ) → `integer`

Summarizes the page range covering the given block, if not already summarized. This is like `brin_summarize_new_values` except that it only processes the page range that covers the given table block number. | | `brin_desummarize_range` ( _`index`_ `regclass`, _`blockNumber`_ `bigint` ) → `void`

Removes the BRIN index tuple that summarizes the page range covering the given table block, if there is one. | | `gin_clean_pending_list` ( _`index`_ `regclass` ) → `bigint`

Cleans up the “pending” list of the specified GIN index by moving entries in it, in bulk, to the main GIN data structure. Returns the number of pages removed from the pending list. If the argument is a GIN index built with the `fastupdate` option disabled, no cleanup happens and the result is zero, because the index doesn't have a pending list. See [Section 65.4.4.1](https://www.postgresql.org/docs/current/gin.html#GIN-FAST-UPDATE "65.4.4.1. GIN Fast Update Technique")
and [Section 65.4.5](https://www.postgresql.org/docs/current/gin.html#GIN-TIPS "65.4.5. GIN Tips and Tricks")
for details about the pending list and `fastupdate` option. | ### 9.28.9. Generic File Access Functions [#](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-GENFILE) The functions shown in [Table 9.108](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-GENFILE-TABLE "Table 9.108. Generic File Access Functions") provide native access to files on the machine hosting the server. Only files within the database cluster directory and the `log_directory` can be accessed, unless the user is a superuser or is granted the role `pg_read_server_files`. Use a relative path for files in the cluster directory, and a path matching the `log_directory` configuration setting for log files. Note that granting users the EXECUTE privilege on `pg_read_file()`, or related functions, allows them the ability to read any file on the server that the database server process can read; these functions bypass all in-database privilege checks. This means that, for example, a user with such access is able to read the contents of the `pg_authid` table where authentication information is stored, as well as read any table data in the database. Therefore, granting access to these functions should be carefully considered. When granting privilege on these functions, note that the table entries showing optional parameters are mostly implemented as several physical functions with different parameter lists. Privilege must be granted separately on each such function, if it is to be used. psql's `\df` command can be useful to check what the actual function signatures are. Some of these functions take an optional _`missing_ok`_ parameter, which specifies the behavior when the file or directory does not exist. If `true`, the function returns `NULL` or an empty result set, as appropriate. If `false`, an error is raised. (Failure conditions other than “file not found” are reported as errors in any case.) The default is `false`. **Table 9.108. Generic File Access Functions** | Function

Description | | --- | | `pg_ls_dir` ( _`dirname`_ `text` \[, _`missing_ok`_ `boolean`, _`include_dot_dirs`_ `boolean` \] ) → `setof text`

Returns the names of all files (and directories and other special files) in the specified directory. The _`include_dot_dirs`_ parameter indicates whether “.” and “..” are to be included in the result set; the default is to exclude them. Including them can be useful when _`missing_ok`_ is `true`, to distinguish an empty directory from a non-existent directory.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_logdir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's log directory. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and roles with privileges of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_waldir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's write-ahead log (WAL) directory. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and roles with privileges of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_logicalmapdir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's `pg_logical/mappings` directory. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_logicalsnapdir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's `pg_logical/snapshots` directory. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_replslotdir` ( _`slot_name`_ `text` ) → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's `pg_replslot/slot_name` directory, where _`slot_name`_ is the name of the replication slot provided as input of the function. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_summariesdir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's WAL summaries directory (`pg_wal/summaries`). Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_archive_statusdir` () → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the server's WAL archive status directory (`pg_wal/archive_status`). Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_ls_tmpdir` ( \[ _`tablespace`_ `oid` \] ) → `setof record` ( _`name`_ `text`, _`size`_ `bigint`, _`modification`_ `timestamp with time zone` )

Returns the name, size, and last modification time (mtime) of each ordinary file in the temporary file directory for the specified _`tablespace`_. If _`tablespace`_ is not provided, the `pg_default` tablespace is examined. Filenames beginning with a dot, directories, and other special files are excluded.

This function is restricted to superusers and members of the `pg_monitor` role by default, but other users can be granted EXECUTE to run the function. | | `pg_read_file` ( _`filename`_ `text` \[, _`offset`_ `bigint`, _`length`_ `bigint` \] \[, _`missing_ok`_ `boolean` \] ) → `text`

Returns all or part of a text file, starting at the given byte _`offset`_, returning at most _`length`_ bytes (less if the end of file is reached first). If _`offset`_ is negative, it is relative to the end of the file. If _`offset`_ and _`length`_ are omitted, the entire file is returned. The bytes read from the file are interpreted as a string in the database's encoding; an error is thrown if they are not valid in that encoding.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | | `pg_read_binary_file` ( _`filename`_ `text` \[, _`offset`_ `bigint`, _`length`_ `bigint` \] \[, _`missing_ok`_ `boolean` \] ) → `bytea`

Returns all or part of a file. This function is identical to `pg_read_file` except that it can read arbitrary binary data, returning the result as `bytea` not `text`; accordingly, no encoding checks are performed.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function.

In combination with the `convert_from` function, this function can be used to read a text file in a specified encoding and convert to the database's encoding:

SELECT convert\_from(pg\_read\_binary\_file('file\_in\_utf8.txt'), 'UTF8'); | | `pg_stat_file` ( _`filename`_ `text` \[, _`missing_ok`_ `boolean` \] ) → `record` ( _`size`_ `bigint`, _`access`_ `timestamp with time zone`, _`modification`_ `timestamp with time zone`, _`change`_ `timestamp with time zone`, _`creation`_ `timestamp with time zone`, _`isdir`_ `boolean` )

Returns a record containing the file's size, last access time stamp, last modification time stamp, last file status change time stamp (Unix platforms only), file creation time stamp (Windows only), and a flag indicating if it is a directory.

This function is restricted to superusers by default, but other users can be granted EXECUTE to run the function. | ### 9.28.10. Advisory Lock Functions [#](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS) The functions shown in [Table 9.109](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS-TABLE "Table 9.109. Advisory Lock Functions") manage advisory locks. For details about proper use of these functions, see [Section 13.3.5](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS "13.3.5. Advisory Locks") . All these functions are intended to be used to lock application-defined resources, which can be identified either by a single 64-bit key value or two 32-bit key values (note that these two key spaces do not overlap). If another session already holds a conflicting lock on the same resource identifier, the functions will either wait until the resource becomes available, or return a `false` result, as appropriate for the function. Locks can be either shared or exclusive: a shared lock does not conflict with other shared locks on the same resource, only with exclusive locks. Locks can be taken at session level (so that they are held until released or the session ends) or at transaction level (so that they are held until the current transaction ends; there is no provision for manual release). Multiple session-level lock requests stack, so that if the same resource identifier is locked three times there must then be three unlock requests to release the resource in advance of session end. **Table 9.109. Advisory Lock Functions** | Function

Description | | --- | | `pg_advisory_lock` ( _`key`_ `bigint` ) → `void`

`pg_advisory_lock` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `void`

Obtains an exclusive session-level advisory lock, waiting if necessary. | | `pg_advisory_lock_shared` ( _`key`_ `bigint` ) → `void`

`pg_advisory_lock_shared` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `void`

Obtains a shared session-level advisory lock, waiting if necessary. | | `pg_advisory_unlock` ( _`key`_ `bigint` ) → `boolean`

`pg_advisory_unlock` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Releases a previously-acquired exclusive session-level advisory lock. Returns `true` if the lock is successfully released. If the lock was not held, `false` is returned, and in addition, an SQL warning will be reported by the server. | | `pg_advisory_unlock_all` () → `void`

Releases all session-level advisory locks held by the current session. (This function is implicitly invoked at session end, even if the client disconnects ungracefully.) | | `pg_advisory_unlock_shared` ( _`key`_ `bigint` ) → `boolean`

`pg_advisory_unlock_shared` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Releases a previously-acquired shared session-level advisory lock. Returns `true` if the lock is successfully released. If the lock was not held, `false` is returned, and in addition, an SQL warning will be reported by the server. | | `pg_advisory_xact_lock` ( _`key`_ `bigint` ) → `void`

`pg_advisory_xact_lock` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `void`

Obtains an exclusive transaction-level advisory lock, waiting if necessary. | | `pg_advisory_xact_lock_shared` ( _`key`_ `bigint` ) → `void`

`pg_advisory_xact_lock_shared` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `void`

Obtains a shared transaction-level advisory lock, waiting if necessary. | | `pg_try_advisory_lock` ( _`key`_ `bigint` ) → `boolean`

`pg_try_advisory_lock` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Obtains an exclusive session-level advisory lock if available. This will either obtain the lock immediately and return `true`, or return `false` without waiting if the lock cannot be acquired immediately. | | `pg_try_advisory_lock_shared` ( _`key`_ `bigint` ) → `boolean`

`pg_try_advisory_lock_shared` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Obtains a shared session-level advisory lock if available. This will either obtain the lock immediately and return `true`, or return `false` without waiting if the lock cannot be acquired immediately. | | `pg_try_advisory_xact_lock` ( _`key`_ `bigint` ) → `boolean`

`pg_try_advisory_xact_lock` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Obtains an exclusive transaction-level advisory lock if available. This will either obtain the lock immediately and return `true`, or return `false` without waiting if the lock cannot be acquired immediately. | | `pg_try_advisory_xact_lock_shared` ( _`key`_ `bigint` ) → `boolean`

`pg_try_advisory_xact_lock_shared` ( _`key1`_ `integer`, _`key2`_ `integer` ) → `boolean`

Obtains a shared transaction-level advisory lock if available. This will either obtain the lock immediately and return `true`, or return `false` without waiting if the lock cannot be acquired immediately. | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/functions-info.html "9.27. System Information Functions and Operators") | [Up](https://www.postgresql.org/docs/current/functions.html "Chapter 9. Functions and Operators") | [Next](https://www.postgresql.org/docs/current/functions-trigger.html "9.29. Trigger Functions") | | 9.27. System Information Functions and Operators | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 9.29. Trigger Functions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/functions-admin.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 52.41. pg_publication_namespace November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-publication-namespace.html "PostgreSQL 18 - 52.41. pg_publication_namespace") ([18](https://www.postgresql.org/docs/18/catalog-pg-publication-namespace.html "PostgreSQL 18 - 52.41. pg_publication_namespace") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-publication-namespace.html "PostgreSQL 17 - 52.41. pg_publication_namespace") / [16](https://www.postgresql.org/docs/16/catalog-pg-publication-namespace.html "PostgreSQL 16 - 52.41. pg_publication_namespace") / [15](https://www.postgresql.org/docs/15/catalog-pg-publication-namespace.html "PostgreSQL 15 - 52.41. pg_publication_namespace") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-publication-namespace.html "PostgreSQL devel - 52.41. pg_publication_namespace") | 52.41. `pg_publication_namespace` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/catalog-pg-publication.html "52.40. pg_publication") | [Up](https://www.postgresql.org/docs/18/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/catalog-pg-publication-rel.html "52.42. pg_publication_rel") | * * * 52.41. `pg_publication_namespace` [#](https://www.postgresql.org/docs/18/catalog-pg-publication-namespace.html#CATALOG-PG-PUBLICATION-NAMESPACE) ------------------------------------------------------------------------------------------------------------------------------------------------- The catalog `pg_publication_namespace` contains the mapping between schemas and publications in the database. This is a many-to-many mapping. **Table 52.41. `pg_publication_namespace` Columns** | Column Type

Description | | --- | | `oid` `oid`

Row identifier | | `pnpubid` `oid` (references [`pg_publication`](https://www.postgresql.org/docs/18/catalog-pg-publication.html "52.40. pg_publication")
.`oid`)

Reference to publication | | `pnnspid` `oid` (references [`pg_namespace`](https://www.postgresql.org/docs/18/catalog-pg-namespace.html "52.32. pg_namespace")
.`oid`)

Reference to schema | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/catalog-pg-publication.html "52.40. pg_publication") | [Up](https://www.postgresql.org/docs/18/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/18/catalog-pg-publication-rel.html "52.42. pg_publication_rel") | | 52.40. `pg_publication` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 52.42. `pg_publication_rel` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/catalog-pg-publication-namespace.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 52.41. pg_publication_namespace November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-publication-namespace.html "PostgreSQL 18 - 52.41. pg_publication_namespace") ([18](https://www.postgresql.org/docs/18/catalog-pg-publication-namespace.html "PostgreSQL 18 - 52.41. pg_publication_namespace") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-publication-namespace.html "PostgreSQL 17 - 52.41. pg_publication_namespace") / [16](https://www.postgresql.org/docs/16/catalog-pg-publication-namespace.html "PostgreSQL 16 - 52.41. pg_publication_namespace") / [15](https://www.postgresql.org/docs/15/catalog-pg-publication-namespace.html "PostgreSQL 15 - 52.41. pg_publication_namespace") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-publication-namespace.html "PostgreSQL devel - 52.41. pg_publication_namespace") | 52.41. `pg_publication_namespace` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-publication.html "52.40. pg_publication") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/catalog-pg-publication-rel.html "52.42. pg_publication_rel") | * * * 52.41. `pg_publication_namespace` [#](https://www.postgresql.org/docs/current/catalog-pg-publication-namespace.html#CATALOG-PG-PUBLICATION-NAMESPACE) ------------------------------------------------------------------------------------------------------------------------------------------------------ The catalog `pg_publication_namespace` contains the mapping between schemas and publications in the database. This is a many-to-many mapping. **Table 52.41. `pg_publication_namespace` Columns** | Column Type

Description | | --- | | `oid` `oid`

Row identifier | | `pnpubid` `oid` (references [`pg_publication`](https://www.postgresql.org/docs/current/catalog-pg-publication.html "52.40. pg_publication")
.`oid`)

Reference to publication | | `pnnspid` `oid` (references [`pg_namespace`](https://www.postgresql.org/docs/current/catalog-pg-namespace.html "52.32. pg_namespace")
.`oid`)

Reference to schema | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-publication.html "52.40. pg_publication") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/current/catalog-pg-publication-rel.html "52.42. pg_publication_rel") | | 52.40. `pg_publication` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 52.42. `pg_publication_rel` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/catalog-pg-publication-namespace.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE TEXT SEARCH TEMPLATE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createtstemplate.html "PostgreSQL 18 - CREATE TEXT SEARCH TEMPLATE") ([18](https://www.postgresql.org/docs/18/sql-createtstemplate.html "PostgreSQL 18 - CREATE TEXT SEARCH TEMPLATE") ) / [17](https://www.postgresql.org/docs/17/sql-createtstemplate.html "PostgreSQL 17 - CREATE TEXT SEARCH TEMPLATE") / [16](https://www.postgresql.org/docs/16/sql-createtstemplate.html "PostgreSQL 16 - CREATE TEXT SEARCH TEMPLATE") / [15](https://www.postgresql.org/docs/15/sql-createtstemplate.html "PostgreSQL 15 - CREATE TEXT SEARCH TEMPLATE") / [14](https://www.postgresql.org/docs/14/sql-createtstemplate.html "PostgreSQL 14 - CREATE TEXT SEARCH TEMPLATE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createtstemplate.html "PostgreSQL devel - CREATE TEXT SEARCH TEMPLATE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createtstemplate.html "PostgreSQL 13 - CREATE TEXT SEARCH TEMPLATE") / [12](https://www.postgresql.org/docs/12/sql-createtstemplate.html "PostgreSQL 12 - CREATE TEXT SEARCH TEMPLATE") / [11](https://www.postgresql.org/docs/11/sql-createtstemplate.html "PostgreSQL 11 - CREATE TEXT SEARCH TEMPLATE") / [10](https://www.postgresql.org/docs/10/sql-createtstemplate.html "PostgreSQL 10 - CREATE TEXT SEARCH TEMPLATE") / [9.6](https://www.postgresql.org/docs/9.6/sql-createtstemplate.html "PostgreSQL 9.6 - CREATE TEXT SEARCH TEMPLATE") / [9.5](https://www.postgresql.org/docs/9.5/sql-createtstemplate.html "PostgreSQL 9.5 - CREATE TEXT SEARCH TEMPLATE") / [9.4](https://www.postgresql.org/docs/9.4/sql-createtstemplate.html "PostgreSQL 9.4 - CREATE TEXT SEARCH TEMPLATE") / [9.3](https://www.postgresql.org/docs/9.3/sql-createtstemplate.html "PostgreSQL 9.3 - CREATE TEXT SEARCH TEMPLATE") / [9.2](https://www.postgresql.org/docs/9.2/sql-createtstemplate.html "PostgreSQL 9.2 - CREATE TEXT SEARCH TEMPLATE") / [9.1](https://www.postgresql.org/docs/9.1/sql-createtstemplate.html "PostgreSQL 9.1 - CREATE TEXT SEARCH TEMPLATE") / [9.0](https://www.postgresql.org/docs/9.0/sql-createtstemplate.html "PostgreSQL 9.0 - CREATE TEXT SEARCH TEMPLATE") / [8.4](https://www.postgresql.org/docs/8.4/sql-createtstemplate.html "PostgreSQL 8.4 - CREATE TEXT SEARCH TEMPLATE") / [8.3](https://www.postgresql.org/docs/8.3/sql-createtstemplate.html "PostgreSQL 8.3 - CREATE TEXT SEARCH TEMPLATE") | CREATE TEXT SEARCH TEMPLATE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createtsparser.html "CREATE TEXT SEARCH PARSER") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-createtransform.html "CREATE TRANSFORM") | * * * CREATE TEXT SEARCH TEMPLATE --------------------------- CREATE TEXT SEARCH TEMPLATE — define a new text search template Synopsis -------- CREATE TEXT SEARCH TEMPLATE _`name`_ ( \[ INIT = _`init_function`_ , \] LEXIZE = _`lexize_function`_ ) Description ----------- `CREATE TEXT SEARCH TEMPLATE` creates a new text search template. Text search templates define the functions that implement text search dictionaries. A template is not useful by itself, but must be instantiated as a dictionary to be used. The dictionary typically specifies parameters to be given to the template functions. If a schema name is given then the text search template is created in the specified schema. Otherwise it is created in the current schema. You must be a superuser to use `CREATE TEXT SEARCH TEMPLATE`. This restriction is made because an erroneous text search template definition could confuse or even crash the server. The reason for separating templates from dictionaries is that a template encapsulates the “unsafe” aspects of defining a dictionary. The parameters that can be set when defining a dictionary are safe for unprivileged users to set, and so creating a dictionary need not be a privileged operation. Refer to [Chapter 12](https://www.postgresql.org/docs/18/textsearch.html "Chapter 12. Full Text Search") for further information. Parameters ---------- _`name`_ The name of the text search template to be created. The name can be schema-qualified. _`init_function`_ The name of the init function for the template. _`lexize_function`_ The name of the lexize function for the template. The function names can be schema-qualified if necessary. Argument types are not given, since the argument list for each type of function is predetermined. The lexize function is required, but the init function is optional. The arguments can appear in any order, not only the one shown above. Compatibility ------------- There is no `CREATE TEXT SEARCH TEMPLATE` statement in the SQL standard. See Also -------- [ALTER TEXT SEARCH TEMPLATE](https://www.postgresql.org/docs/18/sql-altertstemplate.html "ALTER TEXT SEARCH TEMPLATE") , [DROP TEXT SEARCH TEMPLATE](https://www.postgresql.org/docs/18/sql-droptstemplate.html "DROP TEXT SEARCH TEMPLATE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createtsparser.html "CREATE TEXT SEARCH PARSER") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-createtransform.html "CREATE TRANSFORM") | | CREATE TEXT SEARCH PARSER | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | CREATE TRANSFORM | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createtstemplate.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE TEXT SEARCH TEMPLATE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createtstemplate.html "PostgreSQL 18 - CREATE TEXT SEARCH TEMPLATE") ([18](https://www.postgresql.org/docs/18/sql-createtstemplate.html "PostgreSQL 18 - CREATE TEXT SEARCH TEMPLATE") ) / [17](https://www.postgresql.org/docs/17/sql-createtstemplate.html "PostgreSQL 17 - CREATE TEXT SEARCH TEMPLATE") / [16](https://www.postgresql.org/docs/16/sql-createtstemplate.html "PostgreSQL 16 - CREATE TEXT SEARCH TEMPLATE") / [15](https://www.postgresql.org/docs/15/sql-createtstemplate.html "PostgreSQL 15 - CREATE TEXT SEARCH TEMPLATE") / [14](https://www.postgresql.org/docs/14/sql-createtstemplate.html "PostgreSQL 14 - CREATE TEXT SEARCH TEMPLATE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createtstemplate.html "PostgreSQL devel - CREATE TEXT SEARCH TEMPLATE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createtstemplate.html "PostgreSQL 13 - CREATE TEXT SEARCH TEMPLATE") / [12](https://www.postgresql.org/docs/12/sql-createtstemplate.html "PostgreSQL 12 - CREATE TEXT SEARCH TEMPLATE") / [11](https://www.postgresql.org/docs/11/sql-createtstemplate.html "PostgreSQL 11 - CREATE TEXT SEARCH TEMPLATE") / [10](https://www.postgresql.org/docs/10/sql-createtstemplate.html "PostgreSQL 10 - CREATE TEXT SEARCH TEMPLATE") / [9.6](https://www.postgresql.org/docs/9.6/sql-createtstemplate.html "PostgreSQL 9.6 - CREATE TEXT SEARCH TEMPLATE") / [9.5](https://www.postgresql.org/docs/9.5/sql-createtstemplate.html "PostgreSQL 9.5 - CREATE TEXT SEARCH TEMPLATE") / [9.4](https://www.postgresql.org/docs/9.4/sql-createtstemplate.html "PostgreSQL 9.4 - CREATE TEXT SEARCH TEMPLATE") / [9.3](https://www.postgresql.org/docs/9.3/sql-createtstemplate.html "PostgreSQL 9.3 - CREATE TEXT SEARCH TEMPLATE") / [9.2](https://www.postgresql.org/docs/9.2/sql-createtstemplate.html "PostgreSQL 9.2 - CREATE TEXT SEARCH TEMPLATE") / [9.1](https://www.postgresql.org/docs/9.1/sql-createtstemplate.html "PostgreSQL 9.1 - CREATE TEXT SEARCH TEMPLATE") / [9.0](https://www.postgresql.org/docs/9.0/sql-createtstemplate.html "PostgreSQL 9.0 - CREATE TEXT SEARCH TEMPLATE") / [8.4](https://www.postgresql.org/docs/8.4/sql-createtstemplate.html "PostgreSQL 8.4 - CREATE TEXT SEARCH TEMPLATE") / [8.3](https://www.postgresql.org/docs/8.3/sql-createtstemplate.html "PostgreSQL 8.3 - CREATE TEXT SEARCH TEMPLATE") | CREATE TEXT SEARCH TEMPLATE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createtsparser.html "CREATE TEXT SEARCH PARSER") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-createtransform.html "CREATE TRANSFORM") | * * * CREATE TEXT SEARCH TEMPLATE --------------------------- CREATE TEXT SEARCH TEMPLATE — define a new text search template Synopsis -------- CREATE TEXT SEARCH TEMPLATE _`name`_ ( \[ INIT = _`init_function`_ , \] LEXIZE = _`lexize_function`_ ) Description ----------- `CREATE TEXT SEARCH TEMPLATE` creates a new text search template. Text search templates define the functions that implement text search dictionaries. A template is not useful by itself, but must be instantiated as a dictionary to be used. The dictionary typically specifies parameters to be given to the template functions. If a schema name is given then the text search template is created in the specified schema. Otherwise it is created in the current schema. You must be a superuser to use `CREATE TEXT SEARCH TEMPLATE`. This restriction is made because an erroneous text search template definition could confuse or even crash the server. The reason for separating templates from dictionaries is that a template encapsulates the “unsafe” aspects of defining a dictionary. The parameters that can be set when defining a dictionary are safe for unprivileged users to set, and so creating a dictionary need not be a privileged operation. Refer to [Chapter 12](https://www.postgresql.org/docs/current/textsearch.html "Chapter 12. Full Text Search") for further information. Parameters ---------- _`name`_ The name of the text search template to be created. The name can be schema-qualified. _`init_function`_ The name of the init function for the template. _`lexize_function`_ The name of the lexize function for the template. The function names can be schema-qualified if necessary. Argument types are not given, since the argument list for each type of function is predetermined. The lexize function is required, but the init function is optional. The arguments can appear in any order, not only the one shown above. Compatibility ------------- There is no `CREATE TEXT SEARCH TEMPLATE` statement in the SQL standard. See Also -------- [ALTER TEXT SEARCH TEMPLATE](https://www.postgresql.org/docs/current/sql-altertstemplate.html "ALTER TEXT SEARCH TEMPLATE") , [DROP TEXT SEARCH TEMPLATE](https://www.postgresql.org/docs/current/sql-droptstemplate.html "DROP TEXT SEARCH TEMPLATE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createtsparser.html "CREATE TEXT SEARCH PARSER") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-createtransform.html "CREATE TRANSFORM") | | CREATE TEXT SEARCH PARSER | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | CREATE TRANSFORM | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createtstemplate.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 29.11. Security November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/logical-replication-security.html "PostgreSQL 18 - 29.11. Security") ([18](https://www.postgresql.org/docs/18/logical-replication-security.html "PostgreSQL 18 - 29.11. Security") ) / [17](https://www.postgresql.org/docs/17/logical-replication-security.html "PostgreSQL 17 - 29.11. Security") / [16](https://www.postgresql.org/docs/16/logical-replication-security.html "PostgreSQL 16 - 29.11. Security") / [15](https://www.postgresql.org/docs/15/logical-replication-security.html "PostgreSQL 15 - 29.11. Security") / [14](https://www.postgresql.org/docs/14/logical-replication-security.html "PostgreSQL 14 - 29.11. Security") Development Versions: [devel](https://www.postgresql.org/docs/devel/logical-replication-security.html "PostgreSQL devel - 29.11. Security") Unsupported versions: [13](https://www.postgresql.org/docs/13/logical-replication-security.html "PostgreSQL 13 - 29.11. Security") / [12](https://www.postgresql.org/docs/12/logical-replication-security.html "PostgreSQL 12 - 29.11. Security") / [11](https://www.postgresql.org/docs/11/logical-replication-security.html "PostgreSQL 11 - 29.11. Security") / [10](https://www.postgresql.org/docs/10/logical-replication-security.html "PostgreSQL 10 - 29.11. Security") | 29.11. Security | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/logical-replication-monitoring.html "29.10. Monitoring") | [Up](https://www.postgresql.org/docs/18/logical-replication.html "Chapter 29. Logical Replication") | Chapter 29. Logical Replication | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/logical-replication-config.html "29.12. Configuration Settings") | * * * 29.11. Security [#](https://www.postgresql.org/docs/18/logical-replication-security.html#LOGICAL-REPLICATION-SECURITY) ----------------------------------------------------------------------------------------------------------------------- The role used for the replication connection must have the `REPLICATION` attribute (or be a superuser). If the role lacks `SUPERUSER` and `BYPASSRLS`, publisher row security policies can execute. If the role does not trust all table owners, include `options=-crow_security=off` in the connection string; if a table owner then adds a row security policy, that setting will cause replication to halt rather than execute the policy. Access for the role must be configured in `pg_hba.conf` and it must have the `LOGIN` attribute. In order to be able to copy the initial table data, the role used for the replication connection must have the `SELECT` privilege on a published table (or be a superuser). To create a publication, the user must have the `CREATE` privilege in the database. To add tables to a publication, the user must have ownership rights on the table. To add all tables in schema to a publication, the user must be a superuser. To create a publication that publishes all tables or all tables in schema automatically, the user must be a superuser. There are currently no privileges on publications. Any subscription (that is able to connect) can access any publication. Thus, if you intend to hide some information from particular subscribers, such as by using row filters or column lists, or by not adding the whole table to the publication, be aware that other publications in the same database could expose the same information. Publication privileges might be added to PostgreSQL in the future to allow for finer-grained access control. To create a subscription, the user must have the privileges of the `pg_create_subscription` role, as well as `CREATE` privileges on the database. The subscription apply process will, at a session level, run with the privileges of the subscription owner. However, when performing an insert, update, delete, or truncate operation on a particular table, it will switch roles to the table owner and perform the operation with the table owner's privileges. This means that the subscription owner needs to be able to `SET ROLE` to each role that owns a replicated table. If the subscription has been configured with `run_as_owner = true`, then no user switching will occur. Instead, all operations will be performed with the permissions of the subscription owner. In this case, the subscription owner only needs privileges to `SELECT`, `INSERT`, `UPDATE`, and `DELETE` from the target table, and does not need privileges to `SET ROLE` to the table owner. However, this also means that any user who owns a table into which replication is happening can execute arbitrary code with the privileges of the subscription owner. For example, they could do this by simply attaching a trigger to one of the tables which they own. Because it is usually undesirable to allow one role to freely assume the privileges of another, this option should be avoided unless user security within the database is of no concern. On the publisher, privileges are only checked once at the start of a replication connection and are not re-checked as each change record is read. On the subscriber, the subscription owner's privileges are re-checked for each transaction when applied. If a worker is in the process of applying a transaction when the ownership of the subscription is changed by a concurrent transaction, the application of the current transaction will continue under the old owner's privileges. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/logical-replication-monitoring.html "29.10. Monitoring") | [Up](https://www.postgresql.org/docs/18/logical-replication.html "Chapter 29. Logical Replication") | [Next](https://www.postgresql.org/docs/18/logical-replication-config.html "29.12. Configuration Settings") | | 29.10. Monitoring | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 29.12. Configuration Settings | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/logical-replication-security.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 29.11. Security November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/logical-replication-security.html "PostgreSQL 18 - 29.11. Security") ([18](https://www.postgresql.org/docs/18/logical-replication-security.html "PostgreSQL 18 - 29.11. Security") ) / [17](https://www.postgresql.org/docs/17/logical-replication-security.html "PostgreSQL 17 - 29.11. Security") / [16](https://www.postgresql.org/docs/16/logical-replication-security.html "PostgreSQL 16 - 29.11. Security") / [15](https://www.postgresql.org/docs/15/logical-replication-security.html "PostgreSQL 15 - 29.11. Security") / [14](https://www.postgresql.org/docs/14/logical-replication-security.html "PostgreSQL 14 - 29.11. Security") Development Versions: [devel](https://www.postgresql.org/docs/devel/logical-replication-security.html "PostgreSQL devel - 29.11. Security") Unsupported versions: [13](https://www.postgresql.org/docs/13/logical-replication-security.html "PostgreSQL 13 - 29.11. Security") / [12](https://www.postgresql.org/docs/12/logical-replication-security.html "PostgreSQL 12 - 29.11. Security") / [11](https://www.postgresql.org/docs/11/logical-replication-security.html "PostgreSQL 11 - 29.11. Security") / [10](https://www.postgresql.org/docs/10/logical-replication-security.html "PostgreSQL 10 - 29.11. Security") | 29.11. Security | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/logical-replication-monitoring.html "29.10. Monitoring") | [Up](https://www.postgresql.org/docs/current/logical-replication.html "Chapter 29. Logical Replication") | Chapter 29. Logical Replication | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/logical-replication-config.html "29.12. Configuration Settings") | * * * 29.11. Security [#](https://www.postgresql.org/docs/current/logical-replication-security.html#LOGICAL-REPLICATION-SECURITY) ---------------------------------------------------------------------------------------------------------------------------- The role used for the replication connection must have the `REPLICATION` attribute (or be a superuser). If the role lacks `SUPERUSER` and `BYPASSRLS`, publisher row security policies can execute. If the role does not trust all table owners, include `options=-crow_security=off` in the connection string; if a table owner then adds a row security policy, that setting will cause replication to halt rather than execute the policy. Access for the role must be configured in `pg_hba.conf` and it must have the `LOGIN` attribute. In order to be able to copy the initial table data, the role used for the replication connection must have the `SELECT` privilege on a published table (or be a superuser). To create a publication, the user must have the `CREATE` privilege in the database. To add tables to a publication, the user must have ownership rights on the table. To add all tables in schema to a publication, the user must be a superuser. To create a publication that publishes all tables or all tables in schema automatically, the user must be a superuser. There are currently no privileges on publications. Any subscription (that is able to connect) can access any publication. Thus, if you intend to hide some information from particular subscribers, such as by using row filters or column lists, or by not adding the whole table to the publication, be aware that other publications in the same database could expose the same information. Publication privileges might be added to PostgreSQL in the future to allow for finer-grained access control. To create a subscription, the user must have the privileges of the `pg_create_subscription` role, as well as `CREATE` privileges on the database. The subscription apply process will, at a session level, run with the privileges of the subscription owner. However, when performing an insert, update, delete, or truncate operation on a particular table, it will switch roles to the table owner and perform the operation with the table owner's privileges. This means that the subscription owner needs to be able to `SET ROLE` to each role that owns a replicated table. If the subscription has been configured with `run_as_owner = true`, then no user switching will occur. Instead, all operations will be performed with the permissions of the subscription owner. In this case, the subscription owner only needs privileges to `SELECT`, `INSERT`, `UPDATE`, and `DELETE` from the target table, and does not need privileges to `SET ROLE` to the table owner. However, this also means that any user who owns a table into which replication is happening can execute arbitrary code with the privileges of the subscription owner. For example, they could do this by simply attaching a trigger to one of the tables which they own. Because it is usually undesirable to allow one role to freely assume the privileges of another, this option should be avoided unless user security within the database is of no concern. On the publisher, privileges are only checked once at the start of a replication connection and are not re-checked as each change record is read. On the subscriber, the subscription owner's privileges are re-checked for each transaction when applied. If a worker is in the process of applying a transaction when the ownership of the subscription is changed by a concurrent transaction, the application of the current transaction will continue under the old owner's privileges. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/logical-replication-monitoring.html "29.10. Monitoring") | [Up](https://www.postgresql.org/docs/current/logical-replication.html "Chapter 29. Logical Replication") | [Next](https://www.postgresql.org/docs/current/logical-replication-config.html "29.12. Configuration Settings") | | 29.10. Monitoring | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 29.12. Configuration Settings | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/logical-replication-security.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.6. attributes November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-attributes.html "PostgreSQL 18 - 35.6. attributes") ([18](https://www.postgresql.org/docs/18/infoschema-attributes.html "PostgreSQL 18 - 35.6. attributes") ) / [17](https://www.postgresql.org/docs/17/infoschema-attributes.html "PostgreSQL 17 - 35.6. attributes") / [16](https://www.postgresql.org/docs/16/infoschema-attributes.html "PostgreSQL 16 - 35.6. attributes") / [15](https://www.postgresql.org/docs/15/infoschema-attributes.html "PostgreSQL 15 - 35.6. attributes") / [14](https://www.postgresql.org/docs/14/infoschema-attributes.html "PostgreSQL 14 - 35.6. attributes") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-attributes.html "PostgreSQL devel - 35.6. attributes") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-attributes.html "PostgreSQL 13 - 35.6. attributes") / [12](https://www.postgresql.org/docs/12/infoschema-attributes.html "PostgreSQL 12 - 35.6. attributes") / [11](https://www.postgresql.org/docs/11/infoschema-attributes.html "PostgreSQL 11 - 35.6. attributes") / [10](https://www.postgresql.org/docs/10/infoschema-attributes.html "PostgreSQL 10 - 35.6. attributes") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-attributes.html "PostgreSQL 9.6 - 35.6. attributes") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-attributes.html "PostgreSQL 9.5 - 35.6. attributes") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-attributes.html "PostgreSQL 9.4 - 35.6. attributes") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-attributes.html "PostgreSQL 9.3 - 35.6. attributes") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-attributes.html "PostgreSQL 9.2 - 35.6. attributes") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-attributes.html "PostgreSQL 9.1 - 35.6. attributes") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-attributes.html "PostgreSQL 9.0 - 35.6. attributes") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-attributes.html "PostgreSQL 8.4 - 35.6. attributes") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-attributes.html "PostgreSQL 8.3 - 35.6. attributes") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-attributes.html "PostgreSQL 8.2 - 35.6. attributes") | 35.6. `attributes` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-applicable-roles.html "35.5. applicable_roles") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/infoschema-character-sets.html "35.7. character_sets") | * * * 35.6. `attributes` [#](https://www.postgresql.org/docs/18/infoschema-attributes.html#INFOSCHEMA-ATTRIBUTES) ------------------------------------------------------------------------------------------------------------ The view `attributes` contains information about the attributes of composite data types defined in the database. (Note that the view does not give information about table columns, which are sometimes called attributes in PostgreSQL contexts.) Only those attributes are shown that the current user has access to (by way of being the owner of or having some privilege on the type). **Table 35.4. `attributes` Columns** | Column Type

Description | | --- | | `udt_catalog` `sql_identifier`

Name of the database containing the data type (always the current database) | | `udt_schema` `sql_identifier`

Name of the schema containing the data type | | `udt_name` `sql_identifier`

Name of the data type | | `attribute_name` `sql_identifier`

Name of the attribute | | `ordinal_position` `cardinal_number`

Ordinal position of the attribute within the data type (count starts at 1) | | `attribute_default` `character_data`

Default expression of the attribute | | `is_nullable` `yes_or_no`

`YES` if the attribute is possibly nullable, `NO` if it is known not nullable. | | `data_type` `character_data`

Data type of the attribute, if it is a built-in type, or `ARRAY` if it is some array (in that case, see the view `element_types`), else `USER-DEFINED` (in that case, the type is identified in `attribute_udt_name` and associated columns). | | `character_maximum_length` `cardinal_number`

If `data_type` identifies a character or bit string type, the declared maximum length; null for all other data types or if no maximum length was declared. | | `character_octet_length` `cardinal_number`

If `data_type` identifies a character type, the maximum possible length in octets (bytes) of a datum; null for all other data types. The maximum octet length depends on the declared character maximum length (see above) and the server encoding. | | `character_set_catalog` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `character_set_schema` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `character_set_name` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `collation_catalog` `sql_identifier`

Name of the database containing the collation of the attribute (always the current database), null if default or the data type of the attribute is not collatable | | `collation_schema` `sql_identifier`

Name of the schema containing the collation of the attribute, null if default or the data type of the attribute is not collatable | | `collation_name` `sql_identifier`

Name of the collation of the attribute, null if default or the data type of the attribute is not collatable | | `numeric_precision` `cardinal_number`

If `data_type` identifies a numeric type, this column contains the (declared or implicit) precision of the type for this attribute. The precision indicates the number of significant digits. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column `numeric_precision_radix`. For all other data types, this column is null. | | `numeric_precision_radix` `cardinal_number`

If `data_type` identifies a numeric type, this column indicates in which base the values in the columns `numeric_precision` and `numeric_scale` are expressed. The value is either 2 or 10. For all other data types, this column is null. | | `numeric_scale` `cardinal_number`

If `data_type` identifies an exact numeric type, this column contains the (declared or implicit) scale of the type for this attribute. The scale indicates the number of significant digits to the right of the decimal point. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column `numeric_precision_radix`. For all other data types, this column is null. | | `datetime_precision` `cardinal_number`

If `data_type` identifies a date, time, timestamp, or interval type, this column contains the (declared or implicit) fractional seconds precision of the type for this attribute, that is, the number of decimal digits maintained following the decimal point in the seconds value. For all other data types, this column is null. | | `interval_type` `character_data`

If `data_type` identifies an interval type, this column contains the specification which fields the intervals include for this attribute, e.g., `YEAR TO MONTH`, `DAY TO SECOND`, etc. If no field restrictions were specified (that is, the interval accepts all fields), and for all other data types, this field is null. | | `interval_precision` `cardinal_number`

Applies to a feature not available in PostgreSQL (see `datetime_precision` for the fractional seconds precision of interval type attributes) | | `attribute_udt_catalog` `sql_identifier`

Name of the database that the attribute data type is defined in (always the current database) | | `attribute_udt_schema` `sql_identifier`

Name of the schema that the attribute data type is defined in | | `attribute_udt_name` `sql_identifier`

Name of the attribute data type | | `scope_catalog` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `scope_schema` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `scope_name` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `maximum_cardinality` `cardinal_number`

Always null, because arrays always have unlimited maximum cardinality in PostgreSQL | | `dtd_identifier` `sql_identifier`

An identifier of the data type descriptor of the attribute, unique among the data type descriptors pertaining to the composite type. This is mainly useful for joining with other instances of such identifiers. (The specific format of the identifier is not defined and not guaranteed to remain the same in future versions.) | | `is_derived_reference_attribute` `yes_or_no`

Applies to a feature not available in PostgreSQL | See also under [Section 35.17](https://www.postgresql.org/docs/18/infoschema-columns.html "35.17. columns") , a similarly structured view, for further information on some of the columns. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-applicable-roles.html "35.5. applicable_roles") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/18/infoschema-character-sets.html "35.7. character_sets") | | 35.5. `applicable_roles` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 35.7. `character_sets` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-attributes.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.6. attributes November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-attributes.html "PostgreSQL 18 - 35.6. attributes") ([18](https://www.postgresql.org/docs/18/infoschema-attributes.html "PostgreSQL 18 - 35.6. attributes") ) / [17](https://www.postgresql.org/docs/17/infoschema-attributes.html "PostgreSQL 17 - 35.6. attributes") / [16](https://www.postgresql.org/docs/16/infoschema-attributes.html "PostgreSQL 16 - 35.6. attributes") / [15](https://www.postgresql.org/docs/15/infoschema-attributes.html "PostgreSQL 15 - 35.6. attributes") / [14](https://www.postgresql.org/docs/14/infoschema-attributes.html "PostgreSQL 14 - 35.6. attributes") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-attributes.html "PostgreSQL devel - 35.6. attributes") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-attributes.html "PostgreSQL 13 - 35.6. attributes") / [12](https://www.postgresql.org/docs/12/infoschema-attributes.html "PostgreSQL 12 - 35.6. attributes") / [11](https://www.postgresql.org/docs/11/infoschema-attributes.html "PostgreSQL 11 - 35.6. attributes") / [10](https://www.postgresql.org/docs/10/infoschema-attributes.html "PostgreSQL 10 - 35.6. attributes") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-attributes.html "PostgreSQL 9.6 - 35.6. attributes") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-attributes.html "PostgreSQL 9.5 - 35.6. attributes") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-attributes.html "PostgreSQL 9.4 - 35.6. attributes") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-attributes.html "PostgreSQL 9.3 - 35.6. attributes") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-attributes.html "PostgreSQL 9.2 - 35.6. attributes") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-attributes.html "PostgreSQL 9.1 - 35.6. attributes") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-attributes.html "PostgreSQL 9.0 - 35.6. attributes") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-attributes.html "PostgreSQL 8.4 - 35.6. attributes") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-attributes.html "PostgreSQL 8.3 - 35.6. attributes") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-attributes.html "PostgreSQL 8.2 - 35.6. attributes") | 35.6. `attributes` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-applicable-roles.html "35.5. applicable_roles") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/infoschema-character-sets.html "35.7. character_sets") | * * * 35.6. `attributes` [#](https://www.postgresql.org/docs/current/infoschema-attributes.html#INFOSCHEMA-ATTRIBUTES) ----------------------------------------------------------------------------------------------------------------- The view `attributes` contains information about the attributes of composite data types defined in the database. (Note that the view does not give information about table columns, which are sometimes called attributes in PostgreSQL contexts.) Only those attributes are shown that the current user has access to (by way of being the owner of or having some privilege on the type). **Table 35.4. `attributes` Columns** | Column Type

Description | | --- | | `udt_catalog` `sql_identifier`

Name of the database containing the data type (always the current database) | | `udt_schema` `sql_identifier`

Name of the schema containing the data type | | `udt_name` `sql_identifier`

Name of the data type | | `attribute_name` `sql_identifier`

Name of the attribute | | `ordinal_position` `cardinal_number`

Ordinal position of the attribute within the data type (count starts at 1) | | `attribute_default` `character_data`

Default expression of the attribute | | `is_nullable` `yes_or_no`

`YES` if the attribute is possibly nullable, `NO` if it is known not nullable. | | `data_type` `character_data`

Data type of the attribute, if it is a built-in type, or `ARRAY` if it is some array (in that case, see the view `element_types`), else `USER-DEFINED` (in that case, the type is identified in `attribute_udt_name` and associated columns). | | `character_maximum_length` `cardinal_number`

If `data_type` identifies a character or bit string type, the declared maximum length; null for all other data types or if no maximum length was declared. | | `character_octet_length` `cardinal_number`

If `data_type` identifies a character type, the maximum possible length in octets (bytes) of a datum; null for all other data types. The maximum octet length depends on the declared character maximum length (see above) and the server encoding. | | `character_set_catalog` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `character_set_schema` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `character_set_name` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `collation_catalog` `sql_identifier`

Name of the database containing the collation of the attribute (always the current database), null if default or the data type of the attribute is not collatable | | `collation_schema` `sql_identifier`

Name of the schema containing the collation of the attribute, null if default or the data type of the attribute is not collatable | | `collation_name` `sql_identifier`

Name of the collation of the attribute, null if default or the data type of the attribute is not collatable | | `numeric_precision` `cardinal_number`

If `data_type` identifies a numeric type, this column contains the (declared or implicit) precision of the type for this attribute. The precision indicates the number of significant digits. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column `numeric_precision_radix`. For all other data types, this column is null. | | `numeric_precision_radix` `cardinal_number`

If `data_type` identifies a numeric type, this column indicates in which base the values in the columns `numeric_precision` and `numeric_scale` are expressed. The value is either 2 or 10. For all other data types, this column is null. | | `numeric_scale` `cardinal_number`

If `data_type` identifies an exact numeric type, this column contains the (declared or implicit) scale of the type for this attribute. The scale indicates the number of significant digits to the right of the decimal point. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column `numeric_precision_radix`. For all other data types, this column is null. | | `datetime_precision` `cardinal_number`

If `data_type` identifies a date, time, timestamp, or interval type, this column contains the (declared or implicit) fractional seconds precision of the type for this attribute, that is, the number of decimal digits maintained following the decimal point in the seconds value. For all other data types, this column is null. | | `interval_type` `character_data`

If `data_type` identifies an interval type, this column contains the specification which fields the intervals include for this attribute, e.g., `YEAR TO MONTH`, `DAY TO SECOND`, etc. If no field restrictions were specified (that is, the interval accepts all fields), and for all other data types, this field is null. | | `interval_precision` `cardinal_number`

Applies to a feature not available in PostgreSQL (see `datetime_precision` for the fractional seconds precision of interval type attributes) | | `attribute_udt_catalog` `sql_identifier`

Name of the database that the attribute data type is defined in (always the current database) | | `attribute_udt_schema` `sql_identifier`

Name of the schema that the attribute data type is defined in | | `attribute_udt_name` `sql_identifier`

Name of the attribute data type | | `scope_catalog` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `scope_schema` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `scope_name` `sql_identifier`

Applies to a feature not available in PostgreSQL | | `maximum_cardinality` `cardinal_number`

Always null, because arrays always have unlimited maximum cardinality in PostgreSQL | | `dtd_identifier` `sql_identifier`

An identifier of the data type descriptor of the attribute, unique among the data type descriptors pertaining to the composite type. This is mainly useful for joining with other instances of such identifiers. (The specific format of the identifier is not defined and not guaranteed to remain the same in future versions.) | | `is_derived_reference_attribute` `yes_or_no`

Applies to a feature not available in PostgreSQL | See also under [Section 35.17](https://www.postgresql.org/docs/current/infoschema-columns.html "35.17. columns") , a similarly structured view, for further information on some of the columns. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-applicable-roles.html "35.5. applicable_roles") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/current/infoschema-character-sets.html "35.7. character_sets") | | 35.5. `applicable_roles` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 35.7. `character_sets` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-attributes.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 32.17. The Connection Service File November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/libpq-pgservice.html "PostgreSQL 18 - 32.17. The Connection Service File") ([18](https://www.postgresql.org/docs/18/libpq-pgservice.html "PostgreSQL 18 - 32.17. The Connection Service File") ) / [17](https://www.postgresql.org/docs/17/libpq-pgservice.html "PostgreSQL 17 - 32.17. The Connection Service File") / [16](https://www.postgresql.org/docs/16/libpq-pgservice.html "PostgreSQL 16 - 32.17. The Connection Service File") / [15](https://www.postgresql.org/docs/15/libpq-pgservice.html "PostgreSQL 15 - 32.17. The Connection Service File") / [14](https://www.postgresql.org/docs/14/libpq-pgservice.html "PostgreSQL 14 - 32.17. The Connection Service File") Development Versions: [devel](https://www.postgresql.org/docs/devel/libpq-pgservice.html "PostgreSQL devel - 32.17. The Connection Service File") Unsupported versions: [13](https://www.postgresql.org/docs/13/libpq-pgservice.html "PostgreSQL 13 - 32.17. The Connection Service File") / [12](https://www.postgresql.org/docs/12/libpq-pgservice.html "PostgreSQL 12 - 32.17. The Connection Service File") / [11](https://www.postgresql.org/docs/11/libpq-pgservice.html "PostgreSQL 11 - 32.17. The Connection Service File") / [10](https://www.postgresql.org/docs/10/libpq-pgservice.html "PostgreSQL 10 - 32.17. The Connection Service File") / [9.6](https://www.postgresql.org/docs/9.6/libpq-pgservice.html "PostgreSQL 9.6 - 32.17. The Connection Service File") / [9.5](https://www.postgresql.org/docs/9.5/libpq-pgservice.html "PostgreSQL 9.5 - 32.17. The Connection Service File") / [9.4](https://www.postgresql.org/docs/9.4/libpq-pgservice.html "PostgreSQL 9.4 - 32.17. The Connection Service File") / [9.3](https://www.postgresql.org/docs/9.3/libpq-pgservice.html "PostgreSQL 9.3 - 32.17. The Connection Service File") / [9.2](https://www.postgresql.org/docs/9.2/libpq-pgservice.html "PostgreSQL 9.2 - 32.17. The Connection Service File") / [9.1](https://www.postgresql.org/docs/9.1/libpq-pgservice.html "PostgreSQL 9.1 - 32.17. The Connection Service File") / [9.0](https://www.postgresql.org/docs/9.0/libpq-pgservice.html "PostgreSQL 9.0 - 32.17. The Connection Service File") / [8.4](https://www.postgresql.org/docs/8.4/libpq-pgservice.html "PostgreSQL 8.4 - 32.17. The Connection Service File") / [8.3](https://www.postgresql.org/docs/8.3/libpq-pgservice.html "PostgreSQL 8.3 - 32.17. The Connection Service File") / [8.2](https://www.postgresql.org/docs/8.2/libpq-pgservice.html "PostgreSQL 8.2 - 32.17. The Connection Service File") / [8.1](https://www.postgresql.org/docs/8.1/libpq-pgservice.html "PostgreSQL 8.1 - 32.17. The Connection Service File") | 32.17. The Connection Service File | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/libpq-pgpass.html "32.16. The Password File") | [Up](https://www.postgresql.org/docs/18/libpq.html "Chapter 32. libpq — C Library") | Chapter 32. libpq — C Library | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/libpq-ldap.html "32.18. LDAP Lookup of Connection Parameters") | * * * 32.17. The Connection Service File [#](https://www.postgresql.org/docs/18/libpq-pgservice.html#LIBPQ-PGSERVICE) ---------------------------------------------------------------------------------------------------------------- The connection service file allows libpq connection parameters to be associated with a single service name. That service name can then be specified using the `service` key word in a libpq connection string, and the associated settings will be used. This allows connection parameters to be modified without requiring a recompile of the libpq-using application. The service name can also be specified using the `PGSERVICE` environment variable. Service names can be defined in either a per-user service file or a system-wide file. If the same service name exists in both the user and the system file, the user file takes precedence. By default, the per-user service file is named `~/.pg_service.conf`. On Microsoft Windows, it is named `%APPDATA%\postgresql\.pg_service.conf` (where `%APPDATA%` refers to the Application Data subdirectory in the user's profile). A different file name can be specified by setting the environment variable `PGSERVICEFILE`. The system-wide file is named `pg_service.conf`. By default it is sought in the `etc` directory of the PostgreSQL installation (use `pg_config --sysconfdir` to identify this directory precisely). Another directory, but not a different file name, can be specified by setting the environment variable `PGSYSCONFDIR`. Either service file uses an “INI file” format where the section name is the service name and the parameters are connection parameters; see [Section 32.1.2](https://www.postgresql.org/docs/18/libpq-connect.html#LIBPQ-PARAMKEYWORDS "32.1.2. Parameter Key Words") for a list. For example: \# comment \[mydb\] host=somehost port=5433 user=admin An example file is provided in the PostgreSQL installation at `share/pg_service.conf.sample`. Connection parameters obtained from a service file are combined with parameters obtained from other sources. A service file setting overrides the corresponding environment variable, and in turn can be overridden by a value given directly in the connection string. For example, using the above service file, a connection string `service=mydb port=5434` will use host `somehost`, port `5434`, user `admin`, and other parameters as set by environment variables or built-in defaults. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/libpq-pgpass.html "32.16. The Password File") | [Up](https://www.postgresql.org/docs/18/libpq.html "Chapter 32. libpq — C Library") | [Next](https://www.postgresql.org/docs/18/libpq-ldap.html "32.18. LDAP Lookup of Connection Parameters") | | 32.16. The Password File | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 32.18. LDAP Lookup of Connection Parameters | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/libpq-pgservice.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 32.17. The Connection Service File November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/libpq-pgservice.html "PostgreSQL 18 - 32.17. The Connection Service File") ([18](https://www.postgresql.org/docs/18/libpq-pgservice.html "PostgreSQL 18 - 32.17. The Connection Service File") ) / [17](https://www.postgresql.org/docs/17/libpq-pgservice.html "PostgreSQL 17 - 32.17. The Connection Service File") / [16](https://www.postgresql.org/docs/16/libpq-pgservice.html "PostgreSQL 16 - 32.17. The Connection Service File") / [15](https://www.postgresql.org/docs/15/libpq-pgservice.html "PostgreSQL 15 - 32.17. The Connection Service File") / [14](https://www.postgresql.org/docs/14/libpq-pgservice.html "PostgreSQL 14 - 32.17. The Connection Service File") Development Versions: [devel](https://www.postgresql.org/docs/devel/libpq-pgservice.html "PostgreSQL devel - 32.17. The Connection Service File") Unsupported versions: [13](https://www.postgresql.org/docs/13/libpq-pgservice.html "PostgreSQL 13 - 32.17. The Connection Service File") / [12](https://www.postgresql.org/docs/12/libpq-pgservice.html "PostgreSQL 12 - 32.17. The Connection Service File") / [11](https://www.postgresql.org/docs/11/libpq-pgservice.html "PostgreSQL 11 - 32.17. The Connection Service File") / [10](https://www.postgresql.org/docs/10/libpq-pgservice.html "PostgreSQL 10 - 32.17. The Connection Service File") / [9.6](https://www.postgresql.org/docs/9.6/libpq-pgservice.html "PostgreSQL 9.6 - 32.17. The Connection Service File") / [9.5](https://www.postgresql.org/docs/9.5/libpq-pgservice.html "PostgreSQL 9.5 - 32.17. The Connection Service File") / [9.4](https://www.postgresql.org/docs/9.4/libpq-pgservice.html "PostgreSQL 9.4 - 32.17. The Connection Service File") / [9.3](https://www.postgresql.org/docs/9.3/libpq-pgservice.html "PostgreSQL 9.3 - 32.17. The Connection Service File") / [9.2](https://www.postgresql.org/docs/9.2/libpq-pgservice.html "PostgreSQL 9.2 - 32.17. The Connection Service File") / [9.1](https://www.postgresql.org/docs/9.1/libpq-pgservice.html "PostgreSQL 9.1 - 32.17. The Connection Service File") / [9.0](https://www.postgresql.org/docs/9.0/libpq-pgservice.html "PostgreSQL 9.0 - 32.17. The Connection Service File") / [8.4](https://www.postgresql.org/docs/8.4/libpq-pgservice.html "PostgreSQL 8.4 - 32.17. The Connection Service File") / [8.3](https://www.postgresql.org/docs/8.3/libpq-pgservice.html "PostgreSQL 8.3 - 32.17. The Connection Service File") / [8.2](https://www.postgresql.org/docs/8.2/libpq-pgservice.html "PostgreSQL 8.2 - 32.17. The Connection Service File") / [8.1](https://www.postgresql.org/docs/8.1/libpq-pgservice.html "PostgreSQL 8.1 - 32.17. The Connection Service File") | 32.17. The Connection Service File | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/libpq-pgpass.html "32.16. The Password File") | [Up](https://www.postgresql.org/docs/current/libpq.html "Chapter 32. libpq — C Library") | Chapter 32. libpq — C Library | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/libpq-ldap.html "32.18. LDAP Lookup of Connection Parameters") | * * * 32.17. The Connection Service File [#](https://www.postgresql.org/docs/current/libpq-pgservice.html#LIBPQ-PGSERVICE) --------------------------------------------------------------------------------------------------------------------- The connection service file allows libpq connection parameters to be associated with a single service name. That service name can then be specified using the `service` key word in a libpq connection string, and the associated settings will be used. This allows connection parameters to be modified without requiring a recompile of the libpq-using application. The service name can also be specified using the `PGSERVICE` environment variable. Service names can be defined in either a per-user service file or a system-wide file. If the same service name exists in both the user and the system file, the user file takes precedence. By default, the per-user service file is named `~/.pg_service.conf`. On Microsoft Windows, it is named `%APPDATA%\postgresql\.pg_service.conf` (where `%APPDATA%` refers to the Application Data subdirectory in the user's profile). A different file name can be specified by setting the environment variable `PGSERVICEFILE`. The system-wide file is named `pg_service.conf`. By default it is sought in the `etc` directory of the PostgreSQL installation (use `pg_config --sysconfdir` to identify this directory precisely). Another directory, but not a different file name, can be specified by setting the environment variable `PGSYSCONFDIR`. Either service file uses an “INI file” format where the section name is the service name and the parameters are connection parameters; see [Section 32.1.2](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS "32.1.2. Parameter Key Words") for a list. For example: \# comment \[mydb\] host=somehost port=5433 user=admin An example file is provided in the PostgreSQL installation at `share/pg_service.conf.sample`. Connection parameters obtained from a service file are combined with parameters obtained from other sources. A service file setting overrides the corresponding environment variable, and in turn can be overridden by a value given directly in the connection string. For example, using the above service file, a connection string `service=mydb port=5434` will use host `somehost`, port `5434`, user `admin`, and other parameters as set by environment variables or built-in defaults. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/libpq-pgpass.html "32.16. The Password File") | [Up](https://www.postgresql.org/docs/current/libpq.html "Chapter 32. libpq — C Library") | [Next](https://www.postgresql.org/docs/current/libpq-ldap.html "32.18. LDAP Lookup of Connection Parameters") | | 32.16. The Password File | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 32.18. LDAP Lookup of Connection Parameters | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/libpq-pgservice.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.24. pg_sequences November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-sequences.html "PostgreSQL 18 - 53.24. pg_sequences") ([18](https://www.postgresql.org/docs/18/view-pg-sequences.html "PostgreSQL 18 - 53.24. pg_sequences") ) / [17](https://www.postgresql.org/docs/17/view-pg-sequences.html "PostgreSQL 17 - 53.24. pg_sequences") / [16](https://www.postgresql.org/docs/16/view-pg-sequences.html "PostgreSQL 16 - 53.24. pg_sequences") / [15](https://www.postgresql.org/docs/15/view-pg-sequences.html "PostgreSQL 15 - 53.24. pg_sequences") / [14](https://www.postgresql.org/docs/14/view-pg-sequences.html "PostgreSQL 14 - 53.24. pg_sequences") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-sequences.html "PostgreSQL devel - 53.24. pg_sequences") Unsupported versions: [13](https://www.postgresql.org/docs/13/view-pg-sequences.html "PostgreSQL 13 - 53.24. pg_sequences") / [12](https://www.postgresql.org/docs/12/view-pg-sequences.html "PostgreSQL 12 - 53.24. pg_sequences") / [11](https://www.postgresql.org/docs/11/view-pg-sequences.html "PostgreSQL 11 - 53.24. pg_sequences") / [10](https://www.postgresql.org/docs/10/view-pg-sequences.html "PostgreSQL 10 - 53.24. pg_sequences") | 53.24. `pg_sequences` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-seclabels.html "53.23. pg_seclabels") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/view-pg-settings.html "53.25. pg_settings") | * * * 53.24. `pg_sequences` [#](https://www.postgresql.org/docs/18/view-pg-sequences.html#VIEW-PG-SEQUENCES) ------------------------------------------------------------------------------------------------------- The view `pg_sequences` provides access to useful information about each sequence in the database. **Table 53.24. `pg_sequences` Columns** | Column Type

Description | | --- | | `schemaname` `name` (references [`pg_namespace`](https://www.postgresql.org/docs/18/catalog-pg-namespace.html "52.32. pg_namespace")
.`nspname`)

Name of schema containing sequence | | `sequencename` `name` (references [`pg_class`](https://www.postgresql.org/docs/18/catalog-pg-class.html "52.11. pg_class")
.`relname`)

Name of sequence | | `sequenceowner` `name` (references [`pg_authid`](https://www.postgresql.org/docs/18/catalog-pg-authid.html "52.8. pg_authid")
.`rolname`)

Name of sequence's owner | | `data_type` `regtype` (references [`pg_type`](https://www.postgresql.org/docs/18/catalog-pg-type.html "52.64. pg_type")
.`oid`)

Data type of the sequence | | `start_value` `int8`

Start value of the sequence | | `min_value` `int8`

Minimum value of the sequence | | `max_value` `int8`

Maximum value of the sequence | | `increment_by` `int8`

Increment value of the sequence | | `cycle` `bool`

Whether the sequence cycles | | `cache_size` `int8`

Cache size of the sequence | | `last_value` `int8`

The last sequence value written to disk. If caching is used, this value can be greater than the last value handed out from the sequence. | The `last_value` column will read as null if any of the following are true: * The sequence has not been read from yet. * The current user does not have `USAGE` or `SELECT` privilege on the sequence. * The sequence is unlogged and the server is a standby. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-seclabels.html "53.23. pg_seclabels") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/18/view-pg-settings.html "53.25. pg_settings") | | 53.23. `pg_seclabels` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 53.25. `pg_settings` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-sequences.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.24. pg_sequences November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-sequences.html "PostgreSQL 18 - 53.24. pg_sequences") ([18](https://www.postgresql.org/docs/18/view-pg-sequences.html "PostgreSQL 18 - 53.24. pg_sequences") ) / [17](https://www.postgresql.org/docs/17/view-pg-sequences.html "PostgreSQL 17 - 53.24. pg_sequences") / [16](https://www.postgresql.org/docs/16/view-pg-sequences.html "PostgreSQL 16 - 53.24. pg_sequences") / [15](https://www.postgresql.org/docs/15/view-pg-sequences.html "PostgreSQL 15 - 53.24. pg_sequences") / [14](https://www.postgresql.org/docs/14/view-pg-sequences.html "PostgreSQL 14 - 53.24. pg_sequences") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-sequences.html "PostgreSQL devel - 53.24. pg_sequences") Unsupported versions: [13](https://www.postgresql.org/docs/13/view-pg-sequences.html "PostgreSQL 13 - 53.24. pg_sequences") / [12](https://www.postgresql.org/docs/12/view-pg-sequences.html "PostgreSQL 12 - 53.24. pg_sequences") / [11](https://www.postgresql.org/docs/11/view-pg-sequences.html "PostgreSQL 11 - 53.24. pg_sequences") / [10](https://www.postgresql.org/docs/10/view-pg-sequences.html "PostgreSQL 10 - 53.24. pg_sequences") | 53.24. `pg_sequences` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-seclabels.html "53.23. pg_seclabels") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/view-pg-settings.html "53.25. pg_settings") | * * * 53.24. `pg_sequences` [#](https://www.postgresql.org/docs/current/view-pg-sequences.html#VIEW-PG-SEQUENCES) ------------------------------------------------------------------------------------------------------------ The view `pg_sequences` provides access to useful information about each sequence in the database. **Table 53.24. `pg_sequences` Columns** | Column Type

Description | | --- | | `schemaname` `name` (references [`pg_namespace`](https://www.postgresql.org/docs/current/catalog-pg-namespace.html "52.32. pg_namespace")
.`nspname`)

Name of schema containing sequence | | `sequencename` `name` (references [`pg_class`](https://www.postgresql.org/docs/current/catalog-pg-class.html "52.11. pg_class")
.`relname`)

Name of sequence | | `sequenceowner` `name` (references [`pg_authid`](https://www.postgresql.org/docs/current/catalog-pg-authid.html "52.8. pg_authid")
.`rolname`)

Name of sequence's owner | | `data_type` `regtype` (references [`pg_type`](https://www.postgresql.org/docs/current/catalog-pg-type.html "52.64. pg_type")
.`oid`)

Data type of the sequence | | `start_value` `int8`

Start value of the sequence | | `min_value` `int8`

Minimum value of the sequence | | `max_value` `int8`

Maximum value of the sequence | | `increment_by` `int8`

Increment value of the sequence | | `cycle` `bool`

Whether the sequence cycles | | `cache_size` `int8`

Cache size of the sequence | | `last_value` `int8`

The last sequence value written to disk. If caching is used, this value can be greater than the last value handed out from the sequence. | The `last_value` column will read as null if any of the following are true: * The sequence has not been read from yet. * The current user does not have `USAGE` or `SELECT` privilege on the sequence. * The sequence is unlogged and the server is a standby. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-seclabels.html "53.23. pg_seclabels") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/current/view-pg-settings.html "53.25. pg_settings") | | 53.23. `pg_seclabels` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 53.25. `pg_settings` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-sequences.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Appendix A. PostgreSQL Error Codes November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/errcodes-appendix.html "PostgreSQL 18 - Appendix A. PostgreSQL Error Codes") ([18](https://www.postgresql.org/docs/18/errcodes-appendix.html "PostgreSQL 18 - Appendix A. PostgreSQL Error Codes") ) / [17](https://www.postgresql.org/docs/17/errcodes-appendix.html "PostgreSQL 17 - Appendix A. PostgreSQL Error Codes") / [16](https://www.postgresql.org/docs/16/errcodes-appendix.html "PostgreSQL 16 - Appendix A. PostgreSQL Error Codes") / [15](https://www.postgresql.org/docs/15/errcodes-appendix.html "PostgreSQL 15 - Appendix A. PostgreSQL Error Codes") / [14](https://www.postgresql.org/docs/14/errcodes-appendix.html "PostgreSQL 14 - Appendix A. PostgreSQL Error Codes") Development Versions: [devel](https://www.postgresql.org/docs/devel/errcodes-appendix.html "PostgreSQL devel - Appendix A. PostgreSQL Error Codes") Unsupported versions: [13](https://www.postgresql.org/docs/13/errcodes-appendix.html "PostgreSQL 13 - Appendix A. PostgreSQL Error Codes") / [12](https://www.postgresql.org/docs/12/errcodes-appendix.html "PostgreSQL 12 - Appendix A. PostgreSQL Error Codes") / [11](https://www.postgresql.org/docs/11/errcodes-appendix.html "PostgreSQL 11 - Appendix A. PostgreSQL Error Codes") / [10](https://www.postgresql.org/docs/10/errcodes-appendix.html "PostgreSQL 10 - Appendix A. PostgreSQL Error Codes") / [9.6](https://www.postgresql.org/docs/9.6/errcodes-appendix.html "PostgreSQL 9.6 - Appendix A. PostgreSQL Error Codes") / [9.5](https://www.postgresql.org/docs/9.5/errcodes-appendix.html "PostgreSQL 9.5 - Appendix A. PostgreSQL Error Codes") / [9.4](https://www.postgresql.org/docs/9.4/errcodes-appendix.html "PostgreSQL 9.4 - Appendix A. PostgreSQL Error Codes") / [9.3](https://www.postgresql.org/docs/9.3/errcodes-appendix.html "PostgreSQL 9.3 - Appendix A. PostgreSQL Error Codes") / [9.2](https://www.postgresql.org/docs/9.2/errcodes-appendix.html "PostgreSQL 9.2 - Appendix A. PostgreSQL Error Codes") / [9.1](https://www.postgresql.org/docs/9.1/errcodes-appendix.html "PostgreSQL 9.1 - Appendix A. PostgreSQL Error Codes") / [9.0](https://www.postgresql.org/docs/9.0/errcodes-appendix.html "PostgreSQL 9.0 - Appendix A. PostgreSQL Error Codes") / [8.4](https://www.postgresql.org/docs/8.4/errcodes-appendix.html "PostgreSQL 8.4 - Appendix A. PostgreSQL Error Codes") / [8.3](https://www.postgresql.org/docs/8.3/errcodes-appendix.html "PostgreSQL 8.3 - Appendix A. PostgreSQL Error Codes") / [8.2](https://www.postgresql.org/docs/8.2/errcodes-appendix.html "PostgreSQL 8.2 - Appendix A. PostgreSQL Error Codes") / [8.1](https://www.postgresql.org/docs/8.1/errcodes-appendix.html "PostgreSQL 8.1 - Appendix A. PostgreSQL Error Codes") / [8.0](https://www.postgresql.org/docs/8.0/errcodes-appendix.html "PostgreSQL 8.0 - Appendix A. PostgreSQL Error Codes") / [7.4](https://www.postgresql.org/docs/7.4/errcodes-appendix.html "PostgreSQL 7.4 - Appendix A. PostgreSQL Error Codes") | Appendix A. PostgreSQL Error Codes | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/appendixes.html "Part VIII. Appendixes") | [Up](https://www.postgresql.org/docs/18/appendixes.html "Part VIII. Appendixes") | Part VIII. Appendixes | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/datetime-appendix.html "Appendix B. Date/Time Support") | * * * Appendix A. PostgreSQL Error Codes ---------------------------------- All messages emitted by the PostgreSQL server are assigned five-character error codes that follow the SQL standard's conventions for “SQLSTATE” codes. Applications that need to know which error condition has occurred should usually test the error code, rather than looking at the textual error message. The error codes are less likely to change across PostgreSQL releases, and also are not subject to change due to localization of error messages. Note that some, but not all, of the error codes produced by PostgreSQL are defined by the SQL standard; some additional error codes for conditions not defined by the standard have been invented or borrowed from other databases. According to the standard, the first two characters of an error code denote a class of errors, while the last three characters indicate a specific condition within that class. Thus, an application that does not recognize the specific error code might still be able to infer what to do from the error class. [Table A.1](https://www.postgresql.org/docs/18/errcodes-appendix.html#ERRCODES-TABLE "Table A.1. PostgreSQL Error Codes") lists all the error codes defined in PostgreSQL 18.1. (Some are not actually used at present, but are defined by the SQL standard.) The error classes are also shown. For each error class there is a “standard” error code having the last three characters `000`. This code is used only for error conditions that fall within the class but do not have any more-specific code assigned. The symbol shown in the column “Condition Name” is the condition name to use in PL/pgSQL. Condition names can be written in either upper or lower case. (Note that PL/pgSQL does not recognize warning, as opposed to error, condition names; those are classes 00, 01, and 02.) For some types of errors, the server reports the name of a database object (a table, table column, data type, or constraint) associated with the error; for example, the name of the unique constraint that caused a `unique_violation` error. Such names are supplied in separate fields of the error report message so that applications need not try to extract them from the possibly-localized human-readable text of the message. As of PostgreSQL 9.3, complete coverage for this feature exists only for errors in SQLSTATE class 23 (integrity constraint violation), but this is likely to be expanded in future. **Table A.1. PostgreSQL Error Codes** | Error Code | Condition Name | | --- | --- | | **Class 00 — Successful Completion** | | | `00000` | `successful_completion` | | **Class 01 — Warning** | | | `01000` | `warning` | | `0100C` | `dynamic_result_sets_returned` | | `01008` | `implicit_zero_bit_padding` | | `01003` | `null_value_eliminated_in_set_function` | | `01007` | `privilege_not_granted` | | `01006` | `privilege_not_revoked` | | `01004` | `string_data_right_truncation` | | `01P01` | `deprecated_feature` | | **Class 02 — No Data (this is also a warning class per the SQL standard)** | | | `02000` | `no_data` | | `02001` | `no_additional_dynamic_result_sets_returned` | | **Class 03 — SQL Statement Not Yet Complete** | | | `03000` | `sql_statement_not_yet_complete` | | **Class 08 — Connection Exception** | | | `08000` | `connection_exception` | | `08003` | `connection_does_not_exist` | | `08006` | `connection_failure` | | `08001` | `sqlclient_unable_to_establish_sqlconnection` | | `08004` | `sqlserver_rejected_establishment_of_sqlconnection` | | `08007` | `transaction_resolution_unknown` | | `08P01` | `protocol_violation` | | **Class 09 — Triggered Action Exception** | | | `09000` | `triggered_action_exception` | | **Class 0A — Feature Not Supported** | | | `0A000` | `feature_not_supported` | | **Class 0B — Invalid Transaction Initiation** | | | `0B000` | `invalid_transaction_initiation` | | **Class 0F — Locator Exception** | | | `0F000` | `locator_exception` | | `0F001` | `invalid_locator_specification` | | **Class 0L — Invalid Grantor** | | | `0L000` | `invalid_grantor` | | `0LP01` | `invalid_grant_operation` | | **Class 0P — Invalid Role Specification** | | | `0P000` | `invalid_role_specification` | | **Class 0Z — Diagnostics Exception** | | | `0Z000` | `diagnostics_exception` | | `0Z002` | `stacked_diagnostics_accessed_without_active_handler` | | **Class 10 — XQuery Error** | | | `10608` | `invalid_argument_for_xquery` | | **Class 20 — Case Not Found** | | | `20000` | `case_not_found` | | **Class 21 — Cardinality Violation** | | | `21000` | `cardinality_violation` | | **Class 22 — Data Exception** | | | `22000` | `data_exception` | | `2202E` | `array_subscript_error` | | `22021` | `character_not_in_repertoire` | | `22008` | `datetime_field_overflow` | | `22012` | `division_by_zero` | | `22005` | `error_in_assignment` | | `2200B` | `escape_character_conflict` | | `22022` | `indicator_overflow` | | `22015` | `interval_field_overflow` | | `2201E` | `invalid_argument_for_logarithm` | | `22014` | `invalid_argument_for_ntile_function` | | `22016` | `invalid_argument_for_nth_value_function` | | `2201F` | `invalid_argument_for_power_function` | | `2201G` | `invalid_argument_for_width_bucket_function` | | `22018` | `invalid_character_value_for_cast` | | `22007` | `invalid_datetime_format` | | `22019` | `invalid_escape_character` | | `2200D` | `invalid_escape_octet` | | `22025` | `invalid_escape_sequence` | | `22P06` | `nonstandard_use_of_escape_character` | | `22010` | `invalid_indicator_parameter_value` | | `22023` | `invalid_parameter_value` | | `22013` | `invalid_preceding_or_following_size` | | `2201B` | `invalid_regular_expression` | | `2201W` | `invalid_row_count_in_limit_clause` | | `2201X` | `invalid_row_count_in_result_offset_clause` | | `2202H` | `invalid_tablesample_argument` | | `2202G` | `invalid_tablesample_repeat` | | `22009` | `invalid_time_zone_displacement_value` | | `2200C` | `invalid_use_of_escape_character` | | `2200G` | `most_specific_type_mismatch` | | `22004` | `null_value_not_allowed` | | `22002` | `null_value_no_indicator_parameter` | | `22003` | `numeric_value_out_of_range` | | `2200H` | `sequence_generator_limit_exceeded` | | `22026` | `string_data_length_mismatch` | | `22001` | `string_data_right_truncation` | | `22011` | `substring_error` | | `22027` | `trim_error` | | `22024` | `unterminated_c_string` | | `2200F` | `zero_length_character_string` | | `22P01` | `floating_point_exception` | | `22P02` | `invalid_text_representation` | | `22P03` | `invalid_binary_representation` | | `22P04` | `bad_copy_file_format` | | `22P05` | `untranslatable_character` | | `2200L` | `not_an_xml_document` | | `2200M` | `invalid_xml_document` | | `2200N` | `invalid_xml_content` | | `2200S` | `invalid_xml_comment` | | `2200T` | `invalid_xml_processing_instruction` | | `22030` | `duplicate_json_object_key_value` | | `22031` | `invalid_argument_for_sql_json_datetime_function` | | `22032` | `invalid_json_text` | | `22033` | `invalid_sql_json_subscript` | | `22034` | `more_than_one_sql_json_item` | | `22035` | `no_sql_json_item` | | `22036` | `non_numeric_sql_json_item` | | `22037` | `non_unique_keys_in_a_json_object` | | `22038` | `singleton_sql_json_item_required` | | `22039` | `sql_json_array_not_found` | | `2203A` | `sql_json_member_not_found` | | `2203B` | `sql_json_number_not_found` | | `2203C` | `sql_json_object_not_found` | | `2203D` | `too_many_json_array_elements` | | `2203E` | `too_many_json_object_members` | | `2203F` | `sql_json_scalar_required` | | `2203G` | `sql_json_item_cannot_be_cast_to_target_type` | | **Class 23 — Integrity Constraint Violation** | | | `23000` | `integrity_constraint_violation` | | `23001` | `restrict_violation` | | `23502` | `not_null_violation` | | `23503` | `foreign_key_violation` | | `23505` | `unique_violation` | | `23514` | `check_violation` | | `23P01` | `exclusion_violation` | | **Class 24 — Invalid Cursor State** | | | `24000` | `invalid_cursor_state` | | **Class 25 — Invalid Transaction State** | | | `25000` | `invalid_transaction_state` | | `25001` | `active_sql_transaction` | | `25002` | `branch_transaction_already_active` | | `25008` | `held_cursor_requires_same_isolation_level` | | `25003` | `inappropriate_access_mode_for_branch_transaction` | | `25004` | `inappropriate_isolation_level_for_branch_transaction` | | `25005` | `no_active_sql_transaction_for_branch_transaction` | | `25006` | `read_only_sql_transaction` | | `25007` | `schema_and_data_statement_mixing_not_supported` | | `25P01` | `no_active_sql_transaction` | | `25P02` | `in_failed_sql_transaction` | | `25P03` | `idle_in_transaction_session_timeout` | | `25P04` | `transaction_timeout` | | **Class 26 — Invalid SQL Statement Name** | | | `26000` | `invalid_sql_statement_name` | | **Class 27 — Triggered Data Change Violation** | | | `27000` | `triggered_data_change_violation` | | **Class 28 — Invalid Authorization Specification** | | | `28000` | `invalid_authorization_specification` | | `28P01` | `invalid_password` | | **Class 2B — Dependent Privilege Descriptors Still Exist** | | | `2B000` | `dependent_privilege_descriptors_still_exist` | | `2BP01` | `dependent_objects_still_exist` | | **Class 2D — Invalid Transaction Termination** | | | `2D000` | `invalid_transaction_termination` | | **Class 2F — SQL Routine Exception** | | | `2F000` | `sql_routine_exception` | | `2F005` | `function_executed_no_return_statement` | | `2F002` | `modifying_sql_data_not_permitted` | | `2F003` | `prohibited_sql_statement_attempted` | | `2F004` | `reading_sql_data_not_permitted` | | **Class 34 — Invalid Cursor Name** | | | `34000` | `invalid_cursor_name` | | **Class 38 — External Routine Exception** | | | `38000` | `external_routine_exception` | | `38001` | `containing_sql_not_permitted` | | `38002` | `modifying_sql_data_not_permitted` | | `38003` | `prohibited_sql_statement_attempted` | | `38004` | `reading_sql_data_not_permitted` | | **Class 39 — External Routine Invocation Exception** | | | `39000` | `external_routine_invocation_exception` | | `39001` | `invalid_sqlstate_returned` | | `39004` | `null_value_not_allowed` | | `39P01` | `trigger_protocol_violated` | | `39P02` | `srf_protocol_violated` | | `39P03` | `event_trigger_protocol_violated` | | **Class 3B — Savepoint Exception** | | | `3B000` | `savepoint_exception` | | `3B001` | `invalid_savepoint_specification` | | **Class 3D — Invalid Catalog Name** | | | `3D000` | `invalid_catalog_name` | | **Class 3F — Invalid Schema Name** | | | `3F000` | `invalid_schema_name` | | **Class 40 — Transaction Rollback** | | | `40000` | `transaction_rollback` | | `40002` | `transaction_integrity_constraint_violation` | | `40001` | `serialization_failure` | | `40003` | `statement_completion_unknown` | | `40P01` | `deadlock_detected` | | **Class 42 — Syntax Error or Access Rule Violation** | | | `42000` | `syntax_error_or_access_rule_violation` | | `42601` | `syntax_error` | | `42501` | `insufficient_privilege` | | `42846` | `cannot_coerce` | | `42803` | `grouping_error` | | `42P20` | `windowing_error` | | `42P19` | `invalid_recursion` | | `42830` | `invalid_foreign_key` | | `42602` | `invalid_name` | | `42622` | `name_too_long` | | `42939` | `reserved_name` | | `42804` | `datatype_mismatch` | | `42P18` | `indeterminate_datatype` | | `42P21` | `collation_mismatch` | | `42P22` | `indeterminate_collation` | | `42809` | `wrong_object_type` | | `428C9` | `generated_always` | | `42703` | `undefined_column` | | `42883` | `undefined_function` | | `42P01` | `undefined_table` | | `42P02` | `undefined_parameter` | | `42704` | `undefined_object` | | `42701` | `duplicate_column` | | `42P03` | `duplicate_cursor` | | `42P04` | `duplicate_database` | | `42723` | `duplicate_function` | | `42P05` | `duplicate_prepared_statement` | | `42P06` | `duplicate_schema` | | `42P07` | `duplicate_table` | | `42712` | `duplicate_alias` | | `42710` | `duplicate_object` | | `42702` | `ambiguous_column` | | `42725` | `ambiguous_function` | | `42P08` | `ambiguous_parameter` | | `42P09` | `ambiguous_alias` | | `42P10` | `invalid_column_reference` | | `42611` | `invalid_column_definition` | | `42P11` | `invalid_cursor_definition` | | `42P12` | `invalid_database_definition` | | `42P13` | `invalid_function_definition` | | `42P14` | `invalid_prepared_statement_definition` | | `42P15` | `invalid_schema_definition` | | `42P16` | `invalid_table_definition` | | `42P17` | `invalid_object_definition` | | **Class 44 — WITH CHECK OPTION Violation** | | | `44000` | `with_check_option_violation` | | **Class 53 — Insufficient Resources** | | | `53000` | `insufficient_resources` | | `53100` | `disk_full` | | `53200` | `out_of_memory` | | `53300` | `too_many_connections` | | `53400` | `configuration_limit_exceeded` | | **Class 54 — Program Limit Exceeded** | | | `54000` | `program_limit_exceeded` | | `54001` | `statement_too_complex` | | `54011` | `too_many_columns` | | `54023` | `too_many_arguments` | | **Class 55 — Object Not In Prerequisite State** | | | `55000` | `object_not_in_prerequisite_state` | | `55006` | `object_in_use` | | `55P02` | `cant_change_runtime_param` | | `55P03` | `lock_not_available` | | `55P04` | `unsafe_new_enum_value_usage` | | **Class 57 — Operator Intervention** | | | `57000` | `operator_intervention` | | `57014` | `query_canceled` | | `57P01` | `admin_shutdown` | | `57P02` | `crash_shutdown` | | `57P03` | `cannot_connect_now` | | `57P04` | `database_dropped` | | `57P05` | `idle_session_timeout` | | **Class 58 — System Error (errors external to PostgreSQL itself)** | | | `58000` | `system_error` | | `58030` | `io_error` | | `58P01` | `undefined_file` | | `58P02` | `duplicate_file` | | `58P03` | `file_name_too_long` | | **Class F0 — Configuration File Error** | | | `F0000` | `config_file_error` | | `F0001` | `lock_file_exists` | | **Class HV — Foreign Data Wrapper Error (SQL/MED)** | | | `HV000` | `fdw_error` | | `HV005` | `fdw_column_name_not_found` | | `HV002` | `fdw_dynamic_parameter_value_needed` | | `HV010` | `fdw_function_sequence_error` | | `HV021` | `fdw_inconsistent_descriptor_information` | | `HV024` | `fdw_invalid_attribute_value` | | `HV007` | `fdw_invalid_column_name` | | `HV008` | `fdw_invalid_column_number` | | `HV004` | `fdw_invalid_data_type` | | `HV006` | `fdw_invalid_data_type_descriptors` | | `HV091` | `fdw_invalid_descriptor_field_identifier` | | `HV00B` | `fdw_invalid_handle` | | `HV00C` | `fdw_invalid_option_index` | | `HV00D` | `fdw_invalid_option_name` | | `HV090` | `fdw_invalid_string_length_or_buffer_length` | | `HV00A` | `fdw_invalid_string_format` | | `HV009` | `fdw_invalid_use_of_null_pointer` | | `HV014` | `fdw_too_many_handles` | | `HV001` | `fdw_out_of_memory` | | `HV00P` | `fdw_no_schemas` | | `HV00J` | `fdw_option_name_not_found` | | `HV00K` | `fdw_reply_handle` | | `HV00Q` | `fdw_schema_not_found` | | `HV00R` | `fdw_table_not_found` | | `HV00L` | `fdw_unable_to_create_execution` | | `HV00M` | `fdw_unable_to_create_reply` | | `HV00N` | `fdw_unable_to_establish_connection` | | **Class P0 — PL/pgSQL Error** | | | `P0000` | `plpgsql_error` | | `P0001` | `raise_exception` | | `P0002` | `no_data_found` | | `P0003` | `too_many_rows` | | `P0004` | `assert_failure` | | **Class XX — Internal Error** | | | `XX000` | `internal_error` | | `XX001` | `data_corrupted` | | `XX002` | `index_corrupted` | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/appendixes.html "Part VIII. Appendixes") | [Up](https://www.postgresql.org/docs/18/appendixes.html "Part VIII. Appendixes") | [Next](https://www.postgresql.org/docs/18/datetime-appendix.html "Appendix B. Date/Time Support") | | Part VIII. Appendixes | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | Appendix B. Date/Time Support | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/errcodes-appendix.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 10.6. SELECT Output Columns November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/typeconv-select.html "PostgreSQL 18 - 10.6. SELECT Output Columns") ([18](https://www.postgresql.org/docs/18/typeconv-select.html "PostgreSQL 18 - 10.6. SELECT Output Columns") ) / [17](https://www.postgresql.org/docs/17/typeconv-select.html "PostgreSQL 17 - 10.6. SELECT Output Columns") / [16](https://www.postgresql.org/docs/16/typeconv-select.html "PostgreSQL 16 - 10.6. SELECT Output Columns") / [15](https://www.postgresql.org/docs/15/typeconv-select.html "PostgreSQL 15 - 10.6. SELECT Output Columns") / [14](https://www.postgresql.org/docs/14/typeconv-select.html "PostgreSQL 14 - 10.6. SELECT Output Columns") Development Versions: [devel](https://www.postgresql.org/docs/devel/typeconv-select.html "PostgreSQL devel - 10.6. SELECT Output Columns") Unsupported versions: [13](https://www.postgresql.org/docs/13/typeconv-select.html "PostgreSQL 13 - 10.6. SELECT Output Columns") / [12](https://www.postgresql.org/docs/12/typeconv-select.html "PostgreSQL 12 - 10.6. SELECT Output Columns") / [11](https://www.postgresql.org/docs/11/typeconv-select.html "PostgreSQL 11 - 10.6. SELECT Output Columns") / [10](https://www.postgresql.org/docs/10/typeconv-select.html "PostgreSQL 10 - 10.6. SELECT Output Columns") | 10.6. `SELECT` Output Columns | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/typeconv-union-case.html "10.5. UNION, CASE, and Related Constructs") | [Up](https://www.postgresql.org/docs/18/typeconv.html "Chapter 10. Type Conversion") | Chapter 10. Type Conversion | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/indexes.html "Chapter 11. Indexes") | * * * 10.6. `SELECT` Output Columns [#](https://www.postgresql.org/docs/18/typeconv-select.html#TYPECONV-SELECT) ----------------------------------------------------------------------------------------------------------- The rules given in the preceding sections will result in assignment of non-`unknown` data types to all expressions in an SQL query, except for unspecified-type literals that appear as simple output columns of a `SELECT` command. For example, in SELECT 'Hello World'; there is nothing to identify what type the string literal should be taken as. In this situation PostgreSQL will fall back to resolving the literal's type as `text`. When the `SELECT` is one arm of a `UNION` (or `INTERSECT` or `EXCEPT`) construct, or when it appears within `INSERT ... SELECT`, this rule is not applied since rules given in preceding sections take precedence. The type of an unspecified-type literal can be taken from the other `UNION` arm in the first case, or from the destination column in the second case. `RETURNING` lists are treated the same as `SELECT` output lists for this purpose. ### Note Prior to PostgreSQL 10, this rule did not exist, and unspecified-type literals in a `SELECT` output list were left as type `unknown`. That had assorted bad consequences, so it's been changed. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/typeconv-union-case.html "10.5. UNION, CASE, and Related Constructs") | [Up](https://www.postgresql.org/docs/18/typeconv.html "Chapter 10. Type Conversion") | [Next](https://www.postgresql.org/docs/18/indexes.html "Chapter 11. Indexes") | | 10.5. `UNION`, `CASE`, and Related Constructs | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | Chapter 11. Indexes | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/typeconv-select.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.7. character_sets November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-character-sets.html "PostgreSQL 18 - 35.7. character_sets") ([18](https://www.postgresql.org/docs/18/infoschema-character-sets.html "PostgreSQL 18 - 35.7. character_sets") ) / [17](https://www.postgresql.org/docs/17/infoschema-character-sets.html "PostgreSQL 17 - 35.7. character_sets") / [16](https://www.postgresql.org/docs/16/infoschema-character-sets.html "PostgreSQL 16 - 35.7. character_sets") / [15](https://www.postgresql.org/docs/15/infoschema-character-sets.html "PostgreSQL 15 - 35.7. character_sets") / [14](https://www.postgresql.org/docs/14/infoschema-character-sets.html "PostgreSQL 14 - 35.7. character_sets") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-character-sets.html "PostgreSQL devel - 35.7. character_sets") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-character-sets.html "PostgreSQL 13 - 35.7. character_sets") / [12](https://www.postgresql.org/docs/12/infoschema-character-sets.html "PostgreSQL 12 - 35.7. character_sets") / [11](https://www.postgresql.org/docs/11/infoschema-character-sets.html "PostgreSQL 11 - 35.7. character_sets") / [10](https://www.postgresql.org/docs/10/infoschema-character-sets.html "PostgreSQL 10 - 35.7. character_sets") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-character-sets.html "PostgreSQL 9.6 - 35.7. character_sets") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-character-sets.html "PostgreSQL 9.5 - 35.7. character_sets") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-character-sets.html "PostgreSQL 9.4 - 35.7. character_sets") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-character-sets.html "PostgreSQL 9.3 - 35.7. character_sets") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-character-sets.html "PostgreSQL 9.2 - 35.7. character_sets") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-character-sets.html "PostgreSQL 9.1 - 35.7. character_sets") | 35.7. `character_sets` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-attributes.html "35.6. attributes") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/infoschema-check-constraint-routine-usage.html "35.8. check_constraint_routine_usage") | * * * 35.7. `character_sets` [#](https://www.postgresql.org/docs/current/infoschema-character-sets.html#INFOSCHEMA-CHARACTER-SETS) ----------------------------------------------------------------------------------------------------------------------------- The view `character_sets` identifies the character sets available in the current database. Since PostgreSQL does not support multiple character sets within one database, this view only shows one, which is the database encoding. Take note of how the following terms are used in the SQL standard: character repertoire An abstract collection of characters, for example `UNICODE`, `UCS`, or `LATIN1`. Not exposed as an SQL object, but visible in this view. character encoding form An encoding of some character repertoire. Most older character repertoires only use one encoding form, and so there are no separate names for them (e.g., `LATIN2` is an encoding form applicable to the `LATIN2` repertoire). But for example Unicode has the encoding forms `UTF8`, `UTF16`, etc. (not all supported by PostgreSQL). Encoding forms are not exposed as an SQL object, but are visible in this view. character set A named SQL object that identifies a character repertoire, a character encoding, and a default collation. A predefined character set would typically have the same name as an encoding form, but users could define other names. For example, the character set `UTF8` would typically identify the character repertoire `UCS`, encoding form `UTF8`, and some default collation. You can think of an “encoding” in PostgreSQL either as a character set or a character encoding form. They will have the same name, and there can only be one in one database. **Table 35.5. `character_sets` Columns** | Column Type

Description | | --- | | `character_set_catalog` `sql_identifier`

Character sets are currently not implemented as schema objects, so this column is null. | | `character_set_schema` `sql_identifier`

Character sets are currently not implemented as schema objects, so this column is null. | | `character_set_name` `sql_identifier`

Name of the character set, currently implemented as showing the name of the database encoding | | `character_repertoire` `sql_identifier`

Character repertoire, showing `UCS` if the encoding is `UTF8`, else just the encoding name | | `form_of_use` `sql_identifier`

Character encoding form, same as the database encoding | | `default_collate_catalog` `sql_identifier`

Name of the database containing the default collation (always the current database, if any collation is identified) | | `default_collate_schema` `sql_identifier`

Name of the schema containing the default collation | | `default_collate_name` `sql_identifier`

Name of the default collation. The default collation is identified as the collation that matches the `COLLATE` and `CTYPE` settings of the current database. If there is no such collation, then this column and the associated schema and catalog columns are null. | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/infoschema-attributes.html "35.6. attributes") | [Up](https://www.postgresql.org/docs/current/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/current/infoschema-check-constraint-routine-usage.html "35.8. check_constraint_routine_usage") | | 35.6. `attributes` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 35.8. `check_constraint_routine_usage` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-character-sets.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 10.6. SELECT Output Columns November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/typeconv-select.html "PostgreSQL 18 - 10.6. SELECT Output Columns") ([18](https://www.postgresql.org/docs/18/typeconv-select.html "PostgreSQL 18 - 10.6. SELECT Output Columns") ) / [17](https://www.postgresql.org/docs/17/typeconv-select.html "PostgreSQL 17 - 10.6. SELECT Output Columns") / [16](https://www.postgresql.org/docs/16/typeconv-select.html "PostgreSQL 16 - 10.6. SELECT Output Columns") / [15](https://www.postgresql.org/docs/15/typeconv-select.html "PostgreSQL 15 - 10.6. SELECT Output Columns") / [14](https://www.postgresql.org/docs/14/typeconv-select.html "PostgreSQL 14 - 10.6. SELECT Output Columns") Development Versions: [devel](https://www.postgresql.org/docs/devel/typeconv-select.html "PostgreSQL devel - 10.6. SELECT Output Columns") Unsupported versions: [13](https://www.postgresql.org/docs/13/typeconv-select.html "PostgreSQL 13 - 10.6. SELECT Output Columns") / [12](https://www.postgresql.org/docs/12/typeconv-select.html "PostgreSQL 12 - 10.6. SELECT Output Columns") / [11](https://www.postgresql.org/docs/11/typeconv-select.html "PostgreSQL 11 - 10.6. SELECT Output Columns") / [10](https://www.postgresql.org/docs/10/typeconv-select.html "PostgreSQL 10 - 10.6. SELECT Output Columns") | 10.6. `SELECT` Output Columns | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/typeconv-union-case.html "10.5. UNION, CASE, and Related Constructs") | [Up](https://www.postgresql.org/docs/current/typeconv.html "Chapter 10. Type Conversion") | Chapter 10. Type Conversion | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/indexes.html "Chapter 11. Indexes") | * * * 10.6. `SELECT` Output Columns [#](https://www.postgresql.org/docs/current/typeconv-select.html#TYPECONV-SELECT) ---------------------------------------------------------------------------------------------------------------- The rules given in the preceding sections will result in assignment of non-`unknown` data types to all expressions in an SQL query, except for unspecified-type literals that appear as simple output columns of a `SELECT` command. For example, in SELECT 'Hello World'; there is nothing to identify what type the string literal should be taken as. In this situation PostgreSQL will fall back to resolving the literal's type as `text`. When the `SELECT` is one arm of a `UNION` (or `INTERSECT` or `EXCEPT`) construct, or when it appears within `INSERT ... SELECT`, this rule is not applied since rules given in preceding sections take precedence. The type of an unspecified-type literal can be taken from the other `UNION` arm in the first case, or from the destination column in the second case. `RETURNING` lists are treated the same as `SELECT` output lists for this purpose. ### Note Prior to PostgreSQL 10, this rule did not exist, and unspecified-type literals in a `SELECT` output list were left as type `unknown`. That had assorted bad consequences, so it's been changed. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/typeconv-union-case.html "10.5. UNION, CASE, and Related Constructs") | [Up](https://www.postgresql.org/docs/current/typeconv.html "Chapter 10. Type Conversion") | [Next](https://www.postgresql.org/docs/current/indexes.html "Chapter 11. Indexes") | | 10.5. `UNION`, `CASE`, and Related Constructs | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Chapter 11. Indexes | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/typeconv-select.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: pg_isready November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/app-pg-isready.html "PostgreSQL 18 - pg_isready") ([18](https://www.postgresql.org/docs/18/app-pg-isready.html "PostgreSQL 18 - pg_isready") ) / [17](https://www.postgresql.org/docs/17/app-pg-isready.html "PostgreSQL 17 - pg_isready") / [16](https://www.postgresql.org/docs/16/app-pg-isready.html "PostgreSQL 16 - pg_isready") / [15](https://www.postgresql.org/docs/15/app-pg-isready.html "PostgreSQL 15 - pg_isready") / [14](https://www.postgresql.org/docs/14/app-pg-isready.html "PostgreSQL 14 - pg_isready") Development Versions: [devel](https://www.postgresql.org/docs/devel/app-pg-isready.html "PostgreSQL devel - pg_isready") Unsupported versions: [13](https://www.postgresql.org/docs/13/app-pg-isready.html "PostgreSQL 13 - pg_isready") / [12](https://www.postgresql.org/docs/12/app-pg-isready.html "PostgreSQL 12 - pg_isready") / [11](https://www.postgresql.org/docs/11/app-pg-isready.html "PostgreSQL 11 - pg_isready") / [10](https://www.postgresql.org/docs/10/app-pg-isready.html "PostgreSQL 10 - pg_isready") / [9.6](https://www.postgresql.org/docs/9.6/app-pg-isready.html "PostgreSQL 9.6 - pg_isready") / [9.5](https://www.postgresql.org/docs/9.5/app-pg-isready.html "PostgreSQL 9.5 - pg_isready") / [9.4](https://www.postgresql.org/docs/9.4/app-pg-isready.html "PostgreSQL 9.4 - pg_isready") / [9.3](https://www.postgresql.org/docs/9.3/app-pg-isready.html "PostgreSQL 9.3 - pg_isready") | pg\_isready | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/app-pg-dumpall.html "pg_dumpall") | [Up](https://www.postgresql.org/docs/18/reference-client.html "PostgreSQL Client Applications") | PostgreSQL Client Applications | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/app-pgreceivewal.html "pg_receivewal") | * * * pg\_isready ----------- pg\_isready — check the connection status of a PostgreSQL server Synopsis -------- `pg_isready` \[_`connection-option`_...\] \[_`option`_...\] Description ----------- pg\_isready is a utility for checking the connection status of a PostgreSQL database server. The exit status specifies the result of the connection check. Options ------- ``-d _`dbname`_`` ``--dbname=_`dbname`_`` Specifies the name of the database to connect to. The _`dbname`_ can be a [connection string](https://www.postgresql.org/docs/18/libpq-connect.html#LIBPQ-CONNSTRING "32.1.1. Connection Strings") . If so, connection string parameters will override any conflicting command line options. ``-h _`hostname`_`` ``--host=_`hostname`_`` Specifies the host name of the machine on which the server is running. If the value begins with a slash, it is used as the directory for the Unix-domain socket. ``-p _`port`_`` ``--port=_`port`_`` Specifies the TCP port or the local Unix-domain socket file extension on which the server is listening for connections. Defaults to the value of the `PGPORT` environment variable or, if not set, to the port specified at compile time, usually 5432. `-q` `--quiet` Do not display status message. This is useful when scripting. ``-t _`seconds`_`` ``--timeout=_`seconds`_`` The maximum number of seconds to wait when attempting connection before returning that the server is not responding. Setting to 0 disables. The default is 3 seconds. ``-U _`username`_`` ``--username=_`username`_`` Connect to the database as the user _`username`_ instead of the default. `-V` `--version` Print the pg\_isready version and exit. `-?` `--help` Show help about pg\_isready command line arguments, and exit. Exit Status ----------- pg\_isready returns `0` to the shell if the server is accepting connections normally, `1` if the server is rejecting connections (for example during startup), `2` if there was no response to the connection attempt, and `3` if no attempt was made (for example due to invalid parameters). Environment ----------- `pg_isready`, like most other PostgreSQL utilities, also uses the environment variables supported by libpq (see [Section 32.15](https://www.postgresql.org/docs/18/libpq-envars.html "32.15. Environment Variables") ). The environment variable `PG_COLOR` specifies whether to use color in diagnostic messages. Possible values are `always`, `auto` and `never`. Notes ----- It is not necessary to supply correct user name, password, or database name values to obtain the server status; however, if incorrect values are provided, the server will log a failed connection attempt. Examples -------- Standard Usage: $ Running with connection parameters to a PostgreSQL cluster in startup: $ Running with connection parameters to a non-responsive PostgreSQL cluster: $ * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/app-pg-dumpall.html "pg_dumpall") | [Up](https://www.postgresql.org/docs/18/reference-client.html "PostgreSQL Client Applications") | [Next](https://www.postgresql.org/docs/18/app-pgreceivewal.html "pg_receivewal") | | pg\_dumpall | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | pg\_receivewal | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/app-pg-isready.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: pg_isready November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/app-pg-isready.html "PostgreSQL 18 - pg_isready") ([18](https://www.postgresql.org/docs/18/app-pg-isready.html "PostgreSQL 18 - pg_isready") ) / [17](https://www.postgresql.org/docs/17/app-pg-isready.html "PostgreSQL 17 - pg_isready") / [16](https://www.postgresql.org/docs/16/app-pg-isready.html "PostgreSQL 16 - pg_isready") / [15](https://www.postgresql.org/docs/15/app-pg-isready.html "PostgreSQL 15 - pg_isready") / [14](https://www.postgresql.org/docs/14/app-pg-isready.html "PostgreSQL 14 - pg_isready") Development Versions: [devel](https://www.postgresql.org/docs/devel/app-pg-isready.html "PostgreSQL devel - pg_isready") Unsupported versions: [13](https://www.postgresql.org/docs/13/app-pg-isready.html "PostgreSQL 13 - pg_isready") / [12](https://www.postgresql.org/docs/12/app-pg-isready.html "PostgreSQL 12 - pg_isready") / [11](https://www.postgresql.org/docs/11/app-pg-isready.html "PostgreSQL 11 - pg_isready") / [10](https://www.postgresql.org/docs/10/app-pg-isready.html "PostgreSQL 10 - pg_isready") / [9.6](https://www.postgresql.org/docs/9.6/app-pg-isready.html "PostgreSQL 9.6 - pg_isready") / [9.5](https://www.postgresql.org/docs/9.5/app-pg-isready.html "PostgreSQL 9.5 - pg_isready") / [9.4](https://www.postgresql.org/docs/9.4/app-pg-isready.html "PostgreSQL 9.4 - pg_isready") / [9.3](https://www.postgresql.org/docs/9.3/app-pg-isready.html "PostgreSQL 9.3 - pg_isready") | pg\_isready | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/app-pg-dumpall.html "pg_dumpall") | [Up](https://www.postgresql.org/docs/current/reference-client.html "PostgreSQL Client Applications") | PostgreSQL Client Applications | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/app-pgreceivewal.html "pg_receivewal") | * * * pg\_isready ----------- pg\_isready — check the connection status of a PostgreSQL server Synopsis -------- `pg_isready` \[_`connection-option`_...\] \[_`option`_...\] Description ----------- pg\_isready is a utility for checking the connection status of a PostgreSQL database server. The exit status specifies the result of the connection check. Options ------- ``-d _`dbname`_`` ``--dbname=_`dbname`_`` Specifies the name of the database to connect to. The _`dbname`_ can be a [connection string](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING "32.1.1. Connection Strings") . If so, connection string parameters will override any conflicting command line options. ``-h _`hostname`_`` ``--host=_`hostname`_`` Specifies the host name of the machine on which the server is running. If the value begins with a slash, it is used as the directory for the Unix-domain socket. ``-p _`port`_`` ``--port=_`port`_`` Specifies the TCP port or the local Unix-domain socket file extension on which the server is listening for connections. Defaults to the value of the `PGPORT` environment variable or, if not set, to the port specified at compile time, usually 5432. `-q` `--quiet` Do not display status message. This is useful when scripting. ``-t _`seconds`_`` ``--timeout=_`seconds`_`` The maximum number of seconds to wait when attempting connection before returning that the server is not responding. Setting to 0 disables. The default is 3 seconds. ``-U _`username`_`` ``--username=_`username`_`` Connect to the database as the user _`username`_ instead of the default. `-V` `--version` Print the pg\_isready version and exit. `-?` `--help` Show help about pg\_isready command line arguments, and exit. Exit Status ----------- pg\_isready returns `0` to the shell if the server is accepting connections normally, `1` if the server is rejecting connections (for example during startup), `2` if there was no response to the connection attempt, and `3` if no attempt was made (for example due to invalid parameters). Environment ----------- `pg_isready`, like most other PostgreSQL utilities, also uses the environment variables supported by libpq (see [Section 32.15](https://www.postgresql.org/docs/current/libpq-envars.html "32.15. Environment Variables") ). The environment variable `PG_COLOR` specifies whether to use color in diagnostic messages. Possible values are `always`, `auto` and `never`. Notes ----- It is not necessary to supply correct user name, password, or database name values to obtain the server status; however, if incorrect values are provided, the server will log a failed connection attempt. Examples -------- Standard Usage: $ Running with connection parameters to a PostgreSQL cluster in startup: $ Running with connection parameters to a non-responsive PostgreSQL cluster: $ * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/app-pg-dumpall.html "pg_dumpall") | [Up](https://www.postgresql.org/docs/current/reference-client.html "PostgreSQL Client Applications") | [Next](https://www.postgresql.org/docs/current/app-pgreceivewal.html "pg_receivewal") | | pg\_dumpall | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | pg\_receivewal | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/app-pg-isready.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 35.7. character_sets November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-character-sets.html "PostgreSQL 18 - 35.7. character_sets") ([18](https://www.postgresql.org/docs/18/infoschema-character-sets.html "PostgreSQL 18 - 35.7. character_sets") ) / [17](https://www.postgresql.org/docs/17/infoschema-character-sets.html "PostgreSQL 17 - 35.7. character_sets") / [16](https://www.postgresql.org/docs/16/infoschema-character-sets.html "PostgreSQL 16 - 35.7. character_sets") / [15](https://www.postgresql.org/docs/15/infoschema-character-sets.html "PostgreSQL 15 - 35.7. character_sets") / [14](https://www.postgresql.org/docs/14/infoschema-character-sets.html "PostgreSQL 14 - 35.7. character_sets") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-character-sets.html "PostgreSQL devel - 35.7. character_sets") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-character-sets.html "PostgreSQL 13 - 35.7. character_sets") / [12](https://www.postgresql.org/docs/12/infoschema-character-sets.html "PostgreSQL 12 - 35.7. character_sets") / [11](https://www.postgresql.org/docs/11/infoschema-character-sets.html "PostgreSQL 11 - 35.7. character_sets") / [10](https://www.postgresql.org/docs/10/infoschema-character-sets.html "PostgreSQL 10 - 35.7. character_sets") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-character-sets.html "PostgreSQL 9.6 - 35.7. character_sets") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-character-sets.html "PostgreSQL 9.5 - 35.7. character_sets") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-character-sets.html "PostgreSQL 9.4 - 35.7. character_sets") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-character-sets.html "PostgreSQL 9.3 - 35.7. character_sets") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-character-sets.html "PostgreSQL 9.2 - 35.7. character_sets") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-character-sets.html "PostgreSQL 9.1 - 35.7. character_sets") | 35.7. `character_sets` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-attributes.html "35.6. attributes") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | Chapter 35. The Information Schema | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/infoschema-check-constraint-routine-usage.html "35.8. check_constraint_routine_usage") | * * * 35.7. `character_sets` [#](https://www.postgresql.org/docs/18/infoschema-character-sets.html#INFOSCHEMA-CHARACTER-SETS) ------------------------------------------------------------------------------------------------------------------------ The view `character_sets` identifies the character sets available in the current database. Since PostgreSQL does not support multiple character sets within one database, this view only shows one, which is the database encoding. Take note of how the following terms are used in the SQL standard: character repertoire An abstract collection of characters, for example `UNICODE`, `UCS`, or `LATIN1`. Not exposed as an SQL object, but visible in this view. character encoding form An encoding of some character repertoire. Most older character repertoires only use one encoding form, and so there are no separate names for them (e.g., `LATIN2` is an encoding form applicable to the `LATIN2` repertoire). But for example Unicode has the encoding forms `UTF8`, `UTF16`, etc. (not all supported by PostgreSQL). Encoding forms are not exposed as an SQL object, but are visible in this view. character set A named SQL object that identifies a character repertoire, a character encoding, and a default collation. A predefined character set would typically have the same name as an encoding form, but users could define other names. For example, the character set `UTF8` would typically identify the character repertoire `UCS`, encoding form `UTF8`, and some default collation. You can think of an “encoding” in PostgreSQL either as a character set or a character encoding form. They will have the same name, and there can only be one in one database. **Table 35.5. `character_sets` Columns** | Column Type

Description | | --- | | `character_set_catalog` `sql_identifier`

Character sets are currently not implemented as schema objects, so this column is null. | | `character_set_schema` `sql_identifier`

Character sets are currently not implemented as schema objects, so this column is null. | | `character_set_name` `sql_identifier`

Name of the character set, currently implemented as showing the name of the database encoding | | `character_repertoire` `sql_identifier`

Character repertoire, showing `UCS` if the encoding is `UTF8`, else just the encoding name | | `form_of_use` `sql_identifier`

Character encoding form, same as the database encoding | | `default_collate_catalog` `sql_identifier`

Name of the database containing the default collation (always the current database, if any collation is identified) | | `default_collate_schema` `sql_identifier`

Name of the schema containing the default collation | | `default_collate_name` `sql_identifier`

Name of the default collation. The default collation is identified as the collation that matches the `COLLATE` and `CTYPE` settings of the current database. If there is no such collation, then this column and the associated schema and catalog columns are null. | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/infoschema-attributes.html "35.6. attributes") | [Up](https://www.postgresql.org/docs/18/information-schema.html "Chapter 35. The Information Schema") | [Next](https://www.postgresql.org/docs/18/infoschema-check-constraint-routine-usage.html "35.8. check_constraint_routine_usage") | | 35.6. `attributes` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 35.8. `check_constraint_routine_usage` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/infoschema-character-sets.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: SPI_is_cursor_plan November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/spi-spi-is-cursor-plan.html "PostgreSQL 18 - SPI_is_cursor_plan") ([18](https://www.postgresql.org/docs/18/spi-spi-is-cursor-plan.html "PostgreSQL 18 - SPI_is_cursor_plan") ) / [17](https://www.postgresql.org/docs/17/spi-spi-is-cursor-plan.html "PostgreSQL 17 - SPI_is_cursor_plan") / [16](https://www.postgresql.org/docs/16/spi-spi-is-cursor-plan.html "PostgreSQL 16 - SPI_is_cursor_plan") / [15](https://www.postgresql.org/docs/15/spi-spi-is-cursor-plan.html "PostgreSQL 15 - SPI_is_cursor_plan") / [14](https://www.postgresql.org/docs/14/spi-spi-is-cursor-plan.html "PostgreSQL 14 - SPI_is_cursor_plan") Development Versions: [devel](https://www.postgresql.org/docs/devel/spi-spi-is-cursor-plan.html "PostgreSQL devel - SPI_is_cursor_plan") Unsupported versions: [13](https://www.postgresql.org/docs/13/spi-spi-is-cursor-plan.html "PostgreSQL 13 - SPI_is_cursor_plan") / [12](https://www.postgresql.org/docs/12/spi-spi-is-cursor-plan.html "PostgreSQL 12 - SPI_is_cursor_plan") / [11](https://www.postgresql.org/docs/11/spi-spi-is-cursor-plan.html "PostgreSQL 11 - SPI_is_cursor_plan") / [10](https://www.postgresql.org/docs/10/spi-spi-is-cursor-plan.html "PostgreSQL 10 - SPI_is_cursor_plan") / [9.6](https://www.postgresql.org/docs/9.6/spi-spi-is-cursor-plan.html "PostgreSQL 9.6 - SPI_is_cursor_plan") / [9.5](https://www.postgresql.org/docs/9.5/spi-spi-is-cursor-plan.html "PostgreSQL 9.5 - SPI_is_cursor_plan") / [9.4](https://www.postgresql.org/docs/9.4/spi-spi-is-cursor-plan.html "PostgreSQL 9.4 - SPI_is_cursor_plan") / [9.3](https://www.postgresql.org/docs/9.3/spi-spi-is-cursor-plan.html "PostgreSQL 9.3 - SPI_is_cursor_plan") / [9.2](https://www.postgresql.org/docs/9.2/spi-spi-is-cursor-plan.html "PostgreSQL 9.2 - SPI_is_cursor_plan") / [9.1](https://www.postgresql.org/docs/9.1/spi-spi-is-cursor-plan.html "PostgreSQL 9.1 - SPI_is_cursor_plan") / [9.0](https://www.postgresql.org/docs/9.0/spi-spi-is-cursor-plan.html "PostgreSQL 9.0 - SPI_is_cursor_plan") / [8.4](https://www.postgresql.org/docs/8.4/spi-spi-is-cursor-plan.html "PostgreSQL 8.4 - SPI_is_cursor_plan") / [8.3](https://www.postgresql.org/docs/8.3/spi-spi-is-cursor-plan.html "PostgreSQL 8.3 - SPI_is_cursor_plan") / [8.2](https://www.postgresql.org/docs/8.2/spi-spi-is-cursor-plan.html "PostgreSQL 8.2 - SPI_is_cursor_plan") / [8.1](https://www.postgresql.org/docs/8.1/spi-spi-is-cursor-plan.html "PostgreSQL 8.1 - SPI_is_cursor_plan") / [8.0](https://www.postgresql.org/docs/8.0/spi-spi-is-cursor-plan.html "PostgreSQL 8.0 - SPI_is_cursor_plan") | SPI\_is\_cursor\_plan | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-getargtypeid.html "SPI_getargtypeid") | [Up](https://www.postgresql.org/docs/current/spi-interface.html "45.1. Interface Functions") | 45.1. Interface Functions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/spi-spi-execute-plan.html "SPI_execute_plan") | * * * SPI\_is\_cursor\_plan --------------------- SPI\_is\_cursor\_plan — return `true` if a statement prepared by `SPI_prepare` can be used with `SPI_cursor_open` Synopsis -------- bool SPI\_is\_cursor\_plan(SPIPlanPtr _`plan`_) Description ----------- `SPI_is_cursor_plan` returns `true` if a statement prepared by `SPI_prepare` can be passed as an argument to `SPI_cursor_open`, or `false` if that is not the case. The criteria are that the _`plan`_ represents one single command and that this command returns tuples to the caller; for example, `SELECT` is allowed unless it contains an `INTO` clause, and `UPDATE` is allowed only if it contains a `RETURNING` clause. Arguments --------- ``SPIPlanPtr _`plan`_`` prepared statement (returned by `SPI_prepare`) Return Value ------------ `true` or `false` to indicate if the _`plan`_ can produce a cursor or not, with `SPI_result` set to zero. If it is not possible to determine the answer (for example, if the _`plan`_ is `NULL` or invalid, or if called when not connected to SPI), then `SPI_result` is set to a suitable error code and `false` is returned. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/spi-spi-getargtypeid.html "SPI_getargtypeid") | [Up](https://www.postgresql.org/docs/current/spi-interface.html "45.1. Interface Functions") | [Next](https://www.postgresql.org/docs/current/spi-spi-execute-plan.html "SPI_execute_plan") | | SPI\_getargtypeid | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | SPI\_execute\_plan | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/spi-spi-is-cursor-plan.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 22. Managing Databases November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/managing-databases.html "PostgreSQL 18 - Chapter 22. Managing Databases") ([18](https://www.postgresql.org/docs/18/managing-databases.html "PostgreSQL 18 - Chapter 22. Managing Databases") ) / [17](https://www.postgresql.org/docs/17/managing-databases.html "PostgreSQL 17 - Chapter 22. Managing Databases") / [16](https://www.postgresql.org/docs/16/managing-databases.html "PostgreSQL 16 - Chapter 22. Managing Databases") / [15](https://www.postgresql.org/docs/15/managing-databases.html "PostgreSQL 15 - Chapter 22. Managing Databases") / [14](https://www.postgresql.org/docs/14/managing-databases.html "PostgreSQL 14 - Chapter 22. Managing Databases") Development Versions: [devel](https://www.postgresql.org/docs/devel/managing-databases.html "PostgreSQL devel - Chapter 22. Managing Databases") Unsupported versions: [13](https://www.postgresql.org/docs/13/managing-databases.html "PostgreSQL 13 - Chapter 22. Managing Databases") / [12](https://www.postgresql.org/docs/12/managing-databases.html "PostgreSQL 12 - Chapter 22. Managing Databases") / [11](https://www.postgresql.org/docs/11/managing-databases.html "PostgreSQL 11 - Chapter 22. Managing Databases") / [10](https://www.postgresql.org/docs/10/managing-databases.html "PostgreSQL 10 - Chapter 22. Managing Databases") / [9.6](https://www.postgresql.org/docs/9.6/managing-databases.html "PostgreSQL 9.6 - Chapter 22. Managing Databases") / [9.5](https://www.postgresql.org/docs/9.5/managing-databases.html "PostgreSQL 9.5 - Chapter 22. Managing Databases") / [9.4](https://www.postgresql.org/docs/9.4/managing-databases.html "PostgreSQL 9.4 - Chapter 22. Managing Databases") / [9.3](https://www.postgresql.org/docs/9.3/managing-databases.html "PostgreSQL 9.3 - Chapter 22. Managing Databases") / [9.2](https://www.postgresql.org/docs/9.2/managing-databases.html "PostgreSQL 9.2 - Chapter 22. Managing Databases") / [9.1](https://www.postgresql.org/docs/9.1/managing-databases.html "PostgreSQL 9.1 - Chapter 22. Managing Databases") / [9.0](https://www.postgresql.org/docs/9.0/managing-databases.html "PostgreSQL 9.0 - Chapter 22. Managing Databases") / [8.4](https://www.postgresql.org/docs/8.4/managing-databases.html "PostgreSQL 8.4 - Chapter 22. Managing Databases") / [8.3](https://www.postgresql.org/docs/8.3/managing-databases.html "PostgreSQL 8.3 - Chapter 22. Managing Databases") / [8.2](https://www.postgresql.org/docs/8.2/managing-databases.html "PostgreSQL 8.2 - Chapter 22. Managing Databases") / [8.1](https://www.postgresql.org/docs/8.1/managing-databases.html "PostgreSQL 8.1 - Chapter 22. Managing Databases") / [8.0](https://www.postgresql.org/docs/8.0/managing-databases.html "PostgreSQL 8.0 - Chapter 22. Managing Databases") / [7.4](https://www.postgresql.org/docs/7.4/managing-databases.html "PostgreSQL 7.4 - Chapter 22. Managing Databases") / [7.3](https://www.postgresql.org/docs/7.3/managing-databases.html "PostgreSQL 7.3 - Chapter 22. Managing Databases") / [7.2](https://www.postgresql.org/docs/7.2/managing-databases.html "PostgreSQL 7.2 - Chapter 22. Managing Databases") / [7.1](https://www.postgresql.org/docs/7.1/managing-databases.html "PostgreSQL 7.1 - Chapter 22. Managing Databases") | Chapter 22. Managing Databases | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/perm-functions.html "21.6. Function Security") | [Up](https://www.postgresql.org/docs/18/admin.html "Part III. Server Administration") | Part III. Server Administration | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/manage-ag-overview.html "22.1. Overview") | * * * Chapter 22. Managing Databases ------------------------------ **Table of Contents** [22.1. Overview](https://www.postgresql.org/docs/18/manage-ag-overview.html) [22.2. Creating a Database](https://www.postgresql.org/docs/18/manage-ag-createdb.html) [22.3. Template Databases](https://www.postgresql.org/docs/18/manage-ag-templatedbs.html) [22.4. Database Configuration](https://www.postgresql.org/docs/18/manage-ag-config.html) [22.5. Destroying a Database](https://www.postgresql.org/docs/18/manage-ag-dropdb.html) [22.6. Tablespaces](https://www.postgresql.org/docs/18/manage-ag-tablespaces.html) Every instance of a running PostgreSQL server manages one or more databases. Databases are therefore the topmost hierarchical level for organizing SQL objects (“database objects”). This chapter describes the properties of databases, and how to create, manage, and destroy them. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/perm-functions.html "21.6. Function Security") | [Up](https://www.postgresql.org/docs/18/admin.html "Part III. Server Administration") | [Next](https://www.postgresql.org/docs/18/manage-ag-overview.html "22.1. Overview") | | 21.6. Function Security | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 22.1. Overview | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/managing-databases.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 55. PostgreSQL Coding Conventions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/source.html "PostgreSQL 18 - Chapter 55. PostgreSQL Coding Conventions") ([18](https://www.postgresql.org/docs/18/source.html "PostgreSQL 18 - Chapter 55. PostgreSQL Coding Conventions") ) / [17](https://www.postgresql.org/docs/17/source.html "PostgreSQL 17 - Chapter 55. PostgreSQL Coding Conventions") / [16](https://www.postgresql.org/docs/16/source.html "PostgreSQL 16 - Chapter 55. PostgreSQL Coding Conventions") / [15](https://www.postgresql.org/docs/15/source.html "PostgreSQL 15 - Chapter 55. PostgreSQL Coding Conventions") / [14](https://www.postgresql.org/docs/14/source.html "PostgreSQL 14 - Chapter 55. PostgreSQL Coding Conventions") Development Versions: [devel](https://www.postgresql.org/docs/devel/source.html "PostgreSQL devel - Chapter 55. PostgreSQL Coding Conventions") Unsupported versions: [13](https://www.postgresql.org/docs/13/source.html "PostgreSQL 13 - Chapter 55. PostgreSQL Coding Conventions") / [12](https://www.postgresql.org/docs/12/source.html "PostgreSQL 12 - Chapter 55. PostgreSQL Coding Conventions") / [11](https://www.postgresql.org/docs/11/source.html "PostgreSQL 11 - Chapter 55. PostgreSQL Coding Conventions") / [10](https://www.postgresql.org/docs/10/source.html "PostgreSQL 10 - Chapter 55. PostgreSQL Coding Conventions") / [9.6](https://www.postgresql.org/docs/9.6/source.html "PostgreSQL 9.6 - Chapter 55. PostgreSQL Coding Conventions") / [9.5](https://www.postgresql.org/docs/9.5/source.html "PostgreSQL 9.5 - Chapter 55. PostgreSQL Coding Conventions") / [9.4](https://www.postgresql.org/docs/9.4/source.html "PostgreSQL 9.4 - Chapter 55. PostgreSQL Coding Conventions") / [9.3](https://www.postgresql.org/docs/9.3/source.html "PostgreSQL 9.3 - Chapter 55. PostgreSQL Coding Conventions") / [9.2](https://www.postgresql.org/docs/9.2/source.html "PostgreSQL 9.2 - Chapter 55. PostgreSQL Coding Conventions") / [9.1](https://www.postgresql.org/docs/9.1/source.html "PostgreSQL 9.1 - Chapter 55. PostgreSQL Coding Conventions") / [9.0](https://www.postgresql.org/docs/9.0/source.html "PostgreSQL 9.0 - Chapter 55. PostgreSQL Coding Conventions") / [8.4](https://www.postgresql.org/docs/8.4/source.html "PostgreSQL 8.4 - Chapter 55. PostgreSQL Coding Conventions") / [8.3](https://www.postgresql.org/docs/8.3/source.html "PostgreSQL 8.3 - Chapter 55. PostgreSQL Coding Conventions") / [8.2](https://www.postgresql.org/docs/8.2/source.html "PostgreSQL 8.2 - Chapter 55. PostgreSQL Coding Conventions") / [8.1](https://www.postgresql.org/docs/8.1/source.html "PostgreSQL 8.1 - Chapter 55. PostgreSQL Coding Conventions") / [8.0](https://www.postgresql.org/docs/8.0/source.html "PostgreSQL 8.0 - Chapter 55. PostgreSQL Coding Conventions") / [7.4](https://www.postgresql.org/docs/7.4/source.html "PostgreSQL 7.4 - Chapter 55. PostgreSQL Coding Conventions") / [7.3](https://www.postgresql.org/docs/7.3/source.html "PostgreSQL 7.3 - Chapter 55. PostgreSQL Coding Conventions") / [7.2](https://www.postgresql.org/docs/7.2/source.html "PostgreSQL 7.2 - Chapter 55. PostgreSQL Coding Conventions") / [7.1](https://www.postgresql.org/docs/7.1/source.html "PostgreSQL 7.1 - Chapter 55. PostgreSQL Coding Conventions") | Chapter 55. PostgreSQL Coding Conventions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/protocol-changes.html "54.10. Summary of Changes since Protocol 2.0") | [Up](https://www.postgresql.org/docs/current/internals.html "Part VII. Internals") | Part VII. Internals | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/source-format.html "55.1. Formatting") | * * * Chapter 55. PostgreSQL Coding Conventions ----------------------------------------- **Table of Contents** [55.1. Formatting](https://www.postgresql.org/docs/current/source-format.html) [55.2. Reporting Errors Within the Server](https://www.postgresql.org/docs/current/error-message-reporting.html) [55.3. Error Message Style Guide](https://www.postgresql.org/docs/current/error-style-guide.html) [55.4. Miscellaneous Coding Conventions](https://www.postgresql.org/docs/current/source-conventions.html) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/protocol-changes.html "54.10. Summary of Changes since Protocol 2.0") | [Up](https://www.postgresql.org/docs/current/internals.html "Part VII. Internals") | [Next](https://www.postgresql.org/docs/current/source-format.html "55.1. Formatting") | | 54.10. Summary of Changes since Protocol 2.0 | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 55.1. Formatting | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/source.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 27. Monitoring Database Activity November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/monitoring.html "PostgreSQL 18 - Chapter 27. Monitoring Database Activity") ([18](https://www.postgresql.org/docs/18/monitoring.html "PostgreSQL 18 - Chapter 27. Monitoring Database Activity") ) / [17](https://www.postgresql.org/docs/17/monitoring.html "PostgreSQL 17 - Chapter 27. Monitoring Database Activity") / [16](https://www.postgresql.org/docs/16/monitoring.html "PostgreSQL 16 - Chapter 27. Monitoring Database Activity") / [15](https://www.postgresql.org/docs/15/monitoring.html "PostgreSQL 15 - Chapter 27. Monitoring Database Activity") / [14](https://www.postgresql.org/docs/14/monitoring.html "PostgreSQL 14 - Chapter 27. Monitoring Database Activity") Development Versions: [devel](https://www.postgresql.org/docs/devel/monitoring.html "PostgreSQL devel - Chapter 27. Monitoring Database Activity") Unsupported versions: [13](https://www.postgresql.org/docs/13/monitoring.html "PostgreSQL 13 - Chapter 27. Monitoring Database Activity") / [12](https://www.postgresql.org/docs/12/monitoring.html "PostgreSQL 12 - Chapter 27. Monitoring Database Activity") / [11](https://www.postgresql.org/docs/11/monitoring.html "PostgreSQL 11 - Chapter 27. Monitoring Database Activity") / [10](https://www.postgresql.org/docs/10/monitoring.html "PostgreSQL 10 - Chapter 27. Monitoring Database Activity") / [9.6](https://www.postgresql.org/docs/9.6/monitoring.html "PostgreSQL 9.6 - Chapter 27. Monitoring Database Activity") / [9.5](https://www.postgresql.org/docs/9.5/monitoring.html "PostgreSQL 9.5 - Chapter 27. Monitoring Database Activity") / [9.4](https://www.postgresql.org/docs/9.4/monitoring.html "PostgreSQL 9.4 - Chapter 27. Monitoring Database Activity") / [9.3](https://www.postgresql.org/docs/9.3/monitoring.html "PostgreSQL 9.3 - Chapter 27. Monitoring Database Activity") / [9.2](https://www.postgresql.org/docs/9.2/monitoring.html "PostgreSQL 9.2 - Chapter 27. Monitoring Database Activity") / [9.1](https://www.postgresql.org/docs/9.1/monitoring.html "PostgreSQL 9.1 - Chapter 27. Monitoring Database Activity") / [9.0](https://www.postgresql.org/docs/9.0/monitoring.html "PostgreSQL 9.0 - Chapter 27. Monitoring Database Activity") / [8.4](https://www.postgresql.org/docs/8.4/monitoring.html "PostgreSQL 8.4 - Chapter 27. Monitoring Database Activity") / [8.3](https://www.postgresql.org/docs/8.3/monitoring.html "PostgreSQL 8.3 - Chapter 27. Monitoring Database Activity") / [8.2](https://www.postgresql.org/docs/8.2/monitoring.html "PostgreSQL 8.2 - Chapter 27. Monitoring Database Activity") / [8.1](https://www.postgresql.org/docs/8.1/monitoring.html "PostgreSQL 8.1 - Chapter 27. Monitoring Database Activity") / [8.0](https://www.postgresql.org/docs/8.0/monitoring.html "PostgreSQL 8.0 - Chapter 27. Monitoring Database Activity") / [7.4](https://www.postgresql.org/docs/7.4/monitoring.html "PostgreSQL 7.4 - Chapter 27. Monitoring Database Activity") / [7.3](https://www.postgresql.org/docs/7.3/monitoring.html "PostgreSQL 7.3 - Chapter 27. Monitoring Database Activity") / [7.2](https://www.postgresql.org/docs/7.2/monitoring.html "PostgreSQL 7.2 - Chapter 27. Monitoring Database Activity") | Chapter 27. Monitoring Database Activity | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/hot-standby.html "26.4. Hot Standby") | [Up](https://www.postgresql.org/docs/18/admin.html "Part III. Server Administration") | Part III. Server Administration | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/monitoring-ps.html "27.1. Standard Unix Tools") | * * * Chapter 27. Monitoring Database Activity ---------------------------------------- **Table of Contents** [27.1. Standard Unix Tools](https://www.postgresql.org/docs/18/monitoring-ps.html) [27.2. The Cumulative Statistics System](https://www.postgresql.org/docs/18/monitoring-stats.html) [27.2.1. Statistics Collection Configuration](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-STATS-SETUP) [27.2.2. Viewing Statistics](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-STATS-VIEWS) [27.2.3. `pg_stat_activity`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW) [27.2.4. `pg_stat_replication`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-REPLICATION-VIEW) [27.2.5. `pg_stat_replication_slots`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-REPLICATION-SLOTS-VIEW) [27.2.6. `pg_stat_wal_receiver`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-WAL-RECEIVER-VIEW) [27.2.7. `pg_stat_recovery_prefetch`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-RECOVERY-PREFETCH) [27.2.8. `pg_stat_subscription`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-SUBSCRIPTION) [27.2.9. `pg_stat_subscription_stats`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-SUBSCRIPTION-STATS) [27.2.10. `pg_stat_ssl`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-SSL-VIEW) [27.2.11. `pg_stat_gssapi`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-GSSAPI-VIEW) [27.2.12. `pg_stat_archiver`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-ARCHIVER-VIEW) [27.2.13. `pg_stat_io`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-IO-VIEW) [27.2.14. `pg_stat_bgwriter`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-BGWRITER-VIEW) [27.2.15. `pg_stat_checkpointer`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-CHECKPOINTER-VIEW) [27.2.16. `pg_stat_wal`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-WAL-VIEW) [27.2.17. `pg_stat_database`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-VIEW) [27.2.18. `pg_stat_database_conflicts`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-CONFLICTS-VIEW) [27.2.19. `pg_stat_all_tables`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-ALL-TABLES-VIEW) [27.2.20. `pg_stat_all_indexes`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-ALL-INDEXES-VIEW) [27.2.21. `pg_statio_all_tables`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STATIO-ALL-TABLES-VIEW) [27.2.22. `pg_statio_all_indexes`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STATIO-ALL-INDEXES-VIEW) [27.2.23. `pg_statio_all_sequences`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STATIO-ALL-SEQUENCES-VIEW) [27.2.24. `pg_stat_user_functions`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-USER-FUNCTIONS-VIEW) [27.2.25. `pg_stat_slru`](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-SLRU-VIEW) [27.2.26. Statistics Functions](https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-STATS-FUNCTIONS) [27.3. Viewing Locks](https://www.postgresql.org/docs/18/monitoring-locks.html) [27.4. Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html) [27.4.1. ANALYZE Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#ANALYZE-PROGRESS-REPORTING) [27.4.2. CLUSTER Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#CLUSTER-PROGRESS-REPORTING) [27.4.3. COPY Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#COPY-PROGRESS-REPORTING) [27.4.4. CREATE INDEX Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING) [27.4.5. VACUUM Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#VACUUM-PROGRESS-REPORTING) [27.4.6. Base Backup Progress Reporting](https://www.postgresql.org/docs/18/progress-reporting.html#BASEBACKUP-PROGRESS-REPORTING) [27.5. Dynamic Tracing](https://www.postgresql.org/docs/18/dynamic-trace.html) [27.5.1. Compiling for Dynamic Tracing](https://www.postgresql.org/docs/18/dynamic-trace.html#COMPILING-FOR-TRACE) [27.5.2. Built-in Probes](https://www.postgresql.org/docs/18/dynamic-trace.html#TRACE-POINTS) [27.5.3. Using Probes](https://www.postgresql.org/docs/18/dynamic-trace.html#USING-TRACE-POINTS) [27.5.4. Defining New Probes](https://www.postgresql.org/docs/18/dynamic-trace.html#DEFINING-TRACE-POINTS) [27.6. Monitoring Disk Usage](https://www.postgresql.org/docs/18/diskusage.html) [27.6.1. Determining Disk Usage](https://www.postgresql.org/docs/18/diskusage.html#DISK-USAGE) [27.6.2. Disk Full Failure](https://www.postgresql.org/docs/18/diskusage.html#DISK-FULL) A database administrator frequently wonders, “What is the system doing right now?” This chapter discusses how to find that out. Several tools are available for monitoring database activity and analyzing performance. Most of this chapter is devoted to describing PostgreSQL's cumulative statistics system, but one should not neglect regular Unix monitoring programs such as `ps`, `top`, `iostat`, and `vmstat`. Also, once one has identified a poorly-performing query, further investigation might be needed using PostgreSQL's [`EXPLAIN`](https://www.postgresql.org/docs/18/sql-explain.html "EXPLAIN") command. [Section 14.1](https://www.postgresql.org/docs/18/using-explain.html "14.1. Using EXPLAIN") discusses `EXPLAIN` and other methods for understanding the behavior of an individual query. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/hot-standby.html "26.4. Hot Standby") | [Up](https://www.postgresql.org/docs/18/admin.html "Part III. Server Administration") | [Next](https://www.postgresql.org/docs/18/monitoring-ps.html "27.1. Standard Unix Tools") | | 26.4. Hot Standby | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 27.1. Standard Unix Tools | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/monitoring.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: ALTER OPERATOR November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alteroperator.html "PostgreSQL 18 - ALTER OPERATOR") ([18](https://www.postgresql.org/docs/18/sql-alteroperator.html "PostgreSQL 18 - ALTER OPERATOR") ) / [17](https://www.postgresql.org/docs/17/sql-alteroperator.html "PostgreSQL 17 - ALTER OPERATOR") / [16](https://www.postgresql.org/docs/16/sql-alteroperator.html "PostgreSQL 16 - ALTER OPERATOR") / [15](https://www.postgresql.org/docs/15/sql-alteroperator.html "PostgreSQL 15 - ALTER OPERATOR") / [14](https://www.postgresql.org/docs/14/sql-alteroperator.html "PostgreSQL 14 - ALTER OPERATOR") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alteroperator.html "PostgreSQL devel - ALTER OPERATOR") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alteroperator.html "PostgreSQL 13 - ALTER OPERATOR") / [12](https://www.postgresql.org/docs/12/sql-alteroperator.html "PostgreSQL 12 - ALTER OPERATOR") / [11](https://www.postgresql.org/docs/11/sql-alteroperator.html "PostgreSQL 11 - ALTER OPERATOR") / [10](https://www.postgresql.org/docs/10/sql-alteroperator.html "PostgreSQL 10 - ALTER OPERATOR") / [9.6](https://www.postgresql.org/docs/9.6/sql-alteroperator.html "PostgreSQL 9.6 - ALTER OPERATOR") / [9.5](https://www.postgresql.org/docs/9.5/sql-alteroperator.html "PostgreSQL 9.5 - ALTER OPERATOR") / [9.4](https://www.postgresql.org/docs/9.4/sql-alteroperator.html "PostgreSQL 9.4 - ALTER OPERATOR") / [9.3](https://www.postgresql.org/docs/9.3/sql-alteroperator.html "PostgreSQL 9.3 - ALTER OPERATOR") / [9.2](https://www.postgresql.org/docs/9.2/sql-alteroperator.html "PostgreSQL 9.2 - ALTER OPERATOR") / [9.1](https://www.postgresql.org/docs/9.1/sql-alteroperator.html "PostgreSQL 9.1 - ALTER OPERATOR") / [9.0](https://www.postgresql.org/docs/9.0/sql-alteroperator.html "PostgreSQL 9.0 - ALTER OPERATOR") / [8.4](https://www.postgresql.org/docs/8.4/sql-alteroperator.html "PostgreSQL 8.4 - ALTER OPERATOR") / [8.3](https://www.postgresql.org/docs/8.3/sql-alteroperator.html "PostgreSQL 8.3 - ALTER OPERATOR") / [8.2](https://www.postgresql.org/docs/8.2/sql-alteroperator.html "PostgreSQL 8.2 - ALTER OPERATOR") / [8.1](https://www.postgresql.org/docs/8.1/sql-alteroperator.html "PostgreSQL 8.1 - ALTER OPERATOR") / [8.0](https://www.postgresql.org/docs/8.0/sql-alteroperator.html "PostgreSQL 8.0 - ALTER OPERATOR") | ALTER OPERATOR | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-altermaterializedview.html "ALTER MATERIALIZED VIEW") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-alteropclass.html "ALTER OPERATOR CLASS") | * * * ALTER OPERATOR -------------- ALTER OPERATOR — change the definition of an operator Synopsis -------- ALTER OPERATOR _`name`_ ( { _`left_type`_ | NONE } , _`right_type`_ ) OWNER TO { _`new_owner`_ | CURRENT\_ROLE | CURRENT\_USER | SESSION\_USER } ALTER OPERATOR _`name`_ ( { _`left_type`_ | NONE } , _`right_type`_ ) SET SCHEMA _`new_schema`_ ALTER OPERATOR _`name`_ ( { _`left_type`_ | NONE } , _`right_type`_ ) SET ( { RESTRICT = { _`res_proc`_ | NONE } | JOIN = { _`join_proc`_ | NONE } | COMMUTATOR = _`com_op`_ | NEGATOR = _`neg_op`_ | HASHES | MERGES } \[, ... \] ) Description ----------- `ALTER OPERATOR` changes the definition of an operator. You must own the operator to use `ALTER OPERATOR`. To alter the owner, you must be able to `SET ROLE` to the new owning role, and that role must have `CREATE` privilege on the operator's schema. (These restrictions enforce that altering the owner doesn't do anything you couldn't do by dropping and recreating the operator. However, a superuser can alter ownership of any operator anyway.) Parameters ---------- _`name`_ The name (optionally schema-qualified) of an existing operator. _`left_type`_ The data type of the operator's left operand; write `NONE` if the operator has no left operand. _`right_type`_ The data type of the operator's right operand. _`new_owner`_ The new owner of the operator. _`new_schema`_ The new schema for the operator. _`res_proc`_ The restriction selectivity estimator function for this operator; write NONE to remove existing selectivity estimator. _`join_proc`_ The join selectivity estimator function for this operator; write NONE to remove existing selectivity estimator. _`com_op`_ The commutator of this operator. Can only be changed if the operator does not have an existing commutator. _`neg_op`_ The negator of this operator. Can only be changed if the operator does not have an existing negator. `HASHES` Indicates this operator can support a hash join. Can only be enabled and not disabled. `MERGES` Indicates this operator can support a merge join. Can only be enabled and not disabled. Notes ----- Refer to [Section 36.14](https://www.postgresql.org/docs/18/xoper.html "36.14. User-Defined Operators") and [Section 36.15](https://www.postgresql.org/docs/18/xoper-optimization.html "36.15. Operator Optimization Information") for further information. Since commutators come in pairs that are commutators of each other, `ALTER OPERATOR SET COMMUTATOR` will also set the commutator of the _`com_op`_ to be the target operator. Likewise, `ALTER OPERATOR SET NEGATOR` will also set the negator of the _`neg_op`_ to be the target operator. Therefore, you must own the commutator or negator operator as well as the target operator. Examples -------- Change the owner of a custom operator `a @@ b` for type `text`: ALTER OPERATOR @@ (text, text) OWNER TO joe; Change the restriction and join selectivity estimator functions of a custom operator `a && b` for type `int[]`: ALTER OPERATOR && (int\[\], int\[\]) SET (RESTRICT = \_int\_contsel, JOIN = \_int\_contjoinsel); Mark the `&&` operator as being its own commutator: ALTER OPERATOR && (int\[\], int\[\]) SET (COMMUTATOR = &&); Compatibility ------------- There is no `ALTER OPERATOR` statement in the SQL standard. See Also -------- [CREATE OPERATOR](https://www.postgresql.org/docs/18/sql-createoperator.html "CREATE OPERATOR") , [DROP OPERATOR](https://www.postgresql.org/docs/18/sql-dropoperator.html "DROP OPERATOR") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-altermaterializedview.html "ALTER MATERIALIZED VIEW") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-alteropclass.html "ALTER OPERATOR CLASS") | | ALTER MATERIALIZED VIEW | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | ALTER OPERATOR CLASS | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-alteroperator.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE POLICY November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createpolicy.html "PostgreSQL 18 - CREATE POLICY") ([18](https://www.postgresql.org/docs/18/sql-createpolicy.html "PostgreSQL 18 - CREATE POLICY") ) / [17](https://www.postgresql.org/docs/17/sql-createpolicy.html "PostgreSQL 17 - CREATE POLICY") / [16](https://www.postgresql.org/docs/16/sql-createpolicy.html "PostgreSQL 16 - CREATE POLICY") / [15](https://www.postgresql.org/docs/15/sql-createpolicy.html "PostgreSQL 15 - CREATE POLICY") / [14](https://www.postgresql.org/docs/14/sql-createpolicy.html "PostgreSQL 14 - CREATE POLICY") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createpolicy.html "PostgreSQL devel - CREATE POLICY") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createpolicy.html "PostgreSQL 13 - CREATE POLICY") / [12](https://www.postgresql.org/docs/12/sql-createpolicy.html "PostgreSQL 12 - CREATE POLICY") / [11](https://www.postgresql.org/docs/11/sql-createpolicy.html "PostgreSQL 11 - CREATE POLICY") / [10](https://www.postgresql.org/docs/10/sql-createpolicy.html "PostgreSQL 10 - CREATE POLICY") / [9.6](https://www.postgresql.org/docs/9.6/sql-createpolicy.html "PostgreSQL 9.6 - CREATE POLICY") / [9.5](https://www.postgresql.org/docs/9.5/sql-createpolicy.html "PostgreSQL 9.5 - CREATE POLICY") | CREATE POLICY | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createopfamily.html "CREATE OPERATOR FAMILY") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-createprocedure.html "CREATE PROCEDURE") | * * * CREATE POLICY ------------- CREATE POLICY — define a new row-level security policy for a table Synopsis -------- CREATE POLICY _`name`_ ON _`table_name`_ \[ AS { PERMISSIVE | RESTRICTIVE } \] \[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } \] \[ TO { _`role_name`_ | PUBLIC | CURRENT\_ROLE | CURRENT\_USER | SESSION\_USER } \[, ...\] \] \[ USING ( _`using_expression`_ ) \] \[ WITH CHECK ( _`check_expression`_ ) \] Description ----------- The `CREATE POLICY` command defines a new row-level security policy for a table. Note that row-level security must be enabled on the table (using `ALTER TABLE ... ENABLE ROW LEVEL SECURITY`) in order for created policies to be applied. A policy grants the permission to select, insert, update, or delete rows that match the relevant policy expression. Existing table rows are checked against the expression specified in `USING`, while new rows that would be created via `INSERT` or `UPDATE` are checked against the expression specified in `WITH CHECK`. When a `USING` expression returns true for a given row then that row is visible to the user, while if false or null is returned then the row is not visible. When a `WITH CHECK` expression returns true for a row then that row is inserted or updated, while if false or null is returned then an error occurs. For `INSERT`, `UPDATE`, and `MERGE` statements, `WITH CHECK` expressions are enforced after `BEFORE` triggers are fired, and before any actual data modifications are made. Thus a `BEFORE ROW` trigger may modify the data to be inserted, affecting the result of the security policy check. `WITH CHECK` expressions are enforced before any other constraints. Policy names are per-table. Therefore, one policy name can be used for many different tables and have a definition for each table which is appropriate to that table. Policies can be applied for specific commands or for specific roles. The default for newly created policies is that they apply for all commands and roles, unless otherwise specified. Multiple policies may apply to a single command; see below for more details. [Table 300](https://www.postgresql.org/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY "Table 300. Policies Applied by Command Type") summarizes how the different types of policy apply to specific commands. For policies that can have both `USING` and `WITH CHECK` expressions (`ALL` and `UPDATE`), if no `WITH CHECK` expression is defined, then the `USING` expression will be used both to determine which rows are visible (normal `USING` case) and which new rows will be allowed to be added (`WITH CHECK` case). If row-level security is enabled for a table, but no applicable policies exist, a “default deny” policy is assumed, so that no rows will be visible or updatable. Parameters ---------- _`name`_ The name of the policy to be created. This must be distinct from the name of any other policy for the table. _`table_name`_ The name (optionally schema-qualified) of the table the policy applies to. `PERMISSIVE` Specify that the policy is to be created as a permissive policy. All permissive policies which are applicable to a given query will be combined together using the Boolean “OR” operator. By creating permissive policies, administrators can add to the set of records which can be accessed. Policies are permissive by default. `RESTRICTIVE` Specify that the policy is to be created as a restrictive policy. All restrictive policies which are applicable to a given query will be combined together using the Boolean “AND” operator. By creating restrictive policies, administrators can reduce the set of records which can be accessed as all restrictive policies must be passed for each record. Note that there needs to be at least one permissive policy to grant access to records before restrictive policies can be usefully used to reduce that access. If only restrictive policies exist, then no records will be accessible. When a mix of permissive and restrictive policies are present, a record is only accessible if at least one of the permissive policies passes, in addition to all the restrictive policies. _`command`_ The command to which the policy applies. Valid options are `ALL`, `SELECT`, `INSERT`, `UPDATE`, and `DELETE`. `ALL` is the default. See below for specifics regarding how these are applied. _`role_name`_ The role(s) to which the policy is to be applied. The default is `PUBLIC`, which will apply the policy to all roles. _`using_expression`_ Any SQL conditional expression (returning `boolean`). The conditional expression cannot contain any aggregate or window functions. This expression will be added to queries that refer to the table if row-level security is enabled. Rows for which the expression returns true will be visible. Any rows for which the expression returns false or null will not be visible to the user (in a `SELECT`), and will not be available for modification (in an `UPDATE` or `DELETE`). Such rows are silently suppressed; no error is reported. _`check_expression`_ Any SQL conditional expression (returning `boolean`). The conditional expression cannot contain any aggregate or window functions. This expression will be used in `INSERT` and `UPDATE` queries against the table if row-level security is enabled. Only rows for which the expression evaluates to true will be allowed. An error will be thrown if the expression evaluates to false or null for any of the records inserted or any of the records that result from the update. Note that the _`check_expression`_ is evaluated against the proposed new contents of the row, not the original contents. ### Per-Command Policies `ALL` [#](https://www.postgresql.org/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-ALL) Using `ALL` for a policy means that it will apply to all commands, regardless of the type of command. If an `ALL` policy exists and more specific policies exist, then both the `ALL` policy and the more specific policy (or policies) will be applied. Additionally, `ALL` policies will be applied to both the selection side of a query and the modification side, using the `USING` expression for both cases if only a `USING` expression has been defined. As an example, if an `UPDATE` is issued, then the `ALL` policy will be applicable both to what the `UPDATE` will be able to select as rows to be updated (applying the `USING` expression), and to the resulting updated rows, to check if they are permitted to be added to the table (applying the `WITH CHECK` expression, if defined, and the `USING` expression otherwise). If an `INSERT` or `UPDATE` command attempts to add rows to the table that do not pass the `ALL` policy's `WITH CHECK` expression, the entire command will be aborted. `SELECT` [#](https://www.postgresql.org/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SELECT) Using `SELECT` for a policy means that it will apply to `SELECT` queries and whenever `SELECT` permissions are required on the relation the policy is defined for. The result is that only those records from the relation that pass the `SELECT` policy will be returned during a `SELECT` query, and that queries that require `SELECT` permissions, such as `UPDATE`, will also only see those records that are allowed by the `SELECT` policy. A `SELECT` policy cannot have a `WITH CHECK` expression, as it only applies in cases where records are being retrieved from the relation. `INSERT` [#](https://www.postgresql.org/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-INSERT) Using `INSERT` for a policy means that it will apply to `INSERT` commands and `MERGE` commands that contain `INSERT` actions. Rows being inserted that do not pass this policy will result in a policy violation error, and the entire `INSERT` command will be aborted. An `INSERT` policy cannot have a `USING` expression, as it only applies in cases where records are being added to the relation. Note that `INSERT` with `ON CONFLICT DO UPDATE` checks `INSERT` policies' `WITH CHECK` expressions only for rows appended to the relation by the `INSERT` path. `UPDATE` [#](https://www.postgresql.org/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-UPDATE) Using `UPDATE` for a policy means that it will apply to `UPDATE`, `SELECT FOR UPDATE` and `SELECT FOR SHARE` commands, as well as auxiliary `ON CONFLICT DO UPDATE` clauses of `INSERT` commands. `MERGE` commands containing `UPDATE` actions are affected as well. Since `UPDATE` involves pulling an existing record and replacing it with a new modified record, `UPDATE` policies accept both a `USING` expression and a `WITH CHECK` expression. The `USING` expression determines which records the `UPDATE` command will see to operate against, while the `WITH CHECK` expression defines which modified rows are allowed to be stored back into the relation. Any rows whose updated values do not pass the `WITH CHECK` expression will cause an error, and the entire command will be aborted. If only a `USING` clause is specified, then that clause will be used for both `USING` and `WITH CHECK` cases. Typically an `UPDATE` command also needs to read data from columns in the relation being updated (e.g., in a `WHERE` clause or a `RETURNING` clause, or in an expression on the right hand side of the `SET` clause). In this case, `SELECT` rights are also required on the relation being updated, and the appropriate `SELECT` or `ALL` policies will be applied in addition to the `UPDATE` policies. Thus the user must have access to the row(s) being updated through a `SELECT` or `ALL` policy in addition to being granted permission to update the row(s) via an `UPDATE` or `ALL` policy. When an `INSERT` command has an auxiliary `ON CONFLICT DO UPDATE` clause, if the `UPDATE` path is taken, the row to be updated is first checked against the `USING` expressions of any `UPDATE` policies, and then the new updated row is checked against the `WITH CHECK` expressions. Note, however, that unlike a standalone `UPDATE` command, if the existing row does not pass the `USING` expressions, an error will be thrown (the `UPDATE` path will _never_ be silently avoided). `DELETE` [#](https://www.postgresql.org/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-DELETE) Using `DELETE` for a policy means that it will apply to `DELETE` commands. Only rows that pass this policy will be seen by a `DELETE` command. There can be rows that are visible through a `SELECT` that are not available for deletion, if they do not pass the `USING` expression for the `DELETE` policy. In most cases a `DELETE` command also needs to read data from columns in the relation that it is deleting from (e.g., in a `WHERE` clause or a `RETURNING` clause). In this case, `SELECT` rights are also required on the relation, and the appropriate `SELECT` or `ALL` policies will be applied in addition to the `DELETE` policies. Thus the user must have access to the row(s) being deleted through a `SELECT` or `ALL` policy in addition to being granted permission to delete the row(s) via a `DELETE` or `ALL` policy. A `DELETE` policy cannot have a `WITH CHECK` expression, as it only applies in cases where records are being deleted from the relation, so that there is no new row to check. **Table 300. Policies Applied by Command Type** | Command | `SELECT/ALL policy` | `INSERT/ALL policy` | `UPDATE/ALL policy` | | `DELETE/ALL policy` | | --- | --- | --- | --- | --- | --- | | `USING expression` | `WITH CHECK expression` | `USING expression` | `WITH CHECK expression` | `USING expression` | | --- | --- | --- | --- | --- | --- | | `SELECT` | Existing row | — | — | — | — | | `SELECT FOR UPDATE/SHARE` | Existing row | — | Existing row | — | — | | `INSERT` / `MERGE ... THEN INSERT` | — | New row | — | — | — | | `INSERT ... RETURNING` | New row [\[a\]](https://www.postgresql.org/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV) | New row | — | — | — | | `UPDATE` / `MERGE ... THEN UPDATE` | Existing & new rows [\[a\]](https://www.postgresql.org/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV) | — | Existing row | New row | — | | `DELETE` | Existing row [\[a\]](https://www.postgresql.org/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV) | — | — | — | Existing row | | `ON CONFLICT DO UPDATE` | Existing & new rows | — | Existing row | New row | — | | [\[a\]](https://www.postgresql.org/docs/18/sql-createpolicy.html#RLS-SELECT-PRIV)
If read access is required to the existing or new row (for example, a `WHERE` or `RETURNING` clause that refers to columns from the relation). | | | | | | ### Application of Multiple Policies When multiple policies of different command types apply to the same command (for example, `SELECT` and `UPDATE` policies applied to an `UPDATE` command), then the user must have both types of permissions (for example, permission to select rows from the relation as well as permission to update them). Thus the expressions for one type of policy are combined with the expressions for the other type of policy using the `AND` operator. When multiple policies of the same command type apply to the same command, then there must be at least one `PERMISSIVE` policy granting access to the relation, and all of the `RESTRICTIVE` policies must pass. Thus all the `PERMISSIVE` policy expressions are combined using `OR`, all the `RESTRICTIVE` policy expressions are combined using `AND`, and the results are combined using `AND`. If there are no `PERMISSIVE` policies, then access is denied. Note that, for the purposes of combining multiple policies, `ALL` policies are treated as having the same type as whichever other type of policy is being applied. For example, in an `UPDATE` command requiring both `SELECT` and `UPDATE` permissions, if there are multiple applicable policies of each type, they will be combined as follows: _`expression`_ from RESTRICTIVE SELECT/ALL policy 1 AND _`expression`_ from RESTRICTIVE SELECT/ALL policy 2 AND ... AND ( _`expression`_ from PERMISSIVE SELECT/ALL policy 1 OR _`expression`_ from PERMISSIVE SELECT/ALL policy 2 OR ... ) AND _`expression`_ from RESTRICTIVE UPDATE/ALL policy 1 AND _`expression`_ from RESTRICTIVE UPDATE/ALL policy 2 AND ... AND ( _`expression`_ from PERMISSIVE UPDATE/ALL policy 1 OR _`expression`_ from PERMISSIVE UPDATE/ALL policy 2 OR ... ) Notes ----- You must be the owner of a table to create or change policies for it. While policies will be applied for explicit queries against tables in the database, they are not applied when the system is performing internal referential integrity checks or validating constraints. This means there are indirect ways to determine that a given value exists. An example of this is attempting to insert a duplicate value into a column that is a primary key or has a unique constraint. If the insert fails then the user can infer that the value already exists. (This example assumes that the user is permitted by policy to insert records which they are not allowed to see.) Another example is where a user is allowed to insert into a table which references another, otherwise hidden table. Existence can be determined by the user inserting values into the referencing table, where success would indicate that the value exists in the referenced table. These issues can be addressed by carefully crafting policies to prevent users from being able to insert, delete, or update records at all which might possibly indicate a value they are not otherwise able to see, or by using generated values (e.g., surrogate keys) instead of keys with external meanings. Generally, the system will enforce filter conditions imposed using security policies prior to qualifications that appear in user queries, in order to prevent inadvertent exposure of the protected data to user-defined functions which might not be trustworthy. However, functions and operators marked by the system (or the system administrator) as `LEAKPROOF` may be evaluated before policy expressions, as they are assumed to be trustworthy. Since policy expressions are added to the user's query directly, they will be run with the rights of the user running the overall query. Therefore, users who are using a given policy must be able to access any tables or functions referenced in the expression or they will simply receive a permission denied error when attempting to query the table that has row-level security enabled. This does not change how views work, however. As with normal queries and views, permission checks and policies for the tables which are referenced by a view will use the view owner's rights and any policies which apply to the view owner, except if the view is defined using the `security_invoker` option (see [`CREATE VIEW`](https://www.postgresql.org/docs/18/sql-createview.html "CREATE VIEW") ). No separate policy exists for `MERGE`. Instead, the policies defined for `SELECT`, `INSERT`, `UPDATE`, and `DELETE` are applied while executing `MERGE`, depending on the actions that are performed. Additional discussion and practical examples can be found in [Section 5.9](https://www.postgresql.org/docs/18/ddl-rowsecurity.html "5.9. Row Security Policies") . Compatibility ------------- `CREATE POLICY` is a PostgreSQL extension. See Also -------- [ALTER POLICY](https://www.postgresql.org/docs/18/sql-alterpolicy.html "ALTER POLICY") , [DROP POLICY](https://www.postgresql.org/docs/18/sql-droppolicy.html "DROP POLICY") , [ALTER TABLE](https://www.postgresql.org/docs/18/sql-altertable.html "ALTER TABLE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createopfamily.html "CREATE OPERATOR FAMILY") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-createprocedure.html "CREATE PROCEDURE") | | CREATE OPERATOR FAMILY | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | CREATE PROCEDURE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createpolicy.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 11.10. Operator Classes and Operator Families November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/indexes-opclass.html "PostgreSQL 18 - 11.10. Operator Classes and Operator Families") ([18](https://www.postgresql.org/docs/18/indexes-opclass.html "PostgreSQL 18 - 11.10. Operator Classes and Operator Families") ) / [17](https://www.postgresql.org/docs/17/indexes-opclass.html "PostgreSQL 17 - 11.10. Operator Classes and Operator Families") / [16](https://www.postgresql.org/docs/16/indexes-opclass.html "PostgreSQL 16 - 11.10. Operator Classes and Operator Families") / [15](https://www.postgresql.org/docs/15/indexes-opclass.html "PostgreSQL 15 - 11.10. Operator Classes and Operator Families") / [14](https://www.postgresql.org/docs/14/indexes-opclass.html "PostgreSQL 14 - 11.10. Operator Classes and Operator Families") Development Versions: [devel](https://www.postgresql.org/docs/devel/indexes-opclass.html "PostgreSQL devel - 11.10. Operator Classes and Operator Families") Unsupported versions: [13](https://www.postgresql.org/docs/13/indexes-opclass.html "PostgreSQL 13 - 11.10. Operator Classes and Operator Families") / [12](https://www.postgresql.org/docs/12/indexes-opclass.html "PostgreSQL 12 - 11.10. Operator Classes and Operator Families") / [11](https://www.postgresql.org/docs/11/indexes-opclass.html "PostgreSQL 11 - 11.10. Operator Classes and Operator Families") / [10](https://www.postgresql.org/docs/10/indexes-opclass.html "PostgreSQL 10 - 11.10. Operator Classes and Operator Families") / [9.6](https://www.postgresql.org/docs/9.6/indexes-opclass.html "PostgreSQL 9.6 - 11.10. Operator Classes and Operator Families") / [9.5](https://www.postgresql.org/docs/9.5/indexes-opclass.html "PostgreSQL 9.5 - 11.10. Operator Classes and Operator Families") / [9.4](https://www.postgresql.org/docs/9.4/indexes-opclass.html "PostgreSQL 9.4 - 11.10. Operator Classes and Operator Families") / [9.3](https://www.postgresql.org/docs/9.3/indexes-opclass.html "PostgreSQL 9.3 - 11.10. Operator Classes and Operator Families") / [9.2](https://www.postgresql.org/docs/9.2/indexes-opclass.html "PostgreSQL 9.2 - 11.10. Operator Classes and Operator Families") / [9.1](https://www.postgresql.org/docs/9.1/indexes-opclass.html "PostgreSQL 9.1 - 11.10. Operator Classes and Operator Families") / [9.0](https://www.postgresql.org/docs/9.0/indexes-opclass.html "PostgreSQL 9.0 - 11.10. Operator Classes and Operator Families") / [8.4](https://www.postgresql.org/docs/8.4/indexes-opclass.html "PostgreSQL 8.4 - 11.10. Operator Classes and Operator Families") / [8.3](https://www.postgresql.org/docs/8.3/indexes-opclass.html "PostgreSQL 8.3 - 11.10. Operator Classes and Operator Families") / [8.2](https://www.postgresql.org/docs/8.2/indexes-opclass.html "PostgreSQL 8.2 - 11.10. Operator Classes and Operator Families") / [8.1](https://www.postgresql.org/docs/8.1/indexes-opclass.html "PostgreSQL 8.1 - 11.10. Operator Classes and Operator Families") / [8.0](https://www.postgresql.org/docs/8.0/indexes-opclass.html "PostgreSQL 8.0 - 11.10. Operator Classes and Operator Families") / [7.4](https://www.postgresql.org/docs/7.4/indexes-opclass.html "PostgreSQL 7.4 - 11.10. Operator Classes and Operator Families") / [7.3](https://www.postgresql.org/docs/7.3/indexes-opclass.html "PostgreSQL 7.3 - 11.10. Operator Classes and Operator Families") / [7.2](https://www.postgresql.org/docs/7.2/indexes-opclass.html "PostgreSQL 7.2 - 11.10. Operator Classes and Operator Families") | 11.10. Operator Classes and Operator Families | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/indexes-index-only-scans.html "11.9. Index-Only Scans and Covering Indexes") | [Up](https://www.postgresql.org/docs/current/indexes.html "Chapter 11. Indexes") | Chapter 11. Indexes | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/indexes-collations.html "11.11. Indexes and Collations") | * * * 11.10. Operator Classes and Operator Families [#](https://www.postgresql.org/docs/current/indexes-opclass.html#INDEXES-OPCLASS) -------------------------------------------------------------------------------------------------------------------------------- An index definition can specify an _operator class_ for each column of an index. CREATE INDEX _`name`_ ON _`table`_ (_`column`_ _`opclass`_ \[ ( _`opclass_options`_ ) \] \[_`sort options`_\] \[, ...\]); The operator class identifies the operators to be used by the index for that column. For example, a B-tree index on the type `int4` would use the `int4_ops` class; this operator class includes comparison functions for values of type `int4`. In practice the default operator class for the column's data type is usually sufficient. The main reason for having operator classes is that for some data types, there could be more than one meaningful index behavior. For example, we might want to sort a complex-number data type either by absolute value or by real part. We could do this by defining two operator classes for the data type and then selecting the proper class when making an index. The operator class determines the basic sort ordering (which can then be modified by adding sort options `COLLATE`, `ASC`/`DESC` and/or `NULLS FIRST`/`NULLS LAST`). There are also some built-in operator classes besides the default ones: * The operator classes `text_pattern_ops`, `varchar_pattern_ops`, and `bpchar_pattern_ops` support B-tree indexes on the types `text`, `varchar`, and `char` respectively. The difference from the default operator classes is that the values are compared strictly character by character rather than according to the locale-specific collation rules. This makes these operator classes suitable for use by queries involving pattern matching expressions (`LIKE` or POSIX regular expressions) when the database does not use the standard “C” locale. As an example, you might index a `varchar` column like this: CREATE INDEX test\_index ON test\_table (col varchar\_pattern\_ops); Note that you should also create an index with the default operator class if you want queries involving ordinary `<`, `<=`, `>`, or `>=` comparisons to use an index. Such queries cannot use the ``_`xxx`__pattern_ops`` operator classes. (Ordinary equality comparisons can use these operator classes, however.) It is possible to create multiple indexes on the same column with different operator classes. If you do use the C locale, you do not need the ``_`xxx`__pattern_ops`` operator classes, because an index with the default operator class is usable for pattern-matching queries in the C locale. The following query shows all defined operator classes: SELECT am.amname AS index\_method, opc.opcname AS opclass\_name, opc.opcintype::regtype AS indexed\_type, opc.opcdefault AS is\_default FROM pg\_am am, pg\_opclass opc WHERE opc.opcmethod = am.oid ORDER BY index\_method, opclass\_name; An operator class is actually just a subset of a larger structure called an _operator family_. In cases where several data types have similar behaviors, it is frequently useful to define cross-data-type operators and allow these to work with indexes. To do this, the operator classes for each of the types must be grouped into the same operator family. The cross-type operators are members of the family, but are not associated with any single class within the family. This expanded version of the previous query shows the operator family each operator class belongs to: SELECT am.amname AS index\_method, opc.opcname AS opclass\_name, opf.opfname AS opfamily\_name, opc.opcintype::regtype AS indexed\_type, opc.opcdefault AS is\_default FROM pg\_am am, pg\_opclass opc, pg\_opfamily opf WHERE opc.opcmethod = am.oid AND opc.opcfamily = opf.oid ORDER BY index\_method, opclass\_name; This query shows all defined operator families and all the operators included in each family: SELECT am.amname AS index\_method, opf.opfname AS opfamily\_name, amop.amopopr::regoperator AS opfamily\_operator FROM pg\_am am, pg\_opfamily opf, pg\_amop amop WHERE opf.opfmethod = am.oid AND amop.amopfamily = opf.oid ORDER BY index\_method, opfamily\_name, opfamily\_operator; ### Tip [psql](https://www.postgresql.org/docs/current/app-psql.html "psql") has commands `\dAc`, `\dAf`, and `\dAo`, which provide slightly more sophisticated versions of these queries. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/indexes-index-only-scans.html "11.9. Index-Only Scans and Covering Indexes") | [Up](https://www.postgresql.org/docs/current/indexes.html "Chapter 11. Indexes") | [Next](https://www.postgresql.org/docs/current/indexes-collations.html "11.11. Indexes and Collations") | | 11.9. Index-Only Scans and Covering Indexes | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 11.11. Indexes and Collations | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/indexes-opclass.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 8.4: sequences November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 8.4](https://www.postgresql.org/docs/8.4/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-sequences.html "PostgreSQL 18 - sequences") ([18](https://www.postgresql.org/docs/18/infoschema-sequences.html "PostgreSQL 18 - sequences") ) / [17](https://www.postgresql.org/docs/17/infoschema-sequences.html "PostgreSQL 17 - sequences") / [16](https://www.postgresql.org/docs/16/infoschema-sequences.html "PostgreSQL 16 - sequences") / [15](https://www.postgresql.org/docs/15/infoschema-sequences.html "PostgreSQL 15 - sequences") / [14](https://www.postgresql.org/docs/14/infoschema-sequences.html "PostgreSQL 14 - sequences") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-sequences.html "PostgreSQL devel - sequences") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-sequences.html "PostgreSQL 13 - sequences") / [12](https://www.postgresql.org/docs/12/infoschema-sequences.html "PostgreSQL 12 - sequences") / [11](https://www.postgresql.org/docs/11/infoschema-sequences.html "PostgreSQL 11 - sequences") / [10](https://www.postgresql.org/docs/10/infoschema-sequences.html "PostgreSQL 10 - sequences") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-sequences.html "PostgreSQL 9.6 - sequences") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-sequences.html "PostgreSQL 9.5 - sequences") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-sequences.html "PostgreSQL 9.4 - sequences") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-sequences.html "PostgreSQL 9.3 - sequences") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-sequences.html "PostgreSQL 9.2 - sequences") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-sequences.html "PostgreSQL 9.1 - sequences") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-sequences.html "PostgreSQL 9.0 - sequences") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-sequences.html "PostgreSQL 8.4 - sequences") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-sequences.html "PostgreSQL 8.3 - sequences") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-sequences.html "PostgreSQL 8.2 - sequences") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/infoschema-sequences.html "PostgreSQL - sequences") version, or one of the other supported versions listed above instead. | PostgreSQL 8.4.22 Documentation | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/8.4/infoschema-schemata.html) | [Fast Backward](https://www.postgresql.org/docs/8.4/information-schema.html) | Chapter 33. The Information Schema | [Fast Forward](https://www.postgresql.org/docs/8.4/information-schema.html) | [Next](https://www.postgresql.org/docs/8.4/infoschema-sql-features.html) | * * * 33.35. sequences ================ The view sequences contains all sequences defined in the current database. Only those sequences are shown that the current user has access to (by way of being the owner or having some privilege). Table 33-33. sequences Columns | Name | Data Type | Description | | --- | --- | --- | | sequence\_catalog | sql\_identifier | Name of the database that contains the sequence (always the current database) | | sequence\_schema | sql\_identifier | Name of the schema that contains the sequence | | sequence\_name | sql\_identifier | Name of the sequence | | data\_type | character\_data | The data type of the sequence. In PostgreSQL, this is currently always bigint. | | numeric\_precision | cardinal\_number | This column contains the (declared or implicit) precision of the sequence data type (see above). The precision indicates the number of significant digits. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column numeric\_precision\_radix. | | numeric\_precision\_radix | cardinal\_number | This column indicates in which base the values in the columns numeric\_precision and numeric\_scale are expressed. The value is either 2 or 10. | | numeric\_scale | cardinal\_number | This column contains the (declared or implicit) scale of the sequence data type (see above). The scale indicates the number of significant digits to the right of the decimal point. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column numeric\_precision\_radix. | | maximum\_value | cardinal\_number | Not yet implemented | | minimum\_value | cardinal\_number | Not yet implemented | | increment | cardinal\_number | Not yet implemented | | cycle\_option | character\_data | Not yet implemented | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/8.4/infoschema-schemata.html) | [Home](https://www.postgresql.org/docs/8.4/index.html) | [Next](https://www.postgresql.org/docs/8.4/infoschema-sql-features.html) | | schemata | [Up](https://www.postgresql.org/docs/8.4/information-schema.html) | sql\_features | --- # PostgreSQL: Documentation: 18: VACUUM November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-vacuum.html "PostgreSQL 18 - VACUUM") ([18](https://www.postgresql.org/docs/18/sql-vacuum.html "PostgreSQL 18 - VACUUM") ) / [17](https://www.postgresql.org/docs/17/sql-vacuum.html "PostgreSQL 17 - VACUUM") / [16](https://www.postgresql.org/docs/16/sql-vacuum.html "PostgreSQL 16 - VACUUM") / [15](https://www.postgresql.org/docs/15/sql-vacuum.html "PostgreSQL 15 - VACUUM") / [14](https://www.postgresql.org/docs/14/sql-vacuum.html "PostgreSQL 14 - VACUUM") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-vacuum.html "PostgreSQL devel - VACUUM") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-vacuum.html "PostgreSQL 13 - VACUUM") / [12](https://www.postgresql.org/docs/12/sql-vacuum.html "PostgreSQL 12 - VACUUM") / [11](https://www.postgresql.org/docs/11/sql-vacuum.html "PostgreSQL 11 - VACUUM") / [10](https://www.postgresql.org/docs/10/sql-vacuum.html "PostgreSQL 10 - VACUUM") / [9.6](https://www.postgresql.org/docs/9.6/sql-vacuum.html "PostgreSQL 9.6 - VACUUM") / [9.5](https://www.postgresql.org/docs/9.5/sql-vacuum.html "PostgreSQL 9.5 - VACUUM") / [9.4](https://www.postgresql.org/docs/9.4/sql-vacuum.html "PostgreSQL 9.4 - VACUUM") / [9.3](https://www.postgresql.org/docs/9.3/sql-vacuum.html "PostgreSQL 9.3 - VACUUM") / [9.2](https://www.postgresql.org/docs/9.2/sql-vacuum.html "PostgreSQL 9.2 - VACUUM") / [9.1](https://www.postgresql.org/docs/9.1/sql-vacuum.html "PostgreSQL 9.1 - VACUUM") / [9.0](https://www.postgresql.org/docs/9.0/sql-vacuum.html "PostgreSQL 9.0 - VACUUM") / [8.4](https://www.postgresql.org/docs/8.4/sql-vacuum.html "PostgreSQL 8.4 - VACUUM") / [8.3](https://www.postgresql.org/docs/8.3/sql-vacuum.html "PostgreSQL 8.3 - VACUUM") / [8.2](https://www.postgresql.org/docs/8.2/sql-vacuum.html "PostgreSQL 8.2 - VACUUM") / [8.1](https://www.postgresql.org/docs/8.1/sql-vacuum.html "PostgreSQL 8.1 - VACUUM") / [8.0](https://www.postgresql.org/docs/8.0/sql-vacuum.html "PostgreSQL 8.0 - VACUUM") / [7.4](https://www.postgresql.org/docs/7.4/sql-vacuum.html "PostgreSQL 7.4 - VACUUM") / [7.3](https://www.postgresql.org/docs/7.3/sql-vacuum.html "PostgreSQL 7.3 - VACUUM") / [7.2](https://www.postgresql.org/docs/7.2/sql-vacuum.html "PostgreSQL 7.2 - VACUUM") / [7.1](https://www.postgresql.org/docs/7.1/sql-vacuum.html "PostgreSQL 7.1 - VACUUM") | VACUUM | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-update.html "UPDATE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-values.html "VALUES") | * * * VACUUM ------ VACUUM — garbage-collect and optionally analyze a database Synopsis -------- VACUUM \[ ( _`option`_ \[, ...\] ) \] \[ _`table_and_columns`_ \[, ...\] \] where _`option`_ can be one of: FULL \[ _`boolean`_ \] FREEZE \[ _`boolean`_ \] VERBOSE \[ _`boolean`_ \] ANALYZE \[ _`boolean`_ \] DISABLE\_PAGE\_SKIPPING \[ _`boolean`_ \] SKIP\_LOCKED \[ _`boolean`_ \] INDEX\_CLEANUP { AUTO | ON | OFF } PROCESS\_MAIN \[ _`boolean`_ \] PROCESS\_TOAST \[ _`boolean`_ \] TRUNCATE \[ _`boolean`_ \] PARALLEL _`integer`_ SKIP\_DATABASE\_STATS \[ _`boolean`_ \] ONLY\_DATABASE\_STATS \[ _`boolean`_ \] BUFFER\_USAGE\_LIMIT _`size`_ and _`table_and_columns`_ is: \[ ONLY \] _`table_name`_ \[ \* \] \[ ( _`column_name`_ \[, ...\] ) \] Description ----------- `VACUUM` reclaims storage occupied by dead tuples. In normal PostgreSQL operation, tuples that are deleted or obsoleted by an update are not physically removed from their table; they remain present until a `VACUUM` is done. Therefore it's necessary to do `VACUUM` periodically, especially on frequently-updated tables. Without a _`table_and_columns`_ list, `VACUUM` processes every table and materialized view in the current database that the current user has permission to vacuum. With a list, `VACUUM` processes only those table(s). `VACUUM ANALYZE` performs a `VACUUM` and then an `ANALYZE` for each selected table. This is a handy combination form for routine maintenance scripts. See [ANALYZE](https://www.postgresql.org/docs/18/sql-analyze.html "ANALYZE") for more details about its processing. Plain `VACUUM` (without `FULL`) simply reclaims space and makes it available for re-use. This form of the command can operate in parallel with normal reading and writing of the table, as an exclusive lock is not obtained. However, extra space is not returned to the operating system (in most cases); it's just kept available for re-use within the same table. It also allows us to leverage multiple CPUs in order to process indexes. This feature is known as _parallel vacuum_. To disable this feature, one can use `PARALLEL` option and specify parallel workers as zero. `VACUUM FULL` rewrites the entire contents of the table into a new disk file with no extra space, allowing unused space to be returned to the operating system. This form is much slower and requires an `ACCESS EXCLUSIVE` lock on each table while it is being processed. Parameters ---------- `FULL` Selects “full” vacuum, which can reclaim more space, but takes much longer and exclusively locks the table. This method also requires extra disk space, since it writes a new copy of the table and doesn't release the old copy until the operation is complete. Usually this should only be used when a significant amount of space needs to be reclaimed from within the table. `FREEZE` Selects aggressive “freezing” of tuples. Specifying `FREEZE` is equivalent to performing `VACUUM` with the [vacuum\_freeze\_min\_age](https://www.postgresql.org/docs/18/runtime-config-vacuum.html#GUC-VACUUM-FREEZE-MIN-AGE) and [vacuum\_freeze\_table\_age](https://www.postgresql.org/docs/18/runtime-config-vacuum.html#GUC-VACUUM-FREEZE-TABLE-AGE) parameters set to zero. Aggressive freezing is always performed when the table is rewritten, so this option is redundant when `FULL` is specified. `VERBOSE` Prints a detailed vacuum activity report for each table at `INFO` level. `ANALYZE` Updates statistics used by the planner to determine the most efficient way to execute a query. `DISABLE_PAGE_SKIPPING` Normally, `VACUUM` will skip pages based on the [visibility map](https://www.postgresql.org/docs/18/routine-vacuuming.html#VACUUM-FOR-VISIBILITY-MAP "24.1.4. Updating the Visibility Map") . Pages where all tuples are known to be frozen can always be skipped, and those where all tuples are known to be visible to all transactions may be skipped except when performing an aggressive vacuum. Furthermore, except when performing an aggressive vacuum, some pages may be skipped in order to avoid waiting for other sessions to finish using them. This option disables all page-skipping behavior, and is intended to be used only when the contents of the visibility map are suspect, which should happen only if there is a hardware or software issue causing database corruption. `SKIP_LOCKED` Specifies that `VACUUM` should not wait for any conflicting locks to be released when beginning work on a relation: if a relation cannot be locked immediately without waiting, the relation is skipped. Note that even with this option, `VACUUM` may still block when opening the relation's indexes. Additionally, `VACUUM ANALYZE` may still block when acquiring sample rows from partitions, table inheritance children, and some types of foreign tables. Also, while `VACUUM` ordinarily processes all partitions of specified partitioned tables, this option will cause `VACUUM` to skip all partitions if there is a conflicting lock on the partitioned table. `INDEX_CLEANUP` Normally, `VACUUM` will skip index vacuuming when there are very few dead tuples in the table. The cost of processing all of the table's indexes is expected to greatly exceed the benefit of removing dead index tuples when this happens. This option can be used to force `VACUUM` to process indexes when there are more than zero dead tuples. The default is `AUTO`, which allows `VACUUM` to skip index vacuuming when appropriate. If `INDEX_CLEANUP` is set to `ON`, `VACUUM` will conservatively remove all dead tuples from indexes. This may be useful for backwards compatibility with earlier releases of PostgreSQL where this was the standard behavior. `INDEX_CLEANUP` can also be set to `OFF` to force `VACUUM` to _always_ skip index vacuuming, even when there are many dead tuples in the table. This may be useful when it is necessary to make `VACUUM` run as quickly as possible to avoid imminent transaction ID wraparound (see [Section 24.1.5](https://www.postgresql.org/docs/18/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND "24.1.5. Preventing Transaction ID Wraparound Failures") ). However, the wraparound failsafe mechanism controlled by [vacuum\_failsafe\_age](https://www.postgresql.org/docs/18/runtime-config-vacuum.html#GUC-VACUUM-FAILSAFE-AGE) will generally trigger automatically to avoid transaction ID wraparound failure, and should be preferred. If index cleanup is not performed regularly, performance may suffer, because as the table is modified indexes will accumulate dead tuples and the table itself will accumulate dead line pointers that cannot be removed until index cleanup is completed. This option has no effect for tables that have no index and is ignored if the `FULL` option is used. It also has no effect on the transaction ID wraparound failsafe mechanism. When triggered it will skip index vacuuming, even when `INDEX_CLEANUP` is set to `ON`. `PROCESS_MAIN` Specifies that `VACUUM` should attempt to process the main relation. This is usually the desired behavior and is the default. Setting this option to false may be useful when it is only necessary to vacuum a relation's corresponding `TOAST` table. `PROCESS_TOAST` Specifies that `VACUUM` should attempt to process the corresponding `TOAST` table for each relation, if one exists. This is usually the desired behavior and is the default. Setting this option to false may be useful when it is only necessary to vacuum the main relation. This option is required when the `FULL` option is used. `TRUNCATE` Specifies that `VACUUM` should attempt to truncate off any empty pages at the end of the table and allow the disk space for the truncated pages to be returned to the operating system. This is normally the desired behavior and is the default unless [vacuum\_truncate](https://www.postgresql.org/docs/18/runtime-config-vacuum.html#GUC-VACUUM-TRUNCATE) is set to false or the `vacuum_truncate` option has been set to false for the table to be vacuumed. Setting this option to false may be useful to avoid `ACCESS EXCLUSIVE` lock on the table that the truncation requires. This option is ignored if the `FULL` option is used. `PARALLEL` Perform index vacuum and index cleanup phases of `VACUUM` in parallel using _`integer`_ background workers (for the details of each vacuum phase, please refer to [Table 27.46](https://www.postgresql.org/docs/18/progress-reporting.html#VACUUM-PHASES "Table 27.46. VACUUM Phases") ). The number of workers used to perform the operation is equal to the number of indexes on the relation that support parallel vacuum which is limited by the number of workers specified with `PARALLEL` option if any which is further limited by [max\_parallel\_maintenance\_workers](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-MAX-PARALLEL-MAINTENANCE-WORKERS) . An index can participate in parallel vacuum if and only if the size of the index is more than [min\_parallel\_index\_scan\_size](https://www.postgresql.org/docs/18/runtime-config-query.html#GUC-MIN-PARALLEL-INDEX-SCAN-SIZE) . Please note that it is not guaranteed that the number of parallel workers specified in _`integer`_ will be used during execution. It is possible for a vacuum to run with fewer workers than specified, or even with no workers at all. Only one worker can be used per index. So parallel workers are launched only when there are at least `2` indexes in the table. Workers for vacuum are launched before the start of each phase and exit at the end of the phase. These behaviors might change in a future release. This option can't be used with the `FULL` option. `SKIP_DATABASE_STATS` Specifies that `VACUUM` should skip updating the database-wide statistics about oldest unfrozen XIDs. Normally `VACUUM` will update these statistics once at the end of the command. However, this can take awhile in a database with a very large number of tables, and it will accomplish nothing unless the table that had contained the oldest unfrozen XID was among those vacuumed. Moreover, if multiple `VACUUM` commands are issued in parallel, only one of them can update the database-wide statistics at a time. Therefore, if an application intends to issue a series of many `VACUUM` commands, it can be helpful to set this option in all but the last such command; or set it in all the commands and separately issue `VACUUM (ONLY_DATABASE_STATS)` afterwards. `ONLY_DATABASE_STATS` Specifies that `VACUUM` should do nothing except update the database-wide statistics about oldest unfrozen XIDs. When this option is specified, the _`table_and_columns`_ list must be empty, and no other option may be enabled except `VERBOSE`. `BUFFER_USAGE_LIMIT` Specifies the [](https://www.postgresql.org/docs/18/glossary.html#GLOSSARY-BUFFER-ACCESS-STRATEGY) [Buffer Access Strategy](https://www.postgresql.org/docs/18/glossary.html#GLOSSARY-BUFFER-ACCESS-STRATEGY "Buffer Access Strategy") ring buffer size for `VACUUM`. This size is used to calculate the number of shared buffers which will be reused as part of this strategy. `0` disables use of a `Buffer Access Strategy`. If `ANALYZE` is also specified, the `BUFFER_USAGE_LIMIT` value is used for both the vacuum and analyze stages. This option can't be used with the `FULL` option except if `ANALYZE` is also specified. When this option is not specified, `VACUUM` uses the value from [vacuum\_buffer\_usage\_limit](https://www.postgresql.org/docs/18/runtime-config-resource.html#GUC-VACUUM-BUFFER-USAGE-LIMIT) . Higher settings can allow `VACUUM` to run more quickly, but having too large a setting may cause too many other useful pages to be evicted from shared buffers. The minimum value is `128 kB` and the maximum value is `16 GB`. _`boolean`_ Specifies whether the selected option should be turned on or off. You can write `TRUE`, `ON`, or `1` to enable the option, and `FALSE`, `OFF`, or `0` to disable it. The _`boolean`_ value can also be omitted, in which case `TRUE` is assumed. _`integer`_ Specifies a non-negative integer value passed to the selected option. _`size`_ Specifies an amount of memory in kilobytes. Sizes may also be specified as a string containing the numerical size followed by any one of the following memory units: `B` (bytes), `kB` (kilobytes), `MB` (megabytes), `GB` (gigabytes), or `TB` (terabytes). _`table_name`_ The name (optionally schema-qualified) of a specific table or materialized view to vacuum. If `ONLY` is specified before the table name, only that table is vacuumed. If `ONLY` is not specified, the table and all its inheritance child tables or partitions (if any) are also vacuumed. Optionally, `*` can be specified after the table name to explicitly indicate that inheritance child tables (or partitions) are to be vacuumed. _`column_name`_ The name of a specific column to analyze. Defaults to all columns. If a column list is specified, `ANALYZE` must also be specified. Outputs ------- When `VERBOSE` is specified, `VACUUM` emits progress messages to indicate which table is currently being processed. Various statistics about the tables are printed as well. Notes ----- To vacuum a table, one must ordinarily have the `MAINTAIN` privilege on the table. However, database owners are allowed to vacuum all tables in their databases, except shared catalogs. `VACUUM` will skip over any tables that the calling user does not have permission to vacuum. While `VACUUM` is running, the [search\_path](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-SEARCH-PATH) is temporarily changed to `pg_catalog, pg_temp`. `VACUUM` cannot be executed inside a transaction block. For tables with GIN indexes, `VACUUM` (in any form) also completes any pending index insertions, by moving pending index entries to the appropriate places in the main GIN index structure. See [Section 65.4.4.1](https://www.postgresql.org/docs/18/gin.html#GIN-FAST-UPDATE "65.4.4.1. GIN Fast Update Technique") for details. We recommend that all databases be vacuumed regularly in order to remove dead rows. PostgreSQL includes an “autovacuum” facility which can automate routine vacuum maintenance. For more information about automatic and manual vacuuming, see [Section 24.1](https://www.postgresql.org/docs/18/routine-vacuuming.html "24.1. Routine Vacuuming") . The `FULL` option is not recommended for routine use, but might be useful in special cases. An example is when you have deleted or updated most of the rows in a table and would like the table to physically shrink to occupy less disk space and allow faster table scans. `VACUUM FULL` will usually shrink the table more than a plain `VACUUM` would. The `PARALLEL` option is used only for vacuum purposes. If this option is specified with the `ANALYZE` option, it does not affect `ANALYZE`. `VACUUM` causes a substantial increase in I/O traffic, which might cause poor performance for other active sessions. Therefore, it is sometimes advisable to use the cost-based vacuum delay feature. For parallel vacuum, each worker sleeps in proportion to the work done by that worker. See [Section 19.10.2](https://www.postgresql.org/docs/18/runtime-config-vacuum.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST "19.10.2. Cost-based Vacuum Delay") for details. Each backend running `VACUUM` without the `FULL` option will report its progress in the `pg_stat_progress_vacuum` view. Backends running `VACUUM FULL` will instead report their progress in the `pg_stat_progress_cluster` view. See [Section 27.4.5](https://www.postgresql.org/docs/18/progress-reporting.html#VACUUM-PROGRESS-REPORTING "27.4.5. VACUUM Progress Reporting") and [Section 27.4.2](https://www.postgresql.org/docs/18/progress-reporting.html#CLUSTER-PROGRESS-REPORTING "27.4.2. CLUSTER Progress Reporting") for details. Examples -------- To clean a single table `onek`, analyze it for the optimizer and print a detailed vacuum activity report: VACUUM (VERBOSE, ANALYZE) onek; Compatibility ------------- There is no `VACUUM` statement in the SQL standard. The following syntax was used before PostgreSQL version 9.0 and is still supported: VACUUM \[ FULL \] \[ FREEZE \] \[ VERBOSE \] \[ ANALYZE \] \[ _`table_and_columns`_ \[, ...\] \] Note that in this syntax, the options must be specified in exactly the order shown. See Also -------- [vacuumdb](https://www.postgresql.org/docs/18/app-vacuumdb.html "vacuumdb") , [Section 19.10.2](https://www.postgresql.org/docs/18/runtime-config-vacuum.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST "19.10.2. Cost-based Vacuum Delay") , [Section 24.1.6](https://www.postgresql.org/docs/18/routine-vacuuming.html#AUTOVACUUM "24.1.6. The Autovacuum Daemon") , [Section 27.4.5](https://www.postgresql.org/docs/18/progress-reporting.html#VACUUM-PROGRESS-REPORTING "27.4.5. VACUUM Progress Reporting") , [Section 27.4.2](https://www.postgresql.org/docs/18/progress-reporting.html#CLUSTER-PROGRESS-REPORTING "27.4.2. CLUSTER Progress Reporting") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-update.html "UPDATE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-values.html "VALUES") | | UPDATE | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | VALUES | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-vacuum.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: LOCK November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-lock.html "PostgreSQL 18 - LOCK") ([18](https://www.postgresql.org/docs/18/sql-lock.html "PostgreSQL 18 - LOCK") ) / [17](https://www.postgresql.org/docs/17/sql-lock.html "PostgreSQL 17 - LOCK") / [16](https://www.postgresql.org/docs/16/sql-lock.html "PostgreSQL 16 - LOCK") / [15](https://www.postgresql.org/docs/15/sql-lock.html "PostgreSQL 15 - LOCK") / [14](https://www.postgresql.org/docs/14/sql-lock.html "PostgreSQL 14 - LOCK") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-lock.html "PostgreSQL devel - LOCK") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-lock.html "PostgreSQL 13 - LOCK") / [12](https://www.postgresql.org/docs/12/sql-lock.html "PostgreSQL 12 - LOCK") / [11](https://www.postgresql.org/docs/11/sql-lock.html "PostgreSQL 11 - LOCK") / [10](https://www.postgresql.org/docs/10/sql-lock.html "PostgreSQL 10 - LOCK") / [9.6](https://www.postgresql.org/docs/9.6/sql-lock.html "PostgreSQL 9.6 - LOCK") / [9.5](https://www.postgresql.org/docs/9.5/sql-lock.html "PostgreSQL 9.5 - LOCK") / [9.4](https://www.postgresql.org/docs/9.4/sql-lock.html "PostgreSQL 9.4 - LOCK") / [9.3](https://www.postgresql.org/docs/9.3/sql-lock.html "PostgreSQL 9.3 - LOCK") / [9.2](https://www.postgresql.org/docs/9.2/sql-lock.html "PostgreSQL 9.2 - LOCK") / [9.1](https://www.postgresql.org/docs/9.1/sql-lock.html "PostgreSQL 9.1 - LOCK") / [9.0](https://www.postgresql.org/docs/9.0/sql-lock.html "PostgreSQL 9.0 - LOCK") / [8.4](https://www.postgresql.org/docs/8.4/sql-lock.html "PostgreSQL 8.4 - LOCK") / [8.3](https://www.postgresql.org/docs/8.3/sql-lock.html "PostgreSQL 8.3 - LOCK") / [8.2](https://www.postgresql.org/docs/8.2/sql-lock.html "PostgreSQL 8.2 - LOCK") / [8.1](https://www.postgresql.org/docs/8.1/sql-lock.html "PostgreSQL 8.1 - LOCK") / [8.0](https://www.postgresql.org/docs/8.0/sql-lock.html "PostgreSQL 8.0 - LOCK") / [7.4](https://www.postgresql.org/docs/7.4/sql-lock.html "PostgreSQL 7.4 - LOCK") / [7.3](https://www.postgresql.org/docs/7.3/sql-lock.html "PostgreSQL 7.3 - LOCK") / [7.2](https://www.postgresql.org/docs/7.2/sql-lock.html "PostgreSQL 7.2 - LOCK") / [7.1](https://www.postgresql.org/docs/7.1/sql-lock.html "PostgreSQL 7.1 - LOCK") | LOCK | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-load.html "LOAD") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-merge.html "MERGE") | * * * LOCK ---- LOCK — lock a table Synopsis -------- LOCK \[ TABLE \] \[ ONLY \] _`name`_ \[ \* \] \[, ...\] \[ IN _`lockmode`_ MODE \] \[ NOWAIT \] where _`lockmode`_ is one of: ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE Description ----------- `LOCK TABLE` obtains a table-level lock, waiting if necessary for any conflicting locks to be released. If `NOWAIT` is specified, `LOCK TABLE` does not wait to acquire the desired lock: if it cannot be acquired immediately, the command is aborted and an error is emitted. Once obtained, the lock is held for the remainder of the current transaction. (There is no `UNLOCK TABLE` command; locks are always released at transaction end.) When a view is locked, all relations appearing in the view definition query are also locked recursively with the same lock mode. When acquiring locks automatically for commands that reference tables, PostgreSQL always uses the least restrictive lock mode possible. `LOCK TABLE` provides for cases when you might need more restrictive locking. For example, suppose an application runs a transaction at the `READ COMMITTED` isolation level and needs to ensure that data in a table remains stable for the duration of the transaction. To achieve this you could obtain `SHARE` lock mode over the table before querying. This will prevent concurrent data changes and ensure subsequent reads of the table see a stable view of committed data, because `SHARE` lock mode conflicts with the `ROW EXCLUSIVE` lock acquired by writers, and your ``LOCK TABLE _`name`_ IN SHARE MODE`` statement will wait until any concurrent holders of `ROW EXCLUSIVE` mode locks commit or roll back. Thus, once you obtain the lock, there are no uncommitted writes outstanding; furthermore none can begin until you release the lock. To achieve a similar effect when running a transaction at the `REPEATABLE READ` or `SERIALIZABLE` isolation level, you have to execute the `LOCK TABLE` statement before executing any `SELECT` or data modification statement. A `REPEATABLE READ` or `SERIALIZABLE` transaction's view of data will be frozen when its first `SELECT` or data modification statement begins. A `LOCK TABLE` later in the transaction will still prevent concurrent writes — but it won't ensure that what the transaction reads corresponds to the latest committed values. If a transaction of this sort is going to change the data in the table, then it should use `SHARE ROW EXCLUSIVE` lock mode instead of `SHARE` mode. This ensures that only one transaction of this type runs at a time. Without this, a deadlock is possible: two transactions might both acquire `SHARE` mode, and then be unable to also acquire `ROW EXCLUSIVE` mode to actually perform their updates. (Note that a transaction's own locks never conflict, so a transaction can acquire `ROW EXCLUSIVE` mode when it holds `SHARE` mode — but not if anyone else holds `SHARE` mode.) To avoid deadlocks, make sure all transactions acquire locks on the same objects in the same order, and if multiple lock modes are involved for a single object, then transactions should always acquire the most restrictive mode first. More information about the lock modes and locking strategies can be found in [Section 13.3](https://www.postgresql.org/docs/current/explicit-locking.html "13.3. Explicit Locking") . Parameters ---------- _`name`_ The name (optionally schema-qualified) of an existing table to lock. If `ONLY` is specified before the table name, only that table is locked. If `ONLY` is not specified, the table and all its descendant tables (if any) are locked. Optionally, `*` can be specified after the table name to explicitly indicate that descendant tables are included. The command `LOCK TABLE a, b;` is equivalent to `LOCK TABLE a; LOCK TABLE b;`. The tables are locked one-by-one in the order specified in the `LOCK TABLE` command. _`lockmode`_ The lock mode specifies which locks this lock conflicts with. Lock modes are described in [Section 13.3](https://www.postgresql.org/docs/current/explicit-locking.html "13.3. Explicit Locking") . If no lock mode is specified, then `ACCESS EXCLUSIVE`, the most restrictive mode, is used. `NOWAIT` Specifies that `LOCK TABLE` should not wait for any conflicting locks to be released: if the specified lock(s) cannot be acquired immediately without waiting, the transaction is aborted. Notes ----- To lock a table, the user must have the right privilege for the specified _`lockmode`_. If the user has `MAINTAIN`, `UPDATE`, `DELETE`, or `TRUNCATE` privileges on the table, any _`lockmode`_ is permitted. If the user has `INSERT` privileges on the table, `ROW EXCLUSIVE MODE` (or a less-conflicting mode as described in [Section 13.3](https://www.postgresql.org/docs/current/explicit-locking.html "13.3. Explicit Locking") ) is permitted. If a user has `SELECT` privileges on the table, `ACCESS SHARE MODE` is permitted. The user performing the lock on the view must have the corresponding privilege on the view. In addition, by default, the view's owner must have the relevant privileges on the underlying base relations, whereas the user performing the lock does not need any permissions on the underlying base relations. However, if the view has `security_invoker` set to `true` (see [`CREATE VIEW`](https://www.postgresql.org/docs/current/sql-createview.html "CREATE VIEW") ), the user performing the lock, rather than the view owner, must have the relevant privileges on the underlying base relations. `LOCK TABLE` is useless outside a transaction block: the lock would remain held only to the completion of the statement. Therefore PostgreSQL reports an error if `LOCK` is used outside a transaction block. Use [`BEGIN`](https://www.postgresql.org/docs/current/sql-begin.html "BEGIN") and [`COMMIT`](https://www.postgresql.org/docs/current/sql-commit.html "COMMIT") (or [`ROLLBACK`](https://www.postgresql.org/docs/current/sql-rollback.html "ROLLBACK") ) to define a transaction block. `LOCK TABLE` only deals with table-level locks, and so the mode names involving `ROW` are all misnomers. These mode names should generally be read as indicating the intention of the user to acquire row-level locks within the locked table. Also, `ROW EXCLUSIVE` mode is a shareable table lock. Keep in mind that all the lock modes have identical semantics so far as `LOCK TABLE` is concerned, differing only in the rules about which modes conflict with which. For information on how to acquire an actual row-level lock, see [Section 13.3.2](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS "13.3.2. Row-Level Locks") and [The Locking Clause](https://www.postgresql.org/docs/current/sql-select.html#SQL-FOR-UPDATE-SHARE "The Locking Clause") in the [SELECT](https://www.postgresql.org/docs/current/sql-select.html "SELECT") documentation. Examples -------- Obtain a `SHARE` lock on a primary key table when going to perform inserts into a foreign key table: BEGIN WORK; LOCK TABLE films IN SHARE MODE; SELECT id FROM films WHERE name = 'Star Wars: Episode I - The Phantom Menace'; -- Do ROLLBACK if record was not returned INSERT INTO films\_user\_comments VALUES (\_id\_, 'GREAT! I was waiting for it for so long!'); COMMIT WORK; Take a `SHARE ROW EXCLUSIVE` lock on a primary key table when going to perform a delete operation: BEGIN WORK; LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE; DELETE FROM films\_user\_comments WHERE id IN (SELECT id FROM films WHERE rating < 5); DELETE FROM films WHERE rating < 5; COMMIT WORK; Compatibility ------------- There is no `LOCK TABLE` in the SQL standard, which instead uses `SET TRANSACTION` to specify concurrency levels on transactions. PostgreSQL supports that too; see [SET TRANSACTION](https://www.postgresql.org/docs/current/sql-set-transaction.html "SET TRANSACTION") for details. Except for `ACCESS SHARE`, `ACCESS EXCLUSIVE`, and `SHARE UPDATE EXCLUSIVE` lock modes, the PostgreSQL lock modes and the `LOCK TABLE` syntax are compatible with those present in Oracle. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-load.html "LOAD") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-merge.html "MERGE") | | LOAD | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | MERGE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-lock.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 18. Server Setup and Operation November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/runtime.html "PostgreSQL 18 - Chapter 18. Server Setup and Operation") ([18](https://www.postgresql.org/docs/18/runtime.html "PostgreSQL 18 - Chapter 18. Server Setup and Operation") ) / [17](https://www.postgresql.org/docs/17/runtime.html "PostgreSQL 17 - Chapter 18. Server Setup and Operation") / [16](https://www.postgresql.org/docs/16/runtime.html "PostgreSQL 16 - Chapter 18. Server Setup and Operation") / [15](https://www.postgresql.org/docs/15/runtime.html "PostgreSQL 15 - Chapter 18. Server Setup and Operation") / [14](https://www.postgresql.org/docs/14/runtime.html "PostgreSQL 14 - Chapter 18. Server Setup and Operation") Development Versions: [devel](https://www.postgresql.org/docs/devel/runtime.html "PostgreSQL devel - Chapter 18. Server Setup and Operation") Unsupported versions: [13](https://www.postgresql.org/docs/13/runtime.html "PostgreSQL 13 - Chapter 18. Server Setup and Operation") / [12](https://www.postgresql.org/docs/12/runtime.html "PostgreSQL 12 - Chapter 18. Server Setup and Operation") / [11](https://www.postgresql.org/docs/11/runtime.html "PostgreSQL 11 - Chapter 18. Server Setup and Operation") / [10](https://www.postgresql.org/docs/10/runtime.html "PostgreSQL 10 - Chapter 18. Server Setup and Operation") / [9.6](https://www.postgresql.org/docs/9.6/runtime.html "PostgreSQL 9.6 - Chapter 18. Server Setup and Operation") / [9.5](https://www.postgresql.org/docs/9.5/runtime.html "PostgreSQL 9.5 - Chapter 18. Server Setup and Operation") / [9.4](https://www.postgresql.org/docs/9.4/runtime.html "PostgreSQL 9.4 - Chapter 18. Server Setup and Operation") / [9.3](https://www.postgresql.org/docs/9.3/runtime.html "PostgreSQL 9.3 - Chapter 18. Server Setup and Operation") / [9.2](https://www.postgresql.org/docs/9.2/runtime.html "PostgreSQL 9.2 - Chapter 18. Server Setup and Operation") / [9.1](https://www.postgresql.org/docs/9.1/runtime.html "PostgreSQL 9.1 - Chapter 18. Server Setup and Operation") / [9.0](https://www.postgresql.org/docs/9.0/runtime.html "PostgreSQL 9.0 - Chapter 18. Server Setup and Operation") / [8.4](https://www.postgresql.org/docs/8.4/runtime.html "PostgreSQL 8.4 - Chapter 18. Server Setup and Operation") / [8.3](https://www.postgresql.org/docs/8.3/runtime.html "PostgreSQL 8.3 - Chapter 18. Server Setup and Operation") / [8.2](https://www.postgresql.org/docs/8.2/runtime.html "PostgreSQL 8.2 - Chapter 18. Server Setup and Operation") / [8.1](https://www.postgresql.org/docs/8.1/runtime.html "PostgreSQL 8.1 - Chapter 18. Server Setup and Operation") / [8.0](https://www.postgresql.org/docs/8.0/runtime.html "PostgreSQL 8.0 - Chapter 18. Server Setup and Operation") / [7.4](https://www.postgresql.org/docs/7.4/runtime.html "PostgreSQL 7.4 - Chapter 18. Server Setup and Operation") / [7.3](https://www.postgresql.org/docs/7.3/runtime.html "PostgreSQL 7.3 - Chapter 18. Server Setup and Operation") / [7.2](https://www.postgresql.org/docs/7.2/runtime.html "PostgreSQL 7.2 - Chapter 18. Server Setup and Operation") / [7.1](https://www.postgresql.org/docs/7.1/runtime.html "PostgreSQL 7.1 - Chapter 18. Server Setup and Operation") | Chapter 18. Server Setup and Operation | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/installation-platform-notes.html "17.7. Platform-Specific Notes") | [Up](https://www.postgresql.org/docs/current/admin.html "Part III. Server Administration") | Part III. Server Administration | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/postgres-user.html "18.1. The PostgreSQL User Account") | * * * Chapter 18. Server Setup and Operation -------------------------------------- **Table of Contents** [18.1. The PostgreSQL User Account](https://www.postgresql.org/docs/current/postgres-user.html) [18.2. Creating a Database Cluster](https://www.postgresql.org/docs/current/creating-cluster.html) [18.2.1. Use of Secondary File Systems](https://www.postgresql.org/docs/current/creating-cluster.html#CREATING-CLUSTER-MOUNT-POINTS) [18.2.2. File Systems](https://www.postgresql.org/docs/current/creating-cluster.html#CREATING-CLUSTER-FILESYSTEM) [18.3. Starting the Database Server](https://www.postgresql.org/docs/current/server-start.html) [18.3.1. Server Start-up Failures](https://www.postgresql.org/docs/current/server-start.html#SERVER-START-FAILURES) [18.3.2. Client Connection Problems](https://www.postgresql.org/docs/current/server-start.html#CLIENT-CONNECTION-PROBLEMS) [18.4. Managing Kernel Resources](https://www.postgresql.org/docs/current/kernel-resources.html) [18.4.1. Shared Memory and Semaphores](https://www.postgresql.org/docs/current/kernel-resources.html#SYSVIPC) [18.4.2. systemd RemoveIPC](https://www.postgresql.org/docs/current/kernel-resources.html#SYSTEMD-REMOVEIPC) [18.4.3. Resource Limits](https://www.postgresql.org/docs/current/kernel-resources.html#KERNEL-RESOURCES-LIMITS) [18.4.4. Linux Memory Overcommit](https://www.postgresql.org/docs/current/kernel-resources.html#LINUX-MEMORY-OVERCOMMIT) [18.4.5. Linux Huge Pages](https://www.postgresql.org/docs/current/kernel-resources.html#LINUX-HUGE-PAGES) [18.5. Shutting Down the Server](https://www.postgresql.org/docs/current/server-shutdown.html) [18.6. Upgrading a PostgreSQL Cluster](https://www.postgresql.org/docs/current/upgrading.html) [18.6.1. Upgrading Data via pg\_dumpall](https://www.postgresql.org/docs/current/upgrading.html#UPGRADING-VIA-PGDUMPALL) [18.6.2. Upgrading Data via pg\_upgrade](https://www.postgresql.org/docs/current/upgrading.html#UPGRADING-VIA-PG-UPGRADE) [18.6.3. Upgrading Data via Replication](https://www.postgresql.org/docs/current/upgrading.html#UPGRADING-VIA-REPLICATION) [18.7. Preventing Server Spoofing](https://www.postgresql.org/docs/current/preventing-server-spoofing.html) [18.8. Encryption Options](https://www.postgresql.org/docs/current/encryption-options.html) [18.9. Secure TCP/IP Connections with SSL](https://www.postgresql.org/docs/current/ssl-tcp.html) [18.9.1. Basic Setup](https://www.postgresql.org/docs/current/ssl-tcp.html#SSL-SETUP) [18.9.2. OpenSSL Configuration](https://www.postgresql.org/docs/current/ssl-tcp.html#SSL-OPENSSL-CONFIG) [18.9.3. Using Client Certificates](https://www.postgresql.org/docs/current/ssl-tcp.html#SSL-CLIENT-CERTIFICATES) [18.9.4. SSL Server File Usage](https://www.postgresql.org/docs/current/ssl-tcp.html#SSL-SERVER-FILES) [18.9.5. Creating Certificates](https://www.postgresql.org/docs/current/ssl-tcp.html#SSL-CERTIFICATE-CREATION) [18.10. Secure TCP/IP Connections with GSSAPI Encryption](https://www.postgresql.org/docs/current/gssapi-enc.html) [18.10.1. Basic Setup](https://www.postgresql.org/docs/current/gssapi-enc.html#GSSAPI-SETUP) [18.11. Secure TCP/IP Connections with SSH Tunnels](https://www.postgresql.org/docs/current/ssh-tunnels.html) [18.12. Registering Event Log on Windows](https://www.postgresql.org/docs/current/event-log-registration.html) This chapter discusses how to set up and run the database server, and its interactions with the operating system. The directions in this chapter assume that you are working with plain PostgreSQL without any additional infrastructure, for example a copy that you built from source according to the directions in the preceding chapters. If you are working with a pre-packaged or vendor-supplied version of PostgreSQL, it is likely that the packager has made special provisions for installing and starting the database server according to your system's conventions. Consult the package-level documentation for details. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/installation-platform-notes.html "17.7. Platform-Specific Notes") | [Up](https://www.postgresql.org/docs/current/admin.html "Part III. Server Administration") | [Next](https://www.postgresql.org/docs/current/postgres-user.html "18.1. The PostgreSQL User Account") | | 17.7. Platform-Specific Notes | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 18.1. The PostgreSQL User Account | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/runtime.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 17.6. Supported Platforms November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/supported-platforms.html "PostgreSQL 18 - 17.6. Supported Platforms") ([18](https://www.postgresql.org/docs/18/supported-platforms.html "PostgreSQL 18 - 17.6. Supported Platforms") ) / [17](https://www.postgresql.org/docs/17/supported-platforms.html "PostgreSQL 17 - 17.6. Supported Platforms") / [16](https://www.postgresql.org/docs/16/supported-platforms.html "PostgreSQL 16 - 17.6. Supported Platforms") / [15](https://www.postgresql.org/docs/15/supported-platforms.html "PostgreSQL 15 - 17.6. Supported Platforms") / [14](https://www.postgresql.org/docs/14/supported-platforms.html "PostgreSQL 14 - 17.6. Supported Platforms") Development Versions: [devel](https://www.postgresql.org/docs/devel/supported-platforms.html "PostgreSQL devel - 17.6. Supported Platforms") Unsupported versions: [13](https://www.postgresql.org/docs/13/supported-platforms.html "PostgreSQL 13 - 17.6. Supported Platforms") / [12](https://www.postgresql.org/docs/12/supported-platforms.html "PostgreSQL 12 - 17.6. Supported Platforms") / [11](https://www.postgresql.org/docs/11/supported-platforms.html "PostgreSQL 11 - 17.6. Supported Platforms") / [10](https://www.postgresql.org/docs/10/supported-platforms.html "PostgreSQL 10 - 17.6. Supported Platforms") / [9.6](https://www.postgresql.org/docs/9.6/supported-platforms.html "PostgreSQL 9.6 - 17.6. Supported Platforms") / [9.5](https://www.postgresql.org/docs/9.5/supported-platforms.html "PostgreSQL 9.5 - 17.6. Supported Platforms") / [9.4](https://www.postgresql.org/docs/9.4/supported-platforms.html "PostgreSQL 9.4 - 17.6. Supported Platforms") / [9.3](https://www.postgresql.org/docs/9.3/supported-platforms.html "PostgreSQL 9.3 - 17.6. Supported Platforms") / [9.2](https://www.postgresql.org/docs/9.2/supported-platforms.html "PostgreSQL 9.2 - 17.6. Supported Platforms") / [9.1](https://www.postgresql.org/docs/9.1/supported-platforms.html "PostgreSQL 9.1 - 17.6. Supported Platforms") / [9.0](https://www.postgresql.org/docs/9.0/supported-platforms.html "PostgreSQL 9.0 - 17.6. Supported Platforms") / [8.4](https://www.postgresql.org/docs/8.4/supported-platforms.html "PostgreSQL 8.4 - 17.6. Supported Platforms") / [8.3](https://www.postgresql.org/docs/8.3/supported-platforms.html "PostgreSQL 8.3 - 17.6. Supported Platforms") / [8.2](https://www.postgresql.org/docs/8.2/supported-platforms.html "PostgreSQL 8.2 - 17.6. Supported Platforms") / [8.1](https://www.postgresql.org/docs/8.1/supported-platforms.html "PostgreSQL 8.1 - 17.6. Supported Platforms") / [8.0](https://www.postgresql.org/docs/8.0/supported-platforms.html "PostgreSQL 8.0 - 17.6. Supported Platforms") / [7.4](https://www.postgresql.org/docs/7.4/supported-platforms.html "PostgreSQL 7.4 - 17.6. Supported Platforms") / [7.3](https://www.postgresql.org/docs/7.3/supported-platforms.html "PostgreSQL 7.3 - 17.6. Supported Platforms") / [7.2](https://www.postgresql.org/docs/7.2/supported-platforms.html "PostgreSQL 7.2 - 17.6. Supported Platforms") / [7.1](https://www.postgresql.org/docs/7.1/supported-platforms.html "PostgreSQL 7.1 - 17.6. Supported Platforms") | 17.6. Supported Platforms | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/install-post.html "17.5. Post-Installation Setup") | [Up](https://www.postgresql.org/docs/current/installation.html "Chapter 17. Installation from Source Code") | Chapter 17. Installation from Source Code | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/installation-platform-notes.html "17.7. Platform-Specific Notes") | * * * 17.6. Supported Platforms [#](https://www.postgresql.org/docs/current/supported-platforms.html#SUPPORTED-PLATFORMS) -------------------------------------------------------------------------------------------------------------------- A platform (that is, a CPU architecture and operating system combination) is considered supported by the PostgreSQL development community if the code contains provisions to work on that platform and it has recently been verified to build and pass its regression tests on that platform. Currently, most testing of platform compatibility is done automatically by test machines in the [PostgreSQL Build Farm](https://buildfarm.postgresql.org/) . If you are interested in using PostgreSQL on a platform that is not represented in the build farm, but on which the code works or can be made to work, you are strongly encouraged to set up a build farm member machine so that continued compatibility can be assured. In general, PostgreSQL can be expected to work on these CPU architectures: x86, PowerPC, S/390, SPARC, ARM, MIPS, and RISC-V, including big-endian, little-endian, 32-bit, and 64-bit variants where applicable. PostgreSQL can be expected to work on current versions of these operating systems: Linux, Windows, FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, macOS, Solaris, and illumos. Other Unix-like systems may also work but are not currently being tested. In most cases, all CPU architectures supported by a given operating system will work. Look in [Section 17.7](https://www.postgresql.org/docs/current/installation-platform-notes.html "17.7. Platform-Specific Notes") below to see if there is information specific to your operating system, particularly if using an older system. If you have installation problems on a platform that is known to be supported according to recent build farm results, please report it to `<[pgsql-bugs@lists.postgresql.org](mailto:pgsql-bugs@lists.postgresql.org) >`. If you are interested in porting PostgreSQL to a new platform, `<[pgsql-hackers@lists.postgresql.org](mailto:pgsql-hackers@lists.postgresql.org) >` is the appropriate place to discuss that. Historical versions of PostgreSQL or POSTGRES also ran on CPU architectures including Alpha, Itanium, M32R, M68K, M88K, NS32K, PA-RISC, SuperH, and VAX, and operating systems including 4.3BSD, AIX, BEOS, BSD/OS, DG/UX, Dynix, HP-UX, IRIX, NeXTSTEP, QNX, SCO, SINIX, Sprite, SunOS, Tru64 UNIX, and ULTRIX. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/install-post.html "17.5. Post-Installation Setup") | [Up](https://www.postgresql.org/docs/current/installation.html "Chapter 17. Installation from Source Code") | [Next](https://www.postgresql.org/docs/current/installation-platform-notes.html "17.7. Platform-Specific Notes") | | 17.5. Post-Installation Setup | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 17.7. Platform-Specific Notes | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/supported-platforms.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 68.1. System Catalog Declaration Rules November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/system-catalog-declarations.html "PostgreSQL 18 - 68.1. System Catalog Declaration Rules") ([18](https://www.postgresql.org/docs/18/system-catalog-declarations.html "PostgreSQL 18 - 68.1. System Catalog Declaration Rules") ) / [17](https://www.postgresql.org/docs/17/system-catalog-declarations.html "PostgreSQL 17 - 68.1. System Catalog Declaration Rules") / [16](https://www.postgresql.org/docs/16/system-catalog-declarations.html "PostgreSQL 16 - 68.1. System Catalog Declaration Rules") / [15](https://www.postgresql.org/docs/15/system-catalog-declarations.html "PostgreSQL 15 - 68.1. System Catalog Declaration Rules") / [14](https://www.postgresql.org/docs/14/system-catalog-declarations.html "PostgreSQL 14 - 68.1. System Catalog Declaration Rules") Development Versions: [devel](https://www.postgresql.org/docs/devel/system-catalog-declarations.html "PostgreSQL devel - 68.1. System Catalog Declaration Rules") Unsupported versions: [13](https://www.postgresql.org/docs/13/system-catalog-declarations.html "PostgreSQL 13 - 68.1. System Catalog Declaration Rules") / [12](https://www.postgresql.org/docs/12/system-catalog-declarations.html "PostgreSQL 12 - 68.1. System Catalog Declaration Rules") / [11](https://www.postgresql.org/docs/11/system-catalog-declarations.html "PostgreSQL 11 - 68.1. System Catalog Declaration Rules") | 68.1. System Catalog Declaration Rules | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/bki.html "Chapter 68. System Catalog Declarations and Initial Contents") | [Up](https://www.postgresql.org/docs/18/bki.html "Chapter 68. System Catalog Declarations and Initial Contents") | Chapter 68. System Catalog Declarations and Initial Contents | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/system-catalog-initial-data.html "68.2. System Catalog Initial Data") | * * * 68.1. System Catalog Declaration Rules [#](https://www.postgresql.org/docs/18/system-catalog-declarations.html#SYSTEM-CATALOG-DECLARATIONS) -------------------------------------------------------------------------------------------------------------------------------------------- The key part of a catalog header file is a C structure definition describing the layout of each row of the catalog. This begins with a `CATALOG` macro, which so far as the C compiler is concerned is just shorthand for ``typedef struct FormData__`catalogname`_``. Each field in the struct gives rise to a catalog column. Fields can be annotated using the BKI property macros described in `genbki.h`, for example to define a default value for a field or mark it as nullable or not nullable. The `CATALOG` line can also be annotated, with some other BKI property macros described in `genbki.h`, to define other properties of the catalog as a whole, such as whether it is a shared relation. The system catalog cache code (and most catalog-munging code in general) assumes that the fixed-length portions of all system catalog tuples are in fact present, because it maps this C struct declaration onto them. Thus, all variable-length fields and nullable fields must be placed at the end, and they cannot be accessed as struct fields. For example, if you tried to set `pg_type`.`typrelid` to be NULL, it would fail when some piece of code tried to reference `typetup->typrelid` (or worse, `typetup->typelem`, because that follows `typrelid`). This would result in random errors or even segmentation violations. As a partial guard against this type of error, variable-length or nullable fields should not be made directly visible to the C compiler. This is accomplished by wrapping them in `#ifdef CATALOG_VARLEN` ... `#endif` (where `CATALOG_VARLEN` is a symbol that is never defined). This prevents C code from carelessly trying to access fields that might not be there or might be at some other offset. As an independent guard against creating incorrect rows, we require all columns that should be non-nullable to be marked so in `pg_attribute`. The bootstrap code will automatically mark catalog columns as `NOT NULL` if they are fixed-width and are not preceded by any nullable or variable-width column. Where this rule is inadequate, you can force correct marking by using `BKI_FORCE_NOT_NULL` and `BKI_FORCE_NULL` annotations as needed. Frontend code should not include any `pg_xxx.h` catalog header file, as these files may contain C code that won't compile outside the backend. (Typically, that happens because these files also contain declarations for functions in `src/backend/catalog/` files.) Instead, frontend code may include the corresponding generated `pg_xxx_d.h` header, which will contain OID `#define`s and any other data that might be of use on the client side. If you want macros or other code in a catalog header to be visible to frontend code, write `#ifdef EXPOSE_TO_CLIENT_CODE` ... `#endif` around that section to instruct `genbki.pl` to copy that section to the `pg_xxx_d.h` header. A few of the catalogs are so fundamental that they can't even be created by the BKI `create` command that's used for most catalogs, because that command needs to write information into these catalogs to describe the new catalog. These are called _bootstrap_ catalogs, and defining one takes a lot of extra work: you have to manually prepare appropriate entries for them in the pre-loaded contents of `pg_class` and `pg_type`, and those entries will need to be updated for subsequent changes to the catalog's structure. (Bootstrap catalogs also need pre-loaded entries in `pg_attribute`, but fortunately `genbki.pl` handles that chore nowadays.) Avoid making new catalogs be bootstrap catalogs if at all possible. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/bki.html "Chapter 68. System Catalog Declarations and Initial Contents") | [Up](https://www.postgresql.org/docs/18/bki.html "Chapter 68. System Catalog Declarations and Initial Contents") | [Next](https://www.postgresql.org/docs/18/system-catalog-initial-data.html "68.2. System Catalog Initial Data") | | Chapter 68. System Catalog Declarations and Initial Contents | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 68.2. System Catalog Initial Data | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/system-catalog-declarations.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 9.3: ALTER EXTENSION November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 9.3](https://www.postgresql.org/docs/9.3/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alterextension.html "PostgreSQL 18 - ALTER EXTENSION") ([18](https://www.postgresql.org/docs/18/sql-alterextension.html "PostgreSQL 18 - ALTER EXTENSION") ) / [17](https://www.postgresql.org/docs/17/sql-alterextension.html "PostgreSQL 17 - ALTER EXTENSION") / [16](https://www.postgresql.org/docs/16/sql-alterextension.html "PostgreSQL 16 - ALTER EXTENSION") / [15](https://www.postgresql.org/docs/15/sql-alterextension.html "PostgreSQL 15 - ALTER EXTENSION") / [14](https://www.postgresql.org/docs/14/sql-alterextension.html "PostgreSQL 14 - ALTER EXTENSION") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alterextension.html "PostgreSQL devel - ALTER EXTENSION") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alterextension.html "PostgreSQL 13 - ALTER EXTENSION") / [12](https://www.postgresql.org/docs/12/sql-alterextension.html "PostgreSQL 12 - ALTER EXTENSION") / [11](https://www.postgresql.org/docs/11/sql-alterextension.html "PostgreSQL 11 - ALTER EXTENSION") / [10](https://www.postgresql.org/docs/10/sql-alterextension.html "PostgreSQL 10 - ALTER EXTENSION") / [9.6](https://www.postgresql.org/docs/9.6/sql-alterextension.html "PostgreSQL 9.6 - ALTER EXTENSION") / [9.5](https://www.postgresql.org/docs/9.5/sql-alterextension.html "PostgreSQL 9.5 - ALTER EXTENSION") / [9.4](https://www.postgresql.org/docs/9.4/sql-alterextension.html "PostgreSQL 9.4 - ALTER EXTENSION") / [9.3](https://www.postgresql.org/docs/9.3/sql-alterextension.html "PostgreSQL 9.3 - ALTER EXTENSION") / [9.2](https://www.postgresql.org/docs/9.2/sql-alterextension.html "PostgreSQL 9.2 - ALTER EXTENSION") / [9.1](https://www.postgresql.org/docs/9.1/sql-alterextension.html "PostgreSQL 9.1 - ALTER EXTENSION") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/sql-alterextension.html "PostgreSQL - ALTER EXTENSION") version, or one of the other supported versions listed above instead. | [PostgreSQL 9.3.25 Documentation](https://www.postgresql.org/docs/9.3/index.html) | | | | | | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/sql-altereventtrigger.html "ALTER EVENT TRIGGER") | [Up](https://www.postgresql.org/docs/9.3/sql-commands.html) | | [Next](https://www.postgresql.org/docs/9.3/sql-alterforeigndatawrapper.html "ALTER FOREIGN DATA WRAPPER") | * * * ALTER EXTENSION =============== Name ---- ALTER EXTENSION --  change the definition of an extension Synopsis -------- ALTER EXTENSION name UPDATE \[ TO new\_version \] ALTER EXTENSION name SET SCHEMA new\_schema ALTER EXTENSION name ADD member\_object ALTER EXTENSION name DROP member\_object where member\_object is: AGGREGATE agg\_name (agg\_type \[, ...\] ) | CAST (source\_type AS target\_type) | COLLATION object\_name | CONVERSION object\_name | DOMAIN object\_name | EVENT TRIGGER object\_name | FOREIGN DATA WRAPPER object\_name | FOREIGN TABLE object\_name | FUNCTION function\_name ( \[ \[ argmode \] \[ argname \] argtype \[, ...\] \] ) | MATERIALIZED VIEW object\_name | OPERATOR operator\_name (left\_type, right\_type) | OPERATOR CLASS object\_name USING index\_method | OPERATOR FAMILY object\_name USING index\_method | \[ PROCEDURAL \] LANGUAGE object\_name | SCHEMA object\_name | SEQUENCE object\_name | SERVER object\_name | TABLE object\_name | TEXT SEARCH CONFIGURATION object\_name | TEXT SEARCH DICTIONARY object\_name | TEXT SEARCH PARSER object\_name | TEXT SEARCH TEMPLATE object\_name | TYPE object\_name | VIEW object\_name Description ----------- ALTER EXTENSION changes the definition of an installed extension. There are several subforms: UPDATE This form updates the extension to a newer version. The extension must supply a suitable update script (or series of scripts) that can modify the currently-installed version into the requested version. SET SCHEMA This form moves the extension's objects into another schema. The extension has to be _relocatable_ for this command to succeed. ADD member\_object This form adds an existing object to the extension. This is mainly useful in extension update scripts. The object will subsequently be treated as a member of the extension; notably, it can only be dropped by dropping the extension. DROP member\_object This form removes a member object from the extension. This is mainly useful in extension update scripts. The object is not dropped, only disassociated from the extension. See [Section 35.15](https://www.postgresql.org/docs/9.3/extend-extensions.html) for more information about these operations. You must own the extension to use ALTER EXTENSION. The ADD/DROP forms require ownership of the added/dropped object as well. Parameters ---------- name The name of an installed extension. new\_version The desired new version of the extension. This can be written as either an identifier or a string literal. If not specified, ALTER EXTENSION UPDATE attempts to update to whatever is shown as the default version in the extension's control file. new\_schema The new schema for the extension. object\_name agg\_name function\_name operator\_name The name of an object to be added to or removed from the extension. Names of tables, aggregates, domains, foreign tables, functions, operators, operator classes, operator families, sequences, text search objects, types, and views can be schema-qualified. agg\_type An input data type on which the aggregate function operates. To reference a zero-argument aggregate function, write \* in place of the list of input data types. source\_type The name of the source data type of the cast. target\_type The name of the target data type of the cast. argmode The mode of a function argument: IN, OUT, INOUT, or VARIADIC. If omitted, the default is IN. Note that ALTER EXTENSION does not actually pay any attention to OUT arguments, since only the input arguments are needed to determine the function's identity. So it is sufficient to list the IN, INOUT, and VARIADIC arguments. argname The name of a function argument. Note that ALTER EXTENSION does not actually pay any attention to argument names, since only the argument data types are needed to determine the function's identity. argtype The data type(s) of the function's arguments (optionally schema-qualified), if any. left\_type right\_type The data type(s) of the operator's arguments (optionally schema-qualified). Write NONE for the missing argument of a prefix or postfix operator. PROCEDURAL This is a noise word. Examples -------- To update the hstore extension to version 2.0: ALTER EXTENSION hstore UPDATE TO '2.0'; To change the schema of the hstore extension to utils: ALTER EXTENSION hstore SET SCHEMA utils; To add an existing function to the hstore extension: ALTER EXTENSION hstore ADD FUNCTION populate\_record(anyelement, hstore); Compatibility ------------- ALTER EXTENSION is a PostgreSQL extension. See Also -------- [CREATE EXTENSION](https://www.postgresql.org/docs/9.3/sql-createextension.html) , [DROP EXTENSION](https://www.postgresql.org/docs/9.3/sql-dropextension.html) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/sql-altereventtrigger.html) | [Home](https://www.postgresql.org/docs/9.3/index.html) | [Next](https://www.postgresql.org/docs/9.3/sql-alterforeigndatawrapper.html) | | ALTER EVENT TRIGGER | [Up](https://www.postgresql.org/docs/9.3/sql-commands.html) | ALTER FOREIGN DATA WRAPPER | --- # PostgreSQL: Documentation: 18: 32.23. Example Programs November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/libpq-example.html "PostgreSQL 18 - 32.23. Example Programs") ([18](https://www.postgresql.org/docs/18/libpq-example.html "PostgreSQL 18 - 32.23. Example Programs") ) / [17](https://www.postgresql.org/docs/17/libpq-example.html "PostgreSQL 17 - 32.23. Example Programs") / [16](https://www.postgresql.org/docs/16/libpq-example.html "PostgreSQL 16 - 32.23. Example Programs") / [15](https://www.postgresql.org/docs/15/libpq-example.html "PostgreSQL 15 - 32.23. Example Programs") / [14](https://www.postgresql.org/docs/14/libpq-example.html "PostgreSQL 14 - 32.23. Example Programs") Development Versions: [devel](https://www.postgresql.org/docs/devel/libpq-example.html "PostgreSQL devel - 32.23. Example Programs") Unsupported versions: [13](https://www.postgresql.org/docs/13/libpq-example.html "PostgreSQL 13 - 32.23. Example Programs") / [12](https://www.postgresql.org/docs/12/libpq-example.html "PostgreSQL 12 - 32.23. Example Programs") / [11](https://www.postgresql.org/docs/11/libpq-example.html "PostgreSQL 11 - 32.23. Example Programs") / [10](https://www.postgresql.org/docs/10/libpq-example.html "PostgreSQL 10 - 32.23. Example Programs") / [9.6](https://www.postgresql.org/docs/9.6/libpq-example.html "PostgreSQL 9.6 - 32.23. Example Programs") / [9.5](https://www.postgresql.org/docs/9.5/libpq-example.html "PostgreSQL 9.5 - 32.23. Example Programs") / [9.4](https://www.postgresql.org/docs/9.4/libpq-example.html "PostgreSQL 9.4 - 32.23. Example Programs") / [9.3](https://www.postgresql.org/docs/9.3/libpq-example.html "PostgreSQL 9.3 - 32.23. Example Programs") / [9.2](https://www.postgresql.org/docs/9.2/libpq-example.html "PostgreSQL 9.2 - 32.23. Example Programs") / [9.1](https://www.postgresql.org/docs/9.1/libpq-example.html "PostgreSQL 9.1 - 32.23. Example Programs") / [9.0](https://www.postgresql.org/docs/9.0/libpq-example.html "PostgreSQL 9.0 - 32.23. Example Programs") / [8.4](https://www.postgresql.org/docs/8.4/libpq-example.html "PostgreSQL 8.4 - 32.23. Example Programs") / [8.3](https://www.postgresql.org/docs/8.3/libpq-example.html "PostgreSQL 8.3 - 32.23. Example Programs") / [8.2](https://www.postgresql.org/docs/8.2/libpq-example.html "PostgreSQL 8.2 - 32.23. Example Programs") / [8.1](https://www.postgresql.org/docs/8.1/libpq-example.html "PostgreSQL 8.1 - 32.23. Example Programs") / [8.0](https://www.postgresql.org/docs/8.0/libpq-example.html "PostgreSQL 8.0 - 32.23. Example Programs") / [7.4](https://www.postgresql.org/docs/7.4/libpq-example.html "PostgreSQL 7.4 - 32.23. Example Programs") / [7.3](https://www.postgresql.org/docs/7.3/libpq-example.html "PostgreSQL 7.3 - 32.23. Example Programs") / [7.2](https://www.postgresql.org/docs/7.2/libpq-example.html "PostgreSQL 7.2 - 32.23. Example Programs") / [7.1](https://www.postgresql.org/docs/7.1/libpq-example.html "PostgreSQL 7.1 - 32.23. Example Programs") | 32.23. Example Programs | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/libpq-build.html "32.22. Building libpq Programs") | [Up](https://www.postgresql.org/docs/current/libpq.html "Chapter 32. libpq — C Library") | Chapter 32. libpq — C Library | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/largeobjects.html "Chapter 33. Large Objects") | * * * 32.23. Example Programs [#](https://www.postgresql.org/docs/current/libpq-example.html#LIBPQ-EXAMPLE) ------------------------------------------------------------------------------------------------------ These examples and others can be found in the directory `src/test/examples` in the source code distribution. **Example 32.1. libpq Example Program 1** /\* \* src/test/examples/testlibpq.c \* \* \* testlibpq.c \* \* Test the C version of libpq, the PostgreSQL frontend library. \*/ #include #include #include "libpq-fe.h" static void exit\_nicely(PGconn \*conn) { PQfinish(conn); exit(1); } int main(int argc, char \*\*argv) { const char \*conninfo; PGconn \*conn; PGresult \*res; int nFields; int i, j; /\* \* If the user supplies a parameter on the command line, use it as the \* conninfo string; otherwise default to setting dbname=postgres and using \* environment variables or defaults for all other connection parameters. \*/ if (argc > 1) conninfo = argv\[1\]; else conninfo = "dbname = postgres"; /\* Make a connection to the database \*/ conn = PQconnectdb(conninfo); /\* Check to see that the backend connection was successfully made \*/ if (PQstatus(conn) != CONNECTION\_OK) { fprintf(stderr, "%s", PQerrorMessage(conn)); exit\_nicely(conn); } /\* Set always-secure search path, so malicious users can't take control. \*/ res = PQexec(conn, "SELECT pg\_catalog.set\_config('search\_path', '', false)"); if (PQresultStatus(res) != PGRES\_TUPLES\_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } /\* \* Should PQclear PGresult whenever it is no longer needed to avoid memory \* leaks \*/ PQclear(res); /\* \* Our test case here involves using a cursor, for which we must be inside \* a transaction block. We could do the whole thing with a single \* PQexec() of "select \* from pg\_database", but that's too trivial to make \* a good example. \*/ /\* Start a transaction block \*/ res = PQexec(conn, "BEGIN"); if (PQresultStatus(res) != PGRES\_COMMAND\_OK) { fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } PQclear(res); /\* \* Fetch rows from pg\_database, the system catalog of databases \*/ res = PQexec(conn, "DECLARE myportal CURSOR FOR select \* from pg\_database"); if (PQresultStatus(res) != PGRES\_COMMAND\_OK) { fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } PQclear(res); res = PQexec(conn, "FETCH ALL in myportal"); if (PQresultStatus(res) != PGRES\_TUPLES\_OK) { fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } /\* first, print out the attribute names \*/ nFields = PQnfields(res); for (i = 0; i < nFields; i++) printf("%-15s", PQfname(res, i)); printf("\\n\\n"); /\* next, print out the rows \*/ for (i = 0; i < PQntuples(res); i++) { for (j = 0; j < nFields; j++) printf("%-15s", PQgetvalue(res, i, j)); printf("\\n"); } PQclear(res); /\* close the portal ... we don't bother to check for errors ... \*/ res = PQexec(conn, "CLOSE myportal"); PQclear(res); /\* end the transaction \*/ res = PQexec(conn, "END"); PQclear(res); /\* close the connection to the database and cleanup \*/ PQfinish(conn); return 0; } **Example 32.2. libpq Example Program 2** /\* \* src/test/examples/testlibpq2.c \* \* \* testlibpq2.c \* Test of the asynchronous notification interface \* \* Start this program, then from psql in another window do \* NOTIFY TBL2; \* Repeat four times to get this program to exit. \* \* Or, if you want to get fancy, try this: \* populate a database with the following commands \* (provided in src/test/examples/testlibpq2.sql): \* \* CREATE SCHEMA TESTLIBPQ2; \* SET search\_path = TESTLIBPQ2; \* CREATE TABLE TBL1 (i int4); \* CREATE TABLE TBL2 (i int4); \* CREATE RULE r1 AS ON INSERT TO TBL1 DO \* (INSERT INTO TBL2 VALUES (new.i); NOTIFY TBL2); \* \* Start this program, then from psql do this four times: \* \* INSERT INTO TESTLIBPQ2.TBL1 VALUES (10); \*/ #ifdef WIN32 #include #endif #include #include #include #include #include #include #include #include "libpq-fe.h" static void exit\_nicely(PGconn \*conn) { PQfinish(conn); exit(1); } int main(int argc, char \*\*argv) { const char \*conninfo; PGconn \*conn; PGresult \*res; PGnotify \*notify; int nnotifies; /\* \* If the user supplies a parameter on the command line, use it as the \* conninfo string; otherwise default to setting dbname=postgres and using \* environment variables or defaults for all other connection parameters. \*/ if (argc > 1) conninfo = argv\[1\]; else conninfo = "dbname = postgres"; /\* Make a connection to the database \*/ conn = PQconnectdb(conninfo); /\* Check to see that the backend connection was successfully made \*/ if (PQstatus(conn) != CONNECTION\_OK) { fprintf(stderr, "%s", PQerrorMessage(conn)); exit\_nicely(conn); } /\* Set always-secure search path, so malicious users can't take control. \*/ res = PQexec(conn, "SELECT pg\_catalog.set\_config('search\_path', '', false)"); if (PQresultStatus(res) != PGRES\_TUPLES\_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } /\* \* Should PQclear PGresult whenever it is no longer needed to avoid memory \* leaks \*/ PQclear(res); /\* \* Issue LISTEN command to enable notifications from the rule's NOTIFY. \*/ res = PQexec(conn, "LISTEN TBL2"); if (PQresultStatus(res) != PGRES\_COMMAND\_OK) { fprintf(stderr, "LISTEN command failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } PQclear(res); /\* Quit after four notifies are received. \*/ nnotifies = 0; while (nnotifies < 4) { /\* \* Sleep until something happens on the connection. We use select(2) \* to wait for input, but you could also use poll() or similar \* facilities. \*/ int sock; fd\_set input\_mask; sock = PQsocket(conn); if (sock < 0) break; /\* shouldn't happen \*/ FD\_ZERO(&input\_mask); FD\_SET(sock, &input\_mask); if (select(sock + 1, &input\_mask, NULL, NULL, NULL) < 0) { fprintf(stderr, "select() failed: %s\\n", strerror(errno)); exit\_nicely(conn); } /\* Now check for input \*/ PQconsumeInput(conn); while ((notify = PQnotifies(conn)) != NULL) { fprintf(stderr, "ASYNC NOTIFY of '%s' received from backend PID %d\\n", notify->relname, notify->be\_pid); PQfreemem(notify); nnotifies++; PQconsumeInput(conn); } } fprintf(stderr, "Done.\\n"); /\* close the connection to the database and cleanup \*/ PQfinish(conn); return 0; } **Example 32.3. libpq Example Program 3** /\* \* src/test/examples/testlibpq3.c \* \* \* testlibpq3.c \* Test out-of-line parameters and binary I/O. \* \* Before running this, populate a database with the following commands \* (provided in src/test/examples/testlibpq3.sql): \* \* CREATE SCHEMA testlibpq3; \* SET search\_path = testlibpq3; \* SET standard\_conforming\_strings = ON; \* CREATE TABLE test1 (i int4, t text, b bytea); \* INSERT INTO test1 values (1, 'joe''s place', '\\000\\001\\002\\003\\004'); \* INSERT INTO test1 values (2, 'ho there', '\\004\\003\\002\\001\\000'); \* \* The expected output is: \* \* tuple 0: got \* i = (4 bytes) 1 \* t = (11 bytes) 'joe's place' \* b = (5 bytes) \\000\\001\\002\\003\\004 \* \* tuple 0: got \* i = (4 bytes) 2 \* t = (8 bytes) 'ho there' \* b = (5 bytes) \\004\\003\\002\\001\\000 \*/ #ifdef WIN32 #include #endif #include #include #include #include #include #include "libpq-fe.h" /\* for ntohl/htonl \*/ #include #include static void exit\_nicely(PGconn \*conn) { PQfinish(conn); exit(1); } /\* \* This function prints a query result that is a binary-format fetch from \* a table defined as in the comment above. We split it out because the \* main() function uses it twice. \*/ static void show\_binary\_results(PGresult \*res) { int i, j; int i\_fnum, t\_fnum, b\_fnum; /\* Use PQfnumber to avoid assumptions about field order in result \*/ i\_fnum = PQfnumber(res, "i"); t\_fnum = PQfnumber(res, "t"); b\_fnum = PQfnumber(res, "b"); for (i = 0; i < PQntuples(res); i++) { char \*iptr; char \*tptr; char \*bptr; int blen; int ival; /\* Get the field values (we ignore possibility they are null!) \*/ iptr = PQgetvalue(res, i, i\_fnum); tptr = PQgetvalue(res, i, t\_fnum); bptr = PQgetvalue(res, i, b\_fnum); /\* \* The binary representation of INT4 is in network byte order, which \* we'd better coerce to the local byte order. \*/ ival = ntohl(\*((uint32\_t \*) iptr)); /\* \* The binary representation of TEXT is, well, text, and since libpq \* was nice enough to append a zero byte to it, it'll work just fine \* as a C string. \* \* The binary representation of BYTEA is a bunch of bytes, which could \* include embedded nulls so we have to pay attention to field length. \*/ blen = PQgetlength(res, i, b\_fnum); printf("tuple %d: got\\n", i); printf(" i = (%d bytes) %d\\n", PQgetlength(res, i, i\_fnum), ival); printf(" t = (%d bytes) '%s'\\n", PQgetlength(res, i, t\_fnum), tptr); printf(" b = (%d bytes) ", blen); for (j = 0; j < blen; j++) printf("\\\\%03o", bptr\[j\]); printf("\\n\\n"); } } int main(int argc, char \*\*argv) { const char \*conninfo; PGconn \*conn; PGresult \*res; const char \*paramValues\[1\]; int paramLengths\[1\]; int paramFormats\[1\]; uint32\_t binaryIntVal; /\* \* If the user supplies a parameter on the command line, use it as the \* conninfo string; otherwise default to setting dbname=postgres and using \* environment variables or defaults for all other connection parameters. \*/ if (argc > 1) conninfo = argv\[1\]; else conninfo = "dbname = postgres"; /\* Make a connection to the database \*/ conn = PQconnectdb(conninfo); /\* Check to see that the backend connection was successfully made \*/ if (PQstatus(conn) != CONNECTION\_OK) { fprintf(stderr, "%s", PQerrorMessage(conn)); exit\_nicely(conn); } /\* Set always-secure search path, so malicious users can't take control. \*/ res = PQexec(conn, "SET search\_path = testlibpq3"); if (PQresultStatus(res) != PGRES\_COMMAND\_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } PQclear(res); /\* \* The point of this program is to illustrate use of PQexecParams() with \* out-of-line parameters, as well as binary transmission of data. \* \* This first example transmits the parameters as text, but receives the \* results in binary format. By using out-of-line parameters we can avoid \* a lot of tedious mucking about with quoting and escaping, even though \* the data is text. Notice how we don't have to do anything special with \* the quote mark in the parameter value. \*/ /\* Here is our out-of-line parameter value \*/ paramValues\[0\] = "joe's place"; res = PQexecParams(conn, "SELECT \* FROM test1 WHERE t = $1", 1, /\* one param \*/ NULL, /\* let the backend deduce param type \*/ paramValues, NULL, /\* don't need param lengths since text \*/ NULL, /\* default to all text params \*/ 1); /\* ask for binary results \*/ if (PQresultStatus(res) != PGRES\_TUPLES\_OK) { fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } show\_binary\_results(res); PQclear(res); /\* \* In this second example we transmit an integer parameter in binary form, \* and again retrieve the results in binary form. \* \* Although we tell PQexecParams we are letting the backend deduce \* parameter type, we really force the decision by casting the parameter \* symbol in the query text. This is a good safety measure when sending \* binary parameters. \*/ /\* Convert integer value "2" to network byte order \*/ binaryIntVal = htonl((uint32\_t) 2); /\* Set up parameter arrays for PQexecParams \*/ paramValues\[0\] = (char \*) &binaryIntVal; paramLengths\[0\] = sizeof(binaryIntVal); paramFormats\[0\] = 1; /\* binary \*/ res = PQexecParams(conn, "SELECT \* FROM test1 WHERE i = $1::int4", 1, /\* one param \*/ NULL, /\* let the backend deduce param type \*/ paramValues, paramLengths, paramFormats, 1); /\* ask for binary results \*/ if (PQresultStatus(res) != PGRES\_TUPLES\_OK) { fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } show\_binary\_results(res); PQclear(res); /\* close the connection to the database and cleanup \*/ PQfinish(conn); return 0; } * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/libpq-build.html "32.22. Building libpq Programs") | [Up](https://www.postgresql.org/docs/current/libpq.html "Chapter 32. libpq — C Library") | [Next](https://www.postgresql.org/docs/current/largeobjects.html "Chapter 33. Large Objects") | | 32.22. Building libpq Programs | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Chapter 33. Large Objects | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/libpq-example.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 32.23. Example Programs November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/libpq-example.html "PostgreSQL 18 - 32.23. Example Programs") ([18](https://www.postgresql.org/docs/18/libpq-example.html "PostgreSQL 18 - 32.23. Example Programs") ) / [17](https://www.postgresql.org/docs/17/libpq-example.html "PostgreSQL 17 - 32.23. Example Programs") / [16](https://www.postgresql.org/docs/16/libpq-example.html "PostgreSQL 16 - 32.23. Example Programs") / [15](https://www.postgresql.org/docs/15/libpq-example.html "PostgreSQL 15 - 32.23. Example Programs") / [14](https://www.postgresql.org/docs/14/libpq-example.html "PostgreSQL 14 - 32.23. Example Programs") Development Versions: [devel](https://www.postgresql.org/docs/devel/libpq-example.html "PostgreSQL devel - 32.23. Example Programs") Unsupported versions: [13](https://www.postgresql.org/docs/13/libpq-example.html "PostgreSQL 13 - 32.23. Example Programs") / [12](https://www.postgresql.org/docs/12/libpq-example.html "PostgreSQL 12 - 32.23. Example Programs") / [11](https://www.postgresql.org/docs/11/libpq-example.html "PostgreSQL 11 - 32.23. Example Programs") / [10](https://www.postgresql.org/docs/10/libpq-example.html "PostgreSQL 10 - 32.23. Example Programs") / [9.6](https://www.postgresql.org/docs/9.6/libpq-example.html "PostgreSQL 9.6 - 32.23. Example Programs") / [9.5](https://www.postgresql.org/docs/9.5/libpq-example.html "PostgreSQL 9.5 - 32.23. Example Programs") / [9.4](https://www.postgresql.org/docs/9.4/libpq-example.html "PostgreSQL 9.4 - 32.23. Example Programs") / [9.3](https://www.postgresql.org/docs/9.3/libpq-example.html "PostgreSQL 9.3 - 32.23. Example Programs") / [9.2](https://www.postgresql.org/docs/9.2/libpq-example.html "PostgreSQL 9.2 - 32.23. Example Programs") / [9.1](https://www.postgresql.org/docs/9.1/libpq-example.html "PostgreSQL 9.1 - 32.23. Example Programs") / [9.0](https://www.postgresql.org/docs/9.0/libpq-example.html "PostgreSQL 9.0 - 32.23. Example Programs") / [8.4](https://www.postgresql.org/docs/8.4/libpq-example.html "PostgreSQL 8.4 - 32.23. Example Programs") / [8.3](https://www.postgresql.org/docs/8.3/libpq-example.html "PostgreSQL 8.3 - 32.23. Example Programs") / [8.2](https://www.postgresql.org/docs/8.2/libpq-example.html "PostgreSQL 8.2 - 32.23. Example Programs") / [8.1](https://www.postgresql.org/docs/8.1/libpq-example.html "PostgreSQL 8.1 - 32.23. Example Programs") / [8.0](https://www.postgresql.org/docs/8.0/libpq-example.html "PostgreSQL 8.0 - 32.23. Example Programs") / [7.4](https://www.postgresql.org/docs/7.4/libpq-example.html "PostgreSQL 7.4 - 32.23. Example Programs") / [7.3](https://www.postgresql.org/docs/7.3/libpq-example.html "PostgreSQL 7.3 - 32.23. Example Programs") / [7.2](https://www.postgresql.org/docs/7.2/libpq-example.html "PostgreSQL 7.2 - 32.23. Example Programs") / [7.1](https://www.postgresql.org/docs/7.1/libpq-example.html "PostgreSQL 7.1 - 32.23. Example Programs") | 32.23. Example Programs | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/libpq-build.html "32.22. Building libpq Programs") | [Up](https://www.postgresql.org/docs/18/libpq.html "Chapter 32. libpq — C Library") | Chapter 32. libpq — C Library | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/largeobjects.html "Chapter 33. Large Objects") | * * * 32.23. Example Programs [#](https://www.postgresql.org/docs/18/libpq-example.html#LIBPQ-EXAMPLE) ------------------------------------------------------------------------------------------------- These examples and others can be found in the directory `src/test/examples` in the source code distribution. **Example 32.1. libpq Example Program 1** /\* \* src/test/examples/testlibpq.c \* \* \* testlibpq.c \* \* Test the C version of libpq, the PostgreSQL frontend library. \*/ #include #include #include "libpq-fe.h" static void exit\_nicely(PGconn \*conn) { PQfinish(conn); exit(1); } int main(int argc, char \*\*argv) { const char \*conninfo; PGconn \*conn; PGresult \*res; int nFields; int i, j; /\* \* If the user supplies a parameter on the command line, use it as the \* conninfo string; otherwise default to setting dbname=postgres and using \* environment variables or defaults for all other connection parameters. \*/ if (argc > 1) conninfo = argv\[1\]; else conninfo = "dbname = postgres"; /\* Make a connection to the database \*/ conn = PQconnectdb(conninfo); /\* Check to see that the backend connection was successfully made \*/ if (PQstatus(conn) != CONNECTION\_OK) { fprintf(stderr, "%s", PQerrorMessage(conn)); exit\_nicely(conn); } /\* Set always-secure search path, so malicious users can't take control. \*/ res = PQexec(conn, "SELECT pg\_catalog.set\_config('search\_path', '', false)"); if (PQresultStatus(res) != PGRES\_TUPLES\_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } /\* \* Should PQclear PGresult whenever it is no longer needed to avoid memory \* leaks \*/ PQclear(res); /\* \* Our test case here involves using a cursor, for which we must be inside \* a transaction block. We could do the whole thing with a single \* PQexec() of "select \* from pg\_database", but that's too trivial to make \* a good example. \*/ /\* Start a transaction block \*/ res = PQexec(conn, "BEGIN"); if (PQresultStatus(res) != PGRES\_COMMAND\_OK) { fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } PQclear(res); /\* \* Fetch rows from pg\_database, the system catalog of databases \*/ res = PQexec(conn, "DECLARE myportal CURSOR FOR select \* from pg\_database"); if (PQresultStatus(res) != PGRES\_COMMAND\_OK) { fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } PQclear(res); res = PQexec(conn, "FETCH ALL in myportal"); if (PQresultStatus(res) != PGRES\_TUPLES\_OK) { fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } /\* first, print out the attribute names \*/ nFields = PQnfields(res); for (i = 0; i < nFields; i++) printf("%-15s", PQfname(res, i)); printf("\\n\\n"); /\* next, print out the rows \*/ for (i = 0; i < PQntuples(res); i++) { for (j = 0; j < nFields; j++) printf("%-15s", PQgetvalue(res, i, j)); printf("\\n"); } PQclear(res); /\* close the portal ... we don't bother to check for errors ... \*/ res = PQexec(conn, "CLOSE myportal"); PQclear(res); /\* end the transaction \*/ res = PQexec(conn, "END"); PQclear(res); /\* close the connection to the database and cleanup \*/ PQfinish(conn); return 0; } **Example 32.2. libpq Example Program 2** /\* \* src/test/examples/testlibpq2.c \* \* \* testlibpq2.c \* Test of the asynchronous notification interface \* \* Start this program, then from psql in another window do \* NOTIFY TBL2; \* Repeat four times to get this program to exit. \* \* Or, if you want to get fancy, try this: \* populate a database with the following commands \* (provided in src/test/examples/testlibpq2.sql): \* \* CREATE SCHEMA TESTLIBPQ2; \* SET search\_path = TESTLIBPQ2; \* CREATE TABLE TBL1 (i int4); \* CREATE TABLE TBL2 (i int4); \* CREATE RULE r1 AS ON INSERT TO TBL1 DO \* (INSERT INTO TBL2 VALUES (new.i); NOTIFY TBL2); \* \* Start this program, then from psql do this four times: \* \* INSERT INTO TESTLIBPQ2.TBL1 VALUES (10); \*/ #ifdef WIN32 #include #endif #include #include #include #include #include #include #include #include "libpq-fe.h" static void exit\_nicely(PGconn \*conn) { PQfinish(conn); exit(1); } int main(int argc, char \*\*argv) { const char \*conninfo; PGconn \*conn; PGresult \*res; PGnotify \*notify; int nnotifies; /\* \* If the user supplies a parameter on the command line, use it as the \* conninfo string; otherwise default to setting dbname=postgres and using \* environment variables or defaults for all other connection parameters. \*/ if (argc > 1) conninfo = argv\[1\]; else conninfo = "dbname = postgres"; /\* Make a connection to the database \*/ conn = PQconnectdb(conninfo); /\* Check to see that the backend connection was successfully made \*/ if (PQstatus(conn) != CONNECTION\_OK) { fprintf(stderr, "%s", PQerrorMessage(conn)); exit\_nicely(conn); } /\* Set always-secure search path, so malicious users can't take control. \*/ res = PQexec(conn, "SELECT pg\_catalog.set\_config('search\_path', '', false)"); if (PQresultStatus(res) != PGRES\_TUPLES\_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } /\* \* Should PQclear PGresult whenever it is no longer needed to avoid memory \* leaks \*/ PQclear(res); /\* \* Issue LISTEN command to enable notifications from the rule's NOTIFY. \*/ res = PQexec(conn, "LISTEN TBL2"); if (PQresultStatus(res) != PGRES\_COMMAND\_OK) { fprintf(stderr, "LISTEN command failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } PQclear(res); /\* Quit after four notifies are received. \*/ nnotifies = 0; while (nnotifies < 4) { /\* \* Sleep until something happens on the connection. We use select(2) \* to wait for input, but you could also use poll() or similar \* facilities. \*/ int sock; fd\_set input\_mask; sock = PQsocket(conn); if (sock < 0) break; /\* shouldn't happen \*/ FD\_ZERO(&input\_mask); FD\_SET(sock, &input\_mask); if (select(sock + 1, &input\_mask, NULL, NULL, NULL) < 0) { fprintf(stderr, "select() failed: %s\\n", strerror(errno)); exit\_nicely(conn); } /\* Now check for input \*/ PQconsumeInput(conn); while ((notify = PQnotifies(conn)) != NULL) { fprintf(stderr, "ASYNC NOTIFY of '%s' received from backend PID %d\\n", notify->relname, notify->be\_pid); PQfreemem(notify); nnotifies++; PQconsumeInput(conn); } } fprintf(stderr, "Done.\\n"); /\* close the connection to the database and cleanup \*/ PQfinish(conn); return 0; } **Example 32.3. libpq Example Program 3** /\* \* src/test/examples/testlibpq3.c \* \* \* testlibpq3.c \* Test out-of-line parameters and binary I/O. \* \* Before running this, populate a database with the following commands \* (provided in src/test/examples/testlibpq3.sql): \* \* CREATE SCHEMA testlibpq3; \* SET search\_path = testlibpq3; \* SET standard\_conforming\_strings = ON; \* CREATE TABLE test1 (i int4, t text, b bytea); \* INSERT INTO test1 values (1, 'joe''s place', '\\000\\001\\002\\003\\004'); \* INSERT INTO test1 values (2, 'ho there', '\\004\\003\\002\\001\\000'); \* \* The expected output is: \* \* tuple 0: got \* i = (4 bytes) 1 \* t = (11 bytes) 'joe's place' \* b = (5 bytes) \\000\\001\\002\\003\\004 \* \* tuple 0: got \* i = (4 bytes) 2 \* t = (8 bytes) 'ho there' \* b = (5 bytes) \\004\\003\\002\\001\\000 \*/ #ifdef WIN32 #include #endif #include #include #include #include #include #include "libpq-fe.h" /\* for ntohl/htonl \*/ #include #include static void exit\_nicely(PGconn \*conn) { PQfinish(conn); exit(1); } /\* \* This function prints a query result that is a binary-format fetch from \* a table defined as in the comment above. We split it out because the \* main() function uses it twice. \*/ static void show\_binary\_results(PGresult \*res) { int i, j; int i\_fnum, t\_fnum, b\_fnum; /\* Use PQfnumber to avoid assumptions about field order in result \*/ i\_fnum = PQfnumber(res, "i"); t\_fnum = PQfnumber(res, "t"); b\_fnum = PQfnumber(res, "b"); for (i = 0; i < PQntuples(res); i++) { char \*iptr; char \*tptr; char \*bptr; int blen; int ival; /\* Get the field values (we ignore possibility they are null!) \*/ iptr = PQgetvalue(res, i, i\_fnum); tptr = PQgetvalue(res, i, t\_fnum); bptr = PQgetvalue(res, i, b\_fnum); /\* \* The binary representation of INT4 is in network byte order, which \* we'd better coerce to the local byte order. \*/ ival = ntohl(\*((uint32\_t \*) iptr)); /\* \* The binary representation of TEXT is, well, text, and since libpq \* was nice enough to append a zero byte to it, it'll work just fine \* as a C string. \* \* The binary representation of BYTEA is a bunch of bytes, which could \* include embedded nulls so we have to pay attention to field length. \*/ blen = PQgetlength(res, i, b\_fnum); printf("tuple %d: got\\n", i); printf(" i = (%d bytes) %d\\n", PQgetlength(res, i, i\_fnum), ival); printf(" t = (%d bytes) '%s'\\n", PQgetlength(res, i, t\_fnum), tptr); printf(" b = (%d bytes) ", blen); for (j = 0; j < blen; j++) printf("\\\\%03o", bptr\[j\]); printf("\\n\\n"); } } int main(int argc, char \*\*argv) { const char \*conninfo; PGconn \*conn; PGresult \*res; const char \*paramValues\[1\]; int paramLengths\[1\]; int paramFormats\[1\]; uint32\_t binaryIntVal; /\* \* If the user supplies a parameter on the command line, use it as the \* conninfo string; otherwise default to setting dbname=postgres and using \* environment variables or defaults for all other connection parameters. \*/ if (argc > 1) conninfo = argv\[1\]; else conninfo = "dbname = postgres"; /\* Make a connection to the database \*/ conn = PQconnectdb(conninfo); /\* Check to see that the backend connection was successfully made \*/ if (PQstatus(conn) != CONNECTION\_OK) { fprintf(stderr, "%s", PQerrorMessage(conn)); exit\_nicely(conn); } /\* Set always-secure search path, so malicious users can't take control. \*/ res = PQexec(conn, "SET search\_path = testlibpq3"); if (PQresultStatus(res) != PGRES\_COMMAND\_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } PQclear(res); /\* \* The point of this program is to illustrate use of PQexecParams() with \* out-of-line parameters, as well as binary transmission of data. \* \* This first example transmits the parameters as text, but receives the \* results in binary format. By using out-of-line parameters we can avoid \* a lot of tedious mucking about with quoting and escaping, even though \* the data is text. Notice how we don't have to do anything special with \* the quote mark in the parameter value. \*/ /\* Here is our out-of-line parameter value \*/ paramValues\[0\] = "joe's place"; res = PQexecParams(conn, "SELECT \* FROM test1 WHERE t = $1", 1, /\* one param \*/ NULL, /\* let the backend deduce param type \*/ paramValues, NULL, /\* don't need param lengths since text \*/ NULL, /\* default to all text params \*/ 1); /\* ask for binary results \*/ if (PQresultStatus(res) != PGRES\_TUPLES\_OK) { fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } show\_binary\_results(res); PQclear(res); /\* \* In this second example we transmit an integer parameter in binary form, \* and again retrieve the results in binary form. \* \* Although we tell PQexecParams we are letting the backend deduce \* parameter type, we really force the decision by casting the parameter \* symbol in the query text. This is a good safety measure when sending \* binary parameters. \*/ /\* Convert integer value "2" to network byte order \*/ binaryIntVal = htonl((uint32\_t) 2); /\* Set up parameter arrays for PQexecParams \*/ paramValues\[0\] = (char \*) &binaryIntVal; paramLengths\[0\] = sizeof(binaryIntVal); paramFormats\[0\] = 1; /\* binary \*/ res = PQexecParams(conn, "SELECT \* FROM test1 WHERE i = $1::int4", 1, /\* one param \*/ NULL, /\* let the backend deduce param type \*/ paramValues, paramLengths, paramFormats, 1); /\* ask for binary results \*/ if (PQresultStatus(res) != PGRES\_TUPLES\_OK) { fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn)); PQclear(res); exit\_nicely(conn); } show\_binary\_results(res); PQclear(res); /\* close the connection to the database and cleanup \*/ PQfinish(conn); return 0; } * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/libpq-build.html "32.22. Building libpq Programs") | [Up](https://www.postgresql.org/docs/18/libpq.html "Chapter 32. libpq — C Library") | [Next](https://www.postgresql.org/docs/18/largeobjects.html "Chapter 33. Large Objects") | | 32.22. Building libpq Programs | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | Chapter 33. Large Objects | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/libpq-example.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 9.2: sequences November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 9.2](https://www.postgresql.org/docs/9.2/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-sequences.html "PostgreSQL 18 - sequences") ([18](https://www.postgresql.org/docs/18/infoschema-sequences.html "PostgreSQL 18 - sequences") ) / [17](https://www.postgresql.org/docs/17/infoschema-sequences.html "PostgreSQL 17 - sequences") / [16](https://www.postgresql.org/docs/16/infoschema-sequences.html "PostgreSQL 16 - sequences") / [15](https://www.postgresql.org/docs/15/infoschema-sequences.html "PostgreSQL 15 - sequences") / [14](https://www.postgresql.org/docs/14/infoschema-sequences.html "PostgreSQL 14 - sequences") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-sequences.html "PostgreSQL devel - sequences") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-sequences.html "PostgreSQL 13 - sequences") / [12](https://www.postgresql.org/docs/12/infoschema-sequences.html "PostgreSQL 12 - sequences") / [11](https://www.postgresql.org/docs/11/infoschema-sequences.html "PostgreSQL 11 - sequences") / [10](https://www.postgresql.org/docs/10/infoschema-sequences.html "PostgreSQL 10 - sequences") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-sequences.html "PostgreSQL 9.6 - sequences") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-sequences.html "PostgreSQL 9.5 - sequences") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-sequences.html "PostgreSQL 9.4 - sequences") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-sequences.html "PostgreSQL 9.3 - sequences") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-sequences.html "PostgreSQL 9.2 - sequences") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-sequences.html "PostgreSQL 9.1 - sequences") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-sequences.html "PostgreSQL 9.0 - sequences") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-sequences.html "PostgreSQL 8.4 - sequences") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-sequences.html "PostgreSQL 8.3 - sequences") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-sequences.html "PostgreSQL 8.2 - sequences") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/infoschema-sequences.html "PostgreSQL - sequences") version, or one of the other supported versions listed above instead. | [PostgreSQL 9.2.24 Documentation](https://www.postgresql.org/docs/9.2/index.html) | | | | | | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.2/infoschema-schemata.html "schemata") | [Up](https://www.postgresql.org/docs/9.2/information-schema.html) | Chapter 34. The Information Schema | [Next](https://www.postgresql.org/docs/9.2/infoschema-sql-features.html "sql_features") | * * * 34.42. sequences ================ The view sequences contains all sequences defined in the current database. Only those sequences are shown that the current user has access to (by way of being the owner or having some privilege). Table 34-40. sequences Columns | Name | Data Type | Description | | --- | --- | --- | | sequence\_catalog | sql\_identifier | Name of the database that contains the sequence (always the current database) | | sequence\_schema | sql\_identifier | Name of the schema that contains the sequence | | sequence\_name | sql\_identifier | Name of the sequence | | data\_type | character\_data | The data type of the sequence. In PostgreSQL, this is currently always bigint. | | numeric\_precision | cardinal\_number | This column contains the (declared or implicit) precision of the sequence data type (see above). The precision indicates the number of significant digits. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column numeric\_precision\_radix. | | numeric\_precision\_radix | cardinal\_number | This column indicates in which base the values in the columns numeric\_precision and numeric\_scale are expressed. The value is either 2 or 10. | | numeric\_scale | cardinal\_number | This column contains the (declared or implicit) scale of the sequence data type (see above). The scale indicates the number of significant digits to the right of the decimal point. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column numeric\_precision\_radix. | | start\_value | character\_data | The start value of the sequence | | minimum\_value | character\_data | The minimum value of the sequence | | maximum\_value | character\_data | The maximum value of the sequence | | increment | character\_data | The increment of the sequence | | cycle\_option | yes\_or\_no | YES if the sequence cycles, else NO | Note that in accordance with the SQL standard, the start, minimum, maximum, and increment values are returned as character strings. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.2/infoschema-schemata.html) | [Home](https://www.postgresql.org/docs/9.2/index.html) | [Next](https://www.postgresql.org/docs/9.2/infoschema-sql-features.html) | | schemata | [Up](https://www.postgresql.org/docs/9.2/information-schema.html) | sql\_features | --- # PostgreSQL: Documentation: 18: IMPORT FOREIGN SCHEMA November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-importforeignschema.html "PostgreSQL 18 - IMPORT FOREIGN SCHEMA") ([18](https://www.postgresql.org/docs/18/sql-importforeignschema.html "PostgreSQL 18 - IMPORT FOREIGN SCHEMA") ) / [17](https://www.postgresql.org/docs/17/sql-importforeignschema.html "PostgreSQL 17 - IMPORT FOREIGN SCHEMA") / [16](https://www.postgresql.org/docs/16/sql-importforeignschema.html "PostgreSQL 16 - IMPORT FOREIGN SCHEMA") / [15](https://www.postgresql.org/docs/15/sql-importforeignschema.html "PostgreSQL 15 - IMPORT FOREIGN SCHEMA") / [14](https://www.postgresql.org/docs/14/sql-importforeignschema.html "PostgreSQL 14 - IMPORT FOREIGN SCHEMA") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-importforeignschema.html "PostgreSQL devel - IMPORT FOREIGN SCHEMA") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-importforeignschema.html "PostgreSQL 13 - IMPORT FOREIGN SCHEMA") / [12](https://www.postgresql.org/docs/12/sql-importforeignschema.html "PostgreSQL 12 - IMPORT FOREIGN SCHEMA") / [11](https://www.postgresql.org/docs/11/sql-importforeignschema.html "PostgreSQL 11 - IMPORT FOREIGN SCHEMA") / [10](https://www.postgresql.org/docs/10/sql-importforeignschema.html "PostgreSQL 10 - IMPORT FOREIGN SCHEMA") / [9.6](https://www.postgresql.org/docs/9.6/sql-importforeignschema.html "PostgreSQL 9.6 - IMPORT FOREIGN SCHEMA") / [9.5](https://www.postgresql.org/docs/9.5/sql-importforeignschema.html "PostgreSQL 9.5 - IMPORT FOREIGN SCHEMA") | IMPORT FOREIGN SCHEMA | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-grant.html "GRANT") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-insert.html "INSERT") | * * * IMPORT FOREIGN SCHEMA --------------------- IMPORT FOREIGN SCHEMA — import table definitions from a foreign server Synopsis -------- IMPORT FOREIGN SCHEMA _`remote_schema`_ \[ { LIMIT TO | EXCEPT } ( _`table_name`_ \[, ...\] ) \] FROM SERVER _`server_name`_ INTO _`local_schema`_ \[ OPTIONS ( _`option`_ '_`value`_' \[, ... \] ) \] Description ----------- `IMPORT FOREIGN SCHEMA` creates foreign tables that represent tables existing on a foreign server. The new foreign tables will be owned by the user issuing the command and are created with the correct column definitions and options to match the remote tables. By default, all tables and views existing in a particular schema on the foreign server are imported. Optionally, the list of tables can be limited to a specified subset, or specific tables can be excluded. The new foreign tables are all created in the target schema, which must already exist. To use `IMPORT FOREIGN SCHEMA`, the user must have `USAGE` privilege on the foreign server, as well as `CREATE` privilege on the target schema. Parameters ---------- _`remote_schema`_ The remote schema to import from. The specific meaning of a remote schema depends on the foreign data wrapper in use. ``LIMIT TO ( _`table_name`_ [, ...] )`` Import only foreign tables matching one of the given table names. Other tables existing in the foreign schema will be ignored. ``EXCEPT ( _`table_name`_ [, ...] )`` Exclude specified foreign tables from the import. All tables existing in the foreign schema will be imported except the ones listed here. _`server_name`_ The foreign server to import from. _`local_schema`_ The schema in which the imported foreign tables will be created. ``OPTIONS ( _`option`_ '_`value`_' [, ...] )`` Options to be used during the import. The allowed option names and values are specific to each foreign data wrapper. Examples -------- Import table definitions from a remote schema `foreign_films` on server `film_server`, creating the foreign tables in local schema `films`: IMPORT FOREIGN SCHEMA foreign\_films FROM SERVER film\_server INTO films; As above, but import only the two tables `actors` and `directors` (if they exist): IMPORT FOREIGN SCHEMA foreign\_films LIMIT TO (actors, directors) FROM SERVER film\_server INTO films; Compatibility ------------- The `IMPORT FOREIGN SCHEMA` command conforms to the SQL standard, except that the `OPTIONS` clause is a PostgreSQL extension. See Also -------- [CREATE FOREIGN TABLE](https://www.postgresql.org/docs/current/sql-createforeigntable.html "CREATE FOREIGN TABLE") , [CREATE SERVER](https://www.postgresql.org/docs/current/sql-createserver.html "CREATE SERVER") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-grant.html "GRANT") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-insert.html "INSERT") | | GRANT | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | INSERT | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-importforeignschema.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 2.7. Aggregate Functions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/tutorial-agg.html "PostgreSQL 18 - 2.7. Aggregate Functions") ([18](https://www.postgresql.org/docs/18/tutorial-agg.html "PostgreSQL 18 - 2.7. Aggregate Functions") ) / [17](https://www.postgresql.org/docs/17/tutorial-agg.html "PostgreSQL 17 - 2.7. Aggregate Functions") / [16](https://www.postgresql.org/docs/16/tutorial-agg.html "PostgreSQL 16 - 2.7. Aggregate Functions") / [15](https://www.postgresql.org/docs/15/tutorial-agg.html "PostgreSQL 15 - 2.7. Aggregate Functions") / [14](https://www.postgresql.org/docs/14/tutorial-agg.html "PostgreSQL 14 - 2.7. Aggregate Functions") Development Versions: [devel](https://www.postgresql.org/docs/devel/tutorial-agg.html "PostgreSQL devel - 2.7. Aggregate Functions") Unsupported versions: [13](https://www.postgresql.org/docs/13/tutorial-agg.html "PostgreSQL 13 - 2.7. Aggregate Functions") / [12](https://www.postgresql.org/docs/12/tutorial-agg.html "PostgreSQL 12 - 2.7. Aggregate Functions") / [11](https://www.postgresql.org/docs/11/tutorial-agg.html "PostgreSQL 11 - 2.7. Aggregate Functions") / [10](https://www.postgresql.org/docs/10/tutorial-agg.html "PostgreSQL 10 - 2.7. Aggregate Functions") / [9.6](https://www.postgresql.org/docs/9.6/tutorial-agg.html "PostgreSQL 9.6 - 2.7. Aggregate Functions") / [9.5](https://www.postgresql.org/docs/9.5/tutorial-agg.html "PostgreSQL 9.5 - 2.7. Aggregate Functions") / [9.4](https://www.postgresql.org/docs/9.4/tutorial-agg.html "PostgreSQL 9.4 - 2.7. Aggregate Functions") / [9.3](https://www.postgresql.org/docs/9.3/tutorial-agg.html "PostgreSQL 9.3 - 2.7. Aggregate Functions") / [9.2](https://www.postgresql.org/docs/9.2/tutorial-agg.html "PostgreSQL 9.2 - 2.7. Aggregate Functions") / [9.1](https://www.postgresql.org/docs/9.1/tutorial-agg.html "PostgreSQL 9.1 - 2.7. Aggregate Functions") / [9.0](https://www.postgresql.org/docs/9.0/tutorial-agg.html "PostgreSQL 9.0 - 2.7. Aggregate Functions") / [8.4](https://www.postgresql.org/docs/8.4/tutorial-agg.html "PostgreSQL 8.4 - 2.7. Aggregate Functions") / [8.3](https://www.postgresql.org/docs/8.3/tutorial-agg.html "PostgreSQL 8.3 - 2.7. Aggregate Functions") / [8.2](https://www.postgresql.org/docs/8.2/tutorial-agg.html "PostgreSQL 8.2 - 2.7. Aggregate Functions") / [8.1](https://www.postgresql.org/docs/8.1/tutorial-agg.html "PostgreSQL 8.1 - 2.7. Aggregate Functions") / [8.0](https://www.postgresql.org/docs/8.0/tutorial-agg.html "PostgreSQL 8.0 - 2.7. Aggregate Functions") / [7.4](https://www.postgresql.org/docs/7.4/tutorial-agg.html "PostgreSQL 7.4 - 2.7. Aggregate Functions") / [7.3](https://www.postgresql.org/docs/7.3/tutorial-agg.html "PostgreSQL 7.3 - 2.7. Aggregate Functions") / [7.2](https://www.postgresql.org/docs/7.2/tutorial-agg.html "PostgreSQL 7.2 - 2.7. Aggregate Functions") | 2.7. Aggregate Functions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/tutorial-join.html "2.6. Joins Between Tables") | [Up](https://www.postgresql.org/docs/current/tutorial-sql.html "Chapter 2. The SQL Language") | Chapter 2. The SQL Language | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/tutorial-update.html "2.8. Updates") | * * * 2.7. Aggregate Functions [#](https://www.postgresql.org/docs/current/tutorial-agg.html#TUTORIAL-AGG) ----------------------------------------------------------------------------------------------------- Like most other relational database products, PostgreSQL supports _aggregate functions_. An aggregate function computes a single result from multiple input rows. For example, there are aggregates to compute the `count`, `sum`, `avg` (average), `max` (maximum) and `min` (minimum) over a set of rows. As an example, we can find the highest low-temperature reading anywhere with: SELECT max(temp\_lo) FROM weather; max ----- 46 (1 row) If we wanted to know what city (or cities) that reading occurred in, we might try: SELECT city FROM weather WHERE temp\_lo = max(temp\_lo); _\-- WRONG_ but this will not work since the aggregate `max` cannot be used in the `WHERE` clause. (This restriction exists because the `WHERE` clause determines which rows will be included in the aggregate calculation; so obviously it has to be evaluated before aggregate functions are computed.) However, as is often the case the query can be restated to accomplish the desired result, here by using a _subquery_: SELECT city FROM weather WHERE temp\_lo = (SELECT max(temp\_lo) FROM weather); city --------------- San Francisco (1 row) This is OK because the subquery is an independent computation that computes its own aggregate separately from what is happening in the outer query. Aggregates are also very useful in combination with `GROUP BY` clauses. For example, we can get the number of readings and the maximum low temperature observed in each city with: SELECT city, count(\*), max(temp\_lo) FROM weather GROUP BY city; city | count | max ---------------+-------+----- Hayward | 1 | 37 San Francisco | 2 | 46 (2 rows) which gives us one output row per city. Each aggregate result is computed over the table rows matching that city. We can filter these grouped rows using `HAVING`: SELECT city, count(\*), max(temp\_lo) FROM weather GROUP BY city HAVING max(temp\_lo) < 40; city | count | max ---------+-------+----- Hayward | 1 | 37 (1 row) which gives us the same results for only the cities that have all `temp_lo` values below 40. Finally, if we only care about cities whose names begin with “`S`”, we might do: SELECT city, count(\*), max(temp\_lo) FROM weather WHERE city LIKE 'S%' -- (1) GROUP BY city; city | count | max ---------------+-------+----- San Francisco | 2 | 46 (1 row) | | | | --- | --- | | [(1)](https://www.postgresql.org/docs/current/tutorial-agg.html#co.tutorial-agg-like) | The `LIKE` operator does pattern matching and is explained in [Section 9.7](https://www.postgresql.org/docs/current/functions-matching.html "9.7. Pattern Matching")
. | It is important to understand the interaction between aggregates and SQL's `WHERE` and `HAVING` clauses. The fundamental difference between `WHERE` and `HAVING` is this: `WHERE` selects input rows before groups and aggregates are computed (thus, it controls which rows go into the aggregate computation), whereas `HAVING` selects group rows after groups and aggregates are computed. Thus, the `WHERE` clause must not contain aggregate functions; it makes no sense to try to use an aggregate to determine which rows will be inputs to the aggregates. On the other hand, the `HAVING` clause always contains aggregate functions. (Strictly speaking, you are allowed to write a `HAVING` clause that doesn't use aggregates, but it's seldom useful. The same condition could be used more efficiently at the `WHERE` stage.) In the previous example, we can apply the city name restriction in `WHERE`, since it needs no aggregate. This is more efficient than adding the restriction to `HAVING`, because we avoid doing the grouping and aggregate calculations for all rows that fail the `WHERE` check. Another way to select the rows that go into an aggregate computation is to use `FILTER`, which is a per-aggregate option: SELECT city, count(\*) FILTER (WHERE temp\_lo < 45), max(temp\_lo) FROM weather GROUP BY city; city | count | max ---------------+-------+----- Hayward | 1 | 37 San Francisco | 1 | 46 (2 rows) `FILTER` is much like `WHERE`, except that it removes rows only from the input of the particular aggregate function that it is attached to. Here, the `count` aggregate counts only rows with `temp_lo` below 45; but the `max` aggregate is still applied to all rows, so it still finds the reading of 46. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/tutorial-join.html "2.6. Joins Between Tables") | [Up](https://www.postgresql.org/docs/current/tutorial-sql.html "Chapter 2. The SQL Language") | [Next](https://www.postgresql.org/docs/current/tutorial-update.html "2.8. Updates") | | 2.6. Joins Between Tables | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 2.8. Updates | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/tutorial-agg.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.11. pg_ident_file_mappings November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-ident-file-mappings.html "PostgreSQL 18 - 53.11. pg_ident_file_mappings") ([18](https://www.postgresql.org/docs/18/view-pg-ident-file-mappings.html "PostgreSQL 18 - 53.11. pg_ident_file_mappings") ) / [17](https://www.postgresql.org/docs/17/view-pg-ident-file-mappings.html "PostgreSQL 17 - 53.11. pg_ident_file_mappings") / [16](https://www.postgresql.org/docs/16/view-pg-ident-file-mappings.html "PostgreSQL 16 - 53.11. pg_ident_file_mappings") / [15](https://www.postgresql.org/docs/15/view-pg-ident-file-mappings.html "PostgreSQL 15 - 53.11. pg_ident_file_mappings") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-ident-file-mappings.html "PostgreSQL devel - 53.11. pg_ident_file_mappings") | 53.11. `pg_ident_file_mappings` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-hba-file-rules.html "53.10. pg_hba_file_rules") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/view-pg-indexes.html "53.12. pg_indexes") | * * * 53.11. `pg_ident_file_mappings` [#](https://www.postgresql.org/docs/18/view-pg-ident-file-mappings.html#VIEW-PG-IDENT-FILE-MAPPINGS) ------------------------------------------------------------------------------------------------------------------------------------- The view `pg_ident_file_mappings` provides a summary of the contents of the client user name mapping configuration file, [`pg_ident.conf`](https://www.postgresql.org/docs/18/auth-username-maps.html "20.2. User Name Maps") . A row appears in this view for each non-empty, non-comment line in the file, with annotations indicating whether the map could be applied successfully. This view can be helpful for checking whether planned changes in the authentication configuration file will work, or for diagnosing a previous failure. Note that this view reports on the _current_ contents of the file, not on what was last loaded by the server. By default, the `pg_ident_file_mappings` view can be read only by superusers. **Table 53.11. `pg_ident_file_mappings` Columns** | Column Type

Description | | --- | | `map_number` `int4`

Number of this map, in priority order, if valid, otherwise `NULL` | | `file_name` `text`

Name of the file containing this map | | `line_number` `int4`

Line number of this map in `file_name` | | `map_name` `text`

Name of the map | | `sys_name` `text`

Detected user name of the client | | `pg_username` `text`

Requested PostgreSQL user name | | `error` `text`

If not `NULL`, an error message indicating why this line could not be processed | Usually, a row reflecting an incorrect entry will have values for only the `line_number` and `error` fields. See [Chapter 20](https://www.postgresql.org/docs/18/client-authentication.html "Chapter 20. Client Authentication") for more information about client authentication configuration. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-hba-file-rules.html "53.10. pg_hba_file_rules") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/18/view-pg-indexes.html "53.12. pg_indexes") | | 53.10. `pg_hba_file_rules` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 53.12. `pg_indexes` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-ident-file-mappings.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.9. pg_group November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-group.html "PostgreSQL 18 - 53.9. pg_group") ([18](https://www.postgresql.org/docs/18/view-pg-group.html "PostgreSQL 18 - 53.9. pg_group") ) / [17](https://www.postgresql.org/docs/17/view-pg-group.html "PostgreSQL 17 - 53.9. pg_group") / [16](https://www.postgresql.org/docs/16/view-pg-group.html "PostgreSQL 16 - 53.9. pg_group") / [15](https://www.postgresql.org/docs/15/view-pg-group.html "PostgreSQL 15 - 53.9. pg_group") / [14](https://www.postgresql.org/docs/14/view-pg-group.html "PostgreSQL 14 - 53.9. pg_group") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-group.html "PostgreSQL devel - 53.9. pg_group") Unsupported versions: [13](https://www.postgresql.org/docs/13/view-pg-group.html "PostgreSQL 13 - 53.9. pg_group") / [12](https://www.postgresql.org/docs/12/view-pg-group.html "PostgreSQL 12 - 53.9. pg_group") / [11](https://www.postgresql.org/docs/11/view-pg-group.html "PostgreSQL 11 - 53.9. pg_group") / [10](https://www.postgresql.org/docs/10/view-pg-group.html "PostgreSQL 10 - 53.9. pg_group") / [9.6](https://www.postgresql.org/docs/9.6/view-pg-group.html "PostgreSQL 9.6 - 53.9. pg_group") / [9.5](https://www.postgresql.org/docs/9.5/view-pg-group.html "PostgreSQL 9.5 - 53.9. pg_group") / [9.4](https://www.postgresql.org/docs/9.4/view-pg-group.html "PostgreSQL 9.4 - 53.9. pg_group") / [9.3](https://www.postgresql.org/docs/9.3/view-pg-group.html "PostgreSQL 9.3 - 53.9. pg_group") / [9.2](https://www.postgresql.org/docs/9.2/view-pg-group.html "PostgreSQL 9.2 - 53.9. pg_group") / [9.1](https://www.postgresql.org/docs/9.1/view-pg-group.html "PostgreSQL 9.1 - 53.9. pg_group") / [9.0](https://www.postgresql.org/docs/9.0/view-pg-group.html "PostgreSQL 9.0 - 53.9. pg_group") / [8.4](https://www.postgresql.org/docs/8.4/view-pg-group.html "PostgreSQL 8.4 - 53.9. pg_group") / [8.3](https://www.postgresql.org/docs/8.3/view-pg-group.html "PostgreSQL 8.3 - 53.9. pg_group") / [8.2](https://www.postgresql.org/docs/8.2/view-pg-group.html "PostgreSQL 8.2 - 53.9. pg_group") / [8.1](https://www.postgresql.org/docs/8.1/view-pg-group.html "PostgreSQL 8.1 - 53.9. pg_group") | 53.9. `pg_group` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-file-settings.html "53.8. pg_file_settings") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/view-pg-hba-file-rules.html "53.10. pg_hba_file_rules") | * * * 53.9. `pg_group` [#](https://www.postgresql.org/docs/18/view-pg-group.html#VIEW-PG-GROUP) ------------------------------------------------------------------------------------------ The view `pg_group` exists for backwards compatibility: it emulates a catalog that existed in PostgreSQL before version 8.1. It shows the names and members of all roles that are marked as not `rolcanlogin`, which is an approximation to the set of roles that are being used as groups. **Table 53.9. `pg_group` Columns** | Column Type

Description | | --- | | `groname` `name` (references [`pg_authid`](https://www.postgresql.org/docs/18/catalog-pg-authid.html "52.8. pg_authid")
.`rolname`)

Name of the group | | `grosysid` `oid` (references [`pg_authid`](https://www.postgresql.org/docs/18/catalog-pg-authid.html "52.8. pg_authid")
.`oid`)

ID of this group | | `grolist` `oid[]` (references [`pg_authid`](https://www.postgresql.org/docs/18/catalog-pg-authid.html "52.8. pg_authid")
.`oid`)

An array containing the IDs of the roles in this group | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-file-settings.html "53.8. pg_file_settings") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/18/view-pg-hba-file-rules.html "53.10. pg_hba_file_rules") | | 53.8. `pg_file_settings` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 53.10. `pg_hba_file_rules` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-group.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 7.2: Example November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 7.2](https://www.postgresql.org/docs/7.2/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/bki-example.html "PostgreSQL 18 - Example") ([18](https://www.postgresql.org/docs/18/bki-example.html "PostgreSQL 18 - Example") ) / [17](https://www.postgresql.org/docs/17/bki-example.html "PostgreSQL 17 - Example") / [16](https://www.postgresql.org/docs/16/bki-example.html "PostgreSQL 16 - Example") / [15](https://www.postgresql.org/docs/15/bki-example.html "PostgreSQL 15 - Example") / [14](https://www.postgresql.org/docs/14/bki-example.html "PostgreSQL 14 - Example") Development Versions: [devel](https://www.postgresql.org/docs/devel/bki-example.html "PostgreSQL devel - Example") Unsupported versions: [13](https://www.postgresql.org/docs/13/bki-example.html "PostgreSQL 13 - Example") / [12](https://www.postgresql.org/docs/12/bki-example.html "PostgreSQL 12 - Example") / [11](https://www.postgresql.org/docs/11/bki-example.html "PostgreSQL 11 - Example") / [10](https://www.postgresql.org/docs/10/bki-example.html "PostgreSQL 10 - Example") / [9.6](https://www.postgresql.org/docs/9.6/bki-example.html "PostgreSQL 9.6 - Example") / [9.5](https://www.postgresql.org/docs/9.5/bki-example.html "PostgreSQL 9.5 - Example") / [9.4](https://www.postgresql.org/docs/9.4/bki-example.html "PostgreSQL 9.4 - Example") / [9.3](https://www.postgresql.org/docs/9.3/bki-example.html "PostgreSQL 9.3 - Example") / [9.2](https://www.postgresql.org/docs/9.2/bki-example.html "PostgreSQL 9.2 - Example") / [9.1](https://www.postgresql.org/docs/9.1/bki-example.html "PostgreSQL 9.1 - Example") / [9.0](https://www.postgresql.org/docs/9.0/bki-example.html "PostgreSQL 9.0 - Example") / [8.4](https://www.postgresql.org/docs/8.4/bki-example.html "PostgreSQL 8.4 - Example") / [8.3](https://www.postgresql.org/docs/8.3/bki-example.html "PostgreSQL 8.3 - Example") / [8.2](https://www.postgresql.org/docs/8.2/bki-example.html "PostgreSQL 8.2 - Example") / [8.1](https://www.postgresql.org/docs/8.1/bki-example.html "PostgreSQL 8.1 - Example") / [8.0](https://www.postgresql.org/docs/8.0/bki-example.html "PostgreSQL 8.0 - Example") / [7.4](https://www.postgresql.org/docs/7.4/bki-example.html "PostgreSQL 7.4 - Example") / [7.3](https://www.postgresql.org/docs/7.3/bki-example.html "PostgreSQL 7.3 - Example") / [7.2](https://www.postgresql.org/docs/7.2/bki-example.html "PostgreSQL 7.2 - Example") / [7.1](https://www.postgresql.org/docs/7.1/bki-example.html "PostgreSQL 7.1 - Example") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/bki-example.html "PostgreSQL - Example") version, or one of the other supported versions listed above instead. | PostgreSQL 7.2.8 Documentation | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.2/bki-commands.html) | Chapter 6. BKI Backend Interface | [Next](https://www.postgresql.org/docs/7.2/page.html) | * * * 6.3. Example ============ The following sequence of commands will create the test\_table table with the two columns cola and colb of type int4 and text, respectively, and insert two rows into the table. create test\_table (cola = int4, colb = text) open test\_table insert OID=421 ( 1 "value1" ) insert OID=422 ( 2 \_null\_ ) close test\_table * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.2/bki-commands.html) | [Home](https://www.postgresql.org/docs/7.2/index.html) | [Next](https://www.postgresql.org/docs/7.2/page.html) | | BKI Commands | [Up](https://www.postgresql.org/docs/7.2/bki.html) | Page Files | --- # PostgreSQL: Documentation: 7.2: ALTER TABLE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 7.2](https://www.postgresql.org/docs/7.2/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-altertable.html "PostgreSQL 18 - ALTER TABLE ") ([18](https://www.postgresql.org/docs/18/sql-altertable.html "PostgreSQL 18 - ALTER TABLE ") ) / [17](https://www.postgresql.org/docs/17/sql-altertable.html "PostgreSQL 17 - ALTER TABLE ") / [16](https://www.postgresql.org/docs/16/sql-altertable.html "PostgreSQL 16 - ALTER TABLE ") / [15](https://www.postgresql.org/docs/15/sql-altertable.html "PostgreSQL 15 - ALTER TABLE ") / [14](https://www.postgresql.org/docs/14/sql-altertable.html "PostgreSQL 14 - ALTER TABLE ") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-altertable.html "PostgreSQL devel - ALTER TABLE ") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-altertable.html "PostgreSQL 13 - ALTER TABLE ") / [12](https://www.postgresql.org/docs/12/sql-altertable.html "PostgreSQL 12 - ALTER TABLE ") / [11](https://www.postgresql.org/docs/11/sql-altertable.html "PostgreSQL 11 - ALTER TABLE ") / [10](https://www.postgresql.org/docs/10/sql-altertable.html "PostgreSQL 10 - ALTER TABLE ") / [9.6](https://www.postgresql.org/docs/9.6/sql-altertable.html "PostgreSQL 9.6 - ALTER TABLE ") / [9.5](https://www.postgresql.org/docs/9.5/sql-altertable.html "PostgreSQL 9.5 - ALTER TABLE ") / [9.4](https://www.postgresql.org/docs/9.4/sql-altertable.html "PostgreSQL 9.4 - ALTER TABLE ") / [9.3](https://www.postgresql.org/docs/9.3/sql-altertable.html "PostgreSQL 9.3 - ALTER TABLE ") / [9.2](https://www.postgresql.org/docs/9.2/sql-altertable.html "PostgreSQL 9.2 - ALTER TABLE ") / [9.1](https://www.postgresql.org/docs/9.1/sql-altertable.html "PostgreSQL 9.1 - ALTER TABLE ") / [9.0](https://www.postgresql.org/docs/9.0/sql-altertable.html "PostgreSQL 9.0 - ALTER TABLE ") / [8.4](https://www.postgresql.org/docs/8.4/sql-altertable.html "PostgreSQL 8.4 - ALTER TABLE ") / [8.3](https://www.postgresql.org/docs/8.3/sql-altertable.html "PostgreSQL 8.3 - ALTER TABLE ") / [8.2](https://www.postgresql.org/docs/8.2/sql-altertable.html "PostgreSQL 8.2 - ALTER TABLE ") / [8.1](https://www.postgresql.org/docs/8.1/sql-altertable.html "PostgreSQL 8.1 - ALTER TABLE ") / [8.0](https://www.postgresql.org/docs/8.0/sql-altertable.html "PostgreSQL 8.0 - ALTER TABLE ") / [7.4](https://www.postgresql.org/docs/7.4/sql-altertable.html "PostgreSQL 7.4 - ALTER TABLE ") / [7.3](https://www.postgresql.org/docs/7.3/sql-altertable.html "PostgreSQL 7.3 - ALTER TABLE ") / [7.2](https://www.postgresql.org/docs/7.2/sql-altertable.html "PostgreSQL 7.2 - ALTER TABLE ") / [7.1](https://www.postgresql.org/docs/7.1/sql-altertable.html "PostgreSQL 7.1 - ALTER TABLE ") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/sql-altertable.html "PostgreSQL - ALTER TABLE ") version, or one of the other supported versions listed above instead. | PostgreSQL 7.2.8 Documentation | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.2/sql-altergroup.html) | | [Next](https://www.postgresql.org/docs/7.2/sql-alteruser.html) | * * * ALTER TABLE =========== Name ---- ALTER TABLE  --  change the definition of a table Synopsis -------- ALTER TABLE \[ ONLY \] table \[ \* \] ADD \[ COLUMN \] column type \[ column\_constraint \[ ... \] \] ALTER TABLE \[ ONLY \] table \[ \* \] ALTER \[ COLUMN \] column { SET DEFAULT value | DROP DEFAULT } ALTER TABLE \[ ONLY \] table \[ \* \] ALTER \[ COLUMN \] column SET STATISTICS integer ALTER TABLE \[ ONLY \] table \[ \* \] RENAME \[ COLUMN \] column TO newcolumn ALTER TABLE table RENAME TO new\_table ALTER TABLE table ADD table\_constraint\_definition ALTER TABLE \[ ONLY \] table DROP CONSTRAINT constraint { RESTRICT | CASCADE } ALTER TABLE table OWNER TO new\_owner ### Inputs table The name of an existing table to alter. column Name of a new or existing column. type Type of the new column. newcolumn New name for an existing column. new\_table New name for the table. table\_constraint\_definition New table constraint for the table new\_owner The user name of the new owner of the table. ### Outputs ALTER Message returned from column or table renaming. ERROR Message returned if table or column is not available. Description ----------- **ALTER TABLE** changes the definition of an existing table. The ADD COLUMN form adds a new column to the table using the same syntax as [CREATE TABLE](https://www.postgresql.org/docs/7.2/sql-createtable.html) . The ALTER COLUMN SET/DROP DEFAULT forms allow you to set or remove the default for the column. Note that defaults only apply to subsequent **INSERT** commands; they do not cause rows already in the table to change. The ALTER COLUMN SET STATISTICS form allows you to set the statistics-gathering target for subsequent [ANALYZE](https://www.postgresql.org/docs/7.2/sql-analyze.html) operations. The RENAME clause causes the name of a table, column, index, or sequence to change without changing any of the data. The data will remain of the same type and size after the command is executed. The ADD table\_constraint\_definition clause adds a new constraint to the table using the same syntax as [CREATE TABLE](https://www.postgresql.org/docs/7.2/sql-createtable.html) . The DROP CONSTRAINT constraint clause drops all constraints on the table (and its children) that match constraint. The OWNER clause changes the owner of the table to the user new user. You must own the table in order to change its schema. ### Notes The keyword COLUMN is noise and can be omitted. In the current implementation of ADD COLUMN, default and NOT NULL clauses for the new column are not supported. You can use the SET DEFAULT form of **ALTER TABLE** to set the default later. (You may also want to update the already existing rows to the new default value, using [UPDATE](https://www.postgresql.org/docs/7.2/sql-update.html) .) In DROP CONSTRAINT, the RESTRICT keyword is required, although dependencies are not yet checked. The CASCADE option is unsupported. Currently DROP CONSTRAINT drops only CHECK constraints. To remove a PRIMARY or UNIQUE constraint, drop the relevant index using the [DROP INDEX](https://www.postgresql.org/docs/7.2/sql-dropindex.html) command. To remove FOREIGN KEY constraints you need to recreate and reload the table, using other parameters to the [CREATE TABLE](https://www.postgresql.org/docs/7.2/sql-createtable.html) command. For example, to drop all constraints on a table distributors: CREATE TABLE temp AS SELECT \* FROM distributors; DROP TABLE distributors; CREATE TABLE distributors AS SELECT \* FROM temp; DROP TABLE temp; You must own the table in order to change it. Changing any part of the schema of a system catalog is not permitted. The _PostgreSQL User's Guide_ has further information on inheritance. Refer to **CREATE TABLE** for a further description of valid arguments. Usage ----- To add a column of type varchar to a table: ALTER TABLE distributors ADD COLUMN address VARCHAR(30); To rename an existing column: ALTER TABLE distributors RENAME COLUMN address TO city; To rename an existing table: ALTER TABLE distributors RENAME TO suppliers; To add a check constraint to a table: ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char\_length(zipcode) = 5); To remove a check constraint from a table and all its children: ALTER TABLE distributors DROP CONSTRAINT zipchk RESTRICT; To add a foreign key constraint to a table: ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses(address) MATCH FULL; To add a (multicolumn) unique constraint to a table: ALTER TABLE distributors ADD CONSTRAINT dist\_id\_zipcode\_key UNIQUE (dist\_id, zipcode); To add an automatically named primary key constraint to a table, noting that a table can only ever have one primary key: ALTER TABLE distributors ADD PRIMARY KEY (dist\_id); Compatibility ------------- ### SQL92 The ADD COLUMN form is compliant with the exception that it does not support defaults and NOT NULL constraints, as explained above. The ALTER COLUMN form is in full compliance. SQL92 specifies some additional capabilities for **ALTER TABLE** statement which are not yet directly supported by PostgreSQL: ALTER TABLE table DROP \[ COLUMN \] column { RESTRICT | CASCADE } Removes a column from a table. Currently, to remove an existing column the table must be recreated and reloaded: CREATE TABLE temp AS SELECT did, city FROM distributors; DROP TABLE distributors; CREATE TABLE distributors ( did DECIMAL(3) DEFAULT 1, name VARCHAR(40) NOT NULL ); INSERT INTO distributors SELECT \* FROM temp; DROP TABLE temp; The clauses to rename tables, columns, indexes, and sequences are PostgreSQL extensions from SQL92. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.2/sql-altergroup.html) | [Home](https://www.postgresql.org/docs/7.2/index.html) | [Next](https://www.postgresql.org/docs/7.2/sql-alteruser.html) | | ALTER GROUP | [Up](https://www.postgresql.org/docs/7.2/sql-commands.html) | ALTER USER | --- # PostgreSQL: Documentation: 18: 51.3. The Parser Stage November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/parser-stage.html "PostgreSQL 18 - 51.3. The Parser Stage") ([18](https://www.postgresql.org/docs/18/parser-stage.html "PostgreSQL 18 - 51.3. The Parser Stage") ) / [17](https://www.postgresql.org/docs/17/parser-stage.html "PostgreSQL 17 - 51.3. The Parser Stage") / [16](https://www.postgresql.org/docs/16/parser-stage.html "PostgreSQL 16 - 51.3. The Parser Stage") / [15](https://www.postgresql.org/docs/15/parser-stage.html "PostgreSQL 15 - 51.3. The Parser Stage") / [14](https://www.postgresql.org/docs/14/parser-stage.html "PostgreSQL 14 - 51.3. The Parser Stage") Development Versions: [devel](https://www.postgresql.org/docs/devel/parser-stage.html "PostgreSQL devel - 51.3. The Parser Stage") Unsupported versions: [13](https://www.postgresql.org/docs/13/parser-stage.html "PostgreSQL 13 - 51.3. The Parser Stage") / [12](https://www.postgresql.org/docs/12/parser-stage.html "PostgreSQL 12 - 51.3. The Parser Stage") / [11](https://www.postgresql.org/docs/11/parser-stage.html "PostgreSQL 11 - 51.3. The Parser Stage") / [10](https://www.postgresql.org/docs/10/parser-stage.html "PostgreSQL 10 - 51.3. The Parser Stage") / [9.6](https://www.postgresql.org/docs/9.6/parser-stage.html "PostgreSQL 9.6 - 51.3. The Parser Stage") / [9.5](https://www.postgresql.org/docs/9.5/parser-stage.html "PostgreSQL 9.5 - 51.3. The Parser Stage") / [9.4](https://www.postgresql.org/docs/9.4/parser-stage.html "PostgreSQL 9.4 - 51.3. The Parser Stage") / [9.3](https://www.postgresql.org/docs/9.3/parser-stage.html "PostgreSQL 9.3 - 51.3. The Parser Stage") / [9.2](https://www.postgresql.org/docs/9.2/parser-stage.html "PostgreSQL 9.2 - 51.3. The Parser Stage") / [9.1](https://www.postgresql.org/docs/9.1/parser-stage.html "PostgreSQL 9.1 - 51.3. The Parser Stage") / [9.0](https://www.postgresql.org/docs/9.0/parser-stage.html "PostgreSQL 9.0 - 51.3. The Parser Stage") / [8.4](https://www.postgresql.org/docs/8.4/parser-stage.html "PostgreSQL 8.4 - 51.3. The Parser Stage") / [8.3](https://www.postgresql.org/docs/8.3/parser-stage.html "PostgreSQL 8.3 - 51.3. The Parser Stage") / [8.2](https://www.postgresql.org/docs/8.2/parser-stage.html "PostgreSQL 8.2 - 51.3. The Parser Stage") / [8.1](https://www.postgresql.org/docs/8.1/parser-stage.html "PostgreSQL 8.1 - 51.3. The Parser Stage") / [8.0](https://www.postgresql.org/docs/8.0/parser-stage.html "PostgreSQL 8.0 - 51.3. The Parser Stage") / [7.4](https://www.postgresql.org/docs/7.4/parser-stage.html "PostgreSQL 7.4 - 51.3. The Parser Stage") / [7.3](https://www.postgresql.org/docs/7.3/parser-stage.html "PostgreSQL 7.3 - 51.3. The Parser Stage") / [7.2](https://www.postgresql.org/docs/7.2/parser-stage.html "PostgreSQL 7.2 - 51.3. The Parser Stage") / [7.1](https://www.postgresql.org/docs/7.1/parser-stage.html "PostgreSQL 7.1 - 51.3. The Parser Stage") | 51.3. The Parser Stage | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/connect-estab.html "51.2. How Connections Are Established") | [Up](https://www.postgresql.org/docs/current/overview.html "Chapter 51. Overview of PostgreSQL Internals") | Chapter 51. Overview of PostgreSQL Internals | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/rule-system.html "51.4. The PostgreSQL Rule System") | * * * 51.3. The Parser Stage [#](https://www.postgresql.org/docs/current/parser-stage.html#PARSER-STAGE) --------------------------------------------------------------------------------------------------- [51.3.1. Parser](https://www.postgresql.org/docs/current/parser-stage.html#PARSER-STAGE-PARSER) [51.3.2. Transformation Process](https://www.postgresql.org/docs/current/parser-stage.html#PARSER-STAGE-TRANSFORMATION-PROCESS) The _parser stage_ consists of two parts: * The _parser_ defined in `gram.y` and `scan.l` is built using the Unix tools bison and flex. * The _transformation process_ does modifications and augmentations to the data structures returned by the parser. ### 51.3.1. Parser [#](https://www.postgresql.org/docs/current/parser-stage.html#PARSER-STAGE-PARSER) The parser has to check the query string (which arrives as plain text) for valid syntax. If the syntax is correct a _parse tree_ is built up and handed back; otherwise an error is returned. The parser and lexer are implemented using the well-known Unix tools bison and flex. The _lexer_ is defined in the file `scan.l` and is responsible for recognizing _identifiers_, the _SQL key words_ etc. For every key word or identifier that is found, a _token_ is generated and handed to the parser. The parser is defined in the file `gram.y` and consists of a set of _grammar rules_ and _actions_ that are executed whenever a rule is fired. The code of the actions (which is actually C code) is used to build up the parse tree. The file `scan.l` is transformed to the C source file `scan.c` using the program flex and `gram.y` is transformed to `gram.c` using bison. After these transformations have taken place a normal C compiler can be used to create the parser. Never make any changes to the generated C files as they will be overwritten the next time flex or bison is called. ### Note The mentioned transformations and compilations are normally done automatically using the _makefiles_ shipped with the PostgreSQL source distribution. A detailed description of bison or the grammar rules given in `gram.y` would be beyond the scope of this manual. There are many books and documents dealing with flex and bison. You should be familiar with bison before you start to study the grammar given in `gram.y` otherwise you won't understand what happens there. ### 51.3.2. Transformation Process [#](https://www.postgresql.org/docs/current/parser-stage.html#PARSER-STAGE-TRANSFORMATION-PROCESS) The parser stage creates a parse tree using only fixed rules about the syntactic structure of SQL. It does not make any lookups in the system catalogs, so there is no possibility to understand the detailed semantics of the requested operations. After the parser completes, the _transformation process_ takes the tree handed back by the parser as input and does the semantic interpretation needed to understand which tables, functions, and operators are referenced by the query. The data structure that is built to represent this information is called the _query tree_. The reason for separating raw parsing from semantic analysis is that system catalog lookups can only be done within a transaction, and we do not wish to start a transaction immediately upon receiving a query string. The raw parsing stage is sufficient to identify the transaction control commands (`BEGIN`, `ROLLBACK`, etc.), and these can then be correctly executed without any further analysis. Once we know that we are dealing with an actual query (such as `SELECT` or `UPDATE`), it is okay to start a transaction if we're not already in one. Only then can the transformation process be invoked. The query tree created by the transformation process is structurally similar to the raw parse tree in most places, but it has many differences in detail. For example, a `FuncCall` node in the parse tree represents something that looks syntactically like a function call. This might be transformed to either a `FuncExpr` or `Aggref` node depending on whether the referenced name turns out to be an ordinary function or an aggregate function. Also, information about the actual data types of columns and expression results is added to the query tree. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/connect-estab.html "51.2. How Connections Are Established") | [Up](https://www.postgresql.org/docs/current/overview.html "Chapter 51. Overview of PostgreSQL Internals") | [Next](https://www.postgresql.org/docs/current/rule-system.html "51.4. The PostgreSQL Rule System") | | 51.2. How Connections Are Established | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 51.4. The PostgreSQL Rule System | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/parser-stage.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 9.0: sequences November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 9.0](https://www.postgresql.org/docs/9.0/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-sequences.html "PostgreSQL 18 - sequences") ([18](https://www.postgresql.org/docs/18/infoschema-sequences.html "PostgreSQL 18 - sequences") ) / [17](https://www.postgresql.org/docs/17/infoschema-sequences.html "PostgreSQL 17 - sequences") / [16](https://www.postgresql.org/docs/16/infoschema-sequences.html "PostgreSQL 16 - sequences") / [15](https://www.postgresql.org/docs/15/infoschema-sequences.html "PostgreSQL 15 - sequences") / [14](https://www.postgresql.org/docs/14/infoschema-sequences.html "PostgreSQL 14 - sequences") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-sequences.html "PostgreSQL devel - sequences") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-sequences.html "PostgreSQL 13 - sequences") / [12](https://www.postgresql.org/docs/12/infoschema-sequences.html "PostgreSQL 12 - sequences") / [11](https://www.postgresql.org/docs/11/infoschema-sequences.html "PostgreSQL 11 - sequences") / [10](https://www.postgresql.org/docs/10/infoschema-sequences.html "PostgreSQL 10 - sequences") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-sequences.html "PostgreSQL 9.6 - sequences") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-sequences.html "PostgreSQL 9.5 - sequences") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-sequences.html "PostgreSQL 9.4 - sequences") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-sequences.html "PostgreSQL 9.3 - sequences") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-sequences.html "PostgreSQL 9.2 - sequences") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-sequences.html "PostgreSQL 9.1 - sequences") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-sequences.html "PostgreSQL 9.0 - sequences") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-sequences.html "PostgreSQL 8.4 - sequences") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-sequences.html "PostgreSQL 8.3 - sequences") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-sequences.html "PostgreSQL 8.2 - sequences") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/infoschema-sequences.html "PostgreSQL - sequences") version, or one of the other supported versions listed above instead. | [PostgreSQL 9.0.23 Documentation](https://www.postgresql.org/docs/9.0/index.html) | | | | | | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.0/infoschema-schemata.html "schemata") | [Up](https://www.postgresql.org/docs/9.0/information-schema.html) | Chapter 34. The Information Schema | [Next](https://www.postgresql.org/docs/9.0/infoschema-sql-features.html "sql_features") | * * * 34.35. sequences ================ The view sequences contains all sequences defined in the current database. Only those sequences are shown that the current user has access to (by way of being the owner or having some privilege). Table 34-33. sequences Columns | Name | Data Type | Description | | --- | --- | --- | | sequence\_catalog | sql\_identifier | Name of the database that contains the sequence (always the current database) | | sequence\_schema | sql\_identifier | Name of the schema that contains the sequence | | sequence\_name | sql\_identifier | Name of the sequence | | data\_type | character\_data | The data type of the sequence. In PostgreSQL, this is currently always bigint. | | numeric\_precision | cardinal\_number | This column contains the (declared or implicit) precision of the sequence data type (see above). The precision indicates the number of significant digits. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column numeric\_precision\_radix. | | numeric\_precision\_radix | cardinal\_number | This column indicates in which base the values in the columns numeric\_precision and numeric\_scale are expressed. The value is either 2 or 10. | | numeric\_scale | cardinal\_number | This column contains the (declared or implicit) scale of the sequence data type (see above). The scale indicates the number of significant digits to the right of the decimal point. It can be expressed in decimal (base 10) or binary (base 2) terms, as specified in the column numeric\_precision\_radix. | | maximum\_value | cardinal\_number | Not yet implemented | | minimum\_value | cardinal\_number | Not yet implemented | | increment | cardinal\_number | Not yet implemented | | cycle\_option | yes\_or\_no | Not yet implemented | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.0/infoschema-schemata.html) | [Home](https://www.postgresql.org/docs/9.0/index.html) | [Next](https://www.postgresql.org/docs/9.0/infoschema-sql-features.html) | | schemata | [Up](https://www.postgresql.org/docs/9.0/information-schema.html) | sql\_features | --- # PostgreSQL: Documentation: 18: 32.14. Event System November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/libpq-events.html "PostgreSQL 18 - 32.14. Event System") ([18](https://www.postgresql.org/docs/18/libpq-events.html "PostgreSQL 18 - 32.14. Event System") ) / [17](https://www.postgresql.org/docs/17/libpq-events.html "PostgreSQL 17 - 32.14. Event System") / [16](https://www.postgresql.org/docs/16/libpq-events.html "PostgreSQL 16 - 32.14. Event System") / [15](https://www.postgresql.org/docs/15/libpq-events.html "PostgreSQL 15 - 32.14. Event System") / [14](https://www.postgresql.org/docs/14/libpq-events.html "PostgreSQL 14 - 32.14. Event System") Development Versions: [devel](https://www.postgresql.org/docs/devel/libpq-events.html "PostgreSQL devel - 32.14. Event System") Unsupported versions: [13](https://www.postgresql.org/docs/13/libpq-events.html "PostgreSQL 13 - 32.14. Event System") / [12](https://www.postgresql.org/docs/12/libpq-events.html "PostgreSQL 12 - 32.14. Event System") / [11](https://www.postgresql.org/docs/11/libpq-events.html "PostgreSQL 11 - 32.14. Event System") / [10](https://www.postgresql.org/docs/10/libpq-events.html "PostgreSQL 10 - 32.14. Event System") / [9.6](https://www.postgresql.org/docs/9.6/libpq-events.html "PostgreSQL 9.6 - 32.14. Event System") / [9.5](https://www.postgresql.org/docs/9.5/libpq-events.html "PostgreSQL 9.5 - 32.14. Event System") / [9.4](https://www.postgresql.org/docs/9.4/libpq-events.html "PostgreSQL 9.4 - 32.14. Event System") / [9.3](https://www.postgresql.org/docs/9.3/libpq-events.html "PostgreSQL 9.3 - 32.14. Event System") / [9.2](https://www.postgresql.org/docs/9.2/libpq-events.html "PostgreSQL 9.2 - 32.14. Event System") / [9.1](https://www.postgresql.org/docs/9.1/libpq-events.html "PostgreSQL 9.1 - 32.14. Event System") / [9.0](https://www.postgresql.org/docs/9.0/libpq-events.html "PostgreSQL 9.0 - 32.14. Event System") / [8.4](https://www.postgresql.org/docs/8.4/libpq-events.html "PostgreSQL 8.4 - 32.14. Event System") | 32.14. Event System | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/libpq-notice-processing.html "32.13. Notice Processing") | [Up](https://www.postgresql.org/docs/current/libpq.html "Chapter 32. libpq — C Library") | Chapter 32. libpq — C Library | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/libpq-envars.html "32.15. Environment Variables") | * * * 32.14. Event System [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-EVENTS) ------------------------------------------------------------------------------------------------ [32.14.1. Event Types](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-EVENTS-TYPES) [32.14.2. Event Callback Procedure](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-EVENTS-PROC) [32.14.3. Event Support Functions](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-EVENTS-FUNCS) [32.14.4. Event Example](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-EVENTS-EXAMPLE) libpq's event system is designed to notify registered event handlers about interesting libpq events, such as the creation or destruction of `PGconn` and `PGresult` objects. A principal use case is that this allows applications to associate their own data with a `PGconn` or `PGresult` and ensure that that data is freed at an appropriate time. Each registered event handler is associated with two pieces of data, known to libpq only as opaque `void *` pointers. There is a _pass-through_ pointer that is provided by the application when the event handler is registered with a `PGconn`. The pass-through pointer never changes for the life of the `PGconn` and all `PGresult`s generated from it; so if used, it must point to long-lived data. In addition there is an _instance data_ pointer, which starts out `NULL` in every `PGconn` and `PGresult`. This pointer can be manipulated using the [`PQinstanceData`](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQINSTANCEDATA) , [`PQsetInstanceData`](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQSETINSTANCEDATA) , [`PQresultInstanceData`](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQRESULTINSTANCEDATA) and [`PQresultSetInstanceData`](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQRESULTSETINSTANCEDATA) functions. Note that unlike the pass-through pointer, instance data of a `PGconn` is not automatically inherited by `PGresult`s created from it. libpq does not know what pass-through and instance data pointers point to (if anything) and will never attempt to free them — that is the responsibility of the event handler. ### 32.14.1. Event Types [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-EVENTS-TYPES) The enum `PGEventId` names the types of events handled by the event system. All its values have names beginning with `PGEVT`. For each event type, there is a corresponding event info structure that carries the parameters passed to the event handlers. The event types are: `PGEVT_REGISTER` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PGEVT-REGISTER) The register event occurs when [`PQregisterEventProc`](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQREGISTEREVENTPROC) is called. It is the ideal time to initialize any `instanceData` an event procedure may need. Only one register event will be fired per event handler per connection. If the event procedure fails (returns zero), the registration is canceled. typedef struct { PGconn \*conn; } PGEventRegister; When a `PGEVT_REGISTER` event is received, the _`evtInfo`_ pointer should be cast to a `PGEventRegister *`. This structure contains a `PGconn` that should be in the `CONNECTION_OK` status; guaranteed if one calls [`PQregisterEventProc`](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQREGISTEREVENTPROC) right after obtaining a good `PGconn`. When returning a failure code, all cleanup must be performed as no `PGEVT_CONNDESTROY` event will be sent. `PGEVT_CONNRESET` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PGEVT-CONNRESET) The connection reset event is fired on completion of [`PQreset`](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQRESET) or `PQresetPoll`. In both cases, the event is only fired if the reset was successful. The return value of the event procedure is ignored in PostgreSQL v15 and later. With earlier versions, however, it's important to return success (nonzero) or the connection will be aborted. typedef struct { PGconn \*conn; } PGEventConnReset; When a `PGEVT_CONNRESET` event is received, the _`evtInfo`_ pointer should be cast to a `PGEventConnReset *`. Although the contained `PGconn` was just reset, all event data remains unchanged. This event should be used to reset/reload/requery any associated `instanceData`. Note that even if the event procedure fails to process `PGEVT_CONNRESET`, it will still receive a `PGEVT_CONNDESTROY` event when the connection is closed. `PGEVT_CONNDESTROY` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PGEVT-CONNDESTROY) The connection destroy event is fired in response to [`PQfinish`](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQFINISH) . It is the event procedure's responsibility to properly clean up its event data as libpq has no ability to manage this memory. Failure to clean up will lead to memory leaks. typedef struct { PGconn \*conn; } PGEventConnDestroy; When a `PGEVT_CONNDESTROY` event is received, the _`evtInfo`_ pointer should be cast to a `PGEventConnDestroy *`. This event is fired prior to [`PQfinish`](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQFINISH) performing any other cleanup. The return value of the event procedure is ignored since there is no way of indicating a failure from [`PQfinish`](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQFINISH) . Also, an event procedure failure should not abort the process of cleaning up unwanted memory. `PGEVT_RESULTCREATE` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PGEVT-RESULTCREATE) The result creation event is fired in response to any query execution function that generates a result, including [`PQgetResult`](https://www.postgresql.org/docs/current/libpq-async.html#LIBPQ-PQGETRESULT) . This event will only be fired after the result has been created successfully. typedef struct { PGconn \*conn; PGresult \*result; } PGEventResultCreate; When a `PGEVT_RESULTCREATE` event is received, the _`evtInfo`_ pointer should be cast to a `PGEventResultCreate *`. The _`conn`_ is the connection used to generate the result. This is the ideal place to initialize any `instanceData` that needs to be associated with the result. If an event procedure fails (returns zero), that event procedure will be ignored for the remaining lifetime of the result; that is, it will not receive `PGEVT_RESULTCOPY` or `PGEVT_RESULTDESTROY` events for this result or results copied from it. `PGEVT_RESULTCOPY` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PGEVT-RESULTCOPY) The result copy event is fired in response to [`PQcopyResult`](https://www.postgresql.org/docs/current/libpq-misc.html#LIBPQ-PQCOPYRESULT) . This event will only be fired after the copy is complete. Only event procedures that have successfully handled the `PGEVT_RESULTCREATE` or `PGEVT_RESULTCOPY` event for the source result will receive `PGEVT_RESULTCOPY` events. typedef struct { const PGresult \*src; PGresult \*dest; } PGEventResultCopy; When a `PGEVT_RESULTCOPY` event is received, the _`evtInfo`_ pointer should be cast to a `PGEventResultCopy *`. The _`src`_ result is what was copied while the _`dest`_ result is the copy destination. This event can be used to provide a deep copy of `instanceData`, since `PQcopyResult` cannot do that. If an event procedure fails (returns zero), that event procedure will be ignored for the remaining lifetime of the new result; that is, it will not receive `PGEVT_RESULTCOPY` or `PGEVT_RESULTDESTROY` events for that result or results copied from it. `PGEVT_RESULTDESTROY` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PGEVT-RESULTDESTROY) The result destroy event is fired in response to a [`PQclear`](https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQCLEAR) . It is the event procedure's responsibility to properly clean up its event data as libpq has no ability to manage this memory. Failure to clean up will lead to memory leaks. typedef struct { PGresult \*result; } PGEventResultDestroy; When a `PGEVT_RESULTDESTROY` event is received, the _`evtInfo`_ pointer should be cast to a `PGEventResultDestroy *`. This event is fired prior to [`PQclear`](https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQCLEAR) performing any other cleanup. The return value of the event procedure is ignored since there is no way of indicating a failure from [`PQclear`](https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQCLEAR) . Also, an event procedure failure should not abort the process of cleaning up unwanted memory. ### 32.14.2. Event Callback Procedure [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-EVENTS-PROC) `PGEventProc` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PGEVENTPROC) `PGEventProc` is a typedef for a pointer to an event procedure, that is, the user callback function that receives events from libpq. The signature of an event procedure must be int eventproc(PGEventId evtId, void \*evtInfo, void \*passThrough) The _`evtId`_ parameter indicates which `PGEVT` event occurred. The _`evtInfo`_ pointer must be cast to the appropriate structure type to obtain further information about the event. The _`passThrough`_ parameter is the pointer provided to [`PQregisterEventProc`](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQREGISTEREVENTPROC) when the event procedure was registered. The function should return a non-zero value if it succeeds and zero if it fails. A particular event procedure can be registered only once in any `PGconn`. This is because the address of the procedure is used as a lookup key to identify the associated instance data. ### Caution On Windows, functions can have two different addresses: one visible from outside a DLL and another visible from inside the DLL. One should be careful that only one of these addresses is used with libpq's event-procedure functions, else confusion will result. The simplest rule for writing code that will work is to ensure that event procedures are declared `static`. If the procedure's address must be available outside its own source file, expose a separate function to return the address. ### 32.14.3. Event Support Functions [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-EVENTS-FUNCS) `PQregisterEventProc` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQREGISTEREVENTPROC) Registers an event callback procedure with libpq. int PQregisterEventProc(PGconn \*conn, PGEventProc proc, const char \*name, void \*passThrough); An event procedure must be registered once on each `PGconn` you want to receive events about. There is no limit, other than memory, on the number of event procedures that can be registered with a connection. The function returns a non-zero value if it succeeds and zero if it fails. The _`proc`_ argument will be called when a libpq event is fired. Its memory address is also used to lookup `instanceData`. The _`name`_ argument is used to refer to the event procedure in error messages. This value cannot be `NULL` or a zero-length string. The name string is copied into the `PGconn`, so what is passed need not be long-lived. The _`passThrough`_ pointer is passed to the _`proc`_ whenever an event occurs. This argument can be `NULL`. `PQsetInstanceData` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQSETINSTANCEDATA) Sets the connection _`conn`_'s `instanceData` for procedure _`proc`_ to _`data`_. This returns non-zero for success and zero for failure. (Failure is only possible if _`proc`_ has not been properly registered in _`conn`_.) int PQsetInstanceData(PGconn \*conn, PGEventProc proc, void \*data); `PQinstanceData` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQINSTANCEDATA) Returns the connection _`conn`_'s `instanceData` associated with procedure _`proc`_, or `NULL` if there is none. void \*PQinstanceData(const PGconn \*conn, PGEventProc proc); `PQresultSetInstanceData` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQRESULTSETINSTANCEDATA) Sets the result's `instanceData` for _`proc`_ to _`data`_. This returns non-zero for success and zero for failure. (Failure is only possible if _`proc`_ has not been properly registered in the result.) int PQresultSetInstanceData(PGresult \*res, PGEventProc proc, void \*data); Beware that any storage represented by _`data`_ will not be accounted for by [`PQresultMemorySize`](https://www.postgresql.org/docs/current/libpq-misc.html#LIBPQ-PQRESULTMEMORYSIZE) , unless it is allocated using [`PQresultAlloc`](https://www.postgresql.org/docs/current/libpq-misc.html#LIBPQ-PQRESULTALLOC) . (Doing so is recommendable because it eliminates the need to free such storage explicitly when the result is destroyed.) `PQresultInstanceData` [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-PQRESULTINSTANCEDATA) Returns the result's `instanceData` associated with _`proc`_, or `NULL` if there is none. void \*PQresultInstanceData(const PGresult \*res, PGEventProc proc); ### 32.14.4. Event Example [#](https://www.postgresql.org/docs/current/libpq-events.html#LIBPQ-EVENTS-EXAMPLE) Here is a skeleton example of managing private data associated with libpq connections and results. /\* required header for libpq events (note: includes libpq-fe.h) \*/ #include /\* The instanceData \*/ typedef struct { int n; char \*str; } mydata; /\* PGEventProc \*/ static int myEventProc(PGEventId evtId, void \*evtInfo, void \*passThrough); int main(void) { mydata \*data; PGresult \*res; PGconn \*conn = PQconnectdb("dbname=postgres options=-csearch\_path="); if (PQstatus(conn) != CONNECTION\_OK) { /\* PQerrorMessage's result includes a trailing newline \*/ fprintf(stderr, "%s", PQerrorMessage(conn)); PQfinish(conn); return 1; } /\* called once on any connection that should receive events. \* Sends a PGEVT\_REGISTER to myEventProc. \*/ if (!PQregisterEventProc(conn, myEventProc, "mydata\_proc", NULL)) { fprintf(stderr, "Cannot register PGEventProc\\n"); PQfinish(conn); return 1; } /\* conn instanceData is available \*/ data = PQinstanceData(conn, myEventProc); /\* Sends a PGEVT\_RESULTCREATE to myEventProc \*/ res = PQexec(conn, "SELECT 1 + 1"); /\* result instanceData is available \*/ data = PQresultInstanceData(res, myEventProc); /\* If PG\_COPYRES\_EVENTS is used, sends a PGEVT\_RESULTCOPY to myEventProc \*/ res\_copy = PQcopyResult(res, PG\_COPYRES\_TUPLES | PG\_COPYRES\_EVENTS); /\* result instanceData is available if PG\_COPYRES\_EVENTS was \* used during the PQcopyResult call. \*/ data = PQresultInstanceData(res\_copy, myEventProc); /\* Both clears send a PGEVT\_RESULTDESTROY to myEventProc \*/ PQclear(res); PQclear(res\_copy); /\* Sends a PGEVT\_CONNDESTROY to myEventProc \*/ PQfinish(conn); return 0; } static int myEventProc(PGEventId evtId, void \*evtInfo, void \*passThrough) { switch (evtId) { case PGEVT\_REGISTER: { PGEventRegister \*e = (PGEventRegister \*)evtInfo; mydata \*data = get\_mydata(e->conn); /\* associate app specific data with connection \*/ PQsetInstanceData(e->conn, myEventProc, data); break; } case PGEVT\_CONNRESET: { PGEventConnReset \*e = (PGEventConnReset \*)evtInfo; mydata \*data = PQinstanceData(e->conn, myEventProc); if (data) memset(data, 0, sizeof(mydata)); break; } case PGEVT\_CONNDESTROY: { PGEventConnDestroy \*e = (PGEventConnDestroy \*)evtInfo; mydata \*data = PQinstanceData(e->conn, myEventProc); /\* free instance data because the conn is being destroyed \*/ if (data) free\_mydata(data); break; } case PGEVT\_RESULTCREATE: { PGEventResultCreate \*e = (PGEventResultCreate \*)evtInfo; mydata \*conn\_data = PQinstanceData(e->conn, myEventProc); mydata \*res\_data = dup\_mydata(conn\_data); /\* associate app specific data with result (copy it from conn) \*/ PQresultSetInstanceData(e->result, myEventProc, res\_data); break; } case PGEVT\_RESULTCOPY: { PGEventResultCopy \*e = (PGEventResultCopy \*)evtInfo; mydata \*src\_data = PQresultInstanceData(e->src, myEventProc); mydata \*dest\_data = dup\_mydata(src\_data); /\* associate app specific data with result (copy it from a result) \*/ PQresultSetInstanceData(e->dest, myEventProc, dest\_data); break; } case PGEVT\_RESULTDESTROY: { PGEventResultDestroy \*e = (PGEventResultDestroy \*)evtInfo; mydata \*data = PQresultInstanceData(e->result, myEventProc); /\* free instance data because the result is being destroyed \*/ if (data) free\_mydata(data); break; } /\* unknown event ID, just return true. \*/ default: break; } return true; /\* event processing succeeded \*/ } * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/libpq-notice-processing.html "32.13. Notice Processing") | [Up](https://www.postgresql.org/docs/current/libpq.html "Chapter 32. libpq — C Library") | [Next](https://www.postgresql.org/docs/current/libpq-envars.html "32.15. Environment Variables") | | 32.13. Notice Processing | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 32.15. Environment Variables | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/libpq-events.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 14. Performance Tips November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/performance-tips.html "PostgreSQL 18 - Chapter 14. Performance Tips") ([18](https://www.postgresql.org/docs/18/performance-tips.html "PostgreSQL 18 - Chapter 14. Performance Tips") ) / [17](https://www.postgresql.org/docs/17/performance-tips.html "PostgreSQL 17 - Chapter 14. Performance Tips") / [16](https://www.postgresql.org/docs/16/performance-tips.html "PostgreSQL 16 - Chapter 14. Performance Tips") / [15](https://www.postgresql.org/docs/15/performance-tips.html "PostgreSQL 15 - Chapter 14. Performance Tips") / [14](https://www.postgresql.org/docs/14/performance-tips.html "PostgreSQL 14 - Chapter 14. Performance Tips") Development Versions: [devel](https://www.postgresql.org/docs/devel/performance-tips.html "PostgreSQL devel - Chapter 14. Performance Tips") Unsupported versions: [13](https://www.postgresql.org/docs/13/performance-tips.html "PostgreSQL 13 - Chapter 14. Performance Tips") / [12](https://www.postgresql.org/docs/12/performance-tips.html "PostgreSQL 12 - Chapter 14. Performance Tips") / [11](https://www.postgresql.org/docs/11/performance-tips.html "PostgreSQL 11 - Chapter 14. Performance Tips") / [10](https://www.postgresql.org/docs/10/performance-tips.html "PostgreSQL 10 - Chapter 14. Performance Tips") / [9.6](https://www.postgresql.org/docs/9.6/performance-tips.html "PostgreSQL 9.6 - Chapter 14. Performance Tips") / [9.5](https://www.postgresql.org/docs/9.5/performance-tips.html "PostgreSQL 9.5 - Chapter 14. Performance Tips") / [9.4](https://www.postgresql.org/docs/9.4/performance-tips.html "PostgreSQL 9.4 - Chapter 14. Performance Tips") / [9.3](https://www.postgresql.org/docs/9.3/performance-tips.html "PostgreSQL 9.3 - Chapter 14. Performance Tips") / [9.2](https://www.postgresql.org/docs/9.2/performance-tips.html "PostgreSQL 9.2 - Chapter 14. Performance Tips") / [9.1](https://www.postgresql.org/docs/9.1/performance-tips.html "PostgreSQL 9.1 - Chapter 14. Performance Tips") / [9.0](https://www.postgresql.org/docs/9.0/performance-tips.html "PostgreSQL 9.0 - Chapter 14. Performance Tips") / [8.4](https://www.postgresql.org/docs/8.4/performance-tips.html "PostgreSQL 8.4 - Chapter 14. Performance Tips") / [8.3](https://www.postgresql.org/docs/8.3/performance-tips.html "PostgreSQL 8.3 - Chapter 14. Performance Tips") / [8.2](https://www.postgresql.org/docs/8.2/performance-tips.html "PostgreSQL 8.2 - Chapter 14. Performance Tips") / [8.1](https://www.postgresql.org/docs/8.1/performance-tips.html "PostgreSQL 8.1 - Chapter 14. Performance Tips") / [8.0](https://www.postgresql.org/docs/8.0/performance-tips.html "PostgreSQL 8.0 - Chapter 14. Performance Tips") / [7.4](https://www.postgresql.org/docs/7.4/performance-tips.html "PostgreSQL 7.4 - Chapter 14. Performance Tips") / [7.3](https://www.postgresql.org/docs/7.3/performance-tips.html "PostgreSQL 7.3 - Chapter 14. Performance Tips") / [7.2](https://www.postgresql.org/docs/7.2/performance-tips.html "PostgreSQL 7.2 - Chapter 14. Performance Tips") / [7.1](https://www.postgresql.org/docs/7.1/performance-tips.html "PostgreSQL 7.1 - Chapter 14. Performance Tips") | Chapter 14. Performance Tips | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/locking-indexes.html "13.7. Locking and Indexes") | [Up](https://www.postgresql.org/docs/current/sql.html "Part II. The SQL Language") | Part II. The SQL Language | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/using-explain.html "14.1. Using EXPLAIN") | * * * Chapter 14. Performance Tips ---------------------------- **Table of Contents** [14.1. Using `EXPLAIN`](https://www.postgresql.org/docs/current/using-explain.html) [14.1.1. `EXPLAIN` Basics](https://www.postgresql.org/docs/current/using-explain.html#USING-EXPLAIN-BASICS) [14.1.2. `EXPLAIN ANALYZE`](https://www.postgresql.org/docs/current/using-explain.html#USING-EXPLAIN-ANALYZE) [14.1.3. Caveats](https://www.postgresql.org/docs/current/using-explain.html#USING-EXPLAIN-CAVEATS) [14.2. Statistics Used by the Planner](https://www.postgresql.org/docs/current/planner-stats.html) [14.2.1. Single-Column Statistics](https://www.postgresql.org/docs/current/planner-stats.html#PLANNER-STATS-SINGLE-COLUMN) [14.2.2. Extended Statistics](https://www.postgresql.org/docs/current/planner-stats.html#PLANNER-STATS-EXTENDED) [14.3. Controlling the Planner with Explicit `JOIN` Clauses](https://www.postgresql.org/docs/current/explicit-joins.html) [14.4. Populating a Database](https://www.postgresql.org/docs/current/populate.html) [14.4.1. Disable Autocommit](https://www.postgresql.org/docs/current/populate.html#DISABLE-AUTOCOMMIT) [14.4.2. Use `COPY`](https://www.postgresql.org/docs/current/populate.html#POPULATE-COPY-FROM) [14.4.3. Remove Indexes](https://www.postgresql.org/docs/current/populate.html#POPULATE-RM-INDEXES) [14.4.4. Remove Foreign Key Constraints](https://www.postgresql.org/docs/current/populate.html#POPULATE-RM-FKEYS) [14.4.5. Increase `maintenance_work_mem`](https://www.postgresql.org/docs/current/populate.html#POPULATE-WORK-MEM) [14.4.6. Increase `max_wal_size`](https://www.postgresql.org/docs/current/populate.html#POPULATE-MAX-WAL-SIZE) [14.4.7. Disable WAL Archival and Streaming Replication](https://www.postgresql.org/docs/current/populate.html#POPULATE-PITR) [14.4.8. Run `ANALYZE` Afterwards](https://www.postgresql.org/docs/current/populate.html#POPULATE-ANALYZE) [14.4.9. Some Notes about pg\_dump](https://www.postgresql.org/docs/current/populate.html#POPULATE-PG-DUMP) [14.5. Non-Durable Settings](https://www.postgresql.org/docs/current/non-durability.html) Query performance can be affected by many things. Some of these can be controlled by the user, while others are fundamental to the underlying design of the system. This chapter provides some hints about understanding and tuning PostgreSQL performance. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/locking-indexes.html "13.7. Locking and Indexes") | [Up](https://www.postgresql.org/docs/current/sql.html "Part II. The SQL Language") | [Next](https://www.postgresql.org/docs/current/using-explain.html "14.1. Using EXPLAIN") | | 13.7. Locking and Indexes | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 14.1. Using `EXPLAIN` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/performance-tips.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 9.1: ALTER EXTENSION November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 9.1](https://www.postgresql.org/docs/9.1/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alterextension.html "PostgreSQL 18 - ALTER EXTENSION") ([18](https://www.postgresql.org/docs/18/sql-alterextension.html "PostgreSQL 18 - ALTER EXTENSION") ) / [17](https://www.postgresql.org/docs/17/sql-alterextension.html "PostgreSQL 17 - ALTER EXTENSION") / [16](https://www.postgresql.org/docs/16/sql-alterextension.html "PostgreSQL 16 - ALTER EXTENSION") / [15](https://www.postgresql.org/docs/15/sql-alterextension.html "PostgreSQL 15 - ALTER EXTENSION") / [14](https://www.postgresql.org/docs/14/sql-alterextension.html "PostgreSQL 14 - ALTER EXTENSION") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alterextension.html "PostgreSQL devel - ALTER EXTENSION") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alterextension.html "PostgreSQL 13 - ALTER EXTENSION") / [12](https://www.postgresql.org/docs/12/sql-alterextension.html "PostgreSQL 12 - ALTER EXTENSION") / [11](https://www.postgresql.org/docs/11/sql-alterextension.html "PostgreSQL 11 - ALTER EXTENSION") / [10](https://www.postgresql.org/docs/10/sql-alterextension.html "PostgreSQL 10 - ALTER EXTENSION") / [9.6](https://www.postgresql.org/docs/9.6/sql-alterextension.html "PostgreSQL 9.6 - ALTER EXTENSION") / [9.5](https://www.postgresql.org/docs/9.5/sql-alterextension.html "PostgreSQL 9.5 - ALTER EXTENSION") / [9.4](https://www.postgresql.org/docs/9.4/sql-alterextension.html "PostgreSQL 9.4 - ALTER EXTENSION") / [9.3](https://www.postgresql.org/docs/9.3/sql-alterextension.html "PostgreSQL 9.3 - ALTER EXTENSION") / [9.2](https://www.postgresql.org/docs/9.2/sql-alterextension.html "PostgreSQL 9.2 - ALTER EXTENSION") / [9.1](https://www.postgresql.org/docs/9.1/sql-alterextension.html "PostgreSQL 9.1 - ALTER EXTENSION") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/sql-alterextension.html "PostgreSQL - ALTER EXTENSION") version, or one of the other supported versions listed above instead. | [PostgreSQL 9.1.24 Documentation](https://www.postgresql.org/docs/9.1/index.html) | | | | | | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.1/sql-alterdomain.html "ALTER DOMAIN") | [Up](https://www.postgresql.org/docs/9.1/sql-commands.html) | | [Next](https://www.postgresql.org/docs/9.1/sql-alterforeigndatawrapper.html "ALTER FOREIGN DATA WRAPPER") | * * * ALTER EXTENSION =============== Name ---- ALTER EXTENSION --  change the definition of an extension Synopsis -------- ALTER EXTENSION extension\_name UPDATE \[ TO new\_version \] ALTER EXTENSION extension\_name SET SCHEMA new\_schema ALTER EXTENSION extension\_name ADD member\_object ALTER EXTENSION extension\_name DROP member\_object where member\_object is: AGGREGATE agg\_name (agg\_type \[, ...\] ) | CAST (source\_type AS target\_type) | COLLATION object\_name | CONVERSION object\_name | DOMAIN object\_name | FOREIGN DATA WRAPPER object\_name | FOREIGN TABLE object\_name | FUNCTION function\_name ( \[ \[ argmode \] \[ argname \] argtype \[, ...\] \] ) | OPERATOR operator\_name (left\_type, right\_type) | OPERATOR CLASS object\_name USING index\_method | OPERATOR FAMILY object\_name USING index\_method | \[ PROCEDURAL \] LANGUAGE object\_name | SCHEMA object\_name | SEQUENCE object\_name | SERVER object\_name | TABLE object\_name | TEXT SEARCH CONFIGURATION object\_name | TEXT SEARCH DICTIONARY object\_name | TEXT SEARCH PARSER object\_name | TEXT SEARCH TEMPLATE object\_name | TYPE object\_name | VIEW object\_name Description ----------- ALTER EXTENSION changes the definition of an installed extension. There are several subforms: UPDATE This form updates the extension to a newer version. The extension must supply a suitable update script (or series of scripts) that can modify the currently-installed version into the requested version. SET SCHEMA This form moves the extension's objects into another schema. The extension has to be _relocatable_ for this command to succeed. ADD member\_object This form adds an existing object to the extension. This is mainly useful in extension update scripts. The object will subsequently be treated as a member of the extension; notably, it can only be dropped by dropping the extension. DROP member\_object This form removes a member object from the extension. This is mainly useful in extension update scripts. The object is not dropped, only disassociated from the extension. See [Section 35.15](https://www.postgresql.org/docs/9.1/extend-extensions.html) for more information about these operations. You must own the extension to use ALTER EXTENSION. The ADD/DROP forms require ownership of the added/dropped object as well. Parameters ---------- extension\_name The name of an installed extension. new\_version The desired new version of the extension. This can be written as either an identifier or a string literal. If not specified, ALTER EXTENSION UPDATE attempts to update to whatever is shown as the default version in the extension's control file. new\_schema The new schema for the extension. object\_name agg\_name function\_name operator\_name The name of an object to be added to or removed from the extension. Names of tables, aggregates, domains, foreign tables, functions, operators, operator classes, operator families, sequences, text search objects, types, and views can be schema-qualified. agg\_type An input data type on which the aggregate function operates. To reference a zero-argument aggregate function, write \* in place of the list of input data types. source\_type The name of the source data type of the cast. target\_type The name of the target data type of the cast. argmode The mode of a function argument: IN, OUT, INOUT, or VARIADIC. If omitted, the default is IN. Note that ALTER EXTENSION does not actually pay any attention to OUT arguments, since only the input arguments are needed to determine the function's identity. So it is sufficient to list the IN, INOUT, and VARIADIC arguments. argname The name of a function argument. Note that ALTER EXTENSION does not actually pay any attention to argument names, since only the argument data types are needed to determine the function's identity. argtype The data type(s) of the function's arguments (optionally schema-qualified), if any. left\_type right\_type The data type(s) of the operator's arguments (optionally schema-qualified). Write NONE for the missing argument of a prefix or postfix operator. PROCEDURAL This is a noise word. Examples -------- To update the hstore extension to version 2.0: ALTER EXTENSION hstore UPDATE TO '2.0'; To change the schema of the hstore extension to utils: ALTER EXTENSION hstore SET SCHEMA utils; To add an existing function to the hstore extension: ALTER EXTENSION hstore ADD FUNCTION populate\_record(anyelement, hstore); Compatibility ------------- ALTER EXTENSION is a PostgreSQL extension. See Also -------- [CREATE EXTENSION](https://www.postgresql.org/docs/9.1/sql-createextension.html) , [DROP EXTENSION](https://www.postgresql.org/docs/9.1/sql-dropextension.html) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.1/sql-alterdomain.html) | [Home](https://www.postgresql.org/docs/9.1/index.html) | [Next](https://www.postgresql.org/docs/9.1/sql-alterforeigndatawrapper.html) | | ALTER DOMAIN | [Up](https://www.postgresql.org/docs/9.1/sql-commands.html) | ALTER FOREIGN DATA WRAPPER | --- # PostgreSQL: Documentation: 18: CREATE OPERATOR CLASS November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createopclass.html "PostgreSQL 18 - CREATE OPERATOR CLASS") ([18](https://www.postgresql.org/docs/18/sql-createopclass.html "PostgreSQL 18 - CREATE OPERATOR CLASS") ) / [17](https://www.postgresql.org/docs/17/sql-createopclass.html "PostgreSQL 17 - CREATE OPERATOR CLASS") / [16](https://www.postgresql.org/docs/16/sql-createopclass.html "PostgreSQL 16 - CREATE OPERATOR CLASS") / [15](https://www.postgresql.org/docs/15/sql-createopclass.html "PostgreSQL 15 - CREATE OPERATOR CLASS") / [14](https://www.postgresql.org/docs/14/sql-createopclass.html "PostgreSQL 14 - CREATE OPERATOR CLASS") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createopclass.html "PostgreSQL devel - CREATE OPERATOR CLASS") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createopclass.html "PostgreSQL 13 - CREATE OPERATOR CLASS") / [12](https://www.postgresql.org/docs/12/sql-createopclass.html "PostgreSQL 12 - CREATE OPERATOR CLASS") / [11](https://www.postgresql.org/docs/11/sql-createopclass.html "PostgreSQL 11 - CREATE OPERATOR CLASS") / [10](https://www.postgresql.org/docs/10/sql-createopclass.html "PostgreSQL 10 - CREATE OPERATOR CLASS") / [9.6](https://www.postgresql.org/docs/9.6/sql-createopclass.html "PostgreSQL 9.6 - CREATE OPERATOR CLASS") / [9.5](https://www.postgresql.org/docs/9.5/sql-createopclass.html "PostgreSQL 9.5 - CREATE OPERATOR CLASS") / [9.4](https://www.postgresql.org/docs/9.4/sql-createopclass.html "PostgreSQL 9.4 - CREATE OPERATOR CLASS") / [9.3](https://www.postgresql.org/docs/9.3/sql-createopclass.html "PostgreSQL 9.3 - CREATE OPERATOR CLASS") / [9.2](https://www.postgresql.org/docs/9.2/sql-createopclass.html "PostgreSQL 9.2 - CREATE OPERATOR CLASS") / [9.1](https://www.postgresql.org/docs/9.1/sql-createopclass.html "PostgreSQL 9.1 - CREATE OPERATOR CLASS") / [9.0](https://www.postgresql.org/docs/9.0/sql-createopclass.html "PostgreSQL 9.0 - CREATE OPERATOR CLASS") / [8.4](https://www.postgresql.org/docs/8.4/sql-createopclass.html "PostgreSQL 8.4 - CREATE OPERATOR CLASS") / [8.3](https://www.postgresql.org/docs/8.3/sql-createopclass.html "PostgreSQL 8.3 - CREATE OPERATOR CLASS") / [8.2](https://www.postgresql.org/docs/8.2/sql-createopclass.html "PostgreSQL 8.2 - CREATE OPERATOR CLASS") / [8.1](https://www.postgresql.org/docs/8.1/sql-createopclass.html "PostgreSQL 8.1 - CREATE OPERATOR CLASS") / [8.0](https://www.postgresql.org/docs/8.0/sql-createopclass.html "PostgreSQL 8.0 - CREATE OPERATOR CLASS") / [7.4](https://www.postgresql.org/docs/7.4/sql-createopclass.html "PostgreSQL 7.4 - CREATE OPERATOR CLASS") / [7.3](https://www.postgresql.org/docs/7.3/sql-createopclass.html "PostgreSQL 7.3 - CREATE OPERATOR CLASS") | CREATE OPERATOR CLASS | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createoperator.html "CREATE OPERATOR") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-createopfamily.html "CREATE OPERATOR FAMILY") | * * * CREATE OPERATOR CLASS --------------------- CREATE OPERATOR CLASS — define a new operator class Synopsis -------- CREATE OPERATOR CLASS _`name`_ \[ DEFAULT \] FOR TYPE _`data_type`_ USING _`index_method`_ \[ FAMILY _`family_name`_ \] AS { OPERATOR _`strategy_number`_ _`operator_name`_ \[ ( _`op_type`_, _`op_type`_ ) \] \[ FOR SEARCH | FOR ORDER BY _`sort_family_name`_ \] | FUNCTION _`support_number`_ \[ ( _`op_type`_ \[ , _`op_type`_ \] ) \] _`function_name`_ ( _`argument_type`_ \[, ...\] ) | STORAGE _`storage_type`_ } \[, ... \] Description ----------- `CREATE OPERATOR CLASS` creates a new operator class. An operator class defines how a particular data type can be used with an index. The operator class specifies that certain operators will fill particular roles or “strategies” for this data type and this index method. The operator class also specifies the support functions to be used by the index method when the operator class is selected for an index column. All the operators and functions used by an operator class must be defined before the operator class can be created. If a schema name is given then the operator class is created in the specified schema. Otherwise it is created in the current schema. Two operator classes in the same schema can have the same name only if they are for different index methods. The user who defines an operator class becomes its owner. Presently, the creating user must be a superuser. (This restriction is made because an erroneous operator class definition could confuse or even crash the server.) `CREATE OPERATOR CLASS` does not presently check whether the operator class definition includes all the operators and functions required by the index method, nor whether the operators and functions form a self-consistent set. It is the user's responsibility to define a valid operator class. Related operator classes can be grouped into _operator families_. To add a new operator class to an existing family, specify the `FAMILY` option in `CREATE OPERATOR CLASS`. Without this option, the new class is placed into a family named the same as the new class (creating that family if it doesn't already exist). Refer to [Section 36.16](https://www.postgresql.org/docs/current/xindex.html "36.16. Interfacing Extensions to Indexes") for further information. Parameters ---------- _`name`_ The name of the operator class to be created. The name can be schema-qualified. `DEFAULT` If present, the operator class will become the default operator class for its data type. At most one operator class can be the default for a specific data type and index method. _`data_type`_ The column data type that this operator class is for. _`index_method`_ The name of the index method this operator class is for. _`family_name`_ The name of the existing operator family to add this operator class to. If not specified, a family named the same as the operator class is used (creating it, if it doesn't already exist). _`strategy_number`_ The index method's strategy number for an operator associated with the operator class. _`operator_name`_ The name (optionally schema-qualified) of an operator associated with the operator class. _`op_type`_ In an `OPERATOR` clause, the operand data type(s) of the operator, or `NONE` to signify a prefix operator. The operand data types can be omitted in the normal case where they are the same as the operator class's data type. In a `FUNCTION` clause, the operand data type(s) the function is intended to support, if different from the input data type(s) of the function (for B-tree comparison functions and hash functions) or the class's data type (for B-tree sort support functions, B-tree equal image functions, and all functions in GiST, SP-GiST, GIN and BRIN operator classes). These defaults are correct, and so _`op_type`_ need not be specified in `FUNCTION` clauses, except for the case of a B-tree sort support function that is meant to support cross-data-type comparisons. _`sort_family_name`_ The name (optionally schema-qualified) of an existing `btree` operator family that describes the sort ordering associated with an ordering operator. If neither `FOR SEARCH` nor `FOR ORDER BY` is specified, `FOR SEARCH` is the default. _`support_number`_ The index method's support function number for a function associated with the operator class. _`function_name`_ The name (optionally schema-qualified) of a function that is an index method support function for the operator class. _`argument_type`_ The parameter data type(s) of the function. _`storage_type`_ The data type actually stored in the index. Normally this is the same as the column data type, but some index methods (currently GiST, GIN, SP-GiST and BRIN) allow it to be different. The `STORAGE` clause must be omitted unless the index method allows a different type to be used. If the column _`data_type`_ is specified as `anyarray`, the _`storage_type`_ can be declared as `anyelement` to indicate that the index entries are members of the element type belonging to the actual array type that each particular index is created for. The `OPERATOR`, `FUNCTION`, and `STORAGE` clauses can appear in any order. Notes ----- Because the index machinery does not check access permissions on functions before using them, including a function or operator in an operator class is tantamount to granting public execute permission on it. This is usually not an issue for the sorts of functions that are useful in an operator class. The operators should not be defined by SQL functions. An SQL function is likely to be inlined into the calling query, which will prevent the optimizer from recognizing that the query matches an index. Examples -------- The following example command defines a GiST index operator class for the data type `_int4` (array of `int4`). See the [intarray](https://www.postgresql.org/docs/current/intarray.html "F.19. intarray — manipulate arrays of integers") module for the complete example. CREATE OPERATOR CLASS gist\_\_int\_ops DEFAULT FOR TYPE \_int4 USING gist AS OPERATOR 3 &&, OPERATOR 6 = (anyarray, anyarray), OPERATOR 7 @>, OPERATOR 8 <@, OPERATOR 20 @@ (\_int4, query\_int), FUNCTION 1 g\_int\_consistent (internal, \_int4, smallint, oid, internal), FUNCTION 2 g\_int\_union (internal, internal), FUNCTION 3 g\_int\_compress (internal), FUNCTION 4 g\_int\_decompress (internal), FUNCTION 5 g\_int\_penalty (internal, internal, internal), FUNCTION 6 g\_int\_picksplit (internal, internal), FUNCTION 7 g\_int\_same (\_int4, \_int4, internal); Compatibility ------------- `CREATE OPERATOR CLASS` is a PostgreSQL extension. There is no `CREATE OPERATOR CLASS` statement in the SQL standard. See Also -------- [ALTER OPERATOR CLASS](https://www.postgresql.org/docs/current/sql-alteropclass.html "ALTER OPERATOR CLASS") , [DROP OPERATOR CLASS](https://www.postgresql.org/docs/current/sql-dropopclass.html "DROP OPERATOR CLASS") , [CREATE OPERATOR FAMILY](https://www.postgresql.org/docs/current/sql-createopfamily.html "CREATE OPERATOR FAMILY") , [ALTER OPERATOR FAMILY](https://www.postgresql.org/docs/current/sql-alteropfamily.html "ALTER OPERATOR FAMILY") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createoperator.html "CREATE OPERATOR") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-createopfamily.html "CREATE OPERATOR FAMILY") | | CREATE OPERATOR | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | CREATE OPERATOR FAMILY | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createopclass.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.34. pg_timezone_names November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-timezone-names.html "PostgreSQL 18 - 53.34. pg_timezone_names") ([18](https://www.postgresql.org/docs/18/view-pg-timezone-names.html "PostgreSQL 18 - 53.34. pg_timezone_names") ) / [17](https://www.postgresql.org/docs/17/view-pg-timezone-names.html "PostgreSQL 17 - 53.34. pg_timezone_names") / [16](https://www.postgresql.org/docs/16/view-pg-timezone-names.html "PostgreSQL 16 - 53.34. pg_timezone_names") / [15](https://www.postgresql.org/docs/15/view-pg-timezone-names.html "PostgreSQL 15 - 53.34. pg_timezone_names") / [14](https://www.postgresql.org/docs/14/view-pg-timezone-names.html "PostgreSQL 14 - 53.34. pg_timezone_names") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-timezone-names.html "PostgreSQL devel - 53.34. pg_timezone_names") Unsupported versions: [13](https://www.postgresql.org/docs/13/view-pg-timezone-names.html "PostgreSQL 13 - 53.34. pg_timezone_names") / [12](https://www.postgresql.org/docs/12/view-pg-timezone-names.html "PostgreSQL 12 - 53.34. pg_timezone_names") / [11](https://www.postgresql.org/docs/11/view-pg-timezone-names.html "PostgreSQL 11 - 53.34. pg_timezone_names") / [10](https://www.postgresql.org/docs/10/view-pg-timezone-names.html "PostgreSQL 10 - 53.34. pg_timezone_names") / [9.6](https://www.postgresql.org/docs/9.6/view-pg-timezone-names.html "PostgreSQL 9.6 - 53.34. pg_timezone_names") / [9.5](https://www.postgresql.org/docs/9.5/view-pg-timezone-names.html "PostgreSQL 9.5 - 53.34. pg_timezone_names") / [9.4](https://www.postgresql.org/docs/9.4/view-pg-timezone-names.html "PostgreSQL 9.4 - 53.34. pg_timezone_names") / [9.3](https://www.postgresql.org/docs/9.3/view-pg-timezone-names.html "PostgreSQL 9.3 - 53.34. pg_timezone_names") / [9.2](https://www.postgresql.org/docs/9.2/view-pg-timezone-names.html "PostgreSQL 9.2 - 53.34. pg_timezone_names") / [9.1](https://www.postgresql.org/docs/9.1/view-pg-timezone-names.html "PostgreSQL 9.1 - 53.34. pg_timezone_names") / [9.0](https://www.postgresql.org/docs/9.0/view-pg-timezone-names.html "PostgreSQL 9.0 - 53.34. pg_timezone_names") / [8.4](https://www.postgresql.org/docs/8.4/view-pg-timezone-names.html "PostgreSQL 8.4 - 53.34. pg_timezone_names") / [8.3](https://www.postgresql.org/docs/8.3/view-pg-timezone-names.html "PostgreSQL 8.3 - 53.34. pg_timezone_names") / [8.2](https://www.postgresql.org/docs/8.2/view-pg-timezone-names.html "PostgreSQL 8.2 - 53.34. pg_timezone_names") | 53.34. `pg_timezone_names` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-timezone-abbrevs.html "53.33. pg_timezone_abbrevs") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/view-pg-user.html "53.35. pg_user") | * * * 53.34. `pg_timezone_names` [#](https://www.postgresql.org/docs/current/view-pg-timezone-names.html#VIEW-PG-TIMEZONE-NAMES) --------------------------------------------------------------------------------------------------------------------------- The view `pg_timezone_names` provides a list of time zone names that are recognized by `SET TIMEZONE`, along with their associated abbreviations, UTC offsets, and daylight-savings status. (Technically, PostgreSQL does not use UTC because leap seconds are not handled.) Unlike the abbreviations shown in [`pg_timezone_abbrevs`](https://www.postgresql.org/docs/current/view-pg-timezone-abbrevs.html "53.33. pg_timezone_abbrevs") , many of these names imply a set of daylight-savings transition date rules. Therefore, the associated information changes across local DST boundaries. The displayed information is computed based on the current value of `CURRENT_TIMESTAMP`. **Table 53.34. `pg_timezone_names` Columns** | Column Type

Description | | --- | | `name` `text`

Time zone name | | `abbrev` `text`

Time zone abbreviation | | `utc_offset` `interval`

Offset from UTC (positive means east of Greenwich) | | `is_dst` `bool`

True if currently observing daylight savings | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-timezone-abbrevs.html "53.33. pg_timezone_abbrevs") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/current/view-pg-user.html "53.35. pg_user") | | 53.33. `pg_timezone_abbrevs` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 53.35. `pg_user` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-timezone-names.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 43.8. PL/Perl Under the Hood November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plperl-under-the-hood.html "PostgreSQL 18 - 43.8. PL/Perl Under the Hood") ([18](https://www.postgresql.org/docs/18/plperl-under-the-hood.html "PostgreSQL 18 - 43.8. PL/Perl Under the Hood") ) / [17](https://www.postgresql.org/docs/17/plperl-under-the-hood.html "PostgreSQL 17 - 43.8. PL/Perl Under the Hood") / [16](https://www.postgresql.org/docs/16/plperl-under-the-hood.html "PostgreSQL 16 - 43.8. PL/Perl Under the Hood") / [15](https://www.postgresql.org/docs/15/plperl-under-the-hood.html "PostgreSQL 15 - 43.8. PL/Perl Under the Hood") / [14](https://www.postgresql.org/docs/14/plperl-under-the-hood.html "PostgreSQL 14 - 43.8. PL/Perl Under the Hood") Development Versions: [devel](https://www.postgresql.org/docs/devel/plperl-under-the-hood.html "PostgreSQL devel - 43.8. PL/Perl Under the Hood") Unsupported versions: [13](https://www.postgresql.org/docs/13/plperl-under-the-hood.html "PostgreSQL 13 - 43.8. PL/Perl Under the Hood") / [12](https://www.postgresql.org/docs/12/plperl-under-the-hood.html "PostgreSQL 12 - 43.8. PL/Perl Under the Hood") / [11](https://www.postgresql.org/docs/11/plperl-under-the-hood.html "PostgreSQL 11 - 43.8. PL/Perl Under the Hood") / [10](https://www.postgresql.org/docs/10/plperl-under-the-hood.html "PostgreSQL 10 - 43.8. PL/Perl Under the Hood") / [9.6](https://www.postgresql.org/docs/9.6/plperl-under-the-hood.html "PostgreSQL 9.6 - 43.8. PL/Perl Under the Hood") / [9.5](https://www.postgresql.org/docs/9.5/plperl-under-the-hood.html "PostgreSQL 9.5 - 43.8. PL/Perl Under the Hood") / [9.4](https://www.postgresql.org/docs/9.4/plperl-under-the-hood.html "PostgreSQL 9.4 - 43.8. PL/Perl Under the Hood") / [9.3](https://www.postgresql.org/docs/9.3/plperl-under-the-hood.html "PostgreSQL 9.3 - 43.8. PL/Perl Under the Hood") / [9.2](https://www.postgresql.org/docs/9.2/plperl-under-the-hood.html "PostgreSQL 9.2 - 43.8. PL/Perl Under the Hood") / [9.1](https://www.postgresql.org/docs/9.1/plperl-under-the-hood.html "PostgreSQL 9.1 - 43.8. PL/Perl Under the Hood") / [9.0](https://www.postgresql.org/docs/9.0/plperl-under-the-hood.html "PostgreSQL 9.0 - 43.8. PL/Perl Under the Hood") | 43.8. PL/Perl Under the Hood | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/plperl-event-triggers.html "43.7. PL/Perl Event Triggers") | [Up](https://www.postgresql.org/docs/current/plperl.html "Chapter 43. PL/Perl — Perl Procedural Language") | Chapter 43. PL/Perl — Perl Procedural Language | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/plpython.html "Chapter 44. PL/Python — Python Procedural Language") | * * * 43.8. PL/Perl Under the Hood [#](https://www.postgresql.org/docs/current/plperl-under-the-hood.html#PLPERL-UNDER-THE-HOOD) --------------------------------------------------------------------------------------------------------------------------- [43.8.1. Configuration](https://www.postgresql.org/docs/current/plperl-under-the-hood.html#PLPERL-CONFIG) [43.8.2. Limitations and Missing Features](https://www.postgresql.org/docs/current/plperl-under-the-hood.html#PLPERL-MISSING) ### 43.8.1. Configuration [#](https://www.postgresql.org/docs/current/plperl-under-the-hood.html#PLPERL-CONFIG) This section lists configuration parameters that affect PL/Perl. `plperl.on_init` (`string`) [#](https://www.postgresql.org/docs/current/plperl-under-the-hood.html#GUC-PLPERL-ON-INIT) Specifies Perl code to be executed when a Perl interpreter is first initialized, before it is specialized for use by `plperl` or `plperlu`. The SPI functions are not available when this code is executed. If the code fails with an error it will abort the initialization of the interpreter and propagate out to the calling query, causing the current transaction or subtransaction to be aborted. The Perl code is limited to a single string. Longer code can be placed into a module and loaded by the `on_init` string. Examples: plperl.on\_init = 'require "plperlinit.pl"' plperl.on\_init = 'use lib "/my/app"; use MyApp::PgInit;' Any modules loaded by `plperl.on_init`, either directly or indirectly, will be available for use by `plperl`. This may create a security risk. To see what modules have been loaded you can use: DO 'elog(WARNING, join ", ", sort keys %INC)' LANGUAGE plperl; Initialization will happen in the postmaster if the `plperl` library is included in [shared\_preload\_libraries](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES) , in which case extra consideration should be given to the risk of destabilizing the postmaster. The principal reason for making use of this feature is that Perl modules loaded by `plperl.on_init` need be loaded only at postmaster start, and will be instantly available without loading overhead in individual database sessions. However, keep in mind that the overhead is avoided only for the first Perl interpreter used by a database session — either PL/PerlU, or PL/Perl for the first SQL role that calls a PL/Perl function. Any additional Perl interpreters created in a database session will have to execute `plperl.on_init` afresh. Also, on Windows there will be no savings whatsoever from preloading, since the Perl interpreter created in the postmaster process does not propagate to child processes. This parameter can only be set in the `postgresql.conf` file or on the server command line. `plperl.on_plperl_init` (`string`) `plperl.on_plperlu_init` (`string`) [#](https://www.postgresql.org/docs/current/plperl-under-the-hood.html#GUC-PLPERL-ON-PLPERL-INIT) These parameters specify Perl code to be executed when a Perl interpreter is specialized for `plperl` or `plperlu` respectively. This will happen when a PL/Perl or PL/PerlU function is first executed in a database session, or when an additional interpreter has to be created because the other language is called or a PL/Perl function is called by a new SQL role. This follows any initialization done by `plperl.on_init`. The SPI functions are not available when this code is executed. The Perl code in `plperl.on_plperl_init` is executed after “locking down” the interpreter, and thus it can only perform trusted operations. If the code fails with an error it will abort the initialization and propagate out to the calling query, causing the current transaction or subtransaction to be aborted. Any actions already done within Perl won't be undone; however, that interpreter won't be used again. If the language is used again the initialization will be attempted again within a fresh Perl interpreter. Only superusers can change these settings. Although these settings can be changed within a session, such changes will not affect Perl interpreters that have already been used to execute functions. `plperl.use_strict` (`boolean`) [#](https://www.postgresql.org/docs/current/plperl-under-the-hood.html#GUC-PLPERL-USE-STRICT) When set true subsequent compilations of PL/Perl functions will have the `strict` pragma enabled. This parameter does not affect functions already compiled in the current session. ### 43.8.2. Limitations and Missing Features [#](https://www.postgresql.org/docs/current/plperl-under-the-hood.html#PLPERL-MISSING) The following features are currently missing from PL/Perl, but they would make welcome contributions. * PL/Perl functions cannot call each other directly. * SPI is not yet fully implemented. * If you are fetching very large data sets using `spi_exec_query`, you should be aware that these will all go into memory. You can avoid this by using `spi_query`/`spi_fetchrow` as illustrated earlier. A similar problem occurs if a set-returning function passes a large set of rows back to PostgreSQL via `return`. You can avoid this problem too by instead using `return_next` for each row returned, as shown previously. * When a session ends normally, not due to a fatal error, any `END` blocks that have been defined are executed. Currently no other actions are performed. Specifically, file handles are not automatically flushed and objects are not automatically destroyed. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/plperl-event-triggers.html "43.7. PL/Perl Event Triggers") | [Up](https://www.postgresql.org/docs/current/plperl.html "Chapter 43. PL/Perl — Perl Procedural Language") | [Next](https://www.postgresql.org/docs/current/plpython.html "Chapter 44. PL/Python — Python Procedural Language") | | 43.7. PL/Perl Event Triggers | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Chapter 44. PL/Python — Python Procedural Language | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/plperl-under-the-hood.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE STATISTICS November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createstatistics.html "PostgreSQL 18 - CREATE STATISTICS") ([18](https://www.postgresql.org/docs/18/sql-createstatistics.html "PostgreSQL 18 - CREATE STATISTICS") ) / [17](https://www.postgresql.org/docs/17/sql-createstatistics.html "PostgreSQL 17 - CREATE STATISTICS") / [16](https://www.postgresql.org/docs/16/sql-createstatistics.html "PostgreSQL 16 - CREATE STATISTICS") / [15](https://www.postgresql.org/docs/15/sql-createstatistics.html "PostgreSQL 15 - CREATE STATISTICS") / [14](https://www.postgresql.org/docs/14/sql-createstatistics.html "PostgreSQL 14 - CREATE STATISTICS") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createstatistics.html "PostgreSQL devel - CREATE STATISTICS") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createstatistics.html "PostgreSQL 13 - CREATE STATISTICS") / [12](https://www.postgresql.org/docs/12/sql-createstatistics.html "PostgreSQL 12 - CREATE STATISTICS") / [11](https://www.postgresql.org/docs/11/sql-createstatistics.html "PostgreSQL 11 - CREATE STATISTICS") / [10](https://www.postgresql.org/docs/10/sql-createstatistics.html "PostgreSQL 10 - CREATE STATISTICS") | CREATE STATISTICS | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createserver.html "CREATE SERVER") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-createsubscription.html "CREATE SUBSCRIPTION") | * * * CREATE STATISTICS ----------------- CREATE STATISTICS — define extended statistics Synopsis -------- CREATE STATISTICS \[ \[ IF NOT EXISTS \] _`statistics_name`_ \] ON ( _`expression`_ ) FROM _`table_name`_ CREATE STATISTICS \[ \[ IF NOT EXISTS \] _`statistics_name`_ \] \[ ( _`statistics_kind`_ \[, ... \] ) \] ON { _`column_name`_ | ( _`expression`_ ) }, { _`column_name`_ | ( _`expression`_ ) } \[, ...\] FROM _`table_name`_ Description ----------- `CREATE STATISTICS` will create a new extended statistics object tracking data about the specified table, foreign table or materialized view. The statistics object will be created in the current database and will be owned by the user issuing the command. The `CREATE STATISTICS` command has two basic forms. The first form allows univariate statistics for a single expression to be collected, providing benefits similar to an expression index without the overhead of index maintenance. This form does not allow the statistics kind to be specified, since the various statistics kinds refer only to multivariate statistics. The second form of the command allows multivariate statistics on multiple columns and/or expressions to be collected, optionally specifying which statistics kinds to include. This form will also automatically cause univariate statistics to be collected on any expressions included in the list. If a schema name is given (for example, `CREATE STATISTICS myschema.mystat ...`) then the statistics object is created in the specified schema. Otherwise it is created in the current schema. If given, the name of the statistics object must be distinct from the name of any other statistics object in the same schema. Parameters ---------- `IF NOT EXISTS` Do not throw an error if a statistics object with the same name already exists. A notice is issued in this case. Note that only the name of the statistics object is considered here, not the details of its definition. Statistics name is required when `IF NOT EXISTS` is specified. _`statistics_name`_ The name (optionally schema-qualified) of the statistics object to be created. If the name is omitted, PostgreSQL chooses a suitable name based on the parent table's name and the defined column name(s) and/or expression(s). _`statistics_kind`_ A multivariate statistics kind to be computed in this statistics object. Currently supported kinds are `ndistinct`, which enables n-distinct statistics, `dependencies`, which enables functional dependency statistics, and `mcv` which enables most-common values lists. If this clause is omitted, all supported statistics kinds are included in the statistics object. Univariate expression statistics are built automatically if the statistics definition includes any complex expressions rather than just simple column references. For more information, see [Section 14.2.2](https://www.postgresql.org/docs/current/planner-stats.html#PLANNER-STATS-EXTENDED "14.2.2. Extended Statistics") and [Section 69.2](https://www.postgresql.org/docs/current/multivariate-statistics-examples.html "69.2. Multivariate Statistics Examples") . _`column_name`_ The name of a table column to be covered by the computed statistics. This is only allowed when building multivariate statistics. At least two column names or expressions must be specified, and their order is not significant. _`expression`_ An expression to be covered by the computed statistics. This may be used to build univariate statistics on a single expression, or as part of a list of multiple column names and/or expressions to build multivariate statistics. In the latter case, separate univariate statistics are built automatically for each expression in the list. _`table_name`_ The name (optionally schema-qualified) of the table containing the column(s) the statistics are computed on; see [ANALYZE](https://www.postgresql.org/docs/current/sql-analyze.html "ANALYZE") for an explanation of the handling of inheritance and partitions. Notes ----- You must be the owner of a table to create a statistics object reading it. Once created, however, the ownership of the statistics object is independent of the underlying table(s). Expression statistics are per-expression and are similar to creating an index on the expression, except that they avoid the overhead of index maintenance. Expression statistics are built automatically for each expression in the statistics object definition. Extended statistics are not currently used by the planner for selectivity estimations made for table joins. This limitation will likely be removed in a future version of PostgreSQL. Examples -------- Create table `t1` with two functionally dependent columns, i.e., knowledge of a value in the first column is sufficient for determining the value in the other column. Then functional dependency statistics are built on those columns: CREATE TABLE t1 ( a int, b int ); INSERT INTO t1 SELECT i/100, i/500 FROM generate\_series(1,1000000) s(i); ANALYZE t1; -- the number of matching rows will be drastically underestimated: EXPLAIN ANALYZE SELECT \* FROM t1 WHERE (a = 1) AND (b = 0); CREATE STATISTICS s1 (dependencies) ON a, b FROM t1; ANALYZE t1; -- now the row count estimate is more accurate: EXPLAIN ANALYZE SELECT \* FROM t1 WHERE (a = 1) AND (b = 0); Without functional-dependency statistics, the planner would assume that the two `WHERE` conditions are independent, and would multiply their selectivities together to arrive at a much-too-small row count estimate. With such statistics, the planner recognizes that the `WHERE` conditions are redundant and does not underestimate the row count. Create table `t2` with two perfectly correlated columns (containing identical data), and an MCV list on those columns: CREATE TABLE t2 ( a int, b int ); INSERT INTO t2 SELECT mod(i,100), mod(i,100) FROM generate\_series(1,1000000) s(i); CREATE STATISTICS s2 (mcv) ON a, b FROM t2; ANALYZE t2; -- valid combination (found in MCV) EXPLAIN ANALYZE SELECT \* FROM t2 WHERE (a = 1) AND (b = 1); -- invalid combination (not found in MCV) EXPLAIN ANALYZE SELECT \* FROM t2 WHERE (a = 1) AND (b = 2); The MCV list gives the planner more detailed information about the specific values that commonly appear in the table, as well as an upper bound on the selectivities of combinations of values that do not appear in the table, allowing it to generate better estimates in both cases. Create table `t3` with a single timestamp column, and run queries using expressions on that column. Without extended statistics, the planner has no information about the data distribution for the expressions, and uses default estimates. The planner also does not realize that the value of the date truncated to the month is fully determined by the value of the date truncated to the day. Then expression and ndistinct statistics are built on those two expressions: CREATE TABLE t3 ( a timestamp ); INSERT INTO t3 SELECT i FROM generate\_series('2020-01-01'::timestamp, '2020-12-31'::timestamp, '1 minute'::interval) s(i); ANALYZE t3; -- the number of matching rows will be drastically underestimated: EXPLAIN ANALYZE SELECT \* FROM t3 WHERE date\_trunc('month', a) = '2020-01-01'::timestamp; EXPLAIN ANALYZE SELECT \* FROM t3 WHERE date\_trunc('day', a) BETWEEN '2020-01-01'::timestamp AND '2020-06-30'::timestamp; EXPLAIN ANALYZE SELECT date\_trunc('month', a), date\_trunc('day', a) FROM t3 GROUP BY 1, 2; -- build ndistinct statistics on the pair of expressions (per-expression -- statistics are built automatically) CREATE STATISTICS s3 (ndistinct) ON date\_trunc('month', a), date\_trunc('day', a) FROM t3; ANALYZE t3; -- now the row count estimates are more accurate: EXPLAIN ANALYZE SELECT \* FROM t3 WHERE date\_trunc('month', a) = '2020-01-01'::timestamp; EXPLAIN ANALYZE SELECT \* FROM t3 WHERE date\_trunc('day', a) BETWEEN '2020-01-01'::timestamp AND '2020-06-30'::timestamp; EXPLAIN ANALYZE SELECT date\_trunc('month', a), date\_trunc('day', a) FROM t3 GROUP BY 1, 2; Without expression and ndistinct statistics, the planner has no information about the number of distinct values for the expressions, and has to rely on default estimates. The equality and range conditions are assumed to have 0.5% selectivity, and the number of distinct values in the expression is assumed to be the same as for the column (i.e. unique). This results in a significant underestimate of the row count in the first two queries. Moreover, the planner has no information about the relationship between the expressions, so it assumes the two `WHERE` and `GROUP BY` conditions are independent, and multiplies their selectivities together to arrive at a severe overestimate of the group count in the aggregate query. This is further exacerbated by the lack of accurate statistics for the expressions, forcing the planner to use a default ndistinct estimate for the expression derived from ndistinct for the column. With such statistics, the planner recognizes that the conditions are correlated, and arrives at much more accurate estimates. Compatibility ------------- There is no `CREATE STATISTICS` command in the SQL standard. See Also -------- [ALTER STATISTICS](https://www.postgresql.org/docs/current/sql-alterstatistics.html "ALTER STATISTICS") , [DROP STATISTICS](https://www.postgresql.org/docs/current/sql-dropstatistics.html "DROP STATISTICS") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createserver.html "CREATE SERVER") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-createsubscription.html "CREATE SUBSCRIPTION") | | CREATE SERVER | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | CREATE SUBSCRIPTION | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createstatistics.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: ALTER INDEX November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alterindex.html "PostgreSQL 18 - ALTER INDEX") ([18](https://www.postgresql.org/docs/18/sql-alterindex.html "PostgreSQL 18 - ALTER INDEX") ) / [17](https://www.postgresql.org/docs/17/sql-alterindex.html "PostgreSQL 17 - ALTER INDEX") / [16](https://www.postgresql.org/docs/16/sql-alterindex.html "PostgreSQL 16 - ALTER INDEX") / [15](https://www.postgresql.org/docs/15/sql-alterindex.html "PostgreSQL 15 - ALTER INDEX") / [14](https://www.postgresql.org/docs/14/sql-alterindex.html "PostgreSQL 14 - ALTER INDEX") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alterindex.html "PostgreSQL devel - ALTER INDEX") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alterindex.html "PostgreSQL 13 - ALTER INDEX") / [12](https://www.postgresql.org/docs/12/sql-alterindex.html "PostgreSQL 12 - ALTER INDEX") / [11](https://www.postgresql.org/docs/11/sql-alterindex.html "PostgreSQL 11 - ALTER INDEX") / [10](https://www.postgresql.org/docs/10/sql-alterindex.html "PostgreSQL 10 - ALTER INDEX") / [9.6](https://www.postgresql.org/docs/9.6/sql-alterindex.html "PostgreSQL 9.6 - ALTER INDEX") / [9.5](https://www.postgresql.org/docs/9.5/sql-alterindex.html "PostgreSQL 9.5 - ALTER INDEX") / [9.4](https://www.postgresql.org/docs/9.4/sql-alterindex.html "PostgreSQL 9.4 - ALTER INDEX") / [9.3](https://www.postgresql.org/docs/9.3/sql-alterindex.html "PostgreSQL 9.3 - ALTER INDEX") / [9.2](https://www.postgresql.org/docs/9.2/sql-alterindex.html "PostgreSQL 9.2 - ALTER INDEX") / [9.1](https://www.postgresql.org/docs/9.1/sql-alterindex.html "PostgreSQL 9.1 - ALTER INDEX") / [9.0](https://www.postgresql.org/docs/9.0/sql-alterindex.html "PostgreSQL 9.0 - ALTER INDEX") / [8.4](https://www.postgresql.org/docs/8.4/sql-alterindex.html "PostgreSQL 8.4 - ALTER INDEX") / [8.3](https://www.postgresql.org/docs/8.3/sql-alterindex.html "PostgreSQL 8.3 - ALTER INDEX") / [8.2](https://www.postgresql.org/docs/8.2/sql-alterindex.html "PostgreSQL 8.2 - ALTER INDEX") / [8.1](https://www.postgresql.org/docs/8.1/sql-alterindex.html "PostgreSQL 8.1 - ALTER INDEX") / [8.0](https://www.postgresql.org/docs/8.0/sql-alterindex.html "PostgreSQL 8.0 - ALTER INDEX") | ALTER INDEX | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-altergroup.html "ALTER GROUP") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-alterlanguage.html "ALTER LANGUAGE") | * * * ALTER INDEX ----------- ALTER INDEX — change the definition of an index Synopsis -------- ALTER INDEX \[ IF EXISTS \] _`name`_ RENAME TO _`new_name`_ ALTER INDEX \[ IF EXISTS \] _`name`_ SET TABLESPACE _`tablespace_name`_ ALTER INDEX _`name`_ ATTACH PARTITION _`index_name`_ ALTER INDEX _`name`_ \[ NO \] DEPENDS ON EXTENSION _`extension_name`_ ALTER INDEX \[ IF EXISTS \] _`name`_ SET ( _`storage_parameter`_ \[= _`value`_\] \[, ... \] ) ALTER INDEX \[ IF EXISTS \] _`name`_ RESET ( _`storage_parameter`_ \[, ... \] ) ALTER INDEX \[ IF EXISTS \] _`name`_ ALTER \[ COLUMN \] _`column_number`_ SET STATISTICS _`integer`_ ALTER INDEX ALL IN TABLESPACE _`name`_ \[ OWNED BY _`role_name`_ \[, ... \] \] SET TABLESPACE _`new_tablespace`_ \[ NOWAIT \] Description ----------- `ALTER INDEX` changes the definition of an existing index. There are several subforms described below. Note that the lock level required may differ for each subform. An `ACCESS EXCLUSIVE` lock is held unless explicitly noted. When multiple subcommands are listed, the lock held will be the strictest one required from any subcommand. `RENAME` The `RENAME` form changes the name of the index. If the index is associated with a table constraint (either `UNIQUE`, `PRIMARY KEY`, or `EXCLUDE`), the constraint is renamed as well. There is no effect on the stored data. Renaming an index acquires a `SHARE UPDATE EXCLUSIVE` lock. `SET TABLESPACE` This form changes the index's tablespace to the specified tablespace and moves the data file(s) associated with the index to the new tablespace. To change the tablespace of an index, you must own the index and have `CREATE` privilege on the new tablespace. All indexes in the current database in a tablespace can be moved by using the `ALL IN TABLESPACE` form, which will lock all indexes to be moved and then move each one. This form also supports `OWNED BY`, which will only move indexes owned by the roles specified. If the `NOWAIT` option is specified then the command will fail if it is unable to acquire all of the locks required immediately. Note that system catalogs will not be moved by this command, use `ALTER DATABASE` or explicit `ALTER INDEX` invocations instead if desired. See also [`CREATE TABLESPACE`](https://www.postgresql.org/docs/current/sql-createtablespace.html "CREATE TABLESPACE") . ``ATTACH PARTITION _`index_name`_`` Causes the named index (possibly schema-qualified) to become attached to the altered index. The named index must be on a partition of the table containing the index being altered, and have an equivalent definition. An attached index cannot be dropped by itself, and will automatically be dropped if its parent index is dropped. ``DEPENDS ON EXTENSION _`extension_name`_`` ``NO DEPENDS ON EXTENSION _`extension_name`_`` This form marks the index as dependent on the extension, or no longer dependent on that extension if `NO` is specified. An index that's marked as dependent on an extension is automatically dropped when the extension is dropped. ``SET ( _`storage_parameter`_ [= _`value`_] [, ... ] )`` This form changes one or more index-method-specific storage parameters for the index. See [`CREATE INDEX`](https://www.postgresql.org/docs/current/sql-createindex.html "CREATE INDEX") for details on the available parameters. Note that the index contents will not be modified immediately by this command; depending on the parameter you might need to rebuild the index with [`REINDEX`](https://www.postgresql.org/docs/current/sql-reindex.html "REINDEX") to get the desired effects. ``RESET ( _`storage_parameter`_ [, ... ] )`` This form resets one or more index-method-specific storage parameters to their defaults. As with `SET`, a `REINDEX` might be needed to update the index entirely. ``ALTER [ COLUMN ] _`column_number`_ SET STATISTICS _`integer`_`` This form sets the per-column statistics-gathering target for subsequent [`ANALYZE`](https://www.postgresql.org/docs/current/sql-analyze.html "ANALYZE") operations, though can be used only on index columns that are defined as an expression. Since expressions lack a unique name, we refer to them using the ordinal number of the index column. The target can be set in the range 0 to 10000; alternatively, set it to -1 to revert to using the system default statistics target ([default\_statistics\_target](https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-DEFAULT-STATISTICS-TARGET) ). For more information on the use of statistics by the PostgreSQL query planner, refer to [Section 14.2](https://www.postgresql.org/docs/current/planner-stats.html "14.2. Statistics Used by the Planner") . Parameters ---------- `IF EXISTS` Do not throw an error if the index does not exist. A notice is issued in this case. _`column_number`_ The ordinal number refers to the ordinal (left-to-right) position of the index column. _`name`_ The name (possibly schema-qualified) of an existing index to alter. _`new_name`_ The new name for the index. _`tablespace_name`_ The tablespace to which the index will be moved. _`extension_name`_ The name of the extension that the index is to depend on. _`storage_parameter`_ The name of an index-method-specific storage parameter. _`value`_ The new value for an index-method-specific storage parameter. This might be a number or a word depending on the parameter. Notes ----- These operations are also possible using [`ALTER TABLE`](https://www.postgresql.org/docs/current/sql-altertable.html "ALTER TABLE") . `ALTER INDEX` is in fact just an alias for the forms of `ALTER TABLE` that apply to indexes. There was formerly an `ALTER INDEX OWNER` variant, but this is now ignored (with a warning). An index cannot have an owner different from its table's owner. Changing the table's owner automatically changes the index as well. Changing any part of a system catalog index is not permitted. Examples -------- To rename an existing index: ALTER INDEX distributors RENAME TO suppliers; To move an index to a different tablespace: ALTER INDEX distributors SET TABLESPACE fasttablespace; To change an index's fill factor (assuming that the index method supports it): ALTER INDEX distributors SET (fillfactor = 75); REINDEX INDEX distributors; Set the statistics-gathering target for an expression index: CREATE INDEX coord\_idx ON measured (x, y, (z + t)); ALTER INDEX coord\_idx ALTER COLUMN 3 SET STATISTICS 1000; Compatibility ------------- `ALTER INDEX` is a PostgreSQL extension. See Also -------- [CREATE INDEX](https://www.postgresql.org/docs/current/sql-createindex.html "CREATE INDEX") , [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html "REINDEX") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-altergroup.html "ALTER GROUP") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-alterlanguage.html "ALTER LANGUAGE") | | ALTER GROUP | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | ALTER LANGUAGE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-alterindex.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 53.19. pg_replication_origin_status November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-replication-origin-status.html "PostgreSQL 18 - 53.19. pg_replication_origin_status") ([18](https://www.postgresql.org/docs/18/view-pg-replication-origin-status.html "PostgreSQL 18 - 53.19. pg_replication_origin_status") ) / [17](https://www.postgresql.org/docs/17/view-pg-replication-origin-status.html "PostgreSQL 17 - 53.19. pg_replication_origin_status") / [16](https://www.postgresql.org/docs/16/view-pg-replication-origin-status.html "PostgreSQL 16 - 53.19. pg_replication_origin_status") / [15](https://www.postgresql.org/docs/15/view-pg-replication-origin-status.html "PostgreSQL 15 - 53.19. pg_replication_origin_status") / [14](https://www.postgresql.org/docs/14/view-pg-replication-origin-status.html "PostgreSQL 14 - 53.19. pg_replication_origin_status") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-replication-origin-status.html "PostgreSQL devel - 53.19. pg_replication_origin_status") Unsupported versions: [13](https://www.postgresql.org/docs/13/view-pg-replication-origin-status.html "PostgreSQL 13 - 53.19. pg_replication_origin_status") / [12](https://www.postgresql.org/docs/12/view-pg-replication-origin-status.html "PostgreSQL 12 - 53.19. pg_replication_origin_status") / [11](https://www.postgresql.org/docs/11/view-pg-replication-origin-status.html "PostgreSQL 11 - 53.19. pg_replication_origin_status") / [10](https://www.postgresql.org/docs/10/view-pg-replication-origin-status.html "PostgreSQL 10 - 53.19. pg_replication_origin_status") / [9.6](https://www.postgresql.org/docs/9.6/view-pg-replication-origin-status.html "PostgreSQL 9.6 - 53.19. pg_replication_origin_status") / [9.5](https://www.postgresql.org/docs/9.5/view-pg-replication-origin-status.html "PostgreSQL 9.5 - 53.19. pg_replication_origin_status") | 53.19. `pg_replication_origin_status` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-publication-tables.html "53.18. pg_publication_tables") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/view-pg-replication-slots.html "53.20. pg_replication_slots") | * * * 53.19. `pg_replication_origin_status` [#](https://www.postgresql.org/docs/18/view-pg-replication-origin-status.html#VIEW-PG-REPLICATION-ORIGIN-STATUS) ------------------------------------------------------------------------------------------------------------------------------------------------------- The `pg_replication_origin_status` view contains information about how far replay for a certain origin has progressed. For more on replication origins see [Chapter 48](https://www.postgresql.org/docs/18/replication-origins.html "Chapter 48. Replication Progress Tracking") . **Table 53.19. `pg_replication_origin_status` Columns** | Column Type

Description | | --- | | `local_id` `oid` (references [`pg_replication_origin`](https://www.postgresql.org/docs/18/catalog-pg-replication-origin.html "52.44. pg_replication_origin")
.`roident`)

internal node identifier | | `external_id` `text` (references [`pg_replication_origin`](https://www.postgresql.org/docs/18/catalog-pg-replication-origin.html "52.44. pg_replication_origin")
.`roname`)

external node identifier | | `remote_lsn` `pg_lsn`

The origin node's LSN up to which data has been replicated. | | `local_lsn` `pg_lsn`

This node's LSN at which `remote_lsn` has been replicated. Used to flush commit records before persisting data to disk when using asynchronous commits. | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/view-pg-publication-tables.html "53.18. pg_publication_tables") | [Up](https://www.postgresql.org/docs/18/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/18/view-pg-replication-slots.html "53.20. pg_replication_slots") | | 53.18. `pg_publication_tables` | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 53.20. `pg_replication_slots` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-replication-origin-status.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 13. Concurrency Control November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/mvcc.html "PostgreSQL 18 - Chapter 13. Concurrency Control") ([18](https://www.postgresql.org/docs/18/mvcc.html "PostgreSQL 18 - Chapter 13. Concurrency Control") ) / [17](https://www.postgresql.org/docs/17/mvcc.html "PostgreSQL 17 - Chapter 13. Concurrency Control") / [16](https://www.postgresql.org/docs/16/mvcc.html "PostgreSQL 16 - Chapter 13. Concurrency Control") / [15](https://www.postgresql.org/docs/15/mvcc.html "PostgreSQL 15 - Chapter 13. Concurrency Control") / [14](https://www.postgresql.org/docs/14/mvcc.html "PostgreSQL 14 - Chapter 13. Concurrency Control") Development Versions: [devel](https://www.postgresql.org/docs/devel/mvcc.html "PostgreSQL devel - Chapter 13. Concurrency Control") Unsupported versions: [13](https://www.postgresql.org/docs/13/mvcc.html "PostgreSQL 13 - Chapter 13. Concurrency Control") / [12](https://www.postgresql.org/docs/12/mvcc.html "PostgreSQL 12 - Chapter 13. Concurrency Control") / [11](https://www.postgresql.org/docs/11/mvcc.html "PostgreSQL 11 - Chapter 13. Concurrency Control") / [10](https://www.postgresql.org/docs/10/mvcc.html "PostgreSQL 10 - Chapter 13. Concurrency Control") / [9.6](https://www.postgresql.org/docs/9.6/mvcc.html "PostgreSQL 9.6 - Chapter 13. Concurrency Control") / [9.5](https://www.postgresql.org/docs/9.5/mvcc.html "PostgreSQL 9.5 - Chapter 13. Concurrency Control") / [9.4](https://www.postgresql.org/docs/9.4/mvcc.html "PostgreSQL 9.4 - Chapter 13. Concurrency Control") / [9.3](https://www.postgresql.org/docs/9.3/mvcc.html "PostgreSQL 9.3 - Chapter 13. Concurrency Control") / [9.2](https://www.postgresql.org/docs/9.2/mvcc.html "PostgreSQL 9.2 - Chapter 13. Concurrency Control") / [9.1](https://www.postgresql.org/docs/9.1/mvcc.html "PostgreSQL 9.1 - Chapter 13. Concurrency Control") / [9.0](https://www.postgresql.org/docs/9.0/mvcc.html "PostgreSQL 9.0 - Chapter 13. Concurrency Control") / [8.4](https://www.postgresql.org/docs/8.4/mvcc.html "PostgreSQL 8.4 - Chapter 13. Concurrency Control") / [8.3](https://www.postgresql.org/docs/8.3/mvcc.html "PostgreSQL 8.3 - Chapter 13. Concurrency Control") / [8.2](https://www.postgresql.org/docs/8.2/mvcc.html "PostgreSQL 8.2 - Chapter 13. Concurrency Control") / [8.1](https://www.postgresql.org/docs/8.1/mvcc.html "PostgreSQL 8.1 - Chapter 13. Concurrency Control") / [8.0](https://www.postgresql.org/docs/8.0/mvcc.html "PostgreSQL 8.0 - Chapter 13. Concurrency Control") / [7.4](https://www.postgresql.org/docs/7.4/mvcc.html "PostgreSQL 7.4 - Chapter 13. Concurrency Control") / [7.3](https://www.postgresql.org/docs/7.3/mvcc.html "PostgreSQL 7.3 - Chapter 13. Concurrency Control") / [7.2](https://www.postgresql.org/docs/7.2/mvcc.html "PostgreSQL 7.2 - Chapter 13. Concurrency Control") / [7.1](https://www.postgresql.org/docs/7.1/mvcc.html "PostgreSQL 7.1 - Chapter 13. Concurrency Control") | Chapter 13. Concurrency Control | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/textsearch-limitations.html "12.11. Limitations") | [Up](https://www.postgresql.org/docs/current/sql.html "Part II. The SQL Language") | Part II. The SQL Language | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/mvcc-intro.html "13.1. Introduction") | * * * Chapter 13. Concurrency Control ------------------------------- **Table of Contents** [13.1. Introduction](https://www.postgresql.org/docs/current/mvcc-intro.html) [13.2. Transaction Isolation](https://www.postgresql.org/docs/current/transaction-iso.html) [13.2.1. Read Committed Isolation Level](https://www.postgresql.org/docs/current/transaction-iso.html#XACT-READ-COMMITTED) [13.2.2. Repeatable Read Isolation Level](https://www.postgresql.org/docs/current/transaction-iso.html#XACT-REPEATABLE-READ) [13.2.3. Serializable Isolation Level](https://www.postgresql.org/docs/current/transaction-iso.html#XACT-SERIALIZABLE) [13.3. Explicit Locking](https://www.postgresql.org/docs/current/explicit-locking.html) [13.3.1. Table-Level Locks](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-TABLES) [13.3.2. Row-Level Locks](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS) [13.3.3. Page-Level Locks](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-PAGES) [13.3.4. Deadlocks](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-DEADLOCKS) [13.3.5. Advisory Locks](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS) [13.4. Data Consistency Checks at the Application Level](https://www.postgresql.org/docs/current/applevel-consistency.html) [13.4.1. Enforcing Consistency with Serializable Transactions](https://www.postgresql.org/docs/current/applevel-consistency.html#SERIALIZABLE-CONSISTENCY) [13.4.2. Enforcing Consistency with Explicit Blocking Locks](https://www.postgresql.org/docs/current/applevel-consistency.html#NON-SERIALIZABLE-CONSISTENCY) [13.5. Serialization Failure Handling](https://www.postgresql.org/docs/current/mvcc-serialization-failure-handling.html) [13.6. Caveats](https://www.postgresql.org/docs/current/mvcc-caveats.html) [13.7. Locking and Indexes](https://www.postgresql.org/docs/current/locking-indexes.html) This chapter describes the behavior of the PostgreSQL database system when two or more sessions try to access the same data at the same time. The goals in that situation are to allow efficient access for all sessions while maintaining strict data integrity. Every developer of database applications should be familiar with the topics covered in this chapter. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/textsearch-limitations.html "12.11. Limitations") | [Up](https://www.postgresql.org/docs/current/sql.html "Part II. The SQL Language") | [Next](https://www.postgresql.org/docs/current/mvcc-intro.html "13.1. Introduction") | | 12.11. Limitations | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 13.1. Introduction | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/mvcc.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: ALTER OPERATOR November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alteroperator.html "PostgreSQL 18 - ALTER OPERATOR") ([18](https://www.postgresql.org/docs/18/sql-alteroperator.html "PostgreSQL 18 - ALTER OPERATOR") ) / [17](https://www.postgresql.org/docs/17/sql-alteroperator.html "PostgreSQL 17 - ALTER OPERATOR") / [16](https://www.postgresql.org/docs/16/sql-alteroperator.html "PostgreSQL 16 - ALTER OPERATOR") / [15](https://www.postgresql.org/docs/15/sql-alteroperator.html "PostgreSQL 15 - ALTER OPERATOR") / [14](https://www.postgresql.org/docs/14/sql-alteroperator.html "PostgreSQL 14 - ALTER OPERATOR") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alteroperator.html "PostgreSQL devel - ALTER OPERATOR") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alteroperator.html "PostgreSQL 13 - ALTER OPERATOR") / [12](https://www.postgresql.org/docs/12/sql-alteroperator.html "PostgreSQL 12 - ALTER OPERATOR") / [11](https://www.postgresql.org/docs/11/sql-alteroperator.html "PostgreSQL 11 - ALTER OPERATOR") / [10](https://www.postgresql.org/docs/10/sql-alteroperator.html "PostgreSQL 10 - ALTER OPERATOR") / [9.6](https://www.postgresql.org/docs/9.6/sql-alteroperator.html "PostgreSQL 9.6 - ALTER OPERATOR") / [9.5](https://www.postgresql.org/docs/9.5/sql-alteroperator.html "PostgreSQL 9.5 - ALTER OPERATOR") / [9.4](https://www.postgresql.org/docs/9.4/sql-alteroperator.html "PostgreSQL 9.4 - ALTER OPERATOR") / [9.3](https://www.postgresql.org/docs/9.3/sql-alteroperator.html "PostgreSQL 9.3 - ALTER OPERATOR") / [9.2](https://www.postgresql.org/docs/9.2/sql-alteroperator.html "PostgreSQL 9.2 - ALTER OPERATOR") / [9.1](https://www.postgresql.org/docs/9.1/sql-alteroperator.html "PostgreSQL 9.1 - ALTER OPERATOR") / [9.0](https://www.postgresql.org/docs/9.0/sql-alteroperator.html "PostgreSQL 9.0 - ALTER OPERATOR") / [8.4](https://www.postgresql.org/docs/8.4/sql-alteroperator.html "PostgreSQL 8.4 - ALTER OPERATOR") / [8.3](https://www.postgresql.org/docs/8.3/sql-alteroperator.html "PostgreSQL 8.3 - ALTER OPERATOR") / [8.2](https://www.postgresql.org/docs/8.2/sql-alteroperator.html "PostgreSQL 8.2 - ALTER OPERATOR") / [8.1](https://www.postgresql.org/docs/8.1/sql-alteroperator.html "PostgreSQL 8.1 - ALTER OPERATOR") / [8.0](https://www.postgresql.org/docs/8.0/sql-alteroperator.html "PostgreSQL 8.0 - ALTER OPERATOR") | ALTER OPERATOR | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-altermaterializedview.html "ALTER MATERIALIZED VIEW") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-alteropclass.html "ALTER OPERATOR CLASS") | * * * ALTER OPERATOR -------------- ALTER OPERATOR — change the definition of an operator Synopsis -------- ALTER OPERATOR _`name`_ ( { _`left_type`_ | NONE } , _`right_type`_ ) OWNER TO { _`new_owner`_ | CURRENT\_ROLE | CURRENT\_USER | SESSION\_USER } ALTER OPERATOR _`name`_ ( { _`left_type`_ | NONE } , _`right_type`_ ) SET SCHEMA _`new_schema`_ ALTER OPERATOR _`name`_ ( { _`left_type`_ | NONE } , _`right_type`_ ) SET ( { RESTRICT = { _`res_proc`_ | NONE } | JOIN = { _`join_proc`_ | NONE } | COMMUTATOR = _`com_op`_ | NEGATOR = _`neg_op`_ | HASHES | MERGES } \[, ... \] ) Description ----------- `ALTER OPERATOR` changes the definition of an operator. You must own the operator to use `ALTER OPERATOR`. To alter the owner, you must be able to `SET ROLE` to the new owning role, and that role must have `CREATE` privilege on the operator's schema. (These restrictions enforce that altering the owner doesn't do anything you couldn't do by dropping and recreating the operator. However, a superuser can alter ownership of any operator anyway.) Parameters ---------- _`name`_ The name (optionally schema-qualified) of an existing operator. _`left_type`_ The data type of the operator's left operand; write `NONE` if the operator has no left operand. _`right_type`_ The data type of the operator's right operand. _`new_owner`_ The new owner of the operator. _`new_schema`_ The new schema for the operator. _`res_proc`_ The restriction selectivity estimator function for this operator; write NONE to remove existing selectivity estimator. _`join_proc`_ The join selectivity estimator function for this operator; write NONE to remove existing selectivity estimator. _`com_op`_ The commutator of this operator. Can only be changed if the operator does not have an existing commutator. _`neg_op`_ The negator of this operator. Can only be changed if the operator does not have an existing negator. `HASHES` Indicates this operator can support a hash join. Can only be enabled and not disabled. `MERGES` Indicates this operator can support a merge join. Can only be enabled and not disabled. Notes ----- Refer to [Section 36.14](https://www.postgresql.org/docs/current/xoper.html "36.14. User-Defined Operators") and [Section 36.15](https://www.postgresql.org/docs/current/xoper-optimization.html "36.15. Operator Optimization Information") for further information. Since commutators come in pairs that are commutators of each other, `ALTER OPERATOR SET COMMUTATOR` will also set the commutator of the _`com_op`_ to be the target operator. Likewise, `ALTER OPERATOR SET NEGATOR` will also set the negator of the _`neg_op`_ to be the target operator. Therefore, you must own the commutator or negator operator as well as the target operator. Examples -------- Change the owner of a custom operator `a @@ b` for type `text`: ALTER OPERATOR @@ (text, text) OWNER TO joe; Change the restriction and join selectivity estimator functions of a custom operator `a && b` for type `int[]`: ALTER OPERATOR && (int\[\], int\[\]) SET (RESTRICT = \_int\_contsel, JOIN = \_int\_contjoinsel); Mark the `&&` operator as being its own commutator: ALTER OPERATOR && (int\[\], int\[\]) SET (COMMUTATOR = &&); Compatibility ------------- There is no `ALTER OPERATOR` statement in the SQL standard. See Also -------- [CREATE OPERATOR](https://www.postgresql.org/docs/current/sql-createoperator.html "CREATE OPERATOR") , [DROP OPERATOR](https://www.postgresql.org/docs/current/sql-dropoperator.html "DROP OPERATOR") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-altermaterializedview.html "ALTER MATERIALIZED VIEW") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-alteropclass.html "ALTER OPERATOR CLASS") | | ALTER MATERIALIZED VIEW | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | ALTER OPERATOR CLASS | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-alteroperator.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 9.3: column_options November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 9.3](https://www.postgresql.org/docs/9.3/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-column-options.html "PostgreSQL 18 - column_options") ([18](https://www.postgresql.org/docs/18/infoschema-column-options.html "PostgreSQL 18 - column_options") ) / [17](https://www.postgresql.org/docs/17/infoschema-column-options.html "PostgreSQL 17 - column_options") / [16](https://www.postgresql.org/docs/16/infoschema-column-options.html "PostgreSQL 16 - column_options") / [15](https://www.postgresql.org/docs/15/infoschema-column-options.html "PostgreSQL 15 - column_options") / [14](https://www.postgresql.org/docs/14/infoschema-column-options.html "PostgreSQL 14 - column_options") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-column-options.html "PostgreSQL devel - column_options") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-column-options.html "PostgreSQL 13 - column_options") / [12](https://www.postgresql.org/docs/12/infoschema-column-options.html "PostgreSQL 12 - column_options") / [11](https://www.postgresql.org/docs/11/infoschema-column-options.html "PostgreSQL 11 - column_options") / [10](https://www.postgresql.org/docs/10/infoschema-column-options.html "PostgreSQL 10 - column_options") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-column-options.html "PostgreSQL 9.6 - column_options") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-column-options.html "PostgreSQL 9.5 - column_options") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-column-options.html "PostgreSQL 9.4 - column_options") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-column-options.html "PostgreSQL 9.3 - column_options") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-column-options.html "PostgreSQL 9.2 - column_options") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/infoschema-column-options.html "PostgreSQL - column_options") version, or one of the other supported versions listed above instead. | [PostgreSQL 9.3.25 Documentation](https://www.postgresql.org/docs/9.3/index.html) | | | | | | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/infoschema-column-domain-usage.html "column_domain_usage") | [Up](https://www.postgresql.org/docs/9.3/information-schema.html) | Chapter 34. The Information Schema | [Next](https://www.postgresql.org/docs/9.3/infoschema-column-privileges.html "column_privileges") | * * * 34.13. column\_options ====================== The view column\_options contains all the options defined for foreign table columns in the current database. Only those foreign table columns are shown that the current user has access to (by way of being the owner or having some privilege). **Table 34-11. column\_options Columns** | Name | Data Type | Description | | --- | --- | --- | | table\_catalog | sql\_identifier | Name of the database that contains the foreign table (always the current database) | | table\_schema | sql\_identifier | Name of the schema that contains the foreign table | | table\_name | sql\_identifier | Name of the foreign table | | column\_name | sql\_identifier | Name of the column | | option\_name | sql\_identifier | Name of an option | | option\_value | character\_data | Value of the option | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/infoschema-column-domain-usage.html) | [Home](https://www.postgresql.org/docs/9.3/index.html) | [Next](https://www.postgresql.org/docs/9.3/infoschema-column-privileges.html) | | column\_domain\_usage | [Up](https://www.postgresql.org/docs/9.3/information-schema.html) | column\_privileges | --- # PostgreSQL: Documentation: 18: 8.8. Geometric Types November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/datatype-geometric.html "PostgreSQL 18 - 8.8. Geometric Types") ([18](https://www.postgresql.org/docs/18/datatype-geometric.html "PostgreSQL 18 - 8.8. Geometric Types") ) / [17](https://www.postgresql.org/docs/17/datatype-geometric.html "PostgreSQL 17 - 8.8. Geometric Types") / [16](https://www.postgresql.org/docs/16/datatype-geometric.html "PostgreSQL 16 - 8.8. Geometric Types") / [15](https://www.postgresql.org/docs/15/datatype-geometric.html "PostgreSQL 15 - 8.8. Geometric Types") / [14](https://www.postgresql.org/docs/14/datatype-geometric.html "PostgreSQL 14 - 8.8. Geometric Types") Development Versions: [devel](https://www.postgresql.org/docs/devel/datatype-geometric.html "PostgreSQL devel - 8.8. Geometric Types") Unsupported versions: [13](https://www.postgresql.org/docs/13/datatype-geometric.html "PostgreSQL 13 - 8.8. Geometric Types") / [12](https://www.postgresql.org/docs/12/datatype-geometric.html "PostgreSQL 12 - 8.8. Geometric Types") / [11](https://www.postgresql.org/docs/11/datatype-geometric.html "PostgreSQL 11 - 8.8. Geometric Types") / [10](https://www.postgresql.org/docs/10/datatype-geometric.html "PostgreSQL 10 - 8.8. Geometric Types") / [9.6](https://www.postgresql.org/docs/9.6/datatype-geometric.html "PostgreSQL 9.6 - 8.8. Geometric Types") / [9.5](https://www.postgresql.org/docs/9.5/datatype-geometric.html "PostgreSQL 9.5 - 8.8. Geometric Types") / [9.4](https://www.postgresql.org/docs/9.4/datatype-geometric.html "PostgreSQL 9.4 - 8.8. Geometric Types") / [9.3](https://www.postgresql.org/docs/9.3/datatype-geometric.html "PostgreSQL 9.3 - 8.8. Geometric Types") / [9.2](https://www.postgresql.org/docs/9.2/datatype-geometric.html "PostgreSQL 9.2 - 8.8. Geometric Types") / [9.1](https://www.postgresql.org/docs/9.1/datatype-geometric.html "PostgreSQL 9.1 - 8.8. Geometric Types") / [9.0](https://www.postgresql.org/docs/9.0/datatype-geometric.html "PostgreSQL 9.0 - 8.8. Geometric Types") / [8.4](https://www.postgresql.org/docs/8.4/datatype-geometric.html "PostgreSQL 8.4 - 8.8. Geometric Types") / [8.3](https://www.postgresql.org/docs/8.3/datatype-geometric.html "PostgreSQL 8.3 - 8.8. Geometric Types") / [8.2](https://www.postgresql.org/docs/8.2/datatype-geometric.html "PostgreSQL 8.2 - 8.8. Geometric Types") / [8.1](https://www.postgresql.org/docs/8.1/datatype-geometric.html "PostgreSQL 8.1 - 8.8. Geometric Types") / [8.0](https://www.postgresql.org/docs/8.0/datatype-geometric.html "PostgreSQL 8.0 - 8.8. Geometric Types") / [7.4](https://www.postgresql.org/docs/7.4/datatype-geometric.html "PostgreSQL 7.4 - 8.8. Geometric Types") / [7.3](https://www.postgresql.org/docs/7.3/datatype-geometric.html "PostgreSQL 7.3 - 8.8. Geometric Types") / [7.2](https://www.postgresql.org/docs/7.2/datatype-geometric.html "PostgreSQL 7.2 - 8.8. Geometric Types") / [7.1](https://www.postgresql.org/docs/7.1/datatype-geometric.html "PostgreSQL 7.1 - 8.8. Geometric Types") | 8.8. Geometric Types | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/datatype-enum.html "8.7. Enumerated Types") | [Up](https://www.postgresql.org/docs/current/datatype.html "Chapter 8. Data Types") | Chapter 8. Data Types | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/datatype-net-types.html "8.9. Network Address Types") | * * * 8.8. Geometric Types [#](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-GEOMETRIC) ------------------------------------------------------------------------------------------------------------- [8.8.1. Points](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-GEOMETRIC-POINTS) [8.8.2. Lines](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-LINE) [8.8.3. Line Segments](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-LSEG) [8.8.4. Boxes](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-GEOMETRIC-BOXES) [8.8.5. Paths](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-GEOMETRIC-PATHS) [8.8.6. Polygons](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-POLYGON) [8.8.7. Circles](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-CIRCLE) Geometric data types represent two-dimensional spatial objects. [Table 8.20](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-GEO-TABLE "Table 8.20. Geometric Types") shows the geometric types available in PostgreSQL. **Table 8.20. Geometric Types** | Name | Storage Size | Description | Representation | | --- | --- | --- | --- | | `point` | 16 bytes | Point on a plane | (x,y) | | `line` | 24 bytes | Infinite line | {A,B,C} | | `lseg` | 32 bytes | Finite line segment | \[(x1,y1),(x2,y2)\] | | `box` | 32 bytes | Rectangular box | (x1,y1),(x2,y2) | | `path` | 16+16n bytes | Closed path (similar to polygon) | ((x1,y1),...) | | `path` | 16+16n bytes | Open path | \[(x1,y1),...\] | | `polygon` | 40+16n bytes | Polygon (similar to closed path) | ((x1,y1),...) | | `circle` | 24 bytes | Circle | <(x,y),r> (center point and radius) | In all these types, the individual coordinates are stored as `double precision` (`float8`) numbers. A rich set of functions and operators is available to perform various geometric operations such as scaling, translation, rotation, and determining intersections. They are explained in [Section 9.11](https://www.postgresql.org/docs/current/functions-geometry.html "9.11. Geometric Functions and Operators") . ### 8.8.1. Points [#](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-GEOMETRIC-POINTS) Points are the fundamental two-dimensional building block for geometric types. Values of type `point` are specified using either of the following syntaxes: ( _`x`_ , _`y`_ ) _`x`_ , _`y`_ where _`x`_ and _`y`_ are the respective coordinates, as floating-point numbers. Points are output using the first syntax. ### 8.8.2. Lines [#](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-LINE) Lines are represented by the linear equation _`A`_x + _`B`_y + _`C`_ = 0, where _`A`_ and _`B`_ are not both zero. Values of type `line` are input and output in the following form: { _`A`_, _`B`_, _`C`_ } Alternatively, any of the following forms can be used for input: \[ ( _`x1`_ , _`y1`_ ) , ( _`x2`_ , _`y2`_ ) \] ( ( _`x1`_ , _`y1`_ ) , ( _`x2`_ , _`y2`_ ) ) ( _`x1`_ , _`y1`_ ) , ( _`x2`_ , _`y2`_ ) _`x1`_ , _`y1`_ , _`x2`_ , _`y2`_ where ``(_`x1`_,_`y1`_)`` and ``(_`x2`_,_`y2`_)`` are two different points on the line. ### 8.8.3. Line Segments [#](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-LSEG) Line segments are represented by pairs of points that are the endpoints of the segment. Values of type `lseg` are specified using any of the following syntaxes: \[ ( _`x1`_ , _`y1`_ ) , ( _`x2`_ , _`y2`_ ) \] ( ( _`x1`_ , _`y1`_ ) , ( _`x2`_ , _`y2`_ ) ) ( _`x1`_ , _`y1`_ ) , ( _`x2`_ , _`y2`_ ) _`x1`_ , _`y1`_ , _`x2`_ , _`y2`_ where ``(_`x1`_,_`y1`_)`` and ``(_`x2`_,_`y2`_)`` are the end points of the line segment. Line segments are output using the first syntax. ### 8.8.4. Boxes [#](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-GEOMETRIC-BOXES) Boxes are represented by pairs of points that are opposite corners of the box. Values of type `box` are specified using any of the following syntaxes: ( ( _`x1`_ , _`y1`_ ) , ( _`x2`_ , _`y2`_ ) ) ( _`x1`_ , _`y1`_ ) , ( _`x2`_ , _`y2`_ ) _`x1`_ , _`y1`_ , _`x2`_ , _`y2`_ where ``(_`x1`_,_`y1`_)`` and ``(_`x2`_,_`y2`_)`` are any two opposite corners of the box. Boxes are output using the second syntax. Any two opposite corners can be supplied on input, but the values will be reordered as needed to store the upper right and lower left corners, in that order. ### 8.8.5. Paths [#](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-GEOMETRIC-PATHS) Paths are represented by lists of connected points. Paths can be _open_, where the first and last points in the list are considered not connected, or _closed_, where the first and last points are considered connected. Values of type `path` are specified using any of the following syntaxes: \[ ( _`x1`_ , _`y1`_ ) , ... , ( _`xn`_ , _`yn`_ ) \] ( ( _`x1`_ , _`y1`_ ) , ... , ( _`xn`_ , _`yn`_ ) ) ( _`x1`_ , _`y1`_ ) , ... , ( _`xn`_ , _`yn`_ ) ( _`x1`_ , _`y1`_ , ... , _`xn`_ , _`yn`_ ) _`x1`_ , _`y1`_ , ... , _`xn`_ , _`yn`_ where the points are the end points of the line segments comprising the path. Square brackets (`[]`) indicate an open path, while parentheses (`()`) indicate a closed path. When the outermost parentheses are omitted, as in the third through fifth syntaxes, a closed path is assumed. Paths are output using the first or second syntax, as appropriate. ### 8.8.6. Polygons [#](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-POLYGON) Polygons are represented by lists of points (the vertices of the polygon). Polygons are very similar to closed paths; the essential semantic difference is that a polygon is considered to include the area within it, while a path is not. An important implementation difference between polygons and paths is that the stored representation of a polygon includes its smallest bounding box. This speeds up certain search operations, although computing the bounding box adds overhead while constructing new polygons. Values of type `polygon` are specified using any of the following syntaxes: ( ( _`x1`_ , _`y1`_ ) , ... , ( _`xn`_ , _`yn`_ ) ) ( _`x1`_ , _`y1`_ ) , ... , ( _`xn`_ , _`yn`_ ) ( _`x1`_ , _`y1`_ , ... , _`xn`_ , _`yn`_ ) _`x1`_ , _`y1`_ , ... , _`xn`_ , _`yn`_ where the points are the end points of the line segments comprising the boundary of the polygon. Polygons are output using the first syntax. ### 8.8.7. Circles [#](https://www.postgresql.org/docs/current/datatype-geometric.html#DATATYPE-CIRCLE) Circles are represented by a center point and radius. Values of type `circle` are specified using any of the following syntaxes: < ( _`x`_ , _`y`_ ) , _`r`_ > ( ( _`x`_ , _`y`_ ) , _`r`_ ) ( _`x`_ , _`y`_ ) , _`r`_ _`x`_ , _`y`_ , _`r`_ where ``(_`x`_,_`y`_)`` is the center point and _`r`_ is the radius of the circle. Circles are output using the first syntax. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/datatype-enum.html "8.7. Enumerated Types") | [Up](https://www.postgresql.org/docs/current/datatype.html "Chapter 8. Data Types") | [Next](https://www.postgresql.org/docs/current/datatype-net-types.html "8.9. Network Address Types") | | 8.7. Enumerated Types | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 8.9. Network Address Types | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/datatype-geometric.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 8.17. Range Types November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/rangetypes.html "PostgreSQL 18 - 8.17. Range Types") ([18](https://www.postgresql.org/docs/18/rangetypes.html "PostgreSQL 18 - 8.17. Range Types") ) / [17](https://www.postgresql.org/docs/17/rangetypes.html "PostgreSQL 17 - 8.17. Range Types") / [16](https://www.postgresql.org/docs/16/rangetypes.html "PostgreSQL 16 - 8.17. Range Types") / [15](https://www.postgresql.org/docs/15/rangetypes.html "PostgreSQL 15 - 8.17. Range Types") / [14](https://www.postgresql.org/docs/14/rangetypes.html "PostgreSQL 14 - 8.17. Range Types") Development Versions: [devel](https://www.postgresql.org/docs/devel/rangetypes.html "PostgreSQL devel - 8.17. Range Types") Unsupported versions: [13](https://www.postgresql.org/docs/13/rangetypes.html "PostgreSQL 13 - 8.17. Range Types") / [12](https://www.postgresql.org/docs/12/rangetypes.html "PostgreSQL 12 - 8.17. Range Types") / [11](https://www.postgresql.org/docs/11/rangetypes.html "PostgreSQL 11 - 8.17. Range Types") / [10](https://www.postgresql.org/docs/10/rangetypes.html "PostgreSQL 10 - 8.17. Range Types") / [9.6](https://www.postgresql.org/docs/9.6/rangetypes.html "PostgreSQL 9.6 - 8.17. Range Types") / [9.5](https://www.postgresql.org/docs/9.5/rangetypes.html "PostgreSQL 9.5 - 8.17. Range Types") / [9.4](https://www.postgresql.org/docs/9.4/rangetypes.html "PostgreSQL 9.4 - 8.17. Range Types") / [9.3](https://www.postgresql.org/docs/9.3/rangetypes.html "PostgreSQL 9.3 - 8.17. Range Types") / [9.2](https://www.postgresql.org/docs/9.2/rangetypes.html "PostgreSQL 9.2 - 8.17. Range Types") | 8.17. Range Types | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/rowtypes.html "8.16. Composite Types") | [Up](https://www.postgresql.org/docs/current/datatype.html "Chapter 8. Data Types") | Chapter 8. Data Types | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/domains.html "8.18. Domain Types") | * * * 8.17. Range Types [#](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES) ------------------------------------------------------------------------------------------ [8.17.1. Built-in Range and Multirange Types](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-BUILTIN) [8.17.2. Examples](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-EXAMPLES) [8.17.3. Inclusive and Exclusive Bounds](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-INCLUSIVITY) [8.17.4. Infinite (Unbounded) Ranges](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-INFINITE) [8.17.5. Range Input/Output](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-IO) [8.17.6. Constructing Ranges and Multiranges](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-CONSTRUCT) [8.17.7. Discrete Range Types](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-DISCRETE) [8.17.8. Defining New Range Types](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-DEFINING) [8.17.9. Indexing](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-INDEXING) [8.17.10. Constraints on Ranges](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-CONSTRAINT) Range types are data types representing a range of values of some element type (called the range's _subtype_). For instance, ranges of `timestamp` might be used to represent the ranges of time that a meeting room is reserved. In this case the data type is `tsrange` (short for “timestamp range”), and `timestamp` is the subtype. The subtype must have a total order so that it is well-defined whether element values are within, before, or after a range of values. Range types are useful because they represent many element values in a single range value, and because concepts such as overlapping ranges can be expressed clearly. The use of time and date ranges for scheduling purposes is the clearest example; but price ranges, measurement ranges from an instrument, and so forth can also be useful. Every range type has a corresponding multirange type. A multirange is an ordered list of non-contiguous, non-empty, non-null ranges. Most range operators also work on multiranges, and they have a few functions of their own. ### 8.17.1. Built-in Range and Multirange Types [#](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-BUILTIN) PostgreSQL comes with the following built-in range types: * `int4range` — Range of `integer`, `int4multirange` — corresponding Multirange * `int8range` — Range of `bigint`, `int8multirange` — corresponding Multirange * `numrange` — Range of `numeric`, `nummultirange` — corresponding Multirange * `tsrange` — Range of `timestamp without time zone`, `tsmultirange` — corresponding Multirange * `tstzrange` — Range of `timestamp with time zone`, `tstzmultirange` — corresponding Multirange * `daterange` — Range of `date`, `datemultirange` — corresponding Multirange In addition, you can define your own range types; see [CREATE TYPE](https://www.postgresql.org/docs/current/sql-createtype.html "CREATE TYPE") for more information. ### 8.17.2. Examples [#](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-EXAMPLES) CREATE TABLE reservation (room int, during tsrange); INSERT INTO reservation VALUES (1108, '\[2010-01-01 14:30, 2010-01-01 15:30)');\ \ -- Containment\ SELECT int4range(10, 20) @> 3;\ \ -- Overlaps\ SELECT numrange(11.1, 22.2) && numrange(20.0, 30.0);\ \ -- Extract the upper bound\ SELECT upper(int8range(15, 25));\ \ -- Compute the intersection\ SELECT int4range(10, 20) \* int4range(15, 25);\ \ -- Is the range empty?\ SELECT isempty(numrange(1, 5));\ \ See [Table 9.58](https://www.postgresql.org/docs/current/functions-range.html#RANGE-OPERATORS-TABLE "Table 9.58. Range Operators")\ and [Table 9.60](https://www.postgresql.org/docs/current/functions-range.html#RANGE-FUNCTIONS-TABLE "Table 9.60. Range Functions")\ for complete lists of operators and functions on range types.\ \ ### 8.17.3. Inclusive and Exclusive Bounds [#](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-INCLUSIVITY)\ \ Every non-empty range has two bounds, the lower bound and the upper bound. All points between these values are included in the range. An inclusive bound means that the boundary point itself is included in the range as well, while an exclusive bound means that the boundary point is not included in the range.\ \ In the text form of a range, an inclusive lower bound is represented by “`[`” while an exclusive lower bound is represented by “`(`”. Likewise, an inclusive upper bound is represented by “`]`”, while an exclusive upper bound is represented by “`)`”. (See [Section 8.17.5](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-IO "8.17.5. Range Input/Output")\ for more details.)\ \ The functions `lower_inc` and `upper_inc` test the inclusivity of the lower and upper bounds of a range value, respectively.\ \ ### 8.17.4. Infinite (Unbounded) Ranges [#](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-INFINITE)\ \ The lower bound of a range can be omitted, meaning that all values less than the upper bound are included in the range, e.g., `(,3]`. Likewise, if the upper bound of the range is omitted, then all values greater than the lower bound are included in the range. If both lower and upper bounds are omitted, all values of the element type are considered to be in the range. Specifying a missing bound as inclusive is automatically converted to exclusive, e.g., `[,]` is converted to `(,)`. You can think of these missing values as +/-infinity, but they are special range type values and are considered to be beyond any range element type's +/-infinity values. Element types that have the notion of “infinity” can use them as explicit bound values. For example, with timestamp ranges, `[today,infinity)` excludes the special `timestamp` value `infinity`, while `[today,infinity]` include it, as does `[today,)` and `[today,]`.\ \ The functions `lower_inf` and `upper_inf` test for infinite lower and upper bounds of a range, respectively.\ \ ### 8.17.5. Range Input/Output [#](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-IO)\ \ The input for a range value must follow one of the following patterns:\ \ (_`lower-bound`_,_`upper-bound`_)\ (_`lower-bound`_,_`upper-bound`_\]\ \[_`lower-bound`_,_`upper-bound`_)\ \[_`lower-bound`_,_`upper-bound`_\]\ empty\ \ The parentheses or brackets indicate whether the lower and upper bounds are exclusive or inclusive, as described previously. Notice that the final pattern is `empty`, which represents an empty range (a range that contains no points).\ \ The _`lower-bound`_ may be either a string that is valid input for the subtype, or empty to indicate no lower bound. Likewise, _`upper-bound`_ may be either a string that is valid input for the subtype, or empty to indicate no upper bound.\ \ Each bound value can be quoted using `"` (double quote) characters. This is necessary if the bound value contains parentheses, brackets, commas, double quotes, or backslashes, since these characters would otherwise be taken as part of the range syntax. To put a double quote or backslash in a quoted bound value, precede it with a backslash. (Also, a pair of double quotes within a double-quoted bound value is taken to represent a double quote character, analogously to the rules for single quotes in SQL literal strings.) Alternatively, you can avoid quoting and use backslash-escaping to protect all data characters that would otherwise be taken as range syntax. Also, to write a bound value that is an empty string, write `""`, since writing nothing means an infinite bound.\ \ Whitespace is allowed before and after the range value, but any whitespace between the parentheses or brackets is taken as part of the lower or upper bound value. (Depending on the element type, it might or might not be significant.)\ \ ### Note\ \ These rules are very similar to those for writing field values in composite-type literals. See [Section 8.16.6](https://www.postgresql.org/docs/current/rowtypes.html#ROWTYPES-IO-SYNTAX "8.16.6. Composite Type Input and Output Syntax")\ for additional commentary.\ \ Examples:\ \ \-- includes 3, does not include 7, and does include all points in between\ SELECT '\[3,7)'::int4range;\ \ -- does not include either 3 or 7, but includes all points in between\ SELECT '(3,7)'::int4range;\ \ -- includes only the single point 4\ SELECT '\[4,4\]'::int4range;\ \ -- includes no points (and will be normalized to 'empty')\ SELECT '\[4,4)'::int4range;\ \ The input for a multirange is curly brackets (`{` and `}`) containing zero or more valid ranges, separated by commas. Whitespace is permitted around the brackets and commas. This is intended to be reminiscent of array syntax, although multiranges are much simpler: they have just one dimension and there is no need to quote their contents. (The bounds of their ranges may be quoted as above however.)\ \ Examples:\ \ SELECT '{}'::int4multirange;\ SELECT '{\[3,7)}'::int4multirange;\ SELECT '{\[3,7), \[8,9)}'::int4multirange;\ \ ### 8.17.6. Constructing Ranges and Multiranges [#](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-CONSTRUCT)\ \ Each range type has a constructor function with the same name as the range type. Using the constructor function is frequently more convenient than writing a range literal constant, since it avoids the need for extra quoting of the bound values. The constructor function accepts two or three arguments. The two-argument form constructs a range in standard form (lower bound inclusive, upper bound exclusive), while the three-argument form constructs a range with bounds of the form specified by the third argument. The third argument must be one of the strings “`()`”, “`(]`”, “`[)`”, or “`[]`”. For example:\ \ \-- The full form is: lower bound, upper bound, and text argument indicating\ -- inclusivity/exclusivity of bounds.\ SELECT numrange(1.0, 14.0, '(\]');\ \ -- If the third argument is omitted, '\[)' is assumed.\ SELECT numrange(1.0, 14.0);\ \ -- Although '(\]' is specified here, on display the value will be converted to\ -- canonical form, since int8range is a discrete range type (see below).\ SELECT int8range(1, 14, '(\]');\ \ -- Using NULL for either bound causes the range to be unbounded on that side.\ SELECT numrange(NULL, 2.2);\ \ Each range type also has a multirange constructor with the same name as the multirange type. The constructor function takes zero or more arguments which are all ranges of the appropriate type. For example:\ \ SELECT nummultirange();\ SELECT nummultirange(numrange(1.0, 14.0));\ SELECT nummultirange(numrange(1.0, 14.0), numrange(20.0, 25.0));\ \ ### 8.17.7. Discrete Range Types [#](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-DISCRETE)\ \ A discrete range is one whose element type has a well-defined “step”, such as `integer` or `date`. In these types two elements can be said to be adjacent, when there are no valid values between them. This contrasts with continuous ranges, where it's always (or almost always) possible to identify other element values between two given values. For example, a range over the `numeric` type is continuous, as is a range over `timestamp`. (Even though `timestamp` has limited precision, and so could theoretically be treated as discrete, it's better to consider it continuous since the step size is normally not of interest.)\ \ Another way to think about a discrete range type is that there is a clear idea of a “next” or “previous” value for each element value. Knowing that, it is possible to convert between inclusive and exclusive representations of a range's bounds, by choosing the next or previous element value instead of the one originally given. For example, in an integer range type `[4,8]` and `(3,9)` denote the same set of values; but this would not be so for a range over numeric.\ \ A discrete range type should have a _canonicalization_ function that is aware of the desired step size for the element type. The canonicalization function is charged with converting equivalent values of the range type to have identical representations, in particular consistently inclusive or exclusive bounds. If a canonicalization function is not specified, then ranges with different formatting will always be treated as unequal, even though they might represent the same set of values in reality.\ \ The built-in range types `int4range`, `int8range`, and `daterange` all use a canonical form that includes the lower bound and excludes the upper bound; that is, `[)`. User-defined range types can use other conventions, however.\ \ ### 8.17.8. Defining New Range Types [#](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-DEFINING)\ \ Users can define their own range types. The most common reason to do this is to use ranges over subtypes not provided among the built-in range types. For example, to define a new range type of subtype `float8`:\ \ CREATE TYPE floatrange AS RANGE (\ subtype = float8,\ subtype\_diff = float8mi\ );\ \ SELECT '\[1.234, 5.678\]'::floatrange;\ \ Because `float8` has no meaningful “step”, we do not define a canonicalization function in this example.\ \ When you define your own range you automatically get a corresponding multirange type.\ \ Defining your own range type also allows you to specify a different subtype B-tree operator class or collation to use, so as to change the sort ordering that determines which values fall into a given range.\ \ If the subtype is considered to have discrete rather than continuous values, the `CREATE TYPE` command should specify a `canonical` function. The canonicalization function takes an input range value, and must return an equivalent range value that may have different bounds and formatting. The canonical output for two ranges that represent the same set of values, for example the integer ranges `[1, 7]` and `[1, 8)`, must be identical. It doesn't matter which representation you choose to be the canonical one, so long as two equivalent values with different formattings are always mapped to the same value with the same formatting. In addition to adjusting the inclusive/exclusive bounds format, a canonicalization function might round off boundary values, in case the desired step size is larger than what the subtype is capable of storing. For instance, a range type over `timestamp` could be defined to have a step size of an hour, in which case the canonicalization function would need to round off bounds that weren't a multiple of an hour, or perhaps throw an error instead.\ \ In addition, any range type that is meant to be used with GiST or SP-GiST indexes should define a subtype difference, or `subtype_diff`, function. (The index will still work without `subtype_diff`, but it is likely to be considerably less efficient than if a difference function is provided.) The subtype difference function takes two input values of the subtype, and returns their difference (i.e., _`X`_ minus _`Y`_) represented as a `float8` value. In our example above, the function `float8mi` that underlies the regular `float8` minus operator can be used; but for any other subtype, some type conversion would be necessary. Some creative thought about how to represent differences as numbers might be needed, too. To the greatest extent possible, the `subtype_diff` function should agree with the sort ordering implied by the selected operator class and collation; that is, its result should be positive whenever its first argument is greater than its second according to the sort ordering.\ \ A less-oversimplified example of a `subtype_diff` function is:\ \ CREATE FUNCTION time\_subtype\_diff(x time, y time) RETURNS float8 AS\ 'SELECT EXTRACT(EPOCH FROM (x - y))' LANGUAGE sql STRICT IMMUTABLE;\ \ CREATE TYPE timerange AS RANGE (\ subtype = time,\ subtype\_diff = time\_subtype\_diff\ );\ \ SELECT '\[11:10, 23:00\]'::timerange;\ \ See [CREATE TYPE](https://www.postgresql.org/docs/current/sql-createtype.html "CREATE TYPE")\ for more information about creating range types.\ \ ### 8.17.9. Indexing [#](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-INDEXING)\ \ GiST and SP-GiST indexes can be created for table columns of range types. GiST indexes can be also created for table columns of multirange types. For instance, to create a GiST index:\ \ CREATE INDEX reservation\_idx ON reservation USING GIST (during);\ \ A GiST or SP-GiST index on ranges can accelerate queries involving these range operators: `=`, `&&`, `<@`, `@>`, `<<`, `>>`, `-|-`, `&<`, and `&>`. A GiST index on multiranges can accelerate queries involving the same set of multirange operators. A GiST index on ranges and GiST index on multiranges can also accelerate queries involving these cross-type range to multirange and multirange to range operators correspondingly: `&&`, `<@`, `@>`, `<<`, `>>`, `-|-`, `&<`, and `&>`. See [Table 9.58](https://www.postgresql.org/docs/current/functions-range.html#RANGE-OPERATORS-TABLE "Table 9.58. Range Operators")\ for more information.\ \ In addition, B-tree and hash indexes can be created for table columns of range types. For these index types, basically the only useful range operation is equality. There is a B-tree sort ordering defined for range values, with corresponding `<` and `>` operators, but the ordering is rather arbitrary and not usually useful in the real world. Range types' B-tree and hash support is primarily meant to allow sorting and hashing internally in queries, rather than creation of actual indexes.\ \ ### 8.17.10. Constraints on Ranges [#](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-CONSTRAINT)\ \ While `UNIQUE` is a natural constraint for scalar values, it is usually unsuitable for range types. Instead, an exclusion constraint is often more appropriate (see [CREATE TABLE ... CONSTRAINT ... EXCLUDE](https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-EXCLUDE)\ ). Exclusion constraints allow the specification of constraints such as “non-overlapping” on a range type. For example:\ \ CREATE TABLE reservation (\ during tsrange,\ EXCLUDE USING GIST (during WITH &&)\ );\ \ That constraint will prevent any overlapping values from existing in the table at the same time:\ \ INSERT INTO reservation VALUES\ ('\[2010-01-01 11:30, 2010-01-01 15:00)');\ INSERT 0 1\ \ INSERT INTO reservation VALUES\ ('\[2010-01-01 14:45, 2010-01-01 15:45)');\ ERROR: conflicting key value violates exclusion constraint "reservation\_during\_excl"\ DETAIL: Key (during)=(\["2010-01-01 14:45:00","2010-01-01 15:45:00")) conflicts\ with existing key (during)=(\["2010-01-01 11:30:00","2010-01-01 15:00:00")).\ \ You can use the [`btree_gist`](https://www.postgresql.org/docs/current/btree-gist.html "F.8. btree_gist — GiST operator classes with B-tree behavior")\ extension to define exclusion constraints on plain scalar data types, which can then be combined with range exclusions for maximum flexibility. For example, after `btree_gist` is installed, the following constraint will reject overlapping ranges only if the meeting room numbers are equal:\ \ CREATE EXTENSION btree\_gist;\ CREATE TABLE room\_reservation (\ room text,\ during tsrange,\ EXCLUDE USING GIST (room WITH =, during WITH &&)\ );\ \ INSERT INTO room\_reservation VALUES\ ('123A', '\[2010-01-01 14:00, 2010-01-01 15:00)');\ INSERT 0 1\ \ INSERT INTO room\_reservation VALUES\ ('123A', '\[2010-01-01 14:30, 2010-01-01 15:30)');\ ERROR: conflicting key value violates exclusion constraint "room\_reservation\_room\_during\_excl"\ DETAIL: Key (room, during)=(123A, \["2010-01-01 14:30:00","2010-01-01 15:30:00")) conflicts\ with existing key (room, during)=(123A, \["2010-01-01 14:00:00","2010-01-01 15:00:00")).\ \ INSERT INTO room\_reservation VALUES\ ('123B', '\[2010-01-01 14:30, 2010-01-01 15:30)');\ INSERT 0 1\ \ * * *\ \ | | | |\ | --- | --- | --- |\ | [Prev](https://www.postgresql.org/docs/current/rowtypes.html "8.16. Composite Types") | [Up](https://www.postgresql.org/docs/current/datatype.html "Chapter 8. Data Types") | [Next](https://www.postgresql.org/docs/current/domains.html "8.18. Domain Types") |\ | 8.16. Composite Types | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 8.18. Domain Types |\ \ Submit correction\ -----------------\ \ If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/rangetypes.html/)\ to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE FUNCTION November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createfunction.html "PostgreSQL 18 - CREATE FUNCTION") ([18](https://www.postgresql.org/docs/18/sql-createfunction.html "PostgreSQL 18 - CREATE FUNCTION") ) / [17](https://www.postgresql.org/docs/17/sql-createfunction.html "PostgreSQL 17 - CREATE FUNCTION") / [16](https://www.postgresql.org/docs/16/sql-createfunction.html "PostgreSQL 16 - CREATE FUNCTION") / [15](https://www.postgresql.org/docs/15/sql-createfunction.html "PostgreSQL 15 - CREATE FUNCTION") / [14](https://www.postgresql.org/docs/14/sql-createfunction.html "PostgreSQL 14 - CREATE FUNCTION") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createfunction.html "PostgreSQL devel - CREATE FUNCTION") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createfunction.html "PostgreSQL 13 - CREATE FUNCTION") / [12](https://www.postgresql.org/docs/12/sql-createfunction.html "PostgreSQL 12 - CREATE FUNCTION") / [11](https://www.postgresql.org/docs/11/sql-createfunction.html "PostgreSQL 11 - CREATE FUNCTION") / [10](https://www.postgresql.org/docs/10/sql-createfunction.html "PostgreSQL 10 - CREATE FUNCTION") / [9.6](https://www.postgresql.org/docs/9.6/sql-createfunction.html "PostgreSQL 9.6 - CREATE FUNCTION") / [9.5](https://www.postgresql.org/docs/9.5/sql-createfunction.html "PostgreSQL 9.5 - CREATE FUNCTION") / [9.4](https://www.postgresql.org/docs/9.4/sql-createfunction.html "PostgreSQL 9.4 - CREATE FUNCTION") / [9.3](https://www.postgresql.org/docs/9.3/sql-createfunction.html "PostgreSQL 9.3 - CREATE FUNCTION") / [9.2](https://www.postgresql.org/docs/9.2/sql-createfunction.html "PostgreSQL 9.2 - CREATE FUNCTION") / [9.1](https://www.postgresql.org/docs/9.1/sql-createfunction.html "PostgreSQL 9.1 - CREATE FUNCTION") / [9.0](https://www.postgresql.org/docs/9.0/sql-createfunction.html "PostgreSQL 9.0 - CREATE FUNCTION") / [8.4](https://www.postgresql.org/docs/8.4/sql-createfunction.html "PostgreSQL 8.4 - CREATE FUNCTION") / [8.3](https://www.postgresql.org/docs/8.3/sql-createfunction.html "PostgreSQL 8.3 - CREATE FUNCTION") / [8.2](https://www.postgresql.org/docs/8.2/sql-createfunction.html "PostgreSQL 8.2 - CREATE FUNCTION") / [8.1](https://www.postgresql.org/docs/8.1/sql-createfunction.html "PostgreSQL 8.1 - CREATE FUNCTION") / [8.0](https://www.postgresql.org/docs/8.0/sql-createfunction.html "PostgreSQL 8.0 - CREATE FUNCTION") / [7.4](https://www.postgresql.org/docs/7.4/sql-createfunction.html "PostgreSQL 7.4 - CREATE FUNCTION") / [7.3](https://www.postgresql.org/docs/7.3/sql-createfunction.html "PostgreSQL 7.3 - CREATE FUNCTION") / [7.2](https://www.postgresql.org/docs/7.2/sql-createfunction.html "PostgreSQL 7.2 - CREATE FUNCTION") / [7.1](https://www.postgresql.org/docs/7.1/sql-createfunction.html "PostgreSQL 7.1 - CREATE FUNCTION") | CREATE FUNCTION | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createforeigntable.html "CREATE FOREIGN TABLE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-creategroup.html "CREATE GROUP") | * * * CREATE FUNCTION --------------- CREATE FUNCTION — define a new function Synopsis -------- CREATE \[ OR REPLACE \] FUNCTION _`name`_ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[ { DEFAULT | = } _`default_expr`_ \] \[, ...\] \] ) \[ RETURNS _`rettype`_\ | RETURNS TABLE ( _`column_name`_ _`column_type`_ \[, ...\] ) \] { LANGUAGE _`lang_name`_ | TRANSFORM { FOR TYPE _`type_name`_ } \[, ... \] | WINDOW | { IMMUTABLE | STABLE | VOLATILE } | \[ NOT \] LEAKPROOF | { CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT } | { \[ EXTERNAL \] SECURITY INVOKER | \[ EXTERNAL \] SECURITY DEFINER } | PARALLEL { UNSAFE | RESTRICTED | SAFE } | COST _`execution_cost`_ | ROWS _`result_rows`_ | SUPPORT _`support_function`_ | SET _`configuration_parameter`_ { TO _`value`_ | = _`value`_ | FROM CURRENT } | AS '_`definition`_' | AS '_`obj_file`_', '_`link_symbol`_' | _`sql_body`_ } ... Description ----------- `CREATE FUNCTION` defines a new function. `CREATE OR REPLACE FUNCTION` will either create a new function, or replace an existing definition. To be able to define a function, the user must have the `USAGE` privilege on the language. If a schema name is included, then the function is created in the specified schema. Otherwise it is created in the current schema. The name of the new function must not match any existing function or procedure with the same input argument types in the same schema. However, functions and procedures of different argument types can share a name (this is called _overloading_). To replace the current definition of an existing function, use `CREATE OR REPLACE FUNCTION`. It is not possible to change the name or argument types of a function this way (if you tried, you would actually be creating a new, distinct function). Also, `CREATE OR REPLACE FUNCTION` will not let you change the return type of an existing function. To do that, you must drop and recreate the function. (When using `OUT` parameters, that means you cannot change the types of any `OUT` parameters except by dropping the function.) When `CREATE OR REPLACE FUNCTION` is used to replace an existing function, the ownership and permissions of the function do not change. All other function properties are assigned the values specified or implied in the command. You must own the function to replace it (this includes being a member of the owning role). If you drop and then recreate a function, the new function is not the same entity as the old; you will have to drop existing rules, views, triggers, etc. that refer to the old function. Use `CREATE OR REPLACE FUNCTION` to change a function definition without breaking objects that refer to the function. Also, `ALTER FUNCTION` can be used to change most of the auxiliary properties of an existing function. The user that creates the function becomes the owner of the function. To be able to create a function, you must have `USAGE` privilege on the argument types and the return type. Refer to [Section 36.3](https://www.postgresql.org/docs/18/xfunc.html "36.3. User-Defined Functions") for further information on writing functions. Parameters ---------- _`name`_ The name (optionally schema-qualified) of the function to create. _`argmode`_ The mode of an argument: `IN`, `OUT`, `INOUT`, or `VARIADIC`. If omitted, the default is `IN`. Only `OUT` arguments can follow a `VARIADIC` one. Also, `OUT` and `INOUT` arguments cannot be used together with the `RETURNS TABLE` notation. _`argname`_ The name of an argument. Some languages (including SQL and PL/pgSQL) let you use the name in the function body. For other languages the name of an input argument is just extra documentation, so far as the function itself is concerned; but you can use input argument names when calling a function to improve readability (see [Section 4.3](https://www.postgresql.org/docs/18/sql-syntax-calling-funcs.html "4.3. Calling Functions") ). In any case, the name of an output argument is significant, because it defines the column name in the result row type. (If you omit the name for an output argument, the system will choose a default column name.) _`argtype`_ The data type(s) of the function's arguments (optionally schema-qualified), if any. The argument types can be base, composite, or domain types, or can reference the type of a table column. Depending on the implementation language it might also be allowed to specify “pseudo-types” such as `cstring`. Pseudo-types indicate that the actual argument type is either incompletely specified, or outside the set of ordinary SQL data types. The type of a column is referenced by writing ``_`table_name`_._`column_name`_%TYPE``. Using this feature can sometimes help make a function independent of changes to the definition of a table. _`default_expr`_ An expression to be used as default value if the parameter is not specified. The expression has to be coercible to the argument type of the parameter. Only input (including `INOUT`) parameters can have a default value. All input parameters following a parameter with a default value must have default values as well. _`rettype`_ The return data type (optionally schema-qualified). The return type can be a base, composite, or domain type, or can reference the type of a table column. Depending on the implementation language it might also be allowed to specify “pseudo-types” such as `cstring`. If the function is not supposed to return a value, specify `void` as the return type. When there are `OUT` or `INOUT` parameters, the `RETURNS` clause can be omitted. If present, it must agree with the result type implied by the output parameters: `RECORD` if there are multiple output parameters, or the same type as the single output parameter. The `SETOF` modifier indicates that the function will return a set of items, rather than a single item. The type of a column is referenced by writing ``_`table_name`_._`column_name`_%TYPE``. _`column_name`_ The name of an output column in the `RETURNS TABLE` syntax. This is effectively another way of declaring a named `OUT` parameter, except that `RETURNS TABLE` also implies `RETURNS SETOF`. _`column_type`_ The data type of an output column in the `RETURNS TABLE` syntax. _`lang_name`_ The name of the language that the function is implemented in. It can be `sql`, `c`, `internal`, or the name of a user-defined procedural language, e.g., `plpgsql`. The default is `sql` if _`sql_body`_ is specified. Enclosing the name in single quotes is deprecated and requires matching case. ``TRANSFORM { FOR TYPE _`type_name`_ } [, ... ] }`` Lists which transforms a call to the function should apply. Transforms convert between SQL types and language-specific data types; see [CREATE TRANSFORM](https://www.postgresql.org/docs/18/sql-createtransform.html "CREATE TRANSFORM") . Procedural language implementations usually have hardcoded knowledge of the built-in types, so those don't need to be listed here. If a procedural language implementation does not know how to handle a type and no transform is supplied, it will fall back to a default behavior for converting data types, but this depends on the implementation. `WINDOW` `WINDOW` indicates that the function is a _window function_ rather than a plain function. This is currently only useful for functions written in C. The `WINDOW` attribute cannot be changed when replacing an existing function definition. `IMMUTABLE` `STABLE` `VOLATILE` These attributes inform the query optimizer about the behavior of the function. At most one choice can be specified. If none of these appear, `VOLATILE` is the default assumption. `IMMUTABLE` indicates that the function cannot modify the database and always returns the same result when given the same argument values; that is, it does not do database lookups or otherwise use information not directly present in its argument list. If this option is given, any call of the function with all-constant arguments can be immediately replaced with the function value. `STABLE` indicates that the function cannot modify the database, and that within a single table scan it will consistently return the same result for the same argument values, but that its result could change across SQL statements. This is the appropriate selection for functions whose results depend on database lookups, parameter variables (such as the current time zone), etc. (It is inappropriate for `AFTER` triggers that wish to query rows modified by the current command.) Also note that the `current_timestamp` family of functions qualify as stable, since their values do not change within a transaction. `VOLATILE` indicates that the function value can change even within a single table scan, so no optimizations can be made. Relatively few database functions are volatile in this sense; some examples are `random()`, `currval()`, `timeofday()`. But note that any function that has side-effects must be classified volatile, even if its result is quite predictable, to prevent calls from being optimized away; an example is `setval()`. For additional details see [Section 36.7](https://www.postgresql.org/docs/18/xfunc-volatility.html "36.7. Function Volatility Categories") . `LEAKPROOF` `LEAKPROOF` indicates that the function has no side effects. It reveals no information about its arguments other than by its return value. For example, a function which throws an error message for some argument values but not others, or which includes the argument values in any error message, is not leakproof. This affects how the system executes queries against views created with the `security_barrier` option or tables with row level security enabled. The system will enforce conditions from security policies and security barrier views before any user-supplied conditions from the query itself that contain non-leakproof functions, in order to prevent the inadvertent exposure of data. Functions and operators marked as leakproof are assumed to be trustworthy, and may be executed before conditions from security policies and security barrier views. In addition, functions which do not take arguments or which are not passed any arguments from the security barrier view or table do not have to be marked as leakproof to be executed before security conditions. See [CREATE VIEW](https://www.postgresql.org/docs/18/sql-createview.html "CREATE VIEW") and [Section 39.5](https://www.postgresql.org/docs/18/rules-privileges.html "39.5. Rules and Privileges") . This option can only be set by the superuser. `CALLED ON NULL INPUT` `RETURNS NULL ON NULL INPUT` `STRICT` `CALLED ON NULL INPUT` (the default) indicates that the function will be called normally when some of its arguments are null. It is then the function author's responsibility to check for null values if necessary and respond appropriately. `RETURNS NULL ON NULL INPUT` or `STRICT` indicates that the function always returns null whenever any of its arguments are null. If this parameter is specified, the function is not executed when there are null arguments; instead a null result is assumed automatically. `[EXTERNAL] SECURITY INVOKER` `[EXTERNAL] SECURITY DEFINER` `SECURITY INVOKER` indicates that the function is to be executed with the privileges of the user that calls it. That is the default. `SECURITY DEFINER` specifies that the function is to be executed with the privileges of the user that owns it. For information on how to write `SECURITY DEFINER` functions safely, [see below](https://www.postgresql.org/docs/18/sql-createfunction.html#SQL-CREATEFUNCTION-SECURITY "Writing SECURITY DEFINER Functions Safely") . The key word `EXTERNAL` is allowed for SQL conformance, but it is optional since, unlike in SQL, this feature applies to all functions not only external ones. `PARALLEL` `PARALLEL UNSAFE` indicates that the function can't be executed in parallel mode; the presence of such a function in an SQL statement forces a serial execution plan. This is the default. `PARALLEL RESTRICTED` indicates that the function can be executed in parallel mode, but only in the parallel group leader process. `PARALLEL SAFE` indicates that the function is safe to run in parallel mode without restriction, including in parallel worker processes. Functions should be labeled parallel unsafe if they modify any database state, change the transaction state (other than by using a subtransaction for error recovery), access sequences (e.g., by calling `currval`) or make persistent changes to settings. They should be labeled parallel restricted if they access temporary tables, client connection state, cursors, prepared statements, or miscellaneous backend-local state which the system cannot synchronize in parallel mode (e.g., `setseed` cannot be executed other than by the group leader because a change made by another process would not be reflected in the leader). In general, if a function is labeled as being safe when it is restricted or unsafe, or if it is labeled as being restricted when it is in fact unsafe, it may throw errors or produce wrong answers when used in a parallel query. C-language functions could in theory exhibit totally undefined behavior if mislabeled, since there is no way for the system to protect itself against arbitrary C code, but in most likely cases the result will be no worse than for any other function. If in doubt, functions should be labeled as `UNSAFE`, which is the default. `COST` _`execution_cost`_ A positive number giving the estimated execution cost for the function, in units of [cpu\_operator\_cost](https://www.postgresql.org/docs/18/runtime-config-query.html#GUC-CPU-OPERATOR-COST) . If the function returns a set, this is the cost per returned row. If the cost is not specified, 1 unit is assumed for C-language and internal functions, and 100 units for functions in all other languages. Larger values cause the planner to try to avoid evaluating the function more often than necessary. `ROWS` _`result_rows`_ A positive number giving the estimated number of rows that the planner should expect the function to return. This is only allowed when the function is declared to return a set. The default assumption is 1000 rows. `SUPPORT` _`support_function`_ The name (optionally schema-qualified) of a _planner support function_ to use for this function. See [Section 36.11](https://www.postgresql.org/docs/18/xfunc-optimization.html "36.11. Function Optimization Information") for details. You must be superuser to use this option. _`configuration_parameter`_ _`value`_ The `SET` clause causes the specified configuration parameter to be set to the specified value when the function is entered, and then restored to its prior value when the function exits. `SET FROM CURRENT` saves the value of the parameter that is current when `CREATE FUNCTION` is executed as the value to be applied when the function is entered. If a `SET` clause is attached to a function, then the effects of a `SET LOCAL` command executed inside the function for the same variable are restricted to the function: the configuration parameter's prior value is still restored at function exit. However, an ordinary `SET` command (without `LOCAL`) overrides the `SET` clause, much as it would do for a previous `SET LOCAL` command: the effects of such a command will persist after function exit, unless the current transaction is rolled back. See [SET](https://www.postgresql.org/docs/18/sql-set.html "SET") and [Chapter 19](https://www.postgresql.org/docs/18/runtime-config.html "Chapter 19. Server Configuration") for more information about allowed parameter names and values. _`definition`_ A string constant defining the function; the meaning depends on the language. It can be an internal function name, the path to an object file, an SQL command, or text in a procedural language. It is often helpful to use dollar quoting (see [Section 4.1.2.4](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING "4.1.2.4. Dollar-Quoted String Constants") ) to write the function definition string, rather than the normal single quote syntax. Without dollar quoting, any single quotes or backslashes in the function definition must be escaped by doubling them. ``_`obj_file`_, _`link_symbol`_`` This form of the `AS` clause is used for dynamically loadable C language functions when the function name in the C language source code is not the same as the name of the SQL function. The string _`obj_file`_ is the name of the shared library file containing the compiled C function, and is interpreted as for the [`LOAD`](https://www.postgresql.org/docs/18/sql-load.html "LOAD") command. The string _`link_symbol`_ is the function's link symbol, that is, the name of the function in the C language source code. If the link symbol is omitted, it is assumed to be the same as the name of the SQL function being defined. The C names of all functions must be different, so you must give overloaded C functions different C names (for example, use the argument types as part of the C names). When repeated `CREATE FUNCTION` calls refer to the same object file, the file is only loaded once per session. To unload and reload the file (perhaps during development), start a new session. _`sql_body`_ The body of a `LANGUAGE SQL` function. This can either be a single statement RETURN _`expression`_ or a block BEGIN ATOMIC _`statement`_; _`statement`_; ... _`statement`_; END This is similar to writing the text of the function body as a string constant (see _`definition`_ above), but there are some differences: This form only works for `LANGUAGE SQL`, the string constant form works for all languages. This form is parsed at function definition time, the string constant form is parsed at execution time; therefore this form cannot support polymorphic argument types and other constructs that are not resolvable at function definition time. This form tracks dependencies between the function and objects used in the function body, so `DROP ... CASCADE` will work correctly, whereas the form using string literals may leave dangling functions. Finally, this form is more compatible with the SQL standard and other SQL implementations. Overloading ----------- PostgreSQL allows function _overloading_; that is, the same name can be used for several different functions so long as they have distinct input argument types. Whether or not you use it, this capability entails security precautions when calling functions in databases where some users mistrust other users; see [Section 10.3](https://www.postgresql.org/docs/18/typeconv-func.html "10.3. Functions") . Two functions are considered the same if they have the same names and _input_ argument types, ignoring any `OUT` parameters. Thus for example these declarations conflict: CREATE FUNCTION foo(int) ... CREATE FUNCTION foo(int, out text) ... Functions that have different argument type lists will not be considered to conflict at creation time, but if defaults are provided they might conflict in use. For example, consider CREATE FUNCTION foo(int) ... CREATE FUNCTION foo(int, int default 42) ... A call `foo(10)` will fail due to the ambiguity about which function should be called. Notes ----- The full SQL type syntax is allowed for declaring a function's arguments and return value. However, parenthesized type modifiers (e.g., the precision field for type `numeric`) are discarded by `CREATE FUNCTION`. Thus for example `CREATE FUNCTION foo (varchar(10)) ...` is exactly the same as `CREATE FUNCTION foo (varchar) ...`. When replacing an existing function with `CREATE OR REPLACE FUNCTION`, there are restrictions on changing parameter names. You cannot change the name already assigned to any input parameter (although you can add names to parameters that had none before). If there is more than one output parameter, you cannot change the names of the output parameters, because that would change the column names of the anonymous composite type that describes the function's result. These restrictions are made to ensure that existing calls of the function do not stop working when it is replaced. If a function is declared `STRICT` with a `VARIADIC` argument, the strictness check tests that the variadic array _as a whole_ is non-null. The function will still be called if the array has null elements. Examples -------- Add two integers using an SQL function: CREATE FUNCTION add(integer, integer) RETURNS integer AS 'select $1 + $2;' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT; The same function written in a more SQL-conforming style, using argument names and an unquoted body: CREATE FUNCTION add(a integer, b integer) RETURNS integer LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT RETURN a + b; Increment an integer, making use of an argument name, in PL/pgSQL: CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$ BEGIN RETURN i + 1; END; $$ LANGUAGE plpgsql; Return a record containing multiple output parameters: CREATE FUNCTION dup(in int, out f1 int, out f2 text) AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$ LANGUAGE SQL; SELECT \* FROM dup(42); You can do the same thing more verbosely with an explicitly named composite type: CREATE TYPE dup\_result AS (f1 int, f2 text); CREATE FUNCTION dup(int) RETURNS dup\_result AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$ LANGUAGE SQL; SELECT \* FROM dup(42); Another way to return multiple columns is to use a `TABLE` function: CREATE FUNCTION dup(int) RETURNS TABLE(f1 int, f2 text) AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$ LANGUAGE SQL; SELECT \* FROM dup(42); However, a `TABLE` function is different from the preceding examples, because it actually returns a _set_ of records, not just one record. Writing `SECURITY DEFINER` Functions Safely ------------------------------------------- Because a `SECURITY DEFINER` function is executed with the privileges of the user that owns it, care is needed to ensure that the function cannot be misused. For security, [search\_path](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-SEARCH-PATH) should be set to exclude any schemas writable by untrusted users. This prevents malicious users from creating objects (e.g., tables, functions, and operators) that mask objects intended to be used by the function. Particularly important in this regard is the temporary-table schema, which is searched first by default, and is normally writable by anyone. A secure arrangement can be obtained by forcing the temporary schema to be searched last. To do this, write `pg_temp` as the last entry in `search_path`. This function illustrates safe usage: CREATE FUNCTION check\_password(uname TEXT, pass TEXT) RETURNS BOOLEAN AS $$ DECLARE passed BOOLEAN; BEGIN SELECT (pwd = $2) INTO passed FROM pwds WHERE username = $1; RETURN passed; END; $$ LANGUAGE plpgsql SECURITY DEFINER -- Set a secure search\_path: trusted schema(s), then 'pg\_temp'. SET search\_path = admin, pg\_temp; This function's intention is to access a table `admin.pwds`. But without the `SET` clause, or with a `SET` clause mentioning only `admin`, the function could be subverted by creating a temporary table named `pwds`. If the security definer function intends to create roles, and if it is running as a non-superuser, `createrole_self_grant` should also be set to a known value using the `SET` clause. Another point to keep in mind is that by default, execute privilege is granted to `PUBLIC` for newly created functions (see [Section 5.8](https://www.postgresql.org/docs/18/ddl-priv.html "5.8. Privileges") for more information). Frequently you will wish to restrict use of a security definer function to only some users. To do that, you must revoke the default `PUBLIC` privileges and then grant execute privilege selectively. To avoid having a window where the new function is accessible to all, create it and set the privileges within a single transaction. For example: BEGIN; CREATE FUNCTION check\_password(uname TEXT, pass TEXT) ... SECURITY DEFINER; REVOKE ALL ON FUNCTION check\_password(uname TEXT, pass TEXT) FROM PUBLIC; GRANT EXECUTE ON FUNCTION check\_password(uname TEXT, pass TEXT) TO admins; COMMIT; Compatibility ------------- A `CREATE FUNCTION` command is defined in the SQL standard. The PostgreSQL implementation can be used in a compatible way but has many extensions. Conversely, the SQL standard specifies a number of optional features that are not implemented in PostgreSQL. The following are important compatibility issues: * `OR REPLACE` is a PostgreSQL extension. * For compatibility with some other database systems, _`argmode`_ can be written either before or after _`argname`_. But only the first way is standard-compliant. * For parameter defaults, the SQL standard specifies only the syntax with the `DEFAULT` key word. The syntax with `=` is used in T-SQL and Firebird. * The `SETOF` modifier is a PostgreSQL extension. * Only `SQL` is standardized as a language. * All other attributes except `CALLED ON NULL INPUT` and `RETURNS NULL ON NULL INPUT` are not standardized. * For the body of `LANGUAGE SQL` functions, the SQL standard only specifies the _`sql_body`_ form. Simple `LANGUAGE SQL` functions can be written in a way that is both standard-conforming and portable to other implementations. More complex functions using advanced features, optimization attributes, or other languages will necessarily be specific to PostgreSQL in a significant way. See Also -------- [ALTER FUNCTION](https://www.postgresql.org/docs/18/sql-alterfunction.html "ALTER FUNCTION") , [DROP FUNCTION](https://www.postgresql.org/docs/18/sql-dropfunction.html "DROP FUNCTION") , [GRANT](https://www.postgresql.org/docs/18/sql-grant.html "GRANT") , [LOAD](https://www.postgresql.org/docs/18/sql-load.html "LOAD") , [REVOKE](https://www.postgresql.org/docs/18/sql-revoke.html "REVOKE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createforeigntable.html "CREATE FOREIGN TABLE") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-creategroup.html "CREATE GROUP") | | CREATE FOREIGN TABLE | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | CREATE GROUP | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createfunction.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE VIEW November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createview.html "PostgreSQL 18 - CREATE VIEW") ([18](https://www.postgresql.org/docs/18/sql-createview.html "PostgreSQL 18 - CREATE VIEW") ) / [17](https://www.postgresql.org/docs/17/sql-createview.html "PostgreSQL 17 - CREATE VIEW") / [16](https://www.postgresql.org/docs/16/sql-createview.html "PostgreSQL 16 - CREATE VIEW") / [15](https://www.postgresql.org/docs/15/sql-createview.html "PostgreSQL 15 - CREATE VIEW") / [14](https://www.postgresql.org/docs/14/sql-createview.html "PostgreSQL 14 - CREATE VIEW") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createview.html "PostgreSQL devel - CREATE VIEW") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createview.html "PostgreSQL 13 - CREATE VIEW") / [12](https://www.postgresql.org/docs/12/sql-createview.html "PostgreSQL 12 - CREATE VIEW") / [11](https://www.postgresql.org/docs/11/sql-createview.html "PostgreSQL 11 - CREATE VIEW") / [10](https://www.postgresql.org/docs/10/sql-createview.html "PostgreSQL 10 - CREATE VIEW") / [9.6](https://www.postgresql.org/docs/9.6/sql-createview.html "PostgreSQL 9.6 - CREATE VIEW") / [9.5](https://www.postgresql.org/docs/9.5/sql-createview.html "PostgreSQL 9.5 - CREATE VIEW") / [9.4](https://www.postgresql.org/docs/9.4/sql-createview.html "PostgreSQL 9.4 - CREATE VIEW") / [9.3](https://www.postgresql.org/docs/9.3/sql-createview.html "PostgreSQL 9.3 - CREATE VIEW") / [9.2](https://www.postgresql.org/docs/9.2/sql-createview.html "PostgreSQL 9.2 - CREATE VIEW") / [9.1](https://www.postgresql.org/docs/9.1/sql-createview.html "PostgreSQL 9.1 - CREATE VIEW") / [9.0](https://www.postgresql.org/docs/9.0/sql-createview.html "PostgreSQL 9.0 - CREATE VIEW") / [8.4](https://www.postgresql.org/docs/8.4/sql-createview.html "PostgreSQL 8.4 - CREATE VIEW") / [8.3](https://www.postgresql.org/docs/8.3/sql-createview.html "PostgreSQL 8.3 - CREATE VIEW") / [8.2](https://www.postgresql.org/docs/8.2/sql-createview.html "PostgreSQL 8.2 - CREATE VIEW") / [8.1](https://www.postgresql.org/docs/8.1/sql-createview.html "PostgreSQL 8.1 - CREATE VIEW") / [8.0](https://www.postgresql.org/docs/8.0/sql-createview.html "PostgreSQL 8.0 - CREATE VIEW") / [7.4](https://www.postgresql.org/docs/7.4/sql-createview.html "PostgreSQL 7.4 - CREATE VIEW") / [7.3](https://www.postgresql.org/docs/7.3/sql-createview.html "PostgreSQL 7.3 - CREATE VIEW") / [7.2](https://www.postgresql.org/docs/7.2/sql-createview.html "PostgreSQL 7.2 - CREATE VIEW") / [7.1](https://www.postgresql.org/docs/7.1/sql-createview.html "PostgreSQL 7.1 - CREATE VIEW") | CREATE VIEW | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createusermapping.html "CREATE USER MAPPING") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-deallocate.html "DEALLOCATE") | * * * CREATE VIEW ----------- CREATE VIEW — define a new view Synopsis -------- CREATE \[ OR REPLACE \] \[ TEMP | TEMPORARY \] \[ RECURSIVE \] VIEW _`name`_ \[ ( _`column_name`_ \[, ...\] ) \] \[ WITH ( _`view_option_name`_ \[= _`view_option_value`_\] \[, ... \] ) \] AS _`query`_ \[ WITH \[ CASCADED | LOCAL \] CHECK OPTION \] Description ----------- `CREATE VIEW` defines a view of a query. The view is not physically materialized. Instead, the query is run every time the view is referenced in a query. `CREATE OR REPLACE VIEW` is similar, but if a view of the same name already exists, it is replaced. The new query must generate the same columns that were generated by the existing view query (that is, the same column names in the same order and with the same data types), but it may add additional columns to the end of the list. The calculations giving rise to the output columns may be completely different. If a schema name is given (for example, `CREATE VIEW myschema.myview ...`) then the view is created in the specified schema. Otherwise it is created in the current schema. Temporary views exist in a special schema, so a schema name cannot be given when creating a temporary view. The name of the view must be distinct from the name of any other relation (table, sequence, index, view, materialized view, or foreign table) in the same schema. Parameters ---------- `TEMPORARY` or `TEMP` If specified, the view is created as a temporary view. Temporary views are automatically dropped at the end of the current session. Existing permanent relations with the same name are not visible to the current session while the temporary view exists, unless they are referenced with schema-qualified names. If any of the tables referenced by the view are temporary, the view is created as a temporary view (whether `TEMPORARY` is specified or not). `RECURSIVE` Creates a recursive view. The syntax CREATE RECURSIVE VIEW \[ _`schema`_ . \] _`view_name`_ (_`column_names`_) AS SELECT _`...`_; is equivalent to CREATE VIEW \[ _`schema`_ . \] _`view_name`_ AS WITH RECURSIVE _`view_name`_ (_`column_names`_) AS (SELECT _`...`_) SELECT _`column_names`_ FROM _`view_name`_; A view column name list must be specified for a recursive view. _`name`_ The name (optionally schema-qualified) of a view to be created. _`column_name`_ An optional list of names to be used for columns of the view. If not given, the column names are deduced from the query. ``WITH ( _`view_option_name`_ [= _`view_option_value`_] [, ... ] )`` This clause specifies optional parameters for a view; the following parameters are supported: `check_option` (`enum`) This parameter may be either `local` or `cascaded`, and is equivalent to specifying `WITH [ CASCADED | LOCAL ] CHECK OPTION` (see below). `security_barrier` (`boolean`) This should be used if the view is intended to provide row-level security. See [Section 39.5](https://www.postgresql.org/docs/18/rules-privileges.html "39.5. Rules and Privileges") for full details. `security_invoker` (`boolean`) This option causes the underlying base relations to be checked against the privileges of the user of the view rather than the view owner. See the notes below for full details. All of the above options can be changed on existing views using [`ALTER VIEW`](https://www.postgresql.org/docs/18/sql-alterview.html "ALTER VIEW") . _`query`_ A [`SELECT`](https://www.postgresql.org/docs/18/sql-select.html "SELECT") or [`VALUES`](https://www.postgresql.org/docs/18/sql-values.html "VALUES") command which will provide the columns and rows of the view. `WITH [ CASCADED | LOCAL ] CHECK OPTION` This option controls the behavior of automatically updatable views. When this option is specified, `INSERT`, `UPDATE`, and `MERGE` commands on the view will be checked to ensure that new rows satisfy the view-defining condition (that is, the new rows are checked to ensure that they are visible through the view). If they are not, the update will be rejected. If the `CHECK OPTION` is not specified, `INSERT`, `UPDATE`, and `MERGE` commands on the view are allowed to create rows that are not visible through the view. The following check options are supported: `LOCAL` New rows are only checked against the conditions defined directly in the view itself. Any conditions defined on underlying base views are not checked (unless they also specify the `CHECK OPTION`). `CASCADED` New rows are checked against the conditions of the view and all underlying base views. If the `CHECK OPTION` is specified, and neither `LOCAL` nor `CASCADED` is specified, then `CASCADED` is assumed. The `CHECK OPTION` may not be used with `RECURSIVE` views. Note that the `CHECK OPTION` is only supported on views that are automatically updatable, and do not have `INSTEAD OF` triggers or `INSTEAD` rules. If an automatically updatable view is defined on top of a base view that has `INSTEAD OF` triggers, then the `LOCAL CHECK OPTION` may be used to check the conditions on the automatically updatable view, but the conditions on the base view with `INSTEAD OF` triggers will not be checked (a cascaded check option will not cascade down to a trigger-updatable view, and any check options defined directly on a trigger-updatable view will be ignored). If the view or any of its base relations has an `INSTEAD` rule that causes the `INSERT` or `UPDATE` command to be rewritten, then all check options will be ignored in the rewritten query, including any checks from automatically updatable views defined on top of the relation with the `INSTEAD` rule. `MERGE` is not supported if the view or any of its base relations have rules. Notes ----- Use the [`DROP VIEW`](https://www.postgresql.org/docs/18/sql-dropview.html "DROP VIEW") statement to drop views. Be careful that the names and types of the view's columns will be assigned the way you want. For example: CREATE VIEW vista AS SELECT 'Hello World'; is bad form because the column name defaults to `?column?`; also, the column data type defaults to `text`, which might not be what you wanted. Better style for a string literal in a view's result is something like: CREATE VIEW vista AS SELECT text 'Hello World' AS hello; By default, access to the underlying base relations referenced in the view is determined by the permissions of the view owner. In some cases, this can be used to provide secure but restricted access to the underlying tables. However, not all views are secure against tampering; see [Section 39.5](https://www.postgresql.org/docs/18/rules-privileges.html "39.5. Rules and Privileges") for details. If the view has the `security_invoker` property set to `true`, access to the underlying base relations is determined by the permissions of the user executing the query, rather than the view owner. Thus, the user of a security invoker view must have the relevant permissions on the view and its underlying base relations. If any of the underlying base relations is a security invoker view, it will be treated as if it had been accessed directly from the original query. Thus, a security invoker view will always check its underlying base relations using the permissions of the current user, even if it is accessed from a view without the `security_invoker` property. If any of the underlying base relations has [row-level security](https://www.postgresql.org/docs/18/ddl-rowsecurity.html "5.9. Row Security Policies") enabled, then by default, the row-level security policies of the view owner are applied, and access to any additional relations referred to by those policies is determined by the permissions of the view owner. However, if the view has `security_invoker` set to `true`, then the policies and permissions of the invoking user are used instead, as if the base relations had been referenced directly from the query using the view. Functions called in the view are treated the same as if they had been called directly from the query using the view. Therefore, the user of a view must have permissions to call all functions used by the view. Functions in the view are executed with the privileges of the user executing the query or the function owner, depending on whether the functions are defined as `SECURITY INVOKER` or `SECURITY DEFINER`. Thus, for example, calling `CURRENT_USER` directly in a view will always return the invoking user, not the view owner. This is not affected by the view's `security_invoker` setting, and so a view with `security_invoker` set to `false` is _not_ equivalent to a `SECURITY DEFINER` function and those concepts should not be confused. The user creating or replacing a view must have `USAGE` privileges on any schemas referred to in the view query, in order to look up the referenced objects in those schemas. Note, however, that this lookup only happens when the view is created or replaced. Therefore, the user of the view only requires the `USAGE` privilege on the schema containing the view, not on the schemas referred to in the view query, even for a security invoker view. When `CREATE OR REPLACE VIEW` is used on an existing view, only the view's defining SELECT rule, plus any `WITH ( ... )` parameters and its `CHECK OPTION` are changed. Other view properties, including ownership, permissions, and non-SELECT rules, remain unchanged. You must own the view to replace it (this includes being a member of the owning role). ### Updatable Views Simple views are automatically updatable: the system will allow `INSERT`, `UPDATE`, `DELETE`, and `MERGE` statements to be used on the view in the same way as on a regular table. A view is automatically updatable if it satisfies all of the following conditions: * The view must have exactly one entry in its `FROM` list, which must be a table or another updatable view. * The view definition must not contain `WITH`, `DISTINCT`, `GROUP BY`, `HAVING`, `LIMIT`, or `OFFSET` clauses at the top level. * The view definition must not contain set operations (`UNION`, `INTERSECT` or `EXCEPT`) at the top level. * The view's select list must not contain any aggregates, window functions or set-returning functions. An automatically updatable view may contain a mix of updatable and non-updatable columns. A column is updatable if it is a simple reference to an updatable column of the underlying base relation; otherwise the column is read-only, and an error will be raised if an `INSERT`, `UPDATE`, or `MERGE` statement attempts to assign a value to it. If the view is automatically updatable the system will convert any `INSERT`, `UPDATE`, `DELETE`, or `MERGE` statement on the view into the corresponding statement on the underlying base relation. `INSERT` statements that have an `ON CONFLICT UPDATE` clause are fully supported. If an automatically updatable view contains a `WHERE` condition, the condition restricts which rows of the base relation are available to be modified by `UPDATE`, `DELETE`, and `MERGE` statements on the view. However, an `UPDATE` or `MERGE` is allowed to change a row so that it no longer satisfies the `WHERE` condition, and thus is no longer visible through the view. Similarly, an `INSERT` or `MERGE` command can potentially insert base-relation rows that do not satisfy the `WHERE` condition and thus are not visible through the view (`ON CONFLICT UPDATE` may similarly affect an existing row not visible through the view). The `CHECK OPTION` may be used to prevent `INSERT`, `UPDATE`, and `MERGE` commands from creating such rows that are not visible through the view. If an automatically updatable view is marked with the `security_barrier` property then all the view's `WHERE` conditions (and any conditions using operators which are marked as `LEAKPROOF`) will always be evaluated before any conditions that a user of the view has added. See [Section 39.5](https://www.postgresql.org/docs/18/rules-privileges.html "39.5. Rules and Privileges") for full details. Note that, due to this, rows which are not ultimately returned (because they do not pass the user's `WHERE` conditions) may still end up being locked. `EXPLAIN` can be used to see which conditions are applied at the relation level (and therefore do not lock rows) and which are not. A more complex view that does not satisfy all these conditions is read-only by default: the system will not allow an `INSERT`, `UPDATE`, `DELETE`, or `MERGE` on the view. You can get the effect of an updatable view by creating `INSTEAD OF` triggers on the view, which must convert attempted inserts, etc. on the view into appropriate actions on other tables. For more information see [CREATE TRIGGER](https://www.postgresql.org/docs/18/sql-createtrigger.html "CREATE TRIGGER") . Another possibility is to create rules (see [CREATE RULE](https://www.postgresql.org/docs/18/sql-createrule.html "CREATE RULE") ), but in practice triggers are easier to understand and use correctly. Also note that `MERGE` is not supported on relations with rules. Note that the user performing the insert, update or delete on the view must have the corresponding insert, update or delete privilege on the view. In addition, by default, the view's owner must have the relevant privileges on the underlying base relations, whereas the user performing the update does not need any permissions on the underlying base relations (see [Section 39.5](https://www.postgresql.org/docs/18/rules-privileges.html "39.5. Rules and Privileges") ). However, if the view has `security_invoker` set to `true`, the user performing the update, rather than the view owner, must have the relevant privileges on the underlying base relations. Examples -------- Create a view consisting of all comedy films: CREATE VIEW comedies AS SELECT \* FROM films WHERE kind = 'Comedy'; This will create a view containing the columns that are in the `film` table at the time of view creation. Though `*` was used to create the view, columns added later to the table will not be part of the view. Create a view with `LOCAL CHECK OPTION`: CREATE VIEW universal\_comedies AS SELECT \* FROM comedies WHERE classification = 'U' WITH LOCAL CHECK OPTION; This will create a view based on the `comedies` view, showing only films with `kind = 'Comedy'` and `classification = 'U'`. Any attempt to `INSERT` or `UPDATE` a row in the view will be rejected if the new row doesn't have `classification = 'U'`, but the film `kind` will not be checked. Create a view with `CASCADED CHECK OPTION`: CREATE VIEW pg\_comedies AS SELECT \* FROM comedies WHERE classification = 'PG' WITH CASCADED CHECK OPTION; This will create a view that checks both the `kind` and `classification` of new rows. Create a view with a mix of updatable and non-updatable columns: CREATE VIEW comedies AS SELECT f.\*, country\_code\_to\_name(f.country\_code) AS country, (SELECT avg(r.rating) FROM user\_ratings r WHERE r.film\_id = f.id) AS avg\_rating FROM films f WHERE f.kind = 'Comedy'; This view will support `INSERT`, `UPDATE` and `DELETE`. All the columns from the `films` table will be updatable, whereas the computed columns `country` and `avg_rating` will be read-only. Create a recursive view consisting of the numbers from 1 to 100: CREATE RECURSIVE VIEW public.nums\_1\_100 (n) AS VALUES (1) UNION ALL SELECT n+1 FROM nums\_1\_100 WHERE n < 100; Notice that although the recursive view's name is schema-qualified in this `CREATE`, its internal self-reference is not schema-qualified. This is because the implicitly-created CTE's name cannot be schema-qualified. Compatibility ------------- `CREATE OR REPLACE VIEW` is a PostgreSQL language extension. So is the concept of a temporary view. The `WITH ( ... )` clause is an extension as well, as are security barrier views and security invoker views. See Also -------- [ALTER VIEW](https://www.postgresql.org/docs/18/sql-alterview.html "ALTER VIEW") , [DROP VIEW](https://www.postgresql.org/docs/18/sql-dropview.html "DROP VIEW") , [CREATE MATERIALIZED VIEW](https://www.postgresql.org/docs/18/sql-creatematerializedview.html "CREATE MATERIALIZED VIEW") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-createusermapping.html "CREATE USER MAPPING") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-deallocate.html "DEALLOCATE") | | CREATE USER MAPPING | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | DEALLOCATE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createview.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: dropuser November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/app-dropuser.html "PostgreSQL 18 - dropuser") ([18](https://www.postgresql.org/docs/18/app-dropuser.html "PostgreSQL 18 - dropuser") ) / [17](https://www.postgresql.org/docs/17/app-dropuser.html "PostgreSQL 17 - dropuser") / [16](https://www.postgresql.org/docs/16/app-dropuser.html "PostgreSQL 16 - dropuser") / [15](https://www.postgresql.org/docs/15/app-dropuser.html "PostgreSQL 15 - dropuser") / [14](https://www.postgresql.org/docs/14/app-dropuser.html "PostgreSQL 14 - dropuser") Development Versions: [devel](https://www.postgresql.org/docs/devel/app-dropuser.html "PostgreSQL devel - dropuser") Unsupported versions: [13](https://www.postgresql.org/docs/13/app-dropuser.html "PostgreSQL 13 - dropuser") / [12](https://www.postgresql.org/docs/12/app-dropuser.html "PostgreSQL 12 - dropuser") / [11](https://www.postgresql.org/docs/11/app-dropuser.html "PostgreSQL 11 - dropuser") / [10](https://www.postgresql.org/docs/10/app-dropuser.html "PostgreSQL 10 - dropuser") / [9.6](https://www.postgresql.org/docs/9.6/app-dropuser.html "PostgreSQL 9.6 - dropuser") / [9.5](https://www.postgresql.org/docs/9.5/app-dropuser.html "PostgreSQL 9.5 - dropuser") / [9.4](https://www.postgresql.org/docs/9.4/app-dropuser.html "PostgreSQL 9.4 - dropuser") / [9.3](https://www.postgresql.org/docs/9.3/app-dropuser.html "PostgreSQL 9.3 - dropuser") / [9.2](https://www.postgresql.org/docs/9.2/app-dropuser.html "PostgreSQL 9.2 - dropuser") / [9.1](https://www.postgresql.org/docs/9.1/app-dropuser.html "PostgreSQL 9.1 - dropuser") / [9.0](https://www.postgresql.org/docs/9.0/app-dropuser.html "PostgreSQL 9.0 - dropuser") / [8.4](https://www.postgresql.org/docs/8.4/app-dropuser.html "PostgreSQL 8.4 - dropuser") / [8.3](https://www.postgresql.org/docs/8.3/app-dropuser.html "PostgreSQL 8.3 - dropuser") / [8.2](https://www.postgresql.org/docs/8.2/app-dropuser.html "PostgreSQL 8.2 - dropuser") / [8.1](https://www.postgresql.org/docs/8.1/app-dropuser.html "PostgreSQL 8.1 - dropuser") / [8.0](https://www.postgresql.org/docs/8.0/app-dropuser.html "PostgreSQL 8.0 - dropuser") / [7.4](https://www.postgresql.org/docs/7.4/app-dropuser.html "PostgreSQL 7.4 - dropuser") / [7.3](https://www.postgresql.org/docs/7.3/app-dropuser.html "PostgreSQL 7.3 - dropuser") / [7.2](https://www.postgresql.org/docs/7.2/app-dropuser.html "PostgreSQL 7.2 - dropuser") / [7.1](https://www.postgresql.org/docs/7.1/app-dropuser.html "PostgreSQL 7.1 - dropuser") | dropuser | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/app-dropdb.html "dropdb") | [Up](https://www.postgresql.org/docs/18/reference-client.html "PostgreSQL Client Applications") | PostgreSQL Client Applications | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/app-ecpg.html "ecpg") | * * * dropuser -------- dropuser — remove a PostgreSQL user account Synopsis -------- `dropuser` \[_`connection-option`_...\] \[_`option`_...\] \[_`username`_\] Description ----------- dropuser removes an existing PostgreSQL user. Superusers can use this command to remove any role; otherwise, only non-superuser roles can be removed, and only by a user who possesses the `CREATEROLE` privilege and has been granted `ADMIN OPTION` on the target role. dropuser is a wrapper around the SQL command [`DROP ROLE`](https://www.postgresql.org/docs/18/sql-droprole.html "DROP ROLE") . There is no effective difference between dropping users via this utility and via other methods for accessing the server. Options ------- dropuser accepts the following command-line arguments: _`username`_ Specifies the name of the PostgreSQL user to be removed. You will be prompted for a name if none is specified on the command line and the `-i`/`--interactive` option is used. `-e` `--echo` Echo the commands that dropuser generates and sends to the server. `-i` `--interactive` Prompt for confirmation before actually removing the user, and prompt for the user name if none is specified on the command line. `-V` `--version` Print the dropuser version and exit. `--if-exists` Do not throw an error if the user does not exist. A notice is issued in this case. `-?` `--help` Show help about dropuser command line arguments, and exit. dropuser also accepts the following command-line arguments for connection parameters: ``-h _`host`_`` ``--host=_`host`_`` Specifies the host name of the machine on which the server is running. If the value begins with a slash, it is used as the directory for the Unix domain socket. ``-p _`port`_`` ``--port=_`port`_`` Specifies the TCP port or local Unix domain socket file extension on which the server is listening for connections. ``-U _`username`_`` ``--username=_`username`_`` User name to connect as (not the user name to drop). `-w` `--no-password` Never issue a password prompt. If the server requires password authentication and a password is not available by other means such as a `.pgpass` file, the connection attempt will fail. This option can be useful in batch jobs and scripts where no user is present to enter a password. `-W` `--password` Force dropuser to prompt for a password before connecting to a database. This option is never essential, since dropuser will automatically prompt for a password if the server demands password authentication. However, dropuser will waste a connection attempt finding out that the server wants a password. In some cases it is worth typing `-W` to avoid the extra connection attempt. Environment ----------- `PGHOST` `PGPORT` `PGUSER` Default connection parameters `PG_COLOR` Specifies whether to use color in diagnostic messages. Possible values are `always`, `auto` and `never`. This utility, like most other PostgreSQL utilities, also uses the environment variables supported by libpq (see [Section 32.15](https://www.postgresql.org/docs/18/libpq-envars.html "32.15. Environment Variables") ). Diagnostics ----------- In case of difficulty, see [DROP ROLE](https://www.postgresql.org/docs/18/sql-droprole.html "DROP ROLE") and [psql](https://www.postgresql.org/docs/18/app-psql.html "psql") for discussions of potential problems and error messages. The database server must be running at the targeted host. Also, any default connection settings and environment variables used by the libpq front-end library will apply. Examples -------- To remove user `joe` from the default database server: $ To remove user `joe` using the server on host `eden`, port 5000, with verification and a peek at the underlying command: $ See Also -------- [createuser](https://www.postgresql.org/docs/18/app-createuser.html "createuser") , [DROP ROLE](https://www.postgresql.org/docs/18/sql-droprole.html "DROP ROLE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/app-dropdb.html "dropdb") | [Up](https://www.postgresql.org/docs/18/reference-client.html "PostgreSQL Client Applications") | [Next](https://www.postgresql.org/docs/18/app-ecpg.html "ecpg") | | dropdb | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | ecpg | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/app-dropuser.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 4. SQL Syntax November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-syntax.html "PostgreSQL 18 - Chapter 4. SQL Syntax") ([18](https://www.postgresql.org/docs/18/sql-syntax.html "PostgreSQL 18 - Chapter 4. SQL Syntax") ) / [17](https://www.postgresql.org/docs/17/sql-syntax.html "PostgreSQL 17 - Chapter 4. SQL Syntax") / [16](https://www.postgresql.org/docs/16/sql-syntax.html "PostgreSQL 16 - Chapter 4. SQL Syntax") / [15](https://www.postgresql.org/docs/15/sql-syntax.html "PostgreSQL 15 - Chapter 4. SQL Syntax") / [14](https://www.postgresql.org/docs/14/sql-syntax.html "PostgreSQL 14 - Chapter 4. SQL Syntax") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-syntax.html "PostgreSQL devel - Chapter 4. SQL Syntax") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-syntax.html "PostgreSQL 13 - Chapter 4. SQL Syntax") / [12](https://www.postgresql.org/docs/12/sql-syntax.html "PostgreSQL 12 - Chapter 4. SQL Syntax") / [11](https://www.postgresql.org/docs/11/sql-syntax.html "PostgreSQL 11 - Chapter 4. SQL Syntax") / [10](https://www.postgresql.org/docs/10/sql-syntax.html "PostgreSQL 10 - Chapter 4. SQL Syntax") / [9.6](https://www.postgresql.org/docs/9.6/sql-syntax.html "PostgreSQL 9.6 - Chapter 4. SQL Syntax") / [9.5](https://www.postgresql.org/docs/9.5/sql-syntax.html "PostgreSQL 9.5 - Chapter 4. SQL Syntax") / [9.4](https://www.postgresql.org/docs/9.4/sql-syntax.html "PostgreSQL 9.4 - Chapter 4. SQL Syntax") / [9.3](https://www.postgresql.org/docs/9.3/sql-syntax.html "PostgreSQL 9.3 - Chapter 4. SQL Syntax") / [9.2](https://www.postgresql.org/docs/9.2/sql-syntax.html "PostgreSQL 9.2 - Chapter 4. SQL Syntax") / [9.1](https://www.postgresql.org/docs/9.1/sql-syntax.html "PostgreSQL 9.1 - Chapter 4. SQL Syntax") / [9.0](https://www.postgresql.org/docs/9.0/sql-syntax.html "PostgreSQL 9.0 - Chapter 4. SQL Syntax") / [8.4](https://www.postgresql.org/docs/8.4/sql-syntax.html "PostgreSQL 8.4 - Chapter 4. SQL Syntax") / [8.3](https://www.postgresql.org/docs/8.3/sql-syntax.html "PostgreSQL 8.3 - Chapter 4. SQL Syntax") / [8.2](https://www.postgresql.org/docs/8.2/sql-syntax.html "PostgreSQL 8.2 - Chapter 4. SQL Syntax") / [8.1](https://www.postgresql.org/docs/8.1/sql-syntax.html "PostgreSQL 8.1 - Chapter 4. SQL Syntax") / [8.0](https://www.postgresql.org/docs/8.0/sql-syntax.html "PostgreSQL 8.0 - Chapter 4. SQL Syntax") / [7.4](https://www.postgresql.org/docs/7.4/sql-syntax.html "PostgreSQL 7.4 - Chapter 4. SQL Syntax") / [7.3](https://www.postgresql.org/docs/7.3/sql-syntax.html "PostgreSQL 7.3 - Chapter 4. SQL Syntax") / [7.2](https://www.postgresql.org/docs/7.2/sql-syntax.html "PostgreSQL 7.2 - Chapter 4. SQL Syntax") / [7.1](https://www.postgresql.org/docs/7.1/sql-syntax.html "PostgreSQL 7.1 - Chapter 4. SQL Syntax") | Chapter 4. SQL Syntax | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql.html "Part II. The SQL Language") | [Up](https://www.postgresql.org/docs/18/sql.html "Part II. The SQL Language") | Part II. The SQL Language | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-syntax-lexical.html "4.1. Lexical Structure") | * * * Chapter 4. SQL Syntax --------------------- **Table of Contents** [4.1. Lexical Structure](https://www.postgresql.org/docs/18/sql-syntax-lexical.html) [4.1.1. Identifiers and Key Words](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS) [4.1.2. Constants](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS) [4.1.3. Operators](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-SYNTAX-OPERATORS) [4.1.4. Special Characters](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-SYNTAX-SPECIAL-CHARS) [4.1.5. Comments](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-SYNTAX-COMMENTS) [4.1.6. Operator Precedence](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-PRECEDENCE) [4.2. Value Expressions](https://www.postgresql.org/docs/18/sql-expressions.html) [4.2.1. Column References](https://www.postgresql.org/docs/18/sql-expressions.html#SQL-EXPRESSIONS-COLUMN-REFS) [4.2.2. Positional Parameters](https://www.postgresql.org/docs/18/sql-expressions.html#SQL-EXPRESSIONS-PARAMETERS-POSITIONAL) [4.2.3. Subscripts](https://www.postgresql.org/docs/18/sql-expressions.html#SQL-EXPRESSIONS-SUBSCRIPTS) [4.2.4. Field Selection](https://www.postgresql.org/docs/18/sql-expressions.html#FIELD-SELECTION) [4.2.5. Operator Invocations](https://www.postgresql.org/docs/18/sql-expressions.html#SQL-EXPRESSIONS-OPERATOR-CALLS) [4.2.6. Function Calls](https://www.postgresql.org/docs/18/sql-expressions.html#SQL-EXPRESSIONS-FUNCTION-CALLS) [4.2.7. Aggregate Expressions](https://www.postgresql.org/docs/18/sql-expressions.html#SYNTAX-AGGREGATES) [4.2.8. Window Function Calls](https://www.postgresql.org/docs/18/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS) [4.2.9. Type Casts](https://www.postgresql.org/docs/18/sql-expressions.html#SQL-SYNTAX-TYPE-CASTS) [4.2.10. Collation Expressions](https://www.postgresql.org/docs/18/sql-expressions.html#SQL-SYNTAX-COLLATE-EXPRS) [4.2.11. Scalar Subqueries](https://www.postgresql.org/docs/18/sql-expressions.html#SQL-SYNTAX-SCALAR-SUBQUERIES) [4.2.12. Array Constructors](https://www.postgresql.org/docs/18/sql-expressions.html#SQL-SYNTAX-ARRAY-CONSTRUCTORS) [4.2.13. Row Constructors](https://www.postgresql.org/docs/18/sql-expressions.html#SQL-SYNTAX-ROW-CONSTRUCTORS) [4.2.14. Expression Evaluation Rules](https://www.postgresql.org/docs/18/sql-expressions.html#SYNTAX-EXPRESS-EVAL) [4.3. Calling Functions](https://www.postgresql.org/docs/18/sql-syntax-calling-funcs.html) [4.3.1. Using Positional Notation](https://www.postgresql.org/docs/18/sql-syntax-calling-funcs.html#SQL-SYNTAX-CALLING-FUNCS-POSITIONAL) [4.3.2. Using Named Notation](https://www.postgresql.org/docs/18/sql-syntax-calling-funcs.html#SQL-SYNTAX-CALLING-FUNCS-NAMED) [4.3.3. Using Mixed Notation](https://www.postgresql.org/docs/18/sql-syntax-calling-funcs.html#SQL-SYNTAX-CALLING-FUNCS-MIXED) This chapter describes the syntax of SQL. It forms the foundation for understanding the following chapters which will go into detail about how SQL commands are applied to define and modify data. We also advise users who are already familiar with SQL to read this chapter carefully because it contains several rules and concepts that are implemented inconsistently among SQL databases or that are specific to PostgreSQL. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql.html "Part II. The SQL Language") | [Up](https://www.postgresql.org/docs/18/sql.html "Part II. The SQL Language") | [Next](https://www.postgresql.org/docs/18/sql-syntax-lexical.html "4.1. Lexical Structure") | | Part II. The SQL Language | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 4.1. Lexical Structure | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-syntax.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: CREATE OPERATOR November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createoperator.html "PostgreSQL 18 - CREATE OPERATOR") ([18](https://www.postgresql.org/docs/18/sql-createoperator.html "PostgreSQL 18 - CREATE OPERATOR") ) / [17](https://www.postgresql.org/docs/17/sql-createoperator.html "PostgreSQL 17 - CREATE OPERATOR") / [16](https://www.postgresql.org/docs/16/sql-createoperator.html "PostgreSQL 16 - CREATE OPERATOR") / [15](https://www.postgresql.org/docs/15/sql-createoperator.html "PostgreSQL 15 - CREATE OPERATOR") / [14](https://www.postgresql.org/docs/14/sql-createoperator.html "PostgreSQL 14 - CREATE OPERATOR") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createoperator.html "PostgreSQL devel - CREATE OPERATOR") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createoperator.html "PostgreSQL 13 - CREATE OPERATOR") / [12](https://www.postgresql.org/docs/12/sql-createoperator.html "PostgreSQL 12 - CREATE OPERATOR") / [11](https://www.postgresql.org/docs/11/sql-createoperator.html "PostgreSQL 11 - CREATE OPERATOR") / [10](https://www.postgresql.org/docs/10/sql-createoperator.html "PostgreSQL 10 - CREATE OPERATOR") / [9.6](https://www.postgresql.org/docs/9.6/sql-createoperator.html "PostgreSQL 9.6 - CREATE OPERATOR") / [9.5](https://www.postgresql.org/docs/9.5/sql-createoperator.html "PostgreSQL 9.5 - CREATE OPERATOR") / [9.4](https://www.postgresql.org/docs/9.4/sql-createoperator.html "PostgreSQL 9.4 - CREATE OPERATOR") / [9.3](https://www.postgresql.org/docs/9.3/sql-createoperator.html "PostgreSQL 9.3 - CREATE OPERATOR") / [9.2](https://www.postgresql.org/docs/9.2/sql-createoperator.html "PostgreSQL 9.2 - CREATE OPERATOR") / [9.1](https://www.postgresql.org/docs/9.1/sql-createoperator.html "PostgreSQL 9.1 - CREATE OPERATOR") / [9.0](https://www.postgresql.org/docs/9.0/sql-createoperator.html "PostgreSQL 9.0 - CREATE OPERATOR") / [8.4](https://www.postgresql.org/docs/8.4/sql-createoperator.html "PostgreSQL 8.4 - CREATE OPERATOR") / [8.3](https://www.postgresql.org/docs/8.3/sql-createoperator.html "PostgreSQL 8.3 - CREATE OPERATOR") / [8.2](https://www.postgresql.org/docs/8.2/sql-createoperator.html "PostgreSQL 8.2 - CREATE OPERATOR") / [8.1](https://www.postgresql.org/docs/8.1/sql-createoperator.html "PostgreSQL 8.1 - CREATE OPERATOR") / [8.0](https://www.postgresql.org/docs/8.0/sql-createoperator.html "PostgreSQL 8.0 - CREATE OPERATOR") / [7.4](https://www.postgresql.org/docs/7.4/sql-createoperator.html "PostgreSQL 7.4 - CREATE OPERATOR") / [7.3](https://www.postgresql.org/docs/7.3/sql-createoperator.html "PostgreSQL 7.3 - CREATE OPERATOR") / [7.2](https://www.postgresql.org/docs/7.2/sql-createoperator.html "PostgreSQL 7.2 - CREATE OPERATOR") / [7.1](https://www.postgresql.org/docs/7.1/sql-createoperator.html "PostgreSQL 7.1 - CREATE OPERATOR") | CREATE OPERATOR | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-creatematerializedview.html "CREATE MATERIALIZED VIEW") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/sql-createopclass.html "CREATE OPERATOR CLASS") | * * * CREATE OPERATOR --------------- CREATE OPERATOR — define a new operator Synopsis -------- CREATE OPERATOR _`name`_ ( {FUNCTION|PROCEDURE} = _`function_name`_ \[, LEFTARG = _`left_type`_ \] \[, RIGHTARG = _`right_type`_ \] \[, COMMUTATOR = _`com_op`_ \] \[, NEGATOR = _`neg_op`_ \] \[, RESTRICT = _`res_proc`_ \] \[, JOIN = _`join_proc`_ \] \[, HASHES \] \[, MERGES \] ) Description ----------- `CREATE OPERATOR` defines a new operator, _`name`_. The user who defines an operator becomes its owner. If a schema name is given then the operator is created in the specified schema. Otherwise it is created in the current schema. The operator name is a sequence of up to `NAMEDATALEN`\-1 (63 by default) characters from the following list: + - \* / < > = ~ ! @ # % ^ & | \` ? There are a few restrictions on your choice of name: * `--` and `/*` cannot appear anywhere in an operator name, since they will be taken as the start of a comment. * A multicharacter operator name cannot end in `+` or `-`, unless the name also contains at least one of these characters: ~ ! @ # % ^ & | \` ? For example, `@-` is an allowed operator name, but `*-` is not. This restriction allows PostgreSQL to parse SQL-compliant commands without requiring spaces between tokens. * The symbol `=>` is reserved by the SQL grammar, so it cannot be used as an operator name. The operator `!=` is mapped to `<>` on input, so these two names are always equivalent. For binary operators, both `LEFTARG` and `RIGHTARG` must be defined. For prefix operators only `RIGHTARG` should be defined. The _`function_name`_ function must have been previously defined using `CREATE FUNCTION` and must be defined to accept the correct number of arguments (either one or two) of the indicated types. In the syntax of `CREATE OPERATOR`, the keywords `FUNCTION` and `PROCEDURE` are equivalent, but the referenced function must in any case be a function, not a procedure. The use of the keyword `PROCEDURE` here is historical and deprecated. The other clauses specify optional operator optimization attributes. Their meaning is detailed in [Section 36.15](https://www.postgresql.org/docs/18/xoper-optimization.html "36.15. Operator Optimization Information") . To be able to create an operator, you must have `USAGE` privilege on the argument types and the return type, as well as `EXECUTE` privilege on the underlying function. If a commutator or negator operator is specified, you must own those operators. Parameters ---------- _`name`_ The name of the operator to be defined. See above for allowable characters. The name can be schema-qualified, for example `CREATE OPERATOR myschema.+ (...)`. If not, then the operator is created in the current schema. Two operators in the same schema can have the same name if they operate on different data types. This is called _overloading_. _`function_name`_ The function used to implement this operator. _`left_type`_ The data type of the operator's left operand, if any. This option would be omitted for a prefix operator. _`right_type`_ The data type of the operator's right operand. _`com_op`_ The commutator of this operator. _`neg_op`_ The negator of this operator. _`res_proc`_ The restriction selectivity estimator function for this operator. _`join_proc`_ The join selectivity estimator function for this operator. `HASHES` Indicates this operator can support a hash join. `MERGES` Indicates this operator can support a merge join. To give a schema-qualified operator name in _`com_op`_ or the other optional arguments, use the `OPERATOR()` syntax, for example: COMMUTATOR = OPERATOR(myschema.===) , Notes ----- Refer to [Section 36.14](https://www.postgresql.org/docs/18/xoper.html "36.14. User-Defined Operators") and [Section 36.15](https://www.postgresql.org/docs/18/xoper-optimization.html "36.15. Operator Optimization Information") for further information. When you are defining a self-commutative operator, you just do it. When you are defining a pair of commutative operators, things are a little trickier: how can the first one to be defined refer to the other one, which you haven't defined yet? There are three solutions to this problem: * One way is to omit the `COMMUTATOR` clause in the first operator that you define, and then provide one in the second operator's definition. Since PostgreSQL knows that commutative operators come in pairs, when it sees the second definition it will automatically go back and fill in the missing `COMMUTATOR` clause in the first definition. * Another, more straightforward way is just to include `COMMUTATOR` clauses in both definitions. When PostgreSQL processes the first definition and realizes that `COMMUTATOR` refers to a nonexistent operator, the system will make a dummy entry for that operator in the system catalog. This dummy entry will have valid data only for the operator name, left and right operand types, and owner, since that's all that PostgreSQL can deduce at this point. The first operator's catalog entry will link to this dummy entry. Later, when you define the second operator, the system updates the dummy entry with the additional information from the second definition. If you try to use the dummy operator before it's been filled in, you'll just get an error message. * Alternatively, both operators can be defined without `COMMUTATOR` clauses and then `ALTER OPERATOR` can be used to set their commutator links. It's sufficient to `ALTER` either one of the pair. In all three cases, you must own both operators in order to mark them as commutators. Pairs of negator operators can be defined using the same methods as for commutator pairs. It is not possible to specify an operator's lexical precedence in `CREATE OPERATOR`, because the parser's precedence behavior is hard-wired. See [Section 4.1.6](https://www.postgresql.org/docs/18/sql-syntax-lexical.html#SQL-PRECEDENCE "4.1.6. Operator Precedence") for precedence details. The obsolete options `SORT1`, `SORT2`, `LTCMP`, and `GTCMP` were formerly used to specify the names of sort operators associated with a merge-joinable operator. This is no longer necessary, since information about associated operators is found by looking at B-tree operator families instead. If one of these options is given, it is ignored except for implicitly setting `MERGES` true. Use [`DROP OPERATOR`](https://www.postgresql.org/docs/18/sql-dropoperator.html "DROP OPERATOR") to delete user-defined operators from a database. Use [`ALTER OPERATOR`](https://www.postgresql.org/docs/18/sql-alteroperator.html "ALTER OPERATOR") to modify operators in a database. Examples -------- The following command defines a new operator, area-equality, for the data type `box`: CREATE OPERATOR === ( LEFTARG = box, RIGHTARG = box, FUNCTION = area\_equal\_function, COMMUTATOR = ===, NEGATOR = !==, RESTRICT = area\_restriction\_function, JOIN = area\_join\_function, HASHES, MERGES ); Compatibility ------------- `CREATE OPERATOR` is a PostgreSQL extension. There are no provisions for user-defined operators in the SQL standard. See Also -------- [ALTER OPERATOR](https://www.postgresql.org/docs/18/sql-alteroperator.html "ALTER OPERATOR") , [CREATE OPERATOR CLASS](https://www.postgresql.org/docs/18/sql-createopclass.html "CREATE OPERATOR CLASS") , [DROP OPERATOR](https://www.postgresql.org/docs/18/sql-dropoperator.html "DROP OPERATOR") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/sql-creatematerializedview.html "CREATE MATERIALIZED VIEW") | [Up](https://www.postgresql.org/docs/18/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/18/sql-createopclass.html "CREATE OPERATOR CLASS") | | CREATE MATERIALIZED VIEW | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | CREATE OPERATOR CLASS | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createoperator.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 9.3: Date/Time Input Interpretation November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 9.3](https://www.postgresql.org/docs/9.3/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/datetime-input-rules.html "PostgreSQL 18 - Date/Time Input Interpretation") ([18](https://www.postgresql.org/docs/18/datetime-input-rules.html "PostgreSQL 18 - Date/Time Input Interpretation") ) / [17](https://www.postgresql.org/docs/17/datetime-input-rules.html "PostgreSQL 17 - Date/Time Input Interpretation") / [16](https://www.postgresql.org/docs/16/datetime-input-rules.html "PostgreSQL 16 - Date/Time Input Interpretation") / [15](https://www.postgresql.org/docs/15/datetime-input-rules.html "PostgreSQL 15 - Date/Time Input Interpretation") / [14](https://www.postgresql.org/docs/14/datetime-input-rules.html "PostgreSQL 14 - Date/Time Input Interpretation") Development Versions: [devel](https://www.postgresql.org/docs/devel/datetime-input-rules.html "PostgreSQL devel - Date/Time Input Interpretation") Unsupported versions: [13](https://www.postgresql.org/docs/13/datetime-input-rules.html "PostgreSQL 13 - Date/Time Input Interpretation") / [12](https://www.postgresql.org/docs/12/datetime-input-rules.html "PostgreSQL 12 - Date/Time Input Interpretation") / [11](https://www.postgresql.org/docs/11/datetime-input-rules.html "PostgreSQL 11 - Date/Time Input Interpretation") / [10](https://www.postgresql.org/docs/10/datetime-input-rules.html "PostgreSQL 10 - Date/Time Input Interpretation") / [9.6](https://www.postgresql.org/docs/9.6/datetime-input-rules.html "PostgreSQL 9.6 - Date/Time Input Interpretation") / [9.5](https://www.postgresql.org/docs/9.5/datetime-input-rules.html "PostgreSQL 9.5 - Date/Time Input Interpretation") / [9.4](https://www.postgresql.org/docs/9.4/datetime-input-rules.html "PostgreSQL 9.4 - Date/Time Input Interpretation") / [9.3](https://www.postgresql.org/docs/9.3/datetime-input-rules.html "PostgreSQL 9.3 - Date/Time Input Interpretation") / [9.2](https://www.postgresql.org/docs/9.2/datetime-input-rules.html "PostgreSQL 9.2 - Date/Time Input Interpretation") / [9.1](https://www.postgresql.org/docs/9.1/datetime-input-rules.html "PostgreSQL 9.1 - Date/Time Input Interpretation") / [9.0](https://www.postgresql.org/docs/9.0/datetime-input-rules.html "PostgreSQL 9.0 - Date/Time Input Interpretation") / [8.4](https://www.postgresql.org/docs/8.4/datetime-input-rules.html "PostgreSQL 8.4 - Date/Time Input Interpretation") / [8.3](https://www.postgresql.org/docs/8.3/datetime-input-rules.html "PostgreSQL 8.3 - Date/Time Input Interpretation") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/datetime-input-rules.html "PostgreSQL - Date/Time Input Interpretation") version, or one of the other supported versions listed above instead. | [PostgreSQL 9.3.25 Documentation](https://www.postgresql.org/docs/9.3/index.html) | | | | | | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/datetime-appendix.html "Date/Time Support") | [Up](https://www.postgresql.org/docs/9.3/datetime-appendix.html) | Appendix B. Date/Time Support | [Next](https://www.postgresql.org/docs/9.3/datetime-keywords.html "Date/Time Key Words") | * * * B.1. Date/Time Input Interpretation =================================== The date/time type inputs are all decoded using the following procedure. 1. Break the input string into tokens and categorize each token as a string, time, time zone, or number. 1. If the numeric token contains a colon (:), this is a time string. Include all subsequent digits and colons. 2. If the numeric token contains a dash (\-), slash (/), or two or more dots (.), this is a date string which might have a text month. If a date token has already been seen, it is instead interpreted as a time zone name (e.g., America/New\_York). 3. If the token is numeric only, then it is either a single field or an ISO 8601 concatenated date (e.g., 19990113 for January 13, 1999) or time (e.g., 141516 for 14:15:16). 4. If the token starts with a plus (+) or minus (\-), then it is either a numeric time zone or a special field. 2. If the token is a text string, match up with possible strings: 1. Do a binary-search table lookup for the token as a time zone abbreviation. 2. If not found, do a similar binary-search table lookup to match the token as either a special string (e.g., today), day (e.g., Thursday), month (e.g., January), or noise word (e.g., at, on). 3. If still not found, throw an error. 3. When the token is a number or number field: 1. If there are eight or six digits, and if no other date fields have been previously read, then interpret as a "concatenated date" (e.g., 19990118 or 990118). The interpretation is YYYYMMDD or YYMMDD. 2. If the token is three digits and a year has already been read, then interpret as day of year. 3. If four or six digits and a year has already been read, then interpret as a time (HHMM or HHMMSS). 4. If three or more digits and no date fields have yet been found, interpret as a year (this forces yy-mm-dd ordering of the remaining date fields). 5. Otherwise the date field ordering is assumed to follow the DateStyle setting: mm-dd-yy, dd-mm-yy, or yy-mm-dd. Throw an error if a month or day field is found to be out of range. 4. If BC has been specified, negate the year and add one for internal storage. (There is no year zero in the Gregorian calendar, so numerically 1 BC becomes year zero.) 5. If BC was not specified, and if the year field was two digits in length, then adjust the year to four digits. If the field is less than 70, then add 2000, otherwise add 1900. > **Tip:** Gregorian years AD 1-99 can be entered by using 4 digits with leading zeros (e.g., 0099 is AD 99). * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/datetime-appendix.html) | [Home](https://www.postgresql.org/docs/9.3/index.html) | [Next](https://www.postgresql.org/docs/9.3/datetime-keywords.html) | | Date/Time Support | [Up](https://www.postgresql.org/docs/9.3/datetime-appendix.html) | Date/Time Key Words | --- # PostgreSQL: Documentation: 18: CREATE FUNCTION November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createfunction.html "PostgreSQL 18 - CREATE FUNCTION") ([18](https://www.postgresql.org/docs/18/sql-createfunction.html "PostgreSQL 18 - CREATE FUNCTION") ) / [17](https://www.postgresql.org/docs/17/sql-createfunction.html "PostgreSQL 17 - CREATE FUNCTION") / [16](https://www.postgresql.org/docs/16/sql-createfunction.html "PostgreSQL 16 - CREATE FUNCTION") / [15](https://www.postgresql.org/docs/15/sql-createfunction.html "PostgreSQL 15 - CREATE FUNCTION") / [14](https://www.postgresql.org/docs/14/sql-createfunction.html "PostgreSQL 14 - CREATE FUNCTION") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createfunction.html "PostgreSQL devel - CREATE FUNCTION") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createfunction.html "PostgreSQL 13 - CREATE FUNCTION") / [12](https://www.postgresql.org/docs/12/sql-createfunction.html "PostgreSQL 12 - CREATE FUNCTION") / [11](https://www.postgresql.org/docs/11/sql-createfunction.html "PostgreSQL 11 - CREATE FUNCTION") / [10](https://www.postgresql.org/docs/10/sql-createfunction.html "PostgreSQL 10 - CREATE FUNCTION") / [9.6](https://www.postgresql.org/docs/9.6/sql-createfunction.html "PostgreSQL 9.6 - CREATE FUNCTION") / [9.5](https://www.postgresql.org/docs/9.5/sql-createfunction.html "PostgreSQL 9.5 - CREATE FUNCTION") / [9.4](https://www.postgresql.org/docs/9.4/sql-createfunction.html "PostgreSQL 9.4 - CREATE FUNCTION") / [9.3](https://www.postgresql.org/docs/9.3/sql-createfunction.html "PostgreSQL 9.3 - CREATE FUNCTION") / [9.2](https://www.postgresql.org/docs/9.2/sql-createfunction.html "PostgreSQL 9.2 - CREATE FUNCTION") / [9.1](https://www.postgresql.org/docs/9.1/sql-createfunction.html "PostgreSQL 9.1 - CREATE FUNCTION") / [9.0](https://www.postgresql.org/docs/9.0/sql-createfunction.html "PostgreSQL 9.0 - CREATE FUNCTION") / [8.4](https://www.postgresql.org/docs/8.4/sql-createfunction.html "PostgreSQL 8.4 - CREATE FUNCTION") / [8.3](https://www.postgresql.org/docs/8.3/sql-createfunction.html "PostgreSQL 8.3 - CREATE FUNCTION") / [8.2](https://www.postgresql.org/docs/8.2/sql-createfunction.html "PostgreSQL 8.2 - CREATE FUNCTION") / [8.1](https://www.postgresql.org/docs/8.1/sql-createfunction.html "PostgreSQL 8.1 - CREATE FUNCTION") / [8.0](https://www.postgresql.org/docs/8.0/sql-createfunction.html "PostgreSQL 8.0 - CREATE FUNCTION") / [7.4](https://www.postgresql.org/docs/7.4/sql-createfunction.html "PostgreSQL 7.4 - CREATE FUNCTION") / [7.3](https://www.postgresql.org/docs/7.3/sql-createfunction.html "PostgreSQL 7.3 - CREATE FUNCTION") / [7.2](https://www.postgresql.org/docs/7.2/sql-createfunction.html "PostgreSQL 7.2 - CREATE FUNCTION") / [7.1](https://www.postgresql.org/docs/7.1/sql-createfunction.html "PostgreSQL 7.1 - CREATE FUNCTION") | CREATE FUNCTION | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createforeigntable.html "CREATE FOREIGN TABLE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-creategroup.html "CREATE GROUP") | * * * CREATE FUNCTION --------------- CREATE FUNCTION — define a new function Synopsis -------- CREATE \[ OR REPLACE \] FUNCTION _`name`_ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[ { DEFAULT | = } _`default_expr`_ \] \[, ...\] \] ) \[ RETURNS _`rettype`_\ | RETURNS TABLE ( _`column_name`_ _`column_type`_ \[, ...\] ) \] { LANGUAGE _`lang_name`_ | TRANSFORM { FOR TYPE _`type_name`_ } \[, ... \] | WINDOW | { IMMUTABLE | STABLE | VOLATILE } | \[ NOT \] LEAKPROOF | { CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT } | { \[ EXTERNAL \] SECURITY INVOKER | \[ EXTERNAL \] SECURITY DEFINER } | PARALLEL { UNSAFE | RESTRICTED | SAFE } | COST _`execution_cost`_ | ROWS _`result_rows`_ | SUPPORT _`support_function`_ | SET _`configuration_parameter`_ { TO _`value`_ | = _`value`_ | FROM CURRENT } | AS '_`definition`_' | AS '_`obj_file`_', '_`link_symbol`_' | _`sql_body`_ } ... Description ----------- `CREATE FUNCTION` defines a new function. `CREATE OR REPLACE FUNCTION` will either create a new function, or replace an existing definition. To be able to define a function, the user must have the `USAGE` privilege on the language. If a schema name is included, then the function is created in the specified schema. Otherwise it is created in the current schema. The name of the new function must not match any existing function or procedure with the same input argument types in the same schema. However, functions and procedures of different argument types can share a name (this is called _overloading_). To replace the current definition of an existing function, use `CREATE OR REPLACE FUNCTION`. It is not possible to change the name or argument types of a function this way (if you tried, you would actually be creating a new, distinct function). Also, `CREATE OR REPLACE FUNCTION` will not let you change the return type of an existing function. To do that, you must drop and recreate the function. (When using `OUT` parameters, that means you cannot change the types of any `OUT` parameters except by dropping the function.) When `CREATE OR REPLACE FUNCTION` is used to replace an existing function, the ownership and permissions of the function do not change. All other function properties are assigned the values specified or implied in the command. You must own the function to replace it (this includes being a member of the owning role). If you drop and then recreate a function, the new function is not the same entity as the old; you will have to drop existing rules, views, triggers, etc. that refer to the old function. Use `CREATE OR REPLACE FUNCTION` to change a function definition without breaking objects that refer to the function. Also, `ALTER FUNCTION` can be used to change most of the auxiliary properties of an existing function. The user that creates the function becomes the owner of the function. To be able to create a function, you must have `USAGE` privilege on the argument types and the return type. Refer to [Section 36.3](https://www.postgresql.org/docs/current/xfunc.html "36.3. User-Defined Functions") for further information on writing functions. Parameters ---------- _`name`_ The name (optionally schema-qualified) of the function to create. _`argmode`_ The mode of an argument: `IN`, `OUT`, `INOUT`, or `VARIADIC`. If omitted, the default is `IN`. Only `OUT` arguments can follow a `VARIADIC` one. Also, `OUT` and `INOUT` arguments cannot be used together with the `RETURNS TABLE` notation. _`argname`_ The name of an argument. Some languages (including SQL and PL/pgSQL) let you use the name in the function body. For other languages the name of an input argument is just extra documentation, so far as the function itself is concerned; but you can use input argument names when calling a function to improve readability (see [Section 4.3](https://www.postgresql.org/docs/current/sql-syntax-calling-funcs.html "4.3. Calling Functions") ). In any case, the name of an output argument is significant, because it defines the column name in the result row type. (If you omit the name for an output argument, the system will choose a default column name.) _`argtype`_ The data type(s) of the function's arguments (optionally schema-qualified), if any. The argument types can be base, composite, or domain types, or can reference the type of a table column. Depending on the implementation language it might also be allowed to specify “pseudo-types” such as `cstring`. Pseudo-types indicate that the actual argument type is either incompletely specified, or outside the set of ordinary SQL data types. The type of a column is referenced by writing ``_`table_name`_._`column_name`_%TYPE``. Using this feature can sometimes help make a function independent of changes to the definition of a table. _`default_expr`_ An expression to be used as default value if the parameter is not specified. The expression has to be coercible to the argument type of the parameter. Only input (including `INOUT`) parameters can have a default value. All input parameters following a parameter with a default value must have default values as well. _`rettype`_ The return data type (optionally schema-qualified). The return type can be a base, composite, or domain type, or can reference the type of a table column. Depending on the implementation language it might also be allowed to specify “pseudo-types” such as `cstring`. If the function is not supposed to return a value, specify `void` as the return type. When there are `OUT` or `INOUT` parameters, the `RETURNS` clause can be omitted. If present, it must agree with the result type implied by the output parameters: `RECORD` if there are multiple output parameters, or the same type as the single output parameter. The `SETOF` modifier indicates that the function will return a set of items, rather than a single item. The type of a column is referenced by writing ``_`table_name`_._`column_name`_%TYPE``. _`column_name`_ The name of an output column in the `RETURNS TABLE` syntax. This is effectively another way of declaring a named `OUT` parameter, except that `RETURNS TABLE` also implies `RETURNS SETOF`. _`column_type`_ The data type of an output column in the `RETURNS TABLE` syntax. _`lang_name`_ The name of the language that the function is implemented in. It can be `sql`, `c`, `internal`, or the name of a user-defined procedural language, e.g., `plpgsql`. The default is `sql` if _`sql_body`_ is specified. Enclosing the name in single quotes is deprecated and requires matching case. ``TRANSFORM { FOR TYPE _`type_name`_ } [, ... ] }`` Lists which transforms a call to the function should apply. Transforms convert between SQL types and language-specific data types; see [CREATE TRANSFORM](https://www.postgresql.org/docs/current/sql-createtransform.html "CREATE TRANSFORM") . Procedural language implementations usually have hardcoded knowledge of the built-in types, so those don't need to be listed here. If a procedural language implementation does not know how to handle a type and no transform is supplied, it will fall back to a default behavior for converting data types, but this depends on the implementation. `WINDOW` `WINDOW` indicates that the function is a _window function_ rather than a plain function. This is currently only useful for functions written in C. The `WINDOW` attribute cannot be changed when replacing an existing function definition. `IMMUTABLE` `STABLE` `VOLATILE` These attributes inform the query optimizer about the behavior of the function. At most one choice can be specified. If none of these appear, `VOLATILE` is the default assumption. `IMMUTABLE` indicates that the function cannot modify the database and always returns the same result when given the same argument values; that is, it does not do database lookups or otherwise use information not directly present in its argument list. If this option is given, any call of the function with all-constant arguments can be immediately replaced with the function value. `STABLE` indicates that the function cannot modify the database, and that within a single table scan it will consistently return the same result for the same argument values, but that its result could change across SQL statements. This is the appropriate selection for functions whose results depend on database lookups, parameter variables (such as the current time zone), etc. (It is inappropriate for `AFTER` triggers that wish to query rows modified by the current command.) Also note that the `current_timestamp` family of functions qualify as stable, since their values do not change within a transaction. `VOLATILE` indicates that the function value can change even within a single table scan, so no optimizations can be made. Relatively few database functions are volatile in this sense; some examples are `random()`, `currval()`, `timeofday()`. But note that any function that has side-effects must be classified volatile, even if its result is quite predictable, to prevent calls from being optimized away; an example is `setval()`. For additional details see [Section 36.7](https://www.postgresql.org/docs/current/xfunc-volatility.html "36.7. Function Volatility Categories") . `LEAKPROOF` `LEAKPROOF` indicates that the function has no side effects. It reveals no information about its arguments other than by its return value. For example, a function which throws an error message for some argument values but not others, or which includes the argument values in any error message, is not leakproof. This affects how the system executes queries against views created with the `security_barrier` option or tables with row level security enabled. The system will enforce conditions from security policies and security barrier views before any user-supplied conditions from the query itself that contain non-leakproof functions, in order to prevent the inadvertent exposure of data. Functions and operators marked as leakproof are assumed to be trustworthy, and may be executed before conditions from security policies and security barrier views. In addition, functions which do not take arguments or which are not passed any arguments from the security barrier view or table do not have to be marked as leakproof to be executed before security conditions. See [CREATE VIEW](https://www.postgresql.org/docs/current/sql-createview.html "CREATE VIEW") and [Section 39.5](https://www.postgresql.org/docs/current/rules-privileges.html "39.5. Rules and Privileges") . This option can only be set by the superuser. `CALLED ON NULL INPUT` `RETURNS NULL ON NULL INPUT` `STRICT` `CALLED ON NULL INPUT` (the default) indicates that the function will be called normally when some of its arguments are null. It is then the function author's responsibility to check for null values if necessary and respond appropriately. `RETURNS NULL ON NULL INPUT` or `STRICT` indicates that the function always returns null whenever any of its arguments are null. If this parameter is specified, the function is not executed when there are null arguments; instead a null result is assumed automatically. `[EXTERNAL] SECURITY INVOKER` `[EXTERNAL] SECURITY DEFINER` `SECURITY INVOKER` indicates that the function is to be executed with the privileges of the user that calls it. That is the default. `SECURITY DEFINER` specifies that the function is to be executed with the privileges of the user that owns it. For information on how to write `SECURITY DEFINER` functions safely, [see below](https://www.postgresql.org/docs/current/sql-createfunction.html#SQL-CREATEFUNCTION-SECURITY "Writing SECURITY DEFINER Functions Safely") . The key word `EXTERNAL` is allowed for SQL conformance, but it is optional since, unlike in SQL, this feature applies to all functions not only external ones. `PARALLEL` `PARALLEL UNSAFE` indicates that the function can't be executed in parallel mode; the presence of such a function in an SQL statement forces a serial execution plan. This is the default. `PARALLEL RESTRICTED` indicates that the function can be executed in parallel mode, but only in the parallel group leader process. `PARALLEL SAFE` indicates that the function is safe to run in parallel mode without restriction, including in parallel worker processes. Functions should be labeled parallel unsafe if they modify any database state, change the transaction state (other than by using a subtransaction for error recovery), access sequences (e.g., by calling `currval`) or make persistent changes to settings. They should be labeled parallel restricted if they access temporary tables, client connection state, cursors, prepared statements, or miscellaneous backend-local state which the system cannot synchronize in parallel mode (e.g., `setseed` cannot be executed other than by the group leader because a change made by another process would not be reflected in the leader). In general, if a function is labeled as being safe when it is restricted or unsafe, or if it is labeled as being restricted when it is in fact unsafe, it may throw errors or produce wrong answers when used in a parallel query. C-language functions could in theory exhibit totally undefined behavior if mislabeled, since there is no way for the system to protect itself against arbitrary C code, but in most likely cases the result will be no worse than for any other function. If in doubt, functions should be labeled as `UNSAFE`, which is the default. `COST` _`execution_cost`_ A positive number giving the estimated execution cost for the function, in units of [cpu\_operator\_cost](https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-CPU-OPERATOR-COST) . If the function returns a set, this is the cost per returned row. If the cost is not specified, 1 unit is assumed for C-language and internal functions, and 100 units for functions in all other languages. Larger values cause the planner to try to avoid evaluating the function more often than necessary. `ROWS` _`result_rows`_ A positive number giving the estimated number of rows that the planner should expect the function to return. This is only allowed when the function is declared to return a set. The default assumption is 1000 rows. `SUPPORT` _`support_function`_ The name (optionally schema-qualified) of a _planner support function_ to use for this function. See [Section 36.11](https://www.postgresql.org/docs/current/xfunc-optimization.html "36.11. Function Optimization Information") for details. You must be superuser to use this option. _`configuration_parameter`_ _`value`_ The `SET` clause causes the specified configuration parameter to be set to the specified value when the function is entered, and then restored to its prior value when the function exits. `SET FROM CURRENT` saves the value of the parameter that is current when `CREATE FUNCTION` is executed as the value to be applied when the function is entered. If a `SET` clause is attached to a function, then the effects of a `SET LOCAL` command executed inside the function for the same variable are restricted to the function: the configuration parameter's prior value is still restored at function exit. However, an ordinary `SET` command (without `LOCAL`) overrides the `SET` clause, much as it would do for a previous `SET LOCAL` command: the effects of such a command will persist after function exit, unless the current transaction is rolled back. See [SET](https://www.postgresql.org/docs/current/sql-set.html "SET") and [Chapter 19](https://www.postgresql.org/docs/current/runtime-config.html "Chapter 19. Server Configuration") for more information about allowed parameter names and values. _`definition`_ A string constant defining the function; the meaning depends on the language. It can be an internal function name, the path to an object file, an SQL command, or text in a procedural language. It is often helpful to use dollar quoting (see [Section 4.1.2.4](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING "4.1.2.4. Dollar-Quoted String Constants") ) to write the function definition string, rather than the normal single quote syntax. Without dollar quoting, any single quotes or backslashes in the function definition must be escaped by doubling them. ``_`obj_file`_, _`link_symbol`_`` This form of the `AS` clause is used for dynamically loadable C language functions when the function name in the C language source code is not the same as the name of the SQL function. The string _`obj_file`_ is the name of the shared library file containing the compiled C function, and is interpreted as for the [`LOAD`](https://www.postgresql.org/docs/current/sql-load.html "LOAD") command. The string _`link_symbol`_ is the function's link symbol, that is, the name of the function in the C language source code. If the link symbol is omitted, it is assumed to be the same as the name of the SQL function being defined. The C names of all functions must be different, so you must give overloaded C functions different C names (for example, use the argument types as part of the C names). When repeated `CREATE FUNCTION` calls refer to the same object file, the file is only loaded once per session. To unload and reload the file (perhaps during development), start a new session. _`sql_body`_ The body of a `LANGUAGE SQL` function. This can either be a single statement RETURN _`expression`_ or a block BEGIN ATOMIC _`statement`_; _`statement`_; ... _`statement`_; END This is similar to writing the text of the function body as a string constant (see _`definition`_ above), but there are some differences: This form only works for `LANGUAGE SQL`, the string constant form works for all languages. This form is parsed at function definition time, the string constant form is parsed at execution time; therefore this form cannot support polymorphic argument types and other constructs that are not resolvable at function definition time. This form tracks dependencies between the function and objects used in the function body, so `DROP ... CASCADE` will work correctly, whereas the form using string literals may leave dangling functions. Finally, this form is more compatible with the SQL standard and other SQL implementations. Overloading ----------- PostgreSQL allows function _overloading_; that is, the same name can be used for several different functions so long as they have distinct input argument types. Whether or not you use it, this capability entails security precautions when calling functions in databases where some users mistrust other users; see [Section 10.3](https://www.postgresql.org/docs/current/typeconv-func.html "10.3. Functions") . Two functions are considered the same if they have the same names and _input_ argument types, ignoring any `OUT` parameters. Thus for example these declarations conflict: CREATE FUNCTION foo(int) ... CREATE FUNCTION foo(int, out text) ... Functions that have different argument type lists will not be considered to conflict at creation time, but if defaults are provided they might conflict in use. For example, consider CREATE FUNCTION foo(int) ... CREATE FUNCTION foo(int, int default 42) ... A call `foo(10)` will fail due to the ambiguity about which function should be called. Notes ----- The full SQL type syntax is allowed for declaring a function's arguments and return value. However, parenthesized type modifiers (e.g., the precision field for type `numeric`) are discarded by `CREATE FUNCTION`. Thus for example `CREATE FUNCTION foo (varchar(10)) ...` is exactly the same as `CREATE FUNCTION foo (varchar) ...`. When replacing an existing function with `CREATE OR REPLACE FUNCTION`, there are restrictions on changing parameter names. You cannot change the name already assigned to any input parameter (although you can add names to parameters that had none before). If there is more than one output parameter, you cannot change the names of the output parameters, because that would change the column names of the anonymous composite type that describes the function's result. These restrictions are made to ensure that existing calls of the function do not stop working when it is replaced. If a function is declared `STRICT` with a `VARIADIC` argument, the strictness check tests that the variadic array _as a whole_ is non-null. The function will still be called if the array has null elements. Examples -------- Add two integers using an SQL function: CREATE FUNCTION add(integer, integer) RETURNS integer AS 'select $1 + $2;' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT; The same function written in a more SQL-conforming style, using argument names and an unquoted body: CREATE FUNCTION add(a integer, b integer) RETURNS integer LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT RETURN a + b; Increment an integer, making use of an argument name, in PL/pgSQL: CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$ BEGIN RETURN i + 1; END; $$ LANGUAGE plpgsql; Return a record containing multiple output parameters: CREATE FUNCTION dup(in int, out f1 int, out f2 text) AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$ LANGUAGE SQL; SELECT \* FROM dup(42); You can do the same thing more verbosely with an explicitly named composite type: CREATE TYPE dup\_result AS (f1 int, f2 text); CREATE FUNCTION dup(int) RETURNS dup\_result AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$ LANGUAGE SQL; SELECT \* FROM dup(42); Another way to return multiple columns is to use a `TABLE` function: CREATE FUNCTION dup(int) RETURNS TABLE(f1 int, f2 text) AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$ LANGUAGE SQL; SELECT \* FROM dup(42); However, a `TABLE` function is different from the preceding examples, because it actually returns a _set_ of records, not just one record. Writing `SECURITY DEFINER` Functions Safely ------------------------------------------- Because a `SECURITY DEFINER` function is executed with the privileges of the user that owns it, care is needed to ensure that the function cannot be misused. For security, [search\_path](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-SEARCH-PATH) should be set to exclude any schemas writable by untrusted users. This prevents malicious users from creating objects (e.g., tables, functions, and operators) that mask objects intended to be used by the function. Particularly important in this regard is the temporary-table schema, which is searched first by default, and is normally writable by anyone. A secure arrangement can be obtained by forcing the temporary schema to be searched last. To do this, write `pg_temp` as the last entry in `search_path`. This function illustrates safe usage: CREATE FUNCTION check\_password(uname TEXT, pass TEXT) RETURNS BOOLEAN AS $$ DECLARE passed BOOLEAN; BEGIN SELECT (pwd = $2) INTO passed FROM pwds WHERE username = $1; RETURN passed; END; $$ LANGUAGE plpgsql SECURITY DEFINER -- Set a secure search\_path: trusted schema(s), then 'pg\_temp'. SET search\_path = admin, pg\_temp; This function's intention is to access a table `admin.pwds`. But without the `SET` clause, or with a `SET` clause mentioning only `admin`, the function could be subverted by creating a temporary table named `pwds`. If the security definer function intends to create roles, and if it is running as a non-superuser, `createrole_self_grant` should also be set to a known value using the `SET` clause. Another point to keep in mind is that by default, execute privilege is granted to `PUBLIC` for newly created functions (see [Section 5.8](https://www.postgresql.org/docs/current/ddl-priv.html "5.8. Privileges") for more information). Frequently you will wish to restrict use of a security definer function to only some users. To do that, you must revoke the default `PUBLIC` privileges and then grant execute privilege selectively. To avoid having a window where the new function is accessible to all, create it and set the privileges within a single transaction. For example: BEGIN; CREATE FUNCTION check\_password(uname TEXT, pass TEXT) ... SECURITY DEFINER; REVOKE ALL ON FUNCTION check\_password(uname TEXT, pass TEXT) FROM PUBLIC; GRANT EXECUTE ON FUNCTION check\_password(uname TEXT, pass TEXT) TO admins; COMMIT; Compatibility ------------- A `CREATE FUNCTION` command is defined in the SQL standard. The PostgreSQL implementation can be used in a compatible way but has many extensions. Conversely, the SQL standard specifies a number of optional features that are not implemented in PostgreSQL. The following are important compatibility issues: * `OR REPLACE` is a PostgreSQL extension. * For compatibility with some other database systems, _`argmode`_ can be written either before or after _`argname`_. But only the first way is standard-compliant. * For parameter defaults, the SQL standard specifies only the syntax with the `DEFAULT` key word. The syntax with `=` is used in T-SQL and Firebird. * The `SETOF` modifier is a PostgreSQL extension. * Only `SQL` is standardized as a language. * All other attributes except `CALLED ON NULL INPUT` and `RETURNS NULL ON NULL INPUT` are not standardized. * For the body of `LANGUAGE SQL` functions, the SQL standard only specifies the _`sql_body`_ form. Simple `LANGUAGE SQL` functions can be written in a way that is both standard-conforming and portable to other implementations. More complex functions using advanced features, optimization attributes, or other languages will necessarily be specific to PostgreSQL in a significant way. See Also -------- [ALTER FUNCTION](https://www.postgresql.org/docs/current/sql-alterfunction.html "ALTER FUNCTION") , [DROP FUNCTION](https://www.postgresql.org/docs/current/sql-dropfunction.html "DROP FUNCTION") , [GRANT](https://www.postgresql.org/docs/current/sql-grant.html "GRANT") , [LOAD](https://www.postgresql.org/docs/current/sql-load.html "LOAD") , [REVOKE](https://www.postgresql.org/docs/current/sql-revoke.html "REVOKE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-createforeigntable.html "CREATE FOREIGN TABLE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-creategroup.html "CREATE GROUP") | | CREATE FOREIGN TABLE | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | CREATE GROUP | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-createfunction.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 25. Backup and Restore November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/backup.html "PostgreSQL 18 - Chapter 25. Backup and Restore") ([18](https://www.postgresql.org/docs/18/backup.html "PostgreSQL 18 - Chapter 25. Backup and Restore") ) / [17](https://www.postgresql.org/docs/17/backup.html "PostgreSQL 17 - Chapter 25. Backup and Restore") / [16](https://www.postgresql.org/docs/16/backup.html "PostgreSQL 16 - Chapter 25. Backup and Restore") / [15](https://www.postgresql.org/docs/15/backup.html "PostgreSQL 15 - Chapter 25. Backup and Restore") / [14](https://www.postgresql.org/docs/14/backup.html "PostgreSQL 14 - Chapter 25. Backup and Restore") Development Versions: [devel](https://www.postgresql.org/docs/devel/backup.html "PostgreSQL devel - Chapter 25. Backup and Restore") Unsupported versions: [13](https://www.postgresql.org/docs/13/backup.html "PostgreSQL 13 - Chapter 25. Backup and Restore") / [12](https://www.postgresql.org/docs/12/backup.html "PostgreSQL 12 - Chapter 25. Backup and Restore") / [11](https://www.postgresql.org/docs/11/backup.html "PostgreSQL 11 - Chapter 25. Backup and Restore") / [10](https://www.postgresql.org/docs/10/backup.html "PostgreSQL 10 - Chapter 25. Backup and Restore") / [9.6](https://www.postgresql.org/docs/9.6/backup.html "PostgreSQL 9.6 - Chapter 25. Backup and Restore") / [9.5](https://www.postgresql.org/docs/9.5/backup.html "PostgreSQL 9.5 - Chapter 25. Backup and Restore") / [9.4](https://www.postgresql.org/docs/9.4/backup.html "PostgreSQL 9.4 - Chapter 25. Backup and Restore") / [9.3](https://www.postgresql.org/docs/9.3/backup.html "PostgreSQL 9.3 - Chapter 25. Backup and Restore") / [9.2](https://www.postgresql.org/docs/9.2/backup.html "PostgreSQL 9.2 - Chapter 25. Backup and Restore") / [9.1](https://www.postgresql.org/docs/9.1/backup.html "PostgreSQL 9.1 - Chapter 25. Backup and Restore") / [9.0](https://www.postgresql.org/docs/9.0/backup.html "PostgreSQL 9.0 - Chapter 25. Backup and Restore") / [8.4](https://www.postgresql.org/docs/8.4/backup.html "PostgreSQL 8.4 - Chapter 25. Backup and Restore") / [8.3](https://www.postgresql.org/docs/8.3/backup.html "PostgreSQL 8.3 - Chapter 25. Backup and Restore") / [8.2](https://www.postgresql.org/docs/8.2/backup.html "PostgreSQL 8.2 - Chapter 25. Backup and Restore") / [8.1](https://www.postgresql.org/docs/8.1/backup.html "PostgreSQL 8.1 - Chapter 25. Backup and Restore") / [8.0](https://www.postgresql.org/docs/8.0/backup.html "PostgreSQL 8.0 - Chapter 25. Backup and Restore") / [7.4](https://www.postgresql.org/docs/7.4/backup.html "PostgreSQL 7.4 - Chapter 25. Backup and Restore") / [7.3](https://www.postgresql.org/docs/7.3/backup.html "PostgreSQL 7.3 - Chapter 25. Backup and Restore") / [7.2](https://www.postgresql.org/docs/7.2/backup.html "PostgreSQL 7.2 - Chapter 25. Backup and Restore") / [7.1](https://www.postgresql.org/docs/7.1/backup.html "PostgreSQL 7.1 - Chapter 25. Backup and Restore") | Chapter 25. Backup and Restore | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/logfile-maintenance.html "24.3. Log File Maintenance") | [Up](https://www.postgresql.org/docs/current/admin.html "Part III. Server Administration") | Part III. Server Administration | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/backup-dump.html "25.1. SQL Dump") | * * * Chapter 25. Backup and Restore ------------------------------ **Table of Contents** [25.1. SQL Dump](https://www.postgresql.org/docs/current/backup-dump.html) [25.1.1. Restoring the Dump](https://www.postgresql.org/docs/current/backup-dump.html#BACKUP-DUMP-RESTORE) [25.1.2. Using pg\_dumpall](https://www.postgresql.org/docs/current/backup-dump.html#BACKUP-DUMP-ALL) [25.1.3. Handling Large Databases](https://www.postgresql.org/docs/current/backup-dump.html#BACKUP-DUMP-LARGE) [25.2. File System Level Backup](https://www.postgresql.org/docs/current/backup-file.html) [25.3. Continuous Archiving and Point-in-Time Recovery (PITR)](https://www.postgresql.org/docs/current/continuous-archiving.html) [25.3.1. Setting Up WAL Archiving](https://www.postgresql.org/docs/current/continuous-archiving.html#BACKUP-ARCHIVING-WAL) [25.3.2. Making a Base Backup](https://www.postgresql.org/docs/current/continuous-archiving.html#BACKUP-BASE-BACKUP) [25.3.3. Making an Incremental Backup](https://www.postgresql.org/docs/current/continuous-archiving.html#BACKUP-INCREMENTAL-BACKUP) [25.3.4. Making a Base Backup Using the Low Level API](https://www.postgresql.org/docs/current/continuous-archiving.html#BACKUP-LOWLEVEL-BASE-BACKUP) [25.3.5. Recovering Using a Continuous Archive Backup](https://www.postgresql.org/docs/current/continuous-archiving.html#BACKUP-PITR-RECOVERY) [25.3.6. Timelines](https://www.postgresql.org/docs/current/continuous-archiving.html#BACKUP-TIMELINES) [25.3.7. Tips and Examples](https://www.postgresql.org/docs/current/continuous-archiving.html#BACKUP-TIPS) [25.3.8. Caveats](https://www.postgresql.org/docs/current/continuous-archiving.html#CONTINUOUS-ARCHIVING-CAVEATS) As with everything that contains valuable data, PostgreSQL databases should be backed up regularly. While the procedure is essentially simple, it is important to have a clear understanding of the underlying techniques and assumptions. There are three fundamentally different approaches to backing up PostgreSQL data: * SQL dump * File system level backup * Continuous archiving Each has its own strengths and weaknesses; each is discussed in turn in the following sections. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/logfile-maintenance.html "24.3. Log File Maintenance") | [Up](https://www.postgresql.org/docs/current/admin.html "Part III. Server Administration") | [Next](https://www.postgresql.org/docs/current/backup-dump.html "25.1. SQL Dump") | | 24.3. Log File Maintenance | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 25.1. SQL Dump | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/backup.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: ALTER DEFAULT PRIVILEGES November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alterdefaultprivileges.html "PostgreSQL 18 - ALTER DEFAULT PRIVILEGES") ([18](https://www.postgresql.org/docs/18/sql-alterdefaultprivileges.html "PostgreSQL 18 - ALTER DEFAULT PRIVILEGES") ) / [17](https://www.postgresql.org/docs/17/sql-alterdefaultprivileges.html "PostgreSQL 17 - ALTER DEFAULT PRIVILEGES") / [16](https://www.postgresql.org/docs/16/sql-alterdefaultprivileges.html "PostgreSQL 16 - ALTER DEFAULT PRIVILEGES") / [15](https://www.postgresql.org/docs/15/sql-alterdefaultprivileges.html "PostgreSQL 15 - ALTER DEFAULT PRIVILEGES") / [14](https://www.postgresql.org/docs/14/sql-alterdefaultprivileges.html "PostgreSQL 14 - ALTER DEFAULT PRIVILEGES") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alterdefaultprivileges.html "PostgreSQL devel - ALTER DEFAULT PRIVILEGES") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alterdefaultprivileges.html "PostgreSQL 13 - ALTER DEFAULT PRIVILEGES") / [12](https://www.postgresql.org/docs/12/sql-alterdefaultprivileges.html "PostgreSQL 12 - ALTER DEFAULT PRIVILEGES") / [11](https://www.postgresql.org/docs/11/sql-alterdefaultprivileges.html "PostgreSQL 11 - ALTER DEFAULT PRIVILEGES") / [10](https://www.postgresql.org/docs/10/sql-alterdefaultprivileges.html "PostgreSQL 10 - ALTER DEFAULT PRIVILEGES") / [9.6](https://www.postgresql.org/docs/9.6/sql-alterdefaultprivileges.html "PostgreSQL 9.6 - ALTER DEFAULT PRIVILEGES") / [9.5](https://www.postgresql.org/docs/9.5/sql-alterdefaultprivileges.html "PostgreSQL 9.5 - ALTER DEFAULT PRIVILEGES") / [9.4](https://www.postgresql.org/docs/9.4/sql-alterdefaultprivileges.html "PostgreSQL 9.4 - ALTER DEFAULT PRIVILEGES") / [9.3](https://www.postgresql.org/docs/9.3/sql-alterdefaultprivileges.html "PostgreSQL 9.3 - ALTER DEFAULT PRIVILEGES") / [9.2](https://www.postgresql.org/docs/9.2/sql-alterdefaultprivileges.html "PostgreSQL 9.2 - ALTER DEFAULT PRIVILEGES") / [9.1](https://www.postgresql.org/docs/9.1/sql-alterdefaultprivileges.html "PostgreSQL 9.1 - ALTER DEFAULT PRIVILEGES") / [9.0](https://www.postgresql.org/docs/9.0/sql-alterdefaultprivileges.html "PostgreSQL 9.0 - ALTER DEFAULT PRIVILEGES") | ALTER DEFAULT PRIVILEGES | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-alterdatabase.html "ALTER DATABASE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-alterdomain.html "ALTER DOMAIN") | * * * ALTER DEFAULT PRIVILEGES ------------------------ ALTER DEFAULT PRIVILEGES — define default access privileges Synopsis -------- ALTER DEFAULT PRIVILEGES \[ FOR { ROLE | USER } _`target_role`_ \[, ...\] \] \[ IN SCHEMA _`schema_name`_ \[, ...\] \] _`abbreviated_grant_or_revoke`_ where _`abbreviated_grant_or_revoke`_ is one of: GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN } \[, ...\] | ALL \[ PRIVILEGES \] } ON TABLES TO { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ WITH GRANT OPTION \] GRANT { { USAGE | SELECT | UPDATE } \[, ...\] | ALL \[ PRIVILEGES \] } ON SEQUENCES TO { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ WITH GRANT OPTION \] GRANT { EXECUTE | ALL \[ PRIVILEGES \] } ON { FUNCTIONS | ROUTINES } TO { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ WITH GRANT OPTION \] GRANT { USAGE | ALL \[ PRIVILEGES \] } ON TYPES TO { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ WITH GRANT OPTION \] GRANT { { USAGE | CREATE } \[, ...\] | ALL \[ PRIVILEGES \] } ON SCHEMAS TO { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ WITH GRANT OPTION \] GRANT { { SELECT | UPDATE } \[, ...\] | ALL \[ PRIVILEGES \] } ON LARGE OBJECTS TO { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ WITH GRANT OPTION \] REVOKE \[ GRANT OPTION FOR \] { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN } \[, ...\] | ALL \[ PRIVILEGES \] } ON TABLES FROM { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ CASCADE | RESTRICT \] REVOKE \[ GRANT OPTION FOR \] { { USAGE | SELECT | UPDATE } \[, ...\] | ALL \[ PRIVILEGES \] } ON SEQUENCES FROM { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ CASCADE | RESTRICT \] REVOKE \[ GRANT OPTION FOR \] { EXECUTE | ALL \[ PRIVILEGES \] } ON { FUNCTIONS | ROUTINES } FROM { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ CASCADE | RESTRICT \] REVOKE \[ GRANT OPTION FOR \] { USAGE | ALL \[ PRIVILEGES \] } ON TYPES FROM { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ CASCADE | RESTRICT \] REVOKE \[ GRANT OPTION FOR \] { { USAGE | CREATE } \[, ...\] | ALL \[ PRIVILEGES \] } ON SCHEMAS FROM { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ CASCADE | RESTRICT \] REVOKE \[ GRANT OPTION FOR \] { { SELECT | UPDATE } \[, ...\] | ALL \[ PRIVILEGES \] } ON LARGE OBJECTS FROM { \[ GROUP \] _`role_name`_ | PUBLIC } \[, ...\] \[ CASCADE | RESTRICT \] Description ----------- `ALTER DEFAULT PRIVILEGES` allows you to set the privileges that will be applied to objects created in the future. (It does not affect privileges assigned to already-existing objects.) Privileges can be set globally (i.e., for all objects created in the current database), or just for objects created in specified schemas. While you can change your own default privileges and the defaults of roles that you are a member of, at object creation time, new object permissions are only affected by the default privileges of the current role, and are not inherited from any roles in which the current role is a member. As explained in [Section 5.8](https://www.postgresql.org/docs/current/ddl-priv.html "5.8. Privileges") , the default privileges for any object type normally grant all grantable permissions to the object owner, and may grant some privileges to `PUBLIC` as well. However, this behavior can be changed by altering the global default privileges with `ALTER DEFAULT PRIVILEGES`. Currently, only the privileges for schemas, tables (including views and foreign tables), sequences, functions, types (including domains), and large objects can be altered. For this command, functions include aggregates and procedures. The words `FUNCTIONS` and `ROUTINES` are equivalent in this command. (`ROUTINES` is preferred going forward as the standard term for functions and procedures taken together. In earlier PostgreSQL releases, only the word `FUNCTIONS` was allowed. It is not possible to set default privileges for functions and procedures separately.) Default privileges that are specified per-schema are added to whatever the global default privileges are for the particular object type. This means you cannot revoke privileges per-schema if they are granted globally (either by default, or according to a previous `ALTER DEFAULT PRIVILEGES` command that did not specify a schema). Per-schema `REVOKE` is only useful to reverse the effects of a previous per-schema `GRANT`. ### Parameters _`target_role`_ Change default privileges for objects created by the _`target_role`_, or the current role if unspecified. _`schema_name`_ The name of an existing schema. If specified, the default privileges are altered for objects later created in that schema. If `IN SCHEMA` is omitted, the global default privileges are altered. `IN SCHEMA` is not allowed when setting privileges for schemas and large objects, since schemas can't be nested and large objects don't belong to a schema. _`role_name`_ The name of an existing role to grant or revoke privileges for. This parameter, and all the other parameters in _`abbreviated_grant_or_revoke`_, act as described under [GRANT](https://www.postgresql.org/docs/current/sql-grant.html "GRANT") or [REVOKE](https://www.postgresql.org/docs/current/sql-revoke.html "REVOKE") , except that one is setting permissions for a whole class of objects rather than specific named objects. Notes ----- Use [psql](https://www.postgresql.org/docs/current/app-psql.html "psql") 's `\ddp` command to obtain information about existing assignments of default privileges. The meaning of the privilege display is the same as explained for `\dp` in [Section 5.8](https://www.postgresql.org/docs/current/ddl-priv.html "5.8. Privileges") . If you wish to drop a role for which the default privileges have been altered, it is necessary to reverse the changes in its default privileges or use `DROP OWNED BY` to get rid of the default privileges entry for the role. Examples -------- Grant SELECT privilege to everyone for all tables (and views) you subsequently create in schema `myschema`, and allow role `webuser` to INSERT into them too: ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT SELECT ON TABLES TO PUBLIC; ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT INSERT ON TABLES TO webuser; Undo the above, so that subsequently-created tables won't have any more permissions than normal: ALTER DEFAULT PRIVILEGES IN SCHEMA myschema REVOKE SELECT ON TABLES FROM PUBLIC; ALTER DEFAULT PRIVILEGES IN SCHEMA myschema REVOKE INSERT ON TABLES FROM webuser; Remove the public EXECUTE permission that is normally granted on functions, for all functions subsequently created by role `admin`: ALTER DEFAULT PRIVILEGES FOR ROLE admin REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC; Note however that you _cannot_ accomplish that effect with a command limited to a single schema. This command has no effect, unless it is undoing a matching `GRANT`: ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC; That's because per-schema default privileges can only add privileges to the global setting, not remove privileges granted by it. Compatibility ------------- There is no `ALTER DEFAULT PRIVILEGES` statement in the SQL standard. See Also -------- [GRANT](https://www.postgresql.org/docs/current/sql-grant.html "GRANT") , [REVOKE](https://www.postgresql.org/docs/current/sql-revoke.html "REVOKE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-alterdatabase.html "ALTER DATABASE") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-alterdomain.html "ALTER DOMAIN") | | ALTER DATABASE | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | ALTER DOMAIN | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-alterdefaultprivileges.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 55.4. Miscellaneous Coding Conventions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/source-conventions.html "PostgreSQL 18 - 55.4. Miscellaneous Coding Conventions") ([18](https://www.postgresql.org/docs/18/source-conventions.html "PostgreSQL 18 - 55.4. Miscellaneous Coding Conventions") ) / [17](https://www.postgresql.org/docs/17/source-conventions.html "PostgreSQL 17 - 55.4. Miscellaneous Coding Conventions") / [16](https://www.postgresql.org/docs/16/source-conventions.html "PostgreSQL 16 - 55.4. Miscellaneous Coding Conventions") / [15](https://www.postgresql.org/docs/15/source-conventions.html "PostgreSQL 15 - 55.4. Miscellaneous Coding Conventions") / [14](https://www.postgresql.org/docs/14/source-conventions.html "PostgreSQL 14 - 55.4. Miscellaneous Coding Conventions") Development Versions: [devel](https://www.postgresql.org/docs/devel/source-conventions.html "PostgreSQL devel - 55.4. Miscellaneous Coding Conventions") Unsupported versions: [13](https://www.postgresql.org/docs/13/source-conventions.html "PostgreSQL 13 - 55.4. Miscellaneous Coding Conventions") / [12](https://www.postgresql.org/docs/12/source-conventions.html "PostgreSQL 12 - 55.4. Miscellaneous Coding Conventions") / [11](https://www.postgresql.org/docs/11/source-conventions.html "PostgreSQL 11 - 55.4. Miscellaneous Coding Conventions") / [10](https://www.postgresql.org/docs/10/source-conventions.html "PostgreSQL 10 - 55.4. Miscellaneous Coding Conventions") / [9.6](https://www.postgresql.org/docs/9.6/source-conventions.html "PostgreSQL 9.6 - 55.4. Miscellaneous Coding Conventions") | 55.4. Miscellaneous Coding Conventions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/error-style-guide.html "55.3. Error Message Style Guide") | [Up](https://www.postgresql.org/docs/current/source.html "Chapter 55. PostgreSQL Coding Conventions") | Chapter 55. PostgreSQL Coding Conventions | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/nls.html "Chapter 56. Native Language Support") | * * * 55.4. Miscellaneous Coding Conventions [#](https://www.postgresql.org/docs/current/source-conventions.html#SOURCE-CONVENTIONS) ------------------------------------------------------------------------------------------------------------------------------- ### C Standard [#](https://www.postgresql.org/docs/current/source-conventions.html#SOURCE-CONVENTIONS-C-STANDARD) Code in PostgreSQL should only rely on language features available in the C99 standard. That means a conforming C99 compiler has to be able to compile postgres, at least aside from a few platform dependent pieces. A few features included in the C99 standard are, at this time, not permitted to be used in core PostgreSQL code. This currently includes variable length arrays, intermingled declarations and code, `//` comments, universal character names. Reasons for that include portability and historical practices. Features from later revisions of the C standard or compiler specific features can be used, if a fallback is provided. For example `_Static_assert()` and `__builtin_constant_p` are currently used, even though they are from newer revisions of the C standard and a GCC extension respectively. If not available we respectively fall back to using a C99 compatible replacement that performs the same checks, but emits rather cryptic messages and do not use `__builtin_constant_p`. ### Function-Like Macros and Inline Functions [#](https://www.postgresql.org/docs/current/source-conventions.html#SOURCE-CONVENTIONS-MACROS-INLINE) Both macros with arguments and `static inline` functions may be used. The latter are preferable if there are multiple-evaluation hazards when written as a macro, as e.g., the case with #define Max(x, y) ((x) > (y) ? (x) : (y)) or when the macro would be very long. In other cases it's only possible to use macros, or at least easier. For example because expressions of various types need to be passed to the macro. When the definition of an inline function references symbols (i.e., variables, functions) that are only available as part of the backend, the function may not be visible when included from frontend code. #ifndef FRONTEND static inline MemoryContext MemoryContextSwitchTo(MemoryContext context) { MemoryContext old = CurrentMemoryContext; CurrentMemoryContext = context; return old; } #endif /\* FRONTEND \*/ In this example `CurrentMemoryContext`, which is only available in the backend, is referenced and the function thus hidden with a `#ifndef FRONTEND`. This rule exists because some compilers emit references to symbols contained in inline functions even if the function is not used. ### Writing Signal Handlers [#](https://www.postgresql.org/docs/current/source-conventions.html#SOURCE-CONVENTIONS-SIGNAL-HANDLERS) To be suitable to run inside a signal handler code has to be written very carefully. The fundamental problem is that, unless blocked, a signal handler can interrupt code at any time. If code inside the signal handler uses the same state as code outside chaos may ensue. As an example consider what happens if a signal handler tries to acquire a lock that's already held in the interrupted code. Barring special arrangements code in signal handlers may only call async-signal safe functions (as defined in POSIX) and access variables of type `volatile sig_atomic_t`. A few functions in `postgres` are also deemed signal safe, importantly `SetLatch()`. In most cases signal handlers should do nothing more than note that a signal has arrived, and wake up code running outside of the handler using a latch. An example of such a handler is the following: static void handle\_sighup(SIGNAL\_ARGS) { got\_SIGHUP = true; SetLatch(MyLatch); } ### Calling Function Pointers [#](https://www.postgresql.org/docs/current/source-conventions.html#SOURCE-CONVENTIONS-FUNCTION-POINTERS) For clarity, it is preferred to explicitly dereference a function pointer when calling the pointed-to function if the pointer is a simple variable, for example: (\*emit\_log\_hook) (edata); (even though `emit_log_hook(edata)` would also work). When the function pointer is part of a structure, then the extra punctuation can and usually should be omitted, for example: paramInfo->paramFetch(paramInfo, paramId); * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/error-style-guide.html "55.3. Error Message Style Guide") | [Up](https://www.postgresql.org/docs/current/source.html "Chapter 55. PostgreSQL Coding Conventions") | [Next](https://www.postgresql.org/docs/current/nls.html "Chapter 56. Native Language Support") | | 55.3. Error Message Style Guide | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Chapter 56. Native Language Support | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/source-conventions.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: Chapter 3. Advanced Features November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/tutorial-advanced.html "PostgreSQL 18 - Chapter 3. Advanced Features") ([18](https://www.postgresql.org/docs/18/tutorial-advanced.html "PostgreSQL 18 - Chapter 3. Advanced Features") ) / [17](https://www.postgresql.org/docs/17/tutorial-advanced.html "PostgreSQL 17 - Chapter 3. Advanced Features") / [16](https://www.postgresql.org/docs/16/tutorial-advanced.html "PostgreSQL 16 - Chapter 3. Advanced Features") / [15](https://www.postgresql.org/docs/15/tutorial-advanced.html "PostgreSQL 15 - Chapter 3. Advanced Features") / [14](https://www.postgresql.org/docs/14/tutorial-advanced.html "PostgreSQL 14 - Chapter 3. Advanced Features") Development Versions: [devel](https://www.postgresql.org/docs/devel/tutorial-advanced.html "PostgreSQL devel - Chapter 3. Advanced Features") Unsupported versions: [13](https://www.postgresql.org/docs/13/tutorial-advanced.html "PostgreSQL 13 - Chapter 3. Advanced Features") / [12](https://www.postgresql.org/docs/12/tutorial-advanced.html "PostgreSQL 12 - Chapter 3. Advanced Features") / [11](https://www.postgresql.org/docs/11/tutorial-advanced.html "PostgreSQL 11 - Chapter 3. Advanced Features") / [10](https://www.postgresql.org/docs/10/tutorial-advanced.html "PostgreSQL 10 - Chapter 3. Advanced Features") / [9.6](https://www.postgresql.org/docs/9.6/tutorial-advanced.html "PostgreSQL 9.6 - Chapter 3. Advanced Features") / [9.5](https://www.postgresql.org/docs/9.5/tutorial-advanced.html "PostgreSQL 9.5 - Chapter 3. Advanced Features") / [9.4](https://www.postgresql.org/docs/9.4/tutorial-advanced.html "PostgreSQL 9.4 - Chapter 3. Advanced Features") / [9.3](https://www.postgresql.org/docs/9.3/tutorial-advanced.html "PostgreSQL 9.3 - Chapter 3. Advanced Features") / [9.2](https://www.postgresql.org/docs/9.2/tutorial-advanced.html "PostgreSQL 9.2 - Chapter 3. Advanced Features") / [9.1](https://www.postgresql.org/docs/9.1/tutorial-advanced.html "PostgreSQL 9.1 - Chapter 3. Advanced Features") / [9.0](https://www.postgresql.org/docs/9.0/tutorial-advanced.html "PostgreSQL 9.0 - Chapter 3. Advanced Features") / [8.4](https://www.postgresql.org/docs/8.4/tutorial-advanced.html "PostgreSQL 8.4 - Chapter 3. Advanced Features") / [8.3](https://www.postgresql.org/docs/8.3/tutorial-advanced.html "PostgreSQL 8.3 - Chapter 3. Advanced Features") / [8.2](https://www.postgresql.org/docs/8.2/tutorial-advanced.html "PostgreSQL 8.2 - Chapter 3. Advanced Features") / [8.1](https://www.postgresql.org/docs/8.1/tutorial-advanced.html "PostgreSQL 8.1 - Chapter 3. Advanced Features") / [8.0](https://www.postgresql.org/docs/8.0/tutorial-advanced.html "PostgreSQL 8.0 - Chapter 3. Advanced Features") / [7.4](https://www.postgresql.org/docs/7.4/tutorial-advanced.html "PostgreSQL 7.4 - Chapter 3. Advanced Features") / [7.3](https://www.postgresql.org/docs/7.3/tutorial-advanced.html "PostgreSQL 7.3 - Chapter 3. Advanced Features") / [7.2](https://www.postgresql.org/docs/7.2/tutorial-advanced.html "PostgreSQL 7.2 - Chapter 3. Advanced Features") | Chapter 3. Advanced Features | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/tutorial-delete.html "2.9. Deletions") | [Up](https://www.postgresql.org/docs/18/tutorial.html "Part I. Tutorial") | Part I. Tutorial | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/tutorial-advanced-intro.html "3.1. Introduction") | * * * Chapter 3. Advanced Features ---------------------------- **Table of Contents** [3.1. Introduction](https://www.postgresql.org/docs/18/tutorial-advanced-intro.html) [3.2. Views](https://www.postgresql.org/docs/18/tutorial-views.html) [3.3. Foreign Keys](https://www.postgresql.org/docs/18/tutorial-fk.html) [3.4. Transactions](https://www.postgresql.org/docs/18/tutorial-transactions.html) [3.5. Window Functions](https://www.postgresql.org/docs/18/tutorial-window.html) [3.6. Inheritance](https://www.postgresql.org/docs/18/tutorial-inheritance.html) [3.7. Conclusion](https://www.postgresql.org/docs/18/tutorial-conclusion.html) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/tutorial-delete.html "2.9. Deletions") | [Up](https://www.postgresql.org/docs/18/tutorial.html "Part I. Tutorial") | [Next](https://www.postgresql.org/docs/18/tutorial-advanced-intro.html "3.1. Introduction") | | 2.9. Deletions | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 3.1. Introduction | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/tutorial-advanced.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 32.11. Control Functions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/libpq-control.html "PostgreSQL 18 - 32.11. Control Functions") ([18](https://www.postgresql.org/docs/18/libpq-control.html "PostgreSQL 18 - 32.11. Control Functions") ) / [17](https://www.postgresql.org/docs/17/libpq-control.html "PostgreSQL 17 - 32.11. Control Functions") / [16](https://www.postgresql.org/docs/16/libpq-control.html "PostgreSQL 16 - 32.11. Control Functions") / [15](https://www.postgresql.org/docs/15/libpq-control.html "PostgreSQL 15 - 32.11. Control Functions") / [14](https://www.postgresql.org/docs/14/libpq-control.html "PostgreSQL 14 - 32.11. Control Functions") Development Versions: [devel](https://www.postgresql.org/docs/devel/libpq-control.html "PostgreSQL devel - 32.11. Control Functions") Unsupported versions: [13](https://www.postgresql.org/docs/13/libpq-control.html "PostgreSQL 13 - 32.11. Control Functions") / [12](https://www.postgresql.org/docs/12/libpq-control.html "PostgreSQL 12 - 32.11. Control Functions") / [11](https://www.postgresql.org/docs/11/libpq-control.html "PostgreSQL 11 - 32.11. Control Functions") / [10](https://www.postgresql.org/docs/10/libpq-control.html "PostgreSQL 10 - 32.11. Control Functions") / [9.6](https://www.postgresql.org/docs/9.6/libpq-control.html "PostgreSQL 9.6 - 32.11. Control Functions") / [9.5](https://www.postgresql.org/docs/9.5/libpq-control.html "PostgreSQL 9.5 - 32.11. Control Functions") / [9.4](https://www.postgresql.org/docs/9.4/libpq-control.html "PostgreSQL 9.4 - 32.11. Control Functions") / [9.3](https://www.postgresql.org/docs/9.3/libpq-control.html "PostgreSQL 9.3 - 32.11. Control Functions") / [9.2](https://www.postgresql.org/docs/9.2/libpq-control.html "PostgreSQL 9.2 - 32.11. Control Functions") / [9.1](https://www.postgresql.org/docs/9.1/libpq-control.html "PostgreSQL 9.1 - 32.11. Control Functions") / [9.0](https://www.postgresql.org/docs/9.0/libpq-control.html "PostgreSQL 9.0 - 32.11. Control Functions") / [8.4](https://www.postgresql.org/docs/8.4/libpq-control.html "PostgreSQL 8.4 - 32.11. Control Functions") / [8.3](https://www.postgresql.org/docs/8.3/libpq-control.html "PostgreSQL 8.3 - 32.11. Control Functions") / [8.2](https://www.postgresql.org/docs/8.2/libpq-control.html "PostgreSQL 8.2 - 32.11. Control Functions") / [8.1](https://www.postgresql.org/docs/8.1/libpq-control.html "PostgreSQL 8.1 - 32.11. Control Functions") / [8.0](https://www.postgresql.org/docs/8.0/libpq-control.html "PostgreSQL 8.0 - 32.11. Control Functions") / [7.4](https://www.postgresql.org/docs/7.4/libpq-control.html "PostgreSQL 7.4 - 32.11. Control Functions") / [7.3](https://www.postgresql.org/docs/7.3/libpq-control.html "PostgreSQL 7.3 - 32.11. Control Functions") / [7.2](https://www.postgresql.org/docs/7.2/libpq-control.html "PostgreSQL 7.2 - 32.11. Control Functions") / [7.1](https://www.postgresql.org/docs/7.1/libpq-control.html "PostgreSQL 7.1 - 32.11. Control Functions") | 32.11. Control Functions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/libpq-copy.html "32.10. Functions Associated with the COPY Command") | [Up](https://www.postgresql.org/docs/current/libpq.html "Chapter 32. libpq — C Library") | Chapter 32. libpq — C Library | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/libpq-misc.html "32.12. Miscellaneous Functions") | * * * 32.11. Control Functions [#](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-CONTROL) ------------------------------------------------------------------------------------------------------- These functions control miscellaneous details of libpq's behavior. `PQclientEncoding` [#](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQCLIENTENCODING) Returns the client encoding. int PQclientEncoding(const PGconn \*_`conn`_); Note that it returns the encoding ID, not a symbolic string such as `EUC_JP`. If unsuccessful, it returns -1. To convert an encoding ID to an encoding name, you can use: char \*pg\_encoding\_to\_char(int _`encoding_id`_); `PQsetClientEncoding` [#](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETCLIENTENCODING) Sets the client encoding. int PQsetClientEncoding(PGconn \*_`conn`_, const char \*_`encoding`_); _`conn`_ is a connection to the server, and _`encoding`_ is the encoding you want to use. If the function successfully sets the encoding, it returns 0, otherwise -1. The current encoding for this connection can be determined by using [`PQclientEncoding`](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQCLIENTENCODING) . `PQsetErrorVerbosity` [#](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORVERBOSITY) Determines the verbosity of messages returned by [`PQerrorMessage`](https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQERRORMESSAGE) and [`PQresultErrorMessage`](https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQRESULTERRORMESSAGE) . typedef enum { PQERRORS\_TERSE, PQERRORS\_DEFAULT, PQERRORS\_VERBOSE, PQERRORS\_SQLSTATE } PGVerbosity; PGVerbosity PQsetErrorVerbosity(PGconn \*conn, PGVerbosity verbosity); [`PQsetErrorVerbosity`](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORVERBOSITY) sets the verbosity mode, returning the connection's previous setting. In _TERSE_ mode, returned messages include severity, primary text, and position only; this will normally fit on a single line. The _DEFAULT_ mode produces messages that include the above plus any detail, hint, or context fields (these might span multiple lines). The _VERBOSE_ mode includes all available fields. The _SQLSTATE_ mode includes only the error severity and the `SQLSTATE` error code, if one is available (if not, the output is like _TERSE_ mode). Changing the verbosity setting does not affect the messages available from already-existing `PGresult` objects, only subsequently-created ones. (But see [`PQresultVerboseErrorMessage`](https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQRESULTVERBOSEERRORMESSAGE) if you want to print a previous error with a different verbosity.) `PQsetErrorContextVisibility` [#](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY) Determines the handling of `CONTEXT` fields in messages returned by [`PQerrorMessage`](https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQERRORMESSAGE) and [`PQresultErrorMessage`](https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQRESULTERRORMESSAGE) . typedef enum { PQSHOW\_CONTEXT\_NEVER, PQSHOW\_CONTEXT\_ERRORS, PQSHOW\_CONTEXT\_ALWAYS } PGContextVisibility; PGContextVisibility PQsetErrorContextVisibility(PGconn \*conn, PGContextVisibility show\_context); [`PQsetErrorContextVisibility`](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY) sets the context display mode, returning the connection's previous setting. This mode controls whether the `CONTEXT` field is included in messages. The _NEVER_ mode never includes `CONTEXT`, while _ALWAYS_ always includes it if available. In _ERRORS_ mode (the default), `CONTEXT` fields are included only in error messages, not in notices and warnings. (However, if the verbosity setting is _TERSE_ or _SQLSTATE_, `CONTEXT` fields are omitted regardless of the context display mode.) Changing this mode does not affect the messages available from already-existing `PGresult` objects, only subsequently-created ones. (But see [`PQresultVerboseErrorMessage`](https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQRESULTVERBOSEERRORMESSAGE) if you want to print a previous error with a different display mode.) `PQtrace` [#](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQTRACE) Enables tracing of the client/server communication to a debugging file stream. void PQtrace(PGconn \*conn, FILE \*stream); Each line consists of: an optional timestamp, a direction indicator (`F` for messages from client to server or `B` for messages from server to client), message length, message type, and message contents. Non-message contents fields (timestamp, direction, length and message type) are separated by a tab. Message contents are separated by a space. Protocol strings are enclosed in double quotes, while strings used as data values are enclosed in single quotes. Non-printable chars are printed as hexadecimal escapes. Further message-type-specific detail can be found in [Section 54.7](https://www.postgresql.org/docs/current/protocol-message-formats.html "54.7. Message Formats") . ### Note On Windows, if the libpq library and an application are compiled with different flags, this function call will crash the application because the internal representation of the `FILE` pointers differ. Specifically, multithreaded/single-threaded, release/debug, and static/dynamic flags should be the same for the library and all applications using that library. `PQsetTraceFlags` [#](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETTRACEFLAGS) Controls the tracing behavior of client/server communication. void PQsetTraceFlags(PGconn \*conn, int flags); `flags` contains flag bits describing the operating mode of tracing. If `flags` contains `PQTRACE_SUPPRESS_TIMESTAMPS`, then the timestamp is not included when printing each message. If `flags` contains `PQTRACE_REGRESS_MODE`, then some fields are redacted when printing each message, such as object OIDs, to make the output more convenient to use in testing frameworks. This function must be called after calling `PQtrace`. `PQuntrace` [#](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQUNTRACE) Disables tracing started by [`PQtrace`](https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQTRACE) . void PQuntrace(PGconn \*conn); * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/libpq-copy.html "32.10. Functions Associated with the COPY Command") | [Up](https://www.postgresql.org/docs/current/libpq.html "Chapter 32. libpq — C Library") | [Next](https://www.postgresql.org/docs/current/libpq-misc.html "32.12. Miscellaneous Functions") | | 32.10. Functions Associated with the `COPY` Command | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 32.12. Miscellaneous Functions | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/libpq-control.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: 32.22. Building libpq Programs November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/libpq-build.html "PostgreSQL 18 - 32.22. Building libpq Programs") ([18](https://www.postgresql.org/docs/18/libpq-build.html "PostgreSQL 18 - 32.22. Building libpq Programs") ) / [17](https://www.postgresql.org/docs/17/libpq-build.html "PostgreSQL 17 - 32.22. Building libpq Programs") / [16](https://www.postgresql.org/docs/16/libpq-build.html "PostgreSQL 16 - 32.22. Building libpq Programs") / [15](https://www.postgresql.org/docs/15/libpq-build.html "PostgreSQL 15 - 32.22. Building libpq Programs") / [14](https://www.postgresql.org/docs/14/libpq-build.html "PostgreSQL 14 - 32.22. Building libpq Programs") Development Versions: [devel](https://www.postgresql.org/docs/devel/libpq-build.html "PostgreSQL devel - 32.22. Building libpq Programs") Unsupported versions: [13](https://www.postgresql.org/docs/13/libpq-build.html "PostgreSQL 13 - 32.22. Building libpq Programs") / [12](https://www.postgresql.org/docs/12/libpq-build.html "PostgreSQL 12 - 32.22. Building libpq Programs") / [11](https://www.postgresql.org/docs/11/libpq-build.html "PostgreSQL 11 - 32.22. Building libpq Programs") / [10](https://www.postgresql.org/docs/10/libpq-build.html "PostgreSQL 10 - 32.22. Building libpq Programs") / [9.6](https://www.postgresql.org/docs/9.6/libpq-build.html "PostgreSQL 9.6 - 32.22. Building libpq Programs") / [9.5](https://www.postgresql.org/docs/9.5/libpq-build.html "PostgreSQL 9.5 - 32.22. Building libpq Programs") / [9.4](https://www.postgresql.org/docs/9.4/libpq-build.html "PostgreSQL 9.4 - 32.22. Building libpq Programs") / [9.3](https://www.postgresql.org/docs/9.3/libpq-build.html "PostgreSQL 9.3 - 32.22. Building libpq Programs") / [9.2](https://www.postgresql.org/docs/9.2/libpq-build.html "PostgreSQL 9.2 - 32.22. Building libpq Programs") / [9.1](https://www.postgresql.org/docs/9.1/libpq-build.html "PostgreSQL 9.1 - 32.22. Building libpq Programs") / [9.0](https://www.postgresql.org/docs/9.0/libpq-build.html "PostgreSQL 9.0 - 32.22. Building libpq Programs") / [8.4](https://www.postgresql.org/docs/8.4/libpq-build.html "PostgreSQL 8.4 - 32.22. Building libpq Programs") / [8.3](https://www.postgresql.org/docs/8.3/libpq-build.html "PostgreSQL 8.3 - 32.22. Building libpq Programs") / [8.2](https://www.postgresql.org/docs/8.2/libpq-build.html "PostgreSQL 8.2 - 32.22. Building libpq Programs") / [8.1](https://www.postgresql.org/docs/8.1/libpq-build.html "PostgreSQL 8.1 - 32.22. Building libpq Programs") / [8.0](https://www.postgresql.org/docs/8.0/libpq-build.html "PostgreSQL 8.0 - 32.22. Building libpq Programs") / [7.4](https://www.postgresql.org/docs/7.4/libpq-build.html "PostgreSQL 7.4 - 32.22. Building libpq Programs") / [7.3](https://www.postgresql.org/docs/7.3/libpq-build.html "PostgreSQL 7.3 - 32.22. Building libpq Programs") / [7.2](https://www.postgresql.org/docs/7.2/libpq-build.html "PostgreSQL 7.2 - 32.22. Building libpq Programs") | 32.22. Building libpq Programs | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/libpq-threading.html "32.21. Behavior in Threaded Programs") | [Up](https://www.postgresql.org/docs/18/libpq.html "Chapter 32. libpq — C Library") | Chapter 32. libpq — C Library | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/18/libpq-example.html "32.23. Example Programs") | * * * 32.22. Building libpq Programs [#](https://www.postgresql.org/docs/18/libpq-build.html#LIBPQ-BUILD) ---------------------------------------------------------------------------------------------------- To build (i.e., compile and link) a program using libpq you need to do all of the following things: * Include the `libpq-fe.h` header file: #include If you failed to do that then you will normally get error messages from your compiler similar to: foo.c: In function \`main': foo.c:34: \`PGconn' undeclared (first use in this function) foo.c:35: \`PGresult' undeclared (first use in this function) foo.c:54: \`CONNECTION\_BAD' undeclared (first use in this function) foo.c:68: \`PGRES\_COMMAND\_OK' undeclared (first use in this function) foo.c:95: \`PGRES\_TUPLES\_OK' undeclared (first use in this function) * Point your compiler to the directory where the PostgreSQL header files were installed, by supplying the ``-I_`directory`_`` option to your compiler. (In some cases the compiler will look into the directory in question by default, so you can omit this option.) For instance, your compile command line could look like: cc -c -I/usr/local/pgsql/include testprog.c If you are using makefiles then add the option to the `CPPFLAGS` variable: CPPFLAGS += -I/usr/local/pgsql/include If there is any chance that your program might be compiled by other users then you should not hardcode the directory location like that. Instead, you can run the utility `pg_config` to find out where the header files are on the local system: $ If you have `pkg-config` installed, you can run instead: $ Note that this will already include the `-I` in front of the path. Failure to specify the correct option to the compiler will result in an error message such as: testlibpq.c:8:22: libpq-fe.h: No such file or directory * When linking the final program, specify the option `-lpq` so that the libpq library gets pulled in, as well as the option ``-L_`directory`_`` to point the compiler to the directory where the libpq library resides. (Again, the compiler will search some directories by default.) For maximum portability, put the `-L` option before the `-lpq` option. For example: cc -o testprog testprog1.o testprog2.o -L/usr/local/pgsql/lib -lpq You can find out the library directory using `pg_config` as well: $ Or again use `pkg-config`: $ Note again that this prints the full options, not only the path. Error messages that point to problems in this area could look like the following: testlibpq.o: In function \`main': testlibpq.o(.text+0x60): undefined reference to \`PQsetdbLogin' testlibpq.o(.text+0x71): undefined reference to \`PQstatus' testlibpq.o(.text+0xa4): undefined reference to \`PQerrorMessage' This means you forgot `-lpq`. /usr/bin/ld: cannot find -lpq This means you forgot the `-L` option or did not specify the right directory. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/18/libpq-threading.html "32.21. Behavior in Threaded Programs") | [Up](https://www.postgresql.org/docs/18/libpq.html "Chapter 32. libpq — C Library") | [Next](https://www.postgresql.org/docs/18/libpq-example.html "32.23. Example Programs") | | 32.21. Behavior in Threaded Programs | [Home](https://www.postgresql.org/docs/18/index.html "PostgreSQL 18.1 Documentation") | 32.23. Example Programs | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/libpq-build.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 9.3: The Schema November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 9.3](https://www.postgresql.org/docs/9.3/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/infoschema-schema.html "PostgreSQL 18 - The Schema") ([18](https://www.postgresql.org/docs/18/infoschema-schema.html "PostgreSQL 18 - The Schema") ) / [17](https://www.postgresql.org/docs/17/infoschema-schema.html "PostgreSQL 17 - The Schema") / [16](https://www.postgresql.org/docs/16/infoschema-schema.html "PostgreSQL 16 - The Schema") / [15](https://www.postgresql.org/docs/15/infoschema-schema.html "PostgreSQL 15 - The Schema") / [14](https://www.postgresql.org/docs/14/infoschema-schema.html "PostgreSQL 14 - The Schema") Development Versions: [devel](https://www.postgresql.org/docs/devel/infoschema-schema.html "PostgreSQL devel - The Schema") Unsupported versions: [13](https://www.postgresql.org/docs/13/infoschema-schema.html "PostgreSQL 13 - The Schema") / [12](https://www.postgresql.org/docs/12/infoschema-schema.html "PostgreSQL 12 - The Schema") / [11](https://www.postgresql.org/docs/11/infoschema-schema.html "PostgreSQL 11 - The Schema") / [10](https://www.postgresql.org/docs/10/infoschema-schema.html "PostgreSQL 10 - The Schema") / [9.6](https://www.postgresql.org/docs/9.6/infoschema-schema.html "PostgreSQL 9.6 - The Schema") / [9.5](https://www.postgresql.org/docs/9.5/infoschema-schema.html "PostgreSQL 9.5 - The Schema") / [9.4](https://www.postgresql.org/docs/9.4/infoschema-schema.html "PostgreSQL 9.4 - The Schema") / [9.3](https://www.postgresql.org/docs/9.3/infoschema-schema.html "PostgreSQL 9.3 - The Schema") / [9.2](https://www.postgresql.org/docs/9.2/infoschema-schema.html "PostgreSQL 9.2 - The Schema") / [9.1](https://www.postgresql.org/docs/9.1/infoschema-schema.html "PostgreSQL 9.1 - The Schema") / [9.0](https://www.postgresql.org/docs/9.0/infoschema-schema.html "PostgreSQL 9.0 - The Schema") / [8.4](https://www.postgresql.org/docs/8.4/infoschema-schema.html "PostgreSQL 8.4 - The Schema") / [8.3](https://www.postgresql.org/docs/8.3/infoschema-schema.html "PostgreSQL 8.3 - The Schema") / [8.2](https://www.postgresql.org/docs/8.2/infoschema-schema.html "PostgreSQL 8.2 - The Schema") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/infoschema-schema.html "PostgreSQL - The Schema") version, or one of the other supported versions listed above instead. | [PostgreSQL 9.3.25 Documentation](https://www.postgresql.org/docs/9.3/index.html) | | | | | | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/information-schema.html "The Information Schema") | [Up](https://www.postgresql.org/docs/9.3/information-schema.html) | Chapter 34. The Information Schema | [Next](https://www.postgresql.org/docs/9.3/infoschema-datatypes.html "Data Types") | * * * 34.1. The Schema ================ The information schema itself is a schema named information\_schema. This schema automatically exists in all databases. The owner of this schema is the initial database user in the cluster, and that user naturally has all the privileges on this schema, including the ability to drop it (but the space savings achieved by that are minuscule). By default, the information schema is not in the schema search path, so you need to access all objects in it through qualified names. Since the names of some of the objects in the information schema are generic names that might occur in user applications, you should be careful if you want to put the information schema in the path. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/information-schema.html) | [Home](https://www.postgresql.org/docs/9.3/index.html) | [Next](https://www.postgresql.org/docs/9.3/infoschema-datatypes.html) | | The Information Schema | [Up](https://www.postgresql.org/docs/9.3/information-schema.html) | Data Types | --- # PostgreSQL: Documentation: 9.3: pgcrypto November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 9.3](https://www.postgresql.org/docs/9.3/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/pgcrypto.html "PostgreSQL 18 - pgcrypto") ([18](https://www.postgresql.org/docs/18/pgcrypto.html "PostgreSQL 18 - pgcrypto") ) / [17](https://www.postgresql.org/docs/17/pgcrypto.html "PostgreSQL 17 - pgcrypto") / [16](https://www.postgresql.org/docs/16/pgcrypto.html "PostgreSQL 16 - pgcrypto") / [15](https://www.postgresql.org/docs/15/pgcrypto.html "PostgreSQL 15 - pgcrypto") / [14](https://www.postgresql.org/docs/14/pgcrypto.html "PostgreSQL 14 - pgcrypto") Development Versions: [devel](https://www.postgresql.org/docs/devel/pgcrypto.html "PostgreSQL devel - pgcrypto") Unsupported versions: [13](https://www.postgresql.org/docs/13/pgcrypto.html "PostgreSQL 13 - pgcrypto") / [12](https://www.postgresql.org/docs/12/pgcrypto.html "PostgreSQL 12 - pgcrypto") / [11](https://www.postgresql.org/docs/11/pgcrypto.html "PostgreSQL 11 - pgcrypto") / [10](https://www.postgresql.org/docs/10/pgcrypto.html "PostgreSQL 10 - pgcrypto") / [9.6](https://www.postgresql.org/docs/9.6/pgcrypto.html "PostgreSQL 9.6 - pgcrypto") / [9.5](https://www.postgresql.org/docs/9.5/pgcrypto.html "PostgreSQL 9.5 - pgcrypto") / [9.4](https://www.postgresql.org/docs/9.4/pgcrypto.html "PostgreSQL 9.4 - pgcrypto") / [9.3](https://www.postgresql.org/docs/9.3/pgcrypto.html "PostgreSQL 9.3 - pgcrypto") / [9.2](https://www.postgresql.org/docs/9.2/pgcrypto.html "PostgreSQL 9.2 - pgcrypto") / [9.1](https://www.postgresql.org/docs/9.1/pgcrypto.html "PostgreSQL 9.1 - pgcrypto") / [9.0](https://www.postgresql.org/docs/9.0/pgcrypto.html "PostgreSQL 9.0 - pgcrypto") / [8.4](https://www.postgresql.org/docs/8.4/pgcrypto.html "PostgreSQL 8.4 - pgcrypto") / [8.3](https://www.postgresql.org/docs/8.3/pgcrypto.html "PostgreSQL 8.3 - pgcrypto") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/pgcrypto.html "PostgreSQL - pgcrypto") version, or one of the other supported versions listed above instead. | [PostgreSQL 9.3.25 Documentation](https://www.postgresql.org/docs/9.3/index.html) | | | | | | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/pgbuffercache.html "pg_buffercache") | [Up](https://www.postgresql.org/docs/9.3/contrib.html) | Appendix F. Additional Supplied Modules | [Next](https://www.postgresql.org/docs/9.3/pgfreespacemap.html "pg_freespacemap") | * * * F.25. pgcrypto ============== The pgcrypto module provides cryptographic functions for PostgreSQL. F.25.1. General Hashing Functions --------------------------------- ### F.25.1.1. `digest()` digest(data text, type text) returns bytea digest(data bytea, type text) returns bytea Computes a binary hash of the given data. type is the algorithm to use. Standard algorithms are md5, sha1, sha224, sha256, sha384 and sha512. If pgcrypto was built with OpenSSL, more algorithms are available, as detailed in [Table F-20](https://www.postgresql.org/docs/9.3/pgcrypto.html#PGCRYPTO-WITH-WITHOUT-OPENSSL) . If you want the digest as a hexadecimal string, use `encode()` on the result. For example: CREATE OR REPLACE FUNCTION sha1(bytea) returns text AS $$ SELECT encode(digest($1, 'sha1'), 'hex') $$ LANGUAGE SQL STRICT IMMUTABLE; ### F.25.1.2. `hmac()` hmac(data text, key text, type text) returns bytea hmac(data bytea, key bytea, type text) returns bytea Calculates hashed MAC for data with key key. type is the same as in `digest()`. This is similar to `digest()` but the hash can only be recalculated knowing the key. This prevents the scenario of someone altering data and also changing the hash to match. If the key is larger than the hash block size it will first be hashed and the result will be used as key. F.25.2. Password Hashing Functions ---------------------------------- The functions `crypt()` and `gen_salt()` are specifically designed for hashing passwords. `crypt()` does the hashing and `gen_salt()` prepares algorithm parameters for it. The algorithms in `crypt()` differ from the usual MD5 or SHA1 hashing algorithms in the following respects: 1. They are slow. As the amount of data is so small, this is the only way to make brute-forcing passwords hard. 2. They use a random value, called the _salt_, so that users having the same password will have different encrypted passwords. This is also an additional defense against reversing the algorithm. 3. They include the algorithm type in the result, so passwords hashed with different algorithms can co-exist. 4. Some of them are adaptive — that means when computers get faster, you can tune the algorithm to be slower, without introducing incompatibility with existing passwords. [Table F-17](https://www.postgresql.org/docs/9.3/pgcrypto.html#PGCRYPTO-CRYPT-ALGORITHMS) lists the algorithms supported by the `crypt()` function. **Table F-17. Supported Algorithms for `crypt()`** | Algorithm | Max Password Length | Adaptive? | Salt Bits | Output Length | Description | | --- | --- | --- | --- | --- | --- | | bf | 72 | yes | 128 | 60 | Blowfish-based, variant 2a | | md5 | unlimited | no | 48 | 34 | MD5-based crypt | | xdes | 8 | yes | 24 | 20 | Extended DES | | des | 8 | no | 12 | 13 | Original UNIX crypt | ### F.25.2.1. `crypt()` crypt(password text, salt text) returns text Calculates a crypt(3)-style hash of password. When storing a new password, you need to use `gen_salt()` to generate a new salt value. To check a password, pass the stored hash value as salt, and test whether the result matches the stored value. Example of setting a new password: UPDATE ... SET pswhash = crypt('new password', gen\_salt('md5')); Example of authentication: SELECT (pswhash = crypt('entered password', pswhash)) AS pswmatch FROM ... ; This returns true if the entered password is correct. ### F.25.2.2. `gen_salt()` gen\_salt(type text \[, iter\_count integer \]) returns text Generates a new random salt string for use in `crypt()`. The salt string also tells `crypt()` which algorithm to use. The type parameter specifies the hashing algorithm. The accepted types are: des, xdes, md5 and bf. The iter\_count parameter lets the user specify the iteration count, for algorithms that have one. The higher the count, the more time it takes to hash the password and therefore the more time to break it. Although with too high a count the time to calculate a hash may be several years — which is somewhat impractical. If the iter\_count parameter is omitted, the default iteration count is used. Allowed values for iter\_count depend on the algorithm and are shown in [Table F-18](https://www.postgresql.org/docs/9.3/pgcrypto.html#PGCRYPTO-ICFC-TABLE) . **Table F-18. Iteration Counts for `crypt()`** | Algorithm | Default | Min | Max | | --- | --- | --- | --- | | xdes | 725 | 1 | 16777215 | | bf | 6 | 4 | 31 | For xdes there is an additional limitation that the iteration count must be an odd number. To pick an appropriate iteration count, consider that the original DES crypt was designed to have the speed of 4 hashes per second on the hardware of that time. Slower than 4 hashes per second would probably dampen usability. Faster than 100 hashes per second is probably too fast. [Table F-19](https://www.postgresql.org/docs/9.3/pgcrypto.html#PGCRYPTO-HASH-SPEED-TABLE) gives an overview of the relative slowness of different hashing algorithms. The table shows how much time it would take to try all combinations of characters in an 8-character password, assuming that the password contains either only lower case letters, or upper- and lower-case letters and numbers. In the crypt-bf entries, the number after a slash is the iter\_count parameter of `gen_salt`. **Table F-19. Hash Algorithm Speeds** | Algorithm | Hashes/sec | For \[a-z\] | For \[A-Za-z0-9\] | | --- | --- | --- | --- | | crypt-bf/8 | 28 | 246 years | 251322 years | | crypt-bf/7 | 57 | 121 years | 123457 years | | crypt-bf/6 | 112 | 62 years | 62831 years | | crypt-bf/5 | 211 | 33 years | 33351 years | | crypt-md5 | 2681 | 2.6 years | 2625 years | | crypt-des | 362837 | 7 days | 19 years | | sha1 | 590223 | 4 days | 12 years | | md5 hash | 2345086 | 1 day | 3 years | Notes: * The machine used is a 1.5GHz Pentium 4. * crypt-des and crypt-md5 algorithm numbers are taken from John the Ripper v1.6.38 \-test output. * md5 hash numbers are from mdcrack 1.2. * sha1 numbers are from lcrack-20031130-beta. * crypt-bf numbers are taken using a simple program that loops over 1000 8-character passwords. That way I can show the speed with different numbers of iterations. For reference: john -test shows 213 loops/sec for crypt-bf/5. (The very small difference in results is in accordance with the fact that the crypt-bf implementation in pgcrypto is the same one used in John the Ripper.) Note that "try all combinations" is not a realistic exercise. Usually password cracking is done with the help of dictionaries, which contain both regular words and various mutations of them. So, even somewhat word-like passwords could be cracked much faster than the above numbers suggest, while a 6-character non-word-like password may escape cracking. Or not. F.25.3. PGP Encryption Functions -------------------------------- The functions here implement the encryption part of the OpenPGP (RFC 4880) standard. Supported are both symmetric-key and public-key encryption. An encrypted PGP message consists of 2 parts, or _packets_: * Packet containing a session key — either symmetric-key or public-key encrypted. * Packet containing data encrypted with the session key. When encrypting with a symmetric key (i.e., a password): 1. The given password is hashed using a String2Key (S2K) algorithm. This is rather similar to `crypt()` algorithms — purposefully slow and with random salt — but it produces a full-length binary key. 2. If a separate session key is requested, a new random key will be generated. Otherwise the S2K key will be used directly as the session key. 3. If the S2K key is to be used directly, then only S2K settings will be put into the session key packet. Otherwise the session key will be encrypted with the S2K key and put into the session key packet. When encrypting with a public key: 1. A new random session key is generated. 2. It is encrypted using the public key and put into the session key packet. In either case the data to be encrypted is processed as follows: 1. Optional data-manipulation: compression, conversion to UTF-8, and/or conversion of line-endings. 2. The data is prefixed with a block of random bytes. This is equivalent to using a random IV. 3. An SHA1 hash of the random prefix and data is appended. 4. All this is encrypted with the session key and placed in the data packet. ### F.25.3.1. `pgp_sym_encrypt()` pgp\_sym\_encrypt(data text, psw text \[, options text \]) returns bytea pgp\_sym\_encrypt\_bytea(data bytea, psw text \[, options text \]) returns bytea Encrypt data with a symmetric PGP key psw. The options parameter can contain option settings, as described below. ### F.25.3.2. `pgp_sym_decrypt()` pgp\_sym\_decrypt(msg bytea, psw text \[, options text \]) returns text pgp\_sym\_decrypt\_bytea(msg bytea, psw text \[, options text \]) returns bytea Decrypt a symmetric-key-encrypted PGP message. Decrypting bytea data with `pgp_sym_decrypt` is disallowed. This is to avoid outputting invalid character data. Decrypting originally textual data with `pgp_sym_decrypt_bytea` is fine. The options parameter can contain option settings, as described below. ### F.25.3.3. `pgp_pub_encrypt()` pgp\_pub\_encrypt(data text, key bytea \[, options text \]) returns bytea pgp\_pub\_encrypt\_bytea(data bytea, key bytea \[, options text \]) returns bytea Encrypt data with a public PGP key key. Giving this function a secret key will produce an error. The options parameter can contain option settings, as described below. ### F.25.3.4. `pgp_pub_decrypt()` pgp\_pub\_decrypt(msg bytea, key bytea \[, psw text \[, options text \]\]) returns text pgp\_pub\_decrypt\_bytea(msg bytea, key bytea \[, psw text \[, options text \]\]) returns bytea Decrypt a public-key-encrypted message. key must be the secret key corresponding to the public key that was used to encrypt. If the secret key is password-protected, you must give the password in psw. If there is no password, but you want to specify options, you need to give an empty password. Decrypting bytea data with `pgp_pub_decrypt` is disallowed. This is to avoid outputting invalid character data. Decrypting originally textual data with `pgp_pub_decrypt_bytea` is fine. The options parameter can contain option settings, as described below. ### F.25.3.5. `pgp_key_id()` pgp\_key\_id(bytea) returns text `pgp_key_id` extracts the key ID of a PGP public or secret key. Or it gives the key ID that was used for encrypting the data, if given an encrypted message. It can return 2 special key IDs: * SYMKEY The message is encrypted with a symmetric key. * ANYKEY The message is public-key encrypted, but the key ID has been removed. That means you will need to try all your secret keys on it to see which one decrypts it. pgcrypto itself does not produce such messages. Note that different keys may have the same ID. This is rare but a normal event. The client application should then try to decrypt with each one, to see which fits — like handling ANYKEY. ### F.25.3.6. `armor()`, `dearmor()` armor(data bytea) returns text dearmor(data text) returns bytea These functions wrap/unwrap binary data into PGP ASCII-armor format, which is basically Base64 with CRC and additional formatting. ### F.25.3.7. Options for PGP Functions Options are named to be similar to GnuPG. An option's value should be given after an equal sign; separate options from each other with commas. For example: pgp\_sym\_encrypt(data, psw, 'compress-algo=1, cipher-algo=aes256') All of the options except convert-crlf apply only to encrypt functions. Decrypt functions get the parameters from the PGP data. The most interesting options are probably compress-algo and unicode-mode. The rest should have reasonable defaults. #### F.25.3.7.1. cipher-algo Which cipher algorithm to use. Values: bf, aes128, aes192, aes256 (OpenSSL-only: 3des, cast5) Default: aes128 Applies to: pgp\_sym\_encrypt, pgp\_pub\_encrypt #### F.25.3.7.2. compress-algo Which compression algorithm to use. Only available if PostgreSQL was built with zlib. Values:   0 - no compression   1 - ZIP compression   2 - ZLIB compression (= ZIP plus meta-data and block CRCs) Default: 0 Applies to: pgp\_sym\_encrypt, pgp\_pub\_encrypt #### F.25.3.7.3. compress-level How much to compress. Higher levels compress smaller but are slower. 0 disables compression. Values: 0, 1-9 Default: 6 Applies to: pgp\_sym\_encrypt, pgp\_pub\_encrypt #### F.25.3.7.4. convert-crlf Whether to convert \\n into \\r\\n when encrypting and \\r\\n to \\n when decrypting. RFC 4880 specifies that text data should be stored using \\r\\n line-feeds. Use this to get fully RFC-compliant behavior. Values: 0, 1 Default: 0 Applies to: pgp\_sym\_encrypt, pgp\_pub\_encrypt, pgp\_sym\_decrypt, pgp\_pub\_decrypt #### F.25.3.7.5. disable-mdc Do not protect data with SHA-1. The only good reason to use this option is to achieve compatibility with ancient PGP products, predating the addition of SHA-1 protected packets to RFC 4880. Recent gnupg.org and pgp.com software supports it fine. Values: 0, 1 Default: 0 Applies to: pgp\_sym\_encrypt, pgp\_pub\_encrypt #### F.25.3.7.6. sess-key Use separate session key. Public-key encryption always uses a separate session key; this option is for symmetric-key encryption, which by default uses the S2K key directly. Values: 0, 1 Default: 0 Applies to: pgp\_sym\_encrypt #### F.25.3.7.7. s2k-mode Which S2K algorithm to use. Values:   0 - Without salt.  Dangerous!   1 - With salt but with fixed iteration count.   3 - Variable iteration count. Default: 3 Applies to: pgp\_sym\_encrypt #### F.25.3.7.8. s2k-digest-algo Which digest algorithm to use in S2K calculation. Values: md5, sha1 Default: sha1 Applies to: pgp\_sym\_encrypt #### F.25.3.7.9. s2k-cipher-algo Which cipher to use for encrypting separate session key. Values: bf, aes, aes128, aes192, aes256 Default: use cipher-algo Applies to: pgp\_sym\_encrypt #### F.25.3.7.10. unicode-mode Whether to convert textual data from database internal encoding to UTF-8 and back. If your database already is UTF-8, no conversion will be done, but the message will be tagged as UTF-8. Without this option it will not be. Values: 0, 1 Default: 0 Applies to: pgp\_sym\_encrypt, pgp\_pub\_encrypt ### F.25.3.8. Generating PGP Keys with GnuPG To generate a new key: gpg --gen-key The preferred key type is "DSA and Elgamal". For RSA encryption you must create either DSA or RSA sign-only key as master and then add an RSA encryption subkey with gpg --edit-key. To list keys: gpg --list-secret-keys To export a public key in ASCII-armor format: gpg -a --export KEYID > public.key To export a secret key in ASCII-armor format: gpg -a --export-secret-keys KEYID > secret.key You need to use `dearmor()` on these keys before giving them to the PGP functions. Or if you can handle binary data, you can drop \-a from the command. For more details see man gpg, [The GNU Privacy Handbook](http://www.gnupg.org/gph/en/manual.html) and other documentation on [http://www.gnupg.org](http://www.gnupg.org/) . ### F.25.3.9. Limitations of PGP Code * No support for signing. That also means that it is not checked whether the encryption subkey belongs to the master key. * No support for encryption key as master key. As such practice is generally discouraged, this should not be a problem. * No support for several subkeys. This may seem like a problem, as this is common practice. On the other hand, you should not use your regular GPG/PGP keys with pgcrypto, but create new ones, as the usage scenario is rather different. F.25.4. Raw Encryption Functions -------------------------------- These functions only run a cipher over data; they don't have any advanced features of PGP encryption. Therefore they have some major problems: 1. They use user key directly as cipher key. 2. They don't provide any integrity checking, to see if the encrypted data was modified. 3. They expect that users manage all encryption parameters themselves, even IV. 4. They don't handle text. So, with the introduction of PGP encryption, usage of raw encryption functions is discouraged. encrypt(data bytea, key bytea, type text) returns bytea decrypt(data bytea, key bytea, type text) returns bytea encrypt\_iv(data bytea, key bytea, iv bytea, type text) returns bytea decrypt\_iv(data bytea, key bytea, iv bytea, type text) returns bytea Encrypt/decrypt data using the cipher method specified by type. The syntax of the type string is: algorithm \[ \- mode \] \[ /pad: padding \] where algorithm is one of: * bf — Blowfish * aes — AES (Rijndael-128, -192 or -256) and mode is one of: * cbc — next block depends on previous (default) * ecb — each block is encrypted separately (for testing only) and padding is one of: * pkcs — data may be any length (default) * none — data must be multiple of cipher block size So, for example, these are equivalent: encrypt(data, 'fooz', 'bf') encrypt(data, 'fooz', 'bf-cbc/pad:pkcs') In `encrypt_iv` and `decrypt_iv`, the iv parameter is the initial value for the CBC mode; it is ignored for ECB. It is clipped or padded with zeroes if not exactly block size. It defaults to all zeroes in the functions without this parameter. F.25.5. Random-Data Functions ----------------------------- gen\_random\_bytes(count integer) returns bytea Returns count cryptographically strong random bytes. At most 1024 bytes can be extracted at a time. This is to avoid draining the randomness generator pool. F.25.6. Notes ------------- ### F.25.6.1. Configuration pgcrypto configures itself according to the findings of the main PostgreSQL configure script. The options that affect it are \--with-zlib and \--with-openssl. When compiled with zlib, PGP encryption functions are able to compress data before encrypting. When compiled with OpenSSL, there will be more algorithms available. Also public-key encryption functions will be faster as OpenSSL has more optimized BIGNUM functions. **Table F-20. Summary of Functionality with and without OpenSSL** | Functionality | Built-in | With OpenSSL | | --- | --- | --- | | MD5 | yes | yes | | SHA1 | yes | yes | | SHA224/256/384/512 | yes | yes (Note 1) | | Other digest algorithms | no | yes (Note 2) | | Blowfish | yes | yes | | AES | yes | yes (Note 3) | | DES/3DES/CAST5 | no | yes | | Raw encryption | yes | yes | | PGP Symmetric encryption | yes | yes | | PGP Public-Key encryption | yes | yes | Notes: 1. SHA2 algorithms were added to OpenSSL in version 0.9.8. For older versions, pgcrypto will use built-in code. 2. Any digest algorithm OpenSSL supports is automatically picked up. This is not possible with ciphers, which need to be supported explicitly. 3. AES is included in OpenSSL since version 0.9.7. For older versions, pgcrypto will use built-in code. ### F.25.6.2. NULL Handling As is standard in SQL, all functions return NULL, if any of the arguments are NULL. This may create security risks on careless usage. ### F.25.6.3. Security Limitations All pgcrypto functions run inside the database server. That means that all the data and passwords move between pgcrypto and client applications in clear text. Thus you must: 1. Connect locally or use SSL connections. 2. Trust both system and database administrator. If you cannot, then better do crypto inside client application. The implementation does not resist [side-channel attacks](http://en.wikipedia.org/wiki/Side-channel_attack) . For example, the time required for a pgcrypto decryption function to complete varies among ciphertexts of a given size. ### F.25.6.4. Useful Reading * [http://www.gnupg.org/gph/en/manual.html](http://www.gnupg.org/gph/en/manual.html) The GNU Privacy Handbook. * [http://www.openwall.com/crypt/](http://www.openwall.com/crypt/) Describes the crypt-blowfish algorithm. * [http://www.stack.nl/~galactus/remailers/passphrase-faq.html](http://www.stack.nl/~galactus/remailers/passphrase-faq.html) How to choose a good password. * [http://world.std.com/~reinhold/diceware.html](http://world.std.com/~reinhold/diceware.html) Interesting idea for picking passwords. * [http://www.interhack.net/people/cmcurtin/snake-oil-faq.html](http://www.interhack.net/people/cmcurtin/snake-oil-faq.html) Describes good and bad cryptography. ### F.25.6.5. Technical References * [http://www.ietf.org/rfc/rfc4880.txt](http://www.ietf.org/rfc/rfc4880.txt) OpenPGP message format. * [http://www.ietf.org/rfc/rfc1321.txt](http://www.ietf.org/rfc/rfc1321.txt) The MD5 Message-Digest Algorithm. * [http://www.ietf.org/rfc/rfc2104.txt](http://www.ietf.org/rfc/rfc2104.txt) HMAC: Keyed-Hashing for Message Authentication. * [http://www.usenix.org/events/usenix99/provos.html](http://www.usenix.org/events/usenix99/provos.html) Comparison of crypt-des, crypt-md5 and bcrypt algorithms. * [http://csrc.nist.gov/cryptval/des.htm](http://csrc.nist.gov/cryptval/des.htm) Standards for DES, 3DES and AES. * [http://en.wikipedia.org/wiki/Fortuna\_(PRNG)](http://en.wikipedia.org/wiki/Fortuna_(PRNG)) Description of Fortuna CSPRNG. * [http://jlcooke.ca/random/](http://jlcooke.ca/random/) Jean-Luc Cooke Fortuna-based /dev/random driver for Linux. F.25.7. Author -------------- Marko Kreen `<[markokr@gmail.com](mailto:markokr@gmail.com) >` pgcrypto uses code from the following sources: | Algorithm | Author | Source origin | | --- | --- | --- | | DES crypt | David Burren and others | FreeBSD libcrypt | | MD5 crypt | Poul-Henning Kamp | FreeBSD libcrypt | | Blowfish crypt | Solar Designer | www.openwall.com | | Blowfish cipher | Simon Tatham | PuTTY | | Rijndael cipher | Brian Gladman | OpenBSD sys/crypto | | MD5 hash and SHA1 | WIDE Project | KAME kame/sys/crypto | | SHA256/384/512 | Aaron D. Gifford | OpenBSD sys/crypto | | BIGNUM math | Michael J. Fromberger | dartmouth.edu/~sting/sw/imath | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/pgbuffercache.html) | [Home](https://www.postgresql.org/docs/9.3/index.html) | [Next](https://www.postgresql.org/docs/9.3/pgfreespacemap.html) | | pg\_buffercache | [Up](https://www.postgresql.org/docs/9.3/contrib.html) | pg\_freespacemap | --- # PostgreSQL: Documentation: 9.3: CREATE USER MAPPING November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 9.3](https://www.postgresql.org/docs/9.3/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-createusermapping.html "PostgreSQL 18 - CREATE USER MAPPING") ([18](https://www.postgresql.org/docs/18/sql-createusermapping.html "PostgreSQL 18 - CREATE USER MAPPING") ) / [17](https://www.postgresql.org/docs/17/sql-createusermapping.html "PostgreSQL 17 - CREATE USER MAPPING") / [16](https://www.postgresql.org/docs/16/sql-createusermapping.html "PostgreSQL 16 - CREATE USER MAPPING") / [15](https://www.postgresql.org/docs/15/sql-createusermapping.html "PostgreSQL 15 - CREATE USER MAPPING") / [14](https://www.postgresql.org/docs/14/sql-createusermapping.html "PostgreSQL 14 - CREATE USER MAPPING") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-createusermapping.html "PostgreSQL devel - CREATE USER MAPPING") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-createusermapping.html "PostgreSQL 13 - CREATE USER MAPPING") / [12](https://www.postgresql.org/docs/12/sql-createusermapping.html "PostgreSQL 12 - CREATE USER MAPPING") / [11](https://www.postgresql.org/docs/11/sql-createusermapping.html "PostgreSQL 11 - CREATE USER MAPPING") / [10](https://www.postgresql.org/docs/10/sql-createusermapping.html "PostgreSQL 10 - CREATE USER MAPPING") / [9.6](https://www.postgresql.org/docs/9.6/sql-createusermapping.html "PostgreSQL 9.6 - CREATE USER MAPPING") / [9.5](https://www.postgresql.org/docs/9.5/sql-createusermapping.html "PostgreSQL 9.5 - CREATE USER MAPPING") / [9.4](https://www.postgresql.org/docs/9.4/sql-createusermapping.html "PostgreSQL 9.4 - CREATE USER MAPPING") / [9.3](https://www.postgresql.org/docs/9.3/sql-createusermapping.html "PostgreSQL 9.3 - CREATE USER MAPPING") / [9.2](https://www.postgresql.org/docs/9.2/sql-createusermapping.html "PostgreSQL 9.2 - CREATE USER MAPPING") / [9.1](https://www.postgresql.org/docs/9.1/sql-createusermapping.html "PostgreSQL 9.1 - CREATE USER MAPPING") / [9.0](https://www.postgresql.org/docs/9.0/sql-createusermapping.html "PostgreSQL 9.0 - CREATE USER MAPPING") / [8.4](https://www.postgresql.org/docs/8.4/sql-createusermapping.html "PostgreSQL 8.4 - CREATE USER MAPPING") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/sql-createusermapping.html "PostgreSQL - CREATE USER MAPPING") version, or one of the other supported versions listed above instead. | [PostgreSQL 9.3.25 Documentation](https://www.postgresql.org/docs/9.3/index.html) | | | | | | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/sql-createuser.html "CREATE USER") | [Up](https://www.postgresql.org/docs/9.3/sql-commands.html) | | [Next](https://www.postgresql.org/docs/9.3/sql-createview.html "CREATE VIEW") | * * * CREATE USER MAPPING =================== Name ---- CREATE USER MAPPING -- define a new mapping of a user to a foreign server Synopsis -------- CREATE USER MAPPING FOR { user\_name | USER | CURRENT\_USER | PUBLIC } SERVER server\_name \[ OPTIONS ( option 'value' \[ , ... \] ) \] Description ----------- CREATE USER MAPPING defines a mapping of a user to a foreign server. A user mapping typically encapsulates connection information that a foreign-data wrapper uses together with the information encapsulated by a foreign server to access an external data resource. The owner of a foreign server can create user mappings for that server for any user. Also, a user can create a user mapping for his own user name if USAGE privilege on the server has been granted to the user. Parameters ---------- user\_name The name of an existing user that is mapped to foreign server. CURRENT\_USER and USER match the name of the current user. When PUBLIC is specified, a so-called public mapping is created that is used when no user-specific mapping is applicable. server\_name The name of an existing server for which the user mapping is to be created. OPTIONS ( option 'value' \[, ... \] ) This clause specifies the options of the user mapping. The options typically define the actual user name and password of the mapping. Option names must be unique. The allowed option names and values are specific to the server's foreign-data wrapper. Examples -------- Create a user mapping for user bob, server foo: CREATE USER MAPPING FOR bob SERVER foo OPTIONS (user 'bob', password 'secret'); Compatibility ------------- CREATE USER MAPPING conforms to ISO/IEC 9075-9 (SQL/MED). See Also -------- [ALTER USER MAPPING](https://www.postgresql.org/docs/9.3/sql-alterusermapping.html) , [DROP USER MAPPING](https://www.postgresql.org/docs/9.3/sql-dropusermapping.html) , [CREATE FOREIGN DATA WRAPPER](https://www.postgresql.org/docs/9.3/sql-createforeigndatawrapper.html) , [CREATE SERVER](https://www.postgresql.org/docs/9.3/sql-createserver.html) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/sql-createuser.html) | [Home](https://www.postgresql.org/docs/9.3/index.html) | [Next](https://www.postgresql.org/docs/9.3/sql-createview.html) | | CREATE USER | [Up](https://www.postgresql.org/docs/9.3/sql-commands.html) | CREATE VIEW | --- # PostgreSQL: Documentation: 9.3: DEALLOCATE DESCRIPTOR November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 9.3](https://www.postgresql.org/docs/9.3/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/ecpg-sql-deallocate-descriptor.html "PostgreSQL 18 - DEALLOCATE DESCRIPTOR") ([18](https://www.postgresql.org/docs/18/ecpg-sql-deallocate-descriptor.html "PostgreSQL 18 - DEALLOCATE DESCRIPTOR") ) / [17](https://www.postgresql.org/docs/17/ecpg-sql-deallocate-descriptor.html "PostgreSQL 17 - DEALLOCATE DESCRIPTOR") / [16](https://www.postgresql.org/docs/16/ecpg-sql-deallocate-descriptor.html "PostgreSQL 16 - DEALLOCATE DESCRIPTOR") / [15](https://www.postgresql.org/docs/15/ecpg-sql-deallocate-descriptor.html "PostgreSQL 15 - DEALLOCATE DESCRIPTOR") / [14](https://www.postgresql.org/docs/14/ecpg-sql-deallocate-descriptor.html "PostgreSQL 14 - DEALLOCATE DESCRIPTOR") Development Versions: [devel](https://www.postgresql.org/docs/devel/ecpg-sql-deallocate-descriptor.html "PostgreSQL devel - DEALLOCATE DESCRIPTOR") Unsupported versions: [13](https://www.postgresql.org/docs/13/ecpg-sql-deallocate-descriptor.html "PostgreSQL 13 - DEALLOCATE DESCRIPTOR") / [12](https://www.postgresql.org/docs/12/ecpg-sql-deallocate-descriptor.html "PostgreSQL 12 - DEALLOCATE DESCRIPTOR") / [11](https://www.postgresql.org/docs/11/ecpg-sql-deallocate-descriptor.html "PostgreSQL 11 - DEALLOCATE DESCRIPTOR") / [10](https://www.postgresql.org/docs/10/ecpg-sql-deallocate-descriptor.html "PostgreSQL 10 - DEALLOCATE DESCRIPTOR") / [9.6](https://www.postgresql.org/docs/9.6/ecpg-sql-deallocate-descriptor.html "PostgreSQL 9.6 - DEALLOCATE DESCRIPTOR") / [9.5](https://www.postgresql.org/docs/9.5/ecpg-sql-deallocate-descriptor.html "PostgreSQL 9.5 - DEALLOCATE DESCRIPTOR") / [9.4](https://www.postgresql.org/docs/9.4/ecpg-sql-deallocate-descriptor.html "PostgreSQL 9.4 - DEALLOCATE DESCRIPTOR") / [9.3](https://www.postgresql.org/docs/9.3/ecpg-sql-deallocate-descriptor.html "PostgreSQL 9.3 - DEALLOCATE DESCRIPTOR") / [9.2](https://www.postgresql.org/docs/9.2/ecpg-sql-deallocate-descriptor.html "PostgreSQL 9.2 - DEALLOCATE DESCRIPTOR") / [9.1](https://www.postgresql.org/docs/9.1/ecpg-sql-deallocate-descriptor.html "PostgreSQL 9.1 - DEALLOCATE DESCRIPTOR") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/ecpg-sql-deallocate-descriptor.html "PostgreSQL - DEALLOCATE DESCRIPTOR") version, or one of the other supported versions listed above instead. | [PostgreSQL 9.3.25 Documentation](https://www.postgresql.org/docs/9.3/index.html) | | | | | | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/ecpg-sql-connect.html "CONNECT") | [Up](https://www.postgresql.org/docs/9.3/ecpg-sql-commands.html) | | [Next](https://www.postgresql.org/docs/9.3/ecpg-sql-declare.html "DECLARE") | * * * DEALLOCATE DESCRIPTOR ===================== Name ---- DEALLOCATE DESCRIPTOR -- deallocate an SQL descriptor area Synopsis -------- DEALLOCATE DESCRIPTOR name Description ----------- DEALLOCATE DESCRIPTOR deallocates a named SQL descriptor area. Parameters ---------- name The name of the descriptor which is going to be deallocated. It is case sensitive. This can be an SQL identifier or a host variable. Examples -------- EXEC SQL DEALLOCATE DESCRIPTOR mydesc; Compatibility ------------- DEALLOCATE DESCRIPTOR is specified in the SQL standard. See Also -------- [ALLOCATE DESCRIPTOR](https://www.postgresql.org/docs/9.3/ecpg-sql-allocate-descriptor.html) , [GET DESCRIPTOR](https://www.postgresql.org/docs/9.3/ecpg-sql-get-descriptor.html) , [SET DESCRIPTOR](https://www.postgresql.org/docs/9.3/ecpg-sql-set-descriptor.html) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.3/ecpg-sql-connect.html) | [Home](https://www.postgresql.org/docs/9.3/index.html) | [Next](https://www.postgresql.org/docs/9.3/ecpg-sql-declare.html) | | CONNECT | [Up](https://www.postgresql.org/docs/9.3/ecpg-sql-commands.html) | DECLARE | --- # PostgreSQL: Documentation: 16: ALTER LANGUAGE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 16](https://www.postgresql.org/docs/16/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alterlanguage.html "PostgreSQL 18 - ALTER LANGUAGE") ([18](https://www.postgresql.org/docs/18/sql-alterlanguage.html "PostgreSQL 18 - ALTER LANGUAGE") ) / [17](https://www.postgresql.org/docs/17/sql-alterlanguage.html "PostgreSQL 17 - ALTER LANGUAGE") / [16](https://www.postgresql.org/docs/16/sql-alterlanguage.html "PostgreSQL 16 - ALTER LANGUAGE") / [15](https://www.postgresql.org/docs/15/sql-alterlanguage.html "PostgreSQL 15 - ALTER LANGUAGE") / [14](https://www.postgresql.org/docs/14/sql-alterlanguage.html "PostgreSQL 14 - ALTER LANGUAGE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alterlanguage.html "PostgreSQL devel - ALTER LANGUAGE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alterlanguage.html "PostgreSQL 13 - ALTER LANGUAGE") / [12](https://www.postgresql.org/docs/12/sql-alterlanguage.html "PostgreSQL 12 - ALTER LANGUAGE") / [11](https://www.postgresql.org/docs/11/sql-alterlanguage.html "PostgreSQL 11 - ALTER LANGUAGE") / [10](https://www.postgresql.org/docs/10/sql-alterlanguage.html "PostgreSQL 10 - ALTER LANGUAGE") / [9.6](https://www.postgresql.org/docs/9.6/sql-alterlanguage.html "PostgreSQL 9.6 - ALTER LANGUAGE") / [9.5](https://www.postgresql.org/docs/9.5/sql-alterlanguage.html "PostgreSQL 9.5 - ALTER LANGUAGE") / [9.4](https://www.postgresql.org/docs/9.4/sql-alterlanguage.html "PostgreSQL 9.4 - ALTER LANGUAGE") / [9.3](https://www.postgresql.org/docs/9.3/sql-alterlanguage.html "PostgreSQL 9.3 - ALTER LANGUAGE") / [9.2](https://www.postgresql.org/docs/9.2/sql-alterlanguage.html "PostgreSQL 9.2 - ALTER LANGUAGE") / [9.1](https://www.postgresql.org/docs/9.1/sql-alterlanguage.html "PostgreSQL 9.1 - ALTER LANGUAGE") / [9.0](https://www.postgresql.org/docs/9.0/sql-alterlanguage.html "PostgreSQL 9.0 - ALTER LANGUAGE") / [8.4](https://www.postgresql.org/docs/8.4/sql-alterlanguage.html "PostgreSQL 8.4 - ALTER LANGUAGE") / [8.3](https://www.postgresql.org/docs/8.3/sql-alterlanguage.html "PostgreSQL 8.3 - ALTER LANGUAGE") / [8.2](https://www.postgresql.org/docs/8.2/sql-alterlanguage.html "PostgreSQL 8.2 - ALTER LANGUAGE") / [8.1](https://www.postgresql.org/docs/8.1/sql-alterlanguage.html "PostgreSQL 8.1 - ALTER LANGUAGE") / [8.0](https://www.postgresql.org/docs/8.0/sql-alterlanguage.html "PostgreSQL 8.0 - ALTER LANGUAGE") / [7.4](https://www.postgresql.org/docs/7.4/sql-alterlanguage.html "PostgreSQL 7.4 - ALTER LANGUAGE") | ALTER LANGUAGE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/16/sql-alterindex.html "ALTER INDEX") | [Up](https://www.postgresql.org/docs/16/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/16/index.html "PostgreSQL 16.11 Documentation") | [Next](https://www.postgresql.org/docs/16/sql-alterlargeobject.html "ALTER LARGE OBJECT") | * * * ALTER LANGUAGE -------------- ALTER LANGUAGE — change the definition of a procedural language Synopsis -------- ALTER \[ PROCEDURAL \] LANGUAGE _`name`_ RENAME TO _`new_name`_ ALTER \[ PROCEDURAL \] LANGUAGE _`name`_ OWNER TO { _`new_owner`_ | CURRENT\_ROLE | CURRENT\_USER | SESSION\_USER } Description ----------- `ALTER LANGUAGE` changes the definition of a procedural language. The only functionality is to rename the language or assign a new owner. You must be superuser or owner of the language to use `ALTER LANGUAGE`. Parameters ---------- _`name`_ Name of a language _`new_name`_ The new name of the language _`new_owner`_ The new owner of the language Compatibility ------------- There is no `ALTER LANGUAGE` statement in the SQL standard. See Also -------- [CREATE LANGUAGE](https://www.postgresql.org/docs/16/sql-createlanguage.html "CREATE LANGUAGE") , [DROP LANGUAGE](https://www.postgresql.org/docs/16/sql-droplanguage.html "DROP LANGUAGE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/16/sql-alterindex.html "ALTER INDEX") | [Up](https://www.postgresql.org/docs/16/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/16/sql-alterlargeobject.html "ALTER LARGE OBJECT") | | ALTER INDEX | [Home](https://www.postgresql.org/docs/16/index.html "PostgreSQL 16.11 Documentation") | ALTER LARGE OBJECT | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/16/sql-alterlanguage.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 16: Chapter 22. Database Roles November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 16](https://www.postgresql.org/docs/16/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/user-manag.html "PostgreSQL 18 - Chapter 22. Database Roles") ([18](https://www.postgresql.org/docs/18/user-manag.html "PostgreSQL 18 - Chapter 22. Database Roles") ) / [17](https://www.postgresql.org/docs/17/user-manag.html "PostgreSQL 17 - Chapter 22. Database Roles") / [16](https://www.postgresql.org/docs/16/user-manag.html "PostgreSQL 16 - Chapter 22. Database Roles") / [15](https://www.postgresql.org/docs/15/user-manag.html "PostgreSQL 15 - Chapter 22. Database Roles") / [14](https://www.postgresql.org/docs/14/user-manag.html "PostgreSQL 14 - Chapter 22. Database Roles") Development Versions: [devel](https://www.postgresql.org/docs/devel/user-manag.html "PostgreSQL devel - Chapter 22. Database Roles") Unsupported versions: [13](https://www.postgresql.org/docs/13/user-manag.html "PostgreSQL 13 - Chapter 22. Database Roles") / [12](https://www.postgresql.org/docs/12/user-manag.html "PostgreSQL 12 - Chapter 22. Database Roles") / [11](https://www.postgresql.org/docs/11/user-manag.html "PostgreSQL 11 - Chapter 22. Database Roles") / [10](https://www.postgresql.org/docs/10/user-manag.html "PostgreSQL 10 - Chapter 22. Database Roles") / [9.6](https://www.postgresql.org/docs/9.6/user-manag.html "PostgreSQL 9.6 - Chapter 22. Database Roles") / [9.5](https://www.postgresql.org/docs/9.5/user-manag.html "PostgreSQL 9.5 - Chapter 22. Database Roles") / [9.4](https://www.postgresql.org/docs/9.4/user-manag.html "PostgreSQL 9.4 - Chapter 22. Database Roles") / [9.3](https://www.postgresql.org/docs/9.3/user-manag.html "PostgreSQL 9.3 - Chapter 22. Database Roles") / [9.2](https://www.postgresql.org/docs/9.2/user-manag.html "PostgreSQL 9.2 - Chapter 22. Database Roles") / [9.1](https://www.postgresql.org/docs/9.1/user-manag.html "PostgreSQL 9.1 - Chapter 22. Database Roles") / [9.0](https://www.postgresql.org/docs/9.0/user-manag.html "PostgreSQL 9.0 - Chapter 22. Database Roles") / [8.4](https://www.postgresql.org/docs/8.4/user-manag.html "PostgreSQL 8.4 - Chapter 22. Database Roles") / [8.3](https://www.postgresql.org/docs/8.3/user-manag.html "PostgreSQL 8.3 - Chapter 22. Database Roles") / [8.2](https://www.postgresql.org/docs/8.2/user-manag.html "PostgreSQL 8.2 - Chapter 22. Database Roles") / [8.1](https://www.postgresql.org/docs/8.1/user-manag.html "PostgreSQL 8.1 - Chapter 22. Database Roles") / [8.0](https://www.postgresql.org/docs/8.0/user-manag.html "PostgreSQL 8.0 - Chapter 22. Database Roles") / [7.4](https://www.postgresql.org/docs/7.4/user-manag.html "PostgreSQL 7.4 - Chapter 22. Database Roles") / [7.3](https://www.postgresql.org/docs/7.3/user-manag.html "PostgreSQL 7.3 - Chapter 22. Database Roles") / [7.2](https://www.postgresql.org/docs/7.2/user-manag.html "PostgreSQL 7.2 - Chapter 22. Database Roles") / [7.1](https://www.postgresql.org/docs/7.1/user-manag.html "PostgreSQL 7.1 - Chapter 22. Database Roles") | Chapter 22. Database Roles | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/16/client-authentication-problems.html "21.15. Authentication Problems") | [Up](https://www.postgresql.org/docs/16/admin.html "Part III. Server Administration") | Part III. Server Administration | [Home](https://www.postgresql.org/docs/16/index.html "PostgreSQL 16.11 Documentation") | [Next](https://www.postgresql.org/docs/16/database-roles.html "22.1. Database Roles") | * * * Chapter 22. Database Roles -------------------------- **Table of Contents** [22.1. Database Roles](https://www.postgresql.org/docs/16/database-roles.html) [22.2. Role Attributes](https://www.postgresql.org/docs/16/role-attributes.html) [22.3. Role Membership](https://www.postgresql.org/docs/16/role-membership.html) [22.4. Dropping Roles](https://www.postgresql.org/docs/16/role-removal.html) [22.5. Predefined Roles](https://www.postgresql.org/docs/16/predefined-roles.html) [22.6. Function Security](https://www.postgresql.org/docs/16/perm-functions.html) PostgreSQL manages database access permissions using the concept of _roles_. A role can be thought of as either a database user, or a group of database users, depending on how the role is set up. Roles can own database objects (for example, tables and functions) and can assign privileges on those objects to other roles to control who has access to which objects. Furthermore, it is possible to grant _membership_ in a role to another role, thus allowing the member role to use privileges assigned to another role. The concept of roles subsumes the concepts of “users” and “groups”. In PostgreSQL versions before 8.1, users and groups were distinct kinds of entities, but now there are only roles. Any role can act as a user, a group, or both. This chapter describes how to create and manage roles. More information about the effects of role privileges on various database objects can be found in [Section 5.7](https://www.postgresql.org/docs/16/ddl-priv.html "5.7. Privileges") . * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/16/client-authentication-problems.html "21.15. Authentication Problems") | [Up](https://www.postgresql.org/docs/16/admin.html "Part III. Server Administration") | [Next](https://www.postgresql.org/docs/16/database-roles.html "22.1. Database Roles") | | 21.15. Authentication Problems | [Home](https://www.postgresql.org/docs/16/index.html "PostgreSQL 16.11 Documentation") | 22.1. Database Roles | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/16/user-manag.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 16: ALTER TABLE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 16](https://www.postgresql.org/docs/16/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-altertable.html "PostgreSQL 18 - ALTER TABLE") ([18](https://www.postgresql.org/docs/18/sql-altertable.html "PostgreSQL 18 - ALTER TABLE") ) / [17](https://www.postgresql.org/docs/17/sql-altertable.html "PostgreSQL 17 - ALTER TABLE") / [16](https://www.postgresql.org/docs/16/sql-altertable.html "PostgreSQL 16 - ALTER TABLE") / [15](https://www.postgresql.org/docs/15/sql-altertable.html "PostgreSQL 15 - ALTER TABLE") / [14](https://www.postgresql.org/docs/14/sql-altertable.html "PostgreSQL 14 - ALTER TABLE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-altertable.html "PostgreSQL devel - ALTER TABLE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-altertable.html "PostgreSQL 13 - ALTER TABLE") / [12](https://www.postgresql.org/docs/12/sql-altertable.html "PostgreSQL 12 - ALTER TABLE") / [11](https://www.postgresql.org/docs/11/sql-altertable.html "PostgreSQL 11 - ALTER TABLE") / [10](https://www.postgresql.org/docs/10/sql-altertable.html "PostgreSQL 10 - ALTER TABLE") / [9.6](https://www.postgresql.org/docs/9.6/sql-altertable.html "PostgreSQL 9.6 - ALTER TABLE") / [9.5](https://www.postgresql.org/docs/9.5/sql-altertable.html "PostgreSQL 9.5 - ALTER TABLE") / [9.4](https://www.postgresql.org/docs/9.4/sql-altertable.html "PostgreSQL 9.4 - ALTER TABLE") / [9.3](https://www.postgresql.org/docs/9.3/sql-altertable.html "PostgreSQL 9.3 - ALTER TABLE") / [9.2](https://www.postgresql.org/docs/9.2/sql-altertable.html "PostgreSQL 9.2 - ALTER TABLE") / [9.1](https://www.postgresql.org/docs/9.1/sql-altertable.html "PostgreSQL 9.1 - ALTER TABLE") / [9.0](https://www.postgresql.org/docs/9.0/sql-altertable.html "PostgreSQL 9.0 - ALTER TABLE") / [8.4](https://www.postgresql.org/docs/8.4/sql-altertable.html "PostgreSQL 8.4 - ALTER TABLE") / [8.3](https://www.postgresql.org/docs/8.3/sql-altertable.html "PostgreSQL 8.3 - ALTER TABLE") / [8.2](https://www.postgresql.org/docs/8.2/sql-altertable.html "PostgreSQL 8.2 - ALTER TABLE") / [8.1](https://www.postgresql.org/docs/8.1/sql-altertable.html "PostgreSQL 8.1 - ALTER TABLE") / [8.0](https://www.postgresql.org/docs/8.0/sql-altertable.html "PostgreSQL 8.0 - ALTER TABLE") / [7.4](https://www.postgresql.org/docs/7.4/sql-altertable.html "PostgreSQL 7.4 - ALTER TABLE") / [7.3](https://www.postgresql.org/docs/7.3/sql-altertable.html "PostgreSQL 7.3 - ALTER TABLE") / [7.2](https://www.postgresql.org/docs/7.2/sql-altertable.html "PostgreSQL 7.2 - ALTER TABLE") / [7.1](https://www.postgresql.org/docs/7.1/sql-altertable.html "PostgreSQL 7.1 - ALTER TABLE") | ALTER TABLE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/16/sql-altersystem.html "ALTER SYSTEM") | [Up](https://www.postgresql.org/docs/16/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/16/index.html "PostgreSQL 16.11 Documentation") | [Next](https://www.postgresql.org/docs/16/sql-altertablespace.html "ALTER TABLESPACE") | * * * ALTER TABLE ----------- ALTER TABLE — change the definition of a table Synopsis -------- ALTER TABLE \[ IF EXISTS \] \[ ONLY \] _`name`_ \[ \* \] _`action`_ \[, ... \] ALTER TABLE \[ IF EXISTS \] \[ ONLY \] _`name`_ \[ \* \] RENAME \[ COLUMN \] _`column_name`_ TO _`new_column_name`_ ALTER TABLE \[ IF EXISTS \] \[ ONLY \] _`name`_ \[ \* \] RENAME CONSTRAINT _`constraint_name`_ TO _`new_constraint_name`_ ALTER TABLE \[ IF EXISTS \] _`name`_ RENAME TO _`new_name`_ ALTER TABLE \[ IF EXISTS \] _`name`_ SET SCHEMA _`new_schema`_ ALTER TABLE ALL IN TABLESPACE _`name`_ \[ OWNED BY _`role_name`_ \[, ... \] \] SET TABLESPACE _`new_tablespace`_ \[ NOWAIT \] ALTER TABLE \[ IF EXISTS \] _`name`_ ATTACH PARTITION _`partition_name`_ { FOR VALUES _`partition_bound_spec`_ | DEFAULT } ALTER TABLE \[ IF EXISTS \] _`name`_ DETACH PARTITION _`partition_name`_ \[ CONCURRENTLY | FINALIZE \] where _`action`_ is one of: ADD \[ COLUMN \] \[ IF NOT EXISTS \] _`column_name`_ _`data_type`_ \[ COLLATE _`collation`_ \] \[ _`column_constraint`_ \[ ... \] \] DROP \[ COLUMN \] \[ IF EXISTS \] _`column_name`_ \[ RESTRICT | CASCADE \] ALTER \[ COLUMN \] _`column_name`_ \[ SET DATA \] TYPE _`data_type`_ \[ COLLATE _`collation`_ \] \[ USING _`expression`_ \] ALTER \[ COLUMN \] _`column_name`_ SET DEFAULT _`expression`_ ALTER \[ COLUMN \] _`column_name`_ DROP DEFAULT ALTER \[ COLUMN \] _`column_name`_ { SET | DROP } NOT NULL ALTER \[ COLUMN \] _`column_name`_ DROP EXPRESSION \[ IF EXISTS \] ALTER \[ COLUMN \] _`column_name`_ ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY \[ ( _`sequence_options`_ ) \] ALTER \[ COLUMN \] _`column_name`_ { SET GENERATED { ALWAYS | BY DEFAULT } | SET _`sequence_option`_ | RESTART \[ \[ WITH \] _`restart`_ \] } \[...\] ALTER \[ COLUMN \] _`column_name`_ DROP IDENTITY \[ IF EXISTS \] ALTER \[ COLUMN \] _`column_name`_ SET STATISTICS _`integer`_ ALTER \[ COLUMN \] _`column_name`_ SET ( _`attribute_option`_ = _`value`_ \[, ... \] ) ALTER \[ COLUMN \] _`column_name`_ RESET ( _`attribute_option`_ \[, ... \] ) ALTER \[ COLUMN \] _`column_name`_ SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } ALTER \[ COLUMN \] _`column_name`_ SET COMPRESSION _`compression_method`_ ADD _`table_constraint`_ \[ NOT VALID \] ADD _`table_constraint_using_index`_ ALTER CONSTRAINT _`constraint_name`_ \[ DEFERRABLE | NOT DEFERRABLE \] \[ INITIALLY DEFERRED | INITIALLY IMMEDIATE \] VALIDATE CONSTRAINT _`constraint_name`_ DROP CONSTRAINT \[ IF EXISTS \] _`constraint_name`_ \[ RESTRICT | CASCADE \] DISABLE TRIGGER \[ _`trigger_name`_ | ALL | USER \] ENABLE TRIGGER \[ _`trigger_name`_ | ALL | USER \] ENABLE REPLICA TRIGGER _`trigger_name`_ ENABLE ALWAYS TRIGGER _`trigger_name`_ DISABLE RULE _`rewrite_rule_name`_ ENABLE RULE _`rewrite_rule_name`_ ENABLE REPLICA RULE _`rewrite_rule_name`_ ENABLE ALWAYS RULE _`rewrite_rule_name`_ DISABLE ROW LEVEL SECURITY ENABLE ROW LEVEL SECURITY FORCE ROW LEVEL SECURITY NO FORCE ROW LEVEL SECURITY CLUSTER ON _`index_name`_ SET WITHOUT CLUSTER SET WITHOUT OIDS SET ACCESS METHOD _`new_access_method`_ SET TABLESPACE _`new_tablespace`_ SET { LOGGED | UNLOGGED } SET ( _`storage_parameter`_ \[= _`value`_\] \[, ... \] ) RESET ( _`storage_parameter`_ \[, ... \] ) INHERIT _`parent_table`_ NO INHERIT _`parent_table`_ OF _`type_name`_ NOT OF OWNER TO { _`new_owner`_ | CURRENT\_ROLE | CURRENT\_USER | SESSION\_USER } REPLICA IDENTITY { DEFAULT | USING INDEX _`index_name`_ | FULL | NOTHING } and _`partition_bound_spec`_ is: IN ( _`partition_bound_expr`_ \[, ...\] ) | FROM ( { _`partition_bound_expr`_ | MINVALUE | MAXVALUE } \[, ...\] ) TO ( { _`partition_bound_expr`_ | MINVALUE | MAXVALUE } \[, ...\] ) | WITH ( MODULUS _`numeric_literal`_, REMAINDER _`numeric_literal`_ ) and _`column_constraint`_ is: \[ CONSTRAINT _`constraint_name`_ \] { NOT NULL | NULL | CHECK ( _`expression`_ ) \[ NO INHERIT \] | DEFAULT _`default_expr`_ | GENERATED ALWAYS AS ( _`generation_expr`_ ) STORED | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY \[ ( _`sequence_options`_ ) \] | UNIQUE \[ NULLS \[ NOT \] DISTINCT \] _`index_parameters`_ | PRIMARY KEY _`index_parameters`_ | REFERENCES _`reftable`_ \[ ( _`refcolumn`_ ) \] \[ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE \] \[ ON DELETE _`referential_action`_ \] \[ ON UPDATE _`referential_action`_ \] } \[ DEFERRABLE | NOT DEFERRABLE \] \[ INITIALLY DEFERRED | INITIALLY IMMEDIATE \] and _`table_constraint`_ is: \[ CONSTRAINT _`constraint_name`_ \] { CHECK ( _`expression`_ ) \[ NO INHERIT \] | UNIQUE \[ NULLS \[ NOT \] DISTINCT \] ( _`column_name`_ \[, ... \] ) _`index_parameters`_ | PRIMARY KEY ( _`column_name`_ \[, ... \] ) _`index_parameters`_ | EXCLUDE \[ USING _`index_method`_ \] ( _`exclude_element`_ WITH _`operator`_ \[, ... \] ) _`index_parameters`_ \[ WHERE ( _`predicate`_ ) \] | FOREIGN KEY ( _`column_name`_ \[, ... \] ) REFERENCES _`reftable`_ \[ ( _`refcolumn`_ \[, ... \] ) \] \[ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE \] \[ ON DELETE _`referential_action`_ \] \[ ON UPDATE _`referential_action`_ \] } \[ DEFERRABLE | NOT DEFERRABLE \] \[ INITIALLY DEFERRED | INITIALLY IMMEDIATE \] and _`table_constraint_using_index`_ is: \[ CONSTRAINT _`constraint_name`_ \] { UNIQUE | PRIMARY KEY } USING INDEX _`index_name`_ \[ DEFERRABLE | NOT DEFERRABLE \] \[ INITIALLY DEFERRED | INITIALLY IMMEDIATE \] _`index_parameters`_ in `UNIQUE`, `PRIMARY KEY`, and `EXCLUDE` constraints are: \[ INCLUDE ( _`column_name`_ \[, ... \] ) \] \[ WITH ( _`storage_parameter`_ \[= _`value`_\] \[, ... \] ) \] \[ USING INDEX TABLESPACE _`tablespace_name`_ \] _`exclude_element`_ in an `EXCLUDE` constraint is: { _`column_name`_ | ( _`expression`_ ) } \[ COLLATE _`collation`_ \] \[ _`opclass`_ \[ ( _`opclass_parameter`_ = _`value`_ \[, ... \] ) \] \] \[ ASC | DESC \] \[ NULLS { FIRST | LAST } \] _`referential_action`_ in a `FOREIGN KEY`/`REFERENCES` constraint is: { NO ACTION | RESTRICT | CASCADE | SET NULL \[ ( _`column_name`_ \[, ... \] ) \] | SET DEFAULT \[ ( _`column_name`_ \[, ... \] ) \] } Description ----------- `ALTER TABLE` changes the definition of an existing table. There are several subforms described below. Note that the lock level required may differ for each subform. An `ACCESS EXCLUSIVE` lock is acquired unless explicitly noted. When multiple subcommands are given, the lock acquired will be the strictest one required by any subcommand. `ADD COLUMN [ IF NOT EXISTS ]` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-ADD-COLUMN) This form adds a new column to the table, using the same syntax as [`CREATE TABLE`](https://www.postgresql.org/docs/16/sql-createtable.html "CREATE TABLE") . If `IF NOT EXISTS` is specified and a column already exists with this name, no error is thrown. `DROP COLUMN [ IF EXISTS ]` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-DROP-COLUMN) This form drops a column from a table. Indexes and table constraints involving the column will be automatically dropped as well. Multivariate statistics referencing the dropped column will also be removed if the removal of the column would cause the statistics to contain data for only a single column. You will need to say `CASCADE` if anything outside the table depends on the column, for example, foreign key references or views. If `IF EXISTS` is specified and the column does not exist, no error is thrown. In this case a notice is issued instead. `SET DATA TYPE` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-DATA-TYPE) This form changes the type of a column of a table. Indexes and simple table constraints involving the column will be automatically converted to use the new column type by reparsing the originally supplied expression. The optional `COLLATE` clause specifies a collation for the new column; if omitted, the collation is the default for the new column type. The optional `USING` clause specifies how to compute the new column value from the old; if omitted, the default conversion is the same as an assignment cast from old data type to new. A `USING` clause must be provided if there is no implicit or assignment cast from old to new type. When this form is used, the column's statistics are removed, so running [`ANALYZE`](https://www.postgresql.org/docs/16/sql-analyze.html "ANALYZE") on the table afterwards is recommended. `SET`/`DROP DEFAULT` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-DROP-DEFAULT) These forms set or remove the default value for a column (where removal is equivalent to setting the default value to NULL). The new default value will only apply in subsequent `INSERT` or `UPDATE` commands; it does not cause rows already in the table to change. `SET`/`DROP NOT NULL` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-DROP-NOT-NULL) These forms change whether a column is marked to allow null values or to reject null values. `SET NOT NULL` may only be applied to a column provided none of the records in the table contain a `NULL` value for the column. Ordinarily this is checked during the `ALTER TABLE` by scanning the entire table; however, if a valid `CHECK` constraint exists (and is not dropped in the same command) which proves no `NULL` can exist, then the table scan is skipped. If this table is a partition, one cannot perform `DROP NOT NULL` on a column if it is marked `NOT NULL` in the parent table. To drop the `NOT NULL` constraint from all the partitions, perform `DROP NOT NULL` on the parent table. Even if there is no `NOT NULL` constraint on the parent, such a constraint can still be added to individual partitions, if desired; that is, the children can disallow nulls even if the parent allows them, but not the other way around. `DROP EXPRESSION [ IF EXISTS ]` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-DROP-EXPRESSION) This form turns a stored generated column into a normal base column. Existing data in the columns is retained, but future changes will no longer apply the generation expression. If `DROP EXPRESSION IF EXISTS` is specified and the column is not a stored generated column, no error is thrown. In this case a notice is issued instead. `ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY` `SET GENERATED { ALWAYS | BY DEFAULT }` `DROP IDENTITY [ IF EXISTS ]` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-GENERATED-IDENTITY) These forms change whether a column is an identity column or change the generation attribute of an existing identity column. See [`CREATE TABLE`](https://www.postgresql.org/docs/16/sql-createtable.html "CREATE TABLE") for details. Like `SET DEFAULT`, these forms only affect the behavior of subsequent `INSERT` and `UPDATE` commands; they do not cause rows already in the table to change. If `DROP IDENTITY IF EXISTS` is specified and the column is not an identity column, no error is thrown. In this case a notice is issued instead. ``SET _`sequence_option`_`` `RESTART` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-SEQUENCE-OPTION) These forms alter the sequence that underlies an existing identity column. _`sequence_option`_ is an option supported by [`ALTER SEQUENCE`](https://www.postgresql.org/docs/16/sql-altersequence.html "ALTER SEQUENCE") such as `INCREMENT BY`. `SET STATISTICS` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-STATISTICS) This form sets the per-column statistics-gathering target for subsequent [`ANALYZE`](https://www.postgresql.org/docs/16/sql-analyze.html "ANALYZE") operations. The target can be set in the range 0 to 10000; alternatively, set it to -1 to revert to using the system default statistics target ([default\_statistics\_target](https://www.postgresql.org/docs/16/runtime-config-query.html#GUC-DEFAULT-STATISTICS-TARGET) ). For more information on the use of statistics by the PostgreSQL query planner, refer to [Section 14.2](https://www.postgresql.org/docs/16/planner-stats.html "14.2. Statistics Used by the Planner") . `SET STATISTICS` acquires a `SHARE UPDATE EXCLUSIVE` lock. ``SET ( _`attribute_option`_ = _`value`_ [, ... ] )`` ``RESET ( _`attribute_option`_ [, ... ] )`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-ATTRIBUTE-OPTION) This form sets or resets per-attribute options. Currently, the only defined per-attribute options are `n_distinct` and `n_distinct_inherited`, which override the number-of-distinct-values estimates made by subsequent [`ANALYZE`](https://www.postgresql.org/docs/16/sql-analyze.html "ANALYZE") operations. `n_distinct` affects the statistics for the table itself, while `n_distinct_inherited` affects the statistics gathered for the table plus its inheritance children, and for the statistics gathered for partitioned tables. When the value specified is a positive value, the query planner will assume that the column contains exactly the specified number of distinct nonnull values. Fractional values may also be specified by using values below 0 and above or equal to -1. This instructs the query planner to estimate the number of distinct values by multiplying the absolute value of the specified number by the estimated number of rows in the table. For example, a value of -1 implies that all values in the column are distinct, while a value of -0.5 implies that each value appears twice on average. This can be useful when the size of the table changes over time. For more information on the use of statistics by the PostgreSQL query planner, refer to [Section 14.2](https://www.postgresql.org/docs/16/planner-stats.html "14.2. Statistics Used by the Planner") . Changing per-attribute options acquires a `SHARE UPDATE EXCLUSIVE` lock. `SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT }` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-STORAGE) This form sets the storage mode for a column. This controls whether this column is held inline or in a secondary TOAST table, and whether the data should be compressed or not. `PLAIN` must be used for fixed-length values such as `integer` and is inline, uncompressed. `MAIN` is for inline, compressible data. `EXTERNAL` is for external, uncompressed data, and `EXTENDED` is for external, compressed data. Writing `DEFAULT` sets the storage mode to the default mode for the column's data type. `EXTENDED` is the default for most data types that support non-`PLAIN` storage. Use of `EXTERNAL` will make substring operations on very large `text` and `bytea` values run faster, at the penalty of increased storage space. Note that `ALTER TABLE ... SET STORAGE` doesn't itself change anything in the table; it just sets the strategy to be pursued during future table updates. See [Section 73.2](https://www.postgresql.org/docs/16/storage-toast.html "73.2. TOAST") for more information. ``SET COMPRESSION _`compression_method`_`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-COMPRESSION) This form sets the compression method for a column, determining how values inserted in future will be compressed (if the storage mode permits compression at all). This does not cause the table to be rewritten, so existing data may still be compressed with other compression methods. If the table is restored with pg\_restore, then all values are rewritten with the configured compression method. However, when data is inserted from another relation (for example, by `INSERT ... SELECT`), values from the source table are not necessarily detoasted, so any previously compressed data may retain its existing compression method, rather than being recompressed with the compression method of the target column. The supported compression methods are `pglz` and `lz4`. (`lz4` is available only if `--with-lz4` was used when building PostgreSQL.) In addition, _`compression_method`_ can be `default`, which selects the default behavior of consulting the [default\_toast\_compression](https://www.postgresql.org/docs/16/runtime-config-client.html#GUC-DEFAULT-TOAST-COMPRESSION) setting at the time of data insertion to determine the method to use. ``ADD _`table_constraint`_ [ NOT VALID ]`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-ADD-TABLE-CONSTRAINT) This form adds a new constraint to a table using the same constraint syntax as [`CREATE TABLE`](https://www.postgresql.org/docs/16/sql-createtable.html "CREATE TABLE") , plus the option `NOT VALID`, which is currently only allowed for foreign key and CHECK constraints. Normally, this form will cause a scan of the table to verify that all existing rows in the table satisfy the new constraint. But if the `NOT VALID` option is used, this potentially-lengthy scan is skipped. The constraint will still be enforced against subsequent inserts or updates (that is, they'll fail unless there is a matching row in the referenced table, in the case of foreign keys, or they'll fail unless the new row matches the specified check condition). But the database will not assume that the constraint holds for all rows in the table, until it is validated by using the `VALIDATE CONSTRAINT` option. See [Notes](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-NOTES "Notes") below for more information about using the `NOT VALID` option. Although most forms of ``ADD _`table_constraint`_`` require an `ACCESS EXCLUSIVE` lock, `ADD FOREIGN KEY` requires only a `SHARE ROW EXCLUSIVE` lock. Note that `ADD FOREIGN KEY` also acquires a `SHARE ROW EXCLUSIVE` lock on the referenced table, in addition to the lock on the table on which the constraint is declared. Additional restrictions apply when unique or primary key constraints are added to partitioned tables; see [`CREATE TABLE`](https://www.postgresql.org/docs/16/sql-createtable.html "CREATE TABLE") . Also, foreign key constraints on partitioned tables may not be declared `NOT VALID` at present. ``ADD _`table_constraint_using_index`_`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-ADD-TABLE-CONSTRAINT-USING-INDEX) This form adds a new `PRIMARY KEY` or `UNIQUE` constraint to a table based on an existing unique index. All the columns of the index will be included in the constraint. The index cannot have expression columns nor be a partial index. Also, it must be a b-tree index with default sort ordering. These restrictions ensure that the index is equivalent to one that would be built by a regular `ADD PRIMARY KEY` or `ADD UNIQUE` command. If `PRIMARY KEY` is specified, and the index's columns are not already marked `NOT NULL`, then this command will attempt to do `ALTER COLUMN SET NOT NULL` against each such column. That requires a full table scan to verify the column(s) contain no nulls. In all other cases, this is a fast operation. If a constraint name is provided then the index will be renamed to match the constraint name. Otherwise the constraint will be named the same as the index. After this command is executed, the index is “owned” by the constraint, in the same way as if the index had been built by a regular `ADD PRIMARY KEY` or `ADD UNIQUE` command. In particular, dropping the constraint will make the index disappear too. This form is not currently supported on partitioned tables. ### Note Adding a constraint using an existing index can be helpful in situations where a new constraint needs to be added without blocking table updates for a long time. To do that, create the index using `CREATE INDEX CONCURRENTLY`, and then install it as an official constraint using this syntax. See the example below. `ALTER CONSTRAINT` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-ALTER-CONSTRAINT) This form alters the attributes of a constraint that was previously created. Currently only foreign key constraints may be altered. `VALIDATE CONSTRAINT` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-VALIDATE-CONSTRAINT) This form validates a foreign key or check constraint that was previously created as `NOT VALID`, by scanning the table to ensure there are no rows for which the constraint is not satisfied. Nothing happens if the constraint is already marked valid. (See [Notes](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-NOTES "Notes") below for an explanation of the usefulness of this command.) This command acquires a `SHARE UPDATE EXCLUSIVE` lock. `DROP CONSTRAINT [ IF EXISTS ]` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-DROP-CONSTRAINT) This form drops the specified constraint on a table, along with any index underlying the constraint. If `IF EXISTS` is specified and the constraint does not exist, no error is thrown. In this case a notice is issued instead. `DISABLE`/`ENABLE [ REPLICA | ALWAYS ] TRIGGER` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-DISABLE-ENABLE-TRIGGER) These forms configure the firing of trigger(s) belonging to the table. A disabled trigger is still known to the system, but is not executed when its triggering event occurs. (For a deferred trigger, the enable status is checked when the event occurs, not when the trigger function is actually executed.) One can disable or enable a single trigger specified by name, or all triggers on the table, or only user triggers (this option excludes internally generated constraint triggers, such as those that are used to implement foreign key constraints or deferrable uniqueness and exclusion constraints). Disabling or enabling internally generated constraint triggers requires superuser privileges; it should be done with caution since of course the integrity of the constraint cannot be guaranteed if the triggers are not executed. The trigger firing mechanism is also affected by the configuration variable [session\_replication\_role](https://www.postgresql.org/docs/16/runtime-config-client.html#GUC-SESSION-REPLICATION-ROLE) . Simply enabled triggers (the default) will fire when the replication role is “origin” (the default) or “local”. Triggers configured as `ENABLE REPLICA` will only fire if the session is in “replica” mode, and triggers configured as `ENABLE ALWAYS` will fire regardless of the current replication role. The effect of this mechanism is that in the default configuration, triggers do not fire on replicas. This is useful because if a trigger is used on the origin to propagate data between tables, then the replication system will also replicate the propagated data; so the trigger should not fire a second time on the replica, because that would lead to duplication. However, if a trigger is used for another purpose such as creating external alerts, then it might be appropriate to set it to `ENABLE ALWAYS` so that it is also fired on replicas. When this command is applied to a partitioned table, the states of corresponding clone triggers in the partitions are updated too, unless `ONLY` is specified. This command acquires a `SHARE ROW EXCLUSIVE` lock. `DISABLE`/`ENABLE [ REPLICA | ALWAYS ] RULE` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-DISABLE-ENABLE-RULE) These forms configure the firing of rewrite rules belonging to the table. A disabled rule is still known to the system, but is not applied during query rewriting. The semantics are as for disabled/enabled triggers. This configuration is ignored for `ON SELECT` rules, which are always applied in order to keep views working even if the current session is in a non-default replication role. The rule firing mechanism is also affected by the configuration variable [session\_replication\_role](https://www.postgresql.org/docs/16/runtime-config-client.html#GUC-SESSION-REPLICATION-ROLE) , analogous to triggers as described above. `DISABLE`/`ENABLE ROW LEVEL SECURITY` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-DISABLE-ENABLE-ROW-LEVEL-SECURITY) These forms control the application of row security policies belonging to the table. If enabled and no policies exist for the table, then a default-deny policy is applied. Note that policies can exist for a table even if row-level security is disabled. In this case, the policies will _not_ be applied and the policies will be ignored. See also [`CREATE POLICY`](https://www.postgresql.org/docs/16/sql-createpolicy.html "CREATE POLICY") . `NO FORCE`/`FORCE ROW LEVEL SECURITY` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-FORCE-ROW-LEVEL-SECURITY) These forms control the application of row security policies belonging to the table when the user is the table owner. If enabled, row-level security policies will be applied when the user is the table owner. If disabled (the default) then row-level security will not be applied when the user is the table owner. See also [`CREATE POLICY`](https://www.postgresql.org/docs/16/sql-createpolicy.html "CREATE POLICY") . `CLUSTER ON` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-CLUSTER-ON) This form selects the default index for future [`CLUSTER`](https://www.postgresql.org/docs/16/sql-cluster.html "CLUSTER") operations. It does not actually re-cluster the table. Changing cluster options acquires a `SHARE UPDATE EXCLUSIVE` lock. `SET WITHOUT CLUSTER` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-WITHOUT-CLUSTER) This form removes the most recently used [`CLUSTER`](https://www.postgresql.org/docs/16/sql-cluster.html "CLUSTER") index specification from the table. This affects future cluster operations that don't specify an index. Changing cluster options acquires a `SHARE UPDATE EXCLUSIVE` lock. `SET WITHOUT OIDS` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-WITHOUT-OIDS) Backward-compatible syntax for removing the `oid` system column. As `oid` system columns cannot be added anymore, this never has an effect. `SET ACCESS METHOD` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-ACCESS-METHOD) This form changes the access method of the table by rewriting it. See [Chapter 63](https://www.postgresql.org/docs/16/tableam.html "Chapter 63. Table Access Method Interface Definition") for more information. `SET TABLESPACE` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-TABLESPACE) This form changes the table's tablespace to the specified tablespace and moves the data file(s) associated with the table to the new tablespace. Indexes on the table, if any, are not moved; but they can be moved separately with additional `SET TABLESPACE` commands. When applied to a partitioned table, nothing is moved, but any partitions created afterwards with `CREATE TABLE PARTITION OF` will use that tablespace, unless overridden by a `TABLESPACE` clause. All tables in the current database in a tablespace can be moved by using the `ALL IN TABLESPACE` form, which will lock all tables to be moved first and then move each one. This form also supports `OWNED BY`, which will only move tables owned by the roles specified. If the `NOWAIT` option is specified then the command will fail if it is unable to acquire all of the locks required immediately. Note that system catalogs are not moved by this command; use `ALTER DATABASE` or explicit `ALTER TABLE` invocations instead if desired. The `information_schema` relations are not considered part of the system catalogs and will be moved. See also [`CREATE TABLESPACE`](https://www.postgresql.org/docs/16/sql-createtablespace.html "CREATE TABLESPACE") . `SET { LOGGED | UNLOGGED }` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-LOGGED-UNLOGGED) This form changes the table from unlogged to logged or vice-versa (see [`UNLOGGED`](https://www.postgresql.org/docs/16/sql-createtable.html#SQL-CREATETABLE-UNLOGGED) ). It cannot be applied to a temporary table. This also changes the persistence of any sequences linked to the table (for identity or serial columns). However, it is also possible to change the persistence of such sequences separately. ``SET ( _`storage_parameter`_ [= _`value`_] [, ... ] )`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-STORAGE-PARAMETER) This form changes one or more storage parameters for the table. See [Storage Parameters](https://www.postgresql.org/docs/16/sql-createtable.html#SQL-CREATETABLE-STORAGE-PARAMETERS "Storage Parameters") in the [`CREATE TABLE`](https://www.postgresql.org/docs/16/sql-createtable.html "CREATE TABLE") documentation for details on the available parameters. Note that the table contents will not be modified immediately by this command; depending on the parameter you might need to rewrite the table to get the desired effects. That can be done with [`VACUUM FULL`](https://www.postgresql.org/docs/16/sql-vacuum.html "VACUUM") , [`CLUSTER`](https://www.postgresql.org/docs/16/sql-cluster.html "CLUSTER") or one of the forms of `ALTER TABLE` that forces a table rewrite. For planner related parameters, changes will take effect from the next time the table is locked so currently executing queries will not be affected. `SHARE UPDATE EXCLUSIVE` lock will be taken for fillfactor, toast and autovacuum storage parameters, as well as the planner parameter `parallel_workers`. ``RESET ( _`storage_parameter`_ [, ... ] )`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-RESET-STORAGE-PARAMETER) This form resets one or more storage parameters to their defaults. As with `SET`, a table rewrite might be needed to update the table entirely. ``INHERIT _`parent_table`_`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-INHERIT) This form adds the target table as a new child of the specified parent table. Subsequently, queries against the parent will include records of the target table. To be added as a child, the target table must already contain all the same columns as the parent (it could have additional columns, too). The columns must have matching data types, and if they have `NOT NULL` constraints in the parent then they must also have `NOT NULL` constraints in the child. There must also be matching child-table constraints for all `CHECK` constraints of the parent, except those marked non-inheritable (that is, created with `ALTER TABLE ... ADD CONSTRAINT ... NO INHERIT`) in the parent, which are ignored; all child-table constraints matched must not be marked non-inheritable. Currently `UNIQUE`, `PRIMARY KEY`, and `FOREIGN KEY` constraints are not considered, but this might change in the future. ``NO INHERIT _`parent_table`_`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-NO-INHERIT) This form removes the target table from the list of children of the specified parent table. Queries against the parent table will no longer include records drawn from the target table. ``OF _`type_name`_`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-OF) This form links the table to a composite type as though `CREATE TABLE OF` had formed it. The table's list of column names and types must precisely match that of the composite type. The table must not inherit from any other table. These restrictions ensure that `CREATE TABLE OF` would permit an equivalent table definition. `NOT OF` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-NOT-OF) This form dissociates a typed table from its type. `OWNER TO` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-OWNER-TO) This form changes the owner of the table, sequence, view, materialized view, or foreign table to the specified user. `REPLICA IDENTITY` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-REPLICA-IDENTITY) This form changes the information which is written to the write-ahead log to identify rows which are updated or deleted. In most cases, the old value of each column is only logged if it differs from the new value; however, if the old value is stored externally, it is always logged regardless of whether it changed. This option has no effect except when logical replication is in use. `DEFAULT` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-REPLICA-IDENTITY-DEFAULT) Records the old values of the columns of the primary key, if any. This is the default for non-system tables. ``USING INDEX _`index_name`_`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-REPLICA-IDENTITY-USING-INDEX) Records the old values of the columns covered by the named index, that must be unique, not partial, not deferrable, and include only columns marked `NOT NULL`. If this index is dropped, the behavior is the same as `NOTHING`. `FULL` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-REPLICA-IDENTITY-FULL) Records the old values of all columns in the row. `NOTHING` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-REPLICA-IDENTITY-NOTHING) Records no information about the old row. This is the default for system tables. `RENAME` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-RENAME) The `RENAME` forms change the name of a table (or an index, sequence, view, materialized view, or foreign table), the name of an individual column in a table, or the name of a constraint of the table. When renaming a constraint that has an underlying index, the index is renamed as well. There is no effect on the stored data. `SET SCHEMA` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DESC-SET-SCHEMA) This form moves the table into another schema. Associated indexes, constraints, and sequences owned by table columns are moved as well. ``ATTACH PARTITION _`partition_name`_ { FOR VALUES _`partition_bound_spec`_ | DEFAULT }`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-ATTACH-PARTITION) This form attaches an existing table (which might itself be partitioned) as a partition of the target table. The table can be attached as a partition for specific values using `FOR VALUES` or as a default partition by using `DEFAULT`. For each index in the target table, a corresponding one will be created in the attached table; or, if an equivalent index already exists, it will be attached to the target table's index, as if `ALTER INDEX ATTACH PARTITION` had been executed. Note that if the existing table is a foreign table, it is currently not allowed to attach the table as a partition of the target table if there are `UNIQUE` indexes on the target table. (See also [CREATE FOREIGN TABLE](https://www.postgresql.org/docs/16/sql-createforeigntable.html "CREATE FOREIGN TABLE") .) For each user-defined row-level trigger that exists in the target table, a corresponding one is created in the attached table. A partition using `FOR VALUES` uses same syntax for _`partition_bound_spec`_ as [`CREATE TABLE`](https://www.postgresql.org/docs/16/sql-createtable.html "CREATE TABLE") . The partition bound specification must correspond to the partitioning strategy and partition key of the target table. The table to be attached must have all the same columns as the target table and no more; moreover, the column types must also match. Also, it must have all the `NOT NULL` and `CHECK` constraints of the target table, not marked `NO INHERIT`. Currently `FOREIGN KEY` constraints are not considered. `UNIQUE` and `PRIMARY KEY` constraints from the parent table will be created in the partition, if they don't already exist. If the new partition is a regular table, a full table scan is performed to check that existing rows in the table do not violate the partition constraint. It is possible to avoid this scan by adding a valid `CHECK` constraint to the table that allows only rows satisfying the desired partition constraint before running this command. The `CHECK` constraint will be used to determine that the table need not be scanned to validate the partition constraint. This does not work, however, if any of the partition keys is an expression and the partition does not accept `NULL` values. If attaching a list partition that will not accept `NULL` values, also add a `NOT NULL` constraint to the partition key column, unless it's an expression. If the new partition is a foreign table, nothing is done to verify that all the rows in the foreign table obey the partition constraint. (See the discussion in [CREATE FOREIGN TABLE](https://www.postgresql.org/docs/16/sql-createforeigntable.html "CREATE FOREIGN TABLE") about constraints on the foreign table.) When a table has a default partition, defining a new partition changes the partition constraint for the default partition. The default partition can't contain any rows that would need to be moved to the new partition, and will be scanned to verify that none are present. This scan, like the scan of the new partition, can be avoided if an appropriate `CHECK` constraint is present. Also like the scan of the new partition, it is always skipped when the default partition is a foreign table. Attaching a partition acquires a `SHARE UPDATE EXCLUSIVE` lock on the parent table, in addition to the `ACCESS EXCLUSIVE` locks on the table being attached and on the default partition (if any). Further locks must also be held on all sub-partitions if the table being attached is itself a partitioned table. Likewise if the default partition is itself a partitioned table. The locking of the sub-partitions can be avoided by adding a `CHECK` constraint as described in [Section 5.11.2.2](https://www.postgresql.org/docs/16/ddl-partitioning.html#DDL-PARTITIONING-DECLARATIVE-MAINTENANCE "5.11.2.2. Partition Maintenance") . ``DETACH PARTITION _`partition_name`_ [ CONCURRENTLY | FINALIZE ]`` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-DETACH-PARTITION) This form detaches the specified partition of the target table. The detached partition continues to exist as a standalone table, but no longer has any ties to the table from which it was detached. Any indexes that were attached to the target table's indexes are detached. Any triggers that were created as clones of those in the target table are removed. `SHARE` lock is obtained on any tables that reference this partitioned table in foreign key constraints. If `CONCURRENTLY` is specified, it runs using a reduced lock level to avoid blocking other sessions that might be accessing the partitioned table. In this mode, two transactions are used internally. During the first transaction, a `SHARE UPDATE EXCLUSIVE` lock is taken on both parent table and partition, and the partition is marked as undergoing detach; at that point, the transaction is committed and all other transactions using the partitioned table are waited for. Once all those transactions have completed, the second transaction acquires `SHARE UPDATE EXCLUSIVE` on the partitioned table and `ACCESS EXCLUSIVE` on the partition, and the detach process completes. A `CHECK` constraint that duplicates the partition constraint is added to the partition. `CONCURRENTLY` cannot be run in a transaction block and is not allowed if the partitioned table contains a default partition. If `FINALIZE` is specified, a previous `DETACH CONCURRENTLY` invocation that was canceled or interrupted is completed. At most one partition in a partitioned table can be pending detach at a time. All the forms of ALTER TABLE that act on a single table, except `RENAME`, `SET SCHEMA`, `ATTACH PARTITION`, and `DETACH PARTITION` can be combined into a list of multiple alterations to be applied together. For example, it is possible to add several columns and/or alter the type of several columns in a single command. This is particularly useful with large tables, since only one pass over the table need be made. You must own the table to use `ALTER TABLE`. To change the schema or tablespace of a table, you must also have `CREATE` privilege on the new schema or tablespace. To add the table as a new child of a parent table, you must own the parent table as well. Also, to attach a table as a new partition of the table, you must own the table being attached. To alter the owner, you must be able to `SET ROLE` to the new owning role, and that role must have `CREATE` privilege on the table's schema. (These restrictions enforce that altering the owner doesn't do anything you couldn't do by dropping and recreating the table. However, a superuser can alter ownership of any table anyway.) To add a column or alter a column type or use the `OF` clause, you must also have `USAGE` privilege on the data type. Parameters ---------- `IF EXISTS` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-IF-EXISTS) Do not throw an error if the table does not exist. A notice is issued in this case. _`name`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-NAME) The name (optionally schema-qualified) of an existing table to alter. If `ONLY` is specified before the table name, only that table is altered. If `ONLY` is not specified, the table and all its descendant tables (if any) are altered. Optionally, `*` can be specified after the table name to explicitly indicate that descendant tables are included. _`column_name`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-COLUMN-NAME) Name of a new or existing column. _`new_column_name`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-NEW-COLUMN-NAME) New name for an existing column. _`new_name`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-NEW-NAME) New name for the table. _`data_type`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-DATA-TYPE) Data type of the new column, or new data type for an existing column. _`table_constraint`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-TABLE-CONSTRAINT) New table constraint for the table. _`constraint_name`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-CONSTRAINT-NAME) Name of a new or existing constraint. `CASCADE` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-CASCADE) Automatically drop objects that depend on the dropped column or constraint (for example, views referencing the column), and in turn all objects that depend on those objects (see [Section 5.14](https://www.postgresql.org/docs/16/ddl-depend.html "5.14. Dependency Tracking") ). `RESTRICT` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-RESTRICT) Refuse to drop the column or constraint if there are any dependent objects. This is the default behavior. _`trigger_name`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-TRIGGER-NAME) Name of a single trigger to disable or enable. `ALL` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-ALL) Disable or enable all triggers belonging to the table. (This requires superuser privilege if any of the triggers are internally generated constraint triggers, such as those that are used to implement foreign key constraints or deferrable uniqueness and exclusion constraints.) `USER` [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-USER) Disable or enable all triggers belonging to the table except for internally generated constraint triggers, such as those that are used to implement foreign key constraints or deferrable uniqueness and exclusion constraints. _`index_name`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-INDEX-NAME) The name of an existing index. _`storage_parameter`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-STORAGE-PARAMETER) The name of a table storage parameter. _`value`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-VALUE) The new value for a table storage parameter. This might be a number or a word depending on the parameter. _`parent_table`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-PARENT-TABLE) A parent table to associate or de-associate with this table. _`new_owner`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-NEW-OWNER) The user name of the new owner of the table. _`new_access_method`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-NEW-ACCESS-METHOD) The name of the access method to which the table will be converted. _`new_tablespace`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-NEW-TABLESPACE) The name of the tablespace to which the table will be moved. _`new_schema`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-NEW-SCHEMA) The name of the schema to which the table will be moved. _`partition_name`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-PARTITION-NAME) The name of the table to attach as a new partition or to detach from this table. _`partition_bound_spec`_ [#](https://www.postgresql.org/docs/16/sql-altertable.html#SQL-ALTERTABLE-PARMS-PARTITION-BOUND-SPEC) The partition bound specification for a new partition. Refer to [CREATE TABLE](https://www.postgresql.org/docs/16/sql-createtable.html "CREATE TABLE") for more details on the syntax of the same. Notes ----- The key word `COLUMN` is noise and can be omitted. When a column is added with `ADD COLUMN` and a non-volatile `DEFAULT` is specified, the default is evaluated at the time of the statement and the result stored in the table's metadata. That value will be used for the column for all existing rows. If no `DEFAULT` is specified, NULL is used. In neither case is a rewrite of the table required. Adding a column with a volatile `DEFAULT` or changing the type of an existing column will require the entire table and its indexes to be rewritten. As an exception, when changing the type of an existing column, if the `USING` clause does not change the column contents and the old type is either binary coercible to the new type or an unconstrained domain over the new type, a table rewrite is not needed. However, indexes must always be rebuilt unless the system can verify that the new index would be logically equivalent to the existing one. For example, if the collation for a column has been changed, an index rebuild is always required because the new sort order might be different. However, in the absence of a collation change, a column can be changed from `text` to `varchar` (or vice versa) without rebuilding the indexes because these data types sort identically. Table and/or index rebuilds may take a significant amount of time for a large table; and will temporarily require as much as double the disk space. Adding a `CHECK` or `NOT NULL` constraint requires scanning the table to verify that existing rows meet the constraint, but does not require a table rewrite. Similarly, when attaching a new partition it may be scanned to verify that existing rows meet the partition constraint. The main reason for providing the option to specify multiple changes in a single `ALTER TABLE` is that multiple table scans or rewrites can thereby be combined into a single pass over the table. Scanning a large table to verify a new foreign key or check constraint can take a long time, and other updates to the table are locked out until the `ALTER TABLE ADD CONSTRAINT` command is committed. The main purpose of the `NOT VALID` constraint option is to reduce the impact of adding a constraint on concurrent updates. With `NOT VALID`, the `ADD CONSTRAINT` command does not scan the table and can be committed immediately. After that, a `VALIDATE CONSTRAINT` command can be issued to verify that existing rows satisfy the constraint. The validation step does not need to lock out concurrent updates, since it knows that other transactions will be enforcing the constraint for rows that they insert or update; only pre-existing rows need to be checked. Hence, validation acquires only a `SHARE UPDATE EXCLUSIVE` lock on the table being altered. (If the constraint is a foreign key then a `ROW SHARE` lock is also required on the table referenced by the constraint.) In addition to improving concurrency, it can be useful to use `NOT VALID` and `VALIDATE CONSTRAINT` in cases where the table is known to contain pre-existing violations. Once the constraint is in place, no new violations can be inserted, and the existing problems can be corrected at leisure until `VALIDATE CONSTRAINT` finally succeeds. The `DROP COLUMN` form does not physically remove the column, but simply makes it invisible to SQL operations. Subsequent insert and update operations in the table will store a null value for the column. Thus, dropping a column is quick but it will not immediately reduce the on-disk size of your table, as the space occupied by the dropped column is not reclaimed. The space will be reclaimed over time as existing rows are updated. To force immediate reclamation of space occupied by a dropped column, you can execute one of the forms of `ALTER TABLE` that performs a rewrite of the whole table. This results in reconstructing each row with the dropped column replaced by a null value. The rewriting forms of `ALTER TABLE` are not MVCC-safe. After a table rewrite, the table will appear empty to concurrent transactions, if they are using a snapshot taken before the rewrite occurred. See [Section 13.6](https://www.postgresql.org/docs/16/mvcc-caveats.html "13.6. Caveats") for more details. The `USING` option of `SET DATA TYPE` can actually specify any expression involving the old values of the row; that is, it can refer to other columns as well as the one being converted. This allows very general conversions to be done with the `SET DATA TYPE` syntax. Because of this flexibility, the `USING` expression is not applied to the column's default value (if any); the result might not be a constant expression as required for a default. This means that when there is no implicit or assignment cast from old to new type, `SET DATA TYPE` might fail to convert the default even though a `USING` clause is supplied. In such cases, drop the default with `DROP DEFAULT`, perform the `ALTER TYPE`, and then use `SET DEFAULT` to add a suitable new default. Similar considerations apply to indexes and constraints involving the column. If a table has any descendant tables, it is not permitted to add, rename, or change the type of a column in the parent table without doing the same to the descendants. This ensures that the descendants always have columns matching the parent. Similarly, a `CHECK` constraint cannot be renamed in the parent without also renaming it in all descendants, so that `CHECK` constraints also match between the parent and its descendants. (That restriction does not apply to index-based constraints, however.) Also, because selecting from the parent also selects from its descendants, a constraint on the parent cannot be marked valid unless it is also marked valid for those descendants. In all of these cases, `ALTER TABLE ONLY` will be rejected. A recursive `DROP COLUMN` operation will remove a descendant table's column only if the descendant does not inherit that column from any other parents and never had an independent definition of the column. A nonrecursive `DROP COLUMN` (i.e., `ALTER TABLE ONLY ... DROP COLUMN`) never removes any descendant columns, but instead marks them as independently defined rather than inherited. A nonrecursive `DROP COLUMN` command will fail for a partitioned table, because all partitions of a table must have the same columns as the partitioning root. The actions for identity columns (`ADD GENERATED`, `SET` etc., `DROP IDENTITY`), as well as the actions `CLUSTER`, `OWNER`, and `TABLESPACE` never recurse to descendant tables; that is, they always act as though `ONLY` were specified. Actions affecting trigger states recurse to partitions of partitioned tables (unless `ONLY` is specified), but never to traditional-inheritance descendants. Adding a constraint recurses only for `CHECK` constraints that are not marked `NO INHERIT`. Changing any part of a system catalog table is not permitted. Refer to [CREATE TABLE](https://www.postgresql.org/docs/16/sql-createtable.html "CREATE TABLE") for a further description of valid parameters. [Chapter 5](https://www.postgresql.org/docs/16/ddl.html "Chapter 5. Data Definition") has further information on inheritance. Examples -------- To add a column of type `varchar` to a table: ALTER TABLE distributors ADD COLUMN address varchar(30); That will cause all existing rows in the table to be filled with null values for the new column. To add a column with a non-null default: ALTER TABLE measurements ADD COLUMN mtime timestamp with time zone DEFAULT now(); Existing rows will be filled with the current time as the value of the new column, and then new rows will receive the time of their insertion. To add a column and fill it with a value different from the default to be used later: ALTER TABLE transactions ADD COLUMN status varchar(30) DEFAULT 'old', ALTER COLUMN status SET default 'current'; Existing rows will be filled with `old`, but then the default for subsequent commands will be `current`. The effects are the same as if the two sub-commands had been issued in separate `ALTER TABLE` commands. To drop a column from a table: ALTER TABLE distributors DROP COLUMN address RESTRICT; To change the types of two existing columns in one operation: ALTER TABLE distributors ALTER COLUMN address TYPE varchar(80), ALTER COLUMN name TYPE varchar(100); To change an integer column containing Unix timestamps to `timestamp with time zone` via a `USING` clause: ALTER TABLE foo ALTER COLUMN foo\_timestamp SET DATA TYPE timestamp with time zone USING timestamp with time zone 'epoch' + foo\_timestamp \* interval '1 second'; The same, when the column has a default expression that won't automatically cast to the new data type: ALTER TABLE foo ALTER COLUMN foo\_timestamp DROP DEFAULT, ALTER COLUMN foo\_timestamp TYPE timestamp with time zone USING timestamp with time zone 'epoch' + foo\_timestamp \* interval '1 second', ALTER COLUMN foo\_timestamp SET DEFAULT now(); To rename an existing column: ALTER TABLE distributors RENAME COLUMN address TO city; To rename an existing table: ALTER TABLE distributors RENAME TO suppliers; To rename an existing constraint: ALTER TABLE distributors RENAME CONSTRAINT zipchk TO zip\_check; To add a not-null constraint to a column: ALTER TABLE distributors ALTER COLUMN street SET NOT NULL; To remove a not-null constraint from a column: ALTER TABLE distributors ALTER COLUMN street DROP NOT NULL; To add a check constraint to a table and all its children: ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char\_length(zipcode) = 5); To add a check constraint only to a table and not to its children: ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char\_length(zipcode) = 5) NO INHERIT; (The check constraint will not be inherited by future children, either.) To remove a check constraint from a table and all its children: ALTER TABLE distributors DROP CONSTRAINT zipchk; To remove a check constraint from one table only: ALTER TABLE ONLY distributors DROP CONSTRAINT zipchk; (The check constraint remains in place for any child tables.) To add a foreign key constraint to a table: ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address); To add a foreign key constraint to a table with the least impact on other work: ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address) NOT VALID; ALTER TABLE distributors VALIDATE CONSTRAINT distfk; To add a (multicolumn) unique constraint to a table: ALTER TABLE distributors ADD CONSTRAINT dist\_id\_zipcode\_key UNIQUE (dist\_id, zipcode); To add an automatically named primary key constraint to a table, noting that a table can only ever have one primary key: ALTER TABLE distributors ADD PRIMARY KEY (dist\_id); To move a table to a different tablespace: ALTER TABLE distributors SET TABLESPACE fasttablespace; To move a table to a different schema: ALTER TABLE myschema.distributors SET SCHEMA yourschema; To recreate a primary key constraint, without blocking updates while the index is rebuilt: CREATE UNIQUE INDEX CONCURRENTLY dist\_id\_temp\_idx ON distributors (dist\_id); ALTER TABLE distributors DROP CONSTRAINT distributors\_pkey, ADD CONSTRAINT distributors\_pkey PRIMARY KEY USING INDEX dist\_id\_temp\_idx; To attach a partition to a range-partitioned table: ALTER TABLE measurement ATTACH PARTITION measurement\_y2016m07 FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); To attach a partition to a list-partitioned table: ALTER TABLE cities ATTACH PARTITION cities\_ab FOR VALUES IN ('a', 'b'); To attach a partition to a hash-partitioned table: ALTER TABLE orders ATTACH PARTITION orders\_p4 FOR VALUES WITH (MODULUS 4, REMAINDER 3); To attach a default partition to a partitioned table: ALTER TABLE cities ATTACH PARTITION cities\_partdef DEFAULT; To detach a partition from a partitioned table: ALTER TABLE measurement DETACH PARTITION measurement\_y2015m12; Compatibility ------------- The forms `ADD` (without `USING INDEX`), `DROP [COLUMN]`, `DROP IDENTITY`, `RESTART`, `SET DEFAULT`, `SET DATA TYPE` (without `USING`), `SET GENERATED`, and ``SET _`sequence_option`_`` conform with the SQL standard. The other forms are PostgreSQL extensions of the SQL standard. Also, the ability to specify more than one manipulation in a single `ALTER TABLE` command is an extension. `ALTER TABLE DROP COLUMN` can be used to drop the only column of a table, leaving a zero-column table. This is an extension of SQL, which disallows zero-column tables. See Also -------- [CREATE TABLE](https://www.postgresql.org/docs/16/sql-createtable.html "CREATE TABLE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/16/sql-altersystem.html "ALTER SYSTEM") | [Up](https://www.postgresql.org/docs/16/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/16/sql-altertablespace.html "ALTER TABLESPACE") | | ALTER SYSTEM | [Home](https://www.postgresql.org/docs/16/index.html "PostgreSQL 16.11 Documentation") | ALTER TABLESPACE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/16/sql-altertable.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 16: 17.2. Getting the Source November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 16](https://www.postgresql.org/docs/16/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/install-getsource.html "PostgreSQL 18 - 17.2. Getting the Source") ([18](https://www.postgresql.org/docs/18/install-getsource.html "PostgreSQL 18 - 17.2. Getting the Source") ) / [17](https://www.postgresql.org/docs/17/install-getsource.html "PostgreSQL 17 - 17.2. Getting the Source") / [16](https://www.postgresql.org/docs/16/install-getsource.html "PostgreSQL 16 - 17.2. Getting the Source") / [15](https://www.postgresql.org/docs/15/install-getsource.html "PostgreSQL 15 - 17.2. Getting the Source") / [14](https://www.postgresql.org/docs/14/install-getsource.html "PostgreSQL 14 - 17.2. Getting the Source") Development Versions: [devel](https://www.postgresql.org/docs/devel/install-getsource.html "PostgreSQL devel - 17.2. Getting the Source") Unsupported versions: [13](https://www.postgresql.org/docs/13/install-getsource.html "PostgreSQL 13 - 17.2. Getting the Source") / [12](https://www.postgresql.org/docs/12/install-getsource.html "PostgreSQL 12 - 17.2. Getting the Source") / [11](https://www.postgresql.org/docs/11/install-getsource.html "PostgreSQL 11 - 17.2. Getting the Source") / [10](https://www.postgresql.org/docs/10/install-getsource.html "PostgreSQL 10 - 17.2. Getting the Source") / [9.6](https://www.postgresql.org/docs/9.6/install-getsource.html "PostgreSQL 9.6 - 17.2. Getting the Source") / [9.5](https://www.postgresql.org/docs/9.5/install-getsource.html "PostgreSQL 9.5 - 17.2. Getting the Source") / [9.4](https://www.postgresql.org/docs/9.4/install-getsource.html "PostgreSQL 9.4 - 17.2. Getting the Source") / [9.3](https://www.postgresql.org/docs/9.3/install-getsource.html "PostgreSQL 9.3 - 17.2. Getting the Source") / [9.2](https://www.postgresql.org/docs/9.2/install-getsource.html "PostgreSQL 9.2 - 17.2. Getting the Source") / [9.1](https://www.postgresql.org/docs/9.1/install-getsource.html "PostgreSQL 9.1 - 17.2. Getting the Source") / [9.0](https://www.postgresql.org/docs/9.0/install-getsource.html "PostgreSQL 9.0 - 17.2. Getting the Source") / [8.4](https://www.postgresql.org/docs/8.4/install-getsource.html "PostgreSQL 8.4 - 17.2. Getting the Source") / [8.3](https://www.postgresql.org/docs/8.3/install-getsource.html "PostgreSQL 8.3 - 17.2. Getting the Source") / [8.2](https://www.postgresql.org/docs/8.2/install-getsource.html "PostgreSQL 8.2 - 17.2. Getting the Source") / [8.1](https://www.postgresql.org/docs/8.1/install-getsource.html "PostgreSQL 8.1 - 17.2. Getting the Source") / [8.0](https://www.postgresql.org/docs/8.0/install-getsource.html "PostgreSQL 8.0 - 17.2. Getting the Source") / [7.4](https://www.postgresql.org/docs/7.4/install-getsource.html "PostgreSQL 7.4 - 17.2. Getting the Source") / [7.3](https://www.postgresql.org/docs/7.3/install-getsource.html "PostgreSQL 7.3 - 17.2. Getting the Source") / [7.2](https://www.postgresql.org/docs/7.2/install-getsource.html "PostgreSQL 7.2 - 17.2. Getting the Source") / [7.1](https://www.postgresql.org/docs/7.1/install-getsource.html "PostgreSQL 7.1 - 17.2. Getting the Source") | 17.2. Getting the Source | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/16/install-requirements.html "17.1. Requirements") | [Up](https://www.postgresql.org/docs/16/installation.html "Chapter 17. Installation from Source Code") | Chapter 17. Installation from Source Code | [Home](https://www.postgresql.org/docs/16/index.html "PostgreSQL 16.11 Documentation") | [Next](https://www.postgresql.org/docs/16/install-make.html "17.3. Building and Installation with Autoconf and Make") | * * * 17.2. Getting the Source [#](https://www.postgresql.org/docs/16/install-getsource.html#INSTALL-GETSOURCE) ---------------------------------------------------------------------------------------------------------- The PostgreSQL source code for released versions can be obtained from the download section of our website: [https://www.postgresql.org/ftp/source/](https://www.postgresql.org/ftp/source/) . Download the ``postgresql-_`version`_.tar.gz`` or ``postgresql-_`version`_.tar.bz2`` file you're interested in, then unpack it: **``tar xf postgresql-_`version`_.tar.bz2``** This will create a directory ``postgresql-_`version`_`` under the current directory with the PostgreSQL sources. Change into that directory for the rest of the installation procedure. Alternatively, you can use the Git version control system; see [Section I.1](https://www.postgresql.org/docs/16/git.html "I.1. Getting the Source via Git") for more information. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/16/install-requirements.html "17.1. Requirements") | [Up](https://www.postgresql.org/docs/16/installation.html "Chapter 17. Installation from Source Code") | [Next](https://www.postgresql.org/docs/16/install-make.html "17.3. Building and Installation with Autoconf and Make") | | 17.1. Requirements | [Home](https://www.postgresql.org/docs/16/index.html "PostgreSQL 16.11 Documentation") | 17.3. Building and Installation with Autoconf and Make | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/16/install-getsource.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 14: 10.3. Functions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 14](https://www.postgresql.org/docs/14/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/typeconv-func.html "PostgreSQL 18 - 10.3. Functions") ([18](https://www.postgresql.org/docs/18/typeconv-func.html "PostgreSQL 18 - 10.3. Functions") ) / [17](https://www.postgresql.org/docs/17/typeconv-func.html "PostgreSQL 17 - 10.3. Functions") / [16](https://www.postgresql.org/docs/16/typeconv-func.html "PostgreSQL 16 - 10.3. Functions") / [15](https://www.postgresql.org/docs/15/typeconv-func.html "PostgreSQL 15 - 10.3. Functions") / [14](https://www.postgresql.org/docs/14/typeconv-func.html "PostgreSQL 14 - 10.3. Functions") Development Versions: [devel](https://www.postgresql.org/docs/devel/typeconv-func.html "PostgreSQL devel - 10.3. Functions") Unsupported versions: [13](https://www.postgresql.org/docs/13/typeconv-func.html "PostgreSQL 13 - 10.3. Functions") / [12](https://www.postgresql.org/docs/12/typeconv-func.html "PostgreSQL 12 - 10.3. Functions") / [11](https://www.postgresql.org/docs/11/typeconv-func.html "PostgreSQL 11 - 10.3. Functions") / [10](https://www.postgresql.org/docs/10/typeconv-func.html "PostgreSQL 10 - 10.3. Functions") / [9.6](https://www.postgresql.org/docs/9.6/typeconv-func.html "PostgreSQL 9.6 - 10.3. Functions") / [9.5](https://www.postgresql.org/docs/9.5/typeconv-func.html "PostgreSQL 9.5 - 10.3. Functions") / [9.4](https://www.postgresql.org/docs/9.4/typeconv-func.html "PostgreSQL 9.4 - 10.3. Functions") / [9.3](https://www.postgresql.org/docs/9.3/typeconv-func.html "PostgreSQL 9.3 - 10.3. Functions") / [9.2](https://www.postgresql.org/docs/9.2/typeconv-func.html "PostgreSQL 9.2 - 10.3. Functions") / [9.1](https://www.postgresql.org/docs/9.1/typeconv-func.html "PostgreSQL 9.1 - 10.3. Functions") / [9.0](https://www.postgresql.org/docs/9.0/typeconv-func.html "PostgreSQL 9.0 - 10.3. Functions") / [8.4](https://www.postgresql.org/docs/8.4/typeconv-func.html "PostgreSQL 8.4 - 10.3. Functions") / [8.3](https://www.postgresql.org/docs/8.3/typeconv-func.html "PostgreSQL 8.3 - 10.3. Functions") / [8.2](https://www.postgresql.org/docs/8.2/typeconv-func.html "PostgreSQL 8.2 - 10.3. Functions") / [8.1](https://www.postgresql.org/docs/8.1/typeconv-func.html "PostgreSQL 8.1 - 10.3. Functions") / [8.0](https://www.postgresql.org/docs/8.0/typeconv-func.html "PostgreSQL 8.0 - 10.3. Functions") / [7.4](https://www.postgresql.org/docs/7.4/typeconv-func.html "PostgreSQL 7.4 - 10.3. Functions") / [7.3](https://www.postgresql.org/docs/7.3/typeconv-func.html "PostgreSQL 7.3 - 10.3. Functions") / [7.2](https://www.postgresql.org/docs/7.2/typeconv-func.html "PostgreSQL 7.2 - 10.3. Functions") / [7.1](https://www.postgresql.org/docs/7.1/typeconv-func.html "PostgreSQL 7.1 - 10.3. Functions") | 10.3. Functions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/typeconv-oper.html "10.2. Operators") | [Up](https://www.postgresql.org/docs/14/typeconv.html "Chapter 10. Type Conversion") | Chapter 10. Type Conversion | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | [Next](https://www.postgresql.org/docs/14/typeconv-query.html "10.4. Value Storage") | * * * 10.3. Functions --------------- The specific function that is referenced by a function call is determined using the following procedure. **Function Type Resolution** 1. Select the functions to be considered from the `pg_proc` system catalog. If a non-schema-qualified function name was used, the functions considered are those with the matching name and argument count that are visible in the current search path (see [Section 5.9.3](https://www.postgresql.org/docs/14/ddl-schemas.html#DDL-SCHEMAS-PATH "5.9.3. The Schema Search Path") ). If a qualified function name was given, only functions in the specified schema are considered. 1. If the search path finds multiple functions of identical argument types, only the one appearing earliest in the path is considered. Functions of different argument types are considered on an equal footing regardless of search path position. 2. If a function is declared with a `VARIADIC` array parameter, and the call does not use the `VARIADIC` keyword, then the function is treated as if the array parameter were replaced by one or more occurrences of its element type, as needed to match the call. After such expansion the function might have effective argument types identical to some non-variadic function. In that case the function appearing earlier in the search path is used, or if the two functions are in the same schema, the non-variadic one is preferred. This creates a security hazard when calling, via qualified name [\[10\]](https://www.postgresql.org/docs/14/typeconv-func.html#ftn.FUNC-QUALIFIED-SECURITY) , a variadic function found in a schema that permits untrusted users to create objects. A malicious user can take control and execute arbitrary SQL functions as though you executed them. Substitute a call bearing the `VARIADIC` keyword, which bypasses this hazard. Calls populating `VARIADIC "any"` parameters often have no equivalent formulation containing the `VARIADIC` keyword. To issue those calls safely, the function's schema must permit only trusted users to create objects. 3. Functions that have default values for parameters are considered to match any call that omits zero or more of the defaultable parameter positions. If more than one such function matches a call, the one appearing earliest in the search path is used. If there are two or more such functions in the same schema with identical parameter types in the non-defaulted positions (which is possible if they have different sets of defaultable parameters), the system will not be able to determine which to prefer, and so an “ambiguous function call” error will result if no better match to the call can be found. This creates an availability hazard when calling, via qualified name[\[10\]](https://www.postgresql.org/docs/14/typeconv-func.html#ftn.FUNC-QUALIFIED-SECURITY) , any function found in a schema that permits untrusted users to create objects. A malicious user can create a function with the name of an existing function, replicating that function's parameters and appending novel parameters having default values. This precludes new calls to the original function. To forestall this hazard, place functions in schemas that permit only trusted users to create objects. 2. Check for a function accepting exactly the input argument types. If one exists (there can be only one exact match in the set of functions considered), use it. Lack of an exact match creates a security hazard when calling, via qualified name[\[10\]](https://www.postgresql.org/docs/14/typeconv-func.html#ftn.FUNC-QUALIFIED-SECURITY) , a function found in a schema that permits untrusted users to create objects. In such situations, cast arguments to force an exact match. (Cases involving `unknown` will never find a match at this step.) 3. If no exact match is found, see if the function call appears to be a special type conversion request. This happens if the function call has just one argument and the function name is the same as the (internal) name of some data type. Furthermore, the function argument must be either an unknown-type literal, or a type that is binary-coercible to the named data type, or a type that could be converted to the named data type by applying that type's I/O functions (that is, the conversion is either to or from one of the standard string types). When these conditions are met, the function call is treated as a form of `CAST` specification. [\[11\]](https://www.postgresql.org/docs/14/typeconv-func.html#ftn.id-1.5.9.8.4.4.1.2) 4. Look for the best match. 1. Discard candidate functions for which the input types do not match and cannot be converted (using an implicit conversion) to match. `unknown` literals are assumed to be convertible to anything for this purpose. If only one candidate remains, use it; else continue to the next step. 2. If any input argument is of a domain type, treat it as being of the domain's base type for all subsequent steps. This ensures that domains act like their base types for purposes of ambiguous-function resolution. 3. Run through all candidates and keep those with the most exact matches on input types. Keep all candidates if none have exact matches. If only one candidate remains, use it; else continue to the next step. 4. Run through all candidates and keep those that accept preferred types (of the input data type's type category) at the most positions where type conversion will be required. Keep all candidates if none accept preferred types. If only one candidate remains, use it; else continue to the next step. 5. If any input arguments are `unknown`, check the type categories accepted at those argument positions by the remaining candidates. At each position, select the `string` category if any candidate accepts that category. (This bias towards string is appropriate since an unknown-type literal looks like a string.) Otherwise, if all the remaining candidates accept the same type category, select that category; otherwise fail because the correct choice cannot be deduced without more clues. Now discard candidates that do not accept the selected type category. Furthermore, if any candidate accepts a preferred type in that category, discard candidates that accept non-preferred types for that argument. Keep all candidates if none survive these tests. If only one candidate remains, use it; else continue to the next step. 6. If there are both `unknown` and known-type arguments, and all the known-type arguments have the same type, assume that the `unknown` arguments are also of that type, and check which candidates can accept that type at the `unknown`\-argument positions. If exactly one candidate passes this test, use it. Otherwise, fail. Note that the “best match” rules are identical for operator and function type resolution. Some examples follow. **Example 10.6. Rounding Function Argument Type Resolution** There is only one `round` function that takes two arguments; it takes a first argument of type `numeric` and a second argument of type `integer`. So the following query automatically converts the first argument of type `integer` to `numeric`: SELECT round(4, 4); round -------- 4.0000 (1 row) That query is actually transformed by the parser to: SELECT round(CAST (4 AS numeric), 4); Since numeric constants with decimal points are initially assigned the type `numeric`, the following query will require no type conversion and therefore might be slightly more efficient: SELECT round(4.0, 4); **Example 10.7. Variadic Function Resolution** CREATE FUNCTION public.variadic\_example(VARIADIC numeric\[\]) RETURNS int LANGUAGE sql AS 'SELECT 1'; CREATE FUNCTION This function accepts, but does not require, the VARIADIC keyword. It tolerates both integer and numeric arguments: SELECT public.variadic\_example(0), public.variadic\_example(0.0), public.variadic\_example(VARIADIC array\[0.0\]); variadic\_example | variadic\_example | variadic\_example ------------------+------------------+------------------ 1 | 1 | 1 (1 row) However, the first and second calls will prefer more-specific functions, if available: CREATE FUNCTION public.variadic\_example(numeric) RETURNS int LANGUAGE sql AS 'SELECT 2'; CREATE FUNCTION CREATE FUNCTION public.variadic\_example(int) RETURNS int LANGUAGE sql AS 'SELECT 3'; CREATE FUNCTION SELECT public.variadic\_example(0), public.variadic\_example(0.0), public.variadic\_example(VARIADIC array\[0.0\]); variadic\_example | variadic\_example | variadic\_example ------------------+------------------+------------------ 3 | 2 | 1 (1 row) Given the default configuration and only the first function existing, the first and second calls are insecure. Any user could intercept them by creating the second or third function. By matching the argument type exactly and using the `VARIADIC` keyword, the third call is secure. **Example 10.8. Substring Function Type Resolution** There are several `substr` functions, one of which takes types `text` and `integer`. If called with a string constant of unspecified type, the system chooses the candidate function that accepts an argument of the preferred category `string` (namely of type `text`). SELECT substr('1234', 3); substr -------- 34 (1 row) If the string is declared to be of type `varchar`, as might be the case if it comes from a table, then the parser will try to convert it to become `text`: SELECT substr(varchar '1234', 3); substr -------- 34 (1 row) This is transformed by the parser to effectively become: SELECT substr(CAST (varchar '1234' AS text), 3); ### Note The parser learns from the `pg_cast` catalog that `text` and `varchar` are binary-compatible, meaning that one can be passed to a function that accepts the other without doing any physical conversion. Therefore, no type conversion call is really inserted in this case. And, if the function is called with an argument of type `integer`, the parser will try to convert that to `text`: SELECT substr(1234, 3); ERROR: function substr(integer, integer) does not exist HINT: No function matches the given name and argument types. You might need to add explicit type casts. This does not work because `integer` does not have an implicit cast to `text`. An explicit cast will work, however: SELECT substr(CAST (1234 AS text), 3); substr -------- 34 (1 row) * * * [\[10\]](https://www.postgresql.org/docs/14/typeconv-func.html#FUNC-QUALIFIED-SECURITY) The hazard does not arise with a non-schema-qualified name, because a search path containing schemas that permit untrusted users to create objects is not a [secure schema usage pattern](https://www.postgresql.org/docs/14/ddl-schemas.html#DDL-SCHEMAS-PATTERNS "5.9.6. Usage Patterns") . [\[11\]](https://www.postgresql.org/docs/14/typeconv-func.html#id-1.5.9.8.4.4.1.2) The reason for this step is to support function-style cast specifications in cases where there is not an actual cast function. If there is a cast function, it is conventionally named after its output type, and so there is no need to have a special case. See [CREATE CAST](https://www.postgresql.org/docs/14/sql-createcast.html "CREATE CAST") for additional commentary. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/typeconv-oper.html "10.2. Operators") | [Up](https://www.postgresql.org/docs/14/typeconv.html "Chapter 10. Type Conversion") | [Next](https://www.postgresql.org/docs/14/typeconv-query.html "10.4. Value Storage") | | 10.2. Operators | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | 10.4. Value Storage | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/14/typeconv-func.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 14: 53.8. Error and Notice Message Fields November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 14](https://www.postgresql.org/docs/14/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/protocol-error-fields.html "PostgreSQL 18 - 53.8. Error and Notice Message Fields") ([18](https://www.postgresql.org/docs/18/protocol-error-fields.html "PostgreSQL 18 - 53.8. Error and Notice Message Fields") ) / [17](https://www.postgresql.org/docs/17/protocol-error-fields.html "PostgreSQL 17 - 53.8. Error and Notice Message Fields") / [16](https://www.postgresql.org/docs/16/protocol-error-fields.html "PostgreSQL 16 - 53.8. Error and Notice Message Fields") / [15](https://www.postgresql.org/docs/15/protocol-error-fields.html "PostgreSQL 15 - 53.8. Error and Notice Message Fields") / [14](https://www.postgresql.org/docs/14/protocol-error-fields.html "PostgreSQL 14 - 53.8. Error and Notice Message Fields") Development Versions: [devel](https://www.postgresql.org/docs/devel/protocol-error-fields.html "PostgreSQL devel - 53.8. Error and Notice Message Fields") Unsupported versions: [13](https://www.postgresql.org/docs/13/protocol-error-fields.html "PostgreSQL 13 - 53.8. Error and Notice Message Fields") / [12](https://www.postgresql.org/docs/12/protocol-error-fields.html "PostgreSQL 12 - 53.8. Error and Notice Message Fields") / [11](https://www.postgresql.org/docs/11/protocol-error-fields.html "PostgreSQL 11 - 53.8. Error and Notice Message Fields") / [10](https://www.postgresql.org/docs/10/protocol-error-fields.html "PostgreSQL 10 - 53.8. Error and Notice Message Fields") / [9.6](https://www.postgresql.org/docs/9.6/protocol-error-fields.html "PostgreSQL 9.6 - 53.8. Error and Notice Message Fields") / [9.5](https://www.postgresql.org/docs/9.5/protocol-error-fields.html "PostgreSQL 9.5 - 53.8. Error and Notice Message Fields") / [9.4](https://www.postgresql.org/docs/9.4/protocol-error-fields.html "PostgreSQL 9.4 - 53.8. Error and Notice Message Fields") / [9.3](https://www.postgresql.org/docs/9.3/protocol-error-fields.html "PostgreSQL 9.3 - 53.8. Error and Notice Message Fields") / [9.2](https://www.postgresql.org/docs/9.2/protocol-error-fields.html "PostgreSQL 9.2 - 53.8. Error and Notice Message Fields") / [9.1](https://www.postgresql.org/docs/9.1/protocol-error-fields.html "PostgreSQL 9.1 - 53.8. Error and Notice Message Fields") / [9.0](https://www.postgresql.org/docs/9.0/protocol-error-fields.html "PostgreSQL 9.0 - 53.8. Error and Notice Message Fields") / [8.4](https://www.postgresql.org/docs/8.4/protocol-error-fields.html "PostgreSQL 8.4 - 53.8. Error and Notice Message Fields") / [8.3](https://www.postgresql.org/docs/8.3/protocol-error-fields.html "PostgreSQL 8.3 - 53.8. Error and Notice Message Fields") / [8.2](https://www.postgresql.org/docs/8.2/protocol-error-fields.html "PostgreSQL 8.2 - 53.8. Error and Notice Message Fields") / [8.1](https://www.postgresql.org/docs/8.1/protocol-error-fields.html "PostgreSQL 8.1 - 53.8. Error and Notice Message Fields") / [8.0](https://www.postgresql.org/docs/8.0/protocol-error-fields.html "PostgreSQL 8.0 - 53.8. Error and Notice Message Fields") / [7.4](https://www.postgresql.org/docs/7.4/protocol-error-fields.html "PostgreSQL 7.4 - 53.8. Error and Notice Message Fields") | 53.8. Error and Notice Message Fields | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/protocol-message-formats.html "53.7. Message Formats") | [Up](https://www.postgresql.org/docs/14/protocol.html "Chapter 53. Frontend/Backend Protocol") | Chapter 53. Frontend/Backend Protocol | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | [Next](https://www.postgresql.org/docs/14/protocol-logicalrep-message-formats.html "53.9. Logical Replication Message Formats") | * * * 53.8. Error and Notice Message Fields ------------------------------------- This section describes the fields that can appear in ErrorResponse and NoticeResponse messages. Each field type has a single-byte identification token. Note that any given field type should appear at most once per message. `S` Severity: the field contents are `ERROR`, `FATAL`, or `PANIC` (in an error message), or `WARNING`, `NOTICE`, `DEBUG`, `INFO`, or `LOG` (in a notice message), or a localized translation of one of these. Always present. `V` Severity: the field contents are `ERROR`, `FATAL`, or `PANIC` (in an error message), or `WARNING`, `NOTICE`, `DEBUG`, `INFO`, or `LOG` (in a notice message). This is identical to the `S` field except that the contents are never localized. This is present only in messages generated by PostgreSQL versions 9.6 and later. `C` Code: the SQLSTATE code for the error (see [Appendix A](https://www.postgresql.org/docs/14/errcodes-appendix.html "Appendix A. PostgreSQL Error Codes") ). Not localizable. Always present. `M` Message: the primary human-readable error message. This should be accurate but terse (typically one line). Always present. `D` Detail: an optional secondary error message carrying more detail about the problem. Might run to multiple lines. `H` Hint: an optional suggestion what to do about the problem. This is intended to differ from Detail in that it offers advice (potentially inappropriate) rather than hard facts. Might run to multiple lines. `P` Position: the field value is a decimal ASCII integer, indicating an error cursor position as an index into the original query string. The first character has index 1, and positions are measured in characters not bytes. `p` Internal position: this is defined the same as the `P` field, but it is used when the cursor position refers to an internally generated command rather than the one submitted by the client. The `q` field will always appear when this field appears. `q` Internal query: the text of a failed internally-generated command. This could be, for example, an SQL query issued by a PL/pgSQL function. `W` Where: an indication of the context in which the error occurred. Presently this includes a call stack traceback of active procedural language functions and internally-generated queries. The trace is one entry per line, most recent first. `s` Schema name: if the error was associated with a specific database object, the name of the schema containing that object, if any. `t` Table name: if the error was associated with a specific table, the name of the table. (Refer to the schema name field for the name of the table's schema.) `c` Column name: if the error was associated with a specific table column, the name of the column. (Refer to the schema and table name fields to identify the table.) `d` Data type name: if the error was associated with a specific data type, the name of the data type. (Refer to the schema name field for the name of the data type's schema.) `n` Constraint name: if the error was associated with a specific constraint, the name of the constraint. Refer to fields listed above for the associated table or domain. (For this purpose, indexes are treated as constraints, even if they weren't created with constraint syntax.) `F` File: the file name of the source-code location where the error was reported. `L` Line: the line number of the source-code location where the error was reported. `R` Routine: the name of the source-code routine reporting the error. ### Note The fields for schema name, table name, column name, data type name, and constraint name are supplied only for a limited number of error types; see [Appendix A](https://www.postgresql.org/docs/14/errcodes-appendix.html "Appendix A. PostgreSQL Error Codes") . Frontends should not assume that the presence of any of these fields guarantees the presence of another field. Core error sources observe the interrelationships noted above, but user-defined functions may use these fields in other ways. In the same vein, clients should not assume that these fields denote contemporary objects in the current database. The client is responsible for formatting displayed information to meet its needs; in particular it should break long lines as needed. Newline characters appearing in the error message fields should be treated as paragraph breaks, not line breaks. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/protocol-message-formats.html "53.7. Message Formats") | [Up](https://www.postgresql.org/docs/14/protocol.html "Chapter 53. Frontend/Backend Protocol") | [Next](https://www.postgresql.org/docs/14/protocol-logicalrep-message-formats.html "53.9. Logical Replication Message Formats") | | 53.7. Message Formats | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | 53.9. Logical Replication Message Formats | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/14/protocol-error-fields.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 14: Chapter 56. Writing a Procedural Language Handler November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 14](https://www.postgresql.org/docs/14/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plhandler.html "PostgreSQL 18 - Chapter 56. Writing a Procedural Language Handler") ([18](https://www.postgresql.org/docs/18/plhandler.html "PostgreSQL 18 - Chapter 56. Writing a Procedural Language Handler") ) / [17](https://www.postgresql.org/docs/17/plhandler.html "PostgreSQL 17 - Chapter 56. Writing a Procedural Language Handler") / [16](https://www.postgresql.org/docs/16/plhandler.html "PostgreSQL 16 - Chapter 56. Writing a Procedural Language Handler") / [15](https://www.postgresql.org/docs/15/plhandler.html "PostgreSQL 15 - Chapter 56. Writing a Procedural Language Handler") / [14](https://www.postgresql.org/docs/14/plhandler.html "PostgreSQL 14 - Chapter 56. Writing a Procedural Language Handler") Development Versions: [devel](https://www.postgresql.org/docs/devel/plhandler.html "PostgreSQL devel - Chapter 56. Writing a Procedural Language Handler") Unsupported versions: [13](https://www.postgresql.org/docs/13/plhandler.html "PostgreSQL 13 - Chapter 56. Writing a Procedural Language Handler") / [12](https://www.postgresql.org/docs/12/plhandler.html "PostgreSQL 12 - Chapter 56. Writing a Procedural Language Handler") / [11](https://www.postgresql.org/docs/11/plhandler.html "PostgreSQL 11 - Chapter 56. Writing a Procedural Language Handler") / [10](https://www.postgresql.org/docs/10/plhandler.html "PostgreSQL 10 - Chapter 56. Writing a Procedural Language Handler") / [9.6](https://www.postgresql.org/docs/9.6/plhandler.html "PostgreSQL 9.6 - Chapter 56. Writing a Procedural Language Handler") / [9.5](https://www.postgresql.org/docs/9.5/plhandler.html "PostgreSQL 9.5 - Chapter 56. Writing a Procedural Language Handler") / [9.4](https://www.postgresql.org/docs/9.4/plhandler.html "PostgreSQL 9.4 - Chapter 56. Writing a Procedural Language Handler") / [9.3](https://www.postgresql.org/docs/9.3/plhandler.html "PostgreSQL 9.3 - Chapter 56. Writing a Procedural Language Handler") / [9.2](https://www.postgresql.org/docs/9.2/plhandler.html "PostgreSQL 9.2 - Chapter 56. Writing a Procedural Language Handler") / [9.1](https://www.postgresql.org/docs/9.1/plhandler.html "PostgreSQL 9.1 - Chapter 56. Writing a Procedural Language Handler") / [9.0](https://www.postgresql.org/docs/9.0/plhandler.html "PostgreSQL 9.0 - Chapter 56. Writing a Procedural Language Handler") / [8.4](https://www.postgresql.org/docs/8.4/plhandler.html "PostgreSQL 8.4 - Chapter 56. Writing a Procedural Language Handler") / [8.3](https://www.postgresql.org/docs/8.3/plhandler.html "PostgreSQL 8.3 - Chapter 56. Writing a Procedural Language Handler") / [8.2](https://www.postgresql.org/docs/8.2/plhandler.html "PostgreSQL 8.2 - Chapter 56. Writing a Procedural Language Handler") / [8.1](https://www.postgresql.org/docs/8.1/plhandler.html "PostgreSQL 8.1 - Chapter 56. Writing a Procedural Language Handler") / [8.0](https://www.postgresql.org/docs/8.0/plhandler.html "PostgreSQL 8.0 - Chapter 56. Writing a Procedural Language Handler") / [7.4](https://www.postgresql.org/docs/7.4/plhandler.html "PostgreSQL 7.4 - Chapter 56. Writing a Procedural Language Handler") | Chapter 56. Writing a Procedural Language Handler | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/nls-programmer.html "55.2. For the Programmer") | [Up](https://www.postgresql.org/docs/14/internals.html "Part VII. Internals") | Part VII. Internals | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | [Next](https://www.postgresql.org/docs/14/fdwhandler.html "Chapter 57. Writing a Foreign Data Wrapper") | * * * Chapter 56. Writing a Procedural Language Handler ------------------------------------------------- All calls to functions that are written in a language other than the current “version 1” interface for compiled languages (this includes functions in user-defined procedural languages and functions written in SQL) go through a _call handler_ function for the specific language. It is the responsibility of the call handler to execute the function in a meaningful way, such as by interpreting the supplied source text. This chapter outlines how a new procedural language's call handler can be written. The call handler for a procedural language is a “normal” function that must be written in a compiled language such as C, using the version-1 interface, and registered with PostgreSQL as taking no arguments and returning the type `language_handler`. This special pseudo-type identifies the function as a call handler and prevents it from being called directly in SQL commands. For more details on C language calling conventions and dynamic loading, see [Section 38.10](https://www.postgresql.org/docs/14/xfunc-c.html "38.10. C-Language Functions") . The call handler is called in the same way as any other function: It receives a pointer to a `FunctionCallInfoBaseData` `struct` containing argument values and information about the called function, and it is expected to return a `Datum` result (and possibly set the `isnull` field of the `FunctionCallInfoBaseData` structure, if it wishes to return an SQL null result). The difference between a call handler and an ordinary callee function is that the `flinfo->fn_oid` field of the `FunctionCallInfoBaseData` structure will contain the OID of the actual function to be called, not of the call handler itself. The call handler must use this field to determine which function to execute. Also, the passed argument list has been set up according to the declaration of the target function, not of the call handler. It's up to the call handler to fetch the entry of the function from the `pg_proc` system catalog and to analyze the argument and return types of the called function. The `AS` clause from the `CREATE FUNCTION` command for the function will be found in the `prosrc` column of the `pg_proc` row. This is commonly source text in the procedural language, but in theory it could be something else, such as a path name to a file, or anything else that tells the call handler what to do in detail. Often, the same function is called many times per SQL statement. A call handler can avoid repeated lookups of information about the called function by using the `flinfo->fn_extra` field. This will initially be `NULL`, but can be set by the call handler to point at information about the called function. On subsequent calls, if `flinfo->fn_extra` is already non-`NULL` then it can be used and the information lookup step skipped. The call handler must make sure that `flinfo->fn_extra` is made to point at memory that will live at least until the end of the current query, since an `FmgrInfo` data structure could be kept that long. One way to do this is to allocate the extra data in the memory context specified by `flinfo->fn_mcxt`; such data will normally have the same lifespan as the `FmgrInfo` itself. But the handler could also choose to use a longer-lived memory context so that it can cache function definition information across queries. When a procedural-language function is invoked as a trigger, no arguments are passed in the usual way, but the `FunctionCallInfoBaseData`'s `context` field points at a `TriggerData` structure, rather than being `NULL` as it is in a plain function call. A language handler should provide mechanisms for procedural-language functions to get at the trigger information. A template for a procedural-language handler written as a C extension is provided in `src/test/modules/plsample`. This is a working sample demonstrating one way to create a procedural-language handler, process parameters, and return a value. Although providing a call handler is sufficient to create a minimal procedural language, there are two other functions that can optionally be provided to make the language more convenient to use. These are a _validator_ and an _inline handler_. A validator can be provided to allow language-specific checking to be done during [CREATE FUNCTION](https://www.postgresql.org/docs/14/sql-createfunction.html "CREATE FUNCTION") . An inline handler can be provided to allow the language to support anonymous code blocks executed via the [DO](https://www.postgresql.org/docs/14/sql-do.html "DO") command. If a validator is provided by a procedural language, it must be declared as a function taking a single parameter of type `oid`. The validator's result is ignored, so it is customarily declared to return `void`. The validator will be called at the end of a `CREATE FUNCTION` command that has created or updated a function written in the procedural language. The passed-in OID is the OID of the function's `pg_proc` row. The validator must fetch this row in the usual way, and do whatever checking is appropriate. First, call `CheckFunctionValidatorAccess()` to diagnose explicit calls to the validator that the user could not achieve through `CREATE FUNCTION`. Typical checks then include verifying that the function's argument and result types are supported by the language, and that the function's body is syntactically correct in the language. If the validator finds the function to be okay, it should just return. If it finds an error, it should report that via the normal `ereport()` error reporting mechanism. Throwing an error will force a transaction rollback and thus prevent the incorrect function definition from being committed. Validator functions should typically honor the [check\_function\_bodies](https://www.postgresql.org/docs/14/runtime-config-client.html#GUC-CHECK-FUNCTION-BODIES) parameter: if it is turned off then any expensive or context-sensitive checking should be skipped. If the language provides for code execution at compilation time, the validator must suppress checks that would induce such execution. In particular, this parameter is turned off by pg\_dump so that it can load procedural language functions without worrying about side effects or dependencies of the function bodies on other database objects. (Because of this requirement, the call handler should avoid assuming that the validator has fully checked the function. The point of having a validator is not to let the call handler omit checks, but to notify the user immediately if there are obvious errors in a `CREATE FUNCTION` command.) While the choice of exactly what to check is mostly left to the discretion of the validator function, note that the core `CREATE FUNCTION` code only executes `SET` clauses attached to a function when `check_function_bodies` is on. Therefore, checks whose results might be affected by GUC parameters definitely should be skipped when `check_function_bodies` is off, to avoid false failures when restoring a dump. If an inline handler is provided by a procedural language, it must be declared as a function taking a single parameter of type `internal`. The inline handler's result is ignored, so it is customarily declared to return `void`. The inline handler will be called when a `DO` statement is executed specifying the procedural language. The parameter actually passed is a pointer to an `InlineCodeBlock` struct, which contains information about the `DO` statement's parameters, in particular the text of the anonymous code block to be executed. The inline handler should execute this code and return. It's recommended that you wrap all these function declarations, as well as the `CREATE LANGUAGE` command itself, into an _extension_ so that a simple `CREATE EXTENSION` command is sufficient to install the language. See [Section 38.17](https://www.postgresql.org/docs/14/extend-extensions.html "38.17. Packaging Related Objects into an Extension") for information about writing extensions. The procedural languages included in the standard distribution are good references when trying to write your own language handler. Look into the `src/pl` subdirectory of the source tree. The [CREATE LANGUAGE](https://www.postgresql.org/docs/14/sql-createlanguage.html "CREATE LANGUAGE") reference page also has some useful details. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/nls-programmer.html "55.2. For the Programmer") | [Up](https://www.postgresql.org/docs/14/internals.html "Part VII. Internals") | [Next](https://www.postgresql.org/docs/14/fdwhandler.html "Chapter 57. Writing a Foreign Data Wrapper") | | 55.2. For the Programmer | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | Chapter 57. Writing a Foreign Data Wrapper | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/14/plhandler.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 14: TRUNCATE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 14](https://www.postgresql.org/docs/14/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-truncate.html "PostgreSQL 18 - TRUNCATE") ([18](https://www.postgresql.org/docs/18/sql-truncate.html "PostgreSQL 18 - TRUNCATE") ) / [17](https://www.postgresql.org/docs/17/sql-truncate.html "PostgreSQL 17 - TRUNCATE") / [16](https://www.postgresql.org/docs/16/sql-truncate.html "PostgreSQL 16 - TRUNCATE") / [15](https://www.postgresql.org/docs/15/sql-truncate.html "PostgreSQL 15 - TRUNCATE") / [14](https://www.postgresql.org/docs/14/sql-truncate.html "PostgreSQL 14 - TRUNCATE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-truncate.html "PostgreSQL devel - TRUNCATE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-truncate.html "PostgreSQL 13 - TRUNCATE") / [12](https://www.postgresql.org/docs/12/sql-truncate.html "PostgreSQL 12 - TRUNCATE") / [11](https://www.postgresql.org/docs/11/sql-truncate.html "PostgreSQL 11 - TRUNCATE") / [10](https://www.postgresql.org/docs/10/sql-truncate.html "PostgreSQL 10 - TRUNCATE") / [9.6](https://www.postgresql.org/docs/9.6/sql-truncate.html "PostgreSQL 9.6 - TRUNCATE") / [9.5](https://www.postgresql.org/docs/9.5/sql-truncate.html "PostgreSQL 9.5 - TRUNCATE") / [9.4](https://www.postgresql.org/docs/9.4/sql-truncate.html "PostgreSQL 9.4 - TRUNCATE") / [9.3](https://www.postgresql.org/docs/9.3/sql-truncate.html "PostgreSQL 9.3 - TRUNCATE") / [9.2](https://www.postgresql.org/docs/9.2/sql-truncate.html "PostgreSQL 9.2 - TRUNCATE") / [9.1](https://www.postgresql.org/docs/9.1/sql-truncate.html "PostgreSQL 9.1 - TRUNCATE") / [9.0](https://www.postgresql.org/docs/9.0/sql-truncate.html "PostgreSQL 9.0 - TRUNCATE") / [8.4](https://www.postgresql.org/docs/8.4/sql-truncate.html "PostgreSQL 8.4 - TRUNCATE") / [8.3](https://www.postgresql.org/docs/8.3/sql-truncate.html "PostgreSQL 8.3 - TRUNCATE") / [8.2](https://www.postgresql.org/docs/8.2/sql-truncate.html "PostgreSQL 8.2 - TRUNCATE") / [8.1](https://www.postgresql.org/docs/8.1/sql-truncate.html "PostgreSQL 8.1 - TRUNCATE") / [8.0](https://www.postgresql.org/docs/8.0/sql-truncate.html "PostgreSQL 8.0 - TRUNCATE") / [7.4](https://www.postgresql.org/docs/7.4/sql-truncate.html "PostgreSQL 7.4 - TRUNCATE") / [7.3](https://www.postgresql.org/docs/7.3/sql-truncate.html "PostgreSQL 7.3 - TRUNCATE") / [7.2](https://www.postgresql.org/docs/7.2/sql-truncate.html "PostgreSQL 7.2 - TRUNCATE") / [7.1](https://www.postgresql.org/docs/7.1/sql-truncate.html "PostgreSQL 7.1 - TRUNCATE") | TRUNCATE | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/sql-start-transaction.html "START TRANSACTION") | [Up](https://www.postgresql.org/docs/14/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | [Next](https://www.postgresql.org/docs/14/sql-unlisten.html "UNLISTEN") | * * * TRUNCATE -------- TRUNCATE — empty a table or set of tables Synopsis -------- TRUNCATE \[ TABLE \] \[ ONLY \] _`name`_ \[ \* \] \[, ... \] \[ RESTART IDENTITY | CONTINUE IDENTITY \] \[ CASCADE | RESTRICT \] Description ----------- `TRUNCATE` quickly removes all rows from a set of tables. It has the same effect as an unqualified `DELETE` on each table, but since it does not actually scan the tables it is faster. Furthermore, it reclaims disk space immediately, rather than requiring a subsequent `VACUUM` operation. This is most useful on large tables. Parameters ---------- _`name`_ The name (optionally schema-qualified) of a table to truncate. If `ONLY` is specified before the table name, only that table is truncated. If `ONLY` is not specified, the table and all its descendant tables (if any) are truncated. Optionally, `*` can be specified after the table name to explicitly indicate that descendant tables are included. `RESTART IDENTITY` Automatically restart sequences owned by columns of the truncated table(s). `CONTINUE IDENTITY` Do not change the values of sequences. This is the default. `CASCADE` Automatically truncate all tables that have foreign-key references to any of the named tables, or to any tables added to the group due to `CASCADE`. `RESTRICT` Refuse to truncate if any of the tables have foreign-key references from tables that are not listed in the command. This is the default. Notes ----- You must have the `TRUNCATE` privilege on a table to truncate it. `TRUNCATE` acquires an `ACCESS EXCLUSIVE` lock on each table it operates on, which blocks all other concurrent operations on the table. When `RESTART IDENTITY` is specified, any sequences that are to be restarted are likewise locked exclusively. If concurrent access to a table is required, then the `DELETE` command should be used instead. `TRUNCATE` cannot be used on a table that has foreign-key references from other tables, unless all such tables are also truncated in the same command. Checking validity in such cases would require table scans, and the whole point is not to do one. The `CASCADE` option can be used to automatically include all dependent tables — but be very careful when using this option, or else you might lose data you did not intend to! Note in particular that when the table to be truncated is a partition, siblings partitions are left untouched, but cascading occurs to all referencing tables and all their partitions with no distinction. `TRUNCATE` will not fire any `ON DELETE` triggers that might exist for the tables. But it will fire `ON TRUNCATE` triggers. If `ON TRUNCATE` triggers are defined for any of the tables, then all `BEFORE TRUNCATE` triggers are fired before any truncation happens, and all `AFTER TRUNCATE` triggers are fired after the last truncation is performed and any sequences are reset. The triggers will fire in the order that the tables are to be processed (first those listed in the command, and then any that were added due to cascading). `TRUNCATE` is not MVCC-safe. After truncation, the table will appear empty to concurrent transactions, if they are using a snapshot taken before the truncation occurred. See [Section 13.5](https://www.postgresql.org/docs/14/mvcc-caveats.html "13.5. Caveats") for more details. `TRUNCATE` is transaction-safe with respect to the data in the tables: the truncation will be safely rolled back if the surrounding transaction does not commit. When `RESTART IDENTITY` is specified, the implied `ALTER SEQUENCE RESTART` operations are also done transactionally; that is, they will be rolled back if the surrounding transaction does not commit. Be aware that if any additional sequence operations are done on the restarted sequences before the transaction rolls back, the effects of these operations on the sequences will be rolled back, but not their effects on `currval()`; that is, after the transaction `currval()` will continue to reflect the last sequence value obtained inside the failed transaction, even though the sequence itself may no longer be consistent with that. This is similar to the usual behavior of `currval()` after a failed transaction. `TRUNCATE` can be used for foreign tables if supported by the foreign data wrapper, for instance, see [postgres\_fdw](https://www.postgresql.org/docs/14/postgres-fdw.html "F.35. postgres_fdw") . Examples -------- Truncate the tables `bigtable` and `fattable`: TRUNCATE bigtable, fattable; The same, and also reset any associated sequence generators: TRUNCATE bigtable, fattable RESTART IDENTITY; Truncate the table `othertable`, and cascade to any tables that reference `othertable` via foreign-key constraints: TRUNCATE othertable CASCADE; Compatibility ------------- The SQL:2008 standard includes a `TRUNCATE` command with the syntax ``TRUNCATE TABLE _`tablename`_``. The clauses `CONTINUE IDENTITY`/`RESTART IDENTITY` also appear in that standard, but have slightly different though related meanings. Some of the concurrency behavior of this command is left implementation-defined by the standard, so the above notes should be considered and compared with other implementations if necessary. See Also -------- [DELETE](https://www.postgresql.org/docs/14/sql-delete.html "DELETE") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/sql-start-transaction.html "START TRANSACTION") | [Up](https://www.postgresql.org/docs/14/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/14/sql-unlisten.html "UNLISTEN") | | START TRANSACTION | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | UNLISTEN | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/14/sql-truncate.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 14: 53.2. Message Flow November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 14](https://www.postgresql.org/docs/14/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/protocol-flow.html "PostgreSQL 18 - 53.2. Message Flow") ([18](https://www.postgresql.org/docs/18/protocol-flow.html "PostgreSQL 18 - 53.2. Message Flow") ) / [17](https://www.postgresql.org/docs/17/protocol-flow.html "PostgreSQL 17 - 53.2. Message Flow") / [16](https://www.postgresql.org/docs/16/protocol-flow.html "PostgreSQL 16 - 53.2. Message Flow") / [15](https://www.postgresql.org/docs/15/protocol-flow.html "PostgreSQL 15 - 53.2. Message Flow") / [14](https://www.postgresql.org/docs/14/protocol-flow.html "PostgreSQL 14 - 53.2. Message Flow") Development Versions: [devel](https://www.postgresql.org/docs/devel/protocol-flow.html "PostgreSQL devel - 53.2. Message Flow") Unsupported versions: [13](https://www.postgresql.org/docs/13/protocol-flow.html "PostgreSQL 13 - 53.2. Message Flow") / [12](https://www.postgresql.org/docs/12/protocol-flow.html "PostgreSQL 12 - 53.2. Message Flow") / [11](https://www.postgresql.org/docs/11/protocol-flow.html "PostgreSQL 11 - 53.2. Message Flow") / [10](https://www.postgresql.org/docs/10/protocol-flow.html "PostgreSQL 10 - 53.2. Message Flow") / [9.6](https://www.postgresql.org/docs/9.6/protocol-flow.html "PostgreSQL 9.6 - 53.2. Message Flow") / [9.5](https://www.postgresql.org/docs/9.5/protocol-flow.html "PostgreSQL 9.5 - 53.2. Message Flow") / [9.4](https://www.postgresql.org/docs/9.4/protocol-flow.html "PostgreSQL 9.4 - 53.2. Message Flow") / [9.3](https://www.postgresql.org/docs/9.3/protocol-flow.html "PostgreSQL 9.3 - 53.2. Message Flow") / [9.2](https://www.postgresql.org/docs/9.2/protocol-flow.html "PostgreSQL 9.2 - 53.2. Message Flow") / [9.1](https://www.postgresql.org/docs/9.1/protocol-flow.html "PostgreSQL 9.1 - 53.2. Message Flow") / [9.0](https://www.postgresql.org/docs/9.0/protocol-flow.html "PostgreSQL 9.0 - 53.2. Message Flow") / [8.4](https://www.postgresql.org/docs/8.4/protocol-flow.html "PostgreSQL 8.4 - 53.2. Message Flow") / [8.3](https://www.postgresql.org/docs/8.3/protocol-flow.html "PostgreSQL 8.3 - 53.2. Message Flow") / [8.2](https://www.postgresql.org/docs/8.2/protocol-flow.html "PostgreSQL 8.2 - 53.2. Message Flow") / [8.1](https://www.postgresql.org/docs/8.1/protocol-flow.html "PostgreSQL 8.1 - 53.2. Message Flow") / [8.0](https://www.postgresql.org/docs/8.0/protocol-flow.html "PostgreSQL 8.0 - 53.2. Message Flow") / [7.4](https://www.postgresql.org/docs/7.4/protocol-flow.html "PostgreSQL 7.4 - 53.2. Message Flow") | 53.2. Message Flow | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/protocol-overview.html "53.1. Overview") | [Up](https://www.postgresql.org/docs/14/protocol.html "Chapter 53. Frontend/Backend Protocol") | Chapter 53. Frontend/Backend Protocol | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | [Next](https://www.postgresql.org/docs/14/sasl-authentication.html "53.3. SASL Authentication") | * * * 53.2. Message Flow ------------------ [53.2.1. Start-up](https://www.postgresql.org/docs/14/protocol-flow.html#id-1.10.5.7.3) [53.2.2. Simple Query](https://www.postgresql.org/docs/14/protocol-flow.html#id-1.10.5.7.4) [53.2.3. Extended Query](https://www.postgresql.org/docs/14/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY) [53.2.4. Pipelining](https://www.postgresql.org/docs/14/protocol-flow.html#PROTOCOL-FLOW-PIPELINING) [53.2.5. Function Call](https://www.postgresql.org/docs/14/protocol-flow.html#id-1.10.5.7.7) [53.2.6. COPY Operations](https://www.postgresql.org/docs/14/protocol-flow.html#PROTOCOL-COPY) [53.2.7. Asynchronous Operations](https://www.postgresql.org/docs/14/protocol-flow.html#PROTOCOL-ASYNC) [53.2.8. Canceling Requests in Progress](https://www.postgresql.org/docs/14/protocol-flow.html#id-1.10.5.7.10) [53.2.9. Termination](https://www.postgresql.org/docs/14/protocol-flow.html#id-1.10.5.7.11) [53.2.10. SSL Session Encryption](https://www.postgresql.org/docs/14/protocol-flow.html#id-1.10.5.7.12) [53.2.11. GSSAPI Session Encryption](https://www.postgresql.org/docs/14/protocol-flow.html#id-1.10.5.7.13) This section describes the message flow and the semantics of each message type. (Details of the exact representation of each message appear in [Section 53.7](https://www.postgresql.org/docs/14/protocol-message-formats.html "53.7. Message Formats") .) There are several different sub-protocols depending on the state of the connection: start-up, query, function call, `COPY`, and termination. There are also special provisions for asynchronous operations (including notification responses and command cancellation), which can occur at any time after the start-up phase. ### 53.2.1. Start-up To begin a session, a frontend opens a connection to the server and sends a startup message. This message includes the names of the user and of the database the user wants to connect to; it also identifies the particular protocol version to be used. (Optionally, the startup message can include additional settings for run-time parameters.) The server then uses this information and the contents of its configuration files (such as `pg_hba.conf`) to determine whether the connection is provisionally acceptable, and what additional authentication is required (if any). The server then sends an appropriate authentication request message, to which the frontend must reply with an appropriate authentication response message (such as a password). For all authentication methods except GSSAPI, SSPI and SASL, there is at most one request and one response. In some methods, no response at all is needed from the frontend, and so no authentication request occurs. For GSSAPI, SSPI and SASL, multiple exchanges of packets may be needed to complete the authentication. The authentication cycle ends with the server either rejecting the connection attempt (ErrorResponse), or sending AuthenticationOk. The possible messages from the server in this phase are: ErrorResponse The connection attempt has been rejected. The server then immediately closes the connection. AuthenticationOk The authentication exchange is successfully completed. AuthenticationKerberosV5 The frontend must now take part in a Kerberos V5 authentication dialog (not described here, part of the Kerberos specification) with the server. If this is successful, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. This is no longer supported. AuthenticationCleartextPassword The frontend must now send a PasswordMessage containing the password in clear-text form. If this is the correct password, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. AuthenticationMD5Password The frontend must now send a PasswordMessage containing the password (with user name) encrypted via MD5, then encrypted again using the 4-byte random salt specified in the AuthenticationMD5Password message. If this is the correct password, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. The actual PasswordMessage can be computed in SQL as `concat('md5', md5(concat(md5(concat(password, username)), random-salt)))`. (Keep in mind the `md5()` function returns its result as a hex string.) AuthenticationSCMCredential This response is only possible for local Unix-domain connections on platforms that support SCM credential messages. The frontend must issue an SCM credential message and then send a single data byte. (The contents of the data byte are uninteresting; it's only used to ensure that the server waits long enough to receive the credential message.) If the credential is acceptable, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. (This message type is only issued by pre-9.1 servers. It may eventually be removed from the protocol specification.) AuthenticationGSS The frontend must now initiate a GSSAPI negotiation. The frontend will send a GSSResponse message with the first part of the GSSAPI data stream in response to this. If further messages are needed, the server will respond with AuthenticationGSSContinue. AuthenticationSSPI The frontend must now initiate an SSPI negotiation. The frontend will send a GSSResponse with the first part of the SSPI data stream in response to this. If further messages are needed, the server will respond with AuthenticationGSSContinue. AuthenticationGSSContinue This message contains the response data from the previous step of GSSAPI or SSPI negotiation (AuthenticationGSS, AuthenticationSSPI or a previous AuthenticationGSSContinue). If the GSSAPI or SSPI data in this message indicates more data is needed to complete the authentication, the frontend must send that data as another GSSResponse message. If GSSAPI or SSPI authentication is completed by this message, the server will next send AuthenticationOk to indicate successful authentication or ErrorResponse to indicate failure. AuthenticationSASL The frontend must now initiate a SASL negotiation, using one of the SASL mechanisms listed in the message. The frontend will send a SASLInitialResponse with the name of the selected mechanism, and the first part of the SASL data stream in response to this. If further messages are needed, the server will respond with AuthenticationSASLContinue. See [Section 53.3](https://www.postgresql.org/docs/14/sasl-authentication.html "53.3. SASL Authentication") for details. AuthenticationSASLContinue This message contains challenge data from the previous step of SASL negotiation (AuthenticationSASL, or a previous AuthenticationSASLContinue). The frontend must respond with a SASLResponse message. AuthenticationSASLFinal SASL authentication has completed with additional mechanism-specific data for the client. The server will next send AuthenticationOk to indicate successful authentication, or an ErrorResponse to indicate failure. This message is sent only if the SASL mechanism specifies additional data to be sent from server to client at completion. NegotiateProtocolVersion The server does not support the minor protocol version requested by the client, but does support an earlier version of the protocol; this message indicates the highest supported minor version. This message will also be sent if the client requested unsupported protocol options (i.e., beginning with `_pq_.`) in the startup packet. This message will be followed by an ErrorResponse or a message indicating the success or failure of authentication. If the frontend does not support the authentication method requested by the server, then it should immediately close the connection. After having received AuthenticationOk, the frontend must wait for further messages from the server. In this phase a backend process is being started, and the frontend is just an interested bystander. It is still possible for the startup attempt to fail (ErrorResponse) or the server to decline support for the requested minor protocol version (NegotiateProtocolVersion), but in the normal case the backend will send some ParameterStatus messages, BackendKeyData, and finally ReadyForQuery. During this phase the backend will attempt to apply any additional run-time parameter settings that were given in the startup message. If successful, these values become session defaults. An error causes ErrorResponse and exit. The possible messages from the backend in this phase are: BackendKeyData This message provides secret-key data that the frontend must save if it wants to be able to issue cancel requests later. The frontend should not respond to this message, but should continue listening for a ReadyForQuery message. ParameterStatus This message informs the frontend about the current (initial) setting of backend parameters, such as [client\_encoding](https://www.postgresql.org/docs/14/runtime-config-client.html#GUC-CLIENT-ENCODING) or [DateStyle](https://www.postgresql.org/docs/14/runtime-config-client.html#GUC-DATESTYLE) . The frontend can ignore this message, or record the settings for its future use; see [Section 53.2.7](https://www.postgresql.org/docs/14/protocol-flow.html#PROTOCOL-ASYNC "53.2.7. Asynchronous Operations") for more details. The frontend should not respond to this message, but should continue listening for a ReadyForQuery message. ReadyForQuery Start-up is completed. The frontend can now issue commands. ErrorResponse Start-up failed. The connection is closed after sending this message. NoticeResponse A warning message has been issued. The frontend should display the message but continue listening for ReadyForQuery or ErrorResponse. The ReadyForQuery message is the same one that the backend will issue after each command cycle. Depending on the coding needs of the frontend, it is reasonable to consider ReadyForQuery as starting a command cycle, or to consider ReadyForQuery as ending the start-up phase and each subsequent command cycle. ### 53.2.2. Simple Query A simple query cycle is initiated by the frontend sending a Query message to the backend. The message includes an SQL command (or commands) expressed as a text string. The backend then sends one or more response messages depending on the contents of the query command string, and finally a ReadyForQuery response message. ReadyForQuery informs the frontend that it can safely send a new command. (It is not actually necessary for the frontend to wait for ReadyForQuery before issuing another command, but the frontend must then take responsibility for figuring out what happens if the earlier command fails and already-issued later commands succeed.) The possible response messages from the backend are: CommandComplete An SQL command completed normally. CopyInResponse The backend is ready to copy data from the frontend to a table; see [Section 53.2.6](https://www.postgresql.org/docs/14/protocol-flow.html#PROTOCOL-COPY "53.2.6. COPY Operations") . CopyOutResponse The backend is ready to copy data from a table to the frontend; see [Section 53.2.6](https://www.postgresql.org/docs/14/protocol-flow.html#PROTOCOL-COPY "53.2.6. COPY Operations") . RowDescription Indicates that rows are about to be returned in response to a `SELECT`, `FETCH`, etc query. The contents of this message describe the column layout of the rows. This will be followed by a DataRow message for each row being returned to the frontend. DataRow One of the set of rows returned by a `SELECT`, `FETCH`, etc query. EmptyQueryResponse An empty query string was recognized. ErrorResponse An error has occurred. ReadyForQuery Processing of the query string is complete. A separate message is sent to indicate this because the query string might contain multiple SQL commands. (CommandComplete marks the end of processing one SQL command, not the whole string.) ReadyForQuery will always be sent, whether processing terminates successfully or with an error. NoticeResponse A warning message has been issued in relation to the query. Notices are in addition to other responses, i.e., the backend will continue processing the command. The response to a `SELECT` query (or other queries that return row sets, such as `EXPLAIN` or `SHOW`) normally consists of RowDescription, zero or more DataRow messages, and then CommandComplete. `COPY` to or from the frontend invokes special protocol as described in [Section 53.2.6](https://www.postgresql.org/docs/14/protocol-flow.html#PROTOCOL-COPY "53.2.6. COPY Operations") . All other query types normally produce only a CommandComplete message. Since a query string could contain several queries (separated by semicolons), there might be several such response sequences before the backend finishes processing the query string. ReadyForQuery is issued when the entire string has been processed and the backend is ready to accept a new query string. If a completely empty (no contents other than whitespace) query string is received, the response is EmptyQueryResponse followed by ReadyForQuery. In the event of an error, ErrorResponse is issued followed by ReadyForQuery. All further processing of the query string is aborted by ErrorResponse (even if more queries remained in it). Note that this might occur partway through the sequence of messages generated by an individual query. In simple Query mode, the format of retrieved values is always text, except when the given command is a `FETCH` from a cursor declared with the `BINARY` option. In that case, the retrieved values are in binary format. The format codes given in the RowDescription message tell which format is being used. A frontend must be prepared to accept ErrorResponse and NoticeResponse messages whenever it is expecting any other type of message. See also [Section 53.2.7](https://www.postgresql.org/docs/14/protocol-flow.html#PROTOCOL-ASYNC "53.2.7. Asynchronous Operations") concerning messages that the backend might generate due to outside events. Recommended practice is to code frontends in a state-machine style that will accept any message type at any time that it could make sense, rather than wiring in assumptions about the exact sequence of messages. #### 53.2.2.1. Multiple Statements in a Simple Query When a simple Query message contains more than one SQL statement (separated by semicolons), those statements are executed as a single transaction, unless explicit transaction control commands are included to force a different behavior. For example, if the message contains INSERT INTO mytable VALUES(1); SELECT 1/0; INSERT INTO mytable VALUES(2); then the divide-by-zero failure in the `SELECT` will force rollback of the first `INSERT`. Furthermore, because execution of the message is abandoned at the first error, the second `INSERT` is never attempted at all. If instead the message contains BEGIN; INSERT INTO mytable VALUES(1); COMMIT; INSERT INTO mytable VALUES(2); SELECT 1/0; then the first `INSERT` is committed by the explicit `COMMIT` command. The second `INSERT` and the `SELECT` are still treated as a single transaction, so that the divide-by-zero failure will roll back the second `INSERT`, but not the first one. This behavior is implemented by running the statements in a multi-statement Query message in an _implicit transaction block_ unless there is some explicit transaction block for them to run in. The main difference between an implicit transaction block and a regular one is that an implicit block is closed automatically at the end of the Query message, either by an implicit commit if there was no error, or an implicit rollback if there was an error. This is similar to the implicit commit or rollback that happens for a statement executed by itself (when not in a transaction block). If the session is already in a transaction block, as a result of a `BEGIN` in some previous message, then the Query message simply continues that transaction block, whether the message contains one statement or several. However, if the Query message contains a `COMMIT` or `ROLLBACK` closing the existing transaction block, then any following statements are executed in an implicit transaction block. Conversely, if a `BEGIN` appears in a multi-statement Query message, then it starts a regular transaction block that will only be terminated by an explicit `COMMIT` or `ROLLBACK`, whether that appears in this Query message or a later one. If the `BEGIN` follows some statements that were executed as an implicit transaction block, those statements are not immediately committed; in effect, they are retroactively included into the new regular transaction block. A `COMMIT` or `ROLLBACK` appearing in an implicit transaction block is executed as normal, closing the implicit block; however, a warning will be issued since a `COMMIT` or `ROLLBACK` without a previous `BEGIN` might represent a mistake. If more statements follow, a new implicit transaction block will be started for them. Savepoints are not allowed in an implicit transaction block, since they would conflict with the behavior of automatically closing the block upon any error. Remember that, regardless of any transaction control commands that may be present, execution of the Query message stops at the first error. Thus for example given BEGIN; SELECT 1/0; ROLLBACK; in a single Query message, the session will be left inside a failed regular transaction block, since the `ROLLBACK` is not reached after the divide-by-zero error. Another `ROLLBACK` will be needed to restore the session to a usable state. Another behavior of note is that initial lexical and syntactic analysis is done on the entire query string before any of it is executed. Thus simple errors (such as a misspelled keyword) in later statements can prevent execution of any of the statements. This is normally invisible to users since the statements would all roll back anyway when done as an implicit transaction block. However, it can be visible when attempting to do multiple transactions within a multi-statement Query. For instance, if a typo turned our previous example into BEGIN; INSERT INTO mytable VALUES(1); COMMIT; INSERT INTO mytable VALUES(2); SELCT 1/0; then none of the statements would get run, resulting in the visible difference that the first `INSERT` is not committed. Errors detected at semantic analysis or later, such as a misspelled table or column name, do not have this effect. Lastly, note that all the statements within the Query message will observe the same value of `statement_timestamp()`, since that timestamp is updated only upon receipt of the Query message. This will result in them all observing the same value of `transaction_timestamp()` as well, except in cases where the query string ends a previously-started transaction and begins a new one. ### 53.2.3. Extended Query The extended query protocol breaks down the above-described simple query protocol into multiple steps. The results of preparatory steps can be re-used multiple times for improved efficiency. Furthermore, additional features are available, such as the possibility of supplying data values as separate parameters instead of having to insert them directly into a query string. In the extended protocol, the frontend first sends a Parse message, which contains a textual query string, optionally some information about data types of parameter placeholders, and the name of a destination prepared-statement object (an empty string selects the unnamed prepared statement). The response is either ParseComplete or ErrorResponse. Parameter data types can be specified by OID; if not given, the parser attempts to infer the data types in the same way as it would do for untyped literal string constants. ### Note A parameter data type can be left unspecified by setting it to zero, or by making the array of parameter type OIDs shorter than the number of parameter symbols (`$`_`n`_) used in the query string. Another special case is that a parameter's type can be specified as `void` (that is, the OID of the `void` pseudo-type). This is meant to allow parameter symbols to be used for function parameters that are actually OUT parameters. Ordinarily there is no context in which a `void` parameter could be used, but if such a parameter symbol appears in a function's parameter list, it is effectively ignored. For example, a function call such as `foo($1,$2,$3,$4)` could match a function with two IN and two OUT arguments, if `$3` and `$4` are specified as having type `void`. ### Note The query string contained in a Parse message cannot include more than one SQL statement; else a syntax error is reported. This restriction does not exist in the simple-query protocol, but it does exist in the extended protocol, because allowing prepared statements or portals to contain multiple commands would complicate the protocol unduly. If successfully created, a named prepared-statement object lasts till the end of the current session, unless explicitly destroyed. An unnamed prepared statement lasts only until the next Parse statement specifying the unnamed statement as destination is issued. (Note that a simple Query message also destroys the unnamed statement.) Named prepared statements must be explicitly closed before they can be redefined by another Parse message, but this is not required for the unnamed statement. Named prepared statements can also be created and accessed at the SQL command level, using `PREPARE` and `EXECUTE`. Once a prepared statement exists, it can be readied for execution using a Bind message. The Bind message gives the name of the source prepared statement (empty string denotes the unnamed prepared statement), the name of the destination portal (empty string denotes the unnamed portal), and the values to use for any parameter placeholders present in the prepared statement. The supplied parameter set must match those needed by the prepared statement. (If you declared any `void` parameters in the Parse message, pass NULL values for them in the Bind message.) Bind also specifies the format to use for any data returned by the query; the format can be specified overall, or per-column. The response is either BindComplete or ErrorResponse. ### Note The choice between text and binary output is determined by the format codes given in Bind, regardless of the SQL command involved. The `BINARY` attribute in cursor declarations is irrelevant when using extended query protocol. Query planning typically occurs when the Bind message is processed. If the prepared statement has no parameters, or is executed repeatedly, the server might save the created plan and re-use it during subsequent Bind messages for the same prepared statement. However, it will do so only if it finds that a generic plan can be created that is not much less efficient than a plan that depends on the specific parameter values supplied. This happens transparently so far as the protocol is concerned. If successfully created, a named portal object lasts till the end of the current transaction, unless explicitly destroyed. An unnamed portal is destroyed at the end of the transaction, or as soon as the next Bind statement specifying the unnamed portal as destination is issued. (Note that a simple Query message also destroys the unnamed portal.) Named portals must be explicitly closed before they can be redefined by another Bind message, but this is not required for the unnamed portal. Named portals can also be created and accessed at the SQL command level, using `DECLARE CURSOR` and `FETCH`. Once a portal exists, it can be executed using an Execute message. The Execute message specifies the portal name (empty string denotes the unnamed portal) and a maximum result-row count (zero meaning “fetch all rows”). The result-row count is only meaningful for portals containing commands that return row sets; in other cases the command is always executed to completion, and the row count is ignored. The possible responses to Execute are the same as those described above for queries issued via simple query protocol, except that Execute doesn't cause ReadyForQuery or RowDescription to be issued. If Execute terminates before completing the execution of a portal (due to reaching a nonzero result-row count), it will send a PortalSuspended message; the appearance of this message tells the frontend that another Execute should be issued against the same portal to complete the operation. The CommandComplete message indicating completion of the source SQL command is not sent until the portal's execution is completed. Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages: CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended. At completion of each series of extended-query messages, the frontend should issue a Sync message. This parameterless message causes the backend to close the current transaction if it's not inside a `BEGIN`/`COMMIT` transaction block (“close” meaning to commit if no error, or roll back if error). Then a ReadyForQuery response is issued. The purpose of Sync is to provide a resynchronization point for error recovery. When an error is detected while processing any extended-query message, the backend issues ErrorResponse, then reads and discards messages until a Sync is reached, then issues ReadyForQuery and returns to normal message processing. (But note that no skipping occurs if an error is detected _while_ processing Sync — this ensures that there is one and only one ReadyForQuery sent for each Sync.) ### Note Sync does not cause a transaction block opened with `BEGIN` to be closed. It is possible to detect this situation since the ReadyForQuery message includes transaction status information. In addition to these fundamental, required operations, there are several optional operations that can be used with extended-query protocol. The Describe message (portal variant) specifies the name of an existing portal (or an empty string for the unnamed portal). The response is a RowDescription message describing the rows that will be returned by executing the portal; or a NoData message if the portal does not contain a query that will return rows; or ErrorResponse if there is no such portal. The Describe message (statement variant) specifies the name of an existing prepared statement (or an empty string for the unnamed prepared statement). The response is a ParameterDescription message describing the parameters needed by the statement, followed by a RowDescription message describing the rows that will be returned when the statement is eventually executed (or a NoData message if the statement will not return rows). ErrorResponse is issued if there is no such prepared statement. Note that since Bind has not yet been issued, the formats to be used for returned columns are not yet known to the backend; the format code fields in the RowDescription message will be zeroes in this case. ### Tip In most scenarios the frontend should issue one or the other variant of Describe before issuing Execute, to ensure that it knows how to interpret the results it will get back. The Close message closes an existing prepared statement or portal and releases resources. It is not an error to issue Close against a nonexistent statement or portal name. The response is normally CloseComplete, but could be ErrorResponse if some difficulty is encountered while releasing resources. Note that closing a prepared statement implicitly closes any open portals that were constructed from that statement. The Flush message does not cause any specific output to be generated, but forces the backend to deliver any data pending in its output buffers. A Flush must be sent after any extended-query command except Sync, if the frontend wishes to examine the results of that command before issuing more commands. Without Flush, messages returned by the backend will be combined into the minimum possible number of packets to minimize network overhead. ### Note The simple Query message is approximately equivalent to the series Parse, Bind, portal Describe, Execute, Close, Sync, using the unnamed prepared statement and portal objects and no parameters. One difference is that it will accept multiple SQL statements in the query string, automatically performing the bind/describe/execute sequence for each one in succession. Another difference is that it will not return ParseComplete, BindComplete, CloseComplete, or NoData messages. ### 53.2.4. Pipelining Use of the extended query protocol allows _pipelining_, which means sending a series of queries without waiting for earlier ones to complete. This reduces the number of network round trips needed to complete a given series of operations. However, the user must carefully consider the required behavior if one of the steps fails, since later queries will already be in flight to the server. One way to deal with that is to make the whole query series be a single transaction, that is wrap it in `BEGIN` ... `COMMIT`. However, this does not help if one wishes for some of the commands to commit independently of others. The extended query protocol provides another way to manage this concern, which is to omit sending Sync messages between steps that are dependent. Since, after an error, the backend will skip command messages until it finds Sync, this allows later commands in a pipeline to be skipped automatically when an earlier one fails, without the client having to manage that explicitly with `BEGIN` and `COMMIT`. Independently-committable segments of the pipeline can be separated by Sync messages. If the client has not issued an explicit `BEGIN`, then each Sync ordinarily causes an implicit `COMMIT` if the preceding step(s) succeeded, or an implicit `ROLLBACK` if they failed. However, there are a few DDL commands (such as `CREATE DATABASE`) that cannot be executed inside a transaction block. If one of these is executed in a pipeline, it will fail unless it is the first command in the pipeline. Furthermore, upon success it will force an immediate commit to preserve database consistency. Thus a Sync immediately following one of these commands has no effect except to respond with ReadyForQuery. When using this method, completion of the pipeline must be determined by counting ReadyForQuery messages and waiting for that to reach the number of Syncs sent. Counting command completion responses is unreliable, since some of the commands may be skipped and thus not produce a completion message. ### 53.2.5. Function Call The Function Call sub-protocol allows the client to request a direct call of any function that exists in the database's `pg_proc` system catalog. The client must have execute permission for the function. ### Note The Function Call sub-protocol is a legacy feature that is probably best avoided in new code. Similar results can be accomplished by setting up a prepared statement that does `SELECT function($1, ...)`. The Function Call cycle can then be replaced with Bind/Execute. A Function Call cycle is initiated by the frontend sending a FunctionCall message to the backend. The backend then sends one or more response messages depending on the results of the function call, and finally a ReadyForQuery response message. ReadyForQuery informs the frontend that it can safely send a new query or function call. The possible response messages from the backend are: ErrorResponse An error has occurred. FunctionCallResponse The function call was completed and returned the result given in the message. (Note that the Function Call protocol can only handle a single scalar result, not a row type or set of results.) ReadyForQuery Processing of the function call is complete. ReadyForQuery will always be sent, whether processing terminates successfully or with an error. NoticeResponse A warning message has been issued in relation to the function call. Notices are in addition to other responses, i.e., the backend will continue processing the command. ### 53.2.6. COPY Operations The `COPY` command allows high-speed bulk data transfer to or from the server. Copy-in and copy-out operations each switch the connection into a distinct sub-protocol, which lasts until the operation is completed. Copy-in mode (data transfer to the server) is initiated when the backend executes a `COPY FROM STDIN` SQL statement. The backend sends a CopyInResponse message to the frontend. The frontend should then send zero or more CopyData messages, forming a stream of input data. (The message boundaries are not required to have anything to do with row boundaries, although that is often a reasonable choice.) The frontend can terminate the copy-in mode by sending either a CopyDone message (allowing successful termination) or a CopyFail message (which will cause the `COPY` SQL statement to fail with an error). The backend then reverts to the command-processing mode it was in before the `COPY` started, which will be either simple or extended query protocol. It will next send either CommandComplete (if successful) or ErrorResponse (if not). In the event of a backend-detected error during copy-in mode (including receipt of a CopyFail message), the backend will issue an ErrorResponse message. If the `COPY` command was issued via an extended-query message, the backend will now discard frontend messages until a Sync message is received, then it will issue ReadyForQuery and return to normal processing. If the `COPY` command was issued in a simple Query message, the rest of that message is discarded and ReadyForQuery is issued. In either case, any subsequent CopyData, CopyDone, or CopyFail messages issued by the frontend will simply be dropped. The backend will ignore Flush and Sync messages received during copy-in mode. Receipt of any other non-copy message type constitutes an error that will abort the copy-in state as described above. (The exception for Flush and Sync is for the convenience of client libraries that always send Flush or Sync after an Execute message, without checking whether the command to be executed is a `COPY FROM STDIN`.) Copy-out mode (data transfer from the server) is initiated when the backend executes a `COPY TO STDOUT` SQL statement. The backend sends a CopyOutResponse message to the frontend, followed by zero or more CopyData messages (always one per row), followed by CopyDone. The backend then reverts to the command-processing mode it was in before the `COPY` started, and sends CommandComplete. The frontend cannot abort the transfer (except by closing the connection or issuing a Cancel request), but it can discard unwanted CopyData and CopyDone messages. In the event of a backend-detected error during copy-out mode, the backend will issue an ErrorResponse message and revert to normal processing. The frontend should treat receipt of ErrorResponse as terminating the copy-out mode. It is possible for NoticeResponse and ParameterStatus messages to be interspersed between CopyData messages; frontends must handle these cases, and should be prepared for other asynchronous message types as well (see [Section 53.2.7](https://www.postgresql.org/docs/14/protocol-flow.html#PROTOCOL-ASYNC "53.2.7. Asynchronous Operations") ). Otherwise, any message type other than CopyData or CopyDone may be treated as terminating copy-out mode. There is another Copy-related mode called copy-both, which allows high-speed bulk data transfer to _and_ from the server. Copy-both mode is initiated when a backend in walsender mode executes a `START_REPLICATION` statement. The backend sends a CopyBothResponse message to the frontend. Both the backend and the frontend may then send CopyData messages until either end sends a CopyDone message. After the client sends a CopyDone message, the connection goes from copy-both mode to copy-out mode, and the client may not send any more CopyData messages. Similarly, when the server sends a CopyDone message, the connection goes into copy-in mode, and the server may not send any more CopyData messages. After both sides have sent a CopyDone message, the copy mode is terminated, and the backend reverts to the command-processing mode. In the event of a backend-detected error during copy-both mode, the backend will issue an ErrorResponse message, discard frontend messages until a Sync message is received, and then issue ReadyForQuery and return to normal processing. The frontend should treat receipt of ErrorResponse as terminating the copy in both directions; no CopyDone should be sent in this case. See [Section 53.4](https://www.postgresql.org/docs/14/protocol-replication.html "53.4. Streaming Replication Protocol") for more information on the subprotocol transmitted over copy-both mode. The CopyInResponse, CopyOutResponse and CopyBothResponse messages include fields that inform the frontend of the number of columns per row and the format codes being used for each column. (As of the present implementation, all columns in a given `COPY` operation will use the same format, but the message design does not assume this.) ### 53.2.7. Asynchronous Operations There are several cases in which the backend will send messages that are not specifically prompted by the frontend's command stream. Frontends must be prepared to deal with these messages at any time, even when not engaged in a query. At minimum, one should check for these cases before beginning to read a query response. It is possible for NoticeResponse messages to be generated due to outside activity; for example, if the database administrator commands a “fast” database shutdown, the backend will send a NoticeResponse indicating this fact before closing the connection. Accordingly, frontends should always be prepared to accept and display NoticeResponse messages, even when the connection is nominally idle. ParameterStatus messages will be generated whenever the active value changes for any of the parameters the backend believes the frontend should know about. Most commonly this occurs in response to a `SET` SQL command executed by the frontend, and this case is effectively synchronous — but it is also possible for parameter status changes to occur because the administrator changed a configuration file and then sent the SIGHUP signal to the server. Also, if a `SET` command is rolled back, an appropriate ParameterStatus message will be generated to report the current effective value. At present there is a hard-wired set of parameters for which ParameterStatus will be generated: they are `server_version`, `server_encoding`, `client_encoding`, `application_name`, `default_transaction_read_only`, `in_hot_standby`, `is_superuser`, `session_authorization`, `DateStyle`, `IntervalStyle`, `TimeZone`, `integer_datetimes`, and `standard_conforming_strings`. (`server_encoding`, `TimeZone`, and `integer_datetimes` were not reported by releases before 8.0; `standard_conforming_strings` was not reported by releases before 8.1; `IntervalStyle` was not reported by releases before 8.4; `application_name` was not reported by releases before 9.0; `default_transaction_read_only` and `in_hot_standby` were not reported by releases before 14.) Note that `server_version`, `server_encoding` and `integer_datetimes` are pseudo-parameters that cannot change after startup. This set might change in the future, or even become configurable. Accordingly, a frontend should simply ignore ParameterStatus for parameters that it does not understand or care about. If a frontend issues a `LISTEN` command, then the backend will send a NotificationResponse message (not to be confused with NoticeResponse!) whenever a `NOTIFY` command is executed for the same channel name. ### Note At present, NotificationResponse can only be sent outside a transaction, and thus it will not occur in the middle of a command-response series, though it might occur just before ReadyForQuery. It is unwise to design frontend logic that assumes that, however. Good practice is to be able to accept NotificationResponse at any point in the protocol. ### 53.2.8. Canceling Requests in Progress During the processing of a query, the frontend might request cancellation of the query. The cancel request is not sent directly on the open connection to the backend for reasons of implementation efficiency: we don't want to have the backend constantly checking for new input from the frontend during query processing. Cancel requests should be relatively infrequent, so we make them slightly cumbersome in order to avoid a penalty in the normal case. To issue a cancel request, the frontend opens a new connection to the server and sends a CancelRequest message, rather than the StartupMessage message that would ordinarily be sent across a new connection. The server will process this request and then close the connection. For security reasons, no direct reply is made to the cancel request message. A CancelRequest message will be ignored unless it contains the same key data (PID and secret key) passed to the frontend during connection start-up. If the request matches the PID and secret key for a currently executing backend, the processing of the current query is aborted. (In the existing implementation, this is done by sending a special signal to the backend process that is processing the query.) The cancellation signal might or might not have any effect — for example, if it arrives after the backend has finished processing the query, then it will have no effect. If the cancellation is effective, it results in the current command being terminated early with an error message. The upshot of all this is that for reasons of both security and efficiency, the frontend has no direct way to tell whether a cancel request has succeeded. It must continue to wait for the backend to respond to the query. Issuing a cancel simply improves the odds that the current query will finish soon, and improves the odds that it will fail with an error message instead of succeeding. Since the cancel request is sent across a new connection to the server and not across the regular frontend/backend communication link, it is possible for the cancel request to be issued by any process, not just the frontend whose query is to be canceled. This might provide additional flexibility when building multiple-process applications. It also introduces a security risk, in that unauthorized persons might try to cancel queries. The security risk is addressed by requiring a dynamically generated secret key to be supplied in cancel requests. ### 53.2.9. Termination The normal, graceful termination procedure is that the frontend sends a Terminate message and immediately closes the connection. On receipt of this message, the backend closes the connection and terminates. In rare cases (such as an administrator-commanded database shutdown) the backend might disconnect without any frontend request to do so. In such cases the backend will attempt to send an error or notice message giving the reason for the disconnection before it closes the connection. Other termination scenarios arise from various failure cases, such as core dump at one end or the other, loss of the communications link, loss of message-boundary synchronization, etc. If either frontend or backend sees an unexpected closure of the connection, it should clean up and terminate. The frontend has the option of launching a new backend by recontacting the server if it doesn't want to terminate itself. Closing the connection is also advisable if an unrecognizable message type is received, since this probably indicates loss of message-boundary sync. For either normal or abnormal termination, any open transaction is rolled back, not committed. One should note however that if a frontend disconnects while a non-`SELECT` query is being processed, the backend will probably finish the query before noticing the disconnection. If the query is outside any transaction block (`BEGIN` ... `COMMIT` sequence) then its results might be committed before the disconnection is recognized. ### 53.2.10. SSL Session Encryption If PostgreSQL was built with SSL support, frontend/backend communications can be encrypted using SSL. This provides communication security in environments where attackers might be able to capture the session traffic. For more information on encrypting PostgreSQL sessions with SSL, see [Section 19.9](https://www.postgresql.org/docs/14/ssl-tcp.html "19.9. Secure TCP/IP Connections with SSL") . To initiate an SSL\-encrypted connection, the frontend initially sends an SSLRequest message rather than a StartupMessage. The server then responds with a single byte containing `S` or `N`, indicating that it is willing or unwilling to perform SSL, respectively. The frontend might close the connection at this point if it is dissatisfied with the response. To continue after `S`, perform an SSL startup handshake (not described here, part of the SSL specification) with the server. If this is successful, continue with sending the usual StartupMessage. In this case the StartupMessage and all subsequent data will be SSL\-encrypted. To continue after `N`, send the usual StartupMessage and proceed without encryption. (Alternatively, it is permissible to issue a GSSENCRequest message after an `N` response to try to use GSSAPI encryption instead of SSL.) The frontend should also be prepared to handle an ErrorMessage response to SSLRequest from the server. The frontend should not display this error message to the user/application, since the server has not been authenticated ([CVE-2024-10977](https://www.postgresql.org/support/security/CVE-2024-10977/) ). In this case the connection must be closed, but the frontend might choose to open a fresh connection and proceed without requesting SSL. When SSL encryption can be performed, the server is expected to send only the single `S` byte and then wait for the frontend to initiate an SSL handshake. If additional bytes are available to read at this point, it likely means that a man-in-the-middle is attempting to perform a buffer-stuffing attack ([CVE-2021-23222](https://www.postgresql.org/support/security/CVE-2021-23222/) ). Frontends should be coded either to read exactly one byte from the socket before turning the socket over to their SSL library, or to treat it as a protocol violation if they find they have read additional bytes. An initial SSLRequest can also be used in a connection that is being opened to send a CancelRequest message. While the protocol itself does not provide a way for the server to force SSL encryption, the administrator can configure the server to reject unencrypted sessions as a byproduct of authentication checking. ### 53.2.11. GSSAPI Session Encryption If PostgreSQL was built with GSSAPI support, frontend/backend communications can be encrypted using GSSAPI. This provides communication security in environments where attackers might be able to capture the session traffic. For more information on encrypting PostgreSQL sessions with GSSAPI, see [Section 19.10](https://www.postgresql.org/docs/14/gssapi-enc.html "19.10. Secure TCP/IP Connections with GSSAPI Encryption") . To initiate a GSSAPI\-encrypted connection, the frontend initially sends a GSSENCRequest message rather than a StartupMessage. The server then responds with a single byte containing `G` or `N`, indicating that it is willing or unwilling to perform GSSAPI encryption, respectively. The frontend might close the connection at this point if it is dissatisfied with the response. To continue after `G`, using the GSSAPI C bindings as discussed in [RFC 2744](https://datatracker.ietf.org/doc/html/rfc2744) or equivalent, perform a GSSAPI initialization by calling `gss_init_sec_context()` in a loop and sending the result to the server, starting with an empty input and then with each result from the server, until it returns no output. When sending the results of `gss_init_sec_context()` to the server, prepend the length of the message as a four byte integer in network byte order. To continue after `N`, send the usual StartupMessage and proceed without encryption. (Alternatively, it is permissible to issue an SSLRequest message after an `N` response to try to use SSL encryption instead of GSSAPI.) The frontend should also be prepared to handle an ErrorMessage response to GSSENCRequest from the server. The frontend should not display this error message to the user/application, since the server has not been authenticated ([CVE-2024-10977](https://www.postgresql.org/support/security/CVE-2024-10977/) ). In this case the connection must be closed, but the frontend might choose to open a fresh connection and proceed without requesting GSSAPI encryption. When GSSAPI encryption can be performed, the server is expected to send only the single `G` byte and then wait for the frontend to initiate a GSSAPI handshake. If additional bytes are available to read at this point, it likely means that a man-in-the-middle is attempting to perform a buffer-stuffing attack ([CVE-2021-23222](https://www.postgresql.org/support/security/CVE-2021-23222/) ). Frontends should be coded either to read exactly one byte from the socket before turning the socket over to their GSSAPI library, or to treat it as a protocol violation if they find they have read additional bytes. An initial GSSENCRequest can also be used in a connection that is being opened to send a CancelRequest message. Once GSSAPI encryption has been successfully established, use `gss_wrap()` to encrypt the usual StartupMessage and all subsequent data, prepending the length of the result from `gss_wrap()` as a four byte integer in network byte order to the actual encrypted payload. Note that the server will only accept encrypted packets from the client which are less than 16kB; `gss_wrap_size_limit()` should be used by the client to determine the size of the unencrypted message which will fit within this limit and larger messages should be broken up into multiple `gss_wrap()` calls. Typical segments are 8kB of unencrypted data, resulting in encrypted packets of slightly larger than 8kB but well within the 16kB maximum. The server can be expected to not send encrypted packets of larger than 16kB to the client. While the protocol itself does not provide a way for the server to force GSSAPI encryption, the administrator can configure the server to reject unencrypted sessions as a byproduct of authentication checking. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/protocol-overview.html "53.1. Overview") | [Up](https://www.postgresql.org/docs/14/protocol.html "Chapter 53. Frontend/Backend Protocol") | [Next](https://www.postgresql.org/docs/14/sasl-authentication.html "53.3. SASL Authentication") | | 53.1. Overview | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | 53.3. SASL Authentication | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/14/protocol-flow.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 11: Chapter 55. Native Language Support November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 11](https://www.postgresql.org/docs/11/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/nls.html "PostgreSQL 18 - Chapter 55. Native Language Support") ([18](https://www.postgresql.org/docs/18/nls.html "PostgreSQL 18 - Chapter 55. Native Language Support") ) / [17](https://www.postgresql.org/docs/17/nls.html "PostgreSQL 17 - Chapter 55. Native Language Support") / [16](https://www.postgresql.org/docs/16/nls.html "PostgreSQL 16 - Chapter 55. Native Language Support") / [15](https://www.postgresql.org/docs/15/nls.html "PostgreSQL 15 - Chapter 55. Native Language Support") / [14](https://www.postgresql.org/docs/14/nls.html "PostgreSQL 14 - Chapter 55. Native Language Support") Development Versions: [devel](https://www.postgresql.org/docs/devel/nls.html "PostgreSQL devel - Chapter 55. Native Language Support") Unsupported versions: [13](https://www.postgresql.org/docs/13/nls.html "PostgreSQL 13 - Chapter 55. Native Language Support") / [12](https://www.postgresql.org/docs/12/nls.html "PostgreSQL 12 - Chapter 55. Native Language Support") / [11](https://www.postgresql.org/docs/11/nls.html "PostgreSQL 11 - Chapter 55. Native Language Support") / [10](https://www.postgresql.org/docs/10/nls.html "PostgreSQL 10 - Chapter 55. Native Language Support") / [9.6](https://www.postgresql.org/docs/9.6/nls.html "PostgreSQL 9.6 - Chapter 55. Native Language Support") / [9.5](https://www.postgresql.org/docs/9.5/nls.html "PostgreSQL 9.5 - Chapter 55. Native Language Support") / [9.4](https://www.postgresql.org/docs/9.4/nls.html "PostgreSQL 9.4 - Chapter 55. Native Language Support") / [9.3](https://www.postgresql.org/docs/9.3/nls.html "PostgreSQL 9.3 - Chapter 55. Native Language Support") / [9.2](https://www.postgresql.org/docs/9.2/nls.html "PostgreSQL 9.2 - Chapter 55. Native Language Support") / [9.1](https://www.postgresql.org/docs/9.1/nls.html "PostgreSQL 9.1 - Chapter 55. Native Language Support") / [9.0](https://www.postgresql.org/docs/9.0/nls.html "PostgreSQL 9.0 - Chapter 55. Native Language Support") / [8.4](https://www.postgresql.org/docs/8.4/nls.html "PostgreSQL 8.4 - Chapter 55. Native Language Support") / [8.3](https://www.postgresql.org/docs/8.3/nls.html "PostgreSQL 8.3 - Chapter 55. Native Language Support") / [8.2](https://www.postgresql.org/docs/8.2/nls.html "PostgreSQL 8.2 - Chapter 55. Native Language Support") / [8.1](https://www.postgresql.org/docs/8.1/nls.html "PostgreSQL 8.1 - Chapter 55. Native Language Support") / [8.0](https://www.postgresql.org/docs/8.0/nls.html "PostgreSQL 8.0 - Chapter 55. Native Language Support") / [7.4](https://www.postgresql.org/docs/7.4/nls.html "PostgreSQL 7.4 - Chapter 55. Native Language Support") / [7.3](https://www.postgresql.org/docs/7.3/nls.html "PostgreSQL 7.3 - Chapter 55. Native Language Support") / [7.2](https://www.postgresql.org/docs/7.2/nls.html "PostgreSQL 7.2 - Chapter 55. Native Language Support") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/nls.html "PostgreSQL - Chapter 55. Native Language Support") version, or one of the other supported versions listed above instead. | Chapter 55. Native Language Support | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/source-conventions.html "54.4. Miscellaneous Coding Conventions") | [Up](https://www.postgresql.org/docs/11/internals.html "Part VII. Internals") | Part VII. Internals | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | [Next](https://www.postgresql.org/docs/11/nls-translator.html "55.1. For the Translator") | * * * Chapter 55. Native Language Support ----------------------------------- **Table of Contents** [55.1. For the Translator](https://www.postgresql.org/docs/11/nls-translator.html) [55.1.1. Requirements](https://www.postgresql.org/docs/11/nls-translator.html#id-1.10.7.2.3) [55.1.2. Concepts](https://www.postgresql.org/docs/11/nls-translator.html#id-1.10.7.2.4) [55.1.3. Creating and Maintaining Message Catalogs](https://www.postgresql.org/docs/11/nls-translator.html#id-1.10.7.2.5) [55.1.4. Editing the PO Files](https://www.postgresql.org/docs/11/nls-translator.html#id-1.10.7.2.6) [55.2. For the Programmer](https://www.postgresql.org/docs/11/nls-programmer.html) [55.2.1. Mechanics](https://www.postgresql.org/docs/11/nls-programmer.html#NLS-MECHANICS) [55.2.2. Message-writing Guidelines](https://www.postgresql.org/docs/11/nls-programmer.html#NLS-GUIDELINES) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/source-conventions.html "54.4. Miscellaneous Coding Conventions") | [Up](https://www.postgresql.org/docs/11/internals.html "Part VII. Internals") | [Next](https://www.postgresql.org/docs/11/nls-translator.html "55.1. For the Translator") | | 54.4. Miscellaneous Coding Conventions | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | 55.1. For the Translator | --- # PostgreSQL: Documentation: 14: 36.8. Error Handling November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 14](https://www.postgresql.org/docs/14/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/ecpg-errors.html "PostgreSQL 18 - 36.8. Error Handling") ([18](https://www.postgresql.org/docs/18/ecpg-errors.html "PostgreSQL 18 - 36.8. Error Handling") ) / [17](https://www.postgresql.org/docs/17/ecpg-errors.html "PostgreSQL 17 - 36.8. Error Handling") / [16](https://www.postgresql.org/docs/16/ecpg-errors.html "PostgreSQL 16 - 36.8. Error Handling") / [15](https://www.postgresql.org/docs/15/ecpg-errors.html "PostgreSQL 15 - 36.8. Error Handling") / [14](https://www.postgresql.org/docs/14/ecpg-errors.html "PostgreSQL 14 - 36.8. Error Handling") Development Versions: [devel](https://www.postgresql.org/docs/devel/ecpg-errors.html "PostgreSQL devel - 36.8. Error Handling") Unsupported versions: [13](https://www.postgresql.org/docs/13/ecpg-errors.html "PostgreSQL 13 - 36.8. Error Handling") / [12](https://www.postgresql.org/docs/12/ecpg-errors.html "PostgreSQL 12 - 36.8. Error Handling") / [11](https://www.postgresql.org/docs/11/ecpg-errors.html "PostgreSQL 11 - 36.8. Error Handling") / [10](https://www.postgresql.org/docs/10/ecpg-errors.html "PostgreSQL 10 - 36.8. Error Handling") / [9.6](https://www.postgresql.org/docs/9.6/ecpg-errors.html "PostgreSQL 9.6 - 36.8. Error Handling") / [9.5](https://www.postgresql.org/docs/9.5/ecpg-errors.html "PostgreSQL 9.5 - 36.8. Error Handling") / [9.4](https://www.postgresql.org/docs/9.4/ecpg-errors.html "PostgreSQL 9.4 - 36.8. Error Handling") / [9.3](https://www.postgresql.org/docs/9.3/ecpg-errors.html "PostgreSQL 9.3 - 36.8. Error Handling") / [9.2](https://www.postgresql.org/docs/9.2/ecpg-errors.html "PostgreSQL 9.2 - 36.8. Error Handling") / [9.1](https://www.postgresql.org/docs/9.1/ecpg-errors.html "PostgreSQL 9.1 - 36.8. Error Handling") / [9.0](https://www.postgresql.org/docs/9.0/ecpg-errors.html "PostgreSQL 9.0 - 36.8. Error Handling") / [8.4](https://www.postgresql.org/docs/8.4/ecpg-errors.html "PostgreSQL 8.4 - 36.8. Error Handling") / [8.3](https://www.postgresql.org/docs/8.3/ecpg-errors.html "PostgreSQL 8.3 - 36.8. Error Handling") / [8.2](https://www.postgresql.org/docs/8.2/ecpg-errors.html "PostgreSQL 8.2 - 36.8. Error Handling") / [8.1](https://www.postgresql.org/docs/8.1/ecpg-errors.html "PostgreSQL 8.1 - 36.8. Error Handling") / [8.0](https://www.postgresql.org/docs/8.0/ecpg-errors.html "PostgreSQL 8.0 - 36.8. Error Handling") / [7.4](https://www.postgresql.org/docs/7.4/ecpg-errors.html "PostgreSQL 7.4 - 36.8. Error Handling") / [7.3](https://www.postgresql.org/docs/7.3/ecpg-errors.html "PostgreSQL 7.3 - 36.8. Error Handling") | 36.8. Error Handling | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/ecpg-descriptors.html "36.7. Using Descriptor Areas") | [Up](https://www.postgresql.org/docs/14/ecpg.html "Chapter 36. ECPG — Embedded SQL in C") | Chapter 36. ECPG — Embedded SQL in C | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | [Next](https://www.postgresql.org/docs/14/ecpg-preproc.html "36.9. Preprocessor Directives") | * * * 36.8. Error Handling -------------------- [36.8.1. Setting Callbacks](https://www.postgresql.org/docs/14/ecpg-errors.html#ECPG-WHENEVER) [36.8.2. sqlca](https://www.postgresql.org/docs/14/ecpg-errors.html#ECPG-SQLCA) [36.8.3. `SQLSTATE` vs. `SQLCODE`](https://www.postgresql.org/docs/14/ecpg-errors.html#ECPG-SQLSTATE-SQLCODE) This section describes how you can handle exceptional conditions and warnings in an embedded SQL program. There are two nonexclusive facilities for this. * Callbacks can be configured to handle warning and error conditions using the `WHENEVER` command. * Detailed information about the error or warning can be obtained from the `sqlca` variable. ### 36.8.1. Setting Callbacks One simple method to catch errors and warnings is to set a specific action to be executed whenever a particular condition occurs. In general: EXEC SQL WHENEVER _`condition`_ _`action`_; _`condition`_ can be one of the following: `SQLERROR` The specified action is called whenever an error occurs during the execution of an SQL statement. `SQLWARNING` The specified action is called whenever a warning occurs during the execution of an SQL statement. `NOT FOUND` The specified action is called whenever an SQL statement retrieves or affects zero rows. (This condition is not an error, but you might be interested in handling it specially.) _`action`_ can be one of the following: `CONTINUE` This effectively means that the condition is ignored. This is the default. ``GOTO _`label`_`` ``GO TO _`label`_`` Jump to the specified label (using a C `goto` statement). `SQLPRINT` Print a message to standard error. This is useful for simple programs or during prototyping. The details of the message cannot be configured. `STOP` Call `exit(1)`, which will terminate the program. `DO BREAK` Execute the C statement `break`. This should only be used in loops or `switch` statements. `DO CONTINUE` Execute the C statement `continue`. This should only be used in loops statements. if executed, will cause the flow of control to return to the top of the loop. ``CALL _`name`_ (_`args`_)`` ``DO _`name`_ (_`args`_)`` Call the specified C functions with the specified arguments. (This use is different from the meaning of `CALL` and `DO` in the normal PostgreSQL grammar.) The SQL standard only provides for the actions `CONTINUE` and `GOTO` (and `GO TO`). Here is an example that you might want to use in a simple program. It prints a simple message when a warning occurs and aborts the program when an error happens: EXEC SQL WHENEVER SQLWARNING SQLPRINT; EXEC SQL WHENEVER SQLERROR STOP; The statement `EXEC SQL WHENEVER` is a directive of the SQL preprocessor, not a C statement. The error or warning actions that it sets apply to all embedded SQL statements that appear below the point where the handler is set, unless a different action was set for the same condition between the first `EXEC SQL WHENEVER` and the SQL statement causing the condition, regardless of the flow of control in the C program. So neither of the two following C program excerpts will have the desired effect: /\* \* WRONG \*/ int main(int argc, char \*argv\[\]) { ... if (verbose) { EXEC SQL WHENEVER SQLWARNING SQLPRINT; } ... EXEC SQL SELECT ...; ... } /\* \* WRONG \*/ int main(int argc, char \*argv\[\]) { ... set\_error\_handler(); ... EXEC SQL SELECT ...; ... } static void set\_error\_handler(void) { EXEC SQL WHENEVER SQLERROR STOP; } ### 36.8.2. sqlca For more powerful error handling, the embedded SQL interface provides a global variable with the name `sqlca` (SQL communication area) that has the following structure: struct { char sqlcaid\[8\]; long sqlabc; long sqlcode; struct { int sqlerrml; char sqlerrmc\[SQLERRMC\_LEN\]; } sqlerrm; char sqlerrp\[8\]; long sqlerrd\[6\]; char sqlwarn\[8\]; char sqlstate\[5\]; } sqlca; (In a multithreaded program, every thread automatically gets its own copy of `sqlca`. This works similarly to the handling of the standard C global variable `errno`.) `sqlca` covers both warnings and errors. If multiple warnings or errors occur during the execution of a statement, then `sqlca` will only contain information about the last one. If no error occurred in the last SQL statement, `sqlca.sqlcode` will be 0 and `sqlca.sqlstate` will be `"00000"`. If a warning or error occurred, then `sqlca.sqlcode` will be negative and `sqlca.sqlstate` will be different from `"00000"`. A positive `sqlca.sqlcode` indicates a harmless condition, such as that the last query returned zero rows. `sqlcode` and `sqlstate` are two different error code schemes; details appear below. If the last SQL statement was successful, then `sqlca.sqlerrd[1]` contains the OID of the processed row, if applicable, and `sqlca.sqlerrd[2]` contains the number of processed or returned rows, if applicable to the command. In case of an error or warning, `sqlca.sqlerrm.sqlerrmc` will contain a string that describes the error. The field `sqlca.sqlerrm.sqlerrml` contains the length of the error message that is stored in `sqlca.sqlerrm.sqlerrmc` (the result of `strlen()`, not really interesting for a C programmer). Note that some messages are too long to fit in the fixed-size `sqlerrmc` array; they will be truncated. In case of a warning, `sqlca.sqlwarn[2]` is set to `W`. (In all other cases, it is set to something different from `W`.) If `sqlca.sqlwarn[1]` is set to `W`, then a value was truncated when it was stored in a host variable. `sqlca.sqlwarn[0]` is set to `W` if any of the other elements are set to indicate a warning. The fields `sqlcaid`, `sqlabc`, `sqlerrp`, and the remaining elements of `sqlerrd` and `sqlwarn` currently contain no useful information. The structure `sqlca` is not defined in the SQL standard, but is implemented in several other SQL database systems. The definitions are similar at the core, but if you want to write portable applications, then you should investigate the different implementations carefully. Here is one example that combines the use of `WHENEVER` and `sqlca`, printing out the contents of `sqlca` when an error occurs. This is perhaps useful for debugging or prototyping applications, before installing a more “user-friendly” error handler. EXEC SQL WHENEVER SQLERROR CALL print\_sqlca(); void print\_sqlca() { fprintf(stderr, "==== sqlca ====\\n"); fprintf(stderr, "sqlcode: %ld\\n", sqlca.sqlcode); fprintf(stderr, "sqlerrm.sqlerrml: %d\\n", sqlca.sqlerrm.sqlerrml); fprintf(stderr, "sqlerrm.sqlerrmc: %s\\n", sqlca.sqlerrm.sqlerrmc); fprintf(stderr, "sqlerrd: %ld %ld %ld %ld %ld %ld\\n", sqlca.sqlerrd\[0\],sqlca.sqlerrd\[1\],sqlca.sqlerrd\[2\], sqlca.sqlerrd\[3\],sqlca.sqlerrd\[4\],sqlca.sqlerrd\[5\]); fprintf(stderr, "sqlwarn: %d %d %d %d %d %d %d %d\\n", sqlca.sqlwarn\[0\], sqlca.sqlwarn\[1\], sqlca.sqlwarn\[2\], sqlca.sqlwarn\[3\], sqlca.sqlwarn\[4\], sqlca.sqlwarn\[5\], sqlca.sqlwarn\[6\], sqlca.sqlwarn\[7\]); fprintf(stderr, "sqlstate: %5s\\n", sqlca.sqlstate); fprintf(stderr, "===============\\n"); } The result could look as follows (here an error due to a misspelled table name): \==== sqlca ==== sqlcode: -400 sqlerrm.sqlerrml: 49 sqlerrm.sqlerrmc: relation "pg\_databasep" does not exist on line 38 sqlerrd: 0 0 0 0 0 0 sqlwarn: 0 0 0 0 0 0 0 0 sqlstate: 42P01 =============== ### 36.8.3. `SQLSTATE` vs. `SQLCODE` The fields `sqlca.sqlstate` and `sqlca.sqlcode` are two different schemes that provide error codes. Both are derived from the SQL standard, but `SQLCODE` has been marked deprecated in the SQL-92 edition of the standard and has been dropped in later editions. Therefore, new applications are strongly encouraged to use `SQLSTATE`. `SQLSTATE` is a five-character array. The five characters contain digits or upper-case letters that represent codes of various error and warning conditions. `SQLSTATE` has a hierarchical scheme: the first two characters indicate the general class of the condition, the last three characters indicate a subclass of the general condition. A successful state is indicated by the code `00000`. The `SQLSTATE` codes are for the most part defined in the SQL standard. The PostgreSQL server natively supports `SQLSTATE` error codes; therefore a high degree of consistency can be achieved by using this error code scheme throughout all applications. For further information see [Appendix A](https://www.postgresql.org/docs/14/errcodes-appendix.html "Appendix A. PostgreSQL Error Codes") . `SQLCODE`, the deprecated error code scheme, is a simple integer. A value of 0 indicates success, a positive value indicates success with additional information, a negative value indicates an error. The SQL standard only defines the positive value +100, which indicates that the last command returned or affected zero rows, and no specific negative values. Therefore, this scheme can only achieve poor portability and does not have a hierarchical code assignment. Historically, the embedded SQL processor for PostgreSQL has assigned some specific `SQLCODE` values for its use, which are listed below with their numeric value and their symbolic name. Remember that these are not portable to other SQL implementations. To simplify the porting of applications to the `SQLSTATE` scheme, the corresponding `SQLSTATE` is also listed. There is, however, no one-to-one or one-to-many mapping between the two schemes (indeed it is many-to-many), so you should consult the global `SQLSTATE` listing in [Appendix A](https://www.postgresql.org/docs/14/errcodes-appendix.html "Appendix A. PostgreSQL Error Codes") in each case. These are the assigned `SQLCODE` values: 0 (`ECPG_NO_ERROR`) Indicates no error. (SQLSTATE 00000) 100 (`ECPG_NOT_FOUND`) This is a harmless condition indicating that the last command retrieved or processed zero rows, or that you are at the end of the cursor. (SQLSTATE 02000) When processing a cursor in a loop, you could use this code as a way to detect when to abort the loop, like this: while (1) { EXEC SQL FETCH ... ; if (sqlca.sqlcode == ECPG\_NOT\_FOUND) break; } But `WHENEVER NOT FOUND DO BREAK` effectively does this internally, so there is usually no advantage in writing this out explicitly. \-12 (`ECPG_OUT_OF_MEMORY`) Indicates that your virtual memory is exhausted. The numeric value is defined as `-ENOMEM`. (SQLSTATE YE001) \-200 (`ECPG_UNSUPPORTED`) Indicates the preprocessor has generated something that the library does not know about. Perhaps you are running incompatible versions of the preprocessor and the library. (SQLSTATE YE002) \-201 (`ECPG_TOO_MANY_ARGUMENTS`) This means that the command specified more host variables than the command expected. (SQLSTATE 07001 or 07002) \-202 (`ECPG_TOO_FEW_ARGUMENTS`) This means that the command specified fewer host variables than the command expected. (SQLSTATE 07001 or 07002) \-203 (`ECPG_TOO_MANY_MATCHES`) This means a query has returned multiple rows but the statement was only prepared to store one result row (for example, because the specified variables are not arrays). (SQLSTATE 21000) \-204 (`ECPG_INT_FORMAT`) The host variable is of type `int` and the datum in the database is of a different type and contains a value that cannot be interpreted as an `int`. The library uses `strtol()` for this conversion. (SQLSTATE 42804) \-205 (`ECPG_UINT_FORMAT`) The host variable is of type `unsigned int` and the datum in the database is of a different type and contains a value that cannot be interpreted as an `unsigned int`. The library uses `strtoul()` for this conversion. (SQLSTATE 42804) \-206 (`ECPG_FLOAT_FORMAT`) The host variable is of type `float` and the datum in the database is of another type and contains a value that cannot be interpreted as a `float`. The library uses `strtod()` for this conversion. (SQLSTATE 42804) \-207 (`ECPG_NUMERIC_FORMAT`) The host variable is of type `numeric` and the datum in the database is of another type and contains a value that cannot be interpreted as a `numeric` value. (SQLSTATE 42804) \-208 (`ECPG_INTERVAL_FORMAT`) The host variable is of type `interval` and the datum in the database is of another type and contains a value that cannot be interpreted as an `interval` value. (SQLSTATE 42804) \-209 (`ECPG_DATE_FORMAT`) The host variable is of type `date` and the datum in the database is of another type and contains a value that cannot be interpreted as a `date` value. (SQLSTATE 42804) \-210 (`ECPG_TIMESTAMP_FORMAT`) The host variable is of type `timestamp` and the datum in the database is of another type and contains a value that cannot be interpreted as a `timestamp` value. (SQLSTATE 42804) \-211 (`ECPG_CONVERT_BOOL`) This means the host variable is of type `bool` and the datum in the database is neither `'t'` nor `'f'`. (SQLSTATE 42804) \-212 (`ECPG_EMPTY`) The statement sent to the PostgreSQL server was empty. (This cannot normally happen in an embedded SQL program, so it might point to an internal error.) (SQLSTATE YE002) \-213 (`ECPG_MISSING_INDICATOR`) A null value was returned and no null indicator variable was supplied. (SQLSTATE 22002) \-214 (`ECPG_NO_ARRAY`) An ordinary variable was used in a place that requires an array. (SQLSTATE 42804) \-215 (`ECPG_DATA_NOT_ARRAY`) The database returned an ordinary variable in a place that requires array value. (SQLSTATE 42804) \-216 (`ECPG_ARRAY_INSERT`) The value could not be inserted into the array. (SQLSTATE 42804) \-220 (`ECPG_NO_CONN`) The program tried to access a connection that does not exist. (SQLSTATE 08003) \-221 (`ECPG_NOT_CONN`) The program tried to access a connection that does exist but is not open. (This is an internal error.) (SQLSTATE YE002) \-230 (`ECPG_INVALID_STMT`) The statement you are trying to use has not been prepared. (SQLSTATE 26000) \-239 (`ECPG_INFORMIX_DUPLICATE_KEY`) Duplicate key error, violation of unique constraint (Informix compatibility mode). (SQLSTATE 23505) \-240 (`ECPG_UNKNOWN_DESCRIPTOR`) The descriptor specified was not found. The statement you are trying to use has not been prepared. (SQLSTATE 33000) \-241 (`ECPG_INVALID_DESCRIPTOR_INDEX`) The descriptor index specified was out of range. (SQLSTATE 07009) \-242 (`ECPG_UNKNOWN_DESCRIPTOR_ITEM`) An invalid descriptor item was requested. (This is an internal error.) (SQLSTATE YE002) \-243 (`ECPG_VAR_NOT_NUMERIC`) During the execution of a dynamic statement, the database returned a numeric value and the host variable was not numeric. (SQLSTATE 07006) \-244 (`ECPG_VAR_NOT_CHAR`) During the execution of a dynamic statement, the database returned a non-numeric value and the host variable was numeric. (SQLSTATE 07006) \-284 (`ECPG_INFORMIX_SUBSELECT_NOT_ONE`) A result of the subquery is not single row (Informix compatibility mode). (SQLSTATE 21000) \-400 (`ECPG_PGSQL`) Some error caused by the PostgreSQL server. The message contains the error message from the PostgreSQL server. \-401 (`ECPG_TRANS`) The PostgreSQL server signaled that we cannot start, commit, or rollback the transaction. (SQLSTATE 08007) \-402 (`ECPG_CONNECT`) The connection attempt to the database did not succeed. (SQLSTATE 08001) \-403 (`ECPG_DUPLICATE_KEY`) Duplicate key error, violation of unique constraint. (SQLSTATE 23505) \-404 (`ECPG_SUBSELECT_NOT_ONE`) A result for the subquery is not single row. (SQLSTATE 21000) \-602 (`ECPG_WARNING_UNKNOWN_PORTAL`) An invalid cursor name was specified. (SQLSTATE 34000) \-603 (`ECPG_WARNING_IN_TRANSACTION`) Transaction is in progress. (SQLSTATE 25001) \-604 (`ECPG_WARNING_NO_TRANSACTION`) There is no active (in-progress) transaction. (SQLSTATE 25P01) \-605 (`ECPG_WARNING_PORTAL_EXISTS`) An existing cursor name was specified. (SQLSTATE 42P03) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/14/ecpg-descriptors.html "36.7. Using Descriptor Areas") | [Up](https://www.postgresql.org/docs/14/ecpg.html "Chapter 36. ECPG — Embedded SQL in C") | [Next](https://www.postgresql.org/docs/14/ecpg-preproc.html "36.9. Preprocessor Directives") | | 36.7. Using Descriptor Areas | [Home](https://www.postgresql.org/docs/14/index.html "PostgreSQL 14.20 Documentation") | 36.9. Preprocessor Directives | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/14/ecpg-errors.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 11: ALTER EXTENSION November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 11](https://www.postgresql.org/docs/11/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alterextension.html "PostgreSQL 18 - ALTER EXTENSION") ([18](https://www.postgresql.org/docs/18/sql-alterextension.html "PostgreSQL 18 - ALTER EXTENSION") ) / [17](https://www.postgresql.org/docs/17/sql-alterextension.html "PostgreSQL 17 - ALTER EXTENSION") / [16](https://www.postgresql.org/docs/16/sql-alterextension.html "PostgreSQL 16 - ALTER EXTENSION") / [15](https://www.postgresql.org/docs/15/sql-alterextension.html "PostgreSQL 15 - ALTER EXTENSION") / [14](https://www.postgresql.org/docs/14/sql-alterextension.html "PostgreSQL 14 - ALTER EXTENSION") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alterextension.html "PostgreSQL devel - ALTER EXTENSION") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alterextension.html "PostgreSQL 13 - ALTER EXTENSION") / [12](https://www.postgresql.org/docs/12/sql-alterextension.html "PostgreSQL 12 - ALTER EXTENSION") / [11](https://www.postgresql.org/docs/11/sql-alterextension.html "PostgreSQL 11 - ALTER EXTENSION") / [10](https://www.postgresql.org/docs/10/sql-alterextension.html "PostgreSQL 10 - ALTER EXTENSION") / [9.6](https://www.postgresql.org/docs/9.6/sql-alterextension.html "PostgreSQL 9.6 - ALTER EXTENSION") / [9.5](https://www.postgresql.org/docs/9.5/sql-alterextension.html "PostgreSQL 9.5 - ALTER EXTENSION") / [9.4](https://www.postgresql.org/docs/9.4/sql-alterextension.html "PostgreSQL 9.4 - ALTER EXTENSION") / [9.3](https://www.postgresql.org/docs/9.3/sql-alterextension.html "PostgreSQL 9.3 - ALTER EXTENSION") / [9.2](https://www.postgresql.org/docs/9.2/sql-alterextension.html "PostgreSQL 9.2 - ALTER EXTENSION") / [9.1](https://www.postgresql.org/docs/9.1/sql-alterextension.html "PostgreSQL 9.1 - ALTER EXTENSION") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/sql-alterextension.html "PostgreSQL - ALTER EXTENSION") version, or one of the other supported versions listed above instead. | ALTER EXTENSION | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/sql-altereventtrigger.html "ALTER EVENT TRIGGER") | [Up](https://www.postgresql.org/docs/11/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | [Next](https://www.postgresql.org/docs/11/sql-alterforeigndatawrapper.html "ALTER FOREIGN DATA WRAPPER") | * * * ALTER EXTENSION --------------- ALTER EXTENSION — change the definition of an extension Synopsis -------- ALTER EXTENSION _`name`_ UPDATE \[ TO _`new_version`_ \] ALTER EXTENSION _`name`_ SET SCHEMA _`new_schema`_ ALTER EXTENSION _`name`_ ADD _`member_object`_ ALTER EXTENSION _`name`_ DROP _`member_object`_ where _`member_object`_ is: ACCESS METHOD _`object_name`_ | AGGREGATE _`aggregate_name`_ ( _`aggregate_signature`_ ) | CAST (_`source_type`_ AS _`target_type`_) | COLLATION _`object_name`_ | CONVERSION _`object_name`_ | DOMAIN _`object_name`_ | EVENT TRIGGER _`object_name`_ | FOREIGN DATA WRAPPER _`object_name`_ | FOREIGN TABLE _`object_name`_ | FUNCTION _`function_name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] | MATERIALIZED VIEW _`object_name`_ | OPERATOR _`operator_name`_ (_`left_type`_, _`right_type`_) | OPERATOR CLASS _`object_name`_ USING _`index_method`_ | OPERATOR FAMILY _`object_name`_ USING _`index_method`_ | \[ PROCEDURAL \] LANGUAGE _`object_name`_ | PROCEDURE _`procedure_name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] | ROUTINE _`routine_name`_ \[ ( \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[, ...\] \] ) \] | SCHEMA _`object_name`_ | SEQUENCE _`object_name`_ | SERVER _`object_name`_ | TABLE _`object_name`_ | TEXT SEARCH CONFIGURATION _`object_name`_ | TEXT SEARCH DICTIONARY _`object_name`_ | TEXT SEARCH PARSER _`object_name`_ | TEXT SEARCH TEMPLATE _`object_name`_ | TRANSFORM FOR _`type_name`_ LANGUAGE _`lang_name`_ | TYPE _`object_name`_ | VIEW _`object_name`_ and _`aggregate_signature`_ is: \* | \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[ , ... \] | \[ \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[ , ... \] \] ORDER BY \[ _`argmode`_ \] \[ _`argname`_ \] _`argtype`_ \[ , ... \] Description ----------- `ALTER EXTENSION` changes the definition of an installed extension. There are several subforms: `UPDATE` This form updates the extension to a newer version. The extension must supply a suitable update script (or series of scripts) that can modify the currently-installed version into the requested version. `SET SCHEMA` This form moves the extension's objects into another schema. The extension has to be _relocatable_ for this command to succeed. ``ADD _`member_object`_`` This form adds an existing object to the extension. This is mainly useful in extension update scripts. The object will subsequently be treated as a member of the extension; notably, it can only be dropped by dropping the extension. ``DROP _`member_object`_`` This form removes a member object from the extension. This is mainly useful in extension update scripts. The object is not dropped, only disassociated from the extension. See [Section 38.16](https://www.postgresql.org/docs/11/extend-extensions.html "38.16. Packaging Related Objects into an Extension") for more information about these operations. You must own the extension to use `ALTER EXTENSION`. The `ADD`/`DROP` forms require ownership of the added/dropped object as well. Parameters ---------- _`name`_ The name of an installed extension. _`new_version`_ The desired new version of the extension. This can be written as either an identifier or a string literal. If not specified, `ALTER EXTENSION UPDATE` attempts to update to whatever is shown as the default version in the extension's control file. _`new_schema`_ The new schema for the extension. _`object_name`_ _`aggregate_name`_ _`function_name`_ _`operator_name`_ _`procedure_name`_ _`routine_name`_ The name of an object to be added to or removed from the extension. Names of tables, aggregates, domains, foreign tables, functions, operators, operator classes, operator families, procedures, routines, sequences, text search objects, types, and views can be schema-qualified. _`source_type`_ The name of the source data type of the cast. _`target_type`_ The name of the target data type of the cast. _`argmode`_ The mode of a function, procedure, or aggregate argument: `IN`, `OUT`, `INOUT`, or `VARIADIC`. If omitted, the default is `IN`. Note that `ALTER EXTENSION` does not actually pay any attention to `OUT` arguments, since only the input arguments are needed to determine the function's identity. So it is sufficient to list the `IN`, `INOUT`, and `VARIADIC` arguments. _`argname`_ The name of a function, procedure, or aggregate argument. Note that `ALTER EXTENSION` does not actually pay any attention to argument names, since only the argument data types are needed to determine the function's identity. _`argtype`_ The data type of a function, procedure, or aggregate argument. _`left_type`_ _`right_type`_ The data type(s) of the operator's arguments (optionally schema-qualified). Write `NONE` for the missing argument of a prefix or postfix operator. `PROCEDURAL` This is a noise word. _`type_name`_ The name of the data type of the transform. _`lang_name`_ The name of the language of the transform. Examples -------- To update the `hstore` extension to version 2.0: ALTER EXTENSION hstore UPDATE TO '2.0'; To change the schema of the `hstore` extension to `utils`: ALTER EXTENSION hstore SET SCHEMA utils; To add an existing function to the `hstore` extension: ALTER EXTENSION hstore ADD FUNCTION populate\_record(anyelement, hstore); Compatibility ------------- `ALTER EXTENSION` is a PostgreSQL extension. See Also -------- [CREATE EXTENSION](https://www.postgresql.org/docs/11/sql-createextension.html "CREATE EXTENSION") , [DROP EXTENSION](https://www.postgresql.org/docs/11/sql-dropextension.html "DROP EXTENSION") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/sql-altereventtrigger.html "ALTER EVENT TRIGGER") | [Up](https://www.postgresql.org/docs/11/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/11/sql-alterforeigndatawrapper.html "ALTER FOREIGN DATA WRAPPER") | | ALTER EVENT TRIGGER | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | ALTER FOREIGN DATA WRAPPER | --- # PostgreSQL: Documentation: 11: F.26. pg_freespacemap November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 11](https://www.postgresql.org/docs/11/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/pgfreespacemap.html "PostgreSQL 18 - F.26. pg_freespacemap") ([18](https://www.postgresql.org/docs/18/pgfreespacemap.html "PostgreSQL 18 - F.26. pg_freespacemap") ) / [17](https://www.postgresql.org/docs/17/pgfreespacemap.html "PostgreSQL 17 - F.26. pg_freespacemap") / [16](https://www.postgresql.org/docs/16/pgfreespacemap.html "PostgreSQL 16 - F.26. pg_freespacemap") / [15](https://www.postgresql.org/docs/15/pgfreespacemap.html "PostgreSQL 15 - F.26. pg_freespacemap") / [14](https://www.postgresql.org/docs/14/pgfreespacemap.html "PostgreSQL 14 - F.26. pg_freespacemap") Development Versions: [devel](https://www.postgresql.org/docs/devel/pgfreespacemap.html "PostgreSQL devel - F.26. pg_freespacemap") Unsupported versions: [13](https://www.postgresql.org/docs/13/pgfreespacemap.html "PostgreSQL 13 - F.26. pg_freespacemap") / [12](https://www.postgresql.org/docs/12/pgfreespacemap.html "PostgreSQL 12 - F.26. pg_freespacemap") / [11](https://www.postgresql.org/docs/11/pgfreespacemap.html "PostgreSQL 11 - F.26. pg_freespacemap") / [10](https://www.postgresql.org/docs/10/pgfreespacemap.html "PostgreSQL 10 - F.26. pg_freespacemap") / [9.6](https://www.postgresql.org/docs/9.6/pgfreespacemap.html "PostgreSQL 9.6 - F.26. pg_freespacemap") / [9.5](https://www.postgresql.org/docs/9.5/pgfreespacemap.html "PostgreSQL 9.5 - F.26. pg_freespacemap") / [9.4](https://www.postgresql.org/docs/9.4/pgfreespacemap.html "PostgreSQL 9.4 - F.26. pg_freespacemap") / [9.3](https://www.postgresql.org/docs/9.3/pgfreespacemap.html "PostgreSQL 9.3 - F.26. pg_freespacemap") / [9.2](https://www.postgresql.org/docs/9.2/pgfreespacemap.html "PostgreSQL 9.2 - F.26. pg_freespacemap") / [9.1](https://www.postgresql.org/docs/9.1/pgfreespacemap.html "PostgreSQL 9.1 - F.26. pg_freespacemap") / [9.0](https://www.postgresql.org/docs/9.0/pgfreespacemap.html "PostgreSQL 9.0 - F.26. pg_freespacemap") / [8.4](https://www.postgresql.org/docs/8.4/pgfreespacemap.html "PostgreSQL 8.4 - F.26. pg_freespacemap") / [8.3](https://www.postgresql.org/docs/8.3/pgfreespacemap.html "PostgreSQL 8.3 - F.26. pg_freespacemap") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/pgfreespacemap.html "PostgreSQL - F.26. pg_freespacemap") version, or one of the other supported versions listed above instead. | F.26. pg\_freespacemap | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/pgcrypto.html "F.25. pgcrypto") | [Up](https://www.postgresql.org/docs/11/contrib.html "Appendix F. Additional Supplied Modules") | Appendix F. Additional Supplied Modules | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | [Next](https://www.postgresql.org/docs/11/pgprewarm.html "F.27. pg_prewarm") | * * * F.26. pg\_freespacemap ---------------------- [F.26.1. Functions](https://www.postgresql.org/docs/11/pgfreespacemap.html#id-1.11.7.35.5) [F.26.2. Sample Output](https://www.postgresql.org/docs/11/pgfreespacemap.html#id-1.11.7.35.6) [F.26.3. Author](https://www.postgresql.org/docs/11/pgfreespacemap.html#id-1.11.7.35.7) The `pg_freespacemap` module provides a means for examining the free space map (FSM). It provides a function called `pg_freespace`, or two overloaded functions, to be precise. The functions show the value recorded in the free space map for a given page, or for all pages in the relation. By default use is restricted to superusers and members of the `pg_stat_scan_tables` role. Access may be granted to others using `GRANT`. ### F.26.1. Functions `pg_freespace(rel regclass IN, blkno bigint IN) returns int2` Returns the amount of free space on the page of the relation, specified by `blkno`, according to the FSM. `pg_freespace(rel regclass IN, blkno OUT bigint, avail OUT int2)` Displays the amount of free space on each page of the relation, according to the FSM. A set of `(blkno bigint, avail int2)` tuples is returned, one tuple for each page in the relation. The values stored in the free space map are not exact. They're rounded to precision of 1/256th of `BLCKSZ` (32 bytes with default `BLCKSZ`), and they're not kept fully up-to-date as tuples are inserted and updated. For indexes, what is tracked is entirely-unused pages, rather than free space within pages. Therefore, the values are not meaningful, just whether a page is full or empty. ### Note The interface was changed in version 8.4, to reflect the new FSM implementation introduced in the same version. ### F.26.2. Sample Output postgres=# SELECT \* FROM pg\_freespace('foo'); blkno | avail -------+------- 0 | 0 1 | 0 2 | 0 3 | 32 4 | 704 5 | 704 6 | 704 7 | 1216 8 | 704 9 | 704 10 | 704 11 | 704 12 | 704 13 | 704 14 | 704 15 | 704 16 | 704 17 | 704 18 | 704 19 | 3648 (20 rows) postgres=# SELECT \* FROM pg\_freespace('foo', 7); pg\_freespace -------------- 1216 (1 row) ### F.26.3. Author Original version by Mark Kirkwood `<[markir@paradise.net.nz](mailto:markir@paradise.net.nz) >`. Rewritten in version 8.4 to suit new FSM implementation by Heikki Linnakangas `<[heikki@enterprisedb.com](mailto:heikki@enterprisedb.com) >` * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/pgcrypto.html "F.25. pgcrypto") | [Up](https://www.postgresql.org/docs/11/contrib.html "Appendix F. Additional Supplied Modules") | [Next](https://www.postgresql.org/docs/11/pgprewarm.html "F.27. pg_prewarm") | | F.25. pgcrypto | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | F.27. pg\_prewarm | --- # PostgreSQL: Documentation: 11: 60.4. Further Reading November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 11](https://www.postgresql.org/docs/11/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/geqo-biblio.html "PostgreSQL 18 - 60.4. Further Reading") ([18](https://www.postgresql.org/docs/18/geqo-biblio.html "PostgreSQL 18 - 60.4. Further Reading") ) / [17](https://www.postgresql.org/docs/17/geqo-biblio.html "PostgreSQL 17 - 60.4. Further Reading") / [16](https://www.postgresql.org/docs/16/geqo-biblio.html "PostgreSQL 16 - 60.4. Further Reading") / [15](https://www.postgresql.org/docs/15/geqo-biblio.html "PostgreSQL 15 - 60.4. Further Reading") / [14](https://www.postgresql.org/docs/14/geqo-biblio.html "PostgreSQL 14 - 60.4. Further Reading") Development Versions: [devel](https://www.postgresql.org/docs/devel/geqo-biblio.html "PostgreSQL devel - 60.4. Further Reading") Unsupported versions: [13](https://www.postgresql.org/docs/13/geqo-biblio.html "PostgreSQL 13 - 60.4. Further Reading") / [12](https://www.postgresql.org/docs/12/geqo-biblio.html "PostgreSQL 12 - 60.4. Further Reading") / [11](https://www.postgresql.org/docs/11/geqo-biblio.html "PostgreSQL 11 - 60.4. Further Reading") / [10](https://www.postgresql.org/docs/10/geqo-biblio.html "PostgreSQL 10 - 60.4. Further Reading") / [9.6](https://www.postgresql.org/docs/9.6/geqo-biblio.html "PostgreSQL 9.6 - 60.4. Further Reading") / [9.5](https://www.postgresql.org/docs/9.5/geqo-biblio.html "PostgreSQL 9.5 - 60.4. Further Reading") / [9.4](https://www.postgresql.org/docs/9.4/geqo-biblio.html "PostgreSQL 9.4 - 60.4. Further Reading") / [9.3](https://www.postgresql.org/docs/9.3/geqo-biblio.html "PostgreSQL 9.3 - 60.4. Further Reading") / [9.2](https://www.postgresql.org/docs/9.2/geqo-biblio.html "PostgreSQL 9.2 - 60.4. Further Reading") / [9.1](https://www.postgresql.org/docs/9.1/geqo-biblio.html "PostgreSQL 9.1 - 60.4. Further Reading") / [9.0](https://www.postgresql.org/docs/9.0/geqo-biblio.html "PostgreSQL 9.0 - 60.4. Further Reading") / [8.4](https://www.postgresql.org/docs/8.4/geqo-biblio.html "PostgreSQL 8.4 - 60.4. Further Reading") / [8.3](https://www.postgresql.org/docs/8.3/geqo-biblio.html "PostgreSQL 8.3 - 60.4. Further Reading") / [8.2](https://www.postgresql.org/docs/8.2/geqo-biblio.html "PostgreSQL 8.2 - 60.4. Further Reading") / [8.1](https://www.postgresql.org/docs/8.1/geqo-biblio.html "PostgreSQL 8.1 - 60.4. Further Reading") / [8.0](https://www.postgresql.org/docs/8.0/geqo-biblio.html "PostgreSQL 8.0 - 60.4. Further Reading") / [7.4](https://www.postgresql.org/docs/7.4/geqo-biblio.html "PostgreSQL 7.4 - 60.4. Further Reading") / [7.3](https://www.postgresql.org/docs/7.3/geqo-biblio.html "PostgreSQL 7.3 - 60.4. Further Reading") / [7.2](https://www.postgresql.org/docs/7.2/geqo-biblio.html "PostgreSQL 7.2 - 60.4. Further Reading") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/geqo-biblio.html "PostgreSQL - 60.4. Further Reading") version, or one of the other supported versions listed above instead. | 60.4. Further Reading | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/geqo-pg-intro.html "60.3. Genetic Query Optimization (GEQO) in PostgreSQL") | [Up](https://www.postgresql.org/docs/11/geqo.html "Chapter 60. Genetic Query Optimizer") | Chapter 60. Genetic Query Optimizer | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | [Next](https://www.postgresql.org/docs/11/indexam.html "Chapter 61. Index Access Method Interface Definition") | * * * 60.4. Further Reading --------------------- The following resources contain additional information about genetic algorithms: * [The Hitch-Hiker's Guide to Evolutionary Computation](http://www.faqs.org/faqs/ai-faq/genetic/part1/) , (FAQ for [news://comp.ai.genetic](news://comp.ai.genetic) ) * [Evolutionary Computation and its application to art and design](https://www.red3d.com/cwr/evolve.html) , by Craig Reynolds * [\[elma04\]](https://www.postgresql.org/docs/11/biblio.html#ELMA04 "Fundamentals of Database Systems") * [\[fong\]](https://www.postgresql.org/docs/11/biblio.html#FONG "The design and implementation of the POSTGRES query optimizer") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/geqo-pg-intro.html "60.3. Genetic Query Optimization (GEQO) in PostgreSQL") | [Up](https://www.postgresql.org/docs/11/geqo.html "Chapter 60. Genetic Query Optimizer") | [Next](https://www.postgresql.org/docs/11/indexam.html "Chapter 61. Index Access Method Interface Definition") | | 60.3. Genetic Query Optimization (GEQO) in PostgreSQL | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | Chapter 61. Index Access Method Interface Definition | --- # PostgreSQL: Documentation: 11: 52.31. pg_largeobject_metadata November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 11](https://www.postgresql.org/docs/11/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-largeobject-metadata.html "PostgreSQL 18 - 52.31. pg_largeobject_metadata") ([18](https://www.postgresql.org/docs/18/catalog-pg-largeobject-metadata.html "PostgreSQL 18 - 52.31. pg_largeobject_metadata") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-largeobject-metadata.html "PostgreSQL 17 - 52.31. pg_largeobject_metadata") / [16](https://www.postgresql.org/docs/16/catalog-pg-largeobject-metadata.html "PostgreSQL 16 - 52.31. pg_largeobject_metadata") / [15](https://www.postgresql.org/docs/15/catalog-pg-largeobject-metadata.html "PostgreSQL 15 - 52.31. pg_largeobject_metadata") / [14](https://www.postgresql.org/docs/14/catalog-pg-largeobject-metadata.html "PostgreSQL 14 - 52.31. pg_largeobject_metadata") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-largeobject-metadata.html "PostgreSQL devel - 52.31. pg_largeobject_metadata") Unsupported versions: [13](https://www.postgresql.org/docs/13/catalog-pg-largeobject-metadata.html "PostgreSQL 13 - 52.31. pg_largeobject_metadata") / [12](https://www.postgresql.org/docs/12/catalog-pg-largeobject-metadata.html "PostgreSQL 12 - 52.31. pg_largeobject_metadata") / [11](https://www.postgresql.org/docs/11/catalog-pg-largeobject-metadata.html "PostgreSQL 11 - 52.31. pg_largeobject_metadata") / [10](https://www.postgresql.org/docs/10/catalog-pg-largeobject-metadata.html "PostgreSQL 10 - 52.31. pg_largeobject_metadata") / [9.6](https://www.postgresql.org/docs/9.6/catalog-pg-largeobject-metadata.html "PostgreSQL 9.6 - 52.31. pg_largeobject_metadata") / [9.5](https://www.postgresql.org/docs/9.5/catalog-pg-largeobject-metadata.html "PostgreSQL 9.5 - 52.31. pg_largeobject_metadata") / [9.4](https://www.postgresql.org/docs/9.4/catalog-pg-largeobject-metadata.html "PostgreSQL 9.4 - 52.31. pg_largeobject_metadata") / [9.3](https://www.postgresql.org/docs/9.3/catalog-pg-largeobject-metadata.html "PostgreSQL 9.3 - 52.31. pg_largeobject_metadata") / [9.2](https://www.postgresql.org/docs/9.2/catalog-pg-largeobject-metadata.html "PostgreSQL 9.2 - 52.31. pg_largeobject_metadata") / [9.1](https://www.postgresql.org/docs/9.1/catalog-pg-largeobject-metadata.html "PostgreSQL 9.1 - 52.31. pg_largeobject_metadata") / [9.0](https://www.postgresql.org/docs/9.0/catalog-pg-largeobject-metadata.html "PostgreSQL 9.0 - 52.31. pg_largeobject_metadata") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/catalog-pg-largeobject-metadata.html "PostgreSQL - 52.31. pg_largeobject_metadata") version, or one of the other supported versions listed above instead. | 52.31. `pg_largeobject_metadata` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/catalog-pg-largeobject.html "52.30. pg_largeobject") | [Up](https://www.postgresql.org/docs/11/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | [Next](https://www.postgresql.org/docs/11/catalog-pg-namespace.html "52.32. pg_namespace") | * * * 52.31. `pg_largeobject_metadata` -------------------------------- The catalog `pg_largeobject_metadata` holds metadata associated with large objects. The actual large object data is stored in [`pg_largeobject`](https://www.postgresql.org/docs/11/catalog-pg-largeobject.html "52.30. pg_largeobject") . **Table 52.31. `pg_largeobject_metadata` Columns** | Name | Type | References | Description | | --- | --- | --- | --- | | `oid` | `oid` | | Row identifier (hidden attribute; must be explicitly selected) | | `lomowner` | `oid` | ``[`pg_authid`](https://www.postgresql.org/docs/11/catalog-pg-authid.html "52.8. pg_authid") .oid`` | Owner of the large object | | `lomacl` | `aclitem[]` | | Access privileges; see [GRANT](https://www.postgresql.org/docs/11/sql-grant.html "GRANT")
and [REVOKE](https://www.postgresql.org/docs/11/sql-revoke.html "REVOKE")
for details | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/catalog-pg-largeobject.html "52.30. pg_largeobject") | [Up](https://www.postgresql.org/docs/11/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/11/catalog-pg-namespace.html "52.32. pg_namespace") | | 52.30. `pg_largeobject` | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | 52.32. `pg_namespace` | --- # PostgreSQL: Documentation: 11: 46.6. Trigger Functions November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 11](https://www.postgresql.org/docs/11/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plpython-trigger.html "PostgreSQL 18 - 46.6. Trigger Functions") ([18](https://www.postgresql.org/docs/18/plpython-trigger.html "PostgreSQL 18 - 46.6. Trigger Functions") ) / [17](https://www.postgresql.org/docs/17/plpython-trigger.html "PostgreSQL 17 - 46.6. Trigger Functions") / [16](https://www.postgresql.org/docs/16/plpython-trigger.html "PostgreSQL 16 - 46.6. Trigger Functions") / [15](https://www.postgresql.org/docs/15/plpython-trigger.html "PostgreSQL 15 - 46.6. Trigger Functions") / [14](https://www.postgresql.org/docs/14/plpython-trigger.html "PostgreSQL 14 - 46.6. Trigger Functions") Development Versions: [devel](https://www.postgresql.org/docs/devel/plpython-trigger.html "PostgreSQL devel - 46.6. Trigger Functions") Unsupported versions: [13](https://www.postgresql.org/docs/13/plpython-trigger.html "PostgreSQL 13 - 46.6. Trigger Functions") / [12](https://www.postgresql.org/docs/12/plpython-trigger.html "PostgreSQL 12 - 46.6. Trigger Functions") / [11](https://www.postgresql.org/docs/11/plpython-trigger.html "PostgreSQL 11 - 46.6. Trigger Functions") / [10](https://www.postgresql.org/docs/10/plpython-trigger.html "PostgreSQL 10 - 46.6. Trigger Functions") / [9.6](https://www.postgresql.org/docs/9.6/plpython-trigger.html "PostgreSQL 9.6 - 46.6. Trigger Functions") / [9.5](https://www.postgresql.org/docs/9.5/plpython-trigger.html "PostgreSQL 9.5 - 46.6. Trigger Functions") / [9.4](https://www.postgresql.org/docs/9.4/plpython-trigger.html "PostgreSQL 9.4 - 46.6. Trigger Functions") / [9.3](https://www.postgresql.org/docs/9.3/plpython-trigger.html "PostgreSQL 9.3 - 46.6. Trigger Functions") / [9.2](https://www.postgresql.org/docs/9.2/plpython-trigger.html "PostgreSQL 9.2 - 46.6. Trigger Functions") / [9.1](https://www.postgresql.org/docs/9.1/plpython-trigger.html "PostgreSQL 9.1 - 46.6. Trigger Functions") / [9.0](https://www.postgresql.org/docs/9.0/plpython-trigger.html "PostgreSQL 9.0 - 46.6. Trigger Functions") / [8.4](https://www.postgresql.org/docs/8.4/plpython-trigger.html "PostgreSQL 8.4 - 46.6. Trigger Functions") / [8.3](https://www.postgresql.org/docs/8.3/plpython-trigger.html "PostgreSQL 8.3 - 46.6. Trigger Functions") / [8.2](https://www.postgresql.org/docs/8.2/plpython-trigger.html "PostgreSQL 8.2 - 46.6. Trigger Functions") / [8.1](https://www.postgresql.org/docs/8.1/plpython-trigger.html "PostgreSQL 8.1 - 46.6. Trigger Functions") / [8.0](https://www.postgresql.org/docs/8.0/plpython-trigger.html "PostgreSQL 8.0 - 46.6. Trigger Functions") / [7.4](https://www.postgresql.org/docs/7.4/plpython-trigger.html "PostgreSQL 7.4 - 46.6. Trigger Functions") / [7.3](https://www.postgresql.org/docs/7.3/plpython-trigger.html "PostgreSQL 7.3 - 46.6. Trigger Functions") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/plpython-trigger.html "PostgreSQL - 46.6. Trigger Functions") version, or one of the other supported versions listed above instead. | 46.6. Trigger Functions | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/plpython-do.html "46.5. Anonymous Code Blocks") | [Up](https://www.postgresql.org/docs/11/plpython.html "Chapter 46. PL/Python - Python Procedural Language") | Chapter 46. PL/Python - Python Procedural Language | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | [Next](https://www.postgresql.org/docs/11/plpython-database.html "46.7. Database Access") | * * * 46.6. Trigger Functions ----------------------- When a function is used as a trigger, the dictionary `TD` contains trigger-related values: `TD["event"]` contains the event as a string: `INSERT`, `UPDATE`, `DELETE`, or `TRUNCATE`. `TD["when"]` contains one of `BEFORE`, `AFTER`, or `INSTEAD OF`. `TD["level"]` contains `ROW` or `STATEMENT`. `TD["new"]` `TD["old"]` For a row-level trigger, one or both of these fields contain the respective trigger rows, depending on the trigger event. `TD["name"]` contains the trigger name. `TD["table_name"]` contains the name of the table on which the trigger occurred. `TD["table_schema"]` contains the schema of the table on which the trigger occurred. `TD["relid"]` contains the OID of the table on which the trigger occurred. `TD["args"]` If the `CREATE TRIGGER` command included arguments, they are available in `TD["args"][0]` to ``TD["args"][_`n`_-1]``. If `TD["when"]` is `BEFORE` or `INSTEAD OF` and `TD["level"]` is `ROW`, you can return `None` or `"OK"` from the Python function to indicate the row is unmodified, `"SKIP"` to abort the event, or if `TD["event"]` is `INSERT` or `UPDATE` you can return `"MODIFY"` to indicate you've modified the new row. Otherwise the return value is ignored. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/plpython-do.html "46.5. Anonymous Code Blocks") | [Up](https://www.postgresql.org/docs/11/plpython.html "Chapter 46. PL/Python - Python Procedural Language") | [Next](https://www.postgresql.org/docs/11/plpython-database.html "46.7. Database Access") | | 46.5. Anonymous Code Blocks | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | 46.7. Database Access | --- # PostgreSQL: Documentation: 8.1: Release 8.1.18 November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 8.1](https://www.postgresql.org/docs/8.1/index.html) Unsupported versions: [9.3](https://www.postgresql.org/docs/9.3/release-8-1-18.html "PostgreSQL 9.3 - Release 8.1.18") / [9.2](https://www.postgresql.org/docs/9.2/release-8-1-18.html "PostgreSQL 9.2 - Release 8.1.18") / [9.1](https://www.postgresql.org/docs/9.1/release-8-1-18.html "PostgreSQL 9.1 - Release 8.1.18") / [9.0](https://www.postgresql.org/docs/9.0/release-8-1-18.html "PostgreSQL 9.0 - Release 8.1.18") / [8.4](https://www.postgresql.org/docs/8.4/release-8-1-18.html "PostgreSQL 8.4 - Release 8.1.18") / [8.3](https://www.postgresql.org/docs/8.3/release-8-1-18.html "PostgreSQL 8.3 - Release 8.1.18") / [8.2](https://www.postgresql.org/docs/8.2/release-8-1-18.html "PostgreSQL 8.2 - Release 8.1.18") / [8.1](https://www.postgresql.org/docs/8.1/release-8-1-18.html "PostgreSQL 8.1 - Release 8.1.18") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/release-8-1-18.html "PostgreSQL - Release 8.1.18") version, or one of the other supported versions listed above instead. | PostgreSQL 8.1.23 Documentation | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/8.1/release-8-1-19.html) | [Fast Backward](https://www.postgresql.org/docs/8.1/release.html) | Appendix E. Release Notes | [Fast Forward](https://www.postgresql.org/docs/8.1/release.html) | [Next](https://www.postgresql.org/docs/8.1/release-8-1-17.html) | * * * E.6. Release 8.1.18 =================== > **Release date:** 2009-09-09 This release contains a variety of fixes from 8.1.17. For information about new features in the 8.1 major release, see [Section E.24](https://www.postgresql.org/docs/8.1/release-8-1.html) . E.6.1. Migration to Version 8.1.18 ---------------------------------- A dump/restore is not required for those running 8.1.X. However, if you have any hash indexes on interval columns, you must REINDEX them after updating to 8.1.18. Also, if you are upgrading from a version earlier than 8.1.15, see the release notes for 8.1.15. E.6.2. Changes -------------- * Disallow RESET ROLE and RESET SESSION AUTHORIZATION inside security-definer functions (Tom, Heikki) This covers a case that was missed in the previous patch that disallowed SET ROLE and SET SESSION AUTHORIZATION inside security-definer functions. (See CVE-2007-6600) * Fix handling of sub-SELECTs appearing in the arguments of an outer-level aggregate function (Tom) * Fix hash calculation for data type interval (Tom) This corrects wrong results for hash joins on interval values. It also changes the contents of hash indexes on interval columns. If you have any such indexes, you must REINDEX them after updating. * Treat `to_char(..., 'TH')` as an uppercase ordinal suffix with 'HH'/'HH12' (Heikki) It was previously handled as 'th' (lowercase). * Fix overflow for INTERVAL 'x ms' when x is more than 2 million and integer datetimes are in use (Alex Hunsaker) * Fix calculation of distance between a point and a line segment (Tom) This led to incorrect results from a number of geometric operators. * Fix money data type to work in locales where currency amounts have no fractional digits, e.g. Japan (Itagaki Takahiro) * Properly round datetime input like 00:12:57.9999999999999999999999999999 (Tom) * Fix poor choice of page split point in GiST R-tree operator classes (Teodor) * Fix portability issues in plperl initialization (Andrew Dunstan) * Fix pg\_ctl to not go into an infinite loop if postgresql.conf is empty (Jeff Davis) * Fix contrib/xml2's `xslt_process()` to properly handle the maximum number of parameters (twenty) (Tom) * Improve robustness of libpq's code to recover from errors during COPY FROM STDIN (Tom) * Avoid including conflicting readline and editline header files when both libraries are installed (Zdenek Kotala) * Update time zone data files to tzdata release 2009l for DST law changes in Bangladesh, Egypt, Jordan, Pakistan, Argentina/San\_Luis, Cuba, Jordan (historical correction only), Mauritius, Morocco, Palestine, Syria, Tunisia. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/8.1/release-8-1-19.html) | [Home](https://www.postgresql.org/docs/8.1/index.html) | [Next](https://www.postgresql.org/docs/8.1/release-8-1-17.html) | | Release 8.1.19 | [Up](https://www.postgresql.org/docs/8.1/release.html) | Release 8.1.17 | --- # PostgreSQL: Documentation: 11: 52.3. pg_am November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 11](https://www.postgresql.org/docs/11/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-am.html "PostgreSQL 18 - 52.3. pg_am") ([18](https://www.postgresql.org/docs/18/catalog-pg-am.html "PostgreSQL 18 - 52.3. pg_am") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-am.html "PostgreSQL 17 - 52.3. pg_am") / [16](https://www.postgresql.org/docs/16/catalog-pg-am.html "PostgreSQL 16 - 52.3. pg_am") / [15](https://www.postgresql.org/docs/15/catalog-pg-am.html "PostgreSQL 15 - 52.3. pg_am") / [14](https://www.postgresql.org/docs/14/catalog-pg-am.html "PostgreSQL 14 - 52.3. pg_am") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-am.html "PostgreSQL devel - 52.3. pg_am") Unsupported versions: [13](https://www.postgresql.org/docs/13/catalog-pg-am.html "PostgreSQL 13 - 52.3. pg_am") / [12](https://www.postgresql.org/docs/12/catalog-pg-am.html "PostgreSQL 12 - 52.3. pg_am") / [11](https://www.postgresql.org/docs/11/catalog-pg-am.html "PostgreSQL 11 - 52.3. pg_am") / [10](https://www.postgresql.org/docs/10/catalog-pg-am.html "PostgreSQL 10 - 52.3. pg_am") / [9.6](https://www.postgresql.org/docs/9.6/catalog-pg-am.html "PostgreSQL 9.6 - 52.3. pg_am") / [9.5](https://www.postgresql.org/docs/9.5/catalog-pg-am.html "PostgreSQL 9.5 - 52.3. pg_am") / [9.4](https://www.postgresql.org/docs/9.4/catalog-pg-am.html "PostgreSQL 9.4 - 52.3. pg_am") / [9.3](https://www.postgresql.org/docs/9.3/catalog-pg-am.html "PostgreSQL 9.3 - 52.3. pg_am") / [9.2](https://www.postgresql.org/docs/9.2/catalog-pg-am.html "PostgreSQL 9.2 - 52.3. pg_am") / [9.1](https://www.postgresql.org/docs/9.1/catalog-pg-am.html "PostgreSQL 9.1 - 52.3. pg_am") / [9.0](https://www.postgresql.org/docs/9.0/catalog-pg-am.html "PostgreSQL 9.0 - 52.3. pg_am") / [8.4](https://www.postgresql.org/docs/8.4/catalog-pg-am.html "PostgreSQL 8.4 - 52.3. pg_am") / [8.3](https://www.postgresql.org/docs/8.3/catalog-pg-am.html "PostgreSQL 8.3 - 52.3. pg_am") / [8.2](https://www.postgresql.org/docs/8.2/catalog-pg-am.html "PostgreSQL 8.2 - 52.3. pg_am") / [8.1](https://www.postgresql.org/docs/8.1/catalog-pg-am.html "PostgreSQL 8.1 - 52.3. pg_am") / [8.0](https://www.postgresql.org/docs/8.0/catalog-pg-am.html "PostgreSQL 8.0 - 52.3. pg_am") / [7.4](https://www.postgresql.org/docs/7.4/catalog-pg-am.html "PostgreSQL 7.4 - 52.3. pg_am") / [7.3](https://www.postgresql.org/docs/7.3/catalog-pg-am.html "PostgreSQL 7.3 - 52.3. pg_am") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/catalog-pg-am.html "PostgreSQL - 52.3. pg_am") version, or one of the other supported versions listed above instead. | 52.3. `pg_am` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/catalog-pg-aggregate.html "52.2. pg_aggregate") | [Up](https://www.postgresql.org/docs/11/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | [Next](https://www.postgresql.org/docs/11/catalog-pg-amop.html "52.4. pg_amop") | * * * 52.3. `pg_am` ------------- The catalog `pg_am` stores information about relation access methods. There is one row for each access method supported by the system. Currently, only indexes have access methods. The requirements for index access methods are discussed in detail in [Chapter 61](https://www.postgresql.org/docs/11/indexam.html "Chapter 61. Index Access Method Interface Definition") . **Table 52.3. `pg_am` Columns** | Name | Type | References | Description | | --- | --- | --- | --- | | `oid` | `oid` | | Row identifier (hidden attribute; must be explicitly selected) | | `amname` | `name` | | Name of the access method | | `amhandler` | `regproc` | ``[`pg_proc`](https://www.postgresql.org/docs/11/catalog-pg-proc.html "52.39. pg_proc") .oid`` | OID of a handler function that is responsible for supplying information about the access method | | `amtype` | `char` | | Currently always `i` to indicate an index access method; other values may be allowed in future | ### Note Before PostgreSQL 9.6, `pg_am` contained many additional columns representing properties of index access methods. That data is now only directly visible at the C code level. However, `pg_index_column_has_property()` and related functions have been added to allow SQL queries to inspect index access method properties; see [Table 9.63](https://www.postgresql.org/docs/11/functions-info.html#FUNCTIONS-INFO-CATALOG-TABLE "Table 9.63. System Catalog Information Functions") . * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/catalog-pg-aggregate.html "52.2. pg_aggregate") | [Up](https://www.postgresql.org/docs/11/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/11/catalog-pg-amop.html "52.4. pg_amop") | | 52.2. `pg_aggregate` | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | 52.4. `pg_amop` | --- # PostgreSQL: Documentation: 11: H.3. Procedural Languages November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 11](https://www.postgresql.org/docs/11/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/external-pl.html "PostgreSQL 18 - H.3. Procedural Languages") ([18](https://www.postgresql.org/docs/18/external-pl.html "PostgreSQL 18 - H.3. Procedural Languages") ) / [17](https://www.postgresql.org/docs/17/external-pl.html "PostgreSQL 17 - H.3. Procedural Languages") / [16](https://www.postgresql.org/docs/16/external-pl.html "PostgreSQL 16 - H.3. Procedural Languages") / [15](https://www.postgresql.org/docs/15/external-pl.html "PostgreSQL 15 - H.3. Procedural Languages") / [14](https://www.postgresql.org/docs/14/external-pl.html "PostgreSQL 14 - H.3. Procedural Languages") Development Versions: [devel](https://www.postgresql.org/docs/devel/external-pl.html "PostgreSQL devel - H.3. Procedural Languages") Unsupported versions: [13](https://www.postgresql.org/docs/13/external-pl.html "PostgreSQL 13 - H.3. Procedural Languages") / [12](https://www.postgresql.org/docs/12/external-pl.html "PostgreSQL 12 - H.3. Procedural Languages") / [11](https://www.postgresql.org/docs/11/external-pl.html "PostgreSQL 11 - H.3. Procedural Languages") / [10](https://www.postgresql.org/docs/10/external-pl.html "PostgreSQL 10 - H.3. Procedural Languages") / [9.6](https://www.postgresql.org/docs/9.6/external-pl.html "PostgreSQL 9.6 - H.3. Procedural Languages") / [9.5](https://www.postgresql.org/docs/9.5/external-pl.html "PostgreSQL 9.5 - H.3. Procedural Languages") / [9.4](https://www.postgresql.org/docs/9.4/external-pl.html "PostgreSQL 9.4 - H.3. Procedural Languages") / [9.3](https://www.postgresql.org/docs/9.3/external-pl.html "PostgreSQL 9.3 - H.3. Procedural Languages") / [9.2](https://www.postgresql.org/docs/9.2/external-pl.html "PostgreSQL 9.2 - H.3. Procedural Languages") / [9.1](https://www.postgresql.org/docs/9.1/external-pl.html "PostgreSQL 9.1 - H.3. Procedural Languages") / [9.0](https://www.postgresql.org/docs/9.0/external-pl.html "PostgreSQL 9.0 - H.3. Procedural Languages") / [8.4](https://www.postgresql.org/docs/8.4/external-pl.html "PostgreSQL 8.4 - H.3. Procedural Languages") / [8.3](https://www.postgresql.org/docs/8.3/external-pl.html "PostgreSQL 8.3 - H.3. Procedural Languages") / [8.2](https://www.postgresql.org/docs/8.2/external-pl.html "PostgreSQL 8.2 - H.3. Procedural Languages") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/external-pl.html "PostgreSQL - H.3. Procedural Languages") version, or one of the other supported versions listed above instead. | H.3. Procedural Languages | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/external-admin-tools.html "H.2. Administration Tools") | [Up](https://www.postgresql.org/docs/11/external-projects.html "Appendix H. External Projects") | Appendix H. External Projects | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | [Next](https://www.postgresql.org/docs/11/external-extensions.html "H.4. Extensions") | * * * H.3. Procedural Languages ------------------------- PostgreSQL includes several procedural languages with the base distribution: [PL/pgSQL](https://www.postgresql.org/docs/11/plpgsql.html "Chapter 43. PL/pgSQL - SQL Procedural Language") , [PL/Tcl](https://www.postgresql.org/docs/11/pltcl.html "Chapter 44. PL/Tcl - Tcl Procedural Language") , [PL/Perl](https://www.postgresql.org/docs/11/plperl.html "Chapter 45. PL/Perl - Perl Procedural Language") , and [PL/Python](https://www.postgresql.org/docs/11/plpython.html "Chapter 46. PL/Python - Python Procedural Language") . In addition, there are a number of procedural languages that are developed and maintained outside the core PostgreSQL distribution. A list of [procedural languages](https://wiki.postgresql.org/wiki/PL_Matrix) is maintained on the PostgreSQL wiki. Note that some of these projects are not released under the same license as PostgreSQL. For more information on each procedural language, including licensing information, refer to its website and documentation. [https://wiki.postgresql.org/wiki/PL\_Matrix](https://wiki.postgresql.org/wiki/PL_Matrix) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/11/external-admin-tools.html "H.2. Administration Tools") | [Up](https://www.postgresql.org/docs/11/external-projects.html "Appendix H. External Projects") | [Next](https://www.postgresql.org/docs/11/external-extensions.html "H.4. Extensions") | | H.2. Administration Tools | [Home](https://www.postgresql.org/docs/11/index.html "PostgreSQL 11.22 Documentation") | H.4. Extensions | --- # PostgreSQL: Documentation: 18: 52.30. pg_largeobject November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/catalog-pg-largeobject.html "PostgreSQL 18 - 52.30. pg_largeobject") ([18](https://www.postgresql.org/docs/18/catalog-pg-largeobject.html "PostgreSQL 18 - 52.30. pg_largeobject") ) / [17](https://www.postgresql.org/docs/17/catalog-pg-largeobject.html "PostgreSQL 17 - 52.30. pg_largeobject") / [16](https://www.postgresql.org/docs/16/catalog-pg-largeobject.html "PostgreSQL 16 - 52.30. pg_largeobject") / [15](https://www.postgresql.org/docs/15/catalog-pg-largeobject.html "PostgreSQL 15 - 52.30. pg_largeobject") / [14](https://www.postgresql.org/docs/14/catalog-pg-largeobject.html "PostgreSQL 14 - 52.30. pg_largeobject") Development Versions: [devel](https://www.postgresql.org/docs/devel/catalog-pg-largeobject.html "PostgreSQL devel - 52.30. pg_largeobject") Unsupported versions: [13](https://www.postgresql.org/docs/13/catalog-pg-largeobject.html "PostgreSQL 13 - 52.30. pg_largeobject") / [12](https://www.postgresql.org/docs/12/catalog-pg-largeobject.html "PostgreSQL 12 - 52.30. pg_largeobject") / [11](https://www.postgresql.org/docs/11/catalog-pg-largeobject.html "PostgreSQL 11 - 52.30. pg_largeobject") / [10](https://www.postgresql.org/docs/10/catalog-pg-largeobject.html "PostgreSQL 10 - 52.30. pg_largeobject") / [9.6](https://www.postgresql.org/docs/9.6/catalog-pg-largeobject.html "PostgreSQL 9.6 - 52.30. pg_largeobject") / [9.5](https://www.postgresql.org/docs/9.5/catalog-pg-largeobject.html "PostgreSQL 9.5 - 52.30. pg_largeobject") / [9.4](https://www.postgresql.org/docs/9.4/catalog-pg-largeobject.html "PostgreSQL 9.4 - 52.30. pg_largeobject") / [9.3](https://www.postgresql.org/docs/9.3/catalog-pg-largeobject.html "PostgreSQL 9.3 - 52.30. pg_largeobject") / [9.2](https://www.postgresql.org/docs/9.2/catalog-pg-largeobject.html "PostgreSQL 9.2 - 52.30. pg_largeobject") / [9.1](https://www.postgresql.org/docs/9.1/catalog-pg-largeobject.html "PostgreSQL 9.1 - 52.30. pg_largeobject") / [9.0](https://www.postgresql.org/docs/9.0/catalog-pg-largeobject.html "PostgreSQL 9.0 - 52.30. pg_largeobject") / [8.4](https://www.postgresql.org/docs/8.4/catalog-pg-largeobject.html "PostgreSQL 8.4 - 52.30. pg_largeobject") / [8.3](https://www.postgresql.org/docs/8.3/catalog-pg-largeobject.html "PostgreSQL 8.3 - 52.30. pg_largeobject") / [8.2](https://www.postgresql.org/docs/8.2/catalog-pg-largeobject.html "PostgreSQL 8.2 - 52.30. pg_largeobject") / [8.1](https://www.postgresql.org/docs/8.1/catalog-pg-largeobject.html "PostgreSQL 8.1 - 52.30. pg_largeobject") / [8.0](https://www.postgresql.org/docs/8.0/catalog-pg-largeobject.html "PostgreSQL 8.0 - 52.30. pg_largeobject") / [7.4](https://www.postgresql.org/docs/7.4/catalog-pg-largeobject.html "PostgreSQL 7.4 - 52.30. pg_largeobject") / [7.3](https://www.postgresql.org/docs/7.3/catalog-pg-largeobject.html "PostgreSQL 7.3 - 52.30. pg_largeobject") / [7.2](https://www.postgresql.org/docs/7.2/catalog-pg-largeobject.html "PostgreSQL 7.2 - 52.30. pg_largeobject") | 52.30. `pg_largeobject` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-language.html "52.29. pg_language") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | Chapter 52. System Catalogs | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/catalog-pg-largeobject-metadata.html "52.31. pg_largeobject_metadata") | * * * 52.30. `pg_largeobject` [#](https://www.postgresql.org/docs/current/catalog-pg-largeobject.html#CATALOG-PG-LARGEOBJECT) ------------------------------------------------------------------------------------------------------------------------ The catalog `pg_largeobject` holds the data making up “large objects”. A large object is identified by an OID assigned when it is created. Each large object is broken into segments or “pages” small enough to be conveniently stored as rows in `pg_largeobject`. The amount of data per page is defined to be `LOBLKSIZE` (which is currently `BLCKSZ/4`, or typically 2 kB). Prior to PostgreSQL 9.0, there was no permission structure associated with large objects. As a result, `pg_largeobject` was publicly readable and could be used to obtain the OIDs (and contents) of all large objects in the system. This is no longer the case; use [`pg_largeobject_metadata`](https://www.postgresql.org/docs/current/catalog-pg-largeobject-metadata.html "52.31. pg_largeobject_metadata") to obtain a list of large object OIDs. **Table 52.30. `pg_largeobject` Columns** | Column Type

Description | | --- | | `loid` `oid` (references [`pg_largeobject_metadata`](https://www.postgresql.org/docs/current/catalog-pg-largeobject-metadata.html "52.31. pg_largeobject_metadata")
.`oid`)

Identifier of the large object that includes this page | | `pageno` `int4`

Page number of this page within its large object (counting from zero) | | `data` `bytea`

Actual data stored in the large object. This will never be more than `LOBLKSIZE` bytes and might be less. | Each row of `pg_largeobject` holds data for one page of a large object, beginning at byte offset (`pageno * LOBLKSIZE`) within the object. The implementation allows sparse storage: pages might be missing, and might be shorter than `LOBLKSIZE` bytes even if they are not the last page of the object. Missing regions within a large object read as zeroes. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/catalog-pg-language.html "52.29. pg_language") | [Up](https://www.postgresql.org/docs/current/catalogs.html "Chapter 52. System Catalogs") | [Next](https://www.postgresql.org/docs/current/catalog-pg-largeobject-metadata.html "52.31. pg_largeobject_metadata") | | 52.29. `pg_language` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | 52.31. `pg_largeobject_metadata` | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/catalog-pg-largeobject.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 8.1: Supported Platforms November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 8.1](https://www.postgresql.org/docs/8.1/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/supported-platforms.html "PostgreSQL 18 - Supported Platforms") ([18](https://www.postgresql.org/docs/18/supported-platforms.html "PostgreSQL 18 - Supported Platforms") ) / [17](https://www.postgresql.org/docs/17/supported-platforms.html "PostgreSQL 17 - Supported Platforms") / [16](https://www.postgresql.org/docs/16/supported-platforms.html "PostgreSQL 16 - Supported Platforms") / [15](https://www.postgresql.org/docs/15/supported-platforms.html "PostgreSQL 15 - Supported Platforms") / [14](https://www.postgresql.org/docs/14/supported-platforms.html "PostgreSQL 14 - Supported Platforms") Development Versions: [devel](https://www.postgresql.org/docs/devel/supported-platforms.html "PostgreSQL devel - Supported Platforms") Unsupported versions: [13](https://www.postgresql.org/docs/13/supported-platforms.html "PostgreSQL 13 - Supported Platforms") / [12](https://www.postgresql.org/docs/12/supported-platforms.html "PostgreSQL 12 - Supported Platforms") / [11](https://www.postgresql.org/docs/11/supported-platforms.html "PostgreSQL 11 - Supported Platforms") / [10](https://www.postgresql.org/docs/10/supported-platforms.html "PostgreSQL 10 - Supported Platforms") / [9.6](https://www.postgresql.org/docs/9.6/supported-platforms.html "PostgreSQL 9.6 - Supported Platforms") / [9.5](https://www.postgresql.org/docs/9.5/supported-platforms.html "PostgreSQL 9.5 - Supported Platforms") / [9.4](https://www.postgresql.org/docs/9.4/supported-platforms.html "PostgreSQL 9.4 - Supported Platforms") / [9.3](https://www.postgresql.org/docs/9.3/supported-platforms.html "PostgreSQL 9.3 - Supported Platforms") / [9.2](https://www.postgresql.org/docs/9.2/supported-platforms.html "PostgreSQL 9.2 - Supported Platforms") / [9.1](https://www.postgresql.org/docs/9.1/supported-platforms.html "PostgreSQL 9.1 - Supported Platforms") / [9.0](https://www.postgresql.org/docs/9.0/supported-platforms.html "PostgreSQL 9.0 - Supported Platforms") / [8.4](https://www.postgresql.org/docs/8.4/supported-platforms.html "PostgreSQL 8.4 - Supported Platforms") / [8.3](https://www.postgresql.org/docs/8.3/supported-platforms.html "PostgreSQL 8.3 - Supported Platforms") / [8.2](https://www.postgresql.org/docs/8.2/supported-platforms.html "PostgreSQL 8.2 - Supported Platforms") / [8.1](https://www.postgresql.org/docs/8.1/supported-platforms.html "PostgreSQL 8.1 - Supported Platforms") / [8.0](https://www.postgresql.org/docs/8.0/supported-platforms.html "PostgreSQL 8.0 - Supported Platforms") / [7.4](https://www.postgresql.org/docs/7.4/supported-platforms.html "PostgreSQL 7.4 - Supported Platforms") / [7.3](https://www.postgresql.org/docs/7.3/supported-platforms.html "PostgreSQL 7.3 - Supported Platforms") / [7.2](https://www.postgresql.org/docs/7.2/supported-platforms.html "PostgreSQL 7.2 - Supported Platforms") / [7.1](https://www.postgresql.org/docs/7.1/supported-platforms.html "PostgreSQL 7.1 - Supported Platforms") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/supported-platforms.html "PostgreSQL - Supported Platforms") version, or one of the other supported versions listed above instead. | PostgreSQL 8.1.23 Documentation | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/8.1/install-post.html) | [Fast Backward](https://www.postgresql.org/docs/8.1/installation.html) | Chapter 14. Installation Instructions | [Fast Forward](https://www.postgresql.org/docs/8.1/installation.html) | [Next](https://www.postgresql.org/docs/8.1/install-win32.html) | * * * 14.7. Supported Platforms ========================= PostgreSQL has been verified by the developer community to work on the platforms listed below. A supported platform generally means that PostgreSQL builds and installs according to these instructions and that the regression tests pass. "Build farm" entries refer to active test machines in the [PostgreSQL Build Farm](http://www.pgbuildfarm.org/) . Platform entries that show an older version of PostgreSQL are those that did not receive explicit testing at the time of release of version 8.1 but that we still expect to work. > **Note:** If you are having problems with the installation on a supported platform, please write to `<[pgsql-bugs@postgresql.org](mailto:pgsql-bugs@postgresql.org) >`, not to the people listed here. | OS | Processor | Version | Reported | Remarks | | --- | --- | --- | --- | --- | | AIX | PowerPC | 8.1.0 | Build farm kookaburra (5.2, cc 6.0); asp (5.2, gcc 3.3.2) | see doc/FAQ\_AIX, particularly if using AIX 5.3 ML3 | | AIX | RS6000 | 8.0.0 | Hans-Jürgen Schönig (`<[hs@cybertec.at](mailto:hs@cybertec.at) >`), 2004-12-06 | see doc/FAQ\_AIX | | BSD/OS | x86 | 8.1.0 | Bruce Momjian (`<[pgman@candle.pha.pa.us](mailto:pgman@candle.pha.pa.us) >`), 2005-10-26 | 4.3.1 | | Debian GNU/Linux | Alpha | 8.1.0 | Build farm hare (3.1, gcc 3.3.4) | | | Debian GNU/Linux | AMD64 | 8.1.0 | Build farm panda (sid, gcc 3.3.5) | | | Debian GNU/Linux | ARM | 8.1.0 | Build farm penguin (3.1, gcc 3.3.4) | | | Debian GNU/Linux | Athlon XP | 8.1.0 | Build farm rook (3.1, gcc 3.3.5) | | | Debian GNU/Linux | IA64 | 7.4 | Noèl Köthe (`<[noel@debian.org](mailto:noel@debian.org) >`), 2003-10-25 | | | Debian GNU/Linux | m68k | 8.0.0 | Noèl Köthe (`<[noel@debian.org](mailto:noel@debian.org) >`), 2004-12-09 | sid | | Debian GNU/Linux | MIPS | 8.1.0 | Build farm otter (3.1, gcc 3.3.4) | | | Debian GNU/Linux | MIPSEL | 8.1.0 | Build farm lionfish (3.1, gcc 3.3.4); corgi (3.1, gcc 3.3.4) | | | Debian GNU/Linux | PA-RISC | 8.1.0 | Build farm kingfisher (3.1, gcc 3.3.5) | | | Debian GNU/Linux | PowerPC | 8.0.0 | Noèl Köthe (`<[noel@debian.org](mailto:noel@debian.org) >`), 2004-12-15 | sid | | Debian GNU/Linux | S/390 | 7.4 | Noèl Köthe (`<[noel@debian.org](mailto:noel@debian.org) >`), 2003-10-25 | | | Debian GNU/Linux | Sparc | 8.1.0 | Build farm dormouse (3.1, gcc 3.2.5; 64-bit) | | | Debian GNU/Linux | x86 | 8.0.0 | Peter Eisentraut (`<[peter_e@gmx.net](mailto:peter_e@gmx.net) >`), 2004-12-06 | 3.1 (sarge), kernel 2.6 | | Fedora | AMD64 | 8.1.0 | Build farm viper (FC3, gcc 3.4.2) | | | Fedora | x86 | 8.1.0 | Build farm thrush (FC1, gcc 3.3.2) | | | FreeBSD | Alpha | 7.4 | Peter Eisentraut (`<[peter_e@gmx.net](mailto:peter_e@gmx.net) >`), 2003-10-25 | 4.8 | | FreeBSD | AMD64 | 8.1.0 | Build farm platypus (5.2.1, gcc 3.3.3); dove (5.4, gcc 3.4.2) | | | FreeBSD | x86 | 8.1.0 | Build farm octopus (4.11, gcc 2.95.4); flatworm (5.3, gcc 3.4.2); echidna (6, gcc 3.4.2); herring (6, Intel cc 7.1) | | | Gentoo Linux | AMD64 | 8.1.0 | Build farm caribou (2.6.9, gcc 3.3.5) | | | Gentoo Linux | IA64 | 8.1.0 | Build farm stoat (2.6, gcc 3.3) | | | Gentoo Linux | PowerPC 64 | 8.1.0 | Build farm cobra (1.4.16, gcc 3.4.3) | | | Gentoo Linux | x86 | 8.0.0 | Paul Bort (`<[pbort@tmwsystems.com](mailto:pbort@tmwsystems.com) >`), 2004-12-07 | | | HP-UX | IA64 | 8.1.0 | Tom Lane (`<[tgl@sss.pgh.pa.us](mailto:tgl@sss.pgh.pa.us) >`), 2005-10-15 | 11.23, gcc and cc; see doc/FAQ\_HPUX | | HP-UX | PA-RISC | 8.1.0 | Tom Lane (`<[tgl@sss.pgh.pa.us](mailto:tgl@sss.pgh.pa.us) >`), 2005-10-15 | 10.20 and 11.23, gcc and cc; see doc/FAQ\_HPUX | | IRIX | MIPS | 8.1.0 | Kenneth Marshall (`<[ktm@is.rice.edu](mailto:ktm@is.rice.edu) >`), 2005-11-04 | 6.5, cc only | | Mac OS X | PowerPC | 8.1.0 | Build farm tuna (10.4.2, gcc 4.0); cuckoo (10.3.9, gcc 3.3); wallaroo (10.3.8, gcc 3.3) | | | Mandrake Linux | x86 | 8.1.0 | Build farm shrew (10.0, gcc 3.3.2) | | | NetBSD | arm32 | 7.4 | Patrick Welche (`<[prlw1@newn.cam.ac.uk](mailto:prlw1@newn.cam.ac.uk) >`), 2003-11-12 | 1.6ZE/acorn32 | | NetBSD | m68k | 8.1.0 | Build farm osprey (2.0, gcc 3.3.3) | | | NetBSD | Sparc | 7.4.1 | Peter Eisentraut (`<[peter_e@gmx.net](mailto:peter_e@gmx.net) >`), 2003-11-26 | 1.6.1, 32-bit | | NetBSD | x86 | 8.0.0 | Build farm canary, snapshot 2004-12-06 03:30:00 | 1.6 | | OpenBSD | Sparc | 8.0.0 | Chris Mair (`<[list@1006.org](mailto:list@1006.org) >`), 2005-01-10 | 3.3 | | OpenBSD | Sparc64 | 8.1.0 | Build farm spoonbill (3.6, gcc 3.3.2) | compiler bug affects contrib/seg | | OpenBSD | x86 | 8.0.0 | Build farm emu, snapshot 2004-12-06 11:35:03 | 3.6 | | Red Hat Linux | AMD64 | 8.1.0 | Tom Lane (`<[tgl@sss.pgh.pa.us](mailto:tgl@sss.pgh.pa.us) >`), 2005-10-23 | RHEL 4 | | Red Hat Linux | IA64 | 8.1.0 | Tom Lane (`<[tgl@sss.pgh.pa.us](mailto:tgl@sss.pgh.pa.us) >`), 2005-10-23 | RHEL 4 | | Red Hat Linux | PowerPC | 8.1.0 | Tom Lane (`<[tgl@sss.pgh.pa.us](mailto:tgl@sss.pgh.pa.us) >`), 2005-10-23 | RHEL 4 | | Red Hat Linux | PowerPC 64 | 8.1.0 | Tom Lane (`<[tgl@sss.pgh.pa.us](mailto:tgl@sss.pgh.pa.us) >`), 2005-10-23 | RHEL 4 | | Red Hat Linux | S/390 | 8.1.0 | Tom Lane (`<[tgl@sss.pgh.pa.us](mailto:tgl@sss.pgh.pa.us) >`), 2005-10-23 | RHEL 4 | | Red Hat Linux | S/390x | 8.1.0 | Tom Lane (`<[tgl@sss.pgh.pa.us](mailto:tgl@sss.pgh.pa.us) >`), 2005-10-23 | RHEL 4 | | Red Hat Linux | x86 | 8.1.0 | Tom Lane (`<[tgl@sss.pgh.pa.us](mailto:tgl@sss.pgh.pa.us) >`), 2005-10-23 | RHEL 4 | | Slackware Linux | x86 | 8.1.0 | Sergey Koposov (`<[math@sai.msu.ru](mailto:math@sai.msu.ru) >`), 2005-10-24 | 10.0 | | Solaris | Sparc | 8.1.0 | Build farm buzzard (Solaris 10, gcc 3.3.2); Robert Lor (`<[Robert.Lor@sun.com](mailto:Robert.Lor@sun.com) >`), 2005-11-04 (Solaris 9); Kenneth Marshall (`<[ktm@is.rice.edu](mailto:ktm@is.rice.edu) >`), 2005-10-28 (Solaris 8, gcc 3.4.3) | see doc/FAQ\_Solaris | | Solaris | x86 | 8.1.0 | Robert Lor (`<[Robert.Lor@sun.com](mailto:Robert.Lor@sun.com) >`), 2005-11-04 (Solaris 10) | see doc/FAQ\_Solaris | | SUSE Linux | AMD64 | 8.1.0 | Josh Berkus (`<[josh@agliodbs.com](mailto:josh@agliodbs.com) >`), 2005-10-23 | SLES 9.3 | | SUSE Linux | IA64 | 8.0.0 | Reinhard Max (`<[max@suse.de](mailto:max@suse.de) >`), 2005-01-03 | SLES 9 | | SUSE Linux | PowerPC | 8.0.0 | Reinhard Max (`<[max@suse.de](mailto:max@suse.de) >`), 2005-01-03 | SLES 9 | | SUSE Linux | PowerPC 64 | 8.0.0 | Reinhard Max (`<[max@suse.de](mailto:max@suse.de) >`), 2005-01-03 | SLES 9 | | SUSE Linux | S/390 | 8.0.0 | Reinhard Max (`<[max@suse.de](mailto:max@suse.de) >`), 2005-01-03 | SLES 9 | | SUSE Linux | S/390x | 8.0.0 | Reinhard Max (`<[max@suse.de](mailto:max@suse.de) >`), 2005-01-03 | SLES 9 | | SUSE Linux | x86 | 8.0.0 | Reinhard Max (`<[max@suse.de](mailto:max@suse.de) >`), 2005-01-03 | 9.0, 9.1, 9.2, SLES 9 | | Tru64 UNIX | Alpha | 8.1.0 | Honda Shigehiro (`<[fwif0083@mb.infoweb.ne.jp](mailto:fwif0083@mb.infoweb.ne.jp) >`), 2005-11-01 | 5.0, cc 6.1-011 | | UnixWare | x86 | 8.1.0 | Build farm firefly (7.1.4, cc 4.2) | see doc/FAQ\_SCO | | Windows | x86 | 8.1.0 | Build farm loris (XP Pro, gcc 3.2.3); snake (Windows Server 2003, gcc 3.4.2) | see doc/FAQ\_MINGW | | Windows with Cygwin | x86 | 8.1.0 | Build farm ferret (XP Pro, gcc 3.3.3) | see doc/FAQ\_CYGWIN | | Yellow Dog Linux | PowerPC | 8.1.0 | Build farm carp (4.0, gcc 3.3.3) | | **Unsupported Platforms:** The following platforms are either known not to work, or they used to work in a fairly distant previous release. We include these here to let you know that these platforms could be supported if given some attention. | OS | Processor | Version | Reported | Remarks | | --- | --- | --- | --- | --- | | BeOS | x86 | 7.2 | Cyril Velter (`<[cyril.velter@libertysurf.fr](mailto:cyril.velter@libertysurf.fr) >`), 2001-11-29 | needs updates to semaphore code | | Linux | PlayStation 2 | 8.0.0 | Chris Mair (`<[list@1006.org](mailto:list@1006.org) >`), 2005-01-09 | requires \--disable-spinlocks (works, but slow) | | NetBSD | Alpha | 7.2 | Thomas Thai (`<[tom@minnesota.com](mailto:tom@minnesota.com) >`), 2001-11-20 | 1.5W | | NetBSD | MIPS | 7.2.1 | Warwick Hunter (`<[whunter@agile.tv](mailto:whunter@agile.tv) >`), 2002-06-13 | 1.5.3 | | NetBSD | PowerPC | 7.2 | Bill Studenmund (`<[wrstuden@netbsd.org](mailto:wrstuden@netbsd.org) >`), 2001-11-28 | 1.5 | | NetBSD | VAX | 7.1 | Tom I. Helbekkmo (`<[tih@kpnQwest.no](mailto:tih@kpnQwest.no) >`), 2001-03-30 | 1.5 | | QNX 4 RTOS | x86 | 7.2 | Bernd Tegge (`<[tegge@repas-aeg.de](mailto:tegge@repas-aeg.de) >`), 2001-12-10 | needs updates to semaphore code; see also doc/FAQ\_QNX4 | | QNX RTOS v6 | x86 | 7.2 | Igor Kovalenko (`<[Igor.Kovalenko@motorola.com](mailto:Igor.Kovalenko@motorola.com) >`), 2001-11-20 | patches available in archives, but too late for 7.2 | | SCO OpenServer | x86 | 7.3.1 | Shibashish Satpathy (`<[shib@postmark.net](mailto:shib@postmark.net) >`), 2002-12-11 | 5.0.4, gcc; see also doc/FAQ\_SCO | | SunOS 4 | Sparc | 7.2 | Tatsuo Ishii (`<[t-ishii@sra.co.jp](mailto:t-ishii@sra.co.jp) >`), 2001-12-04 | | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/8.1/install-post.html) | [Home](https://www.postgresql.org/docs/8.1/index.html) | [Next](https://www.postgresql.org/docs/8.1/install-win32.html) | | Post-Installation Setup | [Up](https://www.postgresql.org/docs/8.1/installation.html) | Client-Only Installation on Windows | --- # PostgreSQL: Documentation: 7.3: BKI Commands November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 7.3](https://www.postgresql.org/docs/7.3/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/bki-commands.html "PostgreSQL 18 - BKI Commands") ([18](https://www.postgresql.org/docs/18/bki-commands.html "PostgreSQL 18 - BKI Commands") ) / [17](https://www.postgresql.org/docs/17/bki-commands.html "PostgreSQL 17 - BKI Commands") / [16](https://www.postgresql.org/docs/16/bki-commands.html "PostgreSQL 16 - BKI Commands") / [15](https://www.postgresql.org/docs/15/bki-commands.html "PostgreSQL 15 - BKI Commands") / [14](https://www.postgresql.org/docs/14/bki-commands.html "PostgreSQL 14 - BKI Commands") Development Versions: [devel](https://www.postgresql.org/docs/devel/bki-commands.html "PostgreSQL devel - BKI Commands") Unsupported versions: [13](https://www.postgresql.org/docs/13/bki-commands.html "PostgreSQL 13 - BKI Commands") / [12](https://www.postgresql.org/docs/12/bki-commands.html "PostgreSQL 12 - BKI Commands") / [11](https://www.postgresql.org/docs/11/bki-commands.html "PostgreSQL 11 - BKI Commands") / [10](https://www.postgresql.org/docs/10/bki-commands.html "PostgreSQL 10 - BKI Commands") / [9.6](https://www.postgresql.org/docs/9.6/bki-commands.html "PostgreSQL 9.6 - BKI Commands") / [9.5](https://www.postgresql.org/docs/9.5/bki-commands.html "PostgreSQL 9.5 - BKI Commands") / [9.4](https://www.postgresql.org/docs/9.4/bki-commands.html "PostgreSQL 9.4 - BKI Commands") / [9.3](https://www.postgresql.org/docs/9.3/bki-commands.html "PostgreSQL 9.3 - BKI Commands") / [9.2](https://www.postgresql.org/docs/9.2/bki-commands.html "PostgreSQL 9.2 - BKI Commands") / [9.1](https://www.postgresql.org/docs/9.1/bki-commands.html "PostgreSQL 9.1 - BKI Commands") / [9.0](https://www.postgresql.org/docs/9.0/bki-commands.html "PostgreSQL 9.0 - BKI Commands") / [8.4](https://www.postgresql.org/docs/8.4/bki-commands.html "PostgreSQL 8.4 - BKI Commands") / [8.3](https://www.postgresql.org/docs/8.3/bki-commands.html "PostgreSQL 8.3 - BKI Commands") / [8.2](https://www.postgresql.org/docs/8.2/bki-commands.html "PostgreSQL 8.2 - BKI Commands") / [8.1](https://www.postgresql.org/docs/8.1/bki-commands.html "PostgreSQL 8.1 - BKI Commands") / [8.0](https://www.postgresql.org/docs/8.0/bki-commands.html "PostgreSQL 8.0 - BKI Commands") / [7.4](https://www.postgresql.org/docs/7.4/bki-commands.html "PostgreSQL 7.4 - BKI Commands") / [7.3](https://www.postgresql.org/docs/7.3/bki-commands.html "PostgreSQL 7.3 - BKI Commands") / [7.2](https://www.postgresql.org/docs/7.2/bki-commands.html "PostgreSQL 7.2 - BKI Commands") / [7.1](https://www.postgresql.org/docs/7.1/bki-commands.html "PostgreSQL 7.1 - BKI Commands") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/bki-commands.html "PostgreSQL - BKI Commands") version, or one of the other supported versions listed above instead. | PostgreSQL 7.3.21 Documentation | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.3/bki.html) | Chapter 6. BKI Backend Interface | [Next](https://www.postgresql.org/docs/7.3/bki-example.html) | * * * 6.2. BKI Commands ================= open tablename Open the table called tablename for further manipulation. close \[tablename\] Close the open table called tablename. It is an error if tablename is not already opened. If no tablename is given, then the currently open table is closed. create tablename (name1 = type1 \[, name2 = type2, ...\]) Create a table named tablename with the columns given in parentheses. The type is not necessarily the data type that the column will have in the SQL environment; that is determined by the pg\_attribute system catalog. The type here is essentially only used to allocate storage. The following types are allowed: bool, bytea, char (1 byte), name, int2, int2vector, int4, regproc, regclass, regtype, text, oid, tid, xid, cid, oidvector, smgr, \_int4 (array), \_aclitem (array). Array types can also be indicated by writing \[\] after the name of the element type. > **Note:** The table will only be created on disk, it will not automatically be registered in the system catalogs and will therefore not be accessible unless appropriate rows are inserted in pg\_class, pg\_attribute, etc. insert \[OID = oid\_value\] (value1 value2 ...) Insert a new row into the open table using value1, value2, etc., for its column values and oid\_value for its OID. If oid\_value is zero (0) or the clause is omitted, then the next available OID is used. NULL values can be specified using the special key word \_null\_. Values containing spaces must be double quoted. declare \[unique\] index indexname on tablename using amname (opclass1 name1 \[, ...\]) Create an index named indexname on the table named tablename using the amname access method. The fields to index are called name1, name2 etc., and the operator classes to use are opclass1, opclass2 etc., respectively. build indices Build the indices that have previously been declared. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.3/bki.html) | [Home](https://www.postgresql.org/docs/7.3/index.html) | [Next](https://www.postgresql.org/docs/7.3/bki-example.html) | | BKI Backend Interface | [Up](https://www.postgresql.org/docs/7.3/bki.html) | Example | --- # PostgreSQL: Documentation: 18: ALTER VIEW November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alterview.html "PostgreSQL 18 - ALTER VIEW") ([18](https://www.postgresql.org/docs/18/sql-alterview.html "PostgreSQL 18 - ALTER VIEW") ) / [17](https://www.postgresql.org/docs/17/sql-alterview.html "PostgreSQL 17 - ALTER VIEW") / [16](https://www.postgresql.org/docs/16/sql-alterview.html "PostgreSQL 16 - ALTER VIEW") / [15](https://www.postgresql.org/docs/15/sql-alterview.html "PostgreSQL 15 - ALTER VIEW") / [14](https://www.postgresql.org/docs/14/sql-alterview.html "PostgreSQL 14 - ALTER VIEW") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alterview.html "PostgreSQL devel - ALTER VIEW") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alterview.html "PostgreSQL 13 - ALTER VIEW") / [12](https://www.postgresql.org/docs/12/sql-alterview.html "PostgreSQL 12 - ALTER VIEW") / [11](https://www.postgresql.org/docs/11/sql-alterview.html "PostgreSQL 11 - ALTER VIEW") / [10](https://www.postgresql.org/docs/10/sql-alterview.html "PostgreSQL 10 - ALTER VIEW") / [9.6](https://www.postgresql.org/docs/9.6/sql-alterview.html "PostgreSQL 9.6 - ALTER VIEW") / [9.5](https://www.postgresql.org/docs/9.5/sql-alterview.html "PostgreSQL 9.5 - ALTER VIEW") / [9.4](https://www.postgresql.org/docs/9.4/sql-alterview.html "PostgreSQL 9.4 - ALTER VIEW") / [9.3](https://www.postgresql.org/docs/9.3/sql-alterview.html "PostgreSQL 9.3 - ALTER VIEW") / [9.2](https://www.postgresql.org/docs/9.2/sql-alterview.html "PostgreSQL 9.2 - ALTER VIEW") / [9.1](https://www.postgresql.org/docs/9.1/sql-alterview.html "PostgreSQL 9.1 - ALTER VIEW") / [9.0](https://www.postgresql.org/docs/9.0/sql-alterview.html "PostgreSQL 9.0 - ALTER VIEW") / [8.4](https://www.postgresql.org/docs/8.4/sql-alterview.html "PostgreSQL 8.4 - ALTER VIEW") / [8.3](https://www.postgresql.org/docs/8.3/sql-alterview.html "PostgreSQL 8.3 - ALTER VIEW") | ALTER VIEW | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-alterusermapping.html "ALTER USER MAPPING") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-analyze.html "ANALYZE") | * * * ALTER VIEW ---------- ALTER VIEW — change the definition of a view Synopsis -------- ALTER VIEW \[ IF EXISTS \] _`name`_ ALTER \[ COLUMN \] _`column_name`_ SET DEFAULT _`expression`_ ALTER VIEW \[ IF EXISTS \] _`name`_ ALTER \[ COLUMN \] _`column_name`_ DROP DEFAULT ALTER VIEW \[ IF EXISTS \] _`name`_ OWNER TO { _`new_owner`_ | CURRENT\_ROLE | CURRENT\_USER | SESSION\_USER } ALTER VIEW \[ IF EXISTS \] _`name`_ RENAME \[ COLUMN \] _`column_name`_ TO _`new_column_name`_ ALTER VIEW \[ IF EXISTS \] _`name`_ RENAME TO _`new_name`_ ALTER VIEW \[ IF EXISTS \] _`name`_ SET SCHEMA _`new_schema`_ ALTER VIEW \[ IF EXISTS \] _`name`_ SET ( _`view_option_name`_ \[= _`view_option_value`_\] \[, ... \] ) ALTER VIEW \[ IF EXISTS \] _`name`_ RESET ( _`view_option_name`_ \[, ... \] ) Description ----------- `ALTER VIEW` changes various auxiliary properties of a view. (If you want to modify the view's defining query, use `CREATE OR REPLACE VIEW`.) You must own the view to use `ALTER VIEW`. To change a view's schema, you must also have `CREATE` privilege on the new schema. To alter the owner, you must be able to `SET ROLE` to the new owning role, and that role must have `CREATE` privilege on the view's schema. (These restrictions enforce that altering the owner doesn't do anything you couldn't do by dropping and recreating the view. However, a superuser can alter ownership of any view anyway.) Parameters ---------- _`name`_ The name (optionally schema-qualified) of an existing view. _`column_name`_ Name of an existing column. _`new_column_name`_ New name for an existing column. `IF EXISTS` Do not throw an error if the view does not exist. A notice is issued in this case. `SET`/`DROP DEFAULT` These forms set or remove the default value for a column. A view column's default value is substituted into any `INSERT` or `UPDATE` command whose target is the view, before applying any rules or triggers for the view. The view's default will therefore take precedence over any default values from underlying relations. _`new_owner`_ The user name of the new owner of the view. _`new_name`_ The new name for the view. _`new_schema`_ The new schema for the view. ``SET ( _`view_option_name`_ [= _`view_option_value`_] [, ... ] )`` ``RESET ( _`view_option_name`_ [, ... ] )`` Sets or resets a view option. Currently supported options are: `check_option` (`enum`) Changes the check option of the view. The value must be `local` or `cascaded`. `security_barrier` (`boolean`) Changes the security-barrier property of the view. The value must be a Boolean value, such as `true` or `false`. `security_invoker` (`boolean`) Changes the security-invoker property of the view. The value must be a Boolean value, such as `true` or `false`. Notes ----- For historical reasons, `ALTER TABLE` can be used with views too; but the only variants of `ALTER TABLE` that are allowed with views are equivalent to the ones shown above. Examples -------- To rename the view `foo` to `bar`: ALTER VIEW foo RENAME TO bar; To attach a default column value to an updatable view: CREATE TABLE base\_table (id int, ts timestamptz); CREATE VIEW a\_view AS SELECT \* FROM base\_table; ALTER VIEW a\_view ALTER COLUMN ts SET DEFAULT now(); INSERT INTO base\_table(id) VALUES(1); -- ts will receive a NULL INSERT INTO a\_view(id) VALUES(2); -- ts will receive the current time Compatibility ------------- `ALTER VIEW` is a PostgreSQL extension of the SQL standard. See Also -------- [CREATE VIEW](https://www.postgresql.org/docs/current/sql-createview.html "CREATE VIEW") , [DROP VIEW](https://www.postgresql.org/docs/current/sql-dropview.html "DROP VIEW") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-alterusermapping.html "ALTER USER MAPPING") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-analyze.html "ANALYZE") | | ALTER USER MAPPING | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | ANALYZE | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-alterview.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 18: ALTER OPERATOR FAMILY November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-alteropfamily.html "PostgreSQL 18 - ALTER OPERATOR FAMILY") ([18](https://www.postgresql.org/docs/18/sql-alteropfamily.html "PostgreSQL 18 - ALTER OPERATOR FAMILY") ) / [17](https://www.postgresql.org/docs/17/sql-alteropfamily.html "PostgreSQL 17 - ALTER OPERATOR FAMILY") / [16](https://www.postgresql.org/docs/16/sql-alteropfamily.html "PostgreSQL 16 - ALTER OPERATOR FAMILY") / [15](https://www.postgresql.org/docs/15/sql-alteropfamily.html "PostgreSQL 15 - ALTER OPERATOR FAMILY") / [14](https://www.postgresql.org/docs/14/sql-alteropfamily.html "PostgreSQL 14 - ALTER OPERATOR FAMILY") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-alteropfamily.html "PostgreSQL devel - ALTER OPERATOR FAMILY") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-alteropfamily.html "PostgreSQL 13 - ALTER OPERATOR FAMILY") / [12](https://www.postgresql.org/docs/12/sql-alteropfamily.html "PostgreSQL 12 - ALTER OPERATOR FAMILY") / [11](https://www.postgresql.org/docs/11/sql-alteropfamily.html "PostgreSQL 11 - ALTER OPERATOR FAMILY") / [10](https://www.postgresql.org/docs/10/sql-alteropfamily.html "PostgreSQL 10 - ALTER OPERATOR FAMILY") / [9.6](https://www.postgresql.org/docs/9.6/sql-alteropfamily.html "PostgreSQL 9.6 - ALTER OPERATOR FAMILY") / [9.5](https://www.postgresql.org/docs/9.5/sql-alteropfamily.html "PostgreSQL 9.5 - ALTER OPERATOR FAMILY") / [9.4](https://www.postgresql.org/docs/9.4/sql-alteropfamily.html "PostgreSQL 9.4 - ALTER OPERATOR FAMILY") / [9.3](https://www.postgresql.org/docs/9.3/sql-alteropfamily.html "PostgreSQL 9.3 - ALTER OPERATOR FAMILY") / [9.2](https://www.postgresql.org/docs/9.2/sql-alteropfamily.html "PostgreSQL 9.2 - ALTER OPERATOR FAMILY") / [9.1](https://www.postgresql.org/docs/9.1/sql-alteropfamily.html "PostgreSQL 9.1 - ALTER OPERATOR FAMILY") / [9.0](https://www.postgresql.org/docs/9.0/sql-alteropfamily.html "PostgreSQL 9.0 - ALTER OPERATOR FAMILY") / [8.4](https://www.postgresql.org/docs/8.4/sql-alteropfamily.html "PostgreSQL 8.4 - ALTER OPERATOR FAMILY") / [8.3](https://www.postgresql.org/docs/8.3/sql-alteropfamily.html "PostgreSQL 8.3 - ALTER OPERATOR FAMILY") | ALTER OPERATOR FAMILY | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-alteropclass.html "ALTER OPERATOR CLASS") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | SQL Commands | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/sql-alterpolicy.html "ALTER POLICY") | * * * ALTER OPERATOR FAMILY --------------------- ALTER OPERATOR FAMILY — change the definition of an operator family Synopsis -------- ALTER OPERATOR FAMILY _`name`_ USING _`index_method`_ ADD { OPERATOR _`strategy_number`_ _`operator_name`_ ( _`op_type`_, _`op_type`_ ) \[ FOR SEARCH | FOR ORDER BY _`sort_family_name`_ \] | FUNCTION _`support_number`_ \[ ( _`op_type`_ \[ , _`op_type`_ \] ) \] _`function_name`_ \[ ( _`argument_type`_ \[, ...\] ) \] } \[, ... \] ALTER OPERATOR FAMILY _`name`_ USING _`index_method`_ DROP { OPERATOR _`strategy_number`_ ( _`op_type`_ \[ , _`op_type`_ \] ) | FUNCTION _`support_number`_ ( _`op_type`_ \[ , _`op_type`_ \] ) } \[, ... \] ALTER OPERATOR FAMILY _`name`_ USING _`index_method`_ RENAME TO _`new_name`_ ALTER OPERATOR FAMILY _`name`_ USING _`index_method`_ OWNER TO { _`new_owner`_ | CURRENT\_ROLE | CURRENT\_USER | SESSION\_USER } ALTER OPERATOR FAMILY _`name`_ USING _`index_method`_ SET SCHEMA _`new_schema`_ Description ----------- `ALTER OPERATOR FAMILY` changes the definition of an operator family. You can add operators and support functions to the family, remove them from the family, or change the family's name or owner. When operators and support functions are added to a family with `ALTER OPERATOR FAMILY`, they are not part of any specific operator class within the family, but are just “loose” within the family. This indicates that these operators and functions are compatible with the family's semantics, but are not required for correct functioning of any specific index. (Operators and functions that are so required should be declared as part of an operator class, instead; see [CREATE OPERATOR CLASS](https://www.postgresql.org/docs/current/sql-createopclass.html "CREATE OPERATOR CLASS") .) PostgreSQL will allow loose members of a family to be dropped from the family at any time, but members of an operator class cannot be dropped without dropping the whole class and any indexes that depend on it. Typically, single-data-type operators and functions are part of operator classes because they are needed to support an index on that specific data type, while cross-data-type operators and functions are made loose members of the family. You must be a superuser to use `ALTER OPERATOR FAMILY`. (This restriction is made because an erroneous operator family definition could confuse or even crash the server.) `ALTER OPERATOR FAMILY` does not presently check whether the operator family definition includes all the operators and functions required by the index method, nor whether the operators and functions form a self-consistent set. It is the user's responsibility to define a valid operator family. Refer to [Section 36.16](https://www.postgresql.org/docs/current/xindex.html "36.16. Interfacing Extensions to Indexes") for further information. Parameters ---------- _`name`_ The name (optionally schema-qualified) of an existing operator family. _`index_method`_ The name of the index method this operator family is for. _`strategy_number`_ The index method's strategy number for an operator associated with the operator family. _`operator_name`_ The name (optionally schema-qualified) of an operator associated with the operator family. _`op_type`_ In an `OPERATOR` clause, the operand data type(s) of the operator, or `NONE` to signify a prefix operator. Unlike the comparable syntax in `CREATE OPERATOR CLASS`, the operand data types must always be specified. In an `ADD FUNCTION` clause, the operand data type(s) the function is intended to support, if different from the input data type(s) of the function. For B-tree comparison functions and hash functions it is not necessary to specify _`op_type`_ since the function's input data type(s) are always the correct ones to use. For B-tree sort support functions, B-Tree equal image functions, and all functions in GiST, SP-GiST and GIN operator classes, it is necessary to specify the operand data type(s) the function is to be used with. In a `DROP FUNCTION` clause, the operand data type(s) the function is intended to support must be specified. _`sort_family_name`_ The name (optionally schema-qualified) of an existing `btree` operator family that describes the sort ordering associated with an ordering operator. If neither `FOR SEARCH` nor `FOR ORDER BY` is specified, `FOR SEARCH` is the default. _`support_number`_ The index method's support function number for a function associated with the operator family. _`function_name`_ The name (optionally schema-qualified) of a function that is an index method support function for the operator family. If no argument list is specified, the name must be unique in its schema. _`argument_type`_ The parameter data type(s) of the function. _`new_name`_ The new name of the operator family. _`new_owner`_ The new owner of the operator family. _`new_schema`_ The new schema for the operator family. The `OPERATOR` and `FUNCTION` clauses can appear in any order. Notes ----- Notice that the `DROP` syntax only specifies the “slot” in the operator family, by strategy or support number and input data type(s). The name of the operator or function occupying the slot is not mentioned. Also, for `DROP FUNCTION` the type(s) to specify are the input data type(s) the function is intended to support; for GiST, SP-GiST and GIN indexes this might have nothing to do with the actual input argument types of the function. Because the index machinery does not check access permissions on functions before using them, including a function or operator in an operator family is tantamount to granting public execute permission on it. This is usually not an issue for the sorts of functions that are useful in an operator family. The operators should not be defined by SQL functions. An SQL function is likely to be inlined into the calling query, which will prevent the optimizer from recognizing that the query matches an index. Examples -------- The following example command adds cross-data-type operators and support functions to an operator family that already contains B-tree operator classes for data types `int4` and `int2`. ALTER OPERATOR FAMILY integer\_ops USING btree ADD -- int4 vs int2 OPERATOR 1 < (int4, int2) , OPERATOR 2 <= (int4, int2) , OPERATOR 3 = (int4, int2) , OPERATOR 4 >= (int4, int2) , OPERATOR 5 > (int4, int2) , FUNCTION 1 btint42cmp(int4, int2) , -- int2 vs int4 OPERATOR 1 < (int2, int4) , OPERATOR 2 <= (int2, int4) , OPERATOR 3 = (int2, int4) , OPERATOR 4 >= (int2, int4) , OPERATOR 5 > (int2, int4) , FUNCTION 1 btint24cmp(int2, int4) ; To remove these entries again: ALTER OPERATOR FAMILY integer\_ops USING btree DROP -- int4 vs int2 OPERATOR 1 (int4, int2) , OPERATOR 2 (int4, int2) , OPERATOR 3 (int4, int2) , OPERATOR 4 (int4, int2) , OPERATOR 5 (int4, int2) , FUNCTION 1 (int4, int2) , -- int2 vs int4 OPERATOR 1 (int2, int4) , OPERATOR 2 (int2, int4) , OPERATOR 3 (int2, int4) , OPERATOR 4 (int2, int4) , OPERATOR 5 (int2, int4) , FUNCTION 1 (int2, int4) ; Compatibility ------------- There is no `ALTER OPERATOR FAMILY` statement in the SQL standard. See Also -------- [CREATE OPERATOR FAMILY](https://www.postgresql.org/docs/current/sql-createopfamily.html "CREATE OPERATOR FAMILY") , [DROP OPERATOR FAMILY](https://www.postgresql.org/docs/current/sql-dropopfamily.html "DROP OPERATOR FAMILY") , [CREATE OPERATOR CLASS](https://www.postgresql.org/docs/current/sql-createopclass.html "CREATE OPERATOR CLASS") , [ALTER OPERATOR CLASS](https://www.postgresql.org/docs/current/sql-alteropclass.html "ALTER OPERATOR CLASS") , [DROP OPERATOR CLASS](https://www.postgresql.org/docs/current/sql-dropopclass.html "DROP OPERATOR CLASS") * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/sql-alteropclass.html "ALTER OPERATOR CLASS") | [Up](https://www.postgresql.org/docs/current/sql-commands.html "SQL Commands") | [Next](https://www.postgresql.org/docs/current/sql-alterpolicy.html "ALTER POLICY") | | ALTER OPERATOR CLASS | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | ALTER POLICY | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/sql-alteropfamily.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 7.3: Dependency Tracking November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 7.3](https://www.postgresql.org/docs/7.3/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/ddl-depend.html "PostgreSQL 18 - Dependency Tracking") ([18](https://www.postgresql.org/docs/18/ddl-depend.html "PostgreSQL 18 - Dependency Tracking") ) / [17](https://www.postgresql.org/docs/17/ddl-depend.html "PostgreSQL 17 - Dependency Tracking") / [16](https://www.postgresql.org/docs/16/ddl-depend.html "PostgreSQL 16 - Dependency Tracking") / [15](https://www.postgresql.org/docs/15/ddl-depend.html "PostgreSQL 15 - Dependency Tracking") / [14](https://www.postgresql.org/docs/14/ddl-depend.html "PostgreSQL 14 - Dependency Tracking") Development Versions: [devel](https://www.postgresql.org/docs/devel/ddl-depend.html "PostgreSQL devel - Dependency Tracking") Unsupported versions: [13](https://www.postgresql.org/docs/13/ddl-depend.html "PostgreSQL 13 - Dependency Tracking") / [12](https://www.postgresql.org/docs/12/ddl-depend.html "PostgreSQL 12 - Dependency Tracking") / [11](https://www.postgresql.org/docs/11/ddl-depend.html "PostgreSQL 11 - Dependency Tracking") / [10](https://www.postgresql.org/docs/10/ddl-depend.html "PostgreSQL 10 - Dependency Tracking") / [9.6](https://www.postgresql.org/docs/9.6/ddl-depend.html "PostgreSQL 9.6 - Dependency Tracking") / [9.5](https://www.postgresql.org/docs/9.5/ddl-depend.html "PostgreSQL 9.5 - Dependency Tracking") / [9.4](https://www.postgresql.org/docs/9.4/ddl-depend.html "PostgreSQL 9.4 - Dependency Tracking") / [9.3](https://www.postgresql.org/docs/9.3/ddl-depend.html "PostgreSQL 9.3 - Dependency Tracking") / [9.2](https://www.postgresql.org/docs/9.2/ddl-depend.html "PostgreSQL 9.2 - Dependency Tracking") / [9.1](https://www.postgresql.org/docs/9.1/ddl-depend.html "PostgreSQL 9.1 - Dependency Tracking") / [9.0](https://www.postgresql.org/docs/9.0/ddl-depend.html "PostgreSQL 9.0 - Dependency Tracking") / [8.4](https://www.postgresql.org/docs/8.4/ddl-depend.html "PostgreSQL 8.4 - Dependency Tracking") / [8.3](https://www.postgresql.org/docs/8.3/ddl-depend.html "PostgreSQL 8.3 - Dependency Tracking") / [8.2](https://www.postgresql.org/docs/8.2/ddl-depend.html "PostgreSQL 8.2 - Dependency Tracking") / [8.1](https://www.postgresql.org/docs/8.1/ddl-depend.html "PostgreSQL 8.1 - Dependency Tracking") / [8.0](https://www.postgresql.org/docs/8.0/ddl-depend.html "PostgreSQL 8.0 - Dependency Tracking") / [7.4](https://www.postgresql.org/docs/7.4/ddl-depend.html "PostgreSQL 7.4 - Dependency Tracking") / [7.3](https://www.postgresql.org/docs/7.3/ddl-depend.html "PostgreSQL 7.3 - Dependency Tracking") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/ddl-depend.html "PostgreSQL - Dependency Tracking") version, or one of the other supported versions listed above instead. | PostgreSQL 7.3.21 Documentation | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.3/ddl-others.html) | Chapter 2. Data Definition | [Next](https://www.postgresql.org/docs/7.3/dml.html) | * * * 2.10. Dependency Tracking ========================= When you create complex database structures involving many tables with foreign key constraints, views, triggers, functions, etc. you will implicitly create a net of dependencies between the objects. For instance, a table with a foreign key constraint depends on the table it references. To ensure the integrity of the entire database structure, PostgreSQL makes sure that you cannot drop objects that other objects still depend on. For example, attempting to drop the products table we had considered in [Section 2.4.5](https://www.postgresql.org/docs/7.3/ddl-constraints.html#DDL-CONSTRAINTS-FK) , with the orders table depending on it, would result in an error message such as this: DROP TABLE products; NOTICE: constraint $1 on table orders depends on table products ERROR: Cannot drop table products because other objects depend on it Use DROP ... CASCADE to drop the dependent objects too The error message contains a useful hint: If you don't want to bother deleting all the dependent objects individually, you can run DROP TABLE products CASCADE; and all the dependent objects will be removed. In this case, it doesn't remove the orders table, it only removes the foreign key constraint. (If you want to check what DROP ... CASCADE will do, run DROP without CASCADE and read the NOTICE messages.) All drop commands in PostgreSQL support specifying CASCADE. Of course, the nature of the possible dependencies varies with the type of the object. You can also write RESTRICT instead of CASCADE to get the default behavior which is to restrict drops of objects that other objects depend on. > **Note:** According to the SQL standard, specifying either RESTRICT or CASCADE is required. No database system actually implements it that way, but whether the default behavior is RESTRICT or CASCADE varies across systems. > **Note:** Foreign key constraint dependencies and serial column dependencies from PostgreSQL versions prior to 7.3 are not maintained or created during the upgrade process. All other dependency types will be properly created during an upgrade. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.3/ddl-others.html) | [Home](https://www.postgresql.org/docs/7.3/index.html) | [Next](https://www.postgresql.org/docs/7.3/dml.html) | | Other Database Objects | [Up](https://www.postgresql.org/docs/7.3/ddl.html) | Data Manipulation | --- # PostgreSQL: Documentation: 7.2: Controlling the Planner with Explicit JOINs November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 7.2](https://www.postgresql.org/docs/7.2/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/explicit-joins.html "PostgreSQL 18 - Controlling the Planner with Explicit JOINs") ([18](https://www.postgresql.org/docs/18/explicit-joins.html "PostgreSQL 18 - Controlling the Planner with Explicit JOINs") ) / [17](https://www.postgresql.org/docs/17/explicit-joins.html "PostgreSQL 17 - Controlling the Planner with Explicit JOINs") / [16](https://www.postgresql.org/docs/16/explicit-joins.html "PostgreSQL 16 - Controlling the Planner with Explicit JOINs") / [15](https://www.postgresql.org/docs/15/explicit-joins.html "PostgreSQL 15 - Controlling the Planner with Explicit JOINs") / [14](https://www.postgresql.org/docs/14/explicit-joins.html "PostgreSQL 14 - Controlling the Planner with Explicit JOINs") Development Versions: [devel](https://www.postgresql.org/docs/devel/explicit-joins.html "PostgreSQL devel - Controlling the Planner with Explicit JOINs") Unsupported versions: [13](https://www.postgresql.org/docs/13/explicit-joins.html "PostgreSQL 13 - Controlling the Planner with Explicit JOINs") / [12](https://www.postgresql.org/docs/12/explicit-joins.html "PostgreSQL 12 - Controlling the Planner with Explicit JOINs") / [11](https://www.postgresql.org/docs/11/explicit-joins.html "PostgreSQL 11 - Controlling the Planner with Explicit JOINs") / [10](https://www.postgresql.org/docs/10/explicit-joins.html "PostgreSQL 10 - Controlling the Planner with Explicit JOINs") / [9.6](https://www.postgresql.org/docs/9.6/explicit-joins.html "PostgreSQL 9.6 - Controlling the Planner with Explicit JOINs") / [9.5](https://www.postgresql.org/docs/9.5/explicit-joins.html "PostgreSQL 9.5 - Controlling the Planner with Explicit JOINs") / [9.4](https://www.postgresql.org/docs/9.4/explicit-joins.html "PostgreSQL 9.4 - Controlling the Planner with Explicit JOINs") / [9.3](https://www.postgresql.org/docs/9.3/explicit-joins.html "PostgreSQL 9.3 - Controlling the Planner with Explicit JOINs") / [9.2](https://www.postgresql.org/docs/9.2/explicit-joins.html "PostgreSQL 9.2 - Controlling the Planner with Explicit JOINs") / [9.1](https://www.postgresql.org/docs/9.1/explicit-joins.html "PostgreSQL 9.1 - Controlling the Planner with Explicit JOINs") / [9.0](https://www.postgresql.org/docs/9.0/explicit-joins.html "PostgreSQL 9.0 - Controlling the Planner with Explicit JOINs") / [8.4](https://www.postgresql.org/docs/8.4/explicit-joins.html "PostgreSQL 8.4 - Controlling the Planner with Explicit JOINs") / [8.3](https://www.postgresql.org/docs/8.3/explicit-joins.html "PostgreSQL 8.3 - Controlling the Planner with Explicit JOINs") / [8.2](https://www.postgresql.org/docs/8.2/explicit-joins.html "PostgreSQL 8.2 - Controlling the Planner with Explicit JOINs") / [8.1](https://www.postgresql.org/docs/8.1/explicit-joins.html "PostgreSQL 8.1 - Controlling the Planner with Explicit JOINs") / [8.0](https://www.postgresql.org/docs/8.0/explicit-joins.html "PostgreSQL 8.0 - Controlling the Planner with Explicit JOINs") / [7.4](https://www.postgresql.org/docs/7.4/explicit-joins.html "PostgreSQL 7.4 - Controlling the Planner with Explicit JOINs") / [7.3](https://www.postgresql.org/docs/7.3/explicit-joins.html "PostgreSQL 7.3 - Controlling the Planner with Explicit JOINs") / [7.2](https://www.postgresql.org/docs/7.2/explicit-joins.html "PostgreSQL 7.2 - Controlling the Planner with Explicit JOINs") / [7.1](https://www.postgresql.org/docs/7.1/explicit-joins.html "PostgreSQL 7.1 - Controlling the Planner with Explicit JOINs") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/explicit-joins.html "PostgreSQL - Controlling the Planner with Explicit JOINs") version, or one of the other supported versions listed above instead. | PostgreSQL 7.2.8 Documentation | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.2/planner-stats.html) | Chapter 11. Performance Tips | [Next](https://www.postgresql.org/docs/7.2/populate.html) | * * * 11.3. Controlling the Planner with Explicit JOINs ================================================= Beginning with PostgreSQL 7.1 it is possible to control the query planner to some extent by using explicit JOIN syntax. To see why this matters, we first need some background. In a simple join query, such as SELECT \* FROM a,b,c WHERE a.id = b.id AND b.ref = c.id; the planner is free to join the given tables in any order. For example, it could generate a query plan that joins A to B, using the WHERE clause a.id = b.id, and then joins C to this joined table, using the other WHERE clause. Or it could join B to C and then join A to that result. Or it could join A to C and then join them with B --- but that would be inefficient, since the full Cartesian product of A and C would have to be formed, there being no applicable WHERE clause to allow optimization of the join. (All joins in the PostgreSQL executor happen between two input tables, so it's necessary to build up the result in one or another of these fashions.) The important point is that these different join possibilities give semantically equivalent results but may have hugely different execution costs. Therefore, the planner will explore all of them to try to find the most efficient query plan. When a query only involves two or three tables, there aren't many join orders to worry about. But the number of possible join orders grows exponentially as the number of tables expands. Beyond ten or so input tables it's no longer practical to do an exhaustive search of all the possibilities, and even for six or seven tables planning may take an annoyingly long time. When there are too many input tables, the PostgreSQL planner will switch from exhaustive search to a _genetic_ probabilistic search through a limited number of possibilities. (The switch-over threshold is set by the `GEQO_THRESHOLD` run-time parameter described in the _Administrator's Guide_.) The genetic search takes less time, but it won't necessarily find the best possible plan. When the query involves outer joins, the planner has much less freedom than it does for plain (inner) joins. For example, consider SELECT \* FROM a LEFT JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id); Although this query's restrictions are superficially similar to the previous example, the semantics are different because a row must be emitted for each row of A that has no matching row in the join of B and C. Therefore the planner has no choice of join order here: it must join B to C and then join A to that result. Accordingly, this query takes less time to plan than the previous query. In PostgreSQL 7.1, the planner treats all explicit JOIN syntaxes as constraining the join order, even though it is not logically necessary to make such a constraint for inner joins. Therefore, although all of these queries give the same result: SELECT \* FROM a,b,c WHERE a.id = b.id AND b.ref = c.id; SELECT \* FROM a CROSS JOIN b CROSS JOIN c WHERE a.id = b.id AND b.ref = c.id; SELECT \* FROM a JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id); the second and third take less time to plan than the first. This effect is not worth worrying about for only three tables, but it can be a lifesaver with many tables. You do not need to constrain the join order completely in order to cut search time, because it's OK to use JOIN operators in a plain FROM list. For example, SELECT \* FROM a CROSS JOIN b, c, d, e WHERE ...; forces the planner to join A to B before joining them to other tables, but doesn't constrain its choices otherwise. In this example, the number of possible join orders is reduced by a factor of 5. If you have a mix of outer and inner joins in a complex query, you might not want to constrain the planner's search for a good ordering of inner joins inside an outer join. You can't do that directly in the JOIN syntax, but you can get around the syntactic limitation by using subselects. For example, SELECT \* FROM d LEFT JOIN (SELECT \* FROM a, b, c WHERE ...) AS ss ON (...); Here, joining D must be the last step in the query plan, but the planner is free to consider various join orders for A,B,C. Constraining the planner's search in this way is a useful technique both for reducing planning time and for directing the planner to a good query plan. If the planner chooses a bad join order by default, you can force it to choose a better order via JOIN syntax --- assuming that you know of a better order, that is. Experimentation is recommended. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.2/planner-stats.html) | [Home](https://www.postgresql.org/docs/7.2/index.html) | [Next](https://www.postgresql.org/docs/7.2/populate.html) | | Statistics used by the Planner | [Up](https://www.postgresql.org/docs/7.2/performance-tips.html) | Populating a Database | --- # PostgreSQL: Documentation: 7.2: BKI Backend Interface November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 7.2](https://www.postgresql.org/docs/7.2/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/bki.html "PostgreSQL 18 - BKI Backend Interface") ([18](https://www.postgresql.org/docs/18/bki.html "PostgreSQL 18 - BKI Backend Interface") ) / [17](https://www.postgresql.org/docs/17/bki.html "PostgreSQL 17 - BKI Backend Interface") / [16](https://www.postgresql.org/docs/16/bki.html "PostgreSQL 16 - BKI Backend Interface") / [15](https://www.postgresql.org/docs/15/bki.html "PostgreSQL 15 - BKI Backend Interface") / [14](https://www.postgresql.org/docs/14/bki.html "PostgreSQL 14 - BKI Backend Interface") Development Versions: [devel](https://www.postgresql.org/docs/devel/bki.html "PostgreSQL devel - BKI Backend Interface") Unsupported versions: [13](https://www.postgresql.org/docs/13/bki.html "PostgreSQL 13 - BKI Backend Interface") / [12](https://www.postgresql.org/docs/12/bki.html "PostgreSQL 12 - BKI Backend Interface") / [11](https://www.postgresql.org/docs/11/bki.html "PostgreSQL 11 - BKI Backend Interface") / [10](https://www.postgresql.org/docs/10/bki.html "PostgreSQL 10 - BKI Backend Interface") / [9.6](https://www.postgresql.org/docs/9.6/bki.html "PostgreSQL 9.6 - BKI Backend Interface") / [9.5](https://www.postgresql.org/docs/9.5/bki.html "PostgreSQL 9.5 - BKI Backend Interface") / [9.4](https://www.postgresql.org/docs/9.4/bki.html "PostgreSQL 9.4 - BKI Backend Interface") / [9.3](https://www.postgresql.org/docs/9.3/bki.html "PostgreSQL 9.3 - BKI Backend Interface") / [9.2](https://www.postgresql.org/docs/9.2/bki.html "PostgreSQL 9.2 - BKI Backend Interface") / [9.1](https://www.postgresql.org/docs/9.1/bki.html "PostgreSQL 9.1 - BKI Backend Interface") / [9.0](https://www.postgresql.org/docs/9.0/bki.html "PostgreSQL 9.0 - BKI Backend Interface") / [8.4](https://www.postgresql.org/docs/8.4/bki.html "PostgreSQL 8.4 - BKI Backend Interface") / [8.3](https://www.postgresql.org/docs/8.3/bki.html "PostgreSQL 8.3 - BKI Backend Interface") / [8.2](https://www.postgresql.org/docs/8.2/bki.html "PostgreSQL 8.2 - BKI Backend Interface") / [8.1](https://www.postgresql.org/docs/8.1/bki.html "PostgreSQL 8.1 - BKI Backend Interface") / [8.0](https://www.postgresql.org/docs/8.0/bki.html "PostgreSQL 8.0 - BKI Backend Interface") / [7.4](https://www.postgresql.org/docs/7.4/bki.html "PostgreSQL 7.4 - BKI Backend Interface") / [7.3](https://www.postgresql.org/docs/7.3/bki.html "PostgreSQL 7.3 - BKI Backend Interface") / [7.2](https://www.postgresql.org/docs/7.2/bki.html "PostgreSQL 7.2 - BKI Backend Interface") / [7.1](https://www.postgresql.org/docs/7.1/bki.html "PostgreSQL 7.1 - BKI Backend Interface") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/bki.html "PostgreSQL - BKI Backend Interface") version, or one of the other supported versions listed above instead. | PostgreSQL 7.2.8 Documentation | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.2/compiler.html) | | [Next](https://www.postgresql.org/docs/7.2/bki-commands.html) | * * * Chapter 6. BKI Backend Interface ================================ Table of Contents 6.1. [BKI File Format](https://www.postgresql.org/docs/7.2/bki.html#BKI-FORMAT) 6.2. [BKI Commands](https://www.postgresql.org/docs/7.2/bki-commands.html) 6.3. [Example](https://www.postgresql.org/docs/7.2/bki-example.html) Backend Interface (BKI) files are scripts in a special language that are input to the PostgreSQL backend running in the special "bootstrap" mode that allows it to perform database functions without a database system already existing. BKI files can therefore be used to create the database system in the first place. (And they are probably not useful for anything else.) initdb uses a BKI file to do part of its job when creating a new database cluster. The input file used by initdb is created as part of building and installing PostgreSQL by a program named genbki.sh from some specially formatted C header files in the source tree. The created BKI file is called postgres.bki and is normally installed in the share subdirectory of the installation tree. Related information may be found in the documentation for initdb. 6.1. BKI File Format ==================== This section describes how the PostgreSQL backend interprets BKI files. This description will be easier to understand if the postgres.bki file is at hand as an example. You should also study the source code of initdb to get an idea of how the backend is invoked. BKI input consists of a sequence of commands. Commands are made up of a number of tokens, depending on the syntax of the command. Tokens are usually separated by whitespace, but need not be if there is no ambiguity. There is no special command separator; the next token that syntactically cannot belong to the preceding command starts a new one. (Usually you would put a new command on a new line, for clarity.) Tokens can be certain key words, special characters (parentheses, commas, etc.), numbers, or double-quoted strings. Everything is case sensitive. Lines starting with a # are ignored. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.2/compiler.html) | [Home](https://www.postgresql.org/docs/7.2/index.html) | [Next](https://www.postgresql.org/docs/7.2/bki-commands.html) | | gcc Default Optimizations | [Up](https://www.postgresql.org/docs/7.2/developer.html) | BKI Commands | --- # PostgreSQL: Documentation: 9.0: PL/Perl Under the Hood November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 9.0](https://www.postgresql.org/docs/9.0/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/plperl-under-the-hood.html "PostgreSQL 18 - PL/Perl Under the Hood") ([18](https://www.postgresql.org/docs/18/plperl-under-the-hood.html "PostgreSQL 18 - PL/Perl Under the Hood") ) / [17](https://www.postgresql.org/docs/17/plperl-under-the-hood.html "PostgreSQL 17 - PL/Perl Under the Hood") / [16](https://www.postgresql.org/docs/16/plperl-under-the-hood.html "PostgreSQL 16 - PL/Perl Under the Hood") / [15](https://www.postgresql.org/docs/15/plperl-under-the-hood.html "PostgreSQL 15 - PL/Perl Under the Hood") / [14](https://www.postgresql.org/docs/14/plperl-under-the-hood.html "PostgreSQL 14 - PL/Perl Under the Hood") Development Versions: [devel](https://www.postgresql.org/docs/devel/plperl-under-the-hood.html "PostgreSQL devel - PL/Perl Under the Hood") Unsupported versions: [13](https://www.postgresql.org/docs/13/plperl-under-the-hood.html "PostgreSQL 13 - PL/Perl Under the Hood") / [12](https://www.postgresql.org/docs/12/plperl-under-the-hood.html "PostgreSQL 12 - PL/Perl Under the Hood") / [11](https://www.postgresql.org/docs/11/plperl-under-the-hood.html "PostgreSQL 11 - PL/Perl Under the Hood") / [10](https://www.postgresql.org/docs/10/plperl-under-the-hood.html "PostgreSQL 10 - PL/Perl Under the Hood") / [9.6](https://www.postgresql.org/docs/9.6/plperl-under-the-hood.html "PostgreSQL 9.6 - PL/Perl Under the Hood") / [9.5](https://www.postgresql.org/docs/9.5/plperl-under-the-hood.html "PostgreSQL 9.5 - PL/Perl Under the Hood") / [9.4](https://www.postgresql.org/docs/9.4/plperl-under-the-hood.html "PostgreSQL 9.4 - PL/Perl Under the Hood") / [9.3](https://www.postgresql.org/docs/9.3/plperl-under-the-hood.html "PostgreSQL 9.3 - PL/Perl Under the Hood") / [9.2](https://www.postgresql.org/docs/9.2/plperl-under-the-hood.html "PostgreSQL 9.2 - PL/Perl Under the Hood") / [9.1](https://www.postgresql.org/docs/9.1/plperl-under-the-hood.html "PostgreSQL 9.1 - PL/Perl Under the Hood") / [9.0](https://www.postgresql.org/docs/9.0/plperl-under-the-hood.html "PostgreSQL 9.0 - PL/Perl Under the Hood") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/plperl-under-the-hood.html "PostgreSQL - PL/Perl Under the Hood") version, or one of the other supported versions listed above instead. | [PostgreSQL 9.0.23 Documentation](https://www.postgresql.org/docs/9.0/index.html) | | | | | | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.0/plperl-triggers.html "PL/Perl Triggers") | [Up](https://www.postgresql.org/docs/9.0/plperl.html) | Chapter 41. PL/Perl - Perl Procedural Language | [Next](https://www.postgresql.org/docs/9.0/plpython.html "PL/Python - Python Procedural Language") | * * * 41.7. PL/Perl Under the Hood ============================ 41.7.1. Configuration --------------------- This section lists configuration parameters that affect PL/Perl. To set any of these parameters before PL/Perl has been loaded, it is necessary to have added "plperl" to the [custom\_variable\_classes](https://www.postgresql.org/docs/9.0/runtime-config-custom.html#GUC-CUSTOM-VARIABLE-CLASSES) list in postgresql.conf. plperl.on\_init (string) Specifies Perl code to be executed when a Perl interpreter is first initialized, before it is specialized for use by plperl or plperlu. The SPI functions are not available when this code is executed. If the code fails with an error it will abort the initialization of the interpreter and propagate out to the calling query, causing the current transaction or subtransaction to be aborted. The Perl code is limited to a single string. Longer code can be placed into a module and loaded by the on\_init string. Examples: plperl.on\_init = 'require "plperlinit.pl"' plperl.on\_init = 'use lib "/my/app"; use MyApp::PgInit;' Any modules loaded by plperl.on\_init, either directly or indirectly, will be available for use by plperl. This may create a security risk. To see what modules have been loaded you can use: DO 'elog(WARNING, join ", ", sort keys %INC)' language plperl; Initialization will happen in the postmaster if the plperl library is included in [shared\_preload\_libraries](https://www.postgresql.org/docs/9.0/runtime-config-resource.html#GUC-SHARED-PRELOAD-LIBRARIES) , in which case extra consideration should be given to the risk of destabilizing the postmaster. The principal reason for making use of this feature is that Perl modules loaded by plperl.on\_init need be loaded only at postmaster start, and will be instantly available without loading overhead in individual database sessions. However, keep in mind that the overhead is avoided only for the first Perl interpreter used by a database session — either PL/PerlU, or PL/Perl for the first SQL role that calls a PL/Perl function. Any additional Perl interpreters created in a database session will have to execute plperl.on\_init afresh. Also, on Windows there will be no savings whatsoever from preloading, since the Perl interpreter created in the postmaster process does not propagate to child processes. This parameter can only be set in the postgresql.conf file or on the server command line. plperl.on\_plperl\_init (string) plperl.on\_plperlu\_init (string) These parameters specify Perl code to be executed when a Perl interpreter is specialized for plperl or plperlu respectively. This will happen when a PL/Perl or PL/PerlU function is first executed in a database session, or when an additional interpreter has to be created because the other language is called or a PL/Perl function is called by a new SQL role. This follows any initialization done by plperl.on\_init. The SPI functions are not available when this code is executed. The Perl code in plperl.on\_plperl\_init is executed after "locking down" the interpreter, and thus it can only perform trusted operations. If the code fails with an error it will abort the initialization and propagate out to the calling query, causing the current transaction or subtransaction to be aborted. Any actions already done within Perl won't be undone; however, that interpreter won't be used again. If the language is used again the initialization will be attempted again within a fresh Perl interpreter. Only superusers can change these settings. Although these settings can be changed within a session, such changes will not affect Perl interpreters that have already been used to execute functions. plperl.use\_strict (boolean) When set true subsequent compilations of PL/Perl functions will have the strict pragma enabled. This parameter does not affect functions already compiled in the current session. 41.7.2. Limitations and Missing Features ---------------------------------------- The following features are currently missing from PL/Perl, but they would make welcome contributions. * PL/Perl functions cannot call each other directly. * SPI is not yet fully implemented. * If you are fetching very large data sets using spi\_exec\_query, you should be aware that these will all go into memory. You can avoid this by using spi\_query/spi\_fetchrow as illustrated earlier. A similar problem occurs if a set-returning function passes a large set of rows back to PostgreSQL via return. You can avoid this problem too by instead using return\_next for each row returned, as shown previously. * When a session ends normally, not due to a fatal error, any END blocks that have been defined are executed. Currently no other actions are performed. Specifically, file handles are not automatically flushed and objects are not automatically destroyed. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/9.0/plperl-triggers.html) | [Home](https://www.postgresql.org/docs/9.0/index.html) | [Next](https://www.postgresql.org/docs/9.0/plpython.html) | | PL/Perl Triggers | [Up](https://www.postgresql.org/docs/9.0/plperl.html) | PL/Python - Python Procedural Language | --- # PostgreSQL: Documentation: 18: 53.38. pg_wait_events November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 18](https://www.postgresql.org/docs/18/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/view-pg-wait-events.html "PostgreSQL 18 - 53.38. pg_wait_events") ([18](https://www.postgresql.org/docs/18/view-pg-wait-events.html "PostgreSQL 18 - 53.38. pg_wait_events") ) / [17](https://www.postgresql.org/docs/17/view-pg-wait-events.html "PostgreSQL 17 - 53.38. pg_wait_events") Development Versions: [devel](https://www.postgresql.org/docs/devel/view-pg-wait-events.html "PostgreSQL devel - 53.38. pg_wait_events") | 53.38. `pg_wait_events` | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-views.html "53.37. pg_views") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | Chapter 53. System Views | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | [Next](https://www.postgresql.org/docs/current/protocol.html "Chapter 54. Frontend/Backend Protocol") | * * * 53.38. `pg_wait_events` [#](https://www.postgresql.org/docs/current/view-pg-wait-events.html#VIEW-PG-WAIT-EVENTS) ------------------------------------------------------------------------------------------------------------------ The view `pg_wait_events` provides description about the wait events. **Table 53.38. `pg_wait_events` Columns** | Column Type

Description | | --- | | `type` `text`

Wait event type | | `name` `text`

Wait event name | | `description` `text`

Wait event description | * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/current/view-pg-views.html "53.37. pg_views") | [Up](https://www.postgresql.org/docs/current/views.html "Chapter 53. System Views") | [Next](https://www.postgresql.org/docs/current/protocol.html "Chapter 54. Frontend/Backend Protocol") | | 53.37. `pg_views` | [Home](https://www.postgresql.org/docs/current/index.html "PostgreSQL 18.1 Documentation") | Chapter 54. Frontend/Backend Protocol | Submit correction ----------------- If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use [this form](https://www.postgresql.org/account/comments/new/18/view-pg-wait-events.html/) to report a documentation issue. --- # PostgreSQL: Documentation: 8.3: dblink_current_query November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 8.3](https://www.postgresql.org/docs/8.3/index.html) Unsupported versions: [8.3](https://www.postgresql.org/docs/8.3/contrib-dblink-current-query.html "PostgreSQL 8.3 - dblink_current_query") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/contrib-dblink-current-query.html "PostgreSQL - dblink_current_query") version, or one of the other supported versions listed above instead. | PostgreSQL 8.3.23 Documentation | | | | | | --- | --- | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/8.3/contrib-dblink-cancel-query.html) | [Fast Backward](https://www.postgresql.org/docs/8.3/contrib-dblink-cancel-query.html) | | [Fast Forward](https://www.postgresql.org/docs/8.3/contrib-dblink-get-pkey.html) | [Next](https://www.postgresql.org/docs/8.3/contrib-dblink-get-pkey.html) | * * * dblink\_current\_query ====================== Name ---- dblink\_current\_query -- returns the current query string Synopsis -------- dblink\_current\_query() returns text Description ----------- Returns the currently executing interactive command string of the local database session, or NULL if it can't be determined. Note that this function is not really related to dblink's other functionality. It is provided since it is sometimes useful in generating queries to be forwarded to remote databases. Return Value ------------ Returns a copy of the currently executing query string. Example ------- test=# select dblink\_current\_query(); dblink\_current\_query -------------------------------- select dblink\_current\_query(); (1 row) * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/8.3/contrib-dblink-cancel-query.html) | [Home](https://www.postgresql.org/docs/8.3/index.html) | [Next](https://www.postgresql.org/docs/8.3/contrib-dblink-get-pkey.html) | | dblink\_cancel\_query | [Up](https://www.postgresql.org/docs/8.3/dblink.html) | dblink\_get\_pkey | --- # PostgreSQL: Documentation: 7.2: DROP LANGUAGE November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 7.2](https://www.postgresql.org/docs/7.2/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/sql-droplanguage.html "PostgreSQL 18 - DROP LANGUAGE") ([18](https://www.postgresql.org/docs/18/sql-droplanguage.html "PostgreSQL 18 - DROP LANGUAGE") ) / [17](https://www.postgresql.org/docs/17/sql-droplanguage.html "PostgreSQL 17 - DROP LANGUAGE") / [16](https://www.postgresql.org/docs/16/sql-droplanguage.html "PostgreSQL 16 - DROP LANGUAGE") / [15](https://www.postgresql.org/docs/15/sql-droplanguage.html "PostgreSQL 15 - DROP LANGUAGE") / [14](https://www.postgresql.org/docs/14/sql-droplanguage.html "PostgreSQL 14 - DROP LANGUAGE") Development Versions: [devel](https://www.postgresql.org/docs/devel/sql-droplanguage.html "PostgreSQL devel - DROP LANGUAGE") Unsupported versions: [13](https://www.postgresql.org/docs/13/sql-droplanguage.html "PostgreSQL 13 - DROP LANGUAGE") / [12](https://www.postgresql.org/docs/12/sql-droplanguage.html "PostgreSQL 12 - DROP LANGUAGE") / [11](https://www.postgresql.org/docs/11/sql-droplanguage.html "PostgreSQL 11 - DROP LANGUAGE") / [10](https://www.postgresql.org/docs/10/sql-droplanguage.html "PostgreSQL 10 - DROP LANGUAGE") / [9.6](https://www.postgresql.org/docs/9.6/sql-droplanguage.html "PostgreSQL 9.6 - DROP LANGUAGE") / [9.5](https://www.postgresql.org/docs/9.5/sql-droplanguage.html "PostgreSQL 9.5 - DROP LANGUAGE") / [9.4](https://www.postgresql.org/docs/9.4/sql-droplanguage.html "PostgreSQL 9.4 - DROP LANGUAGE") / [9.3](https://www.postgresql.org/docs/9.3/sql-droplanguage.html "PostgreSQL 9.3 - DROP LANGUAGE") / [9.2](https://www.postgresql.org/docs/9.2/sql-droplanguage.html "PostgreSQL 9.2 - DROP LANGUAGE") / [9.1](https://www.postgresql.org/docs/9.1/sql-droplanguage.html "PostgreSQL 9.1 - DROP LANGUAGE") / [9.0](https://www.postgresql.org/docs/9.0/sql-droplanguage.html "PostgreSQL 9.0 - DROP LANGUAGE") / [8.4](https://www.postgresql.org/docs/8.4/sql-droplanguage.html "PostgreSQL 8.4 - DROP LANGUAGE") / [8.3](https://www.postgresql.org/docs/8.3/sql-droplanguage.html "PostgreSQL 8.3 - DROP LANGUAGE") / [8.2](https://www.postgresql.org/docs/8.2/sql-droplanguage.html "PostgreSQL 8.2 - DROP LANGUAGE") / [8.1](https://www.postgresql.org/docs/8.1/sql-droplanguage.html "PostgreSQL 8.1 - DROP LANGUAGE") / [8.0](https://www.postgresql.org/docs/8.0/sql-droplanguage.html "PostgreSQL 8.0 - DROP LANGUAGE") / [7.4](https://www.postgresql.org/docs/7.4/sql-droplanguage.html "PostgreSQL 7.4 - DROP LANGUAGE") / [7.3](https://www.postgresql.org/docs/7.3/sql-droplanguage.html "PostgreSQL 7.3 - DROP LANGUAGE") / [7.2](https://www.postgresql.org/docs/7.2/sql-droplanguage.html "PostgreSQL 7.2 - DROP LANGUAGE") / [7.1](https://www.postgresql.org/docs/7.1/sql-droplanguage.html "PostgreSQL 7.1 - DROP LANGUAGE") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/sql-droplanguage.html "PostgreSQL - DROP LANGUAGE") version, or one of the other supported versions listed above instead. | PostgreSQL 7.2.8 Documentation | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.2/sql-dropindex.html) | | [Next](https://www.postgresql.org/docs/7.2/sql-dropoperator.html) | * * * DROP LANGUAGE ============= Name ---- DROP LANGUAGE  --  remove a user-defined procedural language Synopsis -------- DROP \[ PROCEDURAL \] LANGUAGE name ### Inputs name The name of an existing procedural language. For backward compatibility, the name may be enclosed by single quotes. ### Outputs DROP This message is returned if the language is successfully dropped. ERROR: Language "name" doesn't exist This message occurs if a language called name is not found in the database. Description ----------- **DROP PROCEDURAL LANGUAGE** will remove the definition of the previously registered procedural language called name. ### Notes The **DROP PROCEDURAL LANGUAGE** statement is a PostgreSQL language extension. Refer to [CREATE LANGUAGE](https://www.postgresql.org/docs/7.2/sql-createlanguage.html) for information on how to create procedural languages. No checks are made if functions or trigger procedures registered in this language still exist. To re-enable them without having to drop and recreate all the functions, the pg\_proc's prolang attribute of the functions must be adjusted to the new object ID of the recreated pg\_language entry for the PL. Usage ----- This command removes the PL/Sample language: DROP LANGUAGE plsample; Compatibility ------------- ### SQL92 There is no **DROP PROCEDURAL LANGUAGE** in SQL92. * * * | | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.2/sql-dropindex.html) | [Home](https://www.postgresql.org/docs/7.2/index.html) | [Next](https://www.postgresql.org/docs/7.2/sql-dropoperator.html) | | DROP INDEX | [Up](https://www.postgresql.org/docs/7.2/sql-commands.html) | DROP OPERATOR | --- # PostgreSQL: Documentation: 7.3: SQL Conformance November 13, 2025: [PostgreSQL 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 Released!](https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/) [Documentation](https://www.postgresql.org/docs/ "Documentation") → [PostgreSQL 7.3](https://www.postgresql.org/docs/7.3/index.html) Supported Versions: [Current](https://www.postgresql.org/docs/current/features.html "PostgreSQL 18 - SQL Conformance") ([18](https://www.postgresql.org/docs/18/features.html "PostgreSQL 18 - SQL Conformance") ) / [17](https://www.postgresql.org/docs/17/features.html "PostgreSQL 17 - SQL Conformance") / [16](https://www.postgresql.org/docs/16/features.html "PostgreSQL 16 - SQL Conformance") / [15](https://www.postgresql.org/docs/15/features.html "PostgreSQL 15 - SQL Conformance") / [14](https://www.postgresql.org/docs/14/features.html "PostgreSQL 14 - SQL Conformance") Development Versions: [devel](https://www.postgresql.org/docs/devel/features.html "PostgreSQL devel - SQL Conformance") Unsupported versions: [13](https://www.postgresql.org/docs/13/features.html "PostgreSQL 13 - SQL Conformance") / [12](https://www.postgresql.org/docs/12/features.html "PostgreSQL 12 - SQL Conformance") / [11](https://www.postgresql.org/docs/11/features.html "PostgreSQL 11 - SQL Conformance") / [10](https://www.postgresql.org/docs/10/features.html "PostgreSQL 10 - SQL Conformance") / [9.6](https://www.postgresql.org/docs/9.6/features.html "PostgreSQL 9.6 - SQL Conformance") / [9.5](https://www.postgresql.org/docs/9.5/features.html "PostgreSQL 9.5 - SQL Conformance") / [9.4](https://www.postgresql.org/docs/9.4/features.html "PostgreSQL 9.4 - SQL Conformance") / [9.3](https://www.postgresql.org/docs/9.3/features.html "PostgreSQL 9.3 - SQL Conformance") / [9.2](https://www.postgresql.org/docs/9.2/features.html "PostgreSQL 9.2 - SQL Conformance") / [9.1](https://www.postgresql.org/docs/9.1/features.html "PostgreSQL 9.1 - SQL Conformance") / [9.0](https://www.postgresql.org/docs/9.0/features.html "PostgreSQL 9.0 - SQL Conformance") / [8.4](https://www.postgresql.org/docs/8.4/features.html "PostgreSQL 8.4 - SQL Conformance") / [8.3](https://www.postgresql.org/docs/8.3/features.html "PostgreSQL 8.3 - SQL Conformance") / [8.2](https://www.postgresql.org/docs/8.2/features.html "PostgreSQL 8.2 - SQL Conformance") / [8.1](https://www.postgresql.org/docs/8.1/features.html "PostgreSQL 8.1 - SQL Conformance") / [8.0](https://www.postgresql.org/docs/8.0/features.html "PostgreSQL 8.0 - SQL Conformance") / [7.4](https://www.postgresql.org/docs/7.4/features.html "PostgreSQL 7.4 - SQL Conformance") / [7.3](https://www.postgresql.org/docs/7.3/features.html "PostgreSQL 7.3 - SQL Conformance") This documentation is for an unsupported version of PostgreSQL. You may want to view the same page for the [current](https://www.postgresql.org/docs/current/features.html "PostgreSQL - SQL Conformance") version, or one of the other supported versions listed above instead. | PostgreSQL 7.3.21 Documentation | | | | --- | --- | --- | | [Prev](https://www.postgresql.org/docs/7.3/sql-keywords-appendix.html) | | [Next](https://www.postgresql.org/docs/7.3/unsupported-features-sql99.html) | * * * Appendix C. SQL Conformance =========================== Table of Contents C.1. [Supported Features](https://www.postgresql.org/docs/7.3/features.html#FEATURES-SQL99) C.2. [Unsupported Features](https://www.postgresql.org/docs/7.3/unsupported-features-sql99.html) This section attempts to outline to what extent PostgreSQL conforms to the SQL standard. Full compliance to the standard or a complete statement about the compliance to the standard is complicated and not particularly useful, so this section can only give an overview. The formal name of the SQL standard is ISO/IEC 9075 "Database Language SQL". A revised version of the standard is released from time to time; the most recent one appearing in 1999. That version is refered to as ISO/IEC 9075:1999, or informally as SQL99. The version prior to that was SQL92. PostgreSQL development tends to aim for conformance with the latest official version of the standard where such conformance does not contradict traditional features or common sense. At the time of this writing, ballotting is under way for a new revision of the standard, which, if approved, will eventually become the conformance target for future PostgreSQL development. SQL92 defined three feature sets for conformance: Entry, Intermediate, and Full. Most database products claiming SQL standard conformance were conforming at only the Entry level, since the entire set of features in the Intermediate and Full levels was either too voluminous or in conflict with legacy behaviors. SQL99 defines a large set of individual features rather than the ineffectively broad three levels found in SQL92. A large subset of these features represents the "core" features, which every conforming SQL implementation must supply. The rest of the features are purely optional. Some optional features are grouped together to form "packages", which SQL implementations can claim conformance to, thus claiming conformance to particular groups of features. The SQL99 standard is also split into 5 parts: Framework, Foundation, Call Level Interface, Persistent Stored Modules, and Host Language Bindings. PostgreSQL only covers parts 1, 2, and 5. Part 3 is similar to the ODBC interface, and part 4 is similar to the PL/pgSQL programming language, but exact conformance is not specifically intended in either case. In the following two sections, we provide a list of those features that PostgreSQL supports, followed by a list of the features defined in SQL99 which are not yet supported in PostgreSQL. Both of these lists are approximate: There may be minor details that are nonconforming for a feature that is listed as supported, and large parts of an unsupported feature may in fact be implemented. The main body of the documentation always contains the most accurate information about what does and does not work. > **Note:** Feature codes containing a hyphen are subfeatures. Therefore, if a particular subfeature is not supported, the main feature is listed as unsupported even if some other subfeatures are supported. C.1. Supported Features ======================= | Identifier | Package | Description | Comment | | --- | --- | --- | --- | | B012 | Core | Embedded C | | | B021 | | Direct SQL | | | E011 | Core | Numeric data types | | | E011-01 | Core | INTEGER and SMALLINT data types | | | E011-02 | Core | REAL, DOUBLE PRECISON, and FLOAT data types | | | E011-03 | Core | DECIMAL and NUMERIC data types | | | E011-04 | Core | Arithmetic operators | | | E011-05 | Core | Numeric comparison | | | E011-06 | Core | Implicit casting among the numeric data types | | | E021 | Core | Character data types | | | E021-01 | Core | CHARACTER data type | | | E021-02 | Core | CHARACTER VARYING data type | | | E021-03 | Core | Character literals | | | E021-04 | Core | CHARACTER\_LENGTH function | | | E021-05 | Core | OCTET\_LENGTH function | | | E021-06 | Core | SUBSTRING function | | | E021-07 | Core | Character concatenation | | | E021-08 | Core | UPPER and LOWER functions | | | E021-09 | Core | TRIM function | | | E021-10 | Core | Implicit casting among the character data types | | | E021-11 | Core | POSITION function | | | E011-12 | Core | Character comparison | | | E031 | Core | Identifiers | | | E031-01 | Core | Delimited identifiers | | | E031-02 | Core | Lower case identifiers | | | E031-03 | Core | Trailing underscore | | | E051 | Core | Basic query specification | | | E051-01 | Core | SELECT DISTINCT | | | E051-02 | Core | GROUP BY clause | | | E051-04 | Core | GROUP BY can contain columns not in