Какое расширение у бд postgresql

Какое расширение у бд postgresql

This section describes the storage format at the level of files and directories.

Traditionally, the configuration and data files used by a database cluster are stored together within the cluster’s data directory, commonly referred to as PGDATA (after the name of the environment variable that can be used to define it). A common location for PGDATA is /var/lib/pgsql/data . Multiple clusters, managed by different server instances, can exist on the same machine.

The PGDATA directory contains several subdirectories and control files, as shown in Table 73.1. In addition to these required items, the cluster configuration files postgresql.conf , pg_hba.conf , and pg_ident.conf are traditionally stored in PGDATA , although it is possible to place them elsewhere.

Table 73.1. Contents of PGDATA

Item Description
PG_VERSION A file containing the major version number of PostgreSQL
base Subdirectory containing per-database subdirectories
current_logfiles File recording the log file(s) currently written to by the logging collector
global Subdirectory containing cluster-wide tables, such as pg_database
pg_commit_ts Subdirectory containing transaction commit timestamp data
pg_dynshmem Subdirectory containing files used by the dynamic shared memory subsystem
pg_logical Subdirectory containing status data for logical decoding
pg_multixact Subdirectory containing multitransaction status data (used for shared row locks)
pg_notify Subdirectory containing LISTEN/NOTIFY status data
pg_replslot Subdirectory containing replication slot data
pg_serial Subdirectory containing information about committed serializable transactions
pg_snapshots Subdirectory containing exported snapshots
pg_stat Subdirectory containing permanent files for the statistics subsystem
pg_stat_tmp Subdirectory containing temporary files for the statistics subsystem
pg_subtrans Subdirectory containing subtransaction status data
pg_tblspc Subdirectory containing symbolic links to tablespaces
pg_twophase Subdirectory containing state files for prepared transactions
pg_wal Subdirectory containing WAL (Write Ahead Log) files
pg_xact Subdirectory containing transaction commit status data
postgresql.auto.conf A file used for storing configuration parameters that are set by ALTER SYSTEM
postmaster.opts A file recording the command-line options the server was last started with
postmaster.pid A lock file recording the current postmaster process ID (PID), cluster data directory path, postmaster start timestamp, port number, Unix-domain socket directory path (could be empty), first valid listen_address (IP address or * , or empty if not listening on TCP), and shared memory segment ID (this file is not present after server shutdown)

For each database in the cluster there is a subdirectory within PGDATA /base , named after the database’s OID in pg_database . This subdirectory is the default location for the database’s files; in particular, its system catalogs are stored there.

Note that the following sections describe the behavior of the builtin heap table access method, and the builtin index access methods. Due to the extensible nature of PostgreSQL , other access methods might work differently.

Each table and index is stored in a separate file. For ordinary relations, these files are named after the table or index’s filenode number, which can be found in pg_class . relfilenode . But for temporary relations, the file name is of the form t BBB _ FFF , where BBB is the backend ID of the backend which created the file, and FFF is the filenode number. In either case, in addition to the main file (a/k/a main fork), each table and index has a free space map (see Section 73.3), which stores information about free space available in the relation. The free space map is stored in a file named with the filenode number plus the suffix _fsm . Tables also have a visibility map, stored in a fork with the suffix _vm , to track which pages are known to have no dead tuples. The visibility map is described further in Section 73.4. Unlogged tables and indexes have a third fork, known as the initialization fork, which is stored in a fork with the suffix _init (see Section 73.5).


Note that while a table’s filenode often matches its OID, this is not necessarily the case; some operations, like TRUNCATE , REINDEX , CLUSTER and some forms of ALTER TABLE , can change the filenode while preserving the OID. Avoid assuming that filenode and table OID are the same. Also, for certain system catalogs including pg_class itself, pg_class . relfilenode contains zero. The actual filenode number of these catalogs is stored in a lower-level data structure, and can be obtained using the pg_relation_filenode() function.

When a table or index exceeds 1 GB, it is divided into gigabyte-sized segments. The first segment’s file name is the same as the filenode; subsequent segments are named filenode.1, filenode.2, etc. This arrangement avoids problems on platforms that have file size limitations. (Actually, 1 GB is just the default segment size. The segment size can be adjusted using the configuration option —with-segsize when building PostgreSQL .) In principle, free space map and visibility map forks could require multiple segments as well, though this is unlikely to happen in practice.

