/[rserv]/lib/rserv.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /lib/rserv.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2 by dpavlin, Tue Aug 5 09:52:39 2003 UTC revision 1.5 by dpavlin, Mon Nov 3 21:30:37 2003 UTC
# Line 3  Line 3 
3   * (c) 2000 Vadim Mikheev, PostgreSQL Inc.   * (c) 2000 Vadim Mikheev, PostgreSQL Inc.
4   */   */
5    
6  #include "executor/spi.h"               /* this is what you need to work with SPI */  #include "executor/spi.h"       /* this is what you need to work with SPI */
7  #include "commands/trigger.h"   /* -"- and triggers */  #include "commands/trigger.h"   /* -"- and triggers */
8  #include "utils/tqual.h"                /* -"- and SnapshotData */  #include "utils/tqual.h"        /* -"- and SnapshotData */
9  #include <ctype.h>                              /* tolower () */  #include <ctype.h>              /* tolower () */
10    
11  #ifdef PG_FUNCTION_INFO_V1  #ifdef PG_FUNCTION_INFO_V1
12  #define CurrentTriggerData ((TriggerData *) fcinfo->context)  #define CurrentTriggerData ((TriggerData *) fcinfo->context)
# Line 16  Line 16 
16  PG_FUNCTION_INFO_V1(_rserv_log_);  PG_FUNCTION_INFO_V1(_rserv_log_);
17  PG_FUNCTION_INFO_V1(_rserv_sync_);  PG_FUNCTION_INFO_V1(_rserv_sync_);
18  PG_FUNCTION_INFO_V1(_rserv_debug_);  PG_FUNCTION_INFO_V1(_rserv_debug_);
19    PG_FUNCTION_INFO_V1(_rserv_xid_);
20  Datum           _rserv_log_(PG_FUNCTION_ARGS);  Datum           _rserv_log_(PG_FUNCTION_ARGS);
21  Datum           _rserv_sync_(PG_FUNCTION_ARGS);  Datum           _rserv_sync_(PG_FUNCTION_ARGS);
22  Datum           _rserv_debug_(PG_FUNCTION_ARGS);  Datum           _rserv_debug_(PG_FUNCTION_ARGS);
23    Datum           _rserv_xid_(PG_FUNCTION_ARGS);
24    
25  #else  #else
26  HeapTuple       _rserv_log_(void);  HeapTuple       _rserv_log_(void);
27  int32           _rserv_sync_(int32);  int32           _rserv_sync_(int32);
28  int32           _rserv_debug_(int32);  int32           _rserv_debug_(int32);
29    int32           _rserv_xid_(void);
30  #endif  #endif
31    
32  static int      debug = 0;  static int      debug = 0;
# Line 31  static int     debug = 0; Line 34  static int     debug = 0;
34  static char *OutputValue(char *key, char *buf, int size);  static char *OutputValue(char *key, char *buf, int size);
35    
36  #ifdef PG_FUNCTION_INFO_V1  #ifdef PG_FUNCTION_INFO_V1
37  Datum _rserv_log_(PG_FUNCTION_ARGS)  Datum
38    _rserv_log_(PG_FUNCTION_ARGS)
39  #else  #else
40  HeapTuple _rserv_log_()  HeapTuple
41    _rserv_log_()
42  #endif  #endif
43  {  {
44    Trigger    *trigger;          /* to get trigger name */          Trigger    *trigger;            /* to get trigger name */
45    int           nargs;                  /* # of args specified in CREATE TRIGGER */          int                     nargs;                  /* # of args specified in CREATE TRIGGER */
46    char    **args;                       /* argument: argnum */          char      **args;                       /* argument: argnum */
47    Relation      rel;                    /* triggered relation */          Relation        rel;                    /* triggered relation */
48    HeapTuple     tuple;                  /* tuple to return */          HeapTuple       tuple;                  /* tuple to return */
49    HeapTuple     newtuple = NULL;        /* tuple to return */          HeapTuple       newtuple = NULL;        /* tuple to return */
50    TupleDesc     tupdesc;                /* tuple description */          TupleDesc       tupdesc;                /* tuple description */
51    int                   keynum;          int                     keynum;
52    char     *key;          char       *key;
53    char     *okey;          char       *okey;
54    char     *newkey = NULL;          char       *newkey = NULL;
55    int                   deleted, inserted, updated;          int                     deleted, inserted, updated;
56    char          sql[8192];          char            sql[8192];
57    char          outbuf[8192];          char            outbuf[8192];
58    char          oidbuf[64];          char            oidbuf[64];
59    int                   ret;          int                     ret;
60            int             server;
61    /* Called by trigger manager ? */  
62    if (!CurrentTriggerData)          /* Called by trigger manager ? */
63      elog(ERROR, "_rserv_log_: triggers are not initialized");          if (!CurrentTriggerData)
64                      elog(ERROR, "_rserv_log_: triggers are not initialized");
65    /* Should be called for ROW trigger */  
66    if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))          /* Should be called for ROW trigger */
67      elog(ERROR, "_rserv_log_: can't process STATEMENT events");          if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
68                    elog(ERROR, "_rserv_log_: can't process STATEMENT events");
69    tuple = CurrentTriggerData->tg_trigtuple;  
70            tuple = CurrentTriggerData->tg_trigtuple;
71    trigger = CurrentTriggerData->tg_trigger;  
72    nargs = trigger->tgnargs;          trigger = CurrentTriggerData->tg_trigger;
73    args = trigger->tgargs;          nargs = trigger->tgnargs;
74            args = trigger->tgargs;
75    if (nargs != 1)                               /* odd number of arguments! */  
76      elog(ERROR, "_rserv_log_: need in *one* argument");          if (nargs != 2)                         /* odd number of arguments! */
77                      elog(ERROR, "_rserv_log_: need in *two* arguments, key number and server number");
78    keynum = atoi(args[0]);  
79              keynum = atoi(args[0]);
80    if (keynum < 0 && keynum != ObjectIdAttributeNumber)          server = atoi(args[1]);
81      elog(ERROR, "_rserv_log_: invalid keynum %d", keynum);  
82              if (keynum < 0 && keynum != ObjectIdAttributeNumber)
83    rel = CurrentTriggerData->tg_relation;                  elog(ERROR, "_rserv_log_: invalid keynum %d", keynum);
84    tupdesc = rel->rd_att;  
85              rel = CurrentTriggerData->tg_relation;
86    deleted  = (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event)) ? 1 : 0;          tupdesc = rel->rd_att;
87    inserted = (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event)) ? 1 : 0;  
88    //  updated  = (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event)) ? 1 : 0;          deleted = (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event)) ?
89                    1 : 0;
90    updated = 0;  
91    if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event)) {          inserted = (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event)) ? 1 : 0;
92      updated = 1;  
93      newtuple = CurrentTriggerData->tg_newtuple;          updated = 0;
94    }          if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event)) {
95                    updated = 1;
96                    newtuple = CurrentTriggerData->tg_newtuple;
97            }
98    
99  #ifndef PG_FUNCTION_INFO_V1  #ifndef PG_FUNCTION_INFO_V1
100      
101    /*          /*
102     * Setting CurrentTriggerData to NULL prevents direct calls to trigger           * Setting CurrentTriggerData to NULL prevents direct calls to trigger
103     * functions in queries. Normally, trigger functions have to be called           * functions in queries. Normally, trigger functions have to be called
104     * by trigger manager code only.           * by trigger manager code only.
105     */           */
106    CurrentTriggerData = NULL;          CurrentTriggerData = NULL;
107  #endif  #endif
     
   /* Connect to SPI manager */  
   if ((ret = SPI_connect()) < 0)  
     elog(ERROR, "_rserv_log_: SPI_connect returned %d", ret);  
     
   if (keynum == ObjectIdAttributeNumber) {  
     sprintf(oidbuf, "%u", tuple->t_data->t_oid);  
     key = oidbuf;  
   } else {  
     key = SPI_getvalue(tuple, tupdesc, keynum);  
   }  
   
   if (key == NULL)  
     elog(ERROR, "_rserv_log_: key must be not null");  
     
   if (newtuple && keynum != ObjectIdAttributeNumber) {  
     newkey = SPI_getvalue(newtuple, tupdesc, keynum);  
     if (newkey == NULL)  
       elog(ERROR, "_rserv_log_: key must be not null");  
     if (strcmp(newkey, key) == 0)  
       newkey = NULL;  
     else  
       deleted = 1;              /* old key was deleted */  
   }  
     
   if (strpbrk(key, "\\  \n'"))  
     okey = OutputValue(key, outbuf, sizeof(outbuf));  
   else  
     okey = key;  
   
   
   /**  
      versao onde verifica-se primeiro se o registro existe  
      para decidir se faz insert ou update em _RSERV_LOG_  
   **********************/  
   
 #ifdef ASKFORUPDATE  
   sprintf(sql, "SELECT true WHERE EXISTS (SELECT logid from _RSERV_LOG_ "  
           "WHERE reloid = %u AND key = '%s')",  
           rel->rd_id, okey);  
   
   if (debug)  
     elog(NOTICE, sql);  
   
   if ((ret = SPI_exec(sql, 1)) < 0) {  
     elog(ERROR, "_rserv_log_: SPI_exec(update) returned %d", ret);  
   }  
   
   if (SPI_processed > 0) {  
     sprintf(sql, "update _RSERV_LOG_ set logid = %d, logtime = now(), "  
             "insert = %d, update = %d, delete = %d where reloid = %u "  
             "and key = '%s'",  
             GetCurrentTransactionId(),  
             inserted, updated, deleted, rel->rd_id, okey);  
       
     if (debug)  
       elog(NOTICE, sql);  
       
     ret = SPI_exec(sql, 0);  
       
     if (ret < 0)  
       elog(ERROR, "_rserv_log_: SPI_exec(update) returned %d", ret);  
       
     if (SPI_processed > 1)  
       elog(ERROR, "_rserv_log_: duplicate tuples");  
   } else {  
     sprintf(sql, "insert into _RSERV_LOG_ "  
             "(reloid, logid, logtime, insert, update, delete, key) "  
             "values (%u, %d, now(), %d, %d, %d, '%s')",  
             rel->rd_id, GetCurrentTransactionId(),  
             inserted, updated, deleted, okey);  
       
     if (debug)  
       elog(NOTICE, sql);  
       
     ret = SPI_exec(sql, 0);  
       
     if (ret < 0)  
       elog(ERROR, "_rserv_log_: SPI_exec(insert) returned %d", ret);  
   }  
