]> andersk Git - moira.git/blame - server/qvalidate.c
Used /bin/sh format instead of /bin/csh format, by accident.
[moira.git] / server / qvalidate.c
CommitLineData
f7e925bb 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
8 * <mit-copyright.h>.
9 *
10 */
11
12#ifndef lint
13static char *rcsid_qsupport_dc = "$Header$";
14#endif lint
15
16#include <mit-copyright.h>
17#include <unistd.h>
18#include "query.h"
19#include "mr_server.h"
20#include <ctype.h>
21EXEC SQL INCLUDE sqlca;
22EXEC SQL INCLUDE sqlda;
23#include "qrtn.h"
24
25extern char *whoami;
26extern int ingres_errno, mr_errcode;
27
28EXEC SQL BEGIN DECLARE SECTION;
29extern char stmt_buf[];
30EXEC SQL END DECLARE SECTION;
31
32EXEC SQL WHENEVER SQLERROR CALL ingerr;
33
34#ifdef _DEBUG_MALLOC_INC
35#undef index
36#define dbg_index(str1,c) DBindex(__FILE__, __LINE__, str1, c)
37#else
38#define dbg_index index
39#endif
40
41/* Validation Routines */
42
43validate_row(q, argv, v)
44 register struct query *q;
45 char *argv[];
46 register struct validate *v;
47{
48 EXEC SQL BEGIN DECLARE SECTION;
49 char *name;
50 char qual[128];
51 int rowcount;
52 EXEC SQL END DECLARE SECTION;
53
54 /* build where clause */
55 build_qual(v->qual, v->argc, argv, qual);
56
57 if (log_flags & LOG_VALID)
58 /* tell the logfile what we're doing */
59 com_err(whoami, 0, "validating row: %s", qual);
60
61 /* look for the record */
62 sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s",q->rtable,qual);
63 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
64 if(sqlca.sqlcode)
65 return(MR_INTERNAL);
66 EXEC SQL DECLARE csr126 CURSOR FOR stmt;
67 EXEC SQL OPEN csr126;
68 EXEC SQL FETCH csr126 USING DESCRIPTOR :SQLDA;
69 EXEC SQL CLOSE csr126;
70 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
71
72 if (ingres_errno) return(mr_errcode);
73 if (rowcount == 0) return(MR_NO_MATCH);
74 if (rowcount > 1) return(MR_NOT_UNIQUE);
75 return(MR_EXISTS);
76}
77
78validate_fields(q, argv, vo, n)
79 struct query *q;
80 register char *argv[];
81 register struct valobj *vo;
82 register int n;
83{
84 register int status;
85
86 while (--n >= 0) {
87 switch (vo->type) {
88 case V_NAME:
89 if (log_flags & LOG_VALID)
90 com_err(whoami, 0, "validating %s in %s: %s",
91 vo->namefield, vo->table, argv[vo->index]);
92 status = validate_name(argv, vo);
93 break;
94
95 case V_ID:
96 if (log_flags & LOG_VALID)
97 com_err(whoami, 0, "validating %s in %s: %s",
98 vo->idfield, vo->table, argv[vo->index]);
99 status = validate_id(q, argv, vo);
100 break;
101
102 case V_DATE:
103 if (log_flags & LOG_VALID)
104 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
105 status = validate_date(argv, vo);
106 break;
107
108 case V_TYPE:
109 if (log_flags & LOG_VALID)
110 com_err(whoami, 0, "validating %s type: %s",
111 vo->table, argv[vo->index]);
112 status = validate_type(argv, vo);
113 break;
114
115 case V_TYPEDATA:
116 if (log_flags & LOG_VALID)
117 com_err(whoami, 0, "validating typed data (%s): %s",
118 argv[vo->index - 1], argv[vo->index]);
119 status = validate_typedata(q, argv, vo);
120 break;
121
122 case V_RENAME:
123 if (log_flags & LOG_VALID)
124 com_err(whoami, 0, "validating rename %s in %s",
125 argv[vo->index], vo->table);
126 status = validate_rename(argv, vo);
127 break;
128
129 case V_CHAR:
130 if (log_flags & LOG_VALID)
131 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
132 status = validate_chars(argv[vo->index]);
133 break;
134
135 case V_SORT:
136 status = MR_EXISTS;
137 break;
138
139 case V_LOCK:
140 status = lock_table(vo);
141 break;
142
143 case V_RLOCK:
144 status = readlock_table(vo);
145 break;
146 case V_WILD:
147 status = convert_wildcards(argv[vo->index]);
148 break;
149
150 case V_UPWILD:
151 status = convert_wildcards_uppercase(argv[vo->index]);
152 break;
153
154 }
155
156 if (status != MR_EXISTS){
157 com_err(whoami,0,"validation failed type=%ld, code=%ld\n",vo->type, status);
158 return(status);
159 }
160 vo++;
161 }
162
163 if (ingres_errno) return(mr_errcode);
164 return(MR_SUCCESS);
165}
166
167
168/* validate_chars: verify that there are no illegal characters in
169 * the string. Legal characters are printing chars other than
170 * ", *, ?, \, [ and ].
171 */
172static int illegalchars[] = {
173 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
174 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
175 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
181 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
182 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
183 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
184 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
185 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
186 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
187 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
188 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
189};
190
191validate_chars(s)
192register char *s;
193{
194 while (*s)
195 if (illegalchars[*s++])
196 return(MR_BAD_CHAR);
197 return(MR_EXISTS);
198}
199
200
201validate_id(q, argv, vo)
202 struct query *q;
203 char *argv[];
204 register struct valobj *vo;
205{
206 EXEC SQL BEGIN DECLARE SECTION;
207 char *name, *tbl, *namefield, *idfield;
208 int id, rowcount;
209 EXEC SQL END DECLARE SECTION;
210 int status;
211 register char *c;
212
213 name = argv[vo->index];
214 tbl = vo->table;
215 namefield = vo->namefield;
216 idfield = vo->idfield;
217
218 if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) ||
219 !strcmp(tbl, "machine") ||
220 !strcmp(tbl, "subnet") ||
221 !strcmp(tbl, "filesys") ||
222 !strcmp(tbl, "list") ||
223 !strcmp(tbl, "cluster") ||
224 !strcmp(tbl, "strings")) {
225 if (!strcmp(tbl, "machine") || !strcmp(tbl, "subnet"))
226 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
227 status = name_to_id(name, tbl, &id);
228 if (status == 0) {
229 *(int *)argv[vo->index] = id;
230 return(MR_EXISTS);
231 } else if (status == MR_NO_MATCH && !strcmp(tbl, "strings") &&
232 (q->type == APPEND || q->type == UPDATE)) {
233 id=add_string(name);
234 cache_entry(name, "STRING", id);
235 *(int *)argv[vo->index] = id;
236 return(MR_EXISTS);
237 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
238 return(vo->error);
239 else
240 return(status);
241 }
242
243 if (!strcmp(namefield, "uid")) {
244 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = %s",idfield,tbl,namefield,name);
245 } else {
246 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = '%s'",idfield,tbl,namefield,name);
247 }
248 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
249 if(sqlca.sqlcode)
250 return(MR_INTERNAL);
251 EXEC SQL DECLARE csr127 CURSOR FOR stmt;
252 EXEC SQL OPEN csr127;
253 rowcount=0;
254 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
255 if(sqlca.sqlcode == 0) {
256 rowcount++;
257 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
258 if(sqlca.sqlcode == 0) rowcount++;
259 }
260 EXEC SQL CLOSE csr127;
261 if (ingres_errno)
262 return(mr_errcode);
263
264 if (rowcount != 1) return(vo->error);
265 bcopy(SQLDA->sqlvar[0].sqldata,argv[vo->index],sizeof(int));
266 return(MR_EXISTS);
267}
268
269validate_name(argv, vo)
270 char *argv[];
271 register struct valobj *vo;
272{
273 EXEC SQL BEGIN DECLARE SECTION;
274 char *name, *tbl, *namefield;
275 int rowcount;
276 EXEC SQL END DECLARE SECTION;
277 register char *c;
278
279 name = argv[vo->index];
280 tbl = vo->table;
281 namefield = vo->namefield;
282 if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) {
283 for (c = name; *c; c++)
284 if (islower(*c))
285 *c = toupper(*c);
286 }
287 sprintf(stmt_buf,"SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
288 tbl,tbl,namefield,name);
289 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
290 if(sqlca.sqlcode)
291 return(MR_INTERNAL);
292 EXEC SQL DECLARE csr128 CURSOR FOR stmt;
293 EXEC SQL OPEN csr128;
294 EXEC SQL FETCH csr128 USING DESCRIPTOR :SQLDA;
295 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
296 EXEC SQL CLOSE csr128;
297
298 if (ingres_errno) return(mr_errcode);
299 return ((rowcount == 1) ? MR_EXISTS : vo->error);
300}
301
302validate_date(argv, vo)
303 char *argv[];
304 struct valobj *vo;
305{
306 EXEC SQL BEGIN DECLARE SECTION;
307 char *idate;
308 double dd;
309 int errorno;
310 EXEC SQL END DECLARE SECTION;
311
312 idate = argv[vo->index];
313 EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd;
314
315 if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE);
316 return(MR_EXISTS);
317}
318
319
320validate_rename(argv, vo)
321char *argv[];
322struct valobj *vo;
323{
324 EXEC SQL BEGIN DECLARE SECTION;
325 char *name, *tbl, *namefield, *idfield;
326 int id;
327 EXEC SQL END DECLARE SECTION;
328 int status;
329 register char *c;
330
331 c = name = argv[vo->index];
332 while (*c)
333 if (illegalchars[*c++])
334 return(MR_BAD_CHAR);
335 tbl = vo->table;
336 /* minor kludge to upcasify machine names */
337 if (!strcmp(tbl, "machine"))
338 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
339 namefield = vo->namefield;
340 idfield = vo->idfield;
341 id = -1;
342 if (idfield == 0) {
343 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
344 return(MR_EXISTS);
345 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = LEFT('%s',SIZE(%s))",
346 namefield,tbl,namefield,name,namefield);
347 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
348 if(sqlca.sqlcode)
349 return(MR_INTERNAL);
350 EXEC SQL DECLARE csr129 CURSOR FOR stmt;
351 EXEC SQL OPEN csr129;
352 EXEC SQL FETCH csr129 USING DESCRIPTOR :SQLDA;
353 if(sqlca.sqlcode == 0) id=1; else id=0;
354 EXEC SQL CLOSE csr129;
355
356 if (ingres_errno) return(mr_errcode);
357 if (id)
358 return(vo->error);
359 else
360 return(MR_EXISTS);
361 }
362 status = name_to_id(name, tbl, &id);
363 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
364 return(MR_EXISTS);
365 else
366 return(vo->error);
367}
368
369
370validate_type(argv, vo)
371 char *argv[];
372 register struct valobj *vo;
373{
374 EXEC SQL BEGIN DECLARE SECTION;
375 char *typename;
376 char *val;
377 int cnt;
378 EXEC SQL END DECLARE SECTION;
379 register char *c;
380
381 typename = vo->table;
382 c = val = argv[vo->index];
383 while (*c) {
384 if (illegalchars[*c++])
385 return(MR_BAD_CHAR);
386 }
387
388 /* uppercase type fields */
389 for (c = val; *c; c++) if (islower(*c)) *c = toupper(*c);
390
391 EXEC SQL SELECT COUNT(trans) INTO :cnt FROM alias
392 WHERE name = :typename AND type='TYPE' AND trans = :val;
393 if (ingres_errno) return(mr_errcode);
394 return (cnt ? MR_EXISTS : vo->error);
395}
396
397/* validate member or type-specific data field */
398
399validate_typedata(q, argv, vo)
400 register struct query *q;
401 register char *argv[];
402 register struct valobj *vo;
403{
404 EXEC SQL BEGIN DECLARE SECTION;
405 char *name;
406 char *field_type;
407 char data_type[129];
408 int id;
409 EXEC SQL END DECLARE SECTION;
410 int status;
411 register char *c;
412
413 /* get named object */
414 name = argv[vo->index];
415
416 /* get field type string (known to be at index-1) */
417 field_type = argv[vo->index-1];
418
419 /* get corresponding data type associated with field type name */
420 EXEC SQL SELECT trans INTO :data_type FROM alias
421 WHERE name = :field_type AND type='TYPEDATA';
422 if (ingres_errno) return(mr_errcode);
423 if (sqlca.sqlerrd[2] != 1) return(MR_TYPE);
424
425 /* now retrieve the record id corresponding to the named object */
426 if (dbg_index(data_type, ' '))
427 *dbg_index(data_type, ' ') = 0;
428 if (!strcmp(data_type, "user")) {
429 /* USER */
430 if (dbg_index(name, '@'))
431 return(MR_USER);
432 status = name_to_id(name, data_type, &id);
433 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
434 return(MR_USER);
435 if (status) return(status);
436 } else if (!strcmp(data_type, "list")) {
437 /* LIST */
438 status = name_to_id(name, data_type, &id);
439 if (status && status == MR_NOT_UNIQUE)
440 return(MR_LIST);
441 if (status == MR_NO_MATCH) {
442 /* if idfield is non-zero, then if argv[0] matches the string
443 * that we're trying to resolve, we should get the value of
444 * numvalues.[idfield] for the id.
445 */
446 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
447 set_next_object_id(q->validate->object_id, q->rtable, 0);
448 name = vo->idfield;
449 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
450 WHERE name = :name;
451 if (sqlca.sqlerrd[2] != 1) return(MR_LIST);
452 } else
453 return(MR_LIST);
454 } else if (status) return(status);
455 } else if (!strcmp(data_type, "machine")) {
456 /* MACHINE */
457 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
458 status = name_to_id(name, data_type, &id);
459 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
460 return(MR_MACHINE);
461 if (status) return(status);
462 } else if (!strcmp(data_type, "string")) {
463 /* STRING */
464 status = name_to_id(name, data_type, &id);
465 if (status && status == MR_NOT_UNIQUE)
466 return(MR_STRING);
467 if (status == MR_NO_MATCH) {
468 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
469 id=add_string(name);
470 cache_entry(name, "STRING", id);
471 } else if (status) return(status);
472 } else if (!strcmp(data_type, "none")) {
473 id = 0;
474 } else {
475 return(MR_TYPE);
476 }
477
478 /* now set value in argv */
479 *(int *)argv[vo->index] = id;
480
481 return (MR_EXISTS);
482}
483
484
485/* Lock the table named by the validation object */
486
487lock_table(vo)
488struct valobj *vo;
489{
490 sprintf(stmt_buf,"UPDATE %s SET modtime='now' WHERE %s.%s = 0",
491 vo->table,vo->table,vo->idfield);
492 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
493 if (sqlca.sqlcode == 100){
494 fprintf(stderr,"readlock_table: no matching rows found for %s\n",
495 stmt_buf);
496 return(MR_INTERNAL);
497 }
498 if (ingres_errno)
499 return(mr_errcode);
500 if (sqlca.sqlerrd[2] != 1)
501 return(vo->error);
502 else
503 return(MR_EXISTS);
504}
505
506/*
507 * Get a read lock on the table by accessing the magic lock
508 * record. Certain tables are constructed so that they contain
509 * an id field whose value is zero and a modtime field. We
510 * manipulate the modtime field of the id 0 record to effect
511 * locking of the table
512 */
513
514readlock_table(vo)
515 struct valobj *vo;
516{
517 EXEC SQL BEGIN DECLARE SECTION;
518 int id;
519 char buf[256];
520 char *tbl, *idfield;
521 EXEC SQL END DECLARE SECTION;
522
523 tbl=vo->table;
524 idfield=vo->idfield;
525 sprintf(buf,"SELECT %s FROM %s WHERE %s.%s = 0",
526 vo->idfield, vo->table, vo->table, vo->idfield);
527 EXEC SQL PREPARE stmt FROM :buf;
528 EXEC SQL DESCRIBE stmt INTO SQLDA;
529 EXEC SQL DECLARE rcsr CURSOR FOR stmt;
530 EXEC SQL OPEN rcsr;
531 EXEC SQL FETCH rcsr USING DESCRIPTOR :SQLDA;
532 /* Check for no matching rows found - this is
533 * flagged as an internal error since the table should
534 * have a magic lock record.
535 */
536 if (sqlca.sqlcode == 100){
537 EXEC SQL CLOSE rcsr;
538 com_err(whoami,0,"readlock_table: no matching rows found for %s\n",
539 buf);
540 return(MR_INTERNAL);
541 }
542 EXEC SQL CLOSE rcsr;
543 if (ingres_errno)
544 return(mr_errcode);
545 if (sqlca.sqlcode)
546 return(vo->error);
547 return(MR_EXISTS); /* validate_fields expects us to return
548 * this value if everything went okay
549 */
550}
551
552/* Check the database at startup time. For now this just resets the
553 * inprogress flags that the DCM uses.
554 */
555
556sanity_check_database()
557{
558}
559
560
561/* Dynamic SQL support routines */
562MR_SQLDA_T *mr_alloc_SQLDA()
563{
564 MR_SQLDA_T *it;
565 short *null_indicators;
566 register int j;
567
568 if((it=(MR_SQLDA_T *)malloc(sizeof(MR_SQLDA_T)))==NULL) {
569 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
570 exit(1);
571 }
572
573 if((null_indicators=(short *)calloc(QMAXARGS,sizeof(short)))==NULL) {
574 com_err(whoami, MR_NO_MEM, "setting up SQLDA null indicators");
575 exit(1);
576 }
577
578 for(j=0; j<QMAXARGS; j++) {
579 if((it->sqlvar[j].sqldata=(char *)malloc(sizeof(short)+ARGLEN))==NULL) {
580 com_err(whoami, MR_NO_MEM, "setting up SQLDA variables");
581 exit(1);
582 }
583 it->sqlvar[j].sqllen=ARGLEN;
584 it->sqlvar[j].sqlind=null_indicators+j;
585 null_indicators[j]=0;
586 }
587 it->sqln=QMAXARGS;
588 return it;
589}
590
591
592/* Use this after FETCH USING DESCRIPTOR one or more
593 * result columns may contain NULLs. This routine is
594 * not currently needed, since db/schema creates all
595 * columns with a NOT NULL WITH DEFAULT clause.
596 *
597 * This is currently dead flesh, since no Moira columns
598 * allow null values; all use default values.
599 */
600mr_fix_nulls_in_SQLDA(da)
601 MR_SQLDA_T *da;
602{
603 register IISQLVAR *var;
604 register int j;
605 int *intp;
606
607 for(j=0, var=da->sqlvar; j<da->sqld; j++, var++) {
608 switch(var->sqltype) {
609 case -IISQ_CHA_TYPE:
610 if(*var->sqlind)
611 *var->sqldata='\0';
612 break;
613 case -IISQ_INT_TYPE:
614 if(*var->sqlind) {
615 intp=(int *)var->sqldata;
616 *intp=0;
617 }
618 break;
619 }
620 }
621}
622
623/* Convert normal Unix-style wildcards to SQL voodoo */
624convert_wildcards(arg)
625 char *arg;
626{
627 static char buffer[ARGLEN];
628 register char *s, *d;
629
630 for(d=buffer,s=arg;*s;s++) {
631 switch(*s) {
632 case '*': *d++='%'; *d++='%'; break;
633 case '?': *d++='_'; break;
634 case '_':
635 case '[':
636 case ']': *d++='*'; *d++ = *s; break;
637 case '%': *d++='*'; *d++='%'; *d++='%'; break;
638 default: *d++ = *s; break;
639 }
640 }
641 *d='\0';
642
643 /* Copy back into argv */
644 strcpy(arg,buffer);
645
646 return(MR_EXISTS);
647}
648
649/* This version includes uppercase conversion, for things like gmac.
650 * This is necessary because "LIKE" doesn't work with "uppercase()".
651 * Including it in a wildcard routine saves making two passes over
652 * the argument string.
653 */
654convert_wildcards_uppercase(arg)
655 char *arg;
656{
657 static char buffer[ARGLEN];
658 register char *s, *d;
659
660 for(d=buffer,s=arg;*s;s++) {
661 switch(*s) {
662 case '*': *d++='%'; *d++='%'; break;
663 case '?': *d++='_'; break;
664 case '_':
665 case '[':
666 case ']': *d++='*'; *d++ = *s; break;
667 case '%': *d++='*'; *d++='%'; *d++='%'; break;
668 default: *d++=toupper(*s); break; /* This is the only diff. */
669 }
670 }
671 *d='\0';
672
673 /* Copy back into argv */
674 strcpy(arg,buffer);
675
676 return(MR_EXISTS);
677}
678
679
680/* Looks like it's time to build an abstraction barrier, Yogi */
681mr_select_any(stmt)
682 EXEC SQL BEGIN DECLARE SECTION;
683 char *stmt;
684 EXEC SQL END DECLARE SECTION;
685{
686 int result=0;
687
688 EXEC SQL PREPARE stmt FROM :stmt;
689 EXEC SQL DESCRIBE stmt INTO :SQLDA;
690 if(SQLDA->sqld==0) /* Not a SELECT */
691 return(MR_INTERNAL);
692 EXEC SQL DECLARE csr CURSOR FOR stmt;
693 EXEC SQL OPEN csr;
694 EXEC SQL FETCH csr USING DESCRIPTOR :SQLDA;
695 if(sqlca.sqlcode==0)
696 result=MR_EXISTS;
697 else if((sqlca.sqlcode<0) && mr_errcode)
698 result=mr_errcode;
699 else
700 result=0;
701 EXEC SQL CLOSE csr;
702 return(result);
703}
704
705
706
707/* Adds a string to the string table. Returns the id number.
708 *
709 */
710int add_string(name)
711 EXEC SQL BEGIN DECLARE SECTION;
712 char *name;
713 EXEC SQL END DECLARE SECTION;
714{
715 EXEC SQL BEGIN DECLARE SECTION;
716 char buf[256];
717 int id;
718 EXEC SQL END DECLARE SECTION;
719
720 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
721 id++;
722 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
723
724 /* Use sprintf to get around problem with doubled single quotes */
725 sprintf(buf,"INSERT INTO strings (string_id, string) VALUES (%d, '%s')",id,name);
726 EXEC SQL EXECUTE IMMEDIATE :buf;
727
728 return(id);
729}
730
This page took 0.358105 seconds and 5 git commands to generate.