A table that has columns with potentially large entries will have an associated TOAST table, which is used for out-of-line storage of field values that are too large to keep in the table rows proper. pg_class . reltoastrelid links from a table to its TOAST table, if any. See Section 73.2 for more information.

The contents of tables and indexes are discussed further in Section 73.6.

Tablespaces make the scenario more complicated. Each user-defined tablespace has a symbolic link inside the PGDATA /pg_tblspc directory, which points to the physical tablespace directory (i.e., the location specified in the tablespace’s CREATE TABLESPACE command). This symbolic link is named after the tablespace’s OID. Inside the physical tablespace directory there is a subdirectory with a name that depends on the PostgreSQL server version, such as PG_9.0_201008051 . (The reason for using this subdirectory is so that successive versions of the database can use the same CREATE TABLESPACE location value without conflicts.) Within the version-specific subdirectory, there is a subdirectory for each database that has elements in the tablespace, named after the database’s OID. Tables and indexes are stored within that directory, using the filenode naming scheme. The pg_default tablespace is not accessed through pg_tblspc , but corresponds to PGDATA /base . Similarly, the pg_global tablespace is not accessed through pg_tblspc , but corresponds to PGDATA /global .

The pg_relation_filepath() function shows the entire path (relative to PGDATA ) of any relation. It is often useful as a substitute for remembering many of the above rules. But keep in mind that this function just gives the name of the first segment of the main fork of the relation — you may need to append a segment number and/or _fsm , _vm , or _init to find all the files associated with the relation.

Temporary files (for operations such as sorting more data than can fit in memory) are created within PGDATA /base/pgsql_tmp , or within a pgsql_tmp subdirectory of a tablespace directory if a tablespace other than pg_default is specified for them. The name of a temporary file has the form pgsql_tmp PPP . NNN , where PPP is the PID of the owning backend and NNN distinguishes different temporary files of that backend.

Prev Up Next
Chapter 73. Database Physical Storage Home 73.2. TOAST

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 to report a documentation issue.


Какое расширение у бд postgresql

Полезное расширение PostgreSQL обычно включает несколько объектов SQL; например, с появлением нового типа данных могут потребоваться новые функции, новые операторы и новые классы операторов. Все эти объекты удобно собрать в один пакет, с тем чтобы упростить управление базой данных. В PostgreSQL такие пакеты называются расширениями. Чтобы определить расширение, вам понадобится как минимум файл скрипта с командами SQL , создающими объекты расширения, и управляющий файл, в котором определяются несколько базовых свойств самого расширения. Если расширение написано на C, в него обычно также включается файл разделяемой библиотеки, содержащий скомпилированный код. Обеспечив наличие этих файлов, загрузить их в базу данных можно простой командой CREATE EXTENSION .

Основное преимущество расширений по сравнению с обычным SQL -скриптом, загружающим множество « разрозненных » объектов в базу данных, состоит в том, что PostgreSQL будет понимать, что объекты расширения связаны вместе. Вы можете удалить все объекты одной командой DROP EXTENSION (разрабатывать отдельный скрипт « uninstall » не требуется). Ещё полезнее то, что утилита pg_dump знает, что не нужно выгружать отдельные объекты, составляющие расширение — вместо этого она просто включит в архивный файл команду CREATE EXTENSION . Это кардинально упрощает миграцию на новую версию расширения, которая может содержать новые или другие объекты по сравнению с предыдущей версией. Заметьте, однако, что при загрузке такого архива в базу данных обязательно наличие скрипта, управляющего файла и других файлов расширения.

PostgreSQL не позволит удалить отдельный объект, содержащийся в расширении, кроме как при удалении всего расширения. Также имейте в виду, что вы можете изменить определение объекта, относящегося к расширению (например, командой CREATE OR REPLACE FUNCTION для функции), но изменённое определение не будет выгружено утилитой pg_dump . Такие изменения обычно разумны, только если они параллельно отражаются в файле скрипта расширения. (Для таблиц, содержащих конфигурационные данные, предусмотрены специальные средства; см. Подраздел 38.17.3.) В производственной среде обычно лучше создавать скрипт обновления расширения, который будет изменять относящиеся к расширению объекты.

