2017-03-03 64 views
0

我正在嘗試爲PostgreSQL編寫一個小擴展。似乎我的_PG_init()不會在模塊加載時調用

作爲測試我的模塊是否正確加載的一種方法,我在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 」
  • 解配置=(上 安裝的PostgreSQL 9.6的64位版本的Windows 10)鬆開
  • 解決方案平臺= 64

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」,並增加了一個‘myextension.control’和「myextension- -1.0.sql「到」../PostgreSQL/9.6/share/extension「目錄。

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 ;,然後重新啓動服務器。

如果有人有任何想法可能會導致此,請幫助。

回答

1

一對夫婦的意見讓你在正確的軌道上:

  • _PG_fini()永遠不會被調用,因爲模塊沒有得到卸載。

_PG_init(),然而,這是在加載模塊時調用。你的主要問題似乎是爲什麼沒有寫入F:\init.txt和其他用於記錄的文件。

  • 在Windows上,PostgreSQL通常作爲服務運行。我懷疑操作系統用戶沒有寫入這些文件的權限。我對Windows及其權限管理知之甚少,但我注意到,您不檢查fopen()的返回碼,因此它可能已悄然失敗。

  • 我的建議是使用日誌基礎設施來代替,如與

    elog(LOG, "Init started!"); 
    

    這將寫入消息到PostgreSQL服務器日誌,並且更舒適,更不容易出錯。

兩個更多的評論:

  • 有創建一個擴展是沒有意義的,因爲你的代碼不提供任何SQL函數。 CREATE EXTENSION myextension是無操作的。

  • 不要忘記改變shared_preload_libraries後重新啓動PostgreSQL服務器。

+0

該日誌顯示我所需要的一切!謝謝! – ZrtvenoJagnje