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