Скрипт расширения может устанавливать права доступа для объектов, являющихся частью расширения, выполняя команды GRANT и REVOKE . Окончательный набор прав для каждого объекта (если они заданы) будет сохранён в системном каталоге pg_init_privs . При использовании pg_dump в выгружаемый скрипт будет выведена команда CREATE EXTENSION с последующими операторами GRANT и REVOKE , которые установят права, имевшие место в момент выгрузки.

PostgreSQL в настоящее время не поддерживает скрипты расширений, выполняющие операторы CREATE POLICY или SECURITY LABEL . Ожидается, что такие команды будут выполняться после того, как расширение будет создано. Выгружая данные, pg_dump будет также включать в вывод все политики RLS и метки безопасности.

Механизм расширений также предоставляет средства для поддержки дополнительных скриптов, призванных изменять определение объектов SQL, содержащихся в расширении. Например, если версия расширения 1.1, по сравнению с версией 1.0, добавляет одну функцию и изменяет тело другой функции, автор расширения может предоставить скрипт обновления, который произведёт именно эти два изменения. Затем, воспользовавшись командой ALTER EXTENSION UPDATE , можно будет применить эти изменения и отследить, какая версия расширения фактически установлена в заданной базе данных.

Типы SQL-объектов, которые могут быть членами расширения, перечислены в описании ALTER EXTENSION . Не могут быть его членами, в частности, объекты уровня кластера, такие как базы данных, роли и табличные пространства, так как расширение существует только в рамках одной базы данных. (Скрипту расширения не запрещается создавать такие объекты, но если он сделает это, они не будут считаться частью расширения.) Также заметьте, что несмотря на то, что таблица может быть членом расширения, её подчинённые объекты, такие как индексы, непосредственными членами расширения считаться не будут. Ещё один важный момент — схемы могут принадлежать расширениям, но не наоборот; поэтому расширение имеет неполное имя и не существует « внутри » какой-либо схемы. Однако объекты-члены расширения, будут относиться к схемам, если это уместно для их типов. Сами расширения могут иметь, а могут не иметь основания владеть схемами, к которым относятся объекты-члены расширения.

Если скрипт расширения создаёт какие-либо временные объекты (например, временные таблицы), эти объекты будут считаться членами расширения до конца текущего сеанса, но удалятся автоматически в конце сеанса, как и должны временные объекты. Это является исключением из правила, запрещающего удаление объектов-членов расширения без удаления всего расширения.

38.17.1. Файлы расширений

Команда CREATE EXTENSION задействует управляющий файл расширения, который должен называться по имени расширения, с суффиксом .control , и должен быть помещён в каталог сервера SHAREDIR/extension . Должен быть также ещё минимум один SQL -скрипт, с именем, соответствующим шаблону расширение — версия .sql (например, foo—1.0.sql для версии 1.0 расширения foo ). По умолчанию скрипт(ы) также помещается в каталог SHAREDIR/extension ; но в управляющем файле можно задать и другой каталог.

Формат управляющего файла расширения не отличается от формата postgresql.conf , а именно представляет собой список присваиваний имя_параметра = значение , по одному в строке. В нём также допускаются пустые строки и комментарии, начинающиеся с # . Все значения, отличные от единственного слова или числа, в нём должны заключаться в кавычки.

В управляющем файле могут устанавливаться следующие параметры:

Версия расширения по умолчанию (та, которая будет установлена, если в CREATE EXTENSION не будет указана никакая версия). Хотя этот параметр можно опустить, это приведёт к ошибке в CREATE EXTENSION без явного указания VERSION , что вряд ли будет желаемым поведением. comment ( string )

Комментарий (произвольная строка) к расширению. Комментарий применяется при изначальном создании расширения, но не при обновлениях расширения (так как при этом мог бы заменяться комментарий, заданный пользователем). Комментарий расширения также можно задать посредством команды COMMENT в файле скрипта. encoding ( string )

