バージョンごとのドキュメント一覧

38.17. 関連するオブジェクトを拡張としてパッケージ化 #

<title>Packaging Related Objects into an Extension</title>

A useful extension to <productname>PostgreSQL</productname> typically includes multiple SQL objects; for example, a new data type will require new functions, new operators, and probably new index operator classes. It is helpful to collect all these objects into a single package to simplify database management. <productname>PostgreSQL</productname> calls such a package an <firstterm>extension</firstterm>. To define an extension, you need at least a <firstterm>script file</firstterm> that contains the <acronym>SQL</acronym> commands to create the extension's objects, and a <firstterm>control file</firstterm> that specifies a few basic properties of the extension itself. If the extension includes C code, there will typically also be a shared library file into which the C code has been built. Once you have these files, a simple <link linkend="sql-createextension"><command>CREATE EXTENSION</command></link> command loads the objects into your database. PostgreSQLへの有用な拡張は通常、複数のSQLオブジェクトを含んでいます。 例えば、新しいデータ型は新しい関数、新しい演算子、おそらく新しいインデックス演算子クラスを必要とします。 これらのオブジェクトをすべて単一のパッケージとしてまとめることは、データベース管理を単純化するために役に立ちます。 PostgreSQLではこうしたパッケージを拡張とよびます。 拡張を定義するためには、少なくとも、拡張のオブジェクトを作成するためのSQLコマンドを含むスクリプトファイル、拡張自身の数個の基本属性を指定する制御ファイルが必要です。 また拡張がCコードを含む場合、通常Cコードで構築された共有ライブラリが存在します。 これらのファイルがあれば、単純なCREATE EXTENSIONコマンドがそのオブジェクトをデータベース内に読み込みます。

The main advantage of using an extension, rather than just running the <acronym>SQL</acronym> script to load a bunch of <quote>loose</quote> objects into your database, is that <productname>PostgreSQL</productname> will then understand that the objects of the extension go together. You can drop all the objects with a single <link linkend="sql-dropextension"><command>DROP EXTENSION</command></link> command (no need to maintain a separate <quote>uninstall</quote> script). Even more useful, <application>pg_dump</application> knows that it should not dump the individual member objects of the extension &mdash; it will just include a <command>CREATE EXTENSION</command> command in dumps, instead. This vastly simplifies migration to a new version of the extension that might contain more or different objects than the old version. Note however that you must have the extension's control, script, and other files available when loading such a dump into a new database. 拡張を使用する主な利点は、SQLスクリプトを実行するだけでデータベースに粗ななオブジェクトの群をロードできることではなく、PostgreSQLが拡張のオブジェクトをまとまったものと理解できることです。 単一のDROP EXTENSIONコマンドでオブジェクトすべてを削除できます(個々のアンインストールスクリプトを保守する必要はありません)。 もっと有用なことは、pg_dumpが拡張の個々のメンバオブジェクトをダンプしてはならないことを把握していることです。 代わりにダンプ内にはCREATE EXTENSIONコマンドだけが含まれます。 これは、古いバージョンよりも多くのまたは異なるオブジェクトを含む可能性がある、拡張の新しいバージョンへの移行を大きく単純化します。 しかし、こうしたダンプを新しいデータベースにロードする際には、拡張の制御ファイル、スクリプトファイル、その他のファイルが利用できるようにしておく必要があります。

<productname>PostgreSQL</productname> will not let you drop an individual object contained in an extension, except by dropping the whole extension. Also, while you can change the definition of an extension member object (for example, via <command>CREATE OR REPLACE FUNCTION</command> for a function), bear in mind that the modified definition will not be dumped by <application>pg_dump</application>. Such a change is usually only sensible if you concurrently make the same change in the extension's script file. (But there are special provisions for tables containing configuration data; see <xref linkend="extend-extensions-config-tables"/>.) In production situations, it's generally better to create an extension update script to perform changes to extension member objects. PostgreSQLはユーザに、拡張全体を削除させる以外に、拡張内に含まれる個々のオブジェクトを削除させません。 また、拡張のメンバオブジェクトの定義を変更する(例えば関数ではCREATE OR REPLACE FUNCTIONを介して変更する)ことはできますが、変更した定義はpg_dumpによりダンプされないことに留意してください。 こうした変更は通常、同時に拡張のスクリプトファイルにも同じ変更を行った場合のみ認識できます。 (しかし設定データを持つテーブルに対しては特殊な準備があります。38.17.3を参照してください。) 本番環境では、拡張メンバオブジェクトへの変更を処理するために拡張更新スクリプトを作成するのが一般により良い方法です。

The extension script may set privileges on objects that are part of the extension, using <command>GRANT</command> and <command>REVOKE</command> statements. The final set of privileges for each object (if any are set) will be stored in the <link linkend="catalog-pg-init-privs"><structname>pg_init_privs</structname></link> system catalog. When <application>pg_dump</application> is used, the <command>CREATE EXTENSION</command> command will be included in the dump, followed by the set of <command>GRANT</command> and <command>REVOKE</command> statements necessary to set the privileges on the objects to what they were at the time the dump was taken. 拡張スクリプトは、GRANT文とREVOKE文を使って拡張の一部のオブジェクトに権限を設定するかもしれません。 それぞれのオブジェクト(どれかが設定される場合)の最終的な権限のセットは、pg_init_privsシステムカタログに格納されます。 pg_dumpが使用されると、CREATE EXTENSIONコマンドがダンプ内に含まれ、オブジェクトの権限をダンプが取られた時点のものに設定するために必要となるGRANT文とREVOKE文が後に続きます。

<productname>PostgreSQL</productname> does not currently support extension scripts issuing <command>CREATE POLICY</command> or <command>SECURITY LABEL</command> statements. These are expected to be set after the extension has been created. All RLS policies and security labels on extension objects will be included in dumps created by <application>pg_dump</application>. PostgreSQLは、現在拡張スクリプトにてCREATE POLICY文やSECURITY LABEL文の発行をサポートしていません。 これらは拡張が作成された後に設定されるべきです。 拡張オブジェクトのすべての行セキュリティポリシーとセキュリティラベルはpg_dumpによって作成されたダンプに含まれます。

The extension mechanism also has provisions for packaging modification scripts that adjust the definitions of the SQL objects contained in an extension. For example, if version 1.1 of an extension adds one function and changes the body of another function compared to 1.0, the extension author can provide an <firstterm>update script</firstterm> that makes just those two changes. The <command>ALTER EXTENSION UPDATE</command> command can then be used to apply these changes and track which version of the extension is actually installed in a given database. また拡張機構は、拡張に含まれるSQLオブジェクトの定義を調整するパッケージ調整スクリプトを準備しています。 例えば、拡張のバージョン1.1でバージョン1.0と比べて1つの関数を追加し、他の関数本体を変更する場合、拡張の作成者はこれらの2つの変更のみを行う更新スクリプトを提供できます。 そしてALTER EXTENSION UPDATEコマンドを使用して、これらの変更を適用し、指定されたデータベース内に実際にインストールされた拡張のバージョンが何かを記録します。

