ユーザ用ツール

サイト用ツール


it技術:データベース:postgresql:pg_repack

文書の過去の版を表示しています。


pg_repack

ビルドできても例外エラー

2021年の質問:Windowsでpg_repackをビルドしても例外エラーになってしまう。
pg_repack binaries under windows

下記サイトは2018年のもので静的なpostgres.libを作成して動作したとの報告があったが、現在は postgres.lib が提供されており、上記サイトでも postgres.lib をリンクしても、例外エラーで動作しないことから問題は別物と考える。

調査

pg_repack のデバッグでは、set_pglocale_pgservice(argv[0], “pgscripts”); を実行すると例外エラーとなる。
vaccumedb のデバッグでは、set_pglocale_pgservice(argv[0], “pgscripts”); を使用していても正常に動作する。違いとしてvaccumedb では、postgres.lib をリンクしていない。

pg_repack以外で exe形式で postgres.lib をリンクしたものは他にない。

関数モジュールソース元
set_pglocale_pgservicelibpgcommon.lib
setlocale(pgwin32_setlocale)libpgport.lib
select(pgwin32_select)postgres.libbackend¥port¥win32¥socket.c
pgwin32_dispatch_queued_signalspostgres.libbackend¥port¥win32¥signal.c
errstartpostgres.libbackend\utils\error\elog.c

pg_repack を pgwin32_selectで検索しても見つからないが、select で検索すると見つかる。
ret = select(max_fd + 1, &input_mask, NULL, NULL, &timeout);

win32.port.h
#define setlocale(a,b) pgwin32_setlocale(a,b)
#define select(n, r, w, e, timeout) pgwin32_select(n, r, w, e, timeout)

pg_hello を作成して postgres.lib をリンクしないで pg_repack.c のソースコードに徐々に近づけた。
そして、rebuild_indexes で pgwin32_select が参照している旨のLINKエラーのみになった。

そこで、pg_repack.c を、pg_hello.c に名前を変更してビルド、同様に rebuild_indexes で、pgwin32_select が参照している旨のLINKエラーのみになった。

下記のコードをコメントアウトすると、LINKエラーは出なくなる。

ret = select(max_fd + 1, &input_mask, NULL, NULL, &timeout);

必要なobjファイルだけをリンク

socket.obj、singal.obj をリンクすると、7つの未解決エラーが出る。

1>socket.obj : error LNK2019: 未解決の外部シンボル errstart が関数 pgwin32_select で参照されました
1>signal.obj : error LNK2001: 外部シンボル errstart は未解決です
1>socket.obj : error LNK2019: 未解決の外部シンボル errfinish が関数 pgwin32_select で参照されました
1>signal.obj : error LNK2001: 外部シンボル errfinish は未解決です
1>socket.obj : error LNK2019: 未解決の外部シンボル errmsg_internal が関数 pgwin32_select で参照されました
1>signal.obj : error LNK2001: 外部シンボル errmsg_internal は未解決です
1>signal.obj : error LNK2019: 未解決の外部シンボル write_stderr が関数 pg_signal_thread で参照されました

このぐらいならと elog.obj を追加すると多くの未解決エラーが出る。同じように追加するとどんどん別のobjファイルから未解決エラーが出る。postgres.libとリンクするのと変わらなくなるため、この方法での解決はやめた。

関数名モジュール名オブジェクト名
ExceptionalConditionasset.cassert.obj
pg_codepage_to_encodingchklocale.cchklocale.obj
MemoryContextStrdupmcxt.cmcxt.obj
GetTopTransactionIdIfAnyxact.cxact.obj
GetMessageEncodingmbutils.cmbutils.obj
pgwin32_message_to_UTF16mbutils.cmbutils.obj
pq_putmessage_v2pqcomm.cpqcomm.obj
pq_beginmessagepdformat.cpdformat.obj
pq_endmessagepqformat.cpqformat.obj
pq_sendstringpqformat.cpqformat.obj
pq_send_ascii_stringpdformat.cpdformat.obj
pg_localtimelocaltime.clocaltime.obj
pg_strftimestrftime.cstrftime.obj
ProcessInterruptspostgres,cpostgres,obj
GetBackendTypeDescmiscinit.cmiscinit.obj
pgstat_get_my_query_idbackend_status.cbackend_status.obj
write_syslogger_filesyslogger.csyslogger.obj
proc_exitipc.cipc.obj
MemoryContextResetmcxt.cmcxt.obj
get_ps_displayps_status.cps_status.obj

必要な関数だけを作成

socket.c と signal.c の必要関数を抜き出し、新しい socket.c を作成して、pg_repack に socket.c を追加

次項目の winSock2.h にある Select関数を使用して問題ないなら、新しい socket.c は使用しない方針とする。

select関数の参照先の違い

pg_repack の select関数 は、win32_port.h → socket.c の pgwin32_select関数を参照している。
pgbench や pg_recvlogical の select関数 は、winSock2.h の select関数を参照している。

select関数 を win32_port.h か winSock2.h を参照させる違いはどこにあるのか?

put.h にある #include “c.h” を消すと select関数の定義の参照されなくなるし bool型なども定義がなくなる。
pgbench.c には、bool型とselect関数があるが、参照エラーになっていない。

put.h にある、#include “postgres_fe.h” に切り替えたら、select関数の定義がwinSock2.h の select関数を参照するようになった。

versionの指定

「pg_repack –version」を実行したら、unknown となった。 REPACK_VERSION を指定していないため、プロジェクトのプロパティ C/C++のプリプロセッサに REPACK_VERSION=1.4.7 を追加する。
lib側も同様に設定すること

pg_repack.c
#ifdef REPACK_VERSION
/* macro trick to stringify a macro expansion */
#define xstr(s) str(s)
#define str(s) #s
const char *PROGRAM_VERSION = xstr(REPACK_VERSION);
#else
const char *PROGRAM_VERSION = "unknown";
#endif

relhasoids列がないエラー

SELECT * FROM repack.tables
SQL: COLUMN "relhasoids" does NOT exist

relhasoidsは、PostgreSQLのシステムカタログに存在するカラムであり、バージョン11までは存在していたが、バージョン12からは削除されている。

pg_repack.sql.in ファイルには、get_storage_param 関数内で relhasoids を使用している。

pg_repack.sql.in
get_storage_param
 
    -- table oid
    SELECT 'oids = ' ||
        CASE WHEN relhasoids
            THEN 'true'
            ELSE 'false'
        END
    FROM pg_class

Makefileファイル内にて PostgreSQL12以降は relhasoids を false に書き換えている。

Makefile
# It is not possible to create tables with OIDs on PostgreSQL 12 or later
ifeq ($(shell echo $$(($(INTVERSION) < 1200))),1)
    RELHASOIDS := relhasoids
else
    RELHASOIDS := false
endif
 
pg_repack--$(REPACK_VERSION).sql: pg_repack.sql.in
	sed 's,REPACK_VERSION,$(REPACK_VERSION),g' $< \
	| sed 's,relhasoids,$(RELHASOIDS),g'> $@;

PostgreSQL 12以降は最終的には下記に書き換わる。
※Windowsでは、Makefile を使用しないので、手動で書き換える。

pg_repack.sql
get_storage_param
 
    -- table oid
    SELECT 'oids = ' ||
        CASE WHEN FALSE
            THEN 'true'
            ELSE 'false'
        END
    FROM pg_class
it技術/データベース/postgresql/pg_repack.1751948958.txt.gz · 最終更新: 2025/07/08 13:29 by yajuadmin