Кодировка символов, используемая в файлах скриптов. Её следует указать, если эти файлы содержат символы не из набора ASCII. По умолчанию предполагается, что эти файлы содержат текст в кодировке базы данных. module_pathname ( string )

Значение этого параметра будет подставляться вместо каждого вхождения MODULE_PATHNAME в скриптах. Если этот параметр не задан, подстановка не производится. Обычно для этого параметра устанавливается значение $libdir/ имя_разделяемой_библиотеки , а затем в командах CREATE FUNCTION для функций на языке C указывается MODULE_PATHNAME , чтобы в скриптах не приходилось жёстко задавать имя разделяемой библиотеки. requires ( string )

Список имён расширений, от которых зависит данное, например, requires = ‘foo, bar’ . Эти расширения должны быть уже установлены, прежде чем можно будет установить данное. superuser ( boolean )

Если этот параметр имеет значение true (по умолчанию), только суперпользователи смогут создать это расширение или обновить его до новой версии. (Однако обратите внимание на свойство trusted , описанное ниже). Если он имеет значение false , для этого будет достаточно прав, необходимых для выполнения команд в установочном скрипте или скрипте обновления. Обычно значение true должно устанавливаться, если для выполнения какой-либо из команд в этих скриптах требуются права суперпользователя. Такие команды в любом случае не будут выполнены успешно, но лучше сообщить пользователю об ошибке заранее. trusted ( boolean )

Если этот параметр имеет значение true (по умолчанию это не так), то расширение, для которого свойство superuser равно true , смогут устанавливать не только суперпользователи. А именно, установить его смогут любые пользователи, имеющие право CREATE в текущей базе данных. Когда пользователь, выполняющий CREATE EXTENSION , не является суперпользователем, но ему разрешена установка этого расширения посредством этого параметра, скрипт установки или обновления запускается от имени первоначального суперпользователя, а не от имени вызывающего пользователя. Этот параметр не играет роли, если свойство superuser равно false . Вообще говоря, этот параметр не следует устанавливать для расширений, которые могут открыть возможности, иначе доступные только суперпользователям, например, предоставить доступ к файловой системе. Кроме того, если расширение помечается как доверенное, написание безопасных скриптов установки и обновления для него требует дополнительных усилий; см. Подраздел 38.17.6. relocatable ( boolean )

Расширение является перемещаемым, если относящиеся к нему объекты после создания расширения можно переместить в другую схему. По умолчанию подразумевается false , то есть расширение не считается перемещаемым. Подробнее об этом рассказывается в Подразделе 38.17.2. schema ( string )

Этот параметр может задаваться только для неперемещаемых расширений. Если он задан, расширение можно будет загрузить только в указанную схему и не в какую другую. Подробнее об этом рассказывается ниже. Параметр schema учитывается только при изначальном создании расширения, но не при его обновлении. Подробнее об этом рассказывается в Подразделе 38.17.2.

Помимо главного управляющего файла расширение .control , расширение может включать дополнительные управляющие файлы с именами вида расширение — версия .control . Если они присутствуют, они должны находиться в том же каталоге, что и основной скрипт. Дополнительные управляющие файлы имеют тот же формат, что и основной. Любые параметры, заданные в дополнительном управляющем файле, переопределяют параметры основного файла, когда выполняется установка этой версии расширения или обновление до неё. Однако параметры directory и default_version в дополнительных управляющих файлах задать нельзя.

Если скрипт расширения содержит строку @extowner@ , она будет заменена именем (если требуется, заключённым в кавычки) пользователя, выполняющего команду CREATE EXTENSION или ALTER EXTENSION . Обычно это полезно для доверенных расширений, в которых владельцем внутренних объектов назначается не первоначальный суперпользователь, а вызывающий пользователь. (Однако это следует делать с осторожностью. Например, если назначить обычного пользователя владельцем функции на языке C, это позволит ему повысить свои привилегии.)