The kinds of SQL objects that can be members of an extension are shown in the description of <link linkend="sql-alterextension"><command>ALTER EXTENSION</command></link>. Notably, objects that are database-cluster-wide, such as databases, roles, and tablespaces, cannot be extension members since an extension is only known within one database. (Although an extension script is not prohibited from creating such objects, if it does so they will not be tracked as part of the extension.) Also notice that while a table can be a member of an extension, its subsidiary objects such as indexes are not directly considered members of the extension. Another important point is that schemas can belong to extensions, but not vice versa: an extension as such has an unqualified name and does not exist <quote>within</quote> any schema. The extension's member objects, however, will belong to schemas whenever appropriate for their object types. It may or may not be appropriate for an extension to own the schema(s) its member objects are within. 拡張のメンバとなり得るSQLオブジェクトの種類をALTER EXTENSIONで説明します。 拡張は1つのデータベースの中でのみ認識されますので、データベース、ロール、テーブル空間などデータベースクラスタ全体のオブジェクトは拡張のメンバにすることができないことに注意してください。 (拡張のスクリプトでこうしたオブジェクトを生成することは禁止されていませんが、作成したとしても、拡張の一部として記録されません。) また、テーブルは拡張のメンバになることができますが、インデックスなどそれに付随するオブジェクトは拡張の直接的なメンバとはみなされません。 もう一つの重要な点は、スキーマは拡張に属すことがありますがその逆はないということです。 拡張は非修飾名でいかなるスキーマの中にも存在しません。 しかし、拡張のメンバオブジェクトはオブジェクトの型が適切であればスキーマに属します。 拡張が自身のメンバオブジェクトが属するスキーマを所有することは適切かも知れませんし、そうでないかも知れません。

If an extension's script creates any temporary objects (such as temp tables), those objects are treated as extension members for the remainder of the current session, but are automatically dropped at session end, as any temporary object would be. This is an exception to the rule that extension member objects cannot be dropped without dropping the whole extension. ある拡張のスクリプトが(一時テーブルのような)一時オブジェクトを作成する場合、現在のセッションで、以降そのオブジェクトは拡張のメンバーとして扱われます。 しかしすべての一時オブジェクト同様、セッションの終わりに削除されます。 これは、拡張全体を削除することなしに、拡張のメンバーオブジェクトは削除できない、という規則の例外です。

38.17.1. 拡張のファイル #

<title>Extension Files</title>

The <command>CREATE EXTENSION</command> command relies on a control file for each extension, which must be named the same as the extension with a suffix of <literal>.control</literal>, and must be placed in the installation's <literal>SHAREDIR/extension</literal> directory. There must also be at least one <acronym>SQL</acronym> script file, which follows the naming pattern <literal><replaceable>extension</replaceable>&#45;-<replaceable>version</replaceable>.sql</literal> (for example, <literal>foo&#45;-1.0.sql</literal> for version <literal>1.0</literal> of extension <literal>foo</literal>). By default, the script file(s) are also placed in the <literal>SHAREDIR/extension</literal> directory; but the control file can specify a different directory for the script file(s). CREATE EXTENSIONコマンドは各拡張に関して、拡張と同じ名前に.controlという拡張子を持つファイル名である必要がある、制御ファイルに依存します。 また、このファイルはインストレーションのSHAREDIR/extensionディレクトリ内に存在しなければなりません。 また少なくとも1つの、extension--version.sqlという命名規約(例えばfoo拡張のバージョン1.0ではfoo--1.0.sql)に従ったSQLスクリプトファイルが存在しなければなりません。 デフォルトでは、このスクリプトファイルもSHAREDIR/extensionディレクトリに格納されますが、制御ファイルでスクリプトファイルを別のディレクトリに指定できます。

The file format for an extension control file is the same as for the <filename>postgresql.conf</filename> file, namely a list of <replaceable>parameter_name</replaceable> <literal>=</literal> <replaceable>value</replaceable> assignments, one per line. Blank lines and comments introduced by <literal>#</literal> are allowed. Be sure to quote any value that is not a single word or number. 拡張の制御ファイルのファイル書式はpostgresql.confファイルと同じです。 すなわち、parameter_name = valueという代入を1行当たり1つ記述します。 空行および#から始まるコメントが許されます。 単一の単語または数字ではない値にはすべて引用符で確実にくくってください。

A control file can set the following parameters: 制御ファイルは以下のパラメータを設定できます。

directory (string) #

The directory containing the extension's <acronym>SQL</acronym> script file(s). Unless an absolute path is given, the name is relative to the installation's <literal>SHAREDIR</literal> directory. The default behavior is equivalent to specifying <literal>directory = 'extension'</literal>. 拡張のSQLスクリプトファイルを含むディレクトリです。 絶対パスで指定されていない限り、この名前はインストレーションのSHAREDIRディレクトリからの相対パスになります。 デフォルトの動作はdirectory = 'extension'と指定した場合と同じです。

default_version (string) #

The default version of the extension (the one that will be installed if no version is specified in <command>CREATE EXTENSION</command>). Although this can be omitted, that will result in <command>CREATE EXTENSION</command> failing if no <literal>VERSION</literal> option appears, so you generally don't want to do that. 拡張のデフォルトのバージョン(CREATE EXTENSIONでバージョン指定がない場合にインストールされるバージョン)です。 これは省略できますが、その場合VERSIONオプションがないCREATE EXTENSIONは失敗します。 ですので通常省略しようとは思わないでしょう。

comment (string) #

A comment (any string) about the extension. The comment is applied when initially creating an extension, but not during extension updates (since that might override user-added comments). Alternatively, the extension's comment can be set by writing a <xref linkend="sql-comment"/> command in the script file. 拡張に関するコメント(任意の文字列)です。 最初に拡張が作成されるときにコメントは適用されますが、拡張が更新される間はされません(ユーザが追加したコメントを上書いてしまうため)。 この他の方法として、スクリプトファイル内でCOMMENTコマンドを使用してコメントを設定できます。

encoding (string) #

The character set encoding used by the script file(s). This should be specified if the script files contain any non-ASCII characters. Otherwise the files will be assumed to be in the database encoding. スクリプトファイルで使用される文字セット符号化方式です。 スクリプトファイルに何らかの非ASCII文字が含まれる場合に指定しなければなりません。 指定がなければ、ファイルはデータベース符号化方式であると仮定されます。

module_pathname (string) #

The value of this parameter will be substituted for each occurrence of <literal>MODULE_PATHNAME</literal> in the script file(s). If it is not set, no substitution is made. Typically, this is set to <literal>$libdir/<replaceable>shared_library_name</replaceable></literal> and then <literal>MODULE_PATHNAME</literal> is used in <command>CREATE FUNCTION</command> commands for C-language functions, so that the script files do not need to hard-wire the name of the shared library. このパラメータの値でスクリプトファイル内のMODULE_PATHNAMEの出現箇所が置換されます。 設定されていない場合は置換は行われません。 通常これは、スクリプトファイル内で共有ライブラリの名前を直接書き込む必要がなくなるように$libdir/shared_library_nameに設定され、C言語関数ではCREATE FUNCTIONコマンド中でMODULE_PATHNAMEを使用します。

requires (string) #

A list of names of extensions that this extension depends on, for example <literal>requires = 'foo, bar'</literal>. Those extensions must be installed before this one can be installed. 拡張が依存する拡張の名前のリストです。 例えばrequires = 'foo, bar'です。 対象の拡張がインストールできるようになる前に、これらの拡張がインストールされていなければなりません。

no_relocate (string) #

A list of names of extensions that this extension depends on that should be barred from changing their schemas via <command>ALTER EXTENSION ... SET SCHEMA</command>. This is needed if this extension's script references the name of a required extension's schema (using the <literal>@extschema:<replaceable>name</replaceable>@</literal> syntax) in a way that cannot track renames. この拡張が依存していて、ALTER EXTENSION ... SET SCHEMAでスキーマを変更することを禁止される拡張の名前の一覧です。 この拡張のスクリプトが、(@extschema:name@構文を使って)必要な拡張のスキーマの名前を参照し、名前変更を追跡できない場合に必要です。

superuser (boolean) #

