使用netbeans定义的GUI在postgreSQL中调用位于“postgres.c”中的用户定义函数
我想在PostgreSQL-8.4.15中添加3个user_defined函数。 这里有3个function:
(1) start_create_profile();
(2) make_profile();
(3) check_anomaly();
所有这些都写在位于src / backend / tcop的文件“test.c”中。 我想从exec_simple_query()
的中间调用(1)和(3 exec_simple_query()
。 exec_simple_query()
是PostgreSQL函数,它写在位于src / backend / tcop的“postgres.c”中。 我想直接通过我的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。我希望每当我按下button1或button3时全局变量设置为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;
每当我按下按钮2时,必须直接调用函数(2)。 任何想法我如何设置该变量,使我能够使用我的GUI选择这3个function之一? 如何通过我的GUI直接调用函数(2)?
这里有几个问题。
你不能只从SQL调用任何C函数
首先,你不能只从SQL调用任意函数,你必须使用PostgreSQL的C扩展API和宏; 查看示例源中SQL可调用函数的现有实现。
您通常不必修改核心代码,扩展通常就足够了
其次,如果要向PostgreSQL核心添加函数,必须将它们添加到src/include/catalog/pg_proc.h
以便在initdb
期间定义initdb
。
但是,使用适当的扩展加载设备要好得多:
- http://www.postgresql.org/docs/current/static/xfunc-c.html
- http://www.postgresql.org/docs/current/static/extend-pgxs.html
这样你就可以LOAD
扩展模块,根据文档CREATE FUNCTION
C函数,然后从SQL调用它们。
在你的具体情况下,你看起来确实需要修改核心代码库,但这很不寻常,所以我会为其他人保留这个建议。
PostgreSQL后端的AC函数不能从GUI“直接”调用
你有一个Java Swing GUI,你可以设想在不同的进程中调用C函数,甚至可能在不同的主机上调用它。
这不会出于多种原因,包括:
- 如果没有像
JNI
或JNA
这样的粘合代码,Java就无法直接调用C函数。 - 不可能直接在不同的进程中调用C函数; 您必须使用进程间通信(共享内存,管道,套接字,共享文件等)来交换信息
- 虽然您可以在Pg后端嵌入Java解释器并通过JNI直接调用C函数,但您真的不想尝试直接从Pg后端内部显示Swing GUI。
您需要的是一个多阶段过程:
-
收集您希望在PostgreSQL后端捕获的数据。 如果您打算从它在其中创建的同一连接访问它,则可以使用普通的
palloc
缓冲区。 否则,您将需要从共享内存中分配缓冲区或使用文件系统交换数据。 -
根据PostgreSQL的C扩展函数文档(上面)访问使用SQL可调用接口创建的C函数中的数据
-
使用PostgreSQL连接将数据从SQL可调用接口函数传输到Java应用程序。 在您的应用程序中解码它并根据需要显示它。
交替:
-
要求您的Java程序或其代理程序在与PostgreSQL服务器相同的系统上运行,并让代理程序将文件写入可写入Pg且可由程序读取的位置。
-
使用您的程序或其代理读取文件并处理它们以供显示
你甚至可以让Pg写入你的程序正在监听的套接字,但我不建议这样做,因为程序中的停顿会导致PostgreSQL中的性能问题。