]> andersk Git - moira.git/blame - server/qrtn.dc
Checkin prior to adding optimize_sql_stmt()
[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;
1741dca0 25int mr_sig_length;
048b1b94 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
1741dca0 41#define INGRES_BAD_DATE1 40206
42#define INGRES_BAD_DATE2 40207
43#define INGRES_DEADLOCK 49900
1b247a36 44#define INGRES_TIMEOUT 39100
45bf7573 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
048b1b94 50/*
1741dca0 51 * ingerr: Called when Ingres indicates an error.
b070f8a1 52 */
53
c9a214e4 54void ingerr()
b070f8a1 55{
45bf7573 56 EXEC SQL BEGIN DECLARE SECTION;
57 char err_msg[256];
58 EXEC SQL END DECLARE SECTION;
048b1b94 59 ingres_errno = -sqlca.sqlcode;
b070f8a1 60
048b1b94 61 switch (ingres_errno) {
1741dca0 62 case INGRES_BAD_DATE1:
63 case INGRES_BAD_DATE2:
b070f8a1 64 mr_errcode = MR_DATE;
65 break;
1741dca0 66 case INGRES_DEADLOCK:
b070f8a1 67 mr_errcode = MR_DEADLOCK;
68 com_err(whoami, 0, "INGRES deadlock detected");
69 break;
1b247a36 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:
45bf7573 78 mr_errcode = MR_INTERNAL;
79 com_err(whoami, 0, "Cursor not opened");
80 break;
1b247a36 81 case INGRES_NO_STMT:
45bf7573 82 mr_errcode = MR_INTERNAL;
83 com_err(whoami, 0, "Statement not declared");
84 break;
1b247a36 85 case INGRES_BAD_COLUMN:
1741dca0 86 mr_errcode = MR_INTERNAL;
87 com_err(whoami, 0, "Bad column name in query table");
88 break;
1b247a36 89 case INGRES_ASGN_ERR:
1741dca0 90 mr_errcode = MR_INTERNAL;
91 com_err(whoami, 0, "Error in SQL assignment statement");
92 break;
1b247a36 93/* Others ??? */
94 default:
b070f8a1 95 mr_errcode = MR_INGRES_ERR;
45bf7573 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);
c9a214e4 99 critical_alert("MOIRA", "Moira server encountered INGRES ERROR %d", ingres_errno);
b070f8a1 100 }
b070f8a1 101}
102
45bf7573 103/* This is declarative, not executed. Applies from here on, in this file. */
048b1b94 104EXEC SQL WHENEVER SQLERROR CALL ingerr;
105
b070f8a1 106int mr_open_database()
107{
108 register int i;
109 char *malloc();
c9a214e4 110 MR_SQLDA_T *mr_alloc_SQLDA();
b070f8a1 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
c9a214e4 120 SQLDA = mr_alloc_SQLDA();
121
b070f8a1 122 incremental_init();
123 flush_cache();
124 }
125
126 ingres_errno = 0;
127 mr_errcode = 0;
128
129 /* open the database */
048b1b94 130#ifsql INGRES
131 EXEC SQL CONNECT moira;
1741dca0 132 if(ingres_errno)
133 return (ingres_errno);
048b1b94 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
1741dca0 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);
b070f8a1 150}
151
152int mr_close_database()
153{
154 flush_cache();
048b1b94 155#ifsql INGRES
156 EXEC SQL DISCONNECT;
157#endsql
b070f8a1 158}
159
160mr_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
048b1b94 176 return(mr_verify_query(cl, q, argc, argv_ro));
b070f8a1 177}
178
179mr_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;
048b1b94 194 EXEC SQL BEGIN DECLARE SECTION;
195 char *table_name;
196 EXEC SQL END DECLARE SECTION;
b070f8a1 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) {
048b1b94 243 status = validate_row(q, Argv, v);
b070f8a1 244 if (status != MR_EXISTS) break;
245 }
246
247 /* build "where" clause if needed */
248 if (q->qual) {
048b1b94 249 build_qual(q->qual, q->argc, Argv, qual);
b070f8a1 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);
048b1b94 301 table_name = q->rtable;
b070f8a1 302 if (strcmp(q->shortname, "sshi") && strcmp(q->shortname, "ssif")) {
048b1b94 303 EXEC SQL UPDATE tblstats
304 SET updates = updates + 1, modtime = 'now'
305 WHERE table_name = :table_name;
b070f8a1 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
b070f8a1 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) {
1b247a36 336 sprintf(qual, "%s.%s = %s",q->rvar, v->object_id,
45bf7573 337 Argv[q->argc+q->vcnt]);
b070f8a1 338 incremental_after(q->rtable, qual, argv_ro);
339 } else
340 incremental_after(q->rtable, pqual, argv_ro);
341
048b1b94 342 table_name = q->rtable;
343 EXEC SQL UPDATE tblstats
344 SET appends = appends + 1, modtime = 'now'
345 WHERE table_name = :table_name;
b070f8a1 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);
048b1b94 363 table_name = q->rtable;
364 incremental_before(q->rtable, qual, argv_ro);
b070f8a1 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);
048b1b94 369 EXEC SQL UPDATE tblstats
370 SET deletes = deletes + 1, modtime = 'now'
371 WHERE table_name = :table_name;
b070f8a1 372 }
373
374 /* execute followup routine */
375 if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
376 break;
377
378 }
379
380out:
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
048b1b94 387 if (q->type == RETRIEVE) {
048b1b94 388 EXEC SQL COMMIT WORK;
048b1b94 389 } else {
b070f8a1 390 if (status == MR_SUCCESS) {
048b1b94 391 EXEC SQL COMMIT WORK;
b070f8a1 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 {
1a41acb7 412 cache_abort();
b070f8a1 413 if (ingres_errno != INGRES_DEADLOCK) {
048b1b94 414 EXEC SQL ROLLBACK WORK;
b070f8a1 415 }
416 incremental_flush();
417 }
418 }
1a41acb7 419 cache_commit(); /* commit following abort is safe */
b070f8a1 420
421 if (status != MR_SUCCESS && log_flags & LOG_RES)
422 com_err(whoami, status, " (Query failed)");
423 return(status);
424}
425
426build_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 }
1a41acb7 448 if (c = index(c, '%')) {
449 args[i] = args[i - 1];
450 }
b070f8a1 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;
1a41acb7 472
473 default:
474 com_err(whoami, MR_INTERNAL,
475 "Internal arg count error processing query");
476 return(MR_INTERNAL);
b070f8a1 477 }
478 return(MR_SUCCESS);
479}
480
481char *
482build_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) {
048b1b94 496 sprintf(elem, "%d", vo->index + 1); /* Result column number */
b070f8a1 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
509mr_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;
99e09b48 520 register char *to,*fr,*stop;
b070f8a1 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++) {
99e09b48 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 == '\\')
b070f8a1 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
575check_query_access(q, argv, cl)
576 struct query *q;
577 char *argv[];
578 client *cl;
048b1b94 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;
b070f8a1 587 int status;
588 int client_id;
589 char *client_type;
590
591 /* initialize default uid */
592 if (def_uid == 0) {
048b1b94 593 EXEC SQL SELECT users_id INTO :def_uid FROM users WHERE login='default';
b070f8a1 594 }
595
596 /* get query access control list */
597 if (q->acl != 0)
598 acl_id = q->acl;
599 else {
600 name = q->shortname;
048b1b94 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);
b070f8a1 604 q->acl = acl_id;
605
606 /* check for default access */
048b1b94 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;
b070f8a1 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);
048b1b94 625}
b070f8a1 626
627
628get_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
048b1b94 648find_member(list_type, list_id, member_type, member_id)
1a41acb7 649 char *list_type;
048b1b94 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;
b070f8a1 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 */
048b1b94 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}
b070f8a1 674
675
048b1b94 676do_retrieve(q, pqual, psort, action, actarg)
b070f8a1 677 register struct query *q;
048b1b94 678EXEC SQL BEGIN DECLARE SECTION;
b070f8a1 679 char *pqual;
680 char *psort;
048b1b94 681EXEC SQL END DECLARE SECTION;
b070f8a1 682 int (*action)();
683 char *actarg;
048b1b94 684{
b070f8a1 685 static char **vaddrs = (char **)NULL;
c9a214e4 686 int j, rowcount;
b070f8a1 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 }
45bf7573 695 for (i = 0; i < QMAXARGS; i++) {
c9a214e4 696 vaddrs[i]=SQLDA->sqlvar[i].sqldata;
b070f8a1 697 }
698 }
699
c9a214e4 700 build_sql_stmt(stmt_buf,"SELECT",q->tlist,vaddrs,pqual);
048b1b94 701 if(psort) { strcat(stmt_buf," ORDER BY "); strcat(stmt_buf,psort); }
c9a214e4 702 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
99e09b48 703 if(sqlca.sqlcode)
704 return(MR_INTERNAL);
048b1b94 705 EXEC SQL DECLARE csr001 CURSOR FOR stmt;
706 EXEC SQL OPEN csr001;
c9a214e4 707 rowcount = 0;
048b1b94 708 while(1) {
709 EXEC SQL FETCH csr001 USING DESCRIPTOR :SQLDA;
710 if(sqlca.sqlcode != 0) break;
711 (*action)(q->vcnt, vaddrs, actarg);
c9a214e4 712 rowcount++;
b070f8a1 713 }
048b1b94 714 EXEC SQL CLOSE csr001;
b070f8a1 715
716 if (mr_errcode) return(mr_errcode);
c9a214e4 717 return ((rowcount == 0) ? MR_NO_MATCH : MR_SUCCESS);
048b1b94 718}
719
720build_sql_stmt(result_buf,cmd,targetlist,argv,qual)
721 char *result_buf;
722 char *cmd;
723 char *targetlist;
724 char *argv[];
c9a214e4 725 char *qual;
048b1b94 726{
727 char fmt_buf[MR_STMTBUF_LEN];
99e09b48 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 */
048b1b94 759 }
760 *res='\0';
761}
b070f8a1 762
763do_update(q, argv, qual, action, actarg)
764 register struct query *q;
765 char *argv[];
766 char *qual;
767 int (*action)();
768 char *actarg;
048b1b94 769{
770 build_sql_stmt(stmt_buf,"UPDATE",q->tlist,argv,qual);
c9a214e4 771 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
b070f8a1 772 if (mr_errcode) return(mr_errcode);
773 return(MR_SUCCESS);
048b1b94 774}
b070f8a1 775
776do_append(q, argv, pqual, action, actarg)
777 register struct query *q;
778 char *argv[];
779 char *pqual;
780 int (*action)();
781 char *actarg;
048b1b94 782{
783 build_sql_stmt(stmt_buf,"INSERT",q->tlist,argv,pqual);
c9a214e4 784 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
b070f8a1 785 if (mr_errcode) return(mr_errcode);
786 return(MR_SUCCESS);
048b1b94 787}
b070f8a1 788
789do_delete(q, qual, action, actarg)
790 register struct query *q;
791 char *qual;
792 int (*action)();
793 char *actarg;
048b1b94 794{
795 sprintf(stmt_buf,"DELETE FROM %s WHERE %s",q->rtable,qual);
796 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
b070f8a1 797 if (mr_errcode) return(mr_errcode);
798 return(MR_SUCCESS);
048b1b94 799}
b070f8a1 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
1a41acb7 807 ** limit - should the ID be range limited
b070f8a1 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
048b1b94 814set_next_object_id(object, table_name, limit)
815 EXEC SQL BEGIN DECLARE SECTION;
1a41acb7 816 char *object;
048b1b94 817 char *table_name;
1a41acb7 818 int limit;
048b1b94 819 EXEC SQL END DECLARE SECTION;
820{
821 EXEC SQL BEGIN DECLARE SECTION;
c9a214e4 822 int value;
048b1b94 823 EXEC SQL END DECLARE SECTION;
45bf7573 824 int starting_value;
825
048b1b94 826 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :object;
827 if (sqlca.sqlerrd[2] != 1)
1a41acb7 828 return(MR_NO_ID);
829
45bf7573 830 starting_value=value;
c9a214e4 831 while (1) {
45bf7573 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;
99e09b48 837 if(sqlca.sqlcode)
838 return(MR_INTERNAL);
45bf7573 839 EXEC SQL DECLARE csr002 CURSOR FOR stmt;
c9a214e4 840 EXEC SQL OPEN csr002;
45bf7573 841 EXEC SQL FETCH csr002 USING DESCRIPTOR :SQLDA;
842 if (sqlca.sqlcode < 0) return(mr_errcode);
843 if (sqlca.sqlcode == 100) break;
844
c9a214e4 845 EXEC SQL CLOSE csr002;
45bf7573 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 }
b070f8a1 851 }
c9a214e4 852 EXEC SQL CLOSE csr002;
b070f8a1 853
854 if (LOG_RES)
c9a214e4 855 com_err(whoami, 0, "setting ID %s to %d", object, value);
048b1b94 856 EXEC SQL UPDATE numvalues SET value = :value WHERE name = :object;
b070f8a1 857 return(MR_SUCCESS);
048b1b94 858}
b070f8a1 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
865int set_krb_mapping(name, login, ok, kid, uid)
866char *name;
867char *login;
868int ok;
869int *kid;
870int *uid;
048b1b94 871{
872 EXEC SQL BEGIN DECLARE SECTION;
873 int u_id, k_id;
874 char *krbname;
875 EXEC SQL END DECLARE SECTION;
b070f8a1 876
877 krbname = name;
878 *kid = 0;
879 *uid = 0;
880
fbeb0263 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;
048b1b94 884
b070f8a1 885 if (ingres_errno) return(mr_errcode);
886
048b1b94 887 if (sqlca.sqlerrd[2] == 1) { /* rowcount */
b070f8a1 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
048b1b94 896 if (!ok) {
b070f8a1 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);
048b1b94 908}
b070f8a1 909
910
911/* For now this just checks the argc's. It should also see that there
912 * are no duplicate names.
913 */
914
915sanity_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}
048b1b94 944
945/* eof:qrtn.dc */
This page took 0.191258 seconds and 5 git commands to generate.