/[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.1 by dpavlin, Wed Dec 20 17:22:35 2000 UTC revision 1.2 by dpavlin, Tue Aug 5 09:52:39 2003 UTC
# 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  Datum _rserv_log_(PG_FUNCTION_ARGS);  Datum           _rserv_log_(PG_FUNCTION_ARGS);
20  Datum _rserv_sync_(PG_FUNCTION_ARGS);  Datum           _rserv_sync_(PG_FUNCTION_ARGS);
21  Datum _rserv_debug_(PG_FUNCTION_ARGS);  Datum           _rserv_debug_(PG_FUNCTION_ARGS);
22    
23  #else  #else
24  HeapTuple       _rserv_log_(void);  HeapTuple       _rserv_log_(void);
25  int32           _rserv_sync_(int32);  int32           _rserv_sync_(int32);
# Line 27  int32          _rserv_debug_(int32); Line 28  int32          _rserv_debug_(int32);
28    
29  static int      debug = 0;  static int      debug = 0;
30    
31  static char* OutputValue(char *key, char *buf, int size);  static char *OutputValue(char *key, char *buf, int size);
32    
33  #ifdef PG_FUNCTION_INFO_V1  #ifdef PG_FUNCTION_INFO_V1
34  Datum  Datum _rserv_log_(PG_FUNCTION_ARGS)
 _rserv_log_(PG_FUNCTION_ARGS)  
35  #else  #else
36  HeapTuple  HeapTuple _rserv_log_()
 _rserv_log_()  
37  #endif  #endif
38  {  {
39          Trigger    *trigger;            /* to get trigger name */    Trigger    *trigger;          /* to get trigger name */
40          int                     nargs;                  /* # of args specified in CREATE TRIGGER */    int           nargs;                  /* # of args specified in CREATE TRIGGER */
41          char      **args;                       /* argument: argnum */    char    **args;                       /* argument: argnum */
42          Relation        rel;                    /* triggered relation */    Relation      rel;                    /* triggered relation */
43          HeapTuple       tuple;                  /* tuple to return */    HeapTuple     tuple;                  /* tuple to return */
44          HeapTuple       newtuple = NULL;/* tuple to return */    HeapTuple     newtuple = NULL;        /* tuple to return */
45          TupleDesc       tupdesc;                /* tuple description */    TupleDesc     tupdesc;                /* tuple description */
46          int                     keynum;    int                   keynum;
47          char       *key;    char     *key;
48          char       *okey;    char     *okey;
49          char       *newkey = NULL;    char     *newkey = NULL;
50          int                     deleted;    int                   deleted, inserted, updated;
51          char            sql[8192];    char          sql[8192];
52          char            outbuf[8192];    char          outbuf[8192];
53          char            oidbuf[64];    char          oidbuf[64];
54          int                     ret;    int                   ret;
55    
56          /* Called by trigger manager ? */    /* Called by trigger manager ? */
57          if (!CurrentTriggerData)    if (!CurrentTriggerData)
58                  elog(ERROR, "_rserv_log_: triggers are not initialized");      elog(ERROR, "_rserv_log_: triggers are not initialized");
59      
60          /* Should be called for ROW trigger */    /* Should be called for ROW trigger */
61          if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))    if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
62                  elog(ERROR, "_rserv_log_: can't process STATEMENT events");      elog(ERROR, "_rserv_log_: can't process STATEMENT events");
63    
64          tuple = CurrentTriggerData->tg_trigtuple;    tuple = CurrentTriggerData->tg_trigtuple;
65    
66          trigger = CurrentTriggerData->tg_trigger;    trigger = CurrentTriggerData->tg_trigger;
67          nargs = trigger->tgnargs;    nargs = trigger->tgnargs;
68          args = trigger->tgargs;    args = trigger->tgargs;
69    
70          if (nargs != 1)                 /* odd number of arguments! */    if (nargs != 1)                               /* odd number of arguments! */
71                  elog(ERROR, "_rserv_log_: need in *one* argument");      elog(ERROR, "_rserv_log_: need in *one* argument");
72      
73          keynum = atoi(args[0]);    keynum = atoi(args[0]);
74      
75          if (keynum < 0 && keynum != ObjectIdAttributeNumber)    if (keynum < 0 && keynum != ObjectIdAttributeNumber)
76                  elog(ERROR, "_rserv_log_: invalid keynum %d", keynum);      elog(ERROR, "_rserv_log_: invalid keynum %d", keynum);
77      
78          rel = CurrentTriggerData->tg_relation;    rel = CurrentTriggerData->tg_relation;
79          tupdesc = rel->rd_att;    tupdesc = rel->rd_att;
80      
81          deleted = (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event)) ?    deleted  = (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event)) ? 1 : 0;
82                  1 : 0;    inserted = (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event)) ? 1 : 0;
83      //  updated  = (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event)) ? 1 : 0;
84          if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))  
85                  newtuple = CurrentTriggerData->tg_newtuple;    updated = 0;
86      if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event)) {
87          /*      updated = 1;
88           * Setting CurrentTriggerData to NULL prevents direct calls to trigger      newtuple = CurrentTriggerData->tg_newtuple;
89           * functions in queries. Normally, trigger functions have to be called    }
90           * by trigger manager code only.  
91           */  #ifndef PG_FUNCTION_INFO_V1
92          CurrentTriggerData = NULL;    
93      /*
94          /* Connect to SPI manager */     * Setting CurrentTriggerData to NULL prevents direct calls to trigger
95          if ((ret = SPI_connect()) < 0)     * functions in queries. Normally, trigger functions have to be called
96                  elog(ERROR, "_rserv_log_: SPI_connect returned %d", ret);     * by trigger manager code only.
97       */
98          if (keynum == ObjectIdAttributeNumber)    CurrentTriggerData = NULL;
99          {  #endif
100                  sprintf(oidbuf, "%u", tuple->t_data->t_oid);    
101                  key = oidbuf;    /* Connect to SPI manager */
102          }    if ((ret = SPI_connect()) < 0)
103          else      elog(ERROR, "_rserv_log_: SPI_connect returned %d", ret);
104                  key = SPI_getvalue(tuple, tupdesc, keynum);    
105      if (keynum == ObjectIdAttributeNumber) {
106          if (key == NULL)      sprintf(oidbuf, "%u", tuple->t_data->t_oid);
107                  elog(ERROR, "_rserv_log_: key must be not null");      key = oidbuf;
108      } else {
109          if (newtuple && keynum != ObjectIdAttributeNumber)      key = SPI_getvalue(tuple, tupdesc, keynum);
110          {    }
111                  newkey = SPI_getvalue(newtuple, tupdesc, keynum);  
112                  if (newkey == NULL)    if (key == NULL)
113                          elog(ERROR, "_rserv_log_: key must be not null");      elog(ERROR, "_rserv_log_: key must be not null");
114                  if (strcmp(newkey, key) == 0)    
115                          newkey = NULL;    if (newtuple && keynum != ObjectIdAttributeNumber) {
116                  else      newkey = SPI_getvalue(newtuple, tupdesc, keynum);
117                          deleted = 1;    /* old key was deleted */      if (newkey == NULL)
118          }        elog(ERROR, "_rserv_log_: key must be not null");
119        if (strcmp(newkey, key) == 0)
120          if (strpbrk(key, "\\    \n'"))        newkey = NULL;
121                  okey = OutputValue(key, outbuf, sizeof(outbuf));      else
122          else        deleted = 1;              /* old key was deleted */
123                  okey = key;    }
124      
125          sprintf(sql, "update _RSERV_LOG_ set logid = %d, logtime = now(), "    if (strpbrk(key, "\\  \n'"))
126                          "deleted = %d where reloid = %u and key = '%s'",      okey = OutputValue(key, outbuf, sizeof(outbuf));
127                          GetCurrentTransactionId(), deleted, rel->rd_id, okey);    else
128        okey = key;
129          if (debug)  
130                  elog(NOTICE, sql);  
131      /**
132          ret = SPI_exec(sql, 0);       versao onde verifica-se primeiro se o registro existe
133         para decidir se faz insert ou update em _RSERV_LOG_
134          if (ret < 0)    **********************/
135                  elog(ERROR, "_rserv_log_: SPI_exec(update) returned %d", ret);  
136    #ifdef ASKFORUPDATE
137          /*    sprintf(sql, "SELECT true WHERE EXISTS (SELECT logid from _RSERV_LOG_ "
138           * If no tuple was UPDATEd then do INSERT...            "WHERE reloid = %u AND key = '%s')",
139           */            rel->rd_id, okey);
140          if (SPI_processed > 1)  
141                  elog(ERROR, "_rserv_log_: duplicate tuples");    if (debug)
142          else if (SPI_processed == 0)      elog(NOTICE, sql);
143          {  
144                  sprintf(sql, "insert into _RSERV_LOG_ "    if ((ret = SPI_exec(sql, 1)) < 0) {
145                                  "(reloid, logid, logtime, deleted, key) "      elog(ERROR, "_rserv_log_: SPI_exec(update) returned %d", ret);
146                                  "values (%u, %d, now(), %d, '%s')",    }
147                                  rel->rd_id, GetCurrentTransactionId(),  
148                                  deleted, okey);    if (SPI_processed > 0) {
149        sprintf(sql, "update _RSERV_LOG_ set logid = %d, logtime = now(), "
150                  if (debug)              "insert = %d, update = %d, delete = %d where reloid = %u "
151                          elog(NOTICE, sql);              "and key = '%s'",
152                GetCurrentTransactionId(),
153                  ret = SPI_exec(sql, 0);              inserted, updated, deleted, rel->rd_id, okey);
154        
155                  if (ret < 0)      if (debug)
156                          elog(ERROR, "_rserv_log_: SPI_exec(insert) returned %d", ret);        elog(NOTICE, sql);
157          }      
158        ret = SPI_exec(sql, 0);
159          if (okey != key && okey != outbuf)      
160                  pfree(okey);      if (ret < 0)
161          elog(ERROR, "_rserv_log_: SPI_exec(update) returned %d", ret);
162          if (newkey)      
163          {      if (SPI_processed > 1)
164                  if (strpbrk(newkey, "\\ \n'"))        elog(ERROR, "_rserv_log_: duplicate tuples");
165                          okey = OutputValue(newkey, outbuf, sizeof(outbuf));    } else {
166                  else      sprintf(sql, "insert into _RSERV_LOG_ "
167                          okey = newkey;              "(reloid, logid, logtime, insert, update, delete, key) "
168                "values (%u, %d, now(), %d, %d, %d, '%s')",
169                  sprintf(sql, "insert into _RSERV_LOG_ "              rel->rd_id, GetCurrentTransactionId(),
170                                  "(reloid, logid, logtime, deleted, key) "              inserted, updated, deleted, okey);
171                                  "values (%u, %d, now(), 0, '%s')",      
172                                  rel->rd_id, GetCurrentTransactionId(), okey);      if (debug)
173          elog(NOTICE, sql);
174                  if (debug)      
175                          elog(NOTICE, sql);      ret = SPI_exec(sql, 0);
176        
177                  ret = SPI_exec(sql, 0);      if (ret < 0)
178          elog(ERROR, "_rserv_log_: SPI_exec(insert) returned %d", ret);
179                  if (ret < 0)    }
                         elog(ERROR, "_rserv_log_: SPI_exec returned %d", ret);  
   
                 if (okey != newkey && okey != outbuf)  
                         pfree(okey);  
         }  
   
         SPI_finish();  
