]> andersk Git - moira.git/blob - server/qvalidate.dc
Initial revision
[moira.git] / server / qvalidate.dc
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
13 static 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>
21 EXEC SQL INCLUDE sqlca;
22 EXEC SQL INCLUDE sqlda;
23 #include "qrtn.h"
24
25 extern char *whoami;
26 extern int ingres_errno, mr_errcode;
27
28 EXEC SQL BEGIN DECLARE SECTION;
29 extern char stmt_buf[];
30 EXEC SQL END DECLARE SECTION;
31
32 EXEC SQL WHENEVER SQLERROR CALL ingerr;
33
34
35 /* Validation Routines */
36
37 validate_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
72 validate_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  */
160 static 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
179 validate_chars(s)
180 register char *s;
181 {
182     while (*s)
183       if (illegalchars[*s++])
184         return(MR_BAD_CHAR);
185     return(MR_EXISTS);
186 }
187
188
189 validate_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
257 validate_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
290 validate_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
308 validate_rename(argv, vo)
309 char *argv[];
310 struct 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
358 validate_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
387 validate_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
476 lock_table(vo)
477 struct 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
494 sanity_check_database()
495 {
496 }
497
498
499 /* Dynamic SQL support routines */
500 MR_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  */
538 mr_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
573 prefetch_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  */
612 prefetch_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 */
634 convert_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  */
664 convert_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 */
691 mr_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  */
720 int 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.108468 seconds and 5 git commands to generate.