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