前回のPostgreSQL拡張機能につづき、内部構造をより理解する目的で、下記スライドや動画(最下部)を参考にフックについてテストしてみました。
このフックというのは、コード本体を変更することなく、既存の機能を横取りするしくみで、前回と同じ追加モジュールとして実現します。(同じ環境を利用)
「フックを使ったPostgreSQLの拡張機能を作ってみよう!(第33回PostgreSQLアンカンファレンス@オンライン 発表資料) 」
https://www.slideshare.net/nttdata-tech/postgresql-extension-hook-pgunconf33-nttdata
PostgreSQLには、以下の部分に拡張機能としてプログラムフックをできるしくみがあるようです。
-
General Hooks
Security Hooks
Function Manager Hooks
Planner Hooks
Executor Hooks
PL/pgsql Hooks
今回は、Executor Hookの中のUtility Hookを対象にしました。
https://github.com/taminomara/psql-hooks/blob/master/Detailed.md#ProcessUtility_hook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
#include "postgres.h" #include "fmgr.h" #include "tcop/utility.h" PG_MODULE_MAGIC; void _PG_init(void); void _PG_fini(void); static ProcessUtility_hook_type prev_ProcessUtility = NULL; static void hook_samp01(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *completionTag) { Node *parsetree = pstmt->utilityStmt; elog(INFO, "Query String: %s", queryString); switch(nodeTag(parsetree)) { case T_TruncateStmt: elog(INFO, "T_TruncateStmt"); break; case T_CreateStmt: elog(INFO, "T_CreaeteStmt"); break; case T_DropStmt: elog(INFO, "T_DropStmt"); break; default: elog(INFO, "Others"); break; } standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, completionTag); } void _PG_init(void) { prev_ProcessUtility = ProcessUtility_hook; ProcessUtility_hook = hook_samp01; } void _PG_fini(void) { ProcessUtility_hook = prev_ProcessUtility; } |
hook_samp01()が処理を横取りしている関数です。
src/backend/tcop/utility.c
フック関数の引数については上記、postgres本体を参照。
elog()に、 ERROR,FATAL,PANIC を設定すると、以後の処理をせずに終了します。(スライドでの実装例)
他に DEBUG1,,,DEBUG5,INFO,NOTICE,WARNING,LOGがあり、LOGはログファイルに、INFOはpsqlに出力されます。
LOG出力の場合下記で確認
tail -f /var/log/postgresql/postgresql-14-main.log
Makefile
MODULES = pg_samp01
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) –pgxs)
include $(PGXS)
ビルド
make
sudo make install
環境の確認
# pg_config –pgxs
/usr/lib/postgresql/14/lib/pgxs/src/makefiles/pgxs.mk# ls /usr/lib/postgresql/14/lib/pg_samp01.so
/usr/lib/postgresql/14/lib/pg_samp01.so
設定ファイルにライブラリ追加
vi /etc/postgresql/14/main/postgresql.conf
shared_preload_libraries = ‘pg_samp01’ # (change requires restart)
INSERT,SELECTの場合、このフックに関係ないことがわかります。
ここまで備忘録でした。
参考動画
このシリーズわかりやすいです。