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