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