Вызов пользовательской функции, расположенной в "postgres.c" в postgreSQL, с использованием графического интерфейса, определенного NetBeans

Я пытаюсь добавить 3 user_defined функции в PostgreSQL-8.4.15. Вот 3 функции:

(1) start_create_profile();

(2) make_profile();

(3) check_anomaly();

Все они написаны в файле "test.c", расположенном в src/backend/tcop. Я хочу позвонить (1) и (3) с середины exec_simple_query(), exec_simple_query() является функцией PostgreSQL, которая написана в "postgres.c", расположенном в src/backend/tcop. Я хочу вызвать (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){

}

Теперь я создал очень простой графический интерфейс, включающий 3 кнопки (от netbeans в java). Button1, button2, button3, соответствующие порядку start_create_profile(), make_profile, check_anomaly(),

Я хочу использовать глобальную переменную (Давайте рассмотрим "кнопку", которая может быть установлена ​​на 3 различных значения, таких как 0, 1, 2. Я хочу, чтобы всякий раз, когда я нажимаю кнопку 1 или кнопку 3, глобальная переменная становилась равной 1 или 2, чтобы используйте "если", что я написал в exec_simple_query(), здесь "если"

//initially button=0;
//inside exec_simple_query

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

и всякий раз, когда я нажимаю кнопку2, функция (2) должна вызываться напрямую. Любая идея, как я должен установить эту переменную, чтобы я мог выбрать одну из этих трех функций, используя мой графический интерфейс? Как мне вызвать функцию (2) напрямую через мой графический интерфейс?

1 ответ

Решение

Здесь есть несколько проблем.

Вы не можете вызвать любую функцию C из SQL

Во-первых, вы не можете просто вызывать произвольные функции из SQL, вы должны использовать API и макросы расширения C PostgreSQL; посмотрите на существующие реализации SQL-вызываемых функций в источниках для примеров.

Обычно вам не нужно изменять основной код, часто достаточно расширений

Во-вторых, если вы хотите добавить функции в ядро ​​PostgreSQL, вы должны добавить их в src/include/catalog/pg_proc.h поэтому они определены во время initdb,

Однако гораздо лучше использовать соответствующие средства загрузки расширений:

Таким образом, вы можете LOAD модуль расширения, CREATE FUNCTION C функционирует согласно документам и вызывает их из SQL.

В вашем конкретном случае похоже, что вам нужно изменить базовую кодовую базу, но это довольно необычно, поэтому я оставляю этот совет для других.

Функция A C в бэкэнде PostgreSQL не может быть вызвана "напрямую" из GUI

У вас есть Java Swing GUI, и вы предполагаете каким-то образом вызвать функцию C в другом процессе, возможно, даже на другом хосте.

Это не будет работать по нескольким причинам, в том числе:

  • Java не может напрямую вызывать функции C без склеенного кода, такого как JNI или же JNA,
  • Невозможно напрямую вызвать функцию C в другом процессе; вместо этого вы должны использовать межпроцессное взаимодействие (общая память, каналы, сокеты, общие файлы и т. д.) для обмена информацией
  • Хотя вы можете встроить интерпретатор Java в бэкэнд Pg и вызывать функцию C через JNI, вы действительно не хотите пытаться отображать графический интерфейс Swing непосредственно из бэкэнда Pg.

Что вам нужно, это многоступенчатый процесс:

  • Соберите данные, которые вы хотите захватить, в бэкэнде PostgreSQL. Если вы намереваетесь получить к нему доступ через то же соединение, что и в нем, вы можете использовать обычный palloc Буфер В противном случае вам нужно будет выделить буфер из общей памяти или обмениваться данными с помощью файловой системы.

  • Доступ к этим данным из функции C, созданной с помощью интерфейса, вызываемого SQL, согласно документации по функциям расширения C в PostgreSQL (выше).

  • Используйте соединение PostgreSQL для передачи данных из функции интерфейса, вызываемой SQL, в ваше Java-приложение. Декодируйте его в своем приложении и отображайте по желанию.

С другой стороны:

  • Требуйте, чтобы ваша Java-программа или агент для нее работали в той же системе, что и сервер PostgreSQL, и чтобы агент записывал файлы в место, доступное для записи в Pg и читаемое вашей программой.

  • Прочитайте файлы с помощью вашей программы или ее агента и обработайте их для отображения

Вы могли бы даже сделать так, чтобы Pg записывал в сокет, который слушает ваша программа, но я не рекомендую этого, так как остановка вашей программы вызовет проблемы с производительностью в PostgreSQL.

Другие вопросы по тегам