180    
181    #else
182    
183      sprintf(sql, "update _RSERV_LOG_ set logid = %d, logtime = now(), "
184              "insert = %d, update = %d, delete = %d where reloid = %u "
185              "and key = '%s'",
186              GetCurrentTransactionId(),
187              inserted, updated, deleted, rel->rd_id, okey);
188      
189      if (debug)
190        elog(NOTICE, sql);
191      
192      ret = SPI_exec(sql, 0);
193      
194      if (ret < 0)
195        elog(ERROR, "_rserv_log_: SPI_exec(update) returned %d", ret);
196      
197      
198      /*
199       * If no tuple was UPDATEd then do INSERT...
200       */
201    
202      
203      if (SPI_processed > 1)
204        elog(ERROR, "_rserv_log_: duplicate tuples");
205      else if (SPI_processed == 0) {
206        sprintf(sql, "insert into _RSERV_LOG_ "
207                "(reloid, logid, logtime, insert, update, delete, key) "
208                "values (%u, %d, now(), %d, %d, %d, '%s')",
209                rel->rd_id, GetCurrentTransactionId(),
210                inserted, updated, deleted, okey);
211        
212        if (debug)
213          elog(NOTICE, sql);
214        
215        ret = SPI_exec(sql, 0);
216        
217        if (ret < 0)
218          elog(ERROR, "_rserv_log_: SPI_exec(insert) returned %d", ret);
219      }
220      
221    #endif    
222    
223      if (okey != key && okey != outbuf)
224        pfree(okey);
225      
226      if (newkey) {
227        if (strpbrk(newkey, "\\     \n'"))
228          okey = OutputValue(newkey, outbuf, sizeof(outbuf));
229        else
230          okey = newkey;
231        
232        sprintf(sql, "insert into _RSERV_LOG_ "
233                "(reloid, logid, logtime, insert, update, delete, key) "
234                "values (%u, %d, now(), %d, %d, 0, '%s')",
235                rel->rd_id, GetCurrentTransactionId(), inserted, updated, okey);
236        
237        if (debug)
238          elog(NOTICE, sql);
239        
240        ret = SPI_exec(sql, 0);
241        
242        if (ret < 0)
243          elog(ERROR, "_rserv_log_: SPI_exec returned %d", ret);
244        
245        if (okey != newkey && okey != outbuf)
246          pfree(okey);
247      }
248      
249      SPI_finish();
250      
251  #ifdef PG_FUNCTION_INFO_V1  #ifdef PG_FUNCTION_INFO_V1
252          return (PointerGetDatum(tuple));    return (PointerGetDatum(tuple));
253  #else  #else
254          return (tuple);    return (tuple);
255  #endif  #endif
256  }  }
257    
# Line 202  _rserv_sync_(int32 server) Line 264  _rserv_sync_(int32 server)
264  #endif  #endif
265  {  {
266  #ifdef PG_FUNCTION_INFO_V1  #ifdef PG_FUNCTION_INFO_V1
267          int32 server = PG_GETARG_INT32(0);          int32           server = PG_GETARG_INT32(0);
268  #endif  #endif
269          char    sql[8192];          char            sql[8192];
270          char    buf[8192];          char            buf[8192];
271          char   *active = buf;          char       *active = buf;
272          uint32  xcnt;          uint32          xcnt;
273          int             ret;          int                     ret;
274    
275          if (SerializableSnapshot == NULL)          if (SerializableSnapshot == NULL)
276                  elog(ERROR, "_rserv_sync_: SerializableSnapshot is NULL");                  elog(ERROR, "_rserv_sync_: SerializableSnapshot is NULL");
# Line 217  _rserv_sync_(int32 server) Line 279  _rserv_sync_(int32 server)
279          for (xcnt = 0; xcnt < SerializableSnapshot->xcnt; xcnt++)          for (xcnt = 0; xcnt < SerializableSnapshot->xcnt; xcnt++)
280          {          {
281                  sprintf(buf + strlen(buf), "%s%u", (xcnt) ? ", " : "",                  sprintf(buf + strlen(buf), "%s%u", (xcnt) ? ", " : "",
282                          SerializableSnapshot->xip[xcnt]);                                  SerializableSnapshot->xip[xcnt]);
283          }          }
284    
285          if ((ret = SPI_connect()) < 0)          if ((ret = SPI_connect()) < 0)
# Line 225  _rserv_sync_(int32 server) Line 287  _rserv_sync_(int32 server)
287    
288          sprintf(sql, "insert into _RSERV_SYNC_ "          sprintf(sql, "insert into _RSERV_SYNC_ "
289                          "(server, syncid, synctime, status, minid, maxid, active) "                          "(server, syncid, synctime, status, minid, maxid, active) "
290                          "values (%u, currval('_rserv_sync_seq_'), now(), 0, %d, %d, '%s')",            "values (%u, currval('_rserv_sync_seq_'), now(), 0, %d, %d, '%s')",
291                          server, SerializableSnapshot->xmin, SerializableSnapshot->xmax, active);                          server, SerializableSnapshot->xmin, SerializableSnapshot->xmax, active);
292    
293          ret = SPI_exec(sql, 0);          ret = SPI_exec(sql, 0);
# Line 247  _rserv_debug_(int32 newval) Line 309  _rserv_debug_(int32 newval)
309  #endif  #endif
310  {  {
311  #ifdef PG_FUNCTION_INFO_V1  #ifdef PG_FUNCTION_INFO_V1
312          int32   newval = PG_GETARG_INT32(0);          int32           newval = PG_GETARG_INT32(0);
313  #endif  #endif
314          int32   oldval = debug;          int32           oldval = debug;
315    
316          debug = newval;          debug = newval;
317    
318          return (oldval);          return (oldval);
319  }  }
320    
321  #define ExtendBy        1024  #define ExtendBy        1024
322    
323  static char*  static char *
324  OutputValue(char *key, char *buf, int size)  OutputValue(char *key, char *buf, int size)
325  {  {
326          int                     i = 0;          int                     i = 0;
# Line 267  OutputValue(char *key, char *buf, int si Line 329  OutputValue(char *key, char *buf, int si
329          int                     slen = 0;          int                     slen = 0;
330    
331          size--;          size--;
332          for ( ; ; )          for (;;)
333          {          {
334                  switch (*key)                  switch (*key)
335                  {                  {
336                          case '\\':      subst ="\\\\";                          case '\\':
337                                                  slen = 2;                                  subst = "\\\\";
338                                                  break;                                  slen = 2;
339                          case '  ':      subst = "\\011";                                  break;
340                                                  slen = 4;                          case '  ':
341                                                  break;                                  subst = "\\011";
342                          case '\n':      subst = "\\012";                                  slen = 4;
343                                                  slen = 4;                                  break;
344                                                  break;                          case '\n':
345                          case '\'':      subst = "\\047";                                  subst = "\\012";
346                                                  slen = 4;                                  slen = 4;
347                                                  break;                                  break;
348                          case '\0':      out[i] = 0;                          case '\'':
349                                                  return(out);                                  subst = "\\047";
350                          default:        slen = 1;                                  slen = 4;
351                                                  break;                                  break;
352                            case '\0':
353                                    out[i] = 0;
354                                    return (out);
355                            default:
356                                    slen = 1;
357                                    break;
358                  }                  }
359    
360                  if (i + slen >= size)                  if (i + slen >= size)
361                  {                  {
362                          if (out == buf)                          if (out == buf)
363                          {                          {
364                                  out = (char*) palloc(size + ExtendBy);                                  out = (char *) palloc(size + ExtendBy);
365                                  strncpy(out, buf, i);                                  strncpy(out, buf, i);
366                                  size += ExtendBy;                                  size += ExtendBy;
367                          }                          }
368                          else                          else
369                          {                          {
370                                  out = (char*) repalloc(out, size + ExtendBy);                                  out = (char *) repalloc(out, size + ExtendBy);
371                                  size += ExtendBy;                                  size += ExtendBy;
372                          }                          }
373                  }                  }
# Line 314  OutputValue(char *key, char *buf, int si Line 382  OutputValue(char *key, char *buf, int si
382                  key++;                  key++;
383          }          }
384    
385          return(out);          return (out);
386    
387  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26