powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Написание триггерной процедуры на Си
3 сообщений из 3, страница 1 из 1
Написание триггерной процедуры на Си
    #34195634
postuser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно ли при написании триггерных процедур использовать библиотеку "libpq-fe.h" (в примерах приводят
Код: plaintext
1.
2.
#include "postgres.h"
#include "executor/spi.h"    
#include "commands/trigger.h" 

).
Приведите, плз, простенький пример (если возможно с использованием libpq-fe.h) (соединение, поучение вставляемого значения (триггер вызывается AFTER INSERT), запрос, отключение). И как потом указать путь к экзешнику, чтобы триггер мог запустить его.
Также интересует, как получить текущие значения добавляемх полей (триггер вызывается AFTER INSERT).
...
Рейтинг: 0 / 0
Написание триггерной процедуры на Си
    #34196263
Алексей Ключников
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вместо libpq-fe.h
используйте executor/spi.h
В документации есть примеры. только все это не очень просто..

Здесь не триггерные функции, но хоть что то, т.к. доки очень мало.
http://chernowiki.ru/index.php?node=59
...
Рейтинг: 0 / 0
Написание триггерной процедуры на Си
    #34197608
СергейК
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
postuserМожно ли при написании триггерных процедур использовать библиотеку "libpq-fe.h" (в примерах приводят
Код: plaintext
1.
2.
#include "postgres.h"
#include "executor/spi.h"    
#include "commands/trigger.h" 

).
Приведите, плз, простенький пример (если возможно с использованием libpq-fe.h) (соединение, поучение вставляемого значения (триггер вызывается AFTER INSERT), запрос, отключение). И как потом указать путь к экзешнику, чтобы триггер мог запустить его.
Также интересует, как получить текущие значения добавляемх полей (триггер вызывается AFTER INSERT).

Mojet Vam prigoditsia moi kod, kotoryi pokazyvaet znachenia izmenivshihsia polei pri UPDATE i DELETE.
Kod uchebnyi, tak chto po etomu on tak parshivo vygliadit (no vrode on rabotal).:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
#include "postgres.h"
#include "executor/spi.h"       /* this is what you need to work with SPI */
#include "commands/trigger.h"   /* ... and triggers */

static char * get_column_name(int attrelid, int col_num, char *result)
{
  int ret; 
  char query[ 256 ];
  
  sprintf(query,"select attname from pg_attribute  where attrelid=%d and attnum=%d",attrelid, col_num);
  
  ret = SPI_exec(query,  1 );
  return SPI_getvalue(SPI_tuptable->vals[ 0 ], SPI_tuptable->tupdesc,  1 );
}

