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