【问题标题】:It seems my _PG_init() doesn't get called when the module loads模块加载时似乎没有调用我的 _PG_init()
【发布时间】:2017-03-03 11:44:48
【问题描述】:

我正在尝试为 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)”。
  • 链接器 -> 清单文件,“生成清单”=“否”。
  • 链接器 -> 输入 -> 附加依赖项,将“postgres.lib”添加到 图书馆列表。
  • 配置属性 -> C/C++ -> 常规,附加包含
    目录,添加:“include\server\port\win32_msvc”、“include\server\port\win32”、“include\server”、“include”
  • 解决方案配置 = 发布
  • 解决方案平台 = x64(安装 64 位版本的 PostgreSQL 9.6 Windows 10)

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);
}

我复制了“../PostgreSQL/9.6/lib”目录下的“myextension.dll”,并在“../PostgreSQL/9.6/”中添加了“myextension.control”和“myextension--1.0.sql”共享/扩展”目录。

myextension.control:

# pg_extension extension
comment = 'myextension!!!'
default_version = '1.0'

myextension--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;,然后重新启动服务器。

如果有人知道可能导致此问题的原因,请提供帮助。

【问题讨论】:

    标签: c postgresql dll open-source


    【解决方案1】:

    几个 cmets 让你走上正轨:

    • _PG_fini() 永远不会被调用,因为模块不会被卸载。

    _PG_init() 但是,在加载模块时确实会被调用。您的主要问题似乎是为什么没有任何内容写入 F:\init.txt 和您用于记录的其他文件。

    • 在 Windows 上,PostgreSQL 通常作为服务运行。我怀疑操作系统用户没有写入这些文件的权限。我对Windows及其权限管理知之甚少,但我注意到你没有检查fopen()的返回码,所以它很可能默默地失败了。

    • 我的建议是改用日志基础架构,例如与

      elog(LOG, "Init started!");
      

      这会将消息写入 PostgreSQL 服务器日志,并且更加舒适且不易出错。

    另外两个cmets:

    • 创建扩展没有意义,因为您的代码不提供任何 SQL 函数。 CREATE EXTENSION myextension 是空操作。

    • 更改shared_preload_libraries后别忘了重启PostgreSQL服务器。

    【讨论】:

      猜你喜欢
      • 2014-05-22
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      • 1970-01-01
      • 2021-08-30
      • 2019-08-31
      • 2017-03-20
      • 1970-01-01
      相关资源
      最近更新 更多