- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- ソース を表示
- PostgreSQL/解析/拡張機能の構築基盤 へ行く。
- 1 (2017-06-24 (土) 00:33:32)
- 2 (2017-06-25 (日) 23:07:52)
- 3 (2017-06-26 (月) 23:08:39)
- 4 (2017-06-28 (水) 23:25:26)
- 5 (2017-07-01 (土) 01:18:40)
- 6 (2017-07-02 (日) 20:09:39)
- 7 (2017-07-11 (火) 20:01:26)
- 8 (2017-07-11 (火) 22:58:56)
- 9 (2017-07-11 (火) 23:57:22)
- 10 (2017-07-12 (水) 23:31:04)
- 11 (2017-07-18 (火) 21:51:44)
- 12 (2018-02-04 (日) 22:32:14)
概要 †
ここでは,拡張機能の開発で必要となる知識について整理する。
具体的には,拡張機能のディレクトリ構造,ビルドスクリプト,制御ファイルについて記述する。
拡張機能のディレクトリ構造 †
CREATE EXTENSIONとしてインストールされる拡張機能のディレクトリ構造は,以下のようになっている(ここでは,拡張機能を「myext」として説明を進める)。
myext |- myext.control |- myext--xx.sql |- Makefile |- myext.c
- myext.control
- CREATE EXTENSIONやALTER EXTENSIONが実行されたときに読み込まれる。
- myext--xx.sql
- CREATE EXTENSIONやALTER EXTENSIONが実行されたときに実行されるターゲットバージョンのスクリプト。xxからyyへのアップデートに段階的な更新が必要な場合は,myext--xx--yy.sqlのようにする。
- Makefile
- ビルド定義
- myex.c
- ソースコード。もちろん複数のソースコードのコンパイル&リンクも問題ない。
サンプル1 trueを返すだけのmyext関数の作成
各ファイルの内容はざっと最小限で書いて以下のような感じになる。各ファイルの定義内容については後述する。
Makefile
MODULES = myext EXTENSION = myext DATA = myext--1.0.sql PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS)
myext--1.0.sql
\echo USE "CREATE EXTENSION myext" TO LOAD this file. \quit CREATE OR REPLACE FUNCTION myext() RETURNS BOOL AS 'MODULE_PATHNAME' LANGUAGE C STRICT;
myext.c
#include "postgres.h" #include "fmgr.h" #include "funcapi.h" PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(myext); Datum myext(PG_FUNCTION_ARGS) { PG_RETURN_BOOL(true); // ただtrueを返すだけの関数 }
この内容で作成される拡張関数だが,以下のような結果を返すものである。
postgres=# select myext(); myext ------- t (1 row)
Makefile †
- MODULES
- 同じ系のソースから生成される共有ライブラリのリスト。
- myext.cとmyext2.cがあれば,myext.soとmyext2.soが作成される。
# myext.soとmyext2.soがターゲットリストに加わる MODULES = myext myext2
- MODULE_big
- 作成する共有ライブラリ。
- OBJSにオブジェクトファイルを列挙する。
# myext.soターゲットが作成される # イメージ) # myext.so: $(OBJS) MODULE_big = myext OBJS = myext.o hoge.o
- PROGRAM
- $(pg_config --bindir)にプログラムがインストールされる実行ファイル。
- OBJSにオブジェクトファイルを列挙する。
PROGRAM = myext OBJS = myext.o hoge.o
- EXTENSION
- 拡張の名前を指定する。$(EXTENSION).controlファイルもパッケージに必要。
MODULES = myext # 拡張の名前 # $(pg_config --sharedir)/extension/にmyext.controlがインストールされる EXTENSION = myext
- 拡張の名前を指定する。$(EXTENSION).controlファイルもパッケージに必要。
- MODULEDIR
- DATAやDOCSのインストール先ディレクトリ。
- $(pg_config --sharedir)/$(MODULEDIR)となる。
指定がない場合は,EXTENSIONが使われる。EXTENSIONがなければcontribとなる。MODULES = myext EXTENSION = myext MODULEDIR = myext DATA = myext--1.0.sql
- DATA
- $(pg_config --sharedir)にインストールされるデータ。
MODULES = myext EXTENSION = myext DATA = myext--1.0.sql
- $(pg_config --sharedir)にインストールされるデータ。
- DATA_built
- $(pg_config --sharedir)にインストールされるデータ。
- メモ:DATAとの違いがよく分からない,DATAとの違いは$(srcdir)のプリフィックスはつかないこと?
MODULES = myext EXTENSION = myext DATA_built = myext--1.0.sql
- DOCS
- $(pg_config --docdir)にインストールされるドキュメント。
MODULES = myext DOCS = $(addsuffix .example, $(MODULES))
- $(pg_config --docdir)にインストールされるドキュメント。
- SCRIPTS
- $(pg_config --bindir)にプログラムがインストールされるスクリプト。
SCRIPTS = myext.sh
- $(pg_config --bindir)にプログラムがインストールされるスクリプト。
- SCRIPTS_built
- $(pg_config --bindir)にプログラムがインストールされるスクリプト。
- メモ:SCRIPTSとの違いがよく分からない,SCRIPTSとの違いは$(srcdir)のプリフィックスはつかないこと?
SCRIPTS_built = myext.sh
- REGRESS
- リグレッションテストのリスト(.sqlは不要)。
# sql/myext.sqlが実行される REGRESS = myext
- リグレッションテストのリスト(.sqlは不要)。
- REGRESS_OPTS
- リグレッションテストの実行引数。pg_regressに渡すオプション。
# portオプションを渡す。 # (デフォルトと異なるportで動作している場合) REGRESS_OPTS += --port $(PG_PORT)
- リグレッションテストの実行引数。pg_regressに渡すオプション。
- EXTRA_CLEAN
# rm -rf $(EXTRA_CLEAN) EXTRA_CLEAN = my.log
- PG_CPPFLAGS
CPPFLAGS = -std=c++11
- PG_LIBS
PG_LIBS = /usr/local/postgres/libs/hello.so
- SHLIB_LINK
MODULE_big = /usr/local/postgres/libs/hello.so
- PG_CONFIG
PG_CONFIG = pg_config
- PGFILEDESC
# cleanターゲットで以下のように展開される。PGFILEDESC指定があれば,cleanでwin32ver.oが削除される。 # # clean: # ifdef MODULES # rm -f $... $(if $(PGFILEDESC),$(WIN32RES)) # endif PGFILEDESC = "myext - always returns true"
制御ファイル(.control) †
CreateExtension実行の流れ †
CREATE EXTENSION呼び出しの流れをデバッガのスタックトレースを実行し俯瞰する。
まずは,以下のコマンドを実行してみる。
# デフォルト #directory = 'extension' directory = 'myext'
最終的にはpg_dlsymが呼ばれるだろうと想定しブレークポイントを貼っておく。以下,コマンドを実行しブレークポイントで中断させた時のスタックトレースである。
(lldb) bt * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 24.1 * frame #0: 0x000000010edba000 postgres`pg_dlsym(...) at dynloader.c:38 <-- 最終的にシステムコールで共有オブジェクトの読み込み frame #1: 0x000000010f0083bd postgres`internal_load_library(...) at dfmgr.c:240 <-- ライブラリのロード frame #2: 0x000000010f007d7f postgres`load_external_function(...) at dfmgr.c:105 frame #3: 0x000000010eb8f532 postgres`fmgr_c_validator(...) at pg_proc.c:823 frame #4: 0x000000010f00c143 postgres`OidFunctionCall1Coll(...) at fmgr.c:1596 frame #5: 0x000000010eb8f0bb postgres`ProcedureCreate(...) at pg_proc.c:726 frame #6: 0x000000010ec45204 postgres`CreateFunction(...) at functioncmds.c:1048 frame #7: 0x000000010ee7520e postgres`ProcessUtilitySlow(...) at utility.c:1361 frame #8: 0x000000010ee73878 postgres`standard_ProcessUtility(...) at utility.c:892 frame #9: 0x000000010ee7299d postgres`ProcessUtility(...) at utility.c:334 frame #10: 0x000000010ec3f486 postgres`execute_sql_string(...) at extension.c:744 <-- インストールスクリプト実行 frame #11: 0x000000010ec39764 postgres`execute_extension_script(...) at extension.c:904 frame #12: 0x000000010ec386af postgres`CreateExtension(...) at extension.c:1461 <-- ここでCREATE EXTENSIONコマンド実行 frame #13: 0x000000010ee74cb9 postgres`ProcessUtilitySlow(...) at utility.c:1281 frame #14: 0x000000010ee73878 postgres`standard_ProcessUtility(...) at utility.c:892 frame #15: 0x000000010ee7299d postgres`ProcessUtility(...) at utility.c:334 frame #16: 0x000000010ee72318 postgres`PortalRunUtility(...) at pquery.c:1183 frame #17: 0x000000010ee7155c postgres`PortalRunMulti(...) at pquery.c:1314 frame #18: 0x000000010ee70b6d postgres`PortalRun(...) at pquery.c:812 frame #19: 0x000000010ee6c527 postgres`exec_simple_query(...) at postgres.c:1104 frame #20: 0x000000010ee6b730 postgres`PostgresMain(...) at postgres.c:4045 frame #21: 0x000000010edd45e2 postgres`BackendRun(...) at postmaster.c:4253 frame #22: 0x000000010edd389d postgres`BackendStartup(...) at postmaster.c:3927 frame #23: 0x000000010edd2965 postgres`ServerLoop at postmaster.c:1698 frame #24: 0x000000010edd02d6 postgres`PostmasterMain(...) at postmaster.c:1306 frame #25: 0x000000010ed1097f postgres`main(...) at main.c:228 frame #26: 0x00007fffdb4e0235 libdyld.dylib`start + 1 frame #27: 0x00007fffdb4e0235 libdyld.dylib`start + 1
参考リンク †
- extension.c - on doxygen.postgresql.org
- CreateExtension() - on doxygen.postgresql.org
- AlterExtension() - on doxygen.postgresql.org
- parse_extension_control_file() - on doxygen.postgresql.org
- PostgreSQL 9.5.4文書 35.15. 関連するオブジェクトを拡張としてパッケージ化 - PostgreSQL 9.5.4文書
- PostgreSQL 9.5.4文書 35.16. 拡張構築基盤 - PostgreSQL 9.5.4文書