108    
109  #else          /* Connect to SPI manager */
110            if ((ret = SPI_connect()) < 0)
111    sprintf(sql, "update _RSERV_LOG_ set logid = %d, logtime = now(), "                  elog(ERROR, "_rserv_log_: SPI_connect returned %d", ret);
112            "insert = %d, update = %d, delete = %d where reloid = %u "  
113            "and key = '%s'",          if (keynum == ObjectIdAttributeNumber)
114            GetCurrentTransactionId(),          {
115            inserted, updated, deleted, rel->rd_id, okey);                  snprintf(oidbuf, sizeof(oidbuf), "%u", HeapTupleGetOid(tuple));
116                      key = oidbuf;
117    if (debug)          }
118      elog(NOTICE, sql);          else
119                      key = SPI_getvalue(tuple, tupdesc, keynum);
120    ret = SPI_exec(sql, 0);  
121              if (key == NULL)
122    if (ret < 0)                  elog(ERROR, "_rserv_log_: key must be not null");
123      elog(ERROR, "_rserv_log_: SPI_exec(update) returned %d", ret);  
124              if (newtuple && keynum != ObjectIdAttributeNumber)
125              {
126    /*                  newkey = SPI_getvalue(newtuple, tupdesc, keynum);
127     * If no tuple was UPDATEd then do INSERT...                  if (newkey == NULL)
128     */                          elog(ERROR, "_rserv_log_: key must be not null");
129                    if (strcmp(newkey, key) == 0)
130                              newkey = NULL;
131    if (SPI_processed > 1)                  else
132      elog(ERROR, "_rserv_log_: duplicate tuples");                          deleted = 1;            /* old key was deleted */
133    else if (SPI_processed == 0) {          }
134      sprintf(sql, "insert into _RSERV_LOG_ "  
135              "(reloid, logid, logtime, insert, update, delete, key) "          if (strpbrk(key, "\\    \n'"))
136              "values (%u, %d, now(), %d, %d, %d, '%s')",                  okey = OutputValue(key, outbuf, sizeof(outbuf));
137              rel->rd_id, GetCurrentTransactionId(),          else
138              inserted, updated, deleted, okey);                  okey = key;
139        
140      if (debug)          snprintf(sql, 8192, "update _RSERV_LOG_ set logid = %d, logtime = now(), "
141        elog(NOTICE, sql);                          "insert = %d, update = %d, delete = %d where reloid = %u and key = '%s'",
142                                GetCurrentTransactionId(), inserted, updated, deleted, rel->rd_id, okey);
143      ret = SPI_exec(sql, 0);  
144                if (debug)
145      if (ret < 0)                  elog(DEBUG3, "sql: %s", sql);
146        elog(ERROR, "_rserv_log_: SPI_exec(insert) returned %d", ret);  
147    }          ret = SPI_exec(sql, 0);
148      
149  #endif              if (ret < 0)
150                    elog(ERROR, "_rserv_log_: SPI_exec(update) returned %d", ret);
151    if (okey != key && okey != outbuf)  
152      pfree(okey);          /*
153               * If no tuple was UPDATEd then do INSERT...
154    if (newkey) {           */
155      if (strpbrk(newkey, "\\     \n'"))          if (SPI_processed > 1)
156        okey = OutputValue(newkey, outbuf, sizeof(outbuf));                  elog(ERROR, "_rserv_log_: duplicate tuples");
157      else          else if (SPI_processed == 0)
158        okey = newkey;          {
159                        snprintf(sql, 8192, "insert into _RSERV_LOG_ "
160      sprintf(sql, "insert into _RSERV_LOG_ "                                  "(reloid, logid, logtime, insert, update, delete, key, server) "
161              "(reloid, logid, logtime, insert, update, delete, key) "                                  "values (%u, %d, now(), %d, %d, %d, '%s', %d)",
162              "values (%u, %d, now(), %d, %d, 0, '%s')",                                   rel->rd_id, GetCurrentTransactionId(),
163              rel->rd_id, GetCurrentTransactionId(), inserted, updated, okey);                                  inserted, updated, deleted, okey, server);
164        
165      if (debug)                  if (debug)
166        elog(NOTICE, sql);                          elog(DEBUG3, "sql: %s", sql);
167        
168      ret = SPI_exec(sql, 0);                  ret = SPI_exec(sql, 0);
169        
170      if (ret < 0)                  if (ret < 0)
171        elog(ERROR, "_rserv_log_: SPI_exec returned %d", ret);                          elog(ERROR, "_rserv_log_: SPI_exec(insert) returned %d", ret);
172                }
173      if (okey != newkey && okey != outbuf)  
174        pfree(okey);          if (okey != key && okey != outbuf)
175    }                  pfree(okey);
176      
177    SPI_finish();          if (newkey)
178              {
179                    if (strpbrk(newkey, "\\ \n'"))
180                            okey = OutputValue(newkey, outbuf, sizeof(outbuf));
181                    else
182                            okey = newkey;
183    
184                    snprintf(sql, 8192, "insert into _RSERV_LOG_ "
185                                     "(reloid, logid, logtime, insert, update, deleted, key, server) "
186                                     "values (%u, %d, now(), %d, %d, 0, '%s', %d)",
187                                     rel->rd_id, GetCurrentTransactionId(), inserted, updated, okey, server);
188    
189                    if (debug)
190                            elog(DEBUG3, "sql: %s", sql);
191    
192                    ret = SPI_exec(sql, 0);
193    
194                    if (ret < 0)
195                            elog(ERROR, "_rserv_log_: SPI_exec returned %d", ret);
196    
197                    if (okey != newkey && okey != outbuf)
198                            pfree(okey);
199            }
200    
201            SPI_finish();
202    
203  #ifdef PG_FUNCTION_INFO_V1  #ifdef PG_FUNCTION_INFO_V1
204    return (PointerGetDatum(tuple));          return (PointerGetDatum(tuple));
205  #else  #else
206    return (tuple);          return (tuple);
207  #endif  #endif
208  }  }
209    
# Line 278  _rserv_sync_(int32 server) Line 230  _rserv_sync_(int32 server)
230          buf[0] = 0;          buf[0] = 0;
231          for (xcnt = 0; xcnt < SerializableSnapshot->xcnt; xcnt++)          for (xcnt = 0; xcnt < SerializableSnapshot->xcnt; xcnt++)
232          {          {
233                  sprintf(buf + strlen(buf), "%s%u", (xcnt) ? ", " : "",                  snprintf(buf + strlen(buf), 8192 - strlen(buf),
234                                  SerializableSnapshot->xip[xcnt]);                                   "%s%u", (xcnt) ? ", " : "",
235                                     SerializableSnapshot->xip[xcnt]);
236          }          }
237    
238          if ((ret = SPI_connect()) < 0)          if ((ret = SPI_connect()) < 0)
239                  elog(ERROR, "_rserv_sync_: SPI_connect returned %d", ret);                  elog(ERROR, "_rserv_sync_: SPI_connect returned %d", ret);
240    
241          sprintf(sql, "insert into _RSERV_SYNC_ "          snprintf(sql, 8192, "insert into _RSERV_SYNC_ "
242                          "(server, syncid, synctime, status, minid, maxid, active) "                           "(server, syncid, synctime, status, minid, maxid, active) "
243            "values (%u, currval('_rserv_sync_seq_'), now(), 0, %d, %d, '%s')",            "values (%u, currval('_rserv_sync_seq_'), now(), 0, %d, %d, '%s')",
244                          server, SerializableSnapshot->xmin, SerializableSnapshot->xmax, active);                           server, SerializableSnapshot->xmin, SerializableSnapshot->xmax, active);
245    
246          ret = SPI_exec(sql, 0);          ret = SPI_exec(sql, 0);
247    
# Line 385  OutputValue(char *key, char *buf, int si Line 338  OutputValue(char *key, char *buf, int si
338          return (out);          return (out);
339    
340  }  }
341    
342    #ifdef PG_FUNCTION_INFO_V1
343    Datum
344    _rserv_xid_(PG_FUNCTION_ARGS)
345    #else
346    int32
347    _rserv_xid_(void)
348    #endif
349    {
350            int32   curr_xid = GetCurrentTransactionId();
351    
352            return (curr_xid);
353    }
354    

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.5

  ViewVC Help
Powered by ViewVC 1.1.26