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