はじめに
2018年に下記の記事を書きました。しかし、残念ながら Windows版のpg_repack
を正しく構築することが出来ませんでした。
別件のトラブルでpg_statsinfo
について調べていると、Windows版のpg_repack
バイナリ配布しているという記事を見つけました。
SRA OSSとしてPostgreSQL拡張のWindowsバイナリ提供を開始しているが、今のところはサポート加入者のみで、一般配布は計画中とのこと。
※2025年05月時点ではまだ一般配布は行われていません。
じゃー自力でなんとかしてみようと考えたところです。
環境
- Windos 11 Home 64bit
- Visual Studio 2022(C++ によるデスクトップ開発) インストール済み
- PostgreSQL 14.7
仕事の関係上、現時点では少し古めの PosstgreSQL のバージョンを使用します。
開発準備
PostgreSQL拡張をC言語を使用して開発するのですが、Visual Studio で下準備が必要となります。
単純なHello World
の文字列を返すだけではつまらないので、フィボナッチ数を返す拡張機能を作成することにします。
Visual Studio用の拡張機能のビルド方法はPostgreSQLのWikiにまとまっていますが、英語の上に古いのは否めません。
今回、分かりやすく書いてみました。
参照記事
プロジェクト作成
C++でダイナミックリンクライブラリ(DLL)を選択します。
pg_fibonacci
でプロジェクトを作成します。
プロパティ設定
pg_fibonacci
でプロジェクトのプロパティにて、構成を「すべての構成」にします。
プリプロセッサ定義
C/C++の「プリプロセッサ」を選択、「プリプロセッサの定義」に「WIN32」を追加します。
PostgreSQLは「WINDLL」を同等のものとして認識しないため、Win32プラットフォームの場合は明示的に指定する必要があります。
※2014年の記事を参考にしているため、もう改善されている可能性があります。
C/C++の例外を無効化
C/C++の「コード生成」を選択、「C/C++の例外を有効にする」で「いいえ」にします。
コンパイルをC言語へ
C/C++の「詳細設定」を選択、「コンパイル言語の選択」で「C コードとしてコンパイル(/TC)」にします。
プリコンパイル済みヘッダーを使用しない
C/C++の「プリコンパイル済みヘッダー」を選択、「プリコンパイル済みヘッダー」で「プリコンパイル済みヘッダーを使用しない」にします。
マニフェストを生成しない
リンカーの「マニフェスト ファイル」を選択、「マニフェストの生成」で「いいえ (/MANIFEST:NO)」にします。
追加の依存関係
リンカーの「入力」を選択、「追加の依存ファイル」に「postgres.lib」を追加します。
「親またはプロジェクトの既定値から継承」のチェックは外さないでください。
単純な拡張機能では必要ありませんが、サーバー関数にリンクする場合は必要になります。
インクルードディレクトリ
C/C++の「全般」を選択、「追加のインクルードディレクトリ」で、PostgreSQLインストール配下の4つのフォルダを追加します。
- include\server\port\win32_msvc
- include\server\port\win32
- include\server
- include
今回の筆者の場合、PostgreSQLインストールフォルダは「C:\Program Files\PostgreSQL\14」になります。
ライブラリディレクトリ
リンカーの「全般」を選択、「追加のライブラリ ディレクトリ」で、PostgreSQLインストール配下のlib
フォルダを追加します。次に「ライブラリ依存関係のリンク」を「いいえ」にします。
プロジェクトの構築
既存ファイルの削除
既存ファイルの「dllmain.cpp」と「pch.cpp」は不要なので削除します。
プログラム
構成
pg_fibonacci/
├── pg_fibonacci.c
├── pg_fibonacci.control
├── pg_fibonacci--1.0.sql
C言語ソース pg_fibonacci.c
pg_fibonacci.c
を追加します。
#include "postgres.h"
#include "fmgr.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
#ifdef _WIN32
PGDLLEXPORT Datum fibonacci(PG_FUNCTION_ARGS);
#endif
PG_FUNCTION_INFO_V1(fibonacci);
Datum
fibonacci(PG_FUNCTION_ARGS)
{
int32 n = PG_GETARG_INT32(0);
if (n < 0)
ereport(ERROR, (errmsg("Negative argument not allowed")));
int64 a = 0, b = 1, temp;
for (int i = 0; i < n; i++) {
temp = a + b;
a = b;
b = temp;
}
PG_RETURN_INT64(a);
}
コントロールファイル pg_fibonacci.control
pg_fibonacci.control
を追加、プロパティにて「ビルドから除外」で「はい」にします。
comment = 'Fibonacci function extension'
default_version = '1.0'
module_pathname = '$libdir/pg_fibonacci'
relocatable = true
SQL定義ファイル pg_fibonacci--1.0.sql
pg_fibonacci--1.0.sql
を追加、プロパティにて「ビルドから除外」で「はい」にします。
CREATE FUNCTION fibonacci(integer) RETURNS bigint
AS 'MODULE_PATHNAME', 'fibonacci'
LANGUAGE C STRICT;
導入
配置
今回の筆者の場合、PostgreSQLインストールフォルダは「C:\Program Files\PostgreSQL\14」になりますので、下記に配置します。
ファイル | 配置先 |
---|---|
pg_fibonacci.dll | C:\Program Files\PostgreSQL\14\lib\ |
pg_fibonacci.control | C:\Program Files\PostgreSQL\14\share\extension\ |
pg_fibonacci--1.0.sql | 同上 |
PostgreSQLに拡張機能の登録
CREATE EXTENSION pg_fibonacci;
嵌まったこと
WindowsではC言語ソース内で下記の定義をしないとCREATE EXTENSION
にてcould not find function
エラーになります。
Stuck getting sample C function working on Windows version - stackoverflow
#ifdef _WIN32
PGDLLEXPORT Datum fibonacci(PG_FUNCTION_ARGS);
#endif
SQL : could not find function "fibonacci" in file "C:/Program Files/PostgreSQL/14/lib/pg_fibonacci.dll"
検証
SELECT fibonacci(10); -- 55
SELECT fibonacci(50); -- 12586269025
最後に
今回のpg_fibonacci.c
は、ChatGPTで生成してもらいました。
設定が面倒な方は、GitHubから取得して改良してもらえばいいでしょう。