If this parameter is <literal>true</literal> (which is the default), only superusers can create the extension or update it to a new version (but see also <varname>trusted</varname>, below). If it is set to <literal>false</literal>, just the privileges required to execute the commands in the installation or update script are required. This should normally be set to <literal>true</literal> if any of the script commands require superuser privileges. (Such commands would fail anyway, but it's more user-friendly to give the error up front.) このパラメータがtrue(デフォルト)の場合、スーパーユーザのみが拡張を作成または新しいバージョンに更新できます(ただし、後述するtrustedも参照してください)。 falseに設定されている場合は、インストール中のコマンド実行またはスクリプト更新のために必要な権限のみが必要とされます。 いずれかスクリプトコマンドがスーパーユーザ権限を必要とするなら、通常はtrueに設定されるべきです。 (このようなコマンドはいずれにせよ失敗するでしょうけれども、前もってエラーを出す方がよりユーザフレンドリです。)

trusted (boolean) #

This parameter, if set to <literal>true</literal> (which is not the default), allows some non-superusers to install an extension that has <varname>superuser</varname> set to <literal>true</literal>. Specifically, installation will be permitted for anyone who has <literal>CREATE</literal> privilege on the current database. When the user executing <command>CREATE EXTENSION</command> is not a superuser but is allowed to install by virtue of this parameter, then the installation or update script is run as the bootstrap superuser, not as the calling user. This parameter is irrelevant if <varname>superuser</varname> is <literal>false</literal>. Generally, this should not be set true for extensions that could allow access to otherwise-superuser-only abilities, such as file system access. Also, marking an extension trusted requires significant extra effort to write the extension's installation and update script(s) securely; see <xref linkend="extend-extensions-security"/>. このパラメータは、true(デフォルトではありません)に設定されている場合、一部の非スーパーユーザがsuperusertrueを設定している拡張をインストールできるようにします。 具体的には、現在のデータベースにCREATE権限を持っているユーザにインストールが許可されるようになります。 CREATE EXTENSIONを実行するユーザがスーパーユーザでないけれども本パラメータの効力でインストールできるとき、インストールやスクリプトの更新は実行したユーザではなく、サービス起動のスーパーユーザとして実行されます。 superuserfalseの場合、本パラメータは無意味です。 一般に、ファイルシステムのアクセスなど、別の方法ではスーパーユーザのみができることにアクセスができる拡張に対して、これをtrueにすべきではありません。 また、拡張をtrustedとして作成するには、拡張のインストールとスクリプト更新を安全に記述するために、かなりの追加の労力が影響が必要です。38.17.6を参照してください。

relocatable (boolean) #

An extension is <firstterm>relocatable</firstterm> if it is possible to move its contained objects into a different schema after initial creation of the extension. The default is <literal>false</literal>, i.e., the extension is not relocatable. See <xref linkend="extend-extensions-relocation"/> for more information. 拡張を最初に作成した後に拡張により含まれるオブジェクトを別のスキーマに移動できる場合、拡張は再配置可能です。 デフォルトはfalse、つまり、拡張は再配置可能ではありません。 詳しくは38.17.2を参照してください。

schema (string) #

This parameter can only be set for non-relocatable extensions. It forces the extension to be loaded into exactly the named schema and not any other. The <varname>schema</varname> parameter is consulted only when initially creating an extension, not during extension updates. See <xref linkend="extend-extensions-relocation"/> for more information. このパラメータは再配置可能ではない拡張に対してのみ設定できます。 拡張が指名したスキーマのみにロードされ、他にはロードされないことを強制します。 schemaパラメータは、拡張を最初に作成するときにのみ参照され、拡張が更新される間はされません。 詳しくは38.17.2を参照してください。

In addition to the primary control file <literal><replaceable>extension</replaceable>.control</literal>, an extension can have secondary control files named in the style <literal><replaceable>extension</replaceable>&#45;-<replaceable>version</replaceable>.control</literal>. If supplied, these must be located in the script file directory. Secondary control files follow the same format as the primary control file. Any parameters set in a secondary control file override the primary control file when installing or updating to that version of the extension. However, the parameters <varname>directory</varname> and <varname>default_version</varname> cannot be set in a secondary control file. 主制御ファイルextension.controlに加え、拡張はextension--version.controlという形の名前の副制御ファイルを持つことができます。 これらを提供する場合は、スクリプトファイルディレクトリに格納しなければなりません。 副制御ファイルは主制御ファイルと同じ書式に従います。 拡張の対応するバージョンをインストールまたは更新する時、副制御ファイル内で設定されるパラメータはいずれも、主制御ファイルを上書きします。 しかしdirectoryおよびdefault_versionパラメータは副制御ファイルで設定することはできません。

An extension's <acronym>SQL</acronym> script files can contain any SQL commands, except for transaction control commands (<command>BEGIN</command>, <command>COMMIT</command>, etc.) and commands that cannot be executed inside a transaction block (such as <command>VACUUM</command>). This is because the script files are implicitly executed within a transaction block. 拡張のSQLスクリプトファイルにはトランザクション制御コマンド(BEGINCOMMITなど)およびトランザクションブロックの内側で実行できないコマンド(VACUUMなど)を除く任意のSQLコマンドを含めることができます。 スクリプトファイルが暗黙的にトランザクションブロック内で実行されるためです。

An extension's <acronym>SQL</acronym> script files can also contain lines beginning with <literal>\echo</literal>, which will be ignored (treated as comments) by the extension mechanism. This provision is commonly used to throw an error if the script file is fed to <application>psql</application> rather than being loaded via <command>CREATE EXTENSION</command> (see example script in <xref linkend="extend-extensions-example"/>). Without that, users might accidentally load the extension's contents as <quote>loose</quote> objects rather than as an extension, a state of affairs that's a bit tedious to recover from. 拡張のSQLスクリプトファイルには、\echoから始まる行を含めることができます。 この行は拡張の機構では無視されます(コメントとして扱われます)。 これは、このスクリプトがCREATE EXTENSION38.17.7のスクリプト例を参照)ではなくpsqlに渡された場合にエラーを発生するために一般的に使用するために用意されたものです。 これがないと、ユーザは間違って拡張としてではなく、まとまっていないオブジェクトとして拡張の内容をロードしてしまい、復旧が多少困難な状態になる可能性があります。

If the extension script contains the string <literal>@extowner@</literal>, that string is replaced with the (suitably quoted) name of the user calling <command>CREATE EXTENSION</command> or <command>ALTER EXTENSION</command>. Typically this feature is used by extensions that are marked trusted to assign ownership of selected objects to the calling user rather than the bootstrap superuser. (One should be careful about doing so, however. For example, assigning ownership of a C-language function to a non-superuser would create a privilege escalation path for that user.) 拡張のスクリプトに文字列@extowner@が含まれている場合、この文字列は、CREATE EXTENSIONALTER EXTENSIONを実行した(適切にクォートされた)ユーザ名で置き換えられます。 典型的には、この機能はtrustedと印付けされた拡張が選択されたオブジェクトにサービス起動のスーパーユーザではなく実行したユーザを所有者として割り当てる際に使われます。 (とはいえ、このようにするには注意深くすべきです。例えば、C言語関数の所有者を非スーパーユーザに割り当てると、そのユーザに権限昇格の経路を作ることになるでしょう)

While the script files can contain any characters allowed by the specified encoding, control files should contain only plain ASCII, because there is no way for <productname>PostgreSQL</productname> to know what encoding a control file is in. In practice this is only an issue if you want to use non-ASCII characters in the extension's comment. Recommended practice in that case is to not use the control file <varname>comment</varname> parameter, but instead use <command>COMMENT ON EXTENSION</command> within a script file to set the comment. スクリプトファイルは指定した符号化方式で認められる任意の文字を含めることができますが、PostgreSQLが制御ファイルの符号化方式が何かを把握する方法がありませんので、制御ファイルにはASCII文字のみを含めなければなりません。 実際には、拡張のコメントに非ASCII文字を含めたい場合にのみ、これが問題になります。 このような場合には、制御ファイルのcommentを使用せず、代わりにコメントを設定するためにスクリプトファイル内でCOMMENT ON EXTENSIONを使用することを勧めます。

38.17.2. 拡張の再配置性 #

<title>Extension Relocatability</title>

Users often wish to load the objects contained in an extension into a different schema than the extension's author had in mind. There are three supported levels of relocatability: ユーザは拡張に含まれるオブジェクトを拡張の作成者が考えていたスキーマとは別のスキーマにロードしたいとよく考えます。 再配置性に関して3つのレベルがサポートされます。

  • A fully relocatable extension can be moved into another schema at any time, even after it's been loaded into a database. This is done with the <command>ALTER EXTENSION SET SCHEMA</command> command, which automatically renames all the member objects into the new schema. Normally, this is only possible if the extension contains no internal assumptions about what schema any of its objects are in. Also, the extension's objects must all be in one schema to begin with (ignoring objects that do not belong to any schema, such as procedural languages). Mark a fully relocatable extension by setting <literal>relocatable = true</literal> in its control file. 完全な再配置可能な拡張は、いつでも、データベースにロードされた後であっても、他のスキーマに移動させることができます。 これは、自動的にすべてのメンバオブジェクトを新しいスキーマに名前を変更する、ALTER EXTENSION SET SCHEMAを用いて行います。 通常これは、拡張がオブジェクトが含まれるスキーマが何かに関して内部的な仮定を持たない場合のみ可能です。 また、拡張のオブジェクト(手続き言語など何らかのスキーマに属さないオブジェクトは無視して)はすべて最初に1つのスキーマ内に存在しなければなりません。 制御ファイル内でrelocatable = trueと設定することで、完全な再配置可能と印付けます。

  • An extension might be relocatable during installation but not afterwards. This is typically the case if the extension's script file needs to reference the target schema explicitly, for example in setting <literal>search_path</literal> properties for SQL functions. For such an extension, set <literal>relocatable = false</literal> in its control file, and use <literal>@extschema@</literal> to refer to the target schema in the script file. All occurrences of this string will be replaced by the actual target schema's name (double-quoted if necessary) before the script is executed. The user can set the target schema using the <literal>SCHEMA</literal> option of <command>CREATE EXTENSION</command>. 拡張はインストール処理の間再配置可能ですが、その後再配置することはできません。 通常これは、拡張のスクリプトファイルが、SQL関数用のsearch_path属性の設定など、対象のスキーマを明示的に参照する必要がある場合です。 こうした拡張では、制御ファイルでrelocatable = falseと設定し、スクリプトファイル内で対象のスキーマを参照するために@extschema@を設定してください。 この文字列の出現箇所はすべて、スクリプトが実行される前に、(必要ならば二重引用符で括られて)実際の対象のスキーマ名に置換されます。 ユーザはCREATE EXTENSIONSCHEMAオプションを使用して対象のスキーマを設定できます。

  • If the extension does not support relocation at all, set <literal>relocatable = false</literal> in its control file, and also set <literal>schema</literal> to the name of the intended target schema. This will prevent use of the <literal>SCHEMA</literal> option of <command>CREATE EXTENSION</command>, unless it specifies the same schema named in the control file. This choice is typically necessary if the extension contains internal assumptions about its schema name that can't be replaced by uses of <literal>@extschema@</literal>. The <literal>@extschema@</literal> substitution mechanism is available in this case too, although it is of limited use since the schema name is determined by the control file. 拡張が再配置をまったくサポートしない場合、制御ファイルでrelocatable = falseを設定し、かつ、schemaを意図している対象スキーマの名前に設定してください。 これは、制御ファイル内で指定されたスキーマと同じ名前が指定されていない限り、CREATE EXTENSIONSCHEMAオプションの指定を阻止します。 この選択は通常、拡張が@extschema@を使用して置き換えることができないスキーマ名について内部的な仮定を持つ場合に必要です。 @extschema@置換機構はこの場合でも使用できますが、スキーマ名が制御ファイルによって決定されますので、用途は限定されます。

In all cases, the script file will be executed with <xref linkend="guc-search-path"/> initially set to point to the target schema; that is, <command>CREATE EXTENSION</command> does the equivalent of this: すべての場合において、スクリプトファイルは対象のスキーマを指し示すようにあらかじめ設定したsearch_pathを用いて実行されます。 つまりCREATE EXTENSIONは以下と同じことを行います。

SET LOCAL search_path TO @extschema@, pg_temp;

This allows the objects created by the script file to go into the target schema. The script file can change <varname>search_path</varname> if it wishes, but that is generally undesirable. <varname>search_path</varname> is restored to its previous setting upon completion of <command>CREATE EXTENSION</command>. これによりスクリプトファイルで作成されるオブジェクトを対象のスキーマ内に格納できます。 スクリプトファイルは要望に応じてsearch_pathを変更できますが、一般的には望まれません。 CREATE EXTENSIONの実行後、search_pathは以前の設定に戻されます。

The target schema is determined by the <varname>schema</varname> parameter in the control file if that is given, otherwise by the <literal>SCHEMA</literal> option of <command>CREATE EXTENSION</command> if that is given, otherwise the current default object creation schema (the first one in the caller's <varname>search_path</varname>). When the control file <varname>schema</varname> parameter is used, the target schema will be created if it doesn't already exist, but in the other two cases it must already exist. 対象のスキーマは制御ファイル内のschemaパラメータがあればこのパラメータにより決定されます。 このパラメータがなければ、CREATE EXTENSIONSCHEMAがあればこの値で決まり、これ以外の場合は現在のデフォルトのオブジェクト生成用スキーマ(呼び出し元のsearch_pathの最初のもの)になります。 制御ファイルのschemaパラメータが使用される時、対象のスキーマが存在しない場合は作成されますが、これ以外の2つの場合ではすでに存在しなければなりません。

If any prerequisite extensions are listed in <varname>requires</varname> in the control file, their target schemas are added to the initial setting of <varname>search_path</varname>, following the new extension's target schema. This allows their objects to be visible to the new extension's script file. 何らかの事前に必要な拡張が制御ファイル内のrequiresに列挙されていた場合、それらのターゲットスキーマは新しい機能拡張のターゲットスキーマに続いてsearch_pathの初期設定に追加されます。 これにより新しい拡張のスクリプトファイルからそれらのオブジェクトが可視になります。

For security, <literal>pg_temp</literal> is automatically appended to the end of <varname>search_path</varname> in all cases. 安全のため、全てのケースにおいてpg_tempは自動的にsearch_pathの最後に追記されます。

Although a non-relocatable extension can contain objects spread across multiple schemas, it is usually desirable to place all the objects meant for external use into a single schema, which is considered the extension's target schema. Such an arrangement works conveniently with the default setting of <varname>search_path</varname> during creation of dependent extensions. 再配置不可能な拡張は複数スキーマにまたがるオブジェクトを含めることができますが、通常、外部使用を意図したオブジェクトはすべて単一スキーマに格納することが望まれます。 この単一スキーマが拡張の対象のスキーマとみなされます。 こうした調整は依存する拡張を作成する間、デフォルトのsearch_path設定を都合に合わせて扱います。

If an extension references objects belonging to another extension, it is recommended to schema-qualify those references. To do that, write <literal>@extschema:<replaceable>name</replaceable>@</literal> in the extension's script file, where <replaceable>name</replaceable> is the name of the other extension (which must be listed in this extension's <literal>requires</literal> list). This string will be replaced by the name (double-quoted if necessary) of that extension's target schema. Although this notation avoids the need to make hard-wired assumptions about schema names in the extension's script file, its use may embed the other extension's schema name into the installed objects of this extension. (Typically, that happens when <literal>@extschema:<replaceable>name</replaceable>@</literal> is used inside a string literal, such as a function body or a <varname>search_path</varname> setting. In other cases, the object reference is reduced to an OID during parsing and does not require subsequent lookups.) If the other extension's schema name is so embedded, you should prevent the other extension from being relocated after yours is installed, by adding the name of the other extension to this one's <literal>no_relocate</literal> list. 拡張が別の拡張に属するオブジェクトを参照する場合は、それらの参照をスキーマ修飾することをお勧めします。 これを行うには、拡張のスクリプトファイルに@extschema:name@と記述します。ここで、nameは他の拡張の名前です(他の拡張はこの拡張のrequiresリストに記載されていることが必要です)。 この文字列は、その拡張の対象スキーマの名前に(必要なら二重引用符で括られて)置き換えられます。 この表記では、拡張のスクリプトファイルでスキーマ名が固定されているという仮定の必要性は回避されますが、この表記を使用すると、この拡張のインストールされたオブジェクトに他の拡張のスキーマ名を埋め込むことになります。 (通常、これは@extschema:name@が関数本体やsearch_path設定などの文字列リテラルの内部で使用される場合に発生します。 その他の場合では、オブジェクト参照は解析中にOIDへと縮小され、その後の検索は必要ありません。) 他の拡張のスキーマ名がそのように埋め込まれている場合は、インストール後に他の拡張が再配置されないようにすることが必要です。これを行うには、他の拡張の名前をこの拡張のno_relocateリストに追加します。

38.17.3. 拡張設定テーブル #

<title>Extension Configuration Tables</title>

Some extensions include configuration tables, which contain data that might be added or changed by the user after installation of the extension. Ordinarily, if a table is part of an extension, neither the table's definition nor its content will be dumped by <application>pg_dump</application>. But that behavior is undesirable for a configuration table; any data changes made by the user need to be included in dumps, or the extension will behave differently after a dump and restore. 一部の拡張は、拡張をインストールした後でユーザにより追加または変更される可能性があるデータを持つ設定テーブルを含みます。 通常、テーブルが拡張の一部である場合、テーブル定義もその内容もpg_dumpによりダンプされません。 しかしこの振舞いは設定テーブルの場合望まれません。 ユーザによってなされたデータ変更はダンプ内に含まれなければなりません。 さもないとダンプしリストアした後で拡張の動作が変わってしまいます。

To solve this problem, an extension's script file can mark a table or a sequence it has created as a configuration relation, which will cause <application>pg_dump</application> to include the table's or the sequence's contents (not its definition) in dumps. To do that, call the function <function>pg_extension_config_dump(regclass, text)</function> after creating the table or the sequence, for example この問題を解消するために、拡張のスクリプトファイルでは設定リレーションとして作成されるテーブル、またはシーケンスに印を付け、pg_dumpにテーブルの、またはシーケンスの内容をダンプに含める(定義は含まれません)ようにさせることができます。 このためには、以下の例のようにテーブル、またはシーケンスを作成した後にpg_extension_config_dump(regclass, text)関数を呼び出してください。

CREATE TABLE my_config (key text, value text);
CREATE SEQUENCE my_config_seq;

SELECT pg_catalog.pg_extension_config_dump('my_config', '');
SELECT pg_catalog.pg_extension_config_dump('my_config_seq', '');

Any number of tables or sequences can be marked this way. Sequences associated with <type>serial</type> or <type>bigserial</type> columns can be marked as well. 任意数のテーブル、またはシーケンスをこの方法で印付けることができます。 serial列またはbigserial列に関連したシーケンスが、同様に印付けることができます。

When the second argument of <function>pg_extension_config_dump</function> is an empty string, the entire contents of the table are dumped by <application>pg_dump</application>. This is usually only correct if the table is initially empty as created by the extension script. If there is a mixture of initial data and user-provided data in the table, the second argument of <function>pg_extension_config_dump</function> provides a <literal>WHERE</literal> condition that selects the data to be dumped. For example, you might do pg_extension_config_dumpの第2引数が空文字列である場合、テーブルのすべての内容がpg_dumpによりダンプされます。 これは、拡張のスクリプトによって作成された初期段階においてテーブルが空である場合のみ正しいものです。 テーブルの中で初期データとユーザが提供したデータが混在する場合、pg_extension_config_dumpの第2引数においてダンプすべきデータを選択するWHERE条件を提供します。 以下に例を示します。

CREATE TABLE my_config (key text, value text, standard_entry boolean);

SELECT pg_catalog.pg_extension_config_dump('my_config', 'WHERE NOT standard_entry');

and then make sure that <structfield>standard_entry</structfield> is true only in the rows created by the extension's script. このようにした後、拡張のスクリプトで作成される行のみでstandard_entryが確実に真になるようにします。

For sequences, the second argument of <function>pg_extension_config_dump</function> has no effect. シーケンスにおいて、pg_extension_config_dumpの第2引数は何も影響を及ぼしません。

More complicated situations, such as initially-provided rows that might be modified by users, can be handled by creating triggers on the configuration table to ensure that modified rows are marked correctly. 初期状態で提供される行がユーザによって変更されるようなもっと複雑な状況では、設定テーブルに対するトリガを作成して、変更された行が正しく印付けられることを確実にするように取り扱うことができます。

You can alter the filter condition associated with a configuration table by calling <function>pg_extension_config_dump</function> again. (This would typically be useful in an extension update script.) The only way to mark a table as no longer a configuration table is to dissociate it from the extension with <command>ALTER EXTENSION ... DROP TABLE</command>. pg_extension_config_dumpを再度呼び出すことにより、設定テーブルに関連付いたフィルタ条件を変更できます。 (通常これは拡張の更新スクリプト内で役に立つでしょう。) 設定ファイルからテーブルを取り除くように印付ける方法は、ALTER EXTENSION ... DROP TABLEを用いてテーブルを拡張から分離するしかありません。

Note that foreign key relationships between these tables will dictate the order in which the tables are dumped out by pg_dump. Specifically, pg_dump will attempt to dump the referenced-by table before the referencing table. As the foreign key relationships are set up at CREATE EXTENSION time (prior to data being loaded into the tables) circular dependencies are not supported. When circular dependencies exist, the data will still be dumped out but the dump will not be able to be restored directly and user intervention will be required. このテーブルとの外部キーの関係は、テーブルがpg_dumpによってダンプされる順序に影響します。 特に、pg_dumpは参照しているテーブルの前に参照されているテーブルをダンプしようとします。 外部キーの関係はCREATE EXTENSION時(データがテーブルにロードされる前)に設定されますので、循環依存はサポートされません。 循環依存が存在すれば、データはダンプされますが、そのダンプを直接はリストアできず、ユーザの介入が必要になります。

Sequences associated with <type>serial</type> or <type>bigserial</type> columns need to be directly marked to dump their state. Marking their parent relation is not enough for this purpose. serial列またはbigserial列に関連したシーケンスは、それらの状態をダンプするために直接印付けする必要があります。 親リレーションを印付けすることは、この目的に十分ではありません。

38.17.4. 拡張の更新 #

<title>Extension Updates</title>

One advantage of the extension mechanism is that it provides convenient ways to manage updates to the SQL commands that define an extension's objects. This is done by associating a version name or number with each released version of the extension's installation script. In addition, if you want users to be able to update their databases dynamically from one version to the next, you should provide <firstterm>update scripts</firstterm> that make the necessary changes to go from one version to the next. Update scripts have names following the pattern <literal><replaceable>extension</replaceable>&#45;-<replaceable>old_version</replaceable>&#45;-<replaceable>target_version</replaceable>.sql</literal> (for example, <literal>foo&#45;-1.0&#45;-1.1.sql</literal> contains the commands to modify version <literal>1.0</literal> of extension <literal>foo</literal> into version <literal>1.1</literal>). 拡張機構の1つの利点は、拡張のオブジェクトを定義するSQLコマンドの更新を簡便に管理する方法を提供していることです。 これは、拡張のインストール用スクリプトのリリース版それぞれにバージョン名称またはバージョン番号を関連付けることで行われます。 さらに、ユーザにあるバージョンから次のバージョンへ動的にデータベースを更新させることができるようにしたい場合、あるバージョンから次のバージョンまでの間に行われる必要な変更を行う更新スクリプトを提供しなければなりません。 更新スクリプトはextension--old_version--target_version.sqlというパターンに従った名前(例えば、foo--1.0--1.1.sqlfoo拡張のバージョン1.0からバージョン1.1に変更するコマンドを含みます。)を持たなければなりません。

Given that a suitable update script is available, the command <command>ALTER EXTENSION UPDATE</command> will update an installed extension to the specified new version. The update script is run in the same environment that <command>CREATE EXTENSION</command> provides for installation scripts: in particular, <varname>search_path</varname> is set up in the same way, and any new objects created by the script are automatically added to the extension. Also, if the script chooses to drop extension member objects, they are automatically dissociated from the extension. 適切な更新スクリプトが利用可能である場合、ALTER EXTENSION UPDATEコマンドはインストール済みの拡張を指定した新しいバージョンへ更新します。 更新スクリプトは、CREATE EXTENSIONがインストール用スクリプト向けに提供する環境と同じ環境で実行されます。 具体的にはsearch_pathは同じ方法で設定され、スクリプトにより作成される新しいオブジェクトはすべて自動的に拡張に追加されます。 また、スクリプトが拡張のメンバーオブジェクトを削除する場合には、それらのメンバーオブジェクトは拡張から自動的に分離されます。

If an extension has secondary control files, the control parameters that are used for an update script are those associated with the script's target (new) version. 拡張が副制御ファイルを持つ場合、更新スクリプトで使用される制御パラメータは、スクリプトの対象の(新しい)バージョンに関連付けされたものになります。

<command>ALTER EXTENSION</command> is able to execute sequences of update script files to achieve a requested update. For example, if only <literal>foo&#45;-1.0&#45;-1.1.sql</literal> and <literal>foo&#45;-1.1&#45;-2.0.sql</literal> are available, <command>ALTER EXTENSION</command> will apply them in sequence if an update to version <literal>2.0</literal> is requested when <literal>1.0</literal> is currently installed. ALTER EXTENSIONは、要求される更新を実現するために更新スクリプトを連続して実行できます。 例えばfoo--1.0--1.1.sqlfoo--1.1--2.0.sqlのみが利用可能であるとすると、現在1.0がインストールされている時にバージョン2.0への更新が要求された場合、ALTER EXTENSIONはこれらを順番に適用します。

<productname>PostgreSQL</productname> doesn't assume anything about the properties of version names: for example, it does not know whether <literal>1.1</literal> follows <literal>1.0</literal>. It just matches up the available version names and follows the path that requires applying the fewest update scripts. (A version name can actually be any string that doesn't contain <literal>&#45;-</literal> or leading or trailing <literal>-</literal>.) PostgreSQLはバージョン名称の特性についてまったく仮定を行いません。 例えば1.0の次が1.1であるかどうかを把握しません。 これは利用可能なバージョン名をかみ合わせ、もっとも少ない数の更新スクリプトを適用するために必要な経路を続けるだけです。 (バージョン名には、--を含まず先頭または最後に-が付かなければ、任意の文字を取ることができます。)

Sometimes it is useful to provide <quote>downgrade</quote> scripts, for example <literal>foo&#45;-1.1&#45;-1.0.sql</literal> to allow reverting the changes associated with version <literal>1.1</literal>. If you do that, be careful of the possibility that a downgrade script might unexpectedly get applied because it yields a shorter path. The risky case is where there is a <quote>fast path</quote> update script that jumps ahead several versions as well as a downgrade script to the fast path's start point. It might take fewer steps to apply the downgrade and then the fast path than to move ahead one version at a time. If the downgrade script drops any irreplaceable objects, this will yield undesirable results. ダウングレードスクリプトを提供することが便利な場合があります。 例えばfoo--1.1--1.0.sqlは、バージョン1.1に関連した変更を元に戻すことができます。 この場合、ダウングレードスクリプトがより短いパスを生成するために、予期せず適用されてしまう可能性に注意してください。 複数のバージョンをまたがって更新する近道更新スクリプトと近道の開始バージョンへのダウングレードスクリプトが存在する場合に危険性があります。 ダウングレードしてから近道となる更新スクリプトを実行する方が、バージョンを1つずつ進めるよりも少ない処理で済んでしまうかもしれません。 ダウングレードスクリプトが取り返しがつかないオブジェクトを何か削除してしまう場合、望まない結果になってしまいます。

To check for unexpected update paths, use this command: 想定外の更新経路かどうかを検査するためには、以下のコマンドを使用してください。

SELECT * FROM pg_extension_update_paths('extension_name');

This shows each pair of distinct known version names for the specified extension, together with the update path sequence that would be taken to get from the source version to the target version, or <literal>NULL</literal> if there is no available update path. The path is shown in textual form with <literal>&#45;-</literal> separators. You can use <literal>regexp_split_to_array(path,'&#45;-')</literal> if you prefer an array format. これは指定した拡張の個々の既知のバージョン名の組み合わせをそれぞれ、元のバージョンから対象のバージョンへ進む時に取られる更新経路順、またはもし利用できる更新経路がなければNULLを付けて、表示します。 経路は--を区切り文字として使用したテキスト形式で表示されます。 配列形式の方が良ければregexp_split_to_array(path,'--')を使用できます。

38.17.5. 更新スクリプトを利用した拡張のインストール #

<title>Installing Extensions Using Update Scripts</title>

An extension that has been around for awhile will probably exist in several versions, for which the author will need to write update scripts. For example, if you have released a <literal>foo</literal> extension in versions <literal>1.0</literal>, <literal>1.1</literal>, and <literal>1.2</literal>, there should be update scripts <filename>foo&#45;-1.0&#45;-1.1.sql</filename> and <filename>foo&#45;-1.1&#45;-1.2.sql</filename>. Before <productname>PostgreSQL</productname> 10, it was necessary to also create new script files <filename>foo&#45;-1.1.sql</filename> and <filename>foo&#45;-1.2.sql</filename> that directly build the newer extension versions, or else the newer versions could not be installed directly, only by installing <literal>1.0</literal> and then updating. That was tedious and duplicative, but now it's unnecessary, because <command>CREATE EXTENSION</command> can follow update chains automatically. For example, if only the script files <filename>foo&#45;-1.0.sql</filename>, <filename>foo&#45;-1.0&#45;-1.1.sql</filename>, and <filename>foo&#45;-1.1&#45;-1.2.sql</filename> are available then a request to install version <literal>1.2</literal> is honored by running those three scripts in sequence. The processing is the same as if you'd first installed <literal>1.0</literal> and then updated to <literal>1.2</literal>. (As with <command>ALTER EXTENSION UPDATE</command>, if multiple pathways are available then the shortest is preferred.) Arranging an extension's script files in this style can reduce the amount of maintenance effort needed to produce small updates. 以前から存在している拡張は、おそらく複数のバージョンに渡って存在しているので、拡張の作者は更新スクリプトを開発する必要性が出てきます。 たとえば、拡張fooがバージョン1.01.11.2をリリースしていたとすると、更新スクリプトfoo--1.0--1.1.sqlfoo--1.1--1.2.sqlが存在しなければなりません。 PostgreSQL 10より前では、新しい拡張のバージョンを直接作成するスクリプトファイルfoo--1.1.sqlfoo--1.2.sqlも新規に作る必要がありました。 これらがないと、新しいバージョンの拡張を直接インストールすることはできず、1.0をインストールしてから更新するしかありませんでした。 それにはうんざりしますし、また冗長です。 しかし、今ではCREATE EXTENSIONが自動的に更新連鎖を追跡してくるので、それは不要になりました。 たとえば、foo--1.0.sqlfoo--1.0--1.1.sqlfoo--1.1--1.2.sqlだけしかない場合、バージョン1.2のインストールのリクエストは、これらのスクリプトを順に実行することによって達成されます。 この手順は、最初に1.0をインストールして、1.2にアップデートする場合でも同じです。 (ALTER EXTENSION UPDATEは、複数の手順がある場合には、最短の手順を選びます。) この方法で拡張のスクリプトを調整することにより、小さな更新を複数作成するための保守の手間を減らすことができます。

If you use secondary (version-specific) control files with an extension maintained in this style, keep in mind that each version needs a control file even if it has no stand-alone installation script, as that control file will determine how the implicit update to that version is performed. For example, if <filename>foo&#45;-1.0.control</filename> specifies <literal>requires = 'bar'</literal> but <literal>foo</literal>'s other control files do not, the extension's dependency on <literal>bar</literal> will be dropped when updating from <literal>1.0</literal> to another version. この方法で保守している拡張に二次的な(バージョン固有の)制御ファイルがある場合は、スタンドアローンのインストールスクリプトがない場合でも、各バージョンで制御ファイルが必要になることに注意してください。 そのバージョンへと更新する暗黙的な方法を、制御ファイルが決定するからです。 たとえば、foo--1.0.controlrequires = 'bar'を指定しているのに、fooの他の制御ファイルが指定していないとすると、1.0から他のバージョンに更新した際にbarへの依存性が削除されてしまうでしょう。

38.17.6. 拡張のためのセキュリティに関する考慮事項 #

<title>Security Considerations for Extensions</title>

Widely-distributed extensions should assume little about the database they occupy. Therefore, it's appropriate to write functions provided by an extension in a secure style that cannot be compromised by search-path-based attacks. 広く配布される拡張では、インストールされるデータベースについて想定していないはずです。 このため、拡張はサーチパスに基づく攻撃を受けないよう、安全なスタイルで拡張によって提供される関数記述するのが適切です。

An extension that has the <varname>superuser</varname> property set to true must also consider security hazards for the actions taken within its installation and update scripts. It is not terribly difficult for a malicious user to create trojan-horse objects that will compromise later execution of a carelessly-written extension script, allowing that user to acquire superuser privileges. superuserプロパティを真にしている拡張はインストールや更新スクリプトの中で行われるアクションのセキュリティ面での危険も考慮しなければなりません。 悪意あるユーザが不用意に書かれた拡張スクリプトを悪用してトロイの木馬を作成し、スーパーユーザ権限を獲得できるようにすることは、そう難しくありません。

If an extension is marked <varname>trusted</varname>, then its installation schema can be selected by the installing user, who might intentionally use an insecure schema in hopes of gaining superuser privileges. Therefore, a trusted extension is extremely exposed from a security standpoint, and all its script commands must be carefully examined to ensure that no compromise is possible. 拡張がtrustedと印付けされている場合、そのインストールスキーマはインストールするユーザにより選択できます。そのユーザはスーパーユーザ権限を獲得することを狙って意図的に安全でないスキーマを使用するかもしれません。 したがって、trustedの拡張はセキュリティ観点から極めて危険で、そのスクリプトのコマンドは危険性がないことを確実にするため注意深く検証されなければなりません。

Advice about writing functions securely is provided in <xref linkend="extend-extensions-security-funcs"/> below, and advice about writing installation scripts securely is provided in <xref linkend="extend-extensions-security-scripts"/>. 関数を安全に書くためのアドバイスは以下のリンクから提供されます。 38.17.6.1 また、インストールスクリプトを安全に書くためのアドバイスは以下のリンクから提供されます。 38.17.6.2

38.17.6.1. 拡張関数のためのセキュリティに関する考慮事項 #

<title>Security Considerations for Extension Functions</title>

SQL-language and PL-language functions provided by extensions are at risk of search-path-based attacks when they are executed, since parsing of these functions occurs at execution time not creation time. 拡張により提供されるSQL言語とPL言語関数は実行されるときにサーチパスに基づく攻撃を受ける危険性があります。 これらの関数は作成時ではなく、実行時に解析されるためです。

The <link linkend="sql-createfunction-security"><command>CREATE FUNCTION</command></link> reference page contains advice about writing <literal>SECURITY DEFINER</literal> functions safely. It's good practice to apply those techniques for any function provided by an extension, since the function might be called by a high-privilege user. CREATE FUNCTIONのリファレンスページにはSECURITY DEFINER関数を安全に書くためのアドバイスが記載されています。 拡張が提供するあらゆる関数は、強い権限を持つユーザから実行されることがあるので、これらのテクニックを適用することは、良い習慣です。

XXX It's not enough to use qualified names, because one might write a qualified name to an object that itself uses unqualified names. Many information_schema functions have that defect, for example. However, that's a defect in the referenced object, and relatively few queries will be affected. Also, we direct applications to secure search_path when connecting to an untrusted database; if applications do that, they are immune to known attacks even if some extension refers to a defective object. Therefore, guide extension authors as though core PostgreSQL contained no such defect. XXX 名前を(スキーマ)修飾するだけでは十分ではありません。なぜなら修飾されていない名前を使っているオブジェクトに修飾された名前を書くかもしれないためです。 例えば、多くのインフォメーションスキーマの関数にはこの欠陥があります。 しかし、これは参照されるオブジェクトの欠陥なので影響を受ける問い合わせは少ないでしょう。 また、信頼できないデータベースにアクセスする際、アプリケーションは安全なsearch_pathを使うよう、指示しています。 そして、アプリケーションが指示どおりに作成されていれば、拡張が欠陥があるオブジェクトを参照していたとしても、既知の攻撃に影響されません。 そのため、コアのPostgreSQLにはそのような欠陥が含まれないかのように拡張の作成者に案内して下さい。

If you cannot set the <varname>search_path</varname> to contain only secure schemas, assume that each unqualified name could resolve to an object that a malicious user has defined. Beware of constructs that depend on <varname>search_path</varname> implicitly; for example, <token>IN</token> and <literal>CASE <replaceable>expression</replaceable> WHEN</literal> always select an operator using the search path. In their place, use <literal>OPERATOR(<replaceable>schema</replaceable>.=) ANY</literal> and <literal>CASE WHEN <replaceable>expression</replaceable></literal>. search_pathに安全なスキーマだけを設定できない場合は、修飾されていない名前は悪意あるユーザが定義したオブジェクトとして名前解決されうることを想定してください。 暗黙的にsearch_pathに依存する構文に注意してください。 例えば、INCASE WHENは常にサーチパスを使って演算子を選びます。 これらの場所には、OPERATOR(スキーマ.=) ANYCASE WHEN を使用してください。

A general-purpose extension usually should not assume that it's been installed into a secure schema, which means that even schema-qualified references to its own objects are not entirely risk-free. For example, if the extension has defined a function <literal>myschema.myfunc(bigint)</literal> then a call such as <literal>myschema.myfunc(42)</literal> could be captured by a hostile function <literal>myschema.myfunc(integer)</literal>. Be careful that the data types of function and operator parameters exactly match the declared argument types, using explicit casts where necessary. 汎用の拡張は通常、安全なスキーマにインストールされることを想定するべきではありません。これはスキーマ修飾された自身のオブジェクトであっても完全にリスクがないわけではないことを意味しています。 例えば、拡張が myschema.myfunc(bigint)という関数を定義しているとき、myschema.myfunc(42)というような呼び出しは、悪意ある関数myschema.myfunc(integer)に捕捉される可能性があります。 必要に応じて明示的なキャストを使用して関数と演算子のデータ型が引数の型と厳密に一致するように注意してください。

38.17.6.2. 拡張スクリプトのためのセキュリティに関する考慮事項 #

<title>Security Considerations for Extension Scripts</title>

An extension installation or update script should be written to guard against search-path-based attacks occurring when the script executes. If an object reference in the script can be made to resolve to some other object than the script author intended, then a compromise might occur immediately, or later when the mis-defined extension object is used. 拡張のインストールや更新スクリプトはスクリプト実行時にサーチパスに基づく攻撃を防ぐように記述されなければなりません。 スクリプトが参照するオブジェクトがスクリプトの作者が意図したものではないオブジェクトとして解決されうる場合、即座もしくは、誤って定義された拡張オブジェクトが使われたときに攻撃を受ける可能性があります。

DDL commands such as <command>CREATE FUNCTION</command> and <command>CREATE OPERATOR CLASS</command> are generally secure, but beware of any command having a general-purpose expression as a component. For example, <command>CREATE VIEW</command> needs to be vetted, as does a <literal>DEFAULT</literal> expression in <command>CREATE FUNCTION</command>. CREATE FUNCTIONCREATE OPERATOR CLASSなどのDDLコマンドは一般的には安全ですが、汎用的な式を構成に持つコマンドには注意が必要です。 例えば、CREATE FUNCTIONDEFAULT式に行うのと同様にCREATE VIEWには審査が必要です。

Sometimes an extension script might need to execute general-purpose SQL, for example to make catalog adjustments that aren't possible via DDL. Be careful to execute such commands with a secure <varname>search_path</varname>; do <emphasis>not</emphasis> trust the path provided by <command>CREATE/ALTER EXTENSION</command> to be secure. Best practice is to temporarily set <varname>search_path</varname> to <literal>'pg_catalog, pg_temp'</literal> and insert references to the extension's installation schema explicitly where needed. (This practice might also be helpful for creating views.) Examples can be found in the <filename>contrib</filename> modules in the <productname>PostgreSQL</productname> source code distribution. 拡張スクリプトには汎用SQLを実行する必要があることがあります。 例えば、DDLではできないカタログの調整などです。 そのようなコマンドは安全なsearch_path使って実行するように気をつけてください。 CREATE/ALTER EXTENSIONで提供されるパスが安全であると信用しないでください。 最も良い方法は一時的にsearch_path'pg_catalog, pg_temp'にセットし、必要な箇所に明示的に拡張のインストールスキーマの参照を記述する方法です(この方法はビューを作成する場合にも参考になります)。 例は配布されるPostgreSQLソースコードのcontribに見つけることができます。

Cross-extension references are extremely difficult to make fully secure, partially because of uncertainty about which schema the other extension is in. The hazards are reduced if both extensions are installed in the same schema, because then a hostile object cannot be placed ahead of the referenced extension in the installation-time <varname>search_path</varname>. However, no mechanism currently exists to require that. For now, best practice is to not mark an extension trusted if it depends on another one, unless that other one is always installed in <literal>pg_catalog</literal>. 拡張をまたがる参照を完璧に安全にすることは極めて困難です。 理由の一つに、他の拡張がどのスキーマにあるのか定かではないことがあります。 この危険性は両方の拡張を同じスキーマにインストールすることで軽減できます。 悪意あるオブジェクトをインストール時のsearch_path内で参照された拡張の前に置くことができないからです。 しかしながら、現時点ではこれを要求するメカニズムはありません。 今のところ、最良の手段は他の拡張に依存する拡張であるなら、依存する拡張が常にpg_catalogにインストールされるのでない限り、拡張をtrustedと印付けしないことです。

38.17.7. 拡張の例 #

<title>Extension Example</title>

Here is a complete example of an <acronym>SQL</acronym>-only extension, a two-element composite type that can store any type of value in its slots, which are named <quote>k</quote> and <quote>v</quote>. Non-text values are automatically coerced to text for storage. ここでは、SQLのみの拡張の完全な例を示します。 kvという名称の2つの要素からなる複合型であり、そのスロットには任意の型の値を格納できるものです。 格納の際テキスト以外の値は自動的にテキストに変換されます。

The script file <filename>pair&#45;-1.0.sql</filename> looks like this: pair--1.0.sqlスクリプトファイルは以下のようになります。


&#45;- complain if script is sourced in psql, rather than via CREATE EXTENSION

-- スクリプトが、CREATE EXTENSION経由ではなく、psqlのソースとして使われた場合には文句を言う
\echo Use "CREATE EXTENSION pair" to load this file. \quit

CREATE TYPE pair AS ( k text, v text );

CREATE FUNCTION pair(text, text)
RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::@extschema@.pair;';

CREATE OPERATOR ~> (LEFTARG = text, RIGHTARG = text, FUNCTION = pair);

-- "SET search_path" is easy to get right, but qualified names perform better.
CREATE FUNCTION lower(pair)
RETURNS pair LANGUAGE SQL
AS 'SELECT ROW(lower($1.k), lower($1.v))::@extschema@.pair;'
SET search_path = pg_temp;

CREATE FUNCTION pair_concat(pair, pair)
RETURNS pair LANGUAGE SQL
AS 'SELECT ROW($1.k OPERATOR(pg_catalog.||) $2.k,
               $1.v OPERATOR(pg_catalog.||) $2.v)::@extschema@.pair;';

The control file <filename>pair.control</filename> looks like this: pair.control制御ファイルは以下のようになります。

# pair extension
comment = 'A key/value pair data type'
default_version = '1.0'
# cannot be relocatable because of use of @extschema@
relocatable = false

While you hardly need a makefile to install these two files into the correct directory, you could use a <filename>Makefile</filename> containing this: これらの2つのファイルを正しいディレクトリにインストールするためにmakefileを作成する必要はほとんどありませんが、以下を含むMakefileを使用できます。

EXTENSION = pair
DATA = pair--1.0.sql

PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

This makefile relies on <acronym>PGXS</acronym>, which is described in <xref linkend="extend-pgxs"/>. The command <literal>make install</literal> will install the control and script files into the correct directory as reported by <application>pg_config</application>. このmakefileは38.18で説明するPGXSに依存します。 make installコマンドは制御ファイルとスクリプトファイルをpg_configで報告される正しいディレクトリにインストールします。

Once the files are installed, use the <command>CREATE EXTENSION</command> command to load the objects into any particular database. ファイルがインストールされた後、CREATE EXTENSIONコマンドを使用してオブジェクトを任意の特定のデータベースにロードしてください。