]> andersk Git - moira.git/blob - server/qvalidate.c
Used /bin/sh format instead of /bin/csh format, by accident.
[moira.git] / server / qvalidate.c
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 #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
43 validate_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
78 validate_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  */
172 static 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
191 validate_chars(s)
192 register char *s;
193 {
194     while (*s)
195       if (illegalchars[*s++])
196         return(MR_BAD_CHAR);
197     return(MR_EXISTS);
198 }
199
200
201 validate_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
269 validate_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
302 validate_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
320 validate_rename(argv, vo)
321 char *argv[];
322 struct 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
370 validate_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
399 validate_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
487 lock_table(vo)
488 struct 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
514 readlock_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
556 sanity_check_database()
557 {
558 }
559
560
561 /* Dynamic SQL support routines */
562 MR_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  */
600 mr_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 */
624 convert_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  */
654 convert_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 */
681 mr_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  */
710 int 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.421766 seconds and 5 git commands to generate.