Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Написание триггерной процедуры на Си / 3 сообщений из 3, страница 1 из 1
13.12.2006, 10:52
    #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
13.12.2006, 13:06
    #34196263
Алексей Ключников
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Написание триггерной процедуры на Си
вместо libpq-fe.h
используйте executor/spi.h
В документации есть примеры. только все это не очень просто..

Здесь не триггерные функции, но хоть что то, т.к. доки очень мало.
http://chernowiki.ru/index.php?node=59
...
Рейтинг: 0 / 0
13.12.2006, 17:43
    #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
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Написание триггерной процедуры на Си / 3 сообщений из 3, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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