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