extern Datum trigf(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(trigf);

Datum
trigf(PG_FUNCTION_ARGS)
{
    TriggerData *trigdata = (TriggerData *) fcinfo->context;
    TupleDesc   tupdesc;
    HeapTuple   rettuple;
    char       *when;
    bool        checknull = false;
    bool        isnull;
    int         ret, i;
    enum {UPDATE, DELETE, INSERT} state; 

    /* make sure it's called as a trigger at all */
    if (!CALLED_AS_TRIGGER(fcinfo))
        elog(ERROR, "trigf: not called by trigger manager");

    /* tuple to return to executor */
    if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
    {
        state= UPDATE;
        rettuple = trigdata->tg_newtuple;
    }
    else
        rettuple = trigdata->tg_trigtuple;

    /* check for null values */
    if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
    {
      state = DELETE;
    }

    if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
    {
      state = INSERT;
    }

    tupdesc = trigdata->tg_relation->rd_att;

    /* connect to SPI manager */
    if ((ret = SPI_connect()) < 0)
        elog(ERROR, "trigf (fired %s): SPI_connect returned %d", when, ret);

    
    char *relation_name = SPI_getrelname(trigdata->tg_relation);
    char *schema_name = SPI_getnspname(trigdata->tg_relation);
    /* Should be pfreed at the end */

    elog (INFO, "XXX TABLE %s", name);
//    elog (INFO, "xxx %s", get_column_name(trigdata->tg_relation->rd_id,2,""));
    
    char *buf, *p, *p1;
    int len, buf_len=100;
    buf=palloc(100);
    buf[0]=0;
    buf[1]=0;
    char pgnull[1]={0};
    if (state==DELETE)
    {
      elog (INFO, "XXX DELETE");
      buf[0]='(';
      buf_len=1;
      for(i = 1; i <= tupdesc->natts;i++)
      {
        p=SPI_getvalue(trigdata->tg_trigtuple,tupdesc,i);
        len=strlen(p);
        buf=repalloc(buf,len+buf_len+1);
        if (i!=1) strcat(buf,",");
        strcat(buf,p);
        buf_len+=len+1;
      }
      strcat(buf,")");
      elog (INFO, "XXX %s", buf);
    }
    else if (state==UPDATE)
    {
      elog (INFO, "XXX UPDATE");
      /*
      for(i=1;i<=tupdesc->natts;i++)
      {
        p=SPI_getvalue(trigdata->tg_trigtuple,tupdesc,i);
        p1=SPI_getvalue(trigdata->tg_newtuple,tupdesc,i);
        /*if (strcmp(p,p1))
        {
          elog(INFO, "CHANGE (column %s): %s -> %s", get_column_name(trigdata->tg_relation->rd_id,2,""), p, p1);
        }
        */
        buf[0]='(';
      buf_len=1;
      
      for(i = 1; i <= tupdesc->natts;i++)
      {
        p=SPI_getvalue(trigdata->tg_trigtuple,tupdesc,i);
        if (p==0) {p=pgnull;}        
        len=strlen(p);
        buf=repalloc(buf,len+buf_len+1);
        if (i!=1) strcat(buf,",");
        strcat(buf,p);
        buf_len+=len+1;
      }
      strcat(buf,")");
      elog (INFO, "XXX %s", buf);

        buf[0]='(';
        buf[1]=0;
      buf_len=1;
      for(i = 1; i <= tupdesc->natts;i++)
      {
        p=SPI_getvalue(trigdata->tg_newtuple,tupdesc,i);
        if (p==0) {p=pgnull;}
        len=strlen(p);
        buf=repalloc(buf,len+buf_len+1);
        if (i!=1) strcat(buf,",");
        strcat(buf,p);
        buf_len+=len+1;
      }
      strcat(buf,")");
      elog (INFO,"XXX ->>> %s", buf);        
      /*}*/
      
    }
    else if (state==INSERT)
    {
      elog (INFO, "XXX INSERT");
      buf[0]='(';
      buf_len=1;
      for(i = 1; i <= tupdesc->natts;i++)
      {
        p=SPI_getvalue(trigdata->tg_trigtuple,tupdesc,i);
        if (p==0) {p=pgnull;}
        len=strlen(p);
        buf=repalloc(buf,len+buf_len+1);
        if (i!=1) strcat(buf,",");
        strcat(buf,p);
        buf_len+=len+1;
      }
      strcat(buf,")");
      elog (INFO, "XXX %s", buf);
    }    

//    elog(NOTICE, "XXXX %s",ss);
/*
    ss[0]=0;
    if (trigdata->tg_newtuple!=NULL)
    for(i=1;i<=tupdesc->natts;i++)
    {
      strcat(ss,SPI_getvalue(trigdata->tg_newtuple,tupdesc,i));
    }
    elog(NOTICE, "YYYY %s",ss);
*/

//    SPI_finish();
//    char query[ 256 ];
//    sprintf(query,"SELECT relname FROM pg_class where reltype=%d",trigdata->tg_relation->rd_id);

//    ret = SPI_exec(query,  1 );


/*
    if (ret < 0)
        elog(NOTICE, "trigf (fired %s): SPI_exec returned %d", when, ret);

    char *query1 = SPI_getvalue(SPI_tuptable->vals[0],
                                    SPI_tuptable->tupdesc,
                                    1);

    elog (INFO, "table %s", query1);
*/

//      ret=SPI_execute("INSERT INTO foo VALUES (1)", false,  1 );
//elog(INFO,"%d",ret==SPI_OK_INSERT);


    SPI_finish();

/*
    if (checknull)
    {
        SPI_getbinval(rettuple, tupdesc, 1, &isnull);
        if (isnull)
            rettuple = NULL;
    }
*/
    return PointerGetDatum(rettuple);
}

...
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Написание триггерной процедуры на Си
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]