1

我正在尝试将 3 个 user_defined 函数添加到 PostgreSQL-8.4.15。这里有3个功能:

(1)start_create_profile();

(2)make_profile();

(3)check_anomaly();

所有这些都写在位于 src/backend/tcop 的文件“test.c”中。我想从exec_simple_query(). exec_simple_query()是在 src/backend/tcop 中的“postgres.c”中编写的 PostgreSQL 函数。我想通过我的 GUI 直接调用 (2)。

这是我用“test.c”编写的代码:

#include "postgres.h"

#ifndef PROGPROFILE_H_
#define PROGPROFILE_H_

/* interfaces */
extern void start_create_profile(List *querytree_list);
extern void create_profile();
extern void check_anomaly(List *querytree_list);

#endif /* Test ProgProf */


void start_create_profile(List *querytree_list){

    ListCell *l;
    ListCell *tl;
    FILE *f;

    //if the file exist just open and write
    //else create and write
    f = fopen ("QueryParsed.txt", "a+");

    Query *query_idr = (Query *)linitial(querytree_list);

    // CMD_SELECT=0 CMD_INSERT=1 CMD_UPDATE=2
    switch (query_idr->commandType)
    {
        case CMD_SELECT:
            fputs("CMD_SELECT, ", f);
        break;

        case CMD_INSERT:
            fputs("CMD_INSERT, ", f);
            break;

        case CMD_UPDATE:
            fputs("CMD_UPDATE, ", f);
        break;

        default:
            break;
    }

    //to have the ID of the table
    foreach(l, query_idr->rtable){
        Oid tab_idT = ((RangeTblEntry *) lfirst(l)) ->relid;
        //char temp1[10];
        char *tab_idTConverted = itoa(tab_idT);
        /* This is not a table */
        if (tab_idT == 0)
            continue;

        fputs(" tab_id:  , ", f);
        fputs(tab_idTConverted, f);

    }

    //to have the name of the targer list
    foreach(tl, query_idr->targetList){
        TargetEntry *tle = (TargetEntry *) lfirst(tl);
        Oid tab_id = tle->resorigtbl;
        int tab_idCast=(int)tab_id;
        //char temp[10];
        char *tab_idConverted = itoa(tab_idCast);
        char *resname=tle->resname;

        fputs("Name of column:  ", f);
        fputs(resname, f);
        fputs(" ID:  ", f);
        fputs(tab_idConverted, f);
        fputs("\n", f);
    }

    //close the file that we write
    fputs("$", f);
    fclose (f);
}


void create_profile(){

}

void check_anomaly(List *querytree_list){

}

现在我创建了一个非常简单的 GUI,包括 3 个按钮(通过 java 中的 netbeans)。Button1, button2, button3 按顺序对应start_create_profile(), make_profile, check_anomaly().

我想使用一个全局变量(让我们考虑可以设置为 3 个不同值的“按钮”,如 0、1、2。我希望每当我按下按钮 1 或按钮 3 时,全局变量都设置为 1 或 2,以便使用我写过的exec_simple_query()“if”。这里是“if”

//initially button=0;
//inside exec_simple_query

if(button==1) start_create_profile();
if(button==2) check_anomaly;

每当我按下 button2 时,必须直接调用 function(2)。知道如何设置该变量以使我能够使用我的 GUI 选择这 3 个功能之一吗?我如何必须通过我的 GUI 直接调用函数(2)?

4

1 回答 1

4

这里有几个问题。

您不能只从 SQL 调用任何 C 函数

首先,不能只从 SQL 调用任意函数,必须使用 PostgreSQL 的 C 扩展 API 和宏;查看源代码中 SQL 可调用函数的现有实现以获取示例。

您通常不必修改核心代码,扩展通常就足够了

其次,如果您想将函数添加到核心 PostgreSQL,您必须将它们添加到src/include/catalog/pg_proc.h以便在initdb.

但是,使用适当的扩展加载工具要好得多:

通过这种方式,您可以根据文档LOAD扩展模块、 C 函数,并从 SQL 调用它们。CREATE FUNCTION

在您的特定情况下,您似乎确实需要修改核心代码库,但这很不寻常,所以我将这个建议保留给其他人。

不能从 GUI“直接”调用 PostgreSQL 后端中的 AC 函数

您有一个 Java Swing GUI,并设想以某种方式在不同的进程中调用 C 函数,甚至可能在不同的主机上。

这不起作用有很多原因,包括:

  • Java 不能直接调用 C 函数而无需像JNIor之类的胶水代码JNA
  • 不能直接在不同的进程中调用 C 函数;您必须改为使用进程间通信(共享内存、管道、套接字、共享文件等)来交换信息
  • 虽然您可以在 Pg 后端嵌入 Java 解释器并通过 JNI 直接调用 C 函数,但您确实不想尝试直接从 Pg 后端内部显示 Swing GUI。

你需要的是一个多阶段的过程:

  • 在 PostgreSQL 后端收集您希望捕获的数据。如果您打算从创建它的同一连接访问它,则可以使用普通palloc的 'd 缓冲区。否则,您将需要从共享内存中分配一个缓冲区或使用文件系统交换数据。

  • 根据 PostgreSQL 的 C 扩展函数文档(上图),从使用 SQL 可调用接口创建的 C 函数访问该数据

  • 使用 PostgreSQL 连接将数据从 SQL 可调用接口函数传输到 Java 应用程序。在您的应用程序中对其进行解码并根据需要显示它。

交替:

  • 要求您的 Java 程序或它的代理程序与 PostgreSQL 服务器在同一系统上运行,并让代理程序将文件写入可写入 Pg 并由您的程序读取的位置。

  • 使用您的程序或其代理读取文件并处理它们以供显示

您甚至可以让 Pg 写入您的程序正在侦听的套接字,但我不建议这样做,因为您的程序中的停顿会导致 PostgreSQL 中的性能问题。

于 2013-02-22T08:18:12.707 回答