Тогда как файлы скриптов могут содержать любые символы, допустимые в указанной кодировке, управляющие файлы могут содержать только ASCII-символы, так как указать кодировку этих файлов в PostgreSQL нет никакой возможности. На практике это представляет проблему, только если вы хотите использовать символы не из набора ASCII в комментарии расширения. В таких случаях рекомендуется не использовать параметр comment в управляющем файле, а вместо этого задать комментарий командой COMMENT ON EXTENSION в файле скрипта.

38.17.2. Перемещаемость расширений

У пользователей часто возникает желание загрузить объекты, содержащиеся в расширении, в схему, отличную от той, что выбрал автор расширения. Насколько это поддерживает расширение, описывается одним из трёх уровней:

Полностью перемещаемое расширение может быть перемещено в другую схему в любое время, даже после того, как оно загружено в базу данных. Это осуществляется командой ALTER EXTENSION SET SCHEMA , которая автоматически переименовывает все объекты-члены расширения, перенося их в новую схему. Обычно это возможно, только если в расширении нет никаких внутренних предположений о том, в какой схеме находятся все его объекты. Кроме того, все объекты расширения должны находиться в одной исходной схеме (за исключением объектов, не принадлежащих схемам, как например, процедурные языки). Чтобы пометить расширение как полностью перемещаемое, установите relocatable = true в его управляющем файле.

Расширение может быть перемещаемым в момент установки, но не после. Обычно это имеет место, когда скрипту расширения необходимо явно ссылаться на целевую схему, например, устанавливая свойства search_path для функций SQL. Для такого расширения нужно задать relocatable = false в его управляющем файле и обращаться к целевой схеме в скрипте по псевдоимени @extschema@ . Все вхождения этого псевдоимени будут заменены именем выбранной целевой схемы перед выполнением скрипта. Пользователь может выбрать целевую схему в указании SCHEMA команды CREATE EXTENSION .

Если расширение вовсе не поддерживает перемещение, установите в его управляющем файле relocatable = false , и также задайте в параметре schema имя предполагаемой целевой схемы. Это предотвратит использование указания SCHEMA команды CREATE EXTENSION , если только оно задаёт не то же имя, что определёно в управляющем файле. Этот выбор обычно необходим, если в расширении делаются внутренние предположения об именах схемы, которые нельзя свести к использованию псевдоимени @extschema@ . Механизм подстановки @extschema@ будет работать и в этом случае, хотя польза от него будет ограниченной, так как имя схемы определяется управляющим файлом.

В любом случае при выполнении файла скрипта параметр search_path изначально будет указывать на целевую схему; то есть, CREATE EXTENSION делает то же, что и:

Это позволяет направить объекты, создаваемые скриптом, в целевую схему. Скрипт может изменить search_path , если пожелает, но обычно это нежелательно. Параметр search_path восстанавливает предыдущее значение по завершении CREATE EXTENSION .

Целевая схема определяется параметром schema (если он задан) в управляющем файле, либо указанием SCHEMA команды CREATE EXTENSION (если оно присутствует), а в противном случае выбирается текущая схема для создания объектов по умолчанию (первая указанная в параметре search_path вызывающего). Когда используется параметр управляющего файла schema , целевая схема будет создана, если она ещё не существует, но в двух других случаях она должна уже существовать.

Если в параметре requires в управляющем файле расширения указаны какие-либо расширения, необходимые для данного, их целевые схемы добавляются к начальному значению search_path после целевой схемы нового расширения. Благодаря этому их объекты видны для скрипта нового расширения.

В целях безопасности схема pg_temp всегда автоматически добавляется в конец search_path .

Хотя неперемещаемое расширение может содержать объекты, распределяемые по нескольким схемам, обычно желательно поместить все объекты, предназначенные для внешнего использования, в одну схему, назначенную целевой схемой расширения. Такой порядок будет хорошо согласовываться со значением search_path по умолчанию в процессе создания зависимых расширений.

38.17.3. Конфигурационные таблицы расширений

Некоторые расширения включают конфигурационные таблицы, содержащие данные, которые могут быть добавлены или изменены пользователем после установки расширения. Обычно, если таблица является частью расширения, ни определение таблицы, ни её содержимое не будет выгружаться утилитой pg_dump . Но это поведение нежелательно для конфигурационных таблиц — изменения, внесённые в них пользователем, должны выгружаться; в противном случае расширение будет вести себя по-другому, когда будет загружено вновь.

