ククログ

株式会社クリアコード > ククログ > PGroongaに関数を追加する(SQL編)

PGroongaに関数を追加する(SQL編)

PGroongaについてお勉強中の阿部です。

先日、PGroongaに便利関数を追加したのでその方法について説明します。 今回はSQLのみで実現しました。

PGroongaはPostgreSQLの拡張機能です。 PostgreSQLの拡張機能を1から開発する方法には触れませんが、PostgreSQLに関数を追加する方法を知りたい方の参考にはなると思います。

やること

やることは以下の3つです。

  1. 追加したい機能について考える
  2. CREATE FUNCTION に落とし込む
  3. 所定のファイルに CREATE FUNCTION 文などを追加する

1. 追加したい機能について考える

今回はレプリーケーションを利用しているときにPGroongaのWALで未適用のWALがないかを確認するための関数を追加します。

基本的にPGroongaのWALは自動で適用されないため、適用処理が実行されないとプライマリーとの差が開きます。それを検知するために使います。

参考: pgroonga_standby_maintainerモジュール

具体的な検知方法ですが以下の2つのときに未適用のWALがあると見なすことにしました。

  1. pgroonga_wal_status関数current_*last_* が異なる場合
    • current_* は適用済みのPGroongaのWALの情報
    • last_* は適用されているかどうかに関わらず、現在存在しているPGroongaのWALの情報
    • current_*last_* が異なるということは未適用のPGroongaのWALがある
  2. pg_stat_wal_receiverflushed_lsnlatest_end_lsn が異なる場合
    • flushed_lsn: スタンバイ側で受信したWALの位置
    • latest_end_lsn: プライマリー側のWALの位置
    • flushed_lsnlatest_end_lsn が異なるということはプライマリーとスタンバイでWALの内容が違うので未適用のPGroongaのWALがある可能性がある

1の場合は pgroonga_wal_status の結果でPGroongaのインデックスごとに未適用のWALの有無をチェックできるので、該当するPGroongaのインデックスのみを表示します。

2の場合はプライマリーとスタンバイでWALの状態が違うことまではわかりますが、未適用のPGroongaのWALの有無までは断定できません。 未適用のPGroongaのWALがある可能性もあるので、すべてのPGroongaのインデックスを表示することにしました。

2. CREATE FUNCTION に落とし込む

まずは情報を取得するSQLを考える

「1. 追加したい機能について考える」で考えた情報を取得するSQLを考えます。

  1. pgroonga_wal_status関数current_*last_* が異なる場合
    • 該当するPGroongaのインデックスのみを取得
  2. pg_stat_wal_receiverflushed_lsnlatest_end_lsn が異なる場合
    • すべてのPGroongaのインデックスを表示

これらをSQLにすると以下の通りです。

SELECT name FROM pgroonga_wal_status()
	WHERE current_block != last_block
		OR current_offset != current_offset
		OR current_size != last_size
		OR EXISTS(
			SELECT 1 FROM pg_stat_wal_receiver
			WHERE flushed_lsn != latest_end_lsn
		);

次に関数にする

考えた情報を取得するSQLを CREATE FUNCTION で関数にします。 最終的なSQLをベースに解説します。

参考: CREATE FUNCTION

CREATE FUNCTION pgroonga_list_lagged_indexes()
		RETURNS SETOF text AS '
			SELECT name FROM pgroonga_wal_status()
			WHERE current_block != last_block
				OR current_offset != current_offset
				OR current_size != last_size
				OR EXISTS(
					SELECT 1 FROM pg_stat_wal_receiver
					WHERE flushed_lsn != latest_end_lsn
				);
		' LANGUAGE SQL
		STRICT
		PARALLEL SAFE;

pgroonga_list_lagged_indexes が関数の名前です。今回は引数がないため () です。 引数を取る場合は () に必要な引数を記載します。

何か値を返す関数の場合は RETURNS 句で指定します。 この関数では未適用のWALがあるPGroongaのインデックス名を返すので RETURNS SETOF text としました。 SETOF を指定することで集合を返すことができます。

' ~ ' で囲まれているところが関数の本体です。(' で囲みましたが好きな文字を使うことができます。) また LANGUAGE SQL で関数の本体を記述している言語を指定します。この例ではSQLです。

STRICT を指定すると関数の引数に1つでもNULLがある場合、常にNULLを返すようになります。 この関数では関係ありませんが他のPGroongaの関数で指定されているので合わせました。

PARALLEL SAFE を指定すると並列モードでも実行できます。

この CREATE FUNCTION を実行すると' ~ ' で囲まれている関数の本体を実行し、その結果を返す関数が作れます。

3. 所定のファイルに CREATE FUNCTION 文などを追加する

3つのファイルに追加します。PGroongaでいうと以下の3つのファイルです。

  • data/pgroonga.sql
    • インストール時に実行するSQL
  • data/pgroonga--<現バージョン>--<新バージョン>.sql
    • バージョンアップ時に実行するSQL
    • 例: data/pgroonga--3.2.0--3.2.1.sql
      • PGroongaを3.2.0から3.2.1へアップグレードするときに実行されます
  • data/pgroonga--<新バージョン>--<現バージョン>.sql
    • ダウングレード時に実行するSQL
    • 例: data/pgroonga--3.2.1--3.2.0.sql
      • PGroongaを3.2.1から3.2.0へダウングレードするときに実行されます

data/pgroonga.sql

先ほど考えた CREATE FUNCTION 文を追記します。 このファイルはインストール時に実行するSQLなので、追加する他の関数などもすべて記載されています。

...
CREATE FUNCTION pgroonga_list_lagged_indexes()
		RETURNS SETOF text AS '
			SELECT name FROM pgroonga_wal_status()
			WHERE current_block != last_block
				OR current_offset != current_offset
				OR current_size != last_size
				OR EXISTS(
					SELECT 1 FROM pg_stat_wal_receiver
					WHERE flushed_lsn != latest_end_lsn
				);
		' LANGUAGE SQL
		STRICT
		PARALLEL SAFE;
...

data/pgroonga--<現バージョン>--<新バージョン>.sql

先ほど考えた CREATE FUNCTION 文を追記します。 このファイルはアップグレードするときに実行されるSQLなので、「新バージョン」で追加される機能に関するSQLのみが記載されています。

追加する内容は一緒なので割愛。

data/pgroonga--<新バージョン>--<現バージョン>.sql

このファイルはダウングレードするときに実行されるSQLを書くためのものです。 ですので、「新バージョン」で追加した機能を削除して「現バージョン」の状態に戻すためのSQLを書きます。 よって、CREATE FUNCTION で追加した FUNCTION を削除するSQLを記載します。

DROP FUNCTION pgroonga_list_lagged_indexes;

まとめ

PostgreSQLの拡張機能に CREATE FUNCTION で関数を追加する方法を説明してPGroongaに便利関数を追加する方法をまとめました。 今回はSQLのみで実現しました。 次回はC言語による拡張も使った関数の追加方法も説明するのでご期待ください。

補足

この記事で触れた pgroonga_list_lagged_indexes 関数ですが、PostgreSQLのバージョンが14以下の場合に役立ちます。

PostgreSQLのバージョンが15以上の場合は、より便利な PGroongaのWALリソースマネージャー をご利用ください。 ククログでも紹介しています。