]> andersk Git - moira.git/blob - server/qrtn.dc
d3043948794098a4b13834b138ca2fa54df0d215
[moira.git] / server / qrtn.dc
1 /*
2  *      $Source$
3  *      $Author$
4  *      $Header$
5  *
6  *      Copyright (C) 1987, 1988 by the Massachusetts Institute of Technology
7  *      For copying and distribution information, please see the file
8  *      <mit-copyright.h>.
9  * 
10  */
11
12 #ifndef lint
13 static char *rcsid_qrtn_dc = "$Header$";
14 #endif lint
15
16 #include <mit-copyright.h>
17 #include "query.h"
18 #include "mr_server.h"
19 EXEC SQL INCLUDE sqlca;  /* SQL Communications Area */
20 EXEC SQL INCLUDE sqlda;  /* SQL Descriptor Area */
21 #include "qrtn.h"
22
23 MR_SQLDA_T *SQLDA;
24 EXEC SQL BEGIN DECLARE SECTION; 
25 int idummy;                            
26 char cdummy[MR_CDUMMY_LEN];            
27 char stmt_buf[MR_STMTBUF_LEN];
28 EXEC SQL END DECLARE SECTION; 
29
30 char *Argv[16];
31
32 int ingres_errno = 0;
33 int mr_errcode = 0;
34 EXEC SQL BEGIN DECLARE SECTION; 
35 int query_timeout = 30;
36 EXEC SQL END DECLARE SECTION;
37 extern char *whoami;
38 extern FILE *journal;
39
40 /** Maybe this should be replaced by something like tytso's sql_error */
41
42 #define INGRES_BAD_DATE1 41206
43 #define INGRES_BAD_DATE2 40207
44 #define INGRES_DEADLOCK 49900
45 /*
46 #define INGRES_BAD_INT 
47 #define INGRES_TIMEOUT 
48 #define INGRES_NO_RANGE 
49  */
50
51
52 /*
53  * ingerr: (supposedly) called when Ingres indicates an error.
54  * I have not yet been able to get this to work to intercept a
55  * database open error.
56  */
57
58 void ingerr()
59 {
60     ingres_errno = -sqlca.sqlcode;
61
62     switch (ingres_errno) {
63 /*
64  *  case INGRES_BAD_INT:
65  *      mr_errcode = MR_INTEGER;
66  *      break;
67  */
68     case INGRES_BAD_DATE1:
69     case INGRES_BAD_DATE2:
70         mr_errcode = MR_DATE;
71         break;
72     case INGRES_DEADLOCK:
73         mr_errcode = MR_DEADLOCK;
74         com_err(whoami, 0, "INGRES deadlock detected");
75         break;
76 /*  I just don't know what the equivalent to this is, yet.
77  *  case INGRES_TIMEOUT:
78  *      mr_errcode = MR_BUSY;
79  *      com_err(whoami, 0, "timed out getting lock");
80  *      break;
81  */
82 /*  This probably has no equivalent.
83  *  case INGRES_NO_RANGE:
84  *      mr_errcode = MR_INGRES_SOFTFAIL;
85  *      com_err(whoami, 0, "INGRES missing range statement");
86  *      break;
87  */
88     default:
89         /** Add the INGRES error_text to the alert message ??? **/
90         mr_errcode = MR_INGRES_ERR;
91         com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
92         critical_alert("MOIRA", "Moira server encountered INGRES ERROR %d", ingres_errno);
93     }
94 }
95
96 /* This is declarative, not executed.  Applies from here on, in the file */
97 EXEC SQL WHENEVER SQLERROR CALL ingerr;
98
99 int mr_open_database()
100 {
101     register int i;
102     char *malloc();
103     MR_SQLDA_T *mr_alloc_SQLDA();
104     static first_open = 1;
105
106     if (first_open) {
107         first_open = 0;
108
109         /* initialize local argv */
110         for (i = 0; i < 16; i++)
111           Argv[i] = malloc(ARGLEN);
112
113         SQLDA = mr_alloc_SQLDA();       
114
115         incremental_init();
116         flush_cache();
117     }
118         
119     ingres_errno = 0;
120     mr_errcode = 0;
121
122     /* open the database */
123 #ifsql INGRES
124     EXEC SQL CONNECT moira;
125     EXEC SQL set lockmode session where level = table, timeout = :query_timeout;
126     EXEC SQL set lockmode on capacls where readlock = shared;
127     EXEC SQL set lockmode on alias where readlock = shared;
128 #endsql
129 #ifsql INFORMIX
130     EXEC SQL DATABASE moira
131 #endsql
132     return ingres_errno;
133 }
134
135 int mr_close_database()
136 {
137     flush_cache();
138 #ifsql INGRES
139     EXEC SQL DISCONNECT;
140 #endsql
141 }
142
143 mr_check_access(cl, name, argc, argv_ro)
144     client *cl;
145     char *name;
146     int argc;
147     char *argv_ro[];
148 {
149     struct query *q;
150     struct query *get_query_by_name();
151
152     ingres_errno = 0;
153     mr_errcode = 0;
154
155     q = get_query_by_name(name, cl->args->mr_version_no);
156     if (q == (struct query *)0)
157         return(MR_NO_HANDLE);
158
159     return(mr_verify_query(cl, q, argc, argv_ro));    
160 }
161
162 mr_process_query(cl, name, argc, argv_ro, action, actarg)
163     client *cl;
164     char *name;
165     int argc;
166     char *argv_ro[];
167     int (*action)();
168     char *actarg;
169 {
170     register struct query *q;
171     register int status;
172     register struct validate *v;
173     char qual[256];
174     char sort[32];
175     char *pqual;
176     char *psort;
177     EXEC SQL BEGIN DECLARE SECTION; 
178     char *table_name;
179     EXEC SQL END DECLARE SECTION; 
180     struct save_queue *sq;
181     struct query *get_query_by_name();
182     int sq_save_args();
183     struct save_queue *sq_create();
184     char *build_sort();
185
186     ingres_errno = 0;
187     mr_errcode = 0;
188
189     /* list queries command */
190     if (!strcmp(name, "_list_queries")) {
191         list_queries(cl->args->mr_version_no, action, actarg);
192         return(MR_SUCCESS);
193     }
194
195     /* help query command */
196     if (!strcmp(name, "_help")) {
197         if (argc < 1)
198             return(MR_ARGS);
199         q = get_query_by_name(argv_ro[0], cl->args->mr_version_no);
200         if (q == (struct query *)0) return(MR_NO_HANDLE);
201         help_query(q, action, actarg);
202         return(MR_SUCCESS);
203     }
204
205     /* get query structure, return error if named query does not exist */
206     q = get_query_by_name(name, cl->args->mr_version_no);
207     if (q == (struct query *)0) return(MR_NO_HANDLE);
208     v = q->validate;
209
210     /* setup argument vector, verify access and arguments */
211     if ((status = mr_verify_query(cl, q, argc, argv_ro)) != MR_SUCCESS)
212         goto out;
213
214     /* perform any special query pre-processing */
215     if (v && v->pre_rtn) {
216         status = (*v->pre_rtn)(q, Argv, cl, 0);
217         if (status != MR_SUCCESS)
218             goto out;
219     }
220
221     switch (q->type) {
222     case RETRIEVE:
223         /* for queries that do not permit wildcarding, check if row
224            uniquely exists */
225         if (v && v->field) {
226             status = validate_row(q, Argv, v); 
227             if (status != MR_EXISTS) break;
228         }
229
230         /* build "where" clause if needed */
231         if (q->qual) {
232             build_qual(q->qual, q->argc, Argv, qual); 
233             pqual = qual;
234         } else {
235             pqual = 0;
236         }
237
238         /* build "sort" clause if needed */
239         if (v && v->valobj) {
240             psort = build_sort(v, sort);
241         } else {
242             psort = 0;
243         }
244
245         /* if there is a followup routine, then we must save the results */
246         /* of the first query for use by the followup routine */
247         /* if q->rvar = NULL, perform post_rtn only */
248         if (q->rvar) {
249             if (v && v->post_rtn) {
250                 sq = sq_create();
251                 status = do_retrieve(q, pqual, psort, sq_save_args, sq);
252                 if (status != MR_SUCCESS) {
253                     sq_destroy(sq);
254                     break;
255                 }
256                 status = (*v->post_rtn)(q, sq, v, action, actarg, cl);
257             } else {
258                 /* normal retrieve */
259                 status = do_retrieve(q, pqual, psort, action, actarg);
260             }
261             if (status != MR_SUCCESS) break;
262         } else {
263             status = (*v->post_rtn)(q, Argv, cl, action, actarg);
264         }
265
266         break;
267
268     case UPDATE:
269         /* see if row already exists */
270         if (v->field) {
271             status = validate_row(q, Argv, v);
272             if (status != MR_EXISTS) break;
273         }
274
275         /* build "where" clause and perform update */
276         /* if q->rvar = NULL, perform post_rtn only */
277         if (q->rvar) {
278             build_qual(q->qual, q->argc, Argv, qual);
279             incremental_before(q->rtable, qual, argv_ro);
280             status = do_update(q, &Argv[q->argc], qual, action, actarg);
281             incremental_after(q->rtable, qual, argv_ro);
282             if (status != MR_SUCCESS) break;
283             flush_name(argv_ro[0], q->rtable);
284             table_name = q->rtable;
285             if (strcmp(q->shortname, "sshi") && strcmp(q->shortname, "ssif")) {
286                 EXEC SQL UPDATE tblstats
287                   SET updates = updates + 1, modtime = 'now'
288                   WHERE table_name = :table_name;
289             }
290         }
291
292         /* execute followup routine (if any) */
293         if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
294
295         break;
296
297     case APPEND:
298         /* see if row already exists */
299         if (v->field) {
300             status = validate_row(q, Argv, v);
301             if (status != MR_NO_MATCH) break;
302         }
303
304         /* increment id number if necessary */
305         if (v->object_id) {
306             status = set_next_object_id(v->object_id, q->rtable, 0);
307             if (status != MR_SUCCESS) break;
308         }
309
310         /* build "where" clause if needed */
311         if (q->qual) {
312             build_qual(q->qual, q->argc, Argv, qual);
313             pqual = qual;
314         } else {
315             pqual = 0;
316         }
317
318         /* perform the append */
319         /* if q->rvar = NULL, perform post_rtn only */
320         if (q->rvar) {
321             incremental_clear_before();
322             status = do_append(q, &Argv[q->argc], pqual, action, actarg);
323             if (status != MR_SUCCESS) break;
324             if (v && v->object_id) {
325                 sprintf(qual, "%s.%s = values.value and values.name = '%s'",
326                         q->rtable, v->object_id, v->object_id);
327                 incremental_after(q->rtable, qual, argv_ro);
328             } else
329               incremental_after(q->rtable, pqual, argv_ro);
330
331             table_name = q->rtable;
332             EXEC SQL UPDATE tblstats
333               SET appends = appends + 1, modtime = 'now'
334               WHERE table_name = :table_name;
335         }
336         
337         /* execute followup routine */
338         if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
339         break;
340
341     case DELETE:
342         /* see if row already exists */
343         if (v->field) {
344             status = validate_row(q, Argv, v);
345             if (status != MR_EXISTS) break;
346         }
347
348         /* build "where" clause and perform delete */
349         /* if q->rvar = NULL, perform post_rtn only */
350         if (q->rvar) {
351             build_qual(q->qual, q->argc, Argv, qual);
352             table_name = q->rtable;
353             incremental_before(q->rtable, qual, argv_ro);
354             status = do_delete(q, qual, action, actarg);
355             incremental_clear_after();
356             if (status != MR_SUCCESS) break;
357             flush_name(argv_ro[0], q->rtable);
358             EXEC SQL UPDATE tblstats
359               SET deletes = deletes + 1, modtime = 'now'
360               WHERE table_name = :table_name;
361         }
362
363         /* execute followup routine */
364         if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
365         break;
366
367     }
368
369 out:
370     if (status == MR_SUCCESS && ingres_errno != 0) {
371         com_err(whoami, MR_INTERNAL, "Server didn't notice INGRES ERROR %d",
372                        ingres_errno);
373         status = mr_errcode;
374     }
375
376     if (q->type == RETRIEVE) {
377         EXEC SQL COMMIT WORK;
378     } else {
379         if (status == MR_SUCCESS) {
380         EXEC SQL COMMIT WORK;
381             if (journal) {
382                 char buf[1024], *bp;
383                 int i;
384                 extern time_t now;
385
386                 fprintf(journal, "%% %s %s %s",
387                         cl->clname, cl->entity, ctime(&now));
388                 fprintf(journal, "%s[%d] ", q->name, cl->args->mr_version_no);
389                 for (i = 0; i < argc; i++) {
390                     if (i != 0) {
391                         putc(' ', journal);
392                     }
393                     requote(buf, argv_ro[i], sizeof(buf));
394                     fputs(buf, journal);
395                 }
396                 putc('\n', journal);
397                 fflush(journal);
398             }
399             incremental_update();
400         } else {
401             cache_abort();
402             if (ingres_errno != INGRES_DEADLOCK) {
403                 EXEC SQL ROLLBACK WORK;
404             }
405             incremental_flush();
406         }
407     }
408     cache_commit(); /* commit following abort is safe */
409
410     if (status != MR_SUCCESS && log_flags & LOG_RES)
411         com_err(whoami, status, " (Query failed)");
412     return(status);
413 }
414
415 build_qual(fmt, argc, argv, qual)
416         char *fmt;
417         int argc;
418         char *argv[];
419         char *qual;
420 {
421     register char *c;
422     register int i;
423     char *args[4];
424     char *index();
425
426     c = fmt;
427     for (i = 0; i < argc; i++) {
428         c = index(c, '%');
429         if (c++ == (char *)0) return(MR_ARGS);
430         if (*c == 's')
431             args[i] = argv[i];
432         else if (*c == 'd')
433             *(int *)&args[i] = *(int *)argv[i]; /* sigh */
434         else
435             return(MR_INGRES_ERR);
436     }
437     if (c = index(c, '%')) {
438         args[i] = args[i - 1];
439     }
440
441     switch (argc) {
442     case 0:
443         strcpy(qual, fmt);
444         break;
445
446     case 1:
447         sprintf(qual, fmt, args[0]);
448         break;
449
450     case 2:
451         sprintf(qual, fmt, args[0], args[1]);
452         break;
453
454     case 3:
455         sprintf(qual, fmt, args[0], args[1], args[2]);
456         break;
457
458     case 4:
459         sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
460         break;
461
462     default:
463         com_err(whoami, MR_INTERNAL,
464                 "Internal arg count error processing query");
465         return(MR_INTERNAL);
466     }
467     return(MR_SUCCESS);
468 }
469
470 char *
471 build_sort(v, sort)
472     register struct validate *v;
473     char *sort;
474 {
475     register struct valobj *vo;
476     register int n;
477     char elem[16];
478
479     n = v->objcnt;
480     vo = v->valobj;
481     *sort = 0;
482
483     while (--n >= 0) {
484         if (vo->type == V_SORT) {
485             sprintf(elem, "%d", vo->index + 1);    /* Result column number */
486             if (*sort) strcat(sort, ", ");
487             strcat(sort, elem);
488         }
489         vo++;
490     }
491
492     return ((*sort) ? sort : 0);
493 }
494
495
496 /* Build arguement vector, verify query and arguments */
497
498 mr_verify_query(cl, q, argc, argv_ro)
499     client *cl;
500     struct query *q;
501     int argc;
502     char *argv_ro[];
503 {
504     register int argreq;
505     register int status;
506     register struct validate *v = q->validate;
507     register int i;
508     register int privileged = 0;
509     int len;
510
511     /* copy the arguments into a local argv that we can modify */
512     if (argc >= QMAXARGS)
513       return(MR_ARGS);
514     for (i = 0; i < argc; i++) {
515         if ((len = strlen(argv_ro[i])) < ARGLEN)
516             strcpy(Argv[i], argv_ro[i]);
517         else
518             return(MR_ARG_TOO_LONG);
519         if (Argv[i][len-1] == '\\')
520           return(MR_BAD_CHAR);
521     }
522
523     /* check initial query access */
524     status = check_query_access(q, Argv, cl);
525     if (status != MR_SUCCESS && status != MR_PERM)
526         return(status);
527     if (status == MR_SUCCESS)
528         privileged++;
529
530     /* check argument count */
531     argreq = q->argc;
532     if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
533     if (argc != argreq) return(MR_ARGS);
534
535     /* validate arguments */
536     if (v && v->valobj) {
537         status = validate_fields(q, Argv, v->valobj, v->objcnt);
538         if (status != MR_SUCCESS) return(status);
539     }
540
541     /* perform special query access check */
542     if (!privileged && v && v->acs_rtn) {
543         status = (*v->acs_rtn)(q, Argv, cl);
544         if (status != MR_SUCCESS && status != MR_PERM)
545             return(status);
546         if (status == MR_SUCCESS)
547             privileged++;
548     }
549
550     return(privileged ? MR_SUCCESS : MR_PERM);
551 }
552
553
554 /* This routine caches info from the database.  Each query acl is stored
555  * in the query structure, and whether that acl contains everybody.
556  */
557
558 check_query_access(q, argv, cl)
559     struct query *q;
560     char *argv[];
561     client *cl;
562 {
563     EXEC SQL BEGIN DECLARE SECTION; 
564     char *name;
565     int acl_id;
566     int rowcount;
567     int errorno;
568     static int def_uid;
569     EXEC SQL END DECLARE SECTION; 
570     int status;
571     int client_id;
572     char *client_type;
573
574     /* initialize default uid */
575     if (def_uid == 0) {
576         EXEC SQL SELECT users_id INTO :def_uid FROM users WHERE login='default';
577     }
578
579     /* get query access control list */
580     if (q->acl != 0)
581       acl_id = q->acl;
582     else {
583         name = q->shortname;
584         EXEC SQL SELECT list_id INTO :acl_id FROM capacls WHERE tag = :name;
585         if (sqlca.sqlcode < 0) return(MR_INGRES_ERR);
586         if (sqlca.sqlcode == 100) return(MR_PERM);
587         q->acl = acl_id;
588
589         /* check for default access */
590         EXEC SQL SELECT member_id INTO :acl_id FROM imembers
591           WHERE list_id = :acl_id AND member_type = 'USER' 
592             AND member_id = :def_uid;
593         if (sqlca.sqlerrd[2] == 0)
594           q->everybody = 0;
595         else
596           q->everybody = 1;
597     }
598
599     if (q->everybody)
600       return(MR_SUCCESS);
601
602     if (get_client(cl, &client_type, &client_id) != MR_SUCCESS)
603       return(MR_PERM);
604     if (find_member("LIST", acl_id, client_type, client_id, 0))
605       return(MR_SUCCESS);
606     else
607       return(MR_PERM);
608 }
609
610
611 get_client(cl, client_type, client_id)
612     client *cl;
613     char **client_type;
614     int *client_id;
615 {
616     if (cl->users_id > 0) {
617         *client_id = cl->users_id;
618         *client_type = "USER";
619         return(MR_SUCCESS);
620     }
621
622     if (cl->client_id < 0) {
623         *client_id = -cl->users_id;
624         *client_type = "KERBEROS";
625         return(MR_SUCCESS);
626     }
627
628     return(MR_PERM);
629 }
630
631 find_member(list_type, list_id, member_type, member_id)
632     char *list_type;
633     EXEC SQL BEGIN DECLARE SECTION; 
634     int list_id;
635     char *member_type;
636     int member_id;
637     EXEC SQL END DECLARE SECTION;
638 {
639     EXEC SQL BEGIN DECLARE SECTION; 
640     int flag, errorno;
641     EXEC SQL END DECLARE SECTION; 
642
643     if (!strcmp(strtrim(list_type), strtrim(member_type)) &&
644         list_id == member_id)
645         return(1);
646
647     /* see if client is a direct member of list */
648     flag = 0;
649     EXEC SQL SELECT member_id INTO :flag FROM imembers
650       WHERE list_id = :list_id AND member_type = :member_type 
651         AND member_id = :member_id;
652     if(flag!=0) flag=1;             /** Not strictly necessary */
653     if (sqlca.sqlcode == 0)
654       return(flag);            
655     return(0);
656 }
657
658
659 do_retrieve(q, pqual, psort, action, actarg)            
660     register struct query *q;
661 EXEC SQL BEGIN DECLARE SECTION; 
662     char *pqual;
663     char *psort;
664 EXEC SQL END DECLARE SECTION; 
665     int (*action)();
666     char *actarg;
667 {
668     static char **vaddrs = (char **)NULL;
669     int j, rowcount;
670
671     if (!vaddrs) {
672         register int i;
673
674         if ((vaddrs = (char **)malloc(sizeof(char *) * QMAXARGS)) == NULL) {
675             com_err(whoami, MR_NO_MEM, "setting up static argv");
676             exit(1);
677         }
678         for (i = 0; i < QMAXARGS; i++) {
679             vaddrs[i]=SQLDA->sqlvar[i].sqldata;
680         }
681     }
682
683 /*
684  *  if (psort) {
685  *      csort = psort;
686  *      if (pqual) {
687  *          cqual = pqual;
688  *          retrieve unique (param (q->tlist, vaddrs)) where cqual
689  *                   sort by csort
690  *          {
691  *               (*action)(q->vcnt, vaddrs, actarg);
692  *          }
693  *      } else {
694  *          retrieve unique (param (q->tlist, vaddrs))
695  *                   sort by csort
696  *          {
697  *               (*action)(q->vcnt, vaddrs, actarg);
698  *          }
699  *      }
700  *  
701  *  } else {
702  *      if (pqual) {
703  *          cqual = pqual;
704  *          retrieve unique (param (q->tlist, vaddrs)) where cqual
705  *          {
706  *               (*action)(q->vcnt, vaddrs, actarg);
707  *          }
708  *      } else {
709  *          retrieve unique (param (q->tlist, vaddrs))
710  *          {
711  *               (*action)(q->vcnt, vaddrs, actarg);
712  *          }
713  *      }
714  *  }
715  */
716
717     build_sql_stmt(stmt_buf,"SELECT",q->tlist,vaddrs,pqual);
718     if(psort) { strcat(stmt_buf," ORDER BY "); strcat(stmt_buf,psort); }
719     EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf; 
720     if((mr_errcode=mr_check_SQLDA(SQLDA)) != MR_SUCCESS) 
721       return(mr_errcode);
722     EXEC SQL DECLARE csr001 CURSOR FOR stmt;
723     EXEC SQL OPEN csr001;
724     rowcount = 0;
725     while(1) {
726         EXEC SQL FETCH csr001 USING DESCRIPTOR :SQLDA;
727         if(sqlca.sqlcode != 0) break;
728         mr_fix_nulls_in_SQLDA(SQLDA);
729         (*action)(q->vcnt, vaddrs, actarg);
730         rowcount++;
731     }
732     EXEC SQL CLOSE csr001;
733
734     if (mr_errcode) return(mr_errcode);
735     return ((rowcount == 0) ? MR_NO_MATCH : MR_SUCCESS);
736 }
737
738 build_sql_stmt(result_buf,cmd,targetlist,argv,qual)
739     char *result_buf;
740     char *cmd;
741     char *targetlist;
742     char *argv[];
743     char *qual;
744 {
745     char fmt_buf[MR_STMTBUF_LEN];
746     char tmp_buf[16];
747     char *res=result_buf, *tmp=tmp_buf, *fmt=fmt_buf;
748     int state;
749
750     sprintf(fmt_buf,"%s %s",cmd,targetlist);
751     if(qual) { strcat(fmt_buf," WHERE "); strcat(fmt_buf,qual); }
752
753     for(state=0;*fmt != '\0';fmt++) {
754         switch(state) {
755           case 0:
756             if(*fmt=='%') {                          /* formatting -> tmp */
757                 *tmp++ = *fmt;
758                 state=1;
759             } else *res++ = *fmt;                      /* text -> res */
760             break;
761           case 1:
762             if((*fmt=='%') && (tmp==tmp_buf+1)) {    /* %% -> % */
763                 *res++ = *fmt;           
764                 tmp=tmp_buf;
765                 state=0;
766             } else if(isalpha(*fmt) && (*fmt!='h') && (*fmt!='l')) {  /* end of formatting */
767                 *tmp++ = *fmt;
768                 *tmp='\0';
769                 tmp=tmp_buf;
770                 sprintf(res,tmp_buf,*argv++);        /* print to result buffer */
771                 while(*res++) ;
772                 state=0;
773             } else *tmp++ = *fmt;    /* keep copying the formatting to tmp */
774             break;
775         }
776     }
777     *res='\0';
778 }
779
780 do_update(q, argv, qual, action, actarg)
781     register struct query *q;
782     char *argv[];
783     char *qual;
784     int (*action)();
785     char *actarg;
786 {
787     build_sql_stmt(stmt_buf,"UPDATE",q->tlist,argv,qual);
788     EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
789     if (mr_errcode) return(mr_errcode);
790     return(MR_SUCCESS);
791 }
792
793 do_append(q, argv, pqual, action, actarg)
794     register struct query *q;
795     char *argv[];
796     char *pqual;
797     int (*action)();
798     char *actarg;
799 {
800     build_sql_stmt(stmt_buf,"INSERT",q->tlist,argv,pqual);
801     EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
802     if (mr_errcode) return(mr_errcode);
803     return(MR_SUCCESS);
804 }
805
806 do_delete(q, qual, action, actarg)
807     register struct query *q;
808     char *qual;
809     int (*action)();
810     char *actarg;
811 {
812     sprintf(stmt_buf,"DELETE FROM %s WHERE %s",q->rtable,qual);
813     EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
814     if (mr_errcode) return(mr_errcode);
815     return(MR_SUCCESS);
816 }
817
818
819 /**
820  ** set_next_object_id - set next object id in values table
821  **
822  ** Inputs: object - object name in values table and in objects
823  **         table - name of table objects are found in
824  **         limit - should the ID be range limited
825  **
826  ** - called before an APPEND operation to set the next object id to
827  **   be used for the new record to the next free value
828  **
829  **/
830
831 set_next_object_id(object, table_name, limit)
832     EXEC SQL BEGIN DECLARE SECTION; 
833     char *object;
834     char *table_name;
835     int limit;
836     EXEC SQL END DECLARE SECTION; 
837 {
838     EXEC SQL BEGIN DECLARE SECTION; 
839     int value;
840     EXEC SQL END DECLARE SECTION;
841     int rowcount=0;
842
843     EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :object;
844     if (sqlca.sqlerrd[2] != 1)
845         return(MR_NO_ID);
846
847 /*
848  *  retrieve (exists = any(tbl.name where tbl.name = value)) 
849  */
850     sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s=:value",object,table_name,object);  /** Will this work??? */
851     EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf; 
852     EXEC SQL DECLARE csr002 CURSOR FOR stmt;
853
854     EXEC SQL OPEN csr002;
855     EXEC SQL FETCH csr002 USING DESCRIPTOR :SQLDA; 
856     if(sqlca.sqlcode == 0) {
857         rowcount++;
858         EXEC SQL FETCH csr002 USING DESCRIPTOR :SQLDA; 
859         if(sqlca.sqlcode == 0) rowcount++;
860     }
861     EXEC SQL CLOSE csr002;
862
863     if (rowcount != 1)
864       return(MR_NO_ID);
865     while (1) { 
866         value++;
867         if (limit && value > MAX_ID_VALUE)      /* Potential infinite loop */
868           value = MIN_ID_VALUE;
869 /*
870  *      retrieve (exists = any(tbl.name where tbl.name = value)) 
871  */
872         
873         /** Does the following work like I think it should ??? */
874         EXEC SQL OPEN csr002;
875         EXEC SQL FETCH csr002 USING DESCRIPTOR :SQLDA; 
876         if(sqlca.sqlcode == 100) break;
877         EXEC SQL CLOSE csr002;
878     }
879     EXEC SQL CLOSE csr002;
880
881     if (LOG_RES)
882         com_err(whoami, 0, "setting ID %s to %d", object, value);
883     EXEC SQL UPDATE numvalues SET value = :value WHERE name = :object;
884     return(MR_SUCCESS);
885 }
886
887
888 /* Turn a kerberos name into the user's ID of the account that principal
889  * owns.  Sets the kerberos ID and user ID.
890  */
891
892 int set_krb_mapping(name, login, ok, kid, uid)
893 char *name;
894 char *login;
895 int ok;
896 int *kid;
897 int *uid;
898 {
899     EXEC SQL BEGIN DECLARE SECTION; 
900     int u_id, k_id;
901     char *krbname;
902     EXEC SQL END DECLARE SECTION; 
903
904     krbname = name;
905     *kid = 0;
906     *uid = 0;
907
908     EXEC SQL SELECT k.users_id, k.string_id INTO :u_id, :k_id
909       FROM krbmap k, strings s
910       WHERE k.string_id = s.string_id AND s.string = :krbname;
911
912     if (ingres_errno) return(mr_errcode);
913     
914     if (sqlca.sqlerrd[2] == 1) {    /* rowcount */
915         *kid = -k_id;
916         *uid = u_id;
917         return(MR_SUCCESS);
918     }
919
920     if (name_to_id(name, "STRINGS", &k_id) == MR_SUCCESS)
921       *kid = -k_id;
922
923     if (!ok) {             
924         *uid = *kid;
925         return(MR_SUCCESS);
926     }
927
928     if (name_to_id(login, "USERS", uid) != MR_SUCCESS)
929       *uid = 0;
930
931     if (*kid == 0)
932       *kid = *uid;
933     if (ingres_errno) return(mr_errcode);
934     return(MR_SUCCESS);
935 }
936
937
938 /* For now this just checks the argc's.  It should also see that there
939  * are no duplicate names.
940  */
941
942 sanity_check_queries()
943 {
944     register int i;
945     int maxv = 0, maxa = 0;
946 #ifdef MULTIPROTOCOLS
947     extern int QueryCount1, QueryCount2;
948     extern struct query Queries1[], Queries2[];
949 #else
950     extern int QueryCount2;
951     extern struct query Queries2[];
952 #endif MULTIPROTOCOLS
953
954 #define MAX(x,y) ((x) > (y) ? (x) : (y))
955
956 #ifdef MULTIPROTOCOLS
957     for (i = 0; i < QueryCount1; i++) {
958         maxv = MAX(maxv, Queries1[i].vcnt);
959         maxa = MAX(maxa, Queries1[i].argc);
960     }
961 #endif MULTIPROTOCOLS
962     for (i = 0; i < QueryCount2; i++) {
963         maxv = MAX(maxv, Queries2[i].vcnt);
964         maxa = MAX(maxa, Queries2[i].argc);
965     }
966     if (MAX(maxv, maxa) > QMAXARGS) {
967         com_err(whoami, 0, "A query has more args than QMAXARGS");
968         exit(1);
969     }
970 }
971
972 /* eof:qrtn.dc */
This page took 0.108829 seconds and 3 git commands to generate.