Чтобы решить эту проблему, скрипт расширения может пометить созданную им таблицу или последовательность как конфигурационное отношение, в результате чего pg_dump включит в выгружаемые данные содержимое (но не определение) этой таблицы или последовательности. Для этого нужно вызвать функцию pg_extension_config_dump(regclass, text) после создания таблицы или последовательности, например так:

Так можно пометить любое число таблиц или последовательностей, в том числе последовательности, связанные со столбцами serial или bigserial .

Когда второй аргумент pg_extension_config_dump — пустая строка, pg_dump выгружает всё содержимое таблицы. Обычно это правильно, только если после создания скриптом расширения эта таблица изначально пуста. Если же в таблице оказывается смесь начальных данных и данных, добавленных пользователем, во втором аргументе pg_extension_config_dump передаётся условие WHERE , которое отфильтровывает данные, подлежащие выгрузке. Например, имея таблицу, созданную таким образом:

можно сделать так, чтобы поле standard_entry содержало true только для строк, создаваемых скриптом расширения.

Для последовательностей второй аргумент функции pg_extension_config_dump не имеет значения.

В более сложных ситуациях, когда пользователи могут модифицировать и изначально существовавшие строки, можно создать триггеры для конфигурационной таблицы, которые корректно пометят изменённые строки.

Условие фильтра, связанное с конфигурационной таблицей, можно изменить, повторно вызвав pg_extension_config_dump . (Обычно это находит применение в скрипте обновления расширения.) Единственный способ обозначить, что некоторая таблица более не является конфигурационной — разорвать её связь с расширением командой ALTER EXTENSION . DROP TABLE .

Заметьте, что отношения внешних ключей между таблицами определяют порядок, в котором эти таблицы будет выгружать pg_dump. В частности, pg_dump попытается выгрузить сначала основную таблицу, а затем подчинённую. Так как отношения внешних ключей устанавливаются во время выполнения CREATE EXTENSION (до загрузки данных в таблицы), циклические зависимости не поддерживаются. Когда образуются циклические зависимости, данные тем не менее будут выгружены, но полученный архив нельзя будет восстановить обычным образом, потребуется вмешательство пользователя.

Последовательности, связанные со столбцами serial или bigserial , не обязательно помечать непосредственно, чтобы их состояние было сохранено. Для этой цели достаточно пометить только их родительское отношение.

38.17.4. Обновление расширений

Один из плюсов механизма расширений заключается в том, что он предоставляет удобные способы управления обновлениями SQL-команд, определяющих объекты расширения. В частности, каждой выпускаемой версии установочного скрипта расширения назначается имя или номер версии. Кроме того, если вы хотите, чтобы пользователи могли динамически обновлять одну версию расширения до другой, вы должны предоставить скрипты обновления, которые внесут необходимые изменения для перехода от старой версии к новой. Скриптам обновлений назначаются имена, соответствующие шаблону расширение — старая_версия — новая_версия .sql (например, foo—1.0—1.1.sql будет содержать команды, меняющие версию 1.0 расширения foo на версию 1.1 ).

С условием, что имеется подходящий скрипт расширения, команда ALTER EXTENSION UPDATE обновит установленное расширение до указанной новой версии. Скрипт обновления запускается в том же окружении, которое организует команда CREATE EXTENSION для установочных скриптов: в частности, search_path устанавливается таким же образом, а любые новые объекты, созданные скриптом, автоматически добавляются в расширение. И если скрипт решит удалить объекты-члены расширения, они будут автоматически исключены из его состава.

Если у расширения есть дополнительные управляющие файлы, для скрипта обновления применяются те параметры, которые связаны с целевой (новой) версией скрипта.

ALTER EXTENSION также может выполнять последовательности скриптов обновления для получения запрошенной версии. Например, если имеются только скрипты foo—1.0—1.1.sql и foo—1.1—2.0.sql , ALTER EXTENSION будет применять их по порядку, если при установленной версии 1.0 запрошено обновлении до версии 2.0 .

