似乎我的 _PG_init() 在模块加载时没有被调用
It seems my _PG_init() doesn't get called when the module loads
我正在尝试为 PostgreSQL 编写一个小扩展。
作为测试我的模块是否正确加载的一种方法,我在 void _PG_init(void)
和 void _PG_fini(void)
函数的文件中写了一些东西。下面是这两个函数的代码:
#include "postgres.h"
#include "executor\executor.h"
#include "fmgr.h"
#include "funcapi.h"
#include <stdio.h>
PG_MODULE_MAGIC;
extern void _PG_init(void);
extern void _PG_fini(void);
static void myExecutorStart(QueryDesc *queryDesc, int eflags);
static void myExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count);
static void myExecutorFinish(QueryDesc *queryDesc);
static void myExecutorEnd(QueryDesc *queryDesc);
static ExecutorStart_hook_type prevExecutorStart = NULL;
static ExecutorRun_hook_type prevExecutorRun = NULL;
static ExecutorFinish_hook_type prevExecutorFinish = NULL;
static ExecutorEnd_hook_type prevExecutorEnd = NULL;
void _PG_init(void) {
FILE *file = NULL;
file = fopen("F:\init.txt", "a+");
fprintf(file, "Init started!\n");
fclose(file);
prevExecutorStart = ExecutorStart_hook;
ExecutorStart_hook = myExecutorStart;
prevExecutorRun = ExecutorRun_hook;
ExecutorRun_hook = myExecutorRun;
prevExecutorFinish = ExecutorFinish_hook;
ExecutorFinish_hook = myExecutorFinish;
prevExecutorEnd = ExecutorEnd_hook;
ExecutorEnd_hook = myExecutorEnd;
}
void _PG_fini(void) {
FILE *file = NULL;
file = fopen("F:\fini.txt", "a+");
fprintf(file, "Fini started!\n");
fclose(file);
ExecutorStart_hook = prevExecutorStart;
ExecutorRun_hook = prevExecutorRun;
ExecutorFinish_hook = prevExecutorFinish;
ExecutorEnd_hook = prevExecutorEnd;
}
这些函数在一个名为 "myextension.c" 的文件中,编译成 "myextension.dll"。我在 Visual Studio 2015 年使用以下设置构建它:
- 配置属性 -> 常规,“配置类型”=“动态
库 (.dll)”。
- C/C++ -> 代码生成,“启用 C++ 异常”=“否”,“高级”
设置“编译为”=“编译为 C 代码 (/TC)”。
- 链接器 -> 清单文件,“生成清单”=“否”。
- Linker -> Input -> Additional Dependencies, 添加“postgres.lib”到
图书馆列表。
- 配置属性 -> C/C++ -> 常规,附加包含
目录,添加:“include\server\port\win32_msvc”、“include\server\port\win32”、“include\server”、“include”
- 解决方案配置=发布
- 解决方案平台 = x64(已安装 64 位版本的 PostgreSQL 9.6
Windows10)
在myExecutorXXX函数中我检查是否有之前的ExecutorXXX函数,如果存在则调用它们,如果不存在则调用standard_ExecutorXXX 函数。这是其中一个函数的示例:
static void myExecutorStart(QueryDesc *queryDesc, int eflags) {
if (prevExecutorStart) prevExecutorStart(queryDesc, eflags);
else standard_ExecutorStart(queryDesc, eflags);
FILE *file = NULL;
file = fopen("F:\query.txt", "a+");
fprintf(file, "Query: %s started!\n", queryDesc->sourceText);
fclose(file);
}
我把"myextension.dll"复制到"../PostgreSQL/9.6/lib"目录下,在"../PostgreSQL/9.6/share/extension" 目录.
myextension.control:
# pg_extension extension
comment = 'myextension!!!'
default_version = '1.0'
我的分机--1.0.sql:
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION myextension" to load this file. \quit
在"postgresql.conf"中我添加了shared_preload_libraries='myextension'。之后,我连接到一个测试数据库并 运行: CREATE EXTENSION myextension;,然后重新启动服务器。
如果有人知道可能导致此问题的原因,请提供帮助。
一些评论可以让您走上正轨:
_PG_fini()
永远不会被调用,因为模块不会被卸载。
但是,_PG_init()
会在加载模块时调用。您的主要问题似乎是为什么没有任何内容写入 F:\init.txt
和您用于记录的其他文件。
在 Windows 上,PostgreSQL 通常作为服务运行。我怀疑操作系统用户没有权限写入这些文件。我对Windows及其权限管理知之甚少,但我注意到你没有检查fopen()
的return代码,所以它很可能已经悄无声息地失败了。
我的建议是改用日志记录基础设施,例如与
elog(LOG, "Init started!");
这会将消息写入 PostgreSQL 服务器日志,并且更加舒适且不易出错。
另外两条评论:
创建扩展没有意义,因为您的代码不提供任何 SQL 功能。 CREATE EXTENSION myextension
是一个空操作。
不要忘记在更改 shared_preload_libraries
.
后重新启动 PostgreSQL 服务器
我正在尝试为 PostgreSQL 编写一个小扩展。
作为测试我的模块是否正确加载的一种方法,我在 void _PG_init(void)
和 void _PG_fini(void)
函数的文件中写了一些东西。下面是这两个函数的代码:
#include "postgres.h"
#include "executor\executor.h"
#include "fmgr.h"
#include "funcapi.h"
#include <stdio.h>
PG_MODULE_MAGIC;
extern void _PG_init(void);
extern void _PG_fini(void);
static void myExecutorStart(QueryDesc *queryDesc, int eflags);
static void myExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count);
static void myExecutorFinish(QueryDesc *queryDesc);
static void myExecutorEnd(QueryDesc *queryDesc);
static ExecutorStart_hook_type prevExecutorStart = NULL;
static ExecutorRun_hook_type prevExecutorRun = NULL;
static ExecutorFinish_hook_type prevExecutorFinish = NULL;
static ExecutorEnd_hook_type prevExecutorEnd = NULL;
void _PG_init(void) {
FILE *file = NULL;
file = fopen("F:\init.txt", "a+");
fprintf(file, "Init started!\n");
fclose(file);
prevExecutorStart = ExecutorStart_hook;
ExecutorStart_hook = myExecutorStart;
prevExecutorRun = ExecutorRun_hook;
ExecutorRun_hook = myExecutorRun;
prevExecutorFinish = ExecutorFinish_hook;
ExecutorFinish_hook = myExecutorFinish;
prevExecutorEnd = ExecutorEnd_hook;
ExecutorEnd_hook = myExecutorEnd;
}
void _PG_fini(void) {
FILE *file = NULL;
file = fopen("F:\fini.txt", "a+");
fprintf(file, "Fini started!\n");
fclose(file);
ExecutorStart_hook = prevExecutorStart;
ExecutorRun_hook = prevExecutorRun;
ExecutorFinish_hook = prevExecutorFinish;
ExecutorEnd_hook = prevExecutorEnd;
}
这些函数在一个名为 "myextension.c" 的文件中,编译成 "myextension.dll"。我在 Visual Studio 2015 年使用以下设置构建它:
- 配置属性 -> 常规,“配置类型”=“动态 库 (.dll)”。
- C/C++ -> 代码生成,“启用 C++ 异常”=“否”,“高级”
设置“编译为”=“编译为 C 代码 (/TC)”。 - 链接器 -> 清单文件,“生成清单”=“否”。
- Linker -> Input -> Additional Dependencies, 添加“postgres.lib”到 图书馆列表。
- 配置属性 -> C/C++ -> 常规,附加包含
目录,添加:“include\server\port\win32_msvc”、“include\server\port\win32”、“include\server”、“include” - 解决方案配置=发布
- 解决方案平台 = x64(已安装 64 位版本的 PostgreSQL 9.6 Windows10)
在myExecutorXXX函数中我检查是否有之前的ExecutorXXX函数,如果存在则调用它们,如果不存在则调用standard_ExecutorXXX 函数。这是其中一个函数的示例:
static void myExecutorStart(QueryDesc *queryDesc, int eflags) {
if (prevExecutorStart) prevExecutorStart(queryDesc, eflags);
else standard_ExecutorStart(queryDesc, eflags);
FILE *file = NULL;
file = fopen("F:\query.txt", "a+");
fprintf(file, "Query: %s started!\n", queryDesc->sourceText);
fclose(file);
}
我把"myextension.dll"复制到"../PostgreSQL/9.6/lib"目录下,在"../PostgreSQL/9.6/share/extension" 目录.
myextension.control:
# pg_extension extension
comment = 'myextension!!!'
default_version = '1.0'
我的分机--1.0.sql:
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION myextension" to load this file. \quit
在"postgresql.conf"中我添加了shared_preload_libraries='myextension'。之后,我连接到一个测试数据库并 运行: CREATE EXTENSION myextension;,然后重新启动服务器。
如果有人知道可能导致此问题的原因,请提供帮助。
一些评论可以让您走上正轨:
_PG_fini()
永远不会被调用,因为模块不会被卸载。
_PG_init()
会在加载模块时调用。您的主要问题似乎是为什么没有任何内容写入 F:\init.txt
和您用于记录的其他文件。
在 Windows 上,PostgreSQL 通常作为服务运行。我怀疑操作系统用户没有权限写入这些文件。我对Windows及其权限管理知之甚少,但我注意到你没有检查
fopen()
的return代码,所以它很可能已经悄无声息地失败了。我的建议是改用日志记录基础设施,例如与
elog(LOG, "Init started!");
这会将消息写入 PostgreSQL 服务器日志,并且更加舒适且不易出错。
另外两条评论:
创建扩展没有意义,因为您的代码不提供任何 SQL 功能。
CREATE EXTENSION myextension
是一个空操作。不要忘记在更改
shared_preload_libraries
. 后重新启动 PostgreSQL 服务器