]> andersk Git - moira.git/blame - server/qrtn.dc
added addusr
[moira.git] / server / qrtn.dc
CommitLineData
1a41acb7 1/*
2 * $Source$
3 * $Author$
4 * $Header$
b070f8a1 5 *
1a41acb7 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 *
b070f8a1 10 */
11
12#ifndef lint
048b1b94 13static char *rcsid_qrtn_dc = "$Header$";
b070f8a1 14#endif lint
15
16#include <mit-copyright.h>
17#include "query.h"
18#include "mr_server.h"
048b1b94 19EXEC SQL INCLUDE sqlca; /* SQL Communications Area */
20EXEC SQL INCLUDE sqlda; /* SQL Descriptor Area */
21#include "qrtn.h"
22
23MR_SQLDA_T _SQLDA;
24MR_SQLDA_T *SQLDA=&_SQLDA;
25EXEC SQL BEGIN DECLARE SECTION;
26int idummy;
27char cdummy[MR_CDUMMY_LEN];
28char stmt_buf[MR_STMTBUF_LEN];
29EXEC SQL END DECLARE SECTION;
b070f8a1 30
31char *Argv[16];
32
33int ingres_errno = 0;
34int mr_errcode = 0;
048b1b94 35EXEC SQL BEGIN DECLARE SECTION;
36int query_timeout = 30;
37EXEC SQL END DECLARE SECTION;
b070f8a1 38extern char *whoami;
39extern FILE *journal;
40
048b1b94 41/** Maybe this should be replaced by something like tytso's sql_error
42
43#define INGRES_BAD_DATE1 41206
44#define INGRES_BAD_DATE2 40207
45#define INGRES_DEADLOCK 49900
46/*
47#define INGRES_BAD_INT
48#define INGRES_TIMEOUT
49#define INGRES_NO_RANGE
50 */
b070f8a1 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
048b1b94 58static int ingerr()
b070f8a1 59{
048b1b94 60 ingres_errno = -sqlca.sqlcode;
b070f8a1 61
048b1b94 62 switch (ingres_errno) {
63/*
b070f8a1 64 case INGRES_BAD_INT:
65 mr_errcode = MR_INTEGER;
66 break;
048b1b94 67 */
68 case INGRES_BAD_DATE1:
69 case INGRES_BAD_DATE2:
b070f8a1 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;
048b1b94 76/* I just don't know what the equivalent to this is, yet.
b070f8a1 77 case INGRES_TIMEOUT:
78 mr_errcode = MR_BUSY;
79 com_err(whoami, 0, "timed out getting lock");
80 break;
048b1b94 81 */
82/* This probably has no equivalent.
b070f8a1 83 case INGRES_NO_RANGE:
84 mr_errcode = MR_INGRES_SOFTFAIL;
85 com_err(whoami, 0, "INGRES missing range statement");
86 break;
048b1b94 87 */
b070f8a1 88 default:
048b1b94 89 /** Add the INGRES error_text to the alert message ??? **/
b070f8a1 90 mr_errcode = MR_INGRES_ERR;
1a41acb7 91 com_err(whoami, MR_INGRES_ERR, " code %d\n", *num);
92 critical_alert("MOIRA", "Moira server encountered INGRES ERROR %d", *num);
93 return (*num);
b070f8a1 94 }
95 return (0);
96}
97
048b1b94 98/* This is declarative, not executed. Moved to emphasize the fact. */
99EXEC SQL WHENEVER SQLERROR CALL ingerr;
100
b070f8a1 101int mr_open_database()
102{
103 register int i;
104 char *malloc();
105 static first_open = 1;
106
107 if (first_open) {
108 first_open = 0;
109
110 /* initialize local argv */
111 for (i = 0; i < 16; i++)
112 Argv[i] = malloc(ARGLEN);
113
048b1b94 114 /* EXEC SQL WHENEVER SQLERROR CALL ingerr; */
b070f8a1 115 incremental_init();
116 flush_cache();
117 }
118
119 ingres_errno = 0;
120 mr_errcode = 0;
121
122 /* open the database */
048b1b94 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
b070f8a1 132 return ingres_errno;
133}
134
135int mr_close_database()
136{
137 flush_cache();
048b1b94 138#ifsql INGRES
139 EXEC SQL DISCONNECT;
140#endsql
b070f8a1 141}
142
143mr_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
048b1b94 159 return(mr_verify_query(cl, q, argc, argv_ro));
b070f8a1 160}
161
162mr_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;
048b1b94 177 EXEC SQL BEGIN DECLARE SECTION;
178 char *table_name;
179 EXEC SQL END DECLARE SECTION;
b070f8a1 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) {
048b1b94 226 status = validate_row(q, Argv, v);
b070f8a1 227 if (status != MR_EXISTS) break;
228 }
229
230 /* build "where" clause if needed */
231 if (q->qual) {
048b1b94 232 build_qual(q->qual, q->argc, Argv, qual);
b070f8a1 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);
048b1b94 284 table_name = q->rtable;
b070f8a1 285 if (strcmp(q->shortname, "sshi") && strcmp(q->shortname, "ssif")) {
048b1b94 286 EXEC SQL UPDATE tblstats
287 SET updates = updates + 1, modtime = 'now'
288 WHERE table_name = :table_name;
b070f8a1 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) {
1a41acb7 306 status = set_next_object_id(v->object_id, q->rtable, 0);
b070f8a1 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) {
048b1b94 325 sprintf(qual, "%s.%s = values.value and values.name = '%s',
326 q->rtable, v->object_id, v->object_id);
b070f8a1 327 incremental_after(q->rtable, qual, argv_ro);
328 } else
329 incremental_after(q->rtable, pqual, argv_ro);
330
048b1b94 331 table_name = q->rtable;
332 EXEC SQL UPDATE tblstats
333 SET appends = appends + 1, modtime = 'now'
334 WHERE table_name = :table_name;
b070f8a1 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);
048b1b94 352 table_name = q->rtable;
353 incremental_before(q->rtable, qual, argv_ro);
b070f8a1 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);
048b1b94 358 EXEC SQL UPDATE tblstats
359 SET deletes = deletes + 1, modtime = 'now'
360 WHERE table_name = :table_name;
b070f8a1 361 }
362
363 /* execute followup routine */
364 if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
365 break;
366
367 }
368
369out:
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
048b1b94 376 if (q->type == RETRIEVE) {
377#ifsql INGRES
378 EXEC SQL END TRANSACTION;
379#endsql
380#ifsql INFORMIX
381 EXEC SQL COMMIT WORK;
382#endsql
383 } else {
b070f8a1 384 if (status == MR_SUCCESS) {
048b1b94 385#ifsql INGRES
386 EXEC SQL END TRANSACTION;
387#endsql
388#ifsql INFORMIX
389 EXEC SQL COMMIT WORK;
390#endsql
b070f8a1 391 if (journal) {
392 char buf[1024], *bp;
393 int i;
394 extern time_t now;
395
396 fprintf(journal, "%% %s %s %s",
397 cl->clname, cl->entity, ctime(&now));
398 fprintf(journal, "%s[%d] ", q->name, cl->args->mr_version_no);
399 for (i = 0; i < argc; i++) {
400 if (i != 0) {
401 putc(' ', journal);
402 }
403 requote(buf, argv_ro[i], sizeof(buf));
404 fputs(buf, journal);
405 }
406 putc('\n', journal);
407 fflush(journal);
408 }
409 incremental_update();
410 } else {
1a41acb7 411 cache_abort();
b070f8a1 412 if (ingres_errno != INGRES_DEADLOCK) {
048b1b94 413#ifsql INGRES
414 EXEC SQL ABORT;
415#endsql
416#ifsql INFORMIX
417 EXEC SQL ROLLBACK WORK;
418#endsql
b070f8a1 419 }
420 incremental_flush();
421 }
422 }
1a41acb7 423 cache_commit(); /* commit following abort is safe */
b070f8a1 424
425 if (status != MR_SUCCESS && log_flags & LOG_RES)
426 com_err(whoami, status, " (Query failed)");
427 return(status);
428}
429
430build_qual(fmt, argc, argv, qual)
431 char *fmt;
432 int argc;
433 char *argv[];
434 char *qual;
435{
436 register char *c;
437 register int i;
438 char *args[4];
439 char *index();
440
441 c = fmt;
442 for (i = 0; i < argc; i++) {
443 c = index(c, '%');
444 if (c++ == (char *)0) return(MR_ARGS);
445 if (*c == 's')
446 args[i] = argv[i];
447 else if (*c == 'd')
448 *(int *)&args[i] = *(int *)argv[i]; /* sigh */
449 else
450 return(MR_INGRES_ERR);
451 }
1a41acb7 452 if (c = index(c, '%')) {
453 args[i] = args[i - 1];
454 }
b070f8a1 455
456 switch (argc) {
457 case 0:
458 strcpy(qual, fmt);
459 break;
460
461 case 1:
462 sprintf(qual, fmt, args[0]);
463 break;
464
465 case 2:
466 sprintf(qual, fmt, args[0], args[1]);
467 break;
468
469 case 3:
470 sprintf(qual, fmt, args[0], args[1], args[2]);
471 break;
472
473 case 4:
474 sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
475 break;
1a41acb7 476
477 default:
478 com_err(whoami, MR_INTERNAL,
479 "Internal arg count error processing query");
480 return(MR_INTERNAL);
b070f8a1 481 }
482 return(MR_SUCCESS);
483}
484
485char *
486build_sort(v, sort)
487 register struct validate *v;
488 char *sort;
489{
490 register struct valobj *vo;
491 register int n;
492 char elem[16];
493
494 n = v->objcnt;
495 vo = v->valobj;
496 *sort = 0;
497
498 while (--n >= 0) {
499 if (vo->type == V_SORT) {
048b1b94 500 sprintf(elem, "%d", vo->index + 1); /* Result column number */
b070f8a1 501 if (*sort) strcat(sort, ", ");
502 strcat(sort, elem);
503 }
504 vo++;
505 }
506
507 return ((*sort) ? sort : 0);
508}
509
510
511/* Build arguement vector, verify query and arguments */
512
513mr_verify_query(cl, q, argc, argv_ro)
514 client *cl;
515 struct query *q;
516 int argc;
517 char *argv_ro[];
518{
519 register int argreq;
520 register int status;
521 register struct validate *v = q->validate;
522 register int i;
523 register int privileged = 0;
524 int len;
525
526 /* copy the arguments into a local argv that we can modify */
527 if (argc >= QMAXARGS)
528 return(MR_ARGS);
529 for (i = 0; i < argc; i++) {
530 if ((len = strlen(argv_ro[i])) < ARGLEN)
531 strcpy(Argv[i], argv_ro[i]);
532 else
533 return(MR_ARG_TOO_LONG);
534 if (Argv[i][len-1] == '\\')
535 return(MR_BAD_CHAR);
536 }
537
538 /* check initial query access */
539 status = check_query_access(q, Argv, cl);
540 if (status != MR_SUCCESS && status != MR_PERM)
541 return(status);
542 if (status == MR_SUCCESS)
543 privileged++;
544
545 /* check argument count */
546 argreq = q->argc;
547 if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
548 if (argc != argreq) return(MR_ARGS);
549
550 /* validate arguments */
551 if (v && v->valobj) {
552 status = validate_fields(q, Argv, v->valobj, v->objcnt);
553 if (status != MR_SUCCESS) return(status);
554 }
555
556 /* perform special query access check */
557 if (!privileged && v && v->acs_rtn) {
558 status = (*v->acs_rtn)(q, Argv, cl);
559 if (status != MR_SUCCESS && status != MR_PERM)
560 return(status);
561 if (status == MR_SUCCESS)
562 privileged++;
563 }
564
565 return(privileged ? MR_SUCCESS : MR_PERM);
566}
567
568
569/* This routine caches info from the database. Each query acl is stored
570 * in the query structure, and whether that acl contains everybody.
571 */
572
573check_query_access(q, argv, cl)
574 struct query *q;
575 char *argv[];
576 client *cl;
048b1b94 577{
578 EXEC SQL BEGIN DECLARE SECTION;
579 char *name;
580 int acl_id;
581 int rowcount;
582 int errorno;
583 static int def_uid;
584 EXEC SQL END DECLARE SECTION;
b070f8a1 585 int status;
586 int client_id;
587 char *client_type;
588
589 /* initialize default uid */
590 if (def_uid == 0) {
048b1b94 591 EXEC SQL SELECT users_id INTO :def_uid FROM users WHERE login='default';
b070f8a1 592 }
593
594 /* get query access control list */
595 if (q->acl != 0)
596 acl_id = q->acl;
597 else {
598 name = q->shortname;
048b1b94 599 EXEC SQL SELECT list_id INTO :acl_id FROM capacls WHERE tag = :name;
600 if (sqlca.sqlcode < 0) return(MR_INGRES_ERR);
601 if (sqlca.sqlcode == 100) return(MR_PERM);
b070f8a1 602 q->acl = acl_id;
603
604 /* check for default access */
048b1b94 605 EXEC SQL SELECT member_id INTO :acl_id FROM imembers
606 WHERE list_id = :acl_id AND member_type = 'USER'
607 AND member_id = :def_uid;
608 if (sqlca.sqlerrd[2] == 0)
609 q->everybody = 0;
610 else
611 q->everybody = 1;
b070f8a1 612 }
613
614 if (q->everybody)
615 return(MR_SUCCESS);
616
617 if (get_client(cl, &client_type, &client_id) != MR_SUCCESS)
618 return(MR_PERM);
619 if (find_member("LIST", acl_id, client_type, client_id, 0))
620 return(MR_SUCCESS);
621 else
622 return(MR_PERM);
048b1b94 623}
b070f8a1 624
625
626get_client(cl, client_type, client_id)
627 client *cl;
628 char **client_type;
629 int *client_id;
630{
631 if (cl->users_id > 0) {
632 *client_id = cl->users_id;
633 *client_type = "USER";
634 return(MR_SUCCESS);
635 }
636
637 if (cl->client_id < 0) {
638 *client_id = -cl->users_id;
639 *client_type = "KERBEROS";
640 return(MR_SUCCESS);
641 }
642
643 return(MR_PERM);
644}
645
048b1b94 646find_member(list_type, list_id, member_type, member_id)
1a41acb7 647 char *list_type;
048b1b94 648 EXEC SQL BEGIN DECLARE SECTION;
649 int list_id;
650 char *member_type;
651 int member_id;
652 EXEC SQL END DECLARE SECTION;
653{
654 EXEC SQL BEGIN DECLARE SECTION;
655 int flag, errorno;
656 EXEC SQL END DECLARE SECTION;
b070f8a1 657
658 if (!strcmp(strtrim(list_type), strtrim(member_type)) &&
659 list_id == member_id)
660 return(1);
661
662 /* see if client is a direct member of list */
048b1b94 663 flag = 0;
664 EXEC SQL SELECT member_id INTO :flag FROM imembers
665 WHERE list_id = :list_id AND member_type = :member_type
666 AND member_id = :member_id;
667 if(flag!=0) flag=1; /** Not strictly necessary */
668 if (sqlca.sqlcode == 0)
669 return(flag);
670 return(0);
671}
b070f8a1 672
673
048b1b94 674do_retrieve(q, pqual, psort, action, actarg)
b070f8a1 675 register struct query *q;
048b1b94 676EXEC SQL BEGIN DECLARE SECTION;
b070f8a1 677 char *pqual;
678 char *psort;
048b1b94 679EXEC SQL END DECLARE SECTION;
b070f8a1 680 int (*action)();
681 char *actarg;
048b1b94 682{
b070f8a1 683 static char **vaddrs = (char **)NULL;
684
685 if (!vaddrs) {
686 register int i;
687
688 if ((vaddrs = (char **)malloc(sizeof(char *) * QMAXARGS)) == NULL) {
689 com_err(whoami, MR_NO_MEM, "setting up static argv");
690 exit(1);
691 }
692 for (i = 0; i < QMAXARGS; i++) {
693 if ((vaddrs[i] = malloc(QMAXARGSIZE)) == NULL) {
694 com_err(whoami, MR_NO_MEM, "setting up static argv");
695 exit(1);
696 }
697 }
698 }
699
048b1b94 700/*
701 * if (psort) {
702 * csort = psort;
703 * if (pqual) {
704 * cqual = pqual;
705 * retrieve unique (param (q->tlist, vaddrs)) where cqual
706 * sort by csort
707 * {
708 * (*action)(q->vcnt, vaddrs, actarg);
709 * }
710 * } else {
711 * retrieve unique (param (q->tlist, vaddrs))
712 * sort by csort
713 * {
714 * (*action)(q->vcnt, vaddrs, actarg);
715 * }
716 * }
717 *
718 * } else {
719 * if (pqual) {
720 * cqual = pqual;
721 * retrieve unique (param (q->tlist, vaddrs)) where cqual
722 * {
723 * (*action)(q->vcnt, vaddrs, actarg);
724 * }
725 * } else {
726 * retrieve unique (param (q->tlist, vaddrs))
727 * {
728 * (*action)(q->vcnt, vaddrs, actarg);
729 * }
730 * }
731 * }
732 */
b070f8a1 733
048b1b94 734 build_sql_stmt(stmt_buf,"SELECT",q->tlist,argv,pqual);
735 if(psort) { strcat(stmt_buf," ORDER BY "); strcat(stmt_buf,psort); }
736 EXEC SQL PREPARE stmt FROM :stmt_buf;
737 EXEC SQL DESCRIBE stmt INTO :SQLDA;
738 if(SQLDA->sqld > MR_DYN_VARS) {
739 comm_err(whoami, MR_INTERNAL,
740 "Internal arg count error processing dynamic query");
741 return(MR_INTERNAL);
742 }
b070f8a1 743
048b1b94 744 for(i=0;i<SQLDA->sqld;i++) {
745 SQLDA->sqlvar[i].sqldata=vaddr[i];
746 SQLDA->sqlvar[i].sqllen=QMAXARGSIZE-2;
747 }
748 EXEC SQL DECLARE csr001 CURSOR FOR stmt;
749 EXEC SQL OPEN csr001;
750 while(1) {
751 EXEC SQL FETCH csr001 USING DESCRIPTOR :SQLDA;
752 if(sqlca.sqlcode != 0) break;
753 (*action)(q->vcnt, vaddrs, actarg);
b070f8a1 754 }
048b1b94 755 EXEC SQL CLOSE csr001;
b070f8a1 756
757 if (mr_errcode) return(mr_errcode);
048b1b94 758 return ((sqlca.sqlerrd[2] == 0) ? MR_NO_MATCH : MR_SUCCESS);
759}
760
761build_sql_stmt(result_buf,cmd,targetlist,argv,qual)
762 char *result_buf;
763 char *cmd;
764 char *targetlist;
765 char *argv[];
766 char *squal;
767{
768 char fmt_buf[MR_STMTBUF_LEN];
769 char tmp_buf[16];
770 char *res=result_buf, *tmp=tmp_buf, *fmt=fmt_buf;
771 int state;
772
773 sprintf(fmt_buf,"%s %s",cmd,targetlist);
774 if(qual) { strcat(fmt_buf," WHERE "); strcat(fmt_buf,qual); }
775
776 for(i=0,state=0;*fmt != '\0';fmt++) {
777 switch(state) {
778 case 0:
779 if(*fmt=='%') { /* formatting -> tmp */
780 *tmp++=*fmt;
781 state=1;
782 } else *res++=*fmt; /* text -> res */
783 break;
784 case 1:
785 if((*fmt=='%') && (tmp==tmp_buf+1)) { /* %% -> % */
786 *res++=*fmt;
787 tmp=tmp_buf;
788 state=0;
789 } else if(isalpha(*fmt) && (*fmt!='h') && (*fmt!='l')) { /* end of formatting */
790 *tmp++=*fmt;
791 *tmp='\0';
792 tmp=tmp_buf;
793 sprintf(res,tmp_buf,*argv++); /* print to result buffer */
794 while(*res++) ;
795 state=0;
796 } else *tmp++=*fmt; /* keep copying the formatting to tmp */
797 break;
798 }
799 }
800 *res='\0';
801}
b070f8a1 802
803do_update(q, argv, qual, action, actarg)
804 register struct query *q;
805 char *argv[];
806 char *qual;
807 int (*action)();
808 char *actarg;
048b1b94 809{
810 build_sql_stmt(stmt_buf,"UPDATE",q->tlist,argv,qual);
811 EXEC SQL EXECUTE IMMEDIATE stmt_buf;
b070f8a1 812 if (mr_errcode) return(mr_errcode);
813 return(MR_SUCCESS);
048b1b94 814}
b070f8a1 815
816do_append(q, argv, pqual, action, actarg)
817 register struct query *q;
818 char *argv[];
819 char *pqual;
820 int (*action)();
821 char *actarg;
048b1b94 822{
823 build_sql_stmt(stmt_buf,"INSERT",q->tlist,argv,pqual);
824 EXEC SQL EXECUTE IMMEDIATE stmt_buf;
b070f8a1 825 if (mr_errcode) return(mr_errcode);
826 return(MR_SUCCESS);
048b1b94 827}
b070f8a1 828
829do_delete(q, qual, action, actarg)
830 register struct query *q;
831 char *qual;
832 int (*action)();
833 char *actarg;
048b1b94 834{
835 sprintf(stmt_buf,"DELETE FROM %s WHERE %s",q->rtable,qual);
836 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
b070f8a1 837 if (mr_errcode) return(mr_errcode);
838 return(MR_SUCCESS);
048b1b94 839}
b070f8a1 840
841
842/**
843 ** set_next_object_id - set next object id in values table
844 **
845 ** Inputs: object - object name in values table and in objects
846 ** table - name of table objects are found in
1a41acb7 847 ** limit - should the ID be range limited
b070f8a1 848 **
849 ** - called before an APPEND operation to set the next object id to
850 ** be used for the new record to the next free value
851 **
852 **/
853
048b1b94 854set_next_object_id(object, table_name, limit)
855 EXEC SQL BEGIN DECLARE SECTION;
1a41acb7 856 char *object;
048b1b94 857 char *table_name;
1a41acb7 858 int limit;
048b1b94 859 EXEC SQL END DECLARE SECTION;
860{
861 EXEC SQL BEGIN DECLARE SECTION;
862 int value, dummy;
863 EXEC SQL END DECLARE SECTION;
864
865 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :object;
866 if (sqlca.sqlerrd[2] != 1)
1a41acb7 867 return(MR_NO_ID);
868
048b1b94 869/*
870/* retrieve (exists = any(tbl.name where tbl.name = value)) */
871 */
872/* sprintf(buf,"SELECT name INTO :dummy FROM %s WHERE name=:value",table_name); */
873 EXEC SQL SELECT name INTO :value FROM :table_name WHERE name = :value; /** */
874 if (sqlca.sqlerrd[2] != 1)
1a41acb7 875 return(MR_NO_ID);
048b1b94 876 while (sqlca.sqlerrd[2] != 0) {
b070f8a1 877 value++;
1a41acb7 878 if (limit && value > MAX_ID_VALUE)
b070f8a1 879 value = MIN_ID_VALUE;
048b1b94 880/*
881/* retrieve (exists = any(tbl.name where tbl.name = value)) */
882 */
883 EXEC SQL SELECT name INTO :value FROM :table_name WHERE name = :value; /** */
b070f8a1 884 }
885
886 if (LOG_RES)
887 com_err(whoami, 0, "setting ID %s to %d", name, value);
048b1b94 888 EXEC SQL UPDATE numvalues SET value = :value WHERE name = :object;
b070f8a1 889 return(MR_SUCCESS);
048b1b94 890}
b070f8a1 891
892
893/* Turn a kerberos name into the user's ID of the account that principal
894 * owns. Sets the kerberos ID and user ID.
895 */
896
897int set_krb_mapping(name, login, ok, kid, uid)
898char *name;
899char *login;
900int ok;
901int *kid;
902int *uid;
048b1b94 903{
904 EXEC SQL BEGIN DECLARE SECTION;
905 int u_id, k_id;
906 char *krbname;
907 EXEC SQL END DECLARE SECTION;
b070f8a1 908
909 krbname = name;
910 *kid = 0;
911 *uid = 0;
912
048b1b94 913 EXEC SQL SELECT k.users_id, k.string_id INTO :u_id, :k_id
914 FROM krbmap k, strings s
915 WHERE k.string_id = s.string_id AND s.string = :krbname;
916
b070f8a1 917 if (ingres_errno) return(mr_errcode);
918
048b1b94 919 if (sqlca.sqlerrd[2] == 1) { /* rowcount */
b070f8a1 920 *kid = -k_id;
921 *uid = u_id;
922 return(MR_SUCCESS);
923 }
924
925 if (name_to_id(name, "STRINGS", &k_id) == MR_SUCCESS)
926 *kid = -k_id;
927
048b1b94 928 if (!ok) {
b070f8a1 929 *uid = *kid;
930 return(MR_SUCCESS);
931 }
932
933 if (name_to_id(login, "USERS", uid) != MR_SUCCESS)
934 *uid = 0;
935
936 if (*kid == 0)
937 *kid = *uid;
938 if (ingres_errno) return(mr_errcode);
939 return(MR_SUCCESS);
048b1b94 940}
b070f8a1 941
942
943/* For now this just checks the argc's. It should also see that there
944 * are no duplicate names.
945 */
946
947sanity_check_queries()
948{
949 register int i;
950 int maxv = 0, maxa = 0;
951#ifdef MULTIPROTOCOLS
952 extern int QueryCount1, QueryCount2;
953 extern struct query Queries1[], Queries2[];
954#else
955 extern int QueryCount2;
956 extern struct query Queries2[];
957#endif MULTIPROTOCOLS
958
959#define MAX(x,y) ((x) > (y) ? (x) : (y))
960
961#ifdef MULTIPROTOCOLS
962 for (i = 0; i < QueryCount1; i++) {
963 maxv = MAX(maxv, Queries1[i].vcnt);
964 maxa = MAX(maxa, Queries1[i].argc);
965 }
966#endif MULTIPROTOCOLS
967 for (i = 0; i < QueryCount2; i++) {
968 maxv = MAX(maxv, Queries2[i].vcnt);
969 maxa = MAX(maxa, Queries2[i].argc);
970 }
971 if (MAX(maxv, maxa) > QMAXARGS) {
972 com_err(whoami, 0, "A query has more args than QMAXARGS");
973 exit(1);
974 }
975}
048b1b94 976
977/* eof:qrtn.dc */
This page took 0.212999 seconds and 5 git commands to generate.