PostgreSQL не делает никаких предположений о свойствах имён версий: например, он не знает, следует ли версия 1.1 за 1.0 . Он просто сопоставляет имена имеющихся версий и следует пути, который требует применить как можно меньше скриптов обновлений. (Именем версии на самом деле может быть любая строка, которая не содержит — и при этом не начинается и не заканчивается символом — .)

Иногда бывают полезны скрипты « понижения версии » , например, foo—1.1—1.0.sql , которые позволяют откатить изменения, связанные с версией 1.1 . Если вы применяете их, учтите, что есть вероятность неожиданного выполнения такого скрипта, если он окажется в кратчайшем пути. Рискованная ситуация возникает при наличии скрипта обновления по « короткому пути » , который перепрыгивает через несколько версий, и скрипта понижения версии до начальной точки первого скрипта. В результате может получиться так, что понижение версии с последующим обновлением по короткому пути окажется на несколько шагов короче, чем последовательное повышение версии. Если скрипт понижения версии удаляет какие-либо незаменимые объекты, это может привести к нежелательным результатам.

Чтобы убедиться, что при обновлении не будет выбран нежелательный путь, воспользуйтесь этой командой:

Она показывает каждую пару различных известных имён версий для указанного расширения, вместе с последовательностью обновления, которая будет выбрана для перехода от одной версии к другой, либо NULL , если путь обновления не находится. Путь выводится в текстовом виде с разделителями — . Если вы предпочитаете формат массива, вы можете применить regexp_split_to_array(path,’—‘) .

38.17.5. Установка расширений скриптами обновления

Расширение, существующее некоторое время, вероятно, будет иметь несколько версий, для которых автору надо будет писать скрипты обновления. Например, если вы выпустили расширение foo версий 1.0 , 1.1 и 1.2 , у вас должны быть скрипты обновления foo—1.0—1.1.sql и foo—1.1—1.2.sql . До PostgreSQL версии 10 необходимо было также создавать файлы скриптов foo—1.1.sql и foo—1.2.sql , которые устанавливают непосредственно новые версии скриптов; в противном случае их можно было установить, только установив 1.0 и произведя обновление. Это было утомительно и неэффективно, но теперь такой необходимости нет, так как команда CREATE EXTENSION может сама построить цепочку обновлений. Например, если имеются только файлы скриптов foo—1.0.sql , foo—1.0—1.1.sql и foo—1.1—1.2.sql , то запрос на установку версии 1.2 удовлетворяется запуском этих трёх скриптов по очереди. Это не будет отличаться от установки версии 1.0 с последующим обновлением до 1.2 . (Как и с командой ALTER EXTENSION UPDATE , при наличии нескольких путей выбирается самый короткий.) Организация скриптов расширения по такой схеме может упростить сопровождение небольших обновлений.

Если вы используете дополнительные (ориентированные на версию) управляющие файлы для расширения, поддерживаемого по такой схеме, имейте в виду, что управляющий файл нужен для каждой версии, даже если для неё нет отдельного скрипта установки, так как этот файл будет определять, как произвести неявное обновление до этой версии. Например, если в файле foo—1.0.control задаётся requires = ‘bar’ , а в других управляющих файлах foo — нет, зависимость расширения от bar будет удалена при обновлении с версии 1.0 до другой.

38.17.6. Замечания о безопасности расширений

Широко распространяемые расширения не должны строить никаких предположений относительно базы данных, в которой они находятся. Таким образом, функции, предоставляемые расширениями, следует писать в безопасном стиле, так, чтобы их нельзя было скомпрометировать в атаках с использованием пути поиска.

Расширение, у которого свойство superuser имеет значение true, должно быть также защищено от угроз безопасности, связанных с действиями, которые выполняются при установке и обновлении расширения. Для злонамеренного пользователя не составит большого труда создать объект типа троянского коня, который впоследствии скомпрометирует выполнение неаккуратно написанного скрипта расширения и позволит этому пользователю стать суперпользователем.

Если расширение имеет характеристику trusted , вызывающий пользователь может выбрать схему, в которую оно будет устанавливаться. При этом он может намеренно выбрать небезопасную схему в надежде получить таким образом права суперпользователя. Поэтому доверенное расширение крайне уязвимо с точки зрения безопасности, так что все содержащиеся в его скриптах команды необходимо тщательно проверять, чтобы исключить возможность его компрометации.

Советы по безопасному написанию функций представлены ниже в Подразделе, а советы по написанию установочных скриптов — в Подразделе Замечания о безопасности функций в расширениях

Функции, реализованные в расширениях на языках SQL и PL*, подвержены атакам с использованием пути поиска во время выполнения, так как синтаксический разбор этих функций имеет место, когда они выполняются, а не когда создаются.

На странице CREATE FUNCTION даётся полезный совет по безопасному написанию функций с характеристикой SECURITY DEFINER . Эти приёмы рекомендуется применять и для функций, предоставляемых расширениями, так как подобная функция может вызываться пользователем с расширенными правами.

Если вы не можете оставить в search_path только безопасные схемы, считайте, что каждое заданное без схемы имя может быть разрешено в объект, созданный злонамеренным пользователем. Избегайте конструкций, явно зависящих от search_path ; например, IN и CASE выражение WHEN всегда выбирают оператор по пути поиска. Вместо них следует использовать конструкции OPERATOR( схема .=) ANY и CASE WHEN выражение .

Расширения общего назначения не должны рассчитывать на то, что они устанавливаются в безопасную схему, что означает, что даже ссылаться на собственные объекты с указанием схемы в них небезопасно. Например, если в расширении определена функция myschema.myfunc(bigint) , её вызов в виде myschema.myfunc(42) можно перехватить, создав специальную функцию myschema.myfunc(integer) . Позаботьтесь о том, чтобы типы параметров функций и операторов в точности соответствовали объявленным типам их аргументов, и используйте явные приведения, где это необходимо. Замечания о безопасности скриптов расширений

Скрипт установки или обновления расширения следует защищать от атак, осуществляемых во время выполнения с использованием пути поиска. Если имя объекта, который должен использоваться в скрипте по замыслу автора, может быть разрешено в какой-либо другой объект, компрометация расширения произойдёт сразу либо позже, когда объект расширения будет использоваться.

Команды DDL, например CREATE FUNCTION и CREATE OPERATOR CLASS , в целом безопасны, но будьте бдительны в отношении команд, в которых фигурируют произвольные запросы и выражения. Например, требуют проверки команды CREATE VIEW , а также выражения DEFAULT в CREATE FUNCTION .

Иногда в скрипте расширения возникает потребность выполнить произвольный SQL, например, чтобы внести в каталог изменения, невозможные через DDL. В этом случае обязательно выполняйте такие команды с безопасным search_path ; не доверяйте пути, установленному при выполнении CREATE/ALTER EXTENSION . Для этого рекомендуется временно сменить search_path на ‘pg_catalog, pg_temp’ и добавить явные указания схемы, в которую устанавливается расширение, везде, где это требуется. (Этот приём также может быть полезен при создании представлений.) Практические примеры вы можете найти в модулях contrib в исходном коде PostgreSQL .

Ссылки на другие расширения крайне сложно полностью обезопасить, отчасти из-за отсутствия понимания, в какой схеме находится другое расширения. Риски уменьшаются, если оба расширения устанавливаются в одну схему, так как в этом случае зловредный объект не может оказаться перед объектами в схеме целевого расширения при используемом во время установки search_path . Однако в настоящее время нет механизма, который бы это требовал. Поэтому на данный момент рекомендуется не помечать расширение как доверенное, если оно зависит от других, не считая тех, что уже установлены в схему pg_catalog .

38.17.7. Пример расширения

Файл скрипта pair—1.0.sql выглядит так:

Управляющий файл pair.control выглядит так:

Хотя вам вряд ли понадобится сборочный файл, только для того, чтобы установить эти два файла в нужный каталог, вы можете использовать Makefile следующего содержания:

Этот Makefile опирается на инфраструктуру PGXS , которая описывается в Разделе 38.18. С ним команда make install установит управляющий файл и скрипт в правильный каталог, который определит pg_config .

Когда эти файлы будут установлены, выполните команду CREATE EXTENSION , чтобы загрузить объекты в определённую базу данных.


Читайте также:  Get permission directory linux