]> andersk Git - moira.git/blame - server/qvalidate.pc
Add validation of numeric query arguments
[moira.git] / server / qvalidate.pc
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>
73cf66ba 18#include "mr_server.h"
03c05291 19#include "query.h"
73cf66ba 20#include <ctype.h>
03c05291 21#include <string.h>
73cf66ba 22EXEC SQL INCLUDE sqlca;
23EXEC SQL INCLUDE sqlda;
24#include "qrtn.h"
25
03c05291 26extern char *whoami, *table_name[], *sqlbuffer[QMAXARGS];
27extern int dbms_errno, mr_errcode;
73cf66ba 28
29EXEC SQL BEGIN DECLARE SECTION;
30extern char stmt_buf[];
31EXEC SQL END DECLARE SECTION;
32
03c05291 33int validate_chars(char *argv[], struct valobj *vo);
34int validate_id(struct query *, char *argv[], struct valobj *vo);
35int validate_name(char *argv[], struct valobj *vo);
36int validate_rename(char *argv[], struct valobj *vo);
37int validate_type(char *argv[], struct valobj *vo);
38int validate_typedata(struct query *, char *argv[], struct valobj *vo);
39int validate_len(char *argv[], struct valobj *vo);
f0e5d2fe 40int validate_num(char *argv[], struct valobj *vo);
03c05291 41int lock_table(struct valobj *vo);
42int readlock_table(struct valobj *vo);
43int convert_wildcards_uppercase(char *arg);
73cf66ba 44
960b073b 45extern SQLDA *sqlald(int,int,int);
46
03c05291 47EXEC SQL WHENEVER SQLERROR DO dbmserr();
73cf66ba 48
49/* Validation Routines */
50
03c05291 51int validate_row(q, argv, v)
73cf66ba 52 register struct query *q;
53 char *argv[];
54 register struct validate *v;
55{
56 EXEC SQL BEGIN DECLARE SECTION;
73cf66ba 57 char qual[128];
58 int rowcount;
59 EXEC SQL END DECLARE SECTION;
60
61 /* build where clause */
62 build_qual(v->qual, v->argc, argv, qual);
63
64 if (log_flags & LOG_VALID)
65 /* tell the logfile what we're doing */
66 com_err(whoami, 0, "validating row: %s", qual);
67
68 /* look for the record */
03c05291 69 sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s",
70 table_name[q->rtable],qual);
71 dosql(sqlbuffer);
72 if (dbms_errno) return(mr_errcode);
73
74 rowcount = atoi(sqlbuffer[0]);
73cf66ba 75 if (rowcount == 0) return(MR_NO_MATCH);
76 if (rowcount > 1) return(MR_NOT_UNIQUE);
77 return(MR_EXISTS);
78}
79
03c05291 80int validate_fields(q, argv, vo, n)
73cf66ba 81 struct query *q;
82 register char *argv[];
83 register struct valobj *vo;
84 register int n;
85{
86 register int status;
87
88 while (--n >= 0) {
89 switch (vo->type) {
90 case V_NAME:
91 if (log_flags & LOG_VALID)
92 com_err(whoami, 0, "validating %s in %s: %s",
03c05291 93 vo->namefield, table_name[vo->table], argv[vo->index]);
73cf66ba 94 status = validate_name(argv, vo);
95 break;
96
97 case V_ID:
98 if (log_flags & LOG_VALID)
99 com_err(whoami, 0, "validating %s in %s: %s",
03c05291 100 vo->idfield, table_name[vo->table], argv[vo->index]);
73cf66ba 101 status = validate_id(q, argv, vo);
102 break;
103
03c05291 104 /*
73cf66ba 105 case V_DATE:
106 if (log_flags & LOG_VALID)
107 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
108 status = validate_date(argv, vo);
109 break;
03c05291 110 */
73cf66ba 111
112 case V_TYPE:
113 if (log_flags & LOG_VALID)
114 com_err(whoami, 0, "validating %s type: %s",
03c05291 115 table_name[vo->table], argv[vo->index]);
73cf66ba 116 status = validate_type(argv, vo);
117 break;
118
119 case V_TYPEDATA:
120 if (log_flags & LOG_VALID)
121 com_err(whoami, 0, "validating typed data (%s): %s",
122 argv[vo->index - 1], argv[vo->index]);
123 status = validate_typedata(q, argv, vo);
124 break;
125
126 case V_RENAME:
127 if (log_flags & LOG_VALID)
128 com_err(whoami, 0, "validating rename %s in %s",
03c05291 129 argv[vo->index], table_name[vo->table]);
73cf66ba 130 status = validate_rename(argv, vo);
131 break;
132
133 case V_CHAR:
134 if (log_flags & LOG_VALID)
135 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
03c05291 136 status = validate_chars(argv, vo);
137 break;
138
139 case V_LEN:
140 if (log_flags & LOG_VALID)
141 com_err(whoami, 0, "validating length: %s", argv[vo->index]);
142 status = validate_len(argv, vo);
73cf66ba 143 break;
144
f0e5d2fe 145 case V_NUM:
146 if (log_flags & LOG_VALID)
147 com_err(whoami, 0, "validating number: %s", argv[vo->index]);
148 status = validate_num(argv, vo);
149 break;
150
73cf66ba 151 case V_LOCK:
152 status = lock_table(vo);
153 break;
154
03c05291 155 case V_RLOCK:
156 status = readlock_table(vo);
157 break;
158
159 case V_WILD:
73cf66ba 160 status = convert_wildcards(argv[vo->index]);
161 break;
162
163 case V_UPWILD:
164 status = convert_wildcards_uppercase(argv[vo->index]);
165 break;
166
167 }
168
169 if (status != MR_EXISTS) return(status);
170 vo++;
171 }
172
03c05291 173 if (dbms_errno) return(mr_errcode);
73cf66ba 174 return(MR_SUCCESS);
175}
176
177
178/* validate_chars: verify that there are no illegal characters in
179 * the string. Legal characters are printing chars other than
180 * ", *, ?, \, [ and ].
181 */
182static int illegalchars[] = {
183 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
184 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
185 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
186 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
187 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
188 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
190 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
191 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
192 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
193 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
194 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
195 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
196 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
197 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
198 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
199};
200
03c05291 201int validate_chars(argv, vo)
202 char *argv[];
203 register struct valobj *vo;
73cf66ba 204{
03c05291 205 char *s=argv[vo->index];
206 int arg;
207 EXEC SQL BEGIN DECLARE SECTION;
208 int len;
209 char *tname, *cname;
210 EXEC SQL END DECLARE SECTION;
211
212
213 /* check for bad characters */
73cf66ba 214 while (*s)
215 if (illegalchars[*s++])
216 return(MR_BAD_CHAR);
03c05291 217
218 /* check for length */
219 tname = table_name[vo->table];
220 cname = vo->namefield;
221 EXEC SQL SELECT data_length INTO :len FROM user_tab_columns
222 WHERE table_name=UPPER(:tname) AND column_name=UPPER(:cname);
223
224 if((strlen(argv[vo->index]) > len) &&
225 strcmp(argv[vo->index], UNIQUE_LOGIN)) /* kludge... sigh */
226 argv[vo->index][len]='\0'; /* truncate */
227
228 return MR_EXISTS;
73cf66ba 229}
230
231
03c05291 232int validate_id(q, argv, vo)
73cf66ba 233 struct query *q;
234 char *argv[];
235 register struct valobj *vo;
236{
237 EXEC SQL BEGIN DECLARE SECTION;
03c05291 238 char *name, *namefield, *idfield;
239 int id, rowcount, tbl;
73cf66ba 240 EXEC SQL END DECLARE SECTION;
241 int status;
242 register char *c;
243
244 name = argv[vo->index];
245 tbl = vo->table;
246 namefield = vo->namefield;
247 idfield = vo->idfield;
248
03c05291 249 if ((tbl==USERS_TABLE && !strcmp(namefield, "login")) ||
250 tbl==MACHINE_TABLE || tbl==SUBNET_TABLE || tbl==FILESYS_TABLE ||
251 tbl==LIST_TABLE || tbl==CLUSTER_TABLE || tbl==STRINGS_TABLE) {
252 if (tbl==MACHINE_TABLE || tbl==SUBNET_TABLE)
253 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
254 status = name_to_id(name, tbl, &id);
255 if (status == 0) {
256 *(int *)argv[vo->index] = id;
257 return(MR_EXISTS);
258 } else if (status == MR_NO_MATCH && tbl==STRINGS_TABLE &&
259 (q->type == APPEND || q->type == UPDATE)) {
260 id=add_string(name);
261 cache_entry(name, STRINGS_TABLE, id);
262 *(int *)argv[vo->index] = id;
263 return(MR_EXISTS);
264 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
265 return(vo->error);
266 else
267 return(status);
73cf66ba 268 } else {
03c05291 269 /* else, it's `dubu', which uses unix_uid from users */
270 EXEC SQL SELECT COUNT(*) INTO :rowcount FROM users
271 WHERE unix_uid = :name;
272 if (dbms_errno) return(mr_errcode);
273 if (rowcount != 1) return(vo->error);
274 EXEC SQL SELECT users_id INTO :id FROM users
275 WHERE unix_uid = :name;
276 *(int *)argv[vo->index] = id;
277 return(MR_EXISTS);
73cf66ba 278 }
73cf66ba 279}
280
03c05291 281int validate_name(argv, vo)
73cf66ba 282 char *argv[];
283 register struct valobj *vo;
284{
03c05291 285 char *name, *namefield;
73cf66ba 286 register char *c;
287
288 name = argv[vo->index];
73cf66ba 289 namefield = vo->namefield;
03c05291 290 if (vo->table==SERVERS_TABLE && !strcmp(namefield, "name")) {
73cf66ba 291 for (c = name; *c; c++)
292 if (islower(*c))
293 *c = toupper(*c);
294 }
295 sprintf(stmt_buf,"SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
03c05291 296 table_name[vo->table],table_name[vo->table],namefield,name);
297 dosql(sqlbuffer);
298
299 if (dbms_errno) return(mr_errcode);
300 return ((atoi(sqlbuffer[0]) == 1) ? MR_EXISTS : vo->error);
73cf66ba 301}
302
03c05291 303/*
73cf66ba 304validate_date(argv, vo)
305 char *argv[];
306 struct valobj *vo;
307{
308 EXEC SQL BEGIN DECLARE SECTION;
309 char *idate;
310 double dd;
311 int errorno;
312 EXEC SQL END DECLARE SECTION;
313
314 idate = argv[vo->index];
315 EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd;
73cf66ba 316 if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE);
317 return(MR_EXISTS);
318}
03c05291 319*/
73cf66ba 320
03c05291 321int validate_rename(argv, vo)
322 char *argv[];
323 struct valobj *vo;
73cf66ba 324{
325 EXEC SQL BEGIN DECLARE SECTION;
03c05291 326 char *name, *namefield, *idfield;
73cf66ba 327 int id;
328 EXEC SQL END DECLARE SECTION;
329 int status;
330 register char *c;
331
03c05291 332 status = validate_chars(argv, vo);
333 if(status != MR_EXISTS) return status;
334 name=argv[vo->index];
73cf66ba 335 /* minor kludge to upcasify machine names */
03c05291 336 if (vo->table == MACHINE_TABLE)
73cf66ba 337 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
338 namefield = vo->namefield;
339 idfield = vo->idfield;
340 id = -1;
341 if (idfield == 0) {
342 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
343 return(MR_EXISTS);
03c05291 344 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = '%s'",
345 namefield,table_name[vo->table],namefield,name);
346 dosql(sqlbuffer);
347
348 if (dbms_errno) return(mr_errcode);
349 if (sqlca.sqlcode==SQL_NO_MATCH)
350 return(MR_EXISTS); /* how's _that_ for intuitive? */
73cf66ba 351 else
03c05291 352 return(vo->error);
73cf66ba 353 }
03c05291 354 status = name_to_id(name, vo->table, &id);
73cf66ba 355 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
356 return(MR_EXISTS);
357 else
358 return(vo->error);
359}
360
361
03c05291 362int validate_type(argv, vo)
73cf66ba 363 char *argv[];
364 register struct valobj *vo;
365{
366 EXEC SQL BEGIN DECLARE SECTION;
367 char *typename;
368 char *val;
369 int cnt;
370 EXEC SQL END DECLARE SECTION;
371 register char *c;
372
03c05291 373 typename = vo->namefield;
73cf66ba 374 c = val = argv[vo->index];
375 while (*c) {
376 if (illegalchars[*c++])
377 return(MR_BAD_CHAR);
378 }
379
380 /* uppercase type fields */
381 for (c = val; *c; c++) if (islower(*c)) *c = toupper(*c);
382
383 EXEC SQL SELECT COUNT(trans) INTO :cnt FROM alias
384 WHERE name = :typename AND type='TYPE' AND trans = :val;
03c05291 385 if (dbms_errno) return(mr_errcode);
73cf66ba 386 return (cnt ? MR_EXISTS : vo->error);
387}
388
389/* validate member or type-specific data field */
390
03c05291 391int validate_typedata(q, argv, vo)
73cf66ba 392 register struct query *q;
393 register char *argv[];
394 register struct valobj *vo;
395{
396 EXEC SQL BEGIN DECLARE SECTION;
397 char *name;
398 char *field_type;
399 char data_type[129];
400 int id;
401 EXEC SQL END DECLARE SECTION;
402 int status;
73cf66ba 403 register char *c;
404
405 /* get named object */
406 name = argv[vo->index];
407
408 /* get field type string (known to be at index-1) */
409 field_type = argv[vo->index-1];
410
411 /* get corresponding data type associated with field type name */
412 EXEC SQL SELECT trans INTO :data_type FROM alias
413 WHERE name = :field_type AND type='TYPEDATA';
03c05291 414 if (dbms_errno) return(mr_errcode);
73cf66ba 415 if (sqlca.sqlerrd[2] != 1) return(MR_TYPE);
416
417 /* now retrieve the record id corresponding to the named object */
03c05291 418 if (strchr(data_type, ' '))
419 *strchr(data_type, ' ') = 0;
73cf66ba 420 if (!strcmp(data_type, "user")) {
421 /* USER */
03c05291 422 if (strchr(name, '@'))
73cf66ba 423 return(MR_USER);
03c05291 424 status = name_to_id(name, USERS_TABLE, &id);
73cf66ba 425 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
426 return(MR_USER);
427 if (status) return(status);
428 } else if (!strcmp(data_type, "list")) {
429 /* LIST */
03c05291 430 status = name_to_id(name, LIST_TABLE, &id);
73cf66ba 431 if (status && status == MR_NOT_UNIQUE)
432 return(MR_LIST);
433 if (status == MR_NO_MATCH) {
434 /* if idfield is non-zero, then if argv[0] matches the string
435 * that we're trying to resolve, we should get the value of
436 * numvalues.[idfield] for the id.
437 */
438 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
439 set_next_object_id(q->validate->object_id, q->rtable, 0);
440 name = vo->idfield;
03c05291 441 EXEC SQL SELECT value INTO :id FROM numvalues
73cf66ba 442 WHERE name = :name;
443 if (sqlca.sqlerrd[2] != 1) return(MR_LIST);
444 } else
445 return(MR_LIST);
446 } else if (status) return(status);
447 } else if (!strcmp(data_type, "machine")) {
448 /* MACHINE */
449 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
03c05291 450 status = name_to_id(name, MACHINE_TABLE, &id);
73cf66ba 451 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
452 return(MR_MACHINE);
453 if (status) return(status);
454 } else if (!strcmp(data_type, "string")) {
455 /* STRING */
03c05291 456 status = name_to_id(name, STRINGS_TABLE, &id);
73cf66ba 457 if (status && status == MR_NOT_UNIQUE)
458 return(MR_STRING);
459 if (status == MR_NO_MATCH) {
460 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
461 id=add_string(name);
03c05291 462 cache_entry(name, STRINGS_TABLE, id);
73cf66ba 463 } else if (status) return(status);
464 } else if (!strcmp(data_type, "none")) {
465 id = 0;
466 } else {
467 return(MR_TYPE);
468 }
469
470 /* now set value in argv */
471 *(int *)argv[vo->index] = id;
472
473 return (MR_EXISTS);
474}
475
476
03c05291 477/* Make sure the data fits in the field */
478int validate_len(argv, vo)
479 register char *argv[];
480 register struct valobj *vo;
481{
482 EXEC SQL BEGIN DECLARE SECTION;
483 int len;
484 char *tname, *cname;
485 EXEC SQL END DECLARE SECTION;
486
487 tname = table_name[vo->table];
488 cname = vo->namefield;
489 EXEC SQL SELECT data_length INTO :len FROM user_tab_columns
490 WHERE table_name=UPPER(:tname) AND column_name=UPPER(:cname);
491
492 if((strlen(argv[vo->index]) > len) &&
493 strcmp(argv[vo->index], UNIQUE_LOGIN)) /* kludge... sigh */
494 argv[vo->index][len]='\0'; /* truncate */
495
496 return MR_EXISTS;
497}
498
73cf66ba 499/* Lock the table named by the validation object */
500
03c05291 501int lock_table(vo)
502 struct valobj *vo;
73cf66ba 503{
03c05291 504#ifdef DO_LOCKING
505 sprintf(stmt_buf, "LOCK TABLE %s IN EXCLUSIVE MODE", table_name[vo->table]);
73cf66ba 506 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
03c05291 507 if (dbms_errno)
508 return(mr_errcode);
73cf66ba 509 else
03c05291 510#endif
73cf66ba 511 return(MR_EXISTS);
512}
513
03c05291 514/*
515 * Get a read lock on the table by accessing the magic lock
516 * record. Certain tables are constructed so that they contain
517 * an id field whose value is zero and a modtime field. We
518 * manipulate the modtime field of the id 0 record to effect
519 * locking of the table
73cf66ba 520 */
521
03c05291 522int readlock_table(vo)
523 struct valobj *vo;
73cf66ba 524{
03c05291 525#ifdef DO_LOCKING
526 sprintf(stmt_buf, "LOCK TABLE %s IN SHARE MODE", table_name[vo->table]);
527 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
528
529 if (dbms_errno)
530 return(mr_errcode);
531 if (sqlca.sqlcode)
532 return(vo->error);
533#endif
534 return(MR_EXISTS); /* validate_fields expects us to return
535 * this value if everything went okay
536 */
73cf66ba 537}
538
f0e5d2fe 539/* Make sure the data is numeric */
540int validate_num(argv, vo)
541 register char *argv[];
542 register struct valobj *vo;
543{
544 char *p = argv[vo->index];
545
546 if (*p == '-') p++;
547 for (;*p;p++)
548 if (*p < '0' || *p > '9') return MR_INTEGER;
549
550 return MR_EXISTS;
551}
552
695afd0d 553/* Check the database at startup time. */
03c05291 554
555void sanity_check_database(void)
556{
695afd0d 557 EXEC SQL BEGIN DECLARE SECTION;
558 int oid, id;
559 EXEC SQL END DECLARE SECTION;
560
561 /* Sometimes a crash can leave strings_id in numvalues in an
562 incorrect state. Check for that and fix it. */
563
564 EXEC SQL SELECT value INTO :oid FROM numvalues WHERE name='strings_id';
565
566 for (id=oid+1; sqlca.sqlcode==0; id++)
567 EXEC SQL SELECT string_id INTO :id FROM strings
568 WHERE string_id=:id;
569
570 if (id!=oid+1)
571 EXEC SQL UPDATE numvalues SET value=:id-1 WHERE name='strings_id';
03c05291 572}
573
574
575char *sqlbuffer[QMAXARGS];
73cf66ba 576
577/* Dynamic SQL support routines */
03c05291 578SQLDA *mr_alloc_sqlda()
73cf66ba 579{
03c05291 580 SQLDA *it;
73cf66ba 581 register int j;
582
03c05291 583 it=sqlald(QMAXARGS, ARGLEN, 0);
584 if(it==NULL) {
73cf66ba 585 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
586 exit(1);
587 }
588
73cf66ba 589 for(j=0; j<QMAXARGS; j++) {
03c05291 590 it->V[j]=sqlbuffer[j]=malloc(ARGLEN);
591 it->T[j]=97; /* 97 = CHARZ = null-terminated string */
592 it->L[j]=ARGLEN;
73cf66ba 593 }
03c05291 594
73cf66ba 595 return it;
596}
597
598
73cf66ba 599/* Convert normal Unix-style wildcards to SQL voodoo */
03c05291 600int convert_wildcards(arg)
73cf66ba 601 char *arg;
602{
603 static char buffer[ARGLEN];
604 register char *s, *d;
605
606 for(d=buffer,s=arg;*s;s++) {
607 switch(*s) {
608 case '*': *d++='%'; *d++='%'; break;
609 case '?': *d++='_'; break;
936820fd 610 case '_': *d++='*'; *d++ = *s; break;
73cf66ba 611 case '%': *d++='*'; *d++='%'; *d++='%'; break;
612 default: *d++ = *s; break;
613 }
614 }
615 *d='\0';
616
617 /* Copy back into argv */
618 strcpy(arg,buffer);
619
620 return(MR_EXISTS);
621}
622
623/* This version includes uppercase conversion, for things like gmac.
624 * This is necessary because "LIKE" doesn't work with "uppercase()".
625 * Including it in a wildcard routine saves making two passes over
626 * the argument string.
627 */
03c05291 628int convert_wildcards_uppercase(arg)
73cf66ba 629 char *arg;
630{
631 static char buffer[ARGLEN];
632 register char *s, *d;
633
634 for(d=buffer,s=arg;*s;s++) {
635 switch(*s) {
636 case '*': *d++='%'; *d++='%'; break;
637 case '?': *d++='_'; break;
936820fd 638 case '_': *d++='*'; *d++ = *s; break;
73cf66ba 639 case '%': *d++='*'; *d++='%'; *d++='%'; break;
640 default: *d++=toupper(*s); break; /* This is the only diff. */
641 }
642 }
643 *d='\0';
644
645 /* Copy back into argv */
646 strcpy(arg,buffer);
647
648 return(MR_EXISTS);
649}
650
651
73cf66ba 652/* Adds a string to the string table. Returns the id number.
653 *
654 */
655int add_string(name)
656 EXEC SQL BEGIN DECLARE SECTION;
657 char *name;
658 EXEC SQL END DECLARE SECTION;
659{
660 EXEC SQL BEGIN DECLARE SECTION;
661 char buf[256];
662 int id;
663 EXEC SQL END DECLARE SECTION;
664
665 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
666 id++;
667 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
668
03c05291 669 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
73cf66ba 670
671 return(id);
672}
This page took 0.448279 seconds and 5 git commands to generate.