]> andersk Git - moira.git/blame - server/qrtn.dc
Fix for update_quota (correlation names.)
[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
c9a214e4 23MR_SQLDA_T *SQLDA;
048b1b94 24EXEC SQL BEGIN DECLARE SECTION;
25int idummy;
26char cdummy[MR_CDUMMY_LEN];
27char stmt_buf[MR_STMTBUF_LEN];
28EXEC SQL END DECLARE SECTION;
b070f8a1 29
30char *Argv[16];
31
32int ingres_errno = 0;
33int mr_errcode = 0;
048b1b94 34EXEC SQL BEGIN DECLARE SECTION;
35int query_timeout = 30;
36EXEC SQL END DECLARE SECTION;
b070f8a1 37extern char *whoami;
38extern FILE *journal;
39
c9a214e4 40/** Maybe this should be replaced by something like tytso's sql_error */
048b1b94 41
42#define INGRES_BAD_DATE1 41206
43#define INGRES_BAD_DATE2 40207
44#define INGRES_DEADLOCK 49900
45bf7573 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
048b1b94 51/*
52#define INGRES_BAD_INT
53#define INGRES_TIMEOUT
54#define INGRES_NO_RANGE
55 */
b070f8a1 56
c9a214e4 57
b070f8a1 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
c9a214e4 64void ingerr()
b070f8a1 65{
45bf7573 66 EXEC SQL BEGIN DECLARE SECTION;
67 char err_msg[256];
68 EXEC SQL END DECLARE SECTION;
048b1b94 69 ingres_errno = -sqlca.sqlcode;
b070f8a1 70
048b1b94 71 switch (ingres_errno) {
72/*
c9a214e4 73 * case INGRES_BAD_INT:
74 * mr_errcode = MR_INTEGER;
75 * break;
048b1b94 76 */
77 case INGRES_BAD_DATE1:
78 case INGRES_BAD_DATE2:
b070f8a1 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;
048b1b94 85/* I just don't know what the equivalent to this is, yet.
c9a214e4 86 * case INGRES_TIMEOUT:
87 * mr_errcode = MR_BUSY;
88 * com_err(whoami, 0, "timed out getting lock");
89 * break;
048b1b94 90 */
91/* This probably has no equivalent.
c9a214e4 92 * case INGRES_NO_RANGE:
93 * mr_errcode = MR_INGRES_SOFTFAIL;
94 * com_err(whoami, 0, "INGRES missing range statement");
95 * break;
048b1b94 96 */
45bf7573 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
b070f8a1 116 default:
048b1b94 117 /** Add the INGRES error_text to the alert message ??? **/
b070f8a1 118 mr_errcode = MR_INGRES_ERR;
45bf7573 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);
c9a214e4 122 critical_alert("MOIRA", "Moira server encountered INGRES ERROR %d", ingres_errno);
b070f8a1 123 }
b070f8a1 124}
125
45bf7573 126/* This is declarative, not executed. Applies from here on, in this file. */
048b1b94 127EXEC SQL WHENEVER SQLERROR CALL ingerr;
128
b070f8a1 129int mr_open_database()
130{
131 register int i;
132 char *malloc();
c9a214e4 133 MR_SQLDA_T *mr_alloc_SQLDA();
b070f8a1 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
c9a214e4 143 SQLDA = mr_alloc_SQLDA();
144
b070f8a1 145 incremental_init();
146 flush_cache();
147 }
148
149 ingres_errno = 0;
150 mr_errcode = 0;
151
152 /* open the database */
048b1b94 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
b070f8a1 162 return ingres_errno;
163}
164
165int mr_close_database()
166{
167 flush_cache();
048b1b94 168#ifsql INGRES
169 EXEC SQL DISCONNECT;
170#endsql
b070f8a1 171}
172
173mr_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
048b1b94 189 return(mr_verify_query(cl, q, argc, argv_ro));
b070f8a1 190}
191
192mr_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;
048b1b94 207 EXEC SQL BEGIN DECLARE SECTION;
208 char *table_name;
209 EXEC SQL END DECLARE SECTION;
b070f8a1 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) {
048b1b94 256 status = validate_row(q, Argv, v);
b070f8a1 257 if (status != MR_EXISTS) break;
258 }
259
260 /* build "where" clause if needed */
261 if (q->qual) {
048b1b94 262 build_qual(q->qual, q->argc, Argv, qual);
b070f8a1 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);
048b1b94 314 table_name = q->rtable;
b070f8a1 315 if (strcmp(q->shortname, "sshi") && strcmp(q->shortname, "ssif")) {
048b1b94 316 EXEC SQL UPDATE tblstats
317 SET updates = updates + 1, modtime = 'now'
318 WHERE table_name = :table_name;
b070f8a1 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
45bf7573 334#ifdef NEVER
335 /* This is now done by a valobj, which also fetches the id value */
336
b070f8a1 337 /* increment id number if necessary */
338 if (v->object_id) {
1a41acb7 339 status = set_next_object_id(v->object_id, q->rtable, 0);
b070f8a1 340 if (status != MR_SUCCESS) break;
341 }
45bf7573 342#endif
b070f8a1 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) {
45bf7573 359 sprintf(qual, "%s.%s = %s",q->rtable, v->object_id,
360 Argv[q->argc+q->vcnt]);
b070f8a1 361 incremental_after(q->rtable, qual, argv_ro);
362 } else
363 incremental_after(q->rtable, pqual, argv_ro);
364
048b1b94 365 table_name = q->rtable;
366 EXEC SQL UPDATE tblstats
367 SET appends = appends + 1, modtime = 'now'
368 WHERE table_name = :table_name;
b070f8a1 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);
048b1b94 386 table_name = q->rtable;
387 incremental_before(q->rtable, qual, argv_ro);
b070f8a1 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);
048b1b94 392 EXEC SQL UPDATE tblstats
393 SET deletes = deletes + 1, modtime = 'now'
394 WHERE table_name = :table_name;
b070f8a1 395 }
396
397 /* execute followup routine */
398 if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
399 break;
400
401 }
402
403out:
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
048b1b94 410 if (q->type == RETRIEVE) {
048b1b94 411 EXEC SQL COMMIT WORK;
048b1b94 412 } else {
b070f8a1 413 if (status == MR_SUCCESS) {
048b1b94 414 EXEC SQL COMMIT WORK;
b070f8a1 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 {
1a41acb7 435 cache_abort();
b070f8a1 436 if (ingres_errno != INGRES_DEADLOCK) {
048b1b94 437 EXEC SQL ROLLBACK WORK;
b070f8a1 438 }
439 incremental_flush();
440 }
441 }
1a41acb7 442 cache_commit(); /* commit following abort is safe */
b070f8a1 443
444 if (status != MR_SUCCESS && log_flags & LOG_RES)
445 com_err(whoami, status, " (Query failed)");
446 return(status);
447}
448
449build_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 }
1a41acb7 471 if (c = index(c, '%')) {
472 args[i] = args[i - 1];
473 }
b070f8a1 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;
1a41acb7 495
496 default:
497 com_err(whoami, MR_INTERNAL,
498 "Internal arg count error processing query");
499 return(MR_INTERNAL);
b070f8a1 500 }
501 return(MR_SUCCESS);
502}
503
504char *
505build_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) {
048b1b94 519 sprintf(elem, "%d", vo->index + 1); /* Result column number */
b070f8a1 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
532mr_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;
99e09b48 543 register char *to,*fr,*stop;
b070f8a1 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++) {
99e09b48 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 == '\\')
b070f8a1 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
598check_query_access(q, argv, cl)
599 struct query *q;
600 char *argv[];
601 client *cl;
048b1b94 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;
b070f8a1 610 int status;
611 int client_id;
612 char *client_type;
613
614 /* initialize default uid */
615 if (def_uid == 0) {
048b1b94 616 EXEC SQL SELECT users_id INTO :def_uid FROM users WHERE login='default';
b070f8a1 617 }
618
619 /* get query access control list */
620 if (q->acl != 0)
621 acl_id = q->acl;
622 else {
623 name = q->shortname;
048b1b94 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);
b070f8a1 627 q->acl = acl_id;
628
629 /* check for default access */
048b1b94 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;
b070f8a1 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);
048b1b94 648}
b070f8a1 649
650
651get_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
048b1b94 671find_member(list_type, list_id, member_type, member_id)
1a41acb7 672 char *list_type;
048b1b94 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;
b070f8a1 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 */
048b1b94 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}
b070f8a1 697
698
048b1b94 699do_retrieve(q, pqual, psort, action, actarg)
b070f8a1 700 register struct query *q;
048b1b94 701EXEC SQL BEGIN DECLARE SECTION;
b070f8a1 702 char *pqual;
703 char *psort;
048b1b94 704EXEC SQL END DECLARE SECTION;
b070f8a1 705 int (*action)();
706 char *actarg;
048b1b94 707{
b070f8a1 708 static char **vaddrs = (char **)NULL;
c9a214e4 709 int j, rowcount;
b070f8a1 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 }
45bf7573 718 for (i = 0; i < QMAXARGS; i++) {
c9a214e4 719 vaddrs[i]=SQLDA->sqlvar[i].sqldata;
b070f8a1 720 }
721 }
722
c9a214e4 723 build_sql_stmt(stmt_buf,"SELECT",q->tlist,vaddrs,pqual);
048b1b94 724 if(psort) { strcat(stmt_buf," ORDER BY "); strcat(stmt_buf,psort); }
c9a214e4 725 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
99e09b48 726 if(sqlca.sqlcode)
727 return(MR_INTERNAL);
048b1b94 728 EXEC SQL DECLARE csr001 CURSOR FOR stmt;
729 EXEC SQL OPEN csr001;
c9a214e4 730 rowcount = 0;
048b1b94 731 while(1) {
732 EXEC SQL FETCH csr001 USING DESCRIPTOR :SQLDA;
733 if(sqlca.sqlcode != 0) break;
734 (*action)(q->vcnt, vaddrs, actarg);
c9a214e4 735 rowcount++;
b070f8a1 736 }
048b1b94 737 EXEC SQL CLOSE csr001;
b070f8a1 738
739 if (mr_errcode) return(mr_errcode);
c9a214e4 740 return ((rowcount == 0) ? MR_NO_MATCH : MR_SUCCESS);
048b1b94 741}
742
743build_sql_stmt(result_buf,cmd,targetlist,argv,qual)
744 char *result_buf;
745 char *cmd;
746 char *targetlist;
747 char *argv[];
c9a214e4 748 char *qual;
048b1b94 749{
750 char fmt_buf[MR_STMTBUF_LEN];
99e09b48 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 */
048b1b94 782 }
783 *res='\0';
784}
b070f8a1 785
786do_update(q, argv, qual, action, actarg)
787 register struct query *q;
788 char *argv[];
789 char *qual;
790 int (*action)();
791 char *actarg;
048b1b94 792{
793 build_sql_stmt(stmt_buf,"UPDATE",q->tlist,argv,qual);
c9a214e4 794 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
b070f8a1 795 if (mr_errcode) return(mr_errcode);
796 return(MR_SUCCESS);
048b1b94 797}
b070f8a1 798
799do_append(q, argv, pqual, action, actarg)
800 register struct query *q;
801 char *argv[];
802 char *pqual;
803 int (*action)();
804 char *actarg;
048b1b94 805{
806 build_sql_stmt(stmt_buf,"INSERT",q->tlist,argv,pqual);
c9a214e4 807 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
b070f8a1 808 if (mr_errcode) return(mr_errcode);
809 return(MR_SUCCESS);
048b1b94 810}
b070f8a1 811
812do_delete(q, qual, action, actarg)
813 register struct query *q;
814 char *qual;
815 int (*action)();
816 char *actarg;
048b1b94 817{
818 sprintf(stmt_buf,"DELETE FROM %s WHERE %s",q->rtable,qual);
819 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
b070f8a1 820 if (mr_errcode) return(mr_errcode);
821 return(MR_SUCCESS);
048b1b94 822}
b070f8a1 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
1a41acb7 830 ** limit - should the ID be range limited
b070f8a1 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
048b1b94 837set_next_object_id(object, table_name, limit)
838 EXEC SQL BEGIN DECLARE SECTION;
1a41acb7 839 char *object;
048b1b94 840 char *table_name;
1a41acb7 841 int limit;
048b1b94 842 EXEC SQL END DECLARE SECTION;
843{
844 EXEC SQL BEGIN DECLARE SECTION;
c9a214e4 845 int value;
048b1b94 846 EXEC SQL END DECLARE SECTION;
45bf7573 847 int starting_value;
848
048b1b94 849 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :object;
850 if (sqlca.sqlerrd[2] != 1)
1a41acb7 851 return(MR_NO_ID);
852
45bf7573 853 starting_value=value;
c9a214e4 854 while (1) {
45bf7573 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;
99e09b48 860 if(sqlca.sqlcode)
861 return(MR_INTERNAL);
45bf7573 862 EXEC SQL DECLARE csr002 CURSOR FOR stmt;
c9a214e4 863 EXEC SQL OPEN csr002;
45bf7573 864 EXEC SQL FETCH csr002 USING DESCRIPTOR :SQLDA;
865 if (sqlca.sqlcode < 0) return(mr_errcode);
866 if (sqlca.sqlcode == 100) break;
867
c9a214e4 868 EXEC SQL CLOSE csr002;
45bf7573 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 }
b070f8a1 874 }
c9a214e4 875 EXEC SQL CLOSE csr002;
b070f8a1 876
877 if (LOG_RES)
c9a214e4 878 com_err(whoami, 0, "setting ID %s to %d", object, value);
048b1b94 879 EXEC SQL UPDATE numvalues SET value = :value WHERE name = :object;
b070f8a1 880 return(MR_SUCCESS);
048b1b94 881}
b070f8a1 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
888int set_krb_mapping(name, login, ok, kid, uid)
889char *name;
890char *login;
891int ok;
892int *kid;
893int *uid;
048b1b94 894{
895 EXEC SQL BEGIN DECLARE SECTION;
896 int u_id, k_id;
897 char *krbname;
898 EXEC SQL END DECLARE SECTION;
b070f8a1 899
900 krbname = name;
901 *kid = 0;
902 *uid = 0;
903
048b1b94 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
b070f8a1 908 if (ingres_errno) return(mr_errcode);
909
048b1b94 910 if (sqlca.sqlerrd[2] == 1) { /* rowcount */
b070f8a1 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
048b1b94 919 if (!ok) {
b070f8a1 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);
048b1b94 931}
b070f8a1 932
933
934/* For now this just checks the argc's. It should also see that there
935 * are no duplicate names.
936 */
937
938sanity_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}
048b1b94 967
968/* eof:qrtn.dc */
This page took 0.203904 seconds and 5 git commands to generate.