X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/b070f8a165363a81e0489a04992b0981e7a6d2f2..dcfa270ac1d2f55eb793c4da4bbd555903a88b09:/server/qrtn.dc diff --git a/server/qrtn.dc b/server/qrtn.dc index b2977470..154e4007 100644 --- a/server/qrtn.dc +++ b/server/qrtn.dc @@ -1,78 +1,116 @@ -/* $Header$ +/* + * $Source$ + * $Author$ + * $Header$ * - * Copyright (C) 1987, 1988, 1990 by the Massachusetts Institute of Technology - * For copying and distribution information, please see the file - * . + * Copyright (C) 1987, 1988 by the Massachusetts Institute of Technology + * For copying and distribution information, please see the file + * . + * */ #ifndef lint -static char *rcsid_qrtn_qc = "$Header$"; +static char *rcsid_qrtn_dc = "$Header$"; #endif lint #include +#include #include "query.h" #include "mr_server.h" -EXEC SQL INCLUDE sqlca; +EXEC SQL INCLUDE sqlca; /* SQL Communications Area */ +EXEC SQL INCLUDE sqlda; /* SQL Descriptor Area */ +#include "qrtn.h" + +MR_SQLDA_T *SQLDA; +EXEC SQL BEGIN DECLARE SECTION; +int mr_sig_length; +int idummy; +char cdummy[MR_CDUMMY_LEN]; +char stmt_buf[MR_STMTBUF_LEN]; +EXEC SQL END DECLARE SECTION; -char *Argv[16]; +char *Argv[QMAXARGS]; int ingres_errno = 0; int mr_errcode = 0; -EXEC SQL BEGIN DECLARE SECTION; +EXEC SQL BEGIN DECLARE SECTION; int query_timeout = 30; +char *database = "moira"; EXEC SQL END DECLARE SECTION; extern char *whoami; extern FILE *journal; -#define INGRES_BAD_INT 4111 -#define INGRES_BAD_DATE 4302 -#define INGRES_DEADLOCK 4700 -#define INGRES_TIMEOUT 4702 -#define INGRES_NO_RANGE 2109 +#define INGRES_BAD_DATE1 40206 +#define INGRES_BAD_DATE2 40207 +#define INGRES_DEADLOCK 49900 +#define INGRES_TIMEOUT 39100 +#define INGRES_BAD_COLUMN 30110 +#define INGRES_ASGN_ERR 40204 +#define INGRES_NO_CURSOR 30120 +#define INGRES_NO_STMT 30130 /* - * ingerr: (supposedly) called when Ingres indicates an error. - * I have not yet been able to get this to work to intercept a - * database open error. + * ingerr: Called when Ingres indicates an error. */ -static int ingerr() +void ingerr() { + EXEC SQL BEGIN DECLARE SECTION; + char err_msg[256]; + EXEC SQL END DECLARE SECTION; ingres_errno = -sqlca.sqlcode; switch (ingres_errno) { - case INGRES_BAD_INT: - mr_errcode = MR_INTEGER; - break; - case INGRES_BAD_DATE: + case INGRES_BAD_DATE1: + case INGRES_BAD_DATE2: mr_errcode = MR_DATE; break; - case INGRES_DEADLOCK: + case INGRES_DEADLOCK: mr_errcode = MR_DEADLOCK; com_err(whoami, 0, "INGRES deadlock detected"); break; - case INGRES_TIMEOUT: - mr_errcode = MR_BUSY; - com_err(whoami, 0, "timed out getting lock"); + case INGRES_TIMEOUT: +/* May be something other than timeout! #39100 is "Unknown error" + * Really should parse the error message enough to decide if it's a timeout */ + mr_errcode = MR_BUSY; + com_err(whoami, 0, "timed out getting lock"); + break; +/* These should never come up unless someone breaks the query table */ + case INGRES_NO_CURSOR: + if (mr_errcode != MR_BUSY && + mr_errcode != MR_DEADLOCK) + mr_errcode = MR_INTERNAL; + com_err(whoami, 0, "Cursor not opened"); break; - case INGRES_NO_RANGE: - mr_errcode = MR_INGRES_SOFTFAIL; - com_err(whoami, 0, "INGRES missing range statement"); + case INGRES_NO_STMT: + mr_errcode = MR_INTERNAL; + com_err(whoami, 0, "Statement not declared"); break; - default: + case INGRES_BAD_COLUMN: + mr_errcode = MR_INTERNAL; + com_err(whoami, 0, "Bad column name in query table"); + break; + case INGRES_ASGN_ERR: + mr_errcode = MR_INTERNAL; + com_err(whoami, 0, "Error in SQL assignment statement"); + break; +/* Others ??? */ + default: mr_errcode = MR_INGRES_ERR; com_err(whoami, MR_INGRES_ERR, " code %d\n", ingres_errno); - critical_alert("MOIRA", "Moira server encountered INGRES ERROR %d", - ingres_errno); - return (ingres_errno); + EXEC SQL INQUIRE_SQL(:err_msg = errortext); + com_err(whoami, 0, "SQL error text = %s", err_msg); + critical_alert("MOIRA", "Moira server encountered INGRES ERROR %d", ingres_errno); } - return (0); } +/* This is declarative, not executed. Applies from here on, in this file. */ +EXEC SQL WHENEVER SQLERROR CALL ingerr; + int mr_open_database() { register int i; - char *malloc(); + MR_SQLDA_T *mr_alloc_SQLDA(); static first_open = 1; if (first_open) { @@ -82,7 +120,8 @@ int mr_open_database() for (i = 0; i < 16; i++) Argv[i] = malloc(ARGLEN); - EXEC SQL WHENEVER SQLERROR CALL ingerr; + SQLDA = mr_alloc_SQLDA(); + incremental_init(); flush_cache(); } @@ -92,15 +131,26 @@ int mr_open_database() /* open the database */ #ifsql INGRES - EXEC SQL CONNECT sms; + EXEC SQL CONNECT :database; + if(ingres_errno) + return (ingres_errno); EXEC SQL set lockmode session where level = table, timeout = :query_timeout; EXEC SQL set lockmode on capacls where readlock = shared; EXEC SQL set lockmode on alias where readlock = shared; #endsql #ifsql INFORMIX - EXEC SQL DATABASE sms + EXEC SQL DATABASE moira #endsql - return ingres_errno; + + if(ingres_errno) + return(mr_errcode); + + EXEC SQL SELECT SIZE(signature) INTO :mr_sig_length FROM users WHERE users_id=0; /* Harmless on second open */ + EXEC SQL COMMIT WORK; + if(ingres_errno) + return(mr_errcode); + + return(MR_SUCCESS); } int mr_close_database() @@ -127,7 +177,7 @@ mr_check_access(cl, name, argc, argv_ro) if (q == (struct query *)0) return(MR_NO_HANDLE); - return(mr_verify_query(cl, q, argc, argv_ro)); + return(mr_verify_query(cl, q, argc, argv_ro)); } mr_process_query(cl, name, argc, argv_ro, action, actarg) @@ -145,9 +195,9 @@ mr_process_query(cl, name, argc, argv_ro, action, actarg) char sort[32]; char *pqual; char *psort; - EXEC SQL BEGIN DECLARE SECTION; + EXEC SQL BEGIN DECLARE SECTION; char *table_name; - EXEC SQL END DECLARE SECTION; + EXEC SQL END DECLARE SECTION; struct save_queue *sq; struct query *get_query_by_name(); int sq_save_args(); @@ -194,13 +244,13 @@ mr_process_query(cl, name, argc, argv_ro, action, actarg) /* for queries that do not permit wildcarding, check if row uniquely exists */ if (v && v->field) { - status = validate_row(q, Argv, v); + status = validate_row(q, Argv, v); if (status != MR_EXISTS) break; } /* build "where" clause if needed */ if (q->qual) { - build_qual(q->qual, q->argc, Argv, qual); + build_qual(q->qual, q->argc, Argv, qual); pqual = qual; } else { pqual = 0; @@ -252,11 +302,11 @@ mr_process_query(cl, name, argc, argv_ro, action, actarg) incremental_after(q->rtable, qual, argv_ro); if (status != MR_SUCCESS) break; flush_name(argv_ro[0], q->rtable); - tbl = q->rtable; + table_name = q->rtable; if (strcmp(q->shortname, "sshi") && strcmp(q->shortname, "ssif")) { EXEC SQL UPDATE tblstats - SET updates = updates + 1, modtime = "now" - WHERE tbl = :table_name; + SET updates = updates + 1, modtime = 'now' + WHERE table_name = :table_name; } } @@ -272,12 +322,6 @@ mr_process_query(cl, name, argc, argv_ro, action, actarg) if (status != MR_NO_MATCH) break; } - /* increment id number if necessary */ - if (v->object_id) { - status = set_next_object_id(v->object_id, q->rtable); - if (status != MR_SUCCESS) break; - } - /* build "where" clause if needed */ if (q->qual) { build_qual(q->qual, q->argc, Argv, qual); @@ -293,16 +337,16 @@ mr_process_query(cl, name, argc, argv_ro, action, actarg) status = do_append(q, &Argv[q->argc], pqual, action, actarg); if (status != MR_SUCCESS) break; if (v && v->object_id) { - sprintf(qual, "%s.%s = values.value and values.name = \"%s\"", - q->rvar, v->object_id, v->object_id); + sprintf(qual, "%s.%s = %s",q->rvar, v->object_id, + Argv[q->argc+q->vcnt]); incremental_after(q->rtable, qual, argv_ro); } else incremental_after(q->rtable, pqual, argv_ro); - tbl = q->rtable; + table_name = q->rtable; EXEC SQL UPDATE tblstats - SET appends = appends + 1, modtime = "now" - WHERE tbl = :table_name; + SET appends = appends + 1, modtime = 'now' + WHERE table_name = :table_name; } /* execute followup routine */ @@ -320,15 +364,15 @@ mr_process_query(cl, name, argc, argv_ro, action, actarg) /* if q->rvar = NULL, perform post_rtn only */ if (q->rvar) { build_qual(q->qual, q->argc, Argv, qual); - tbl = q->rtable; - incremental_before(q->rtable, qual, argv_ro); + table_name = q->rtable; + incremental_before(q->rtable, qual, argv_ro); status = do_delete(q, qual, action, actarg); incremental_clear_after(); if (status != MR_SUCCESS) break; flush_name(argv_ro[0], q->rtable); EXEC SQL UPDATE tblstats - SET deletes = deletes + 1, modtime = "now" - WHERE tbl = :table_name; + SET deletes = deletes + 1, modtime = 'now' + WHERE table_name = :table_name; } /* execute followup routine */ @@ -345,20 +389,10 @@ out: } if (q->type == RETRIEVE) { -#ifsql INGRES - EXEC SQL END TRANSACTION; -#endsql -#ifsql INFORMIX - EXEC SQL COMMIT WORK; -#endsql + EXEC SQL COMMIT WORK; } else { if (status == MR_SUCCESS) { -#ifsql INGRES - EXEC SQL END TRANSACTION; -#endsql -#ifsql INFORMIX - EXEC SQL COMMIT WORK; -#endsql + EXEC SQL COMMIT WORK; if (journal) { char buf[1024], *bp; int i; @@ -379,17 +413,14 @@ out: } incremental_update(); } else { + cache_abort(); if (ingres_errno != INGRES_DEADLOCK) { -#ifsql INGRES - EXEC SQL ABORT; -#endsql -#ifsql INFORMIX - EXEC SQL ROLLBACK WORK; -#endsql + EXEC SQL ROLLBACK WORK; } incremental_flush(); } } + cache_commit(); /* commit following abort is safe */ if (status != MR_SUCCESS && log_flags & LOG_RES) com_err(whoami, status, " (Query failed)"); @@ -405,7 +436,6 @@ build_qual(fmt, argc, argv, qual) register char *c; register int i; char *args[4]; - char *index(); c = fmt; for (i = 0; i < argc; i++) { @@ -418,6 +448,9 @@ build_qual(fmt, argc, argv, qual) else return(MR_INGRES_ERR); } + if (c = index(c, '%')) { + args[i] = args[i - 1]; + } switch (argc) { case 0: @@ -439,6 +472,11 @@ build_qual(fmt, argc, argv, qual) case 4: sprintf(qual, fmt, args[0], args[1], args[2], args[3]); break; + + default: + com_err(whoami, MR_INTERNAL, + "Internal arg count error processing query"); + return(MR_INTERNAL); } return(MR_SUCCESS); } @@ -451,6 +489,9 @@ build_sort(v, sort) register struct valobj *vo; register int n; char elem[16]; +#ifdef _DEBUG_MALLOC_INC +#undef index +#endif n = v->objcnt; vo = v->valobj; @@ -458,7 +499,7 @@ build_sort(v, sort) while (--n >= 0) { if (vo->type == V_SORT) { - sprintf(elem, "RET_VAR%d", vo->index + 1); + sprintf(elem, "%d", vo->index + 1); /* Result column number */ if (*sort) strcat(sort, ", "); strcat(sort, elem); } @@ -471,6 +512,8 @@ build_sort(v, sort) /* Build arguement vector, verify query and arguments */ +int privileged; + mr_verify_query(cl, q, argc, argv_ro) client *cl; struct query *q; @@ -481,18 +524,25 @@ mr_verify_query(cl, q, argc, argv_ro) register int status; register struct validate *v = q->validate; register int i; - register int privileged = 0; - int len; + register char *to,*fr,*stop; + + privileged = 0; /* copy the arguments into a local argv that we can modify */ if (argc >= QMAXARGS) return(MR_ARGS); for (i = 0; i < argc; i++) { - if ((len = strlen(argv_ro[i])) < ARGLEN) - strcpy(Argv[i], argv_ro[i]); - else - return(MR_ARG_TOO_LONG); - if (Argv[i][len-1] == '\\') + /* Single quotes must be doubled for SQL */ + for (to=Argv[i], fr=argv_ro[i], stop=to+ARGLEN; (*fr) && (toacl; else { name = q->shortname; - EXEC SQL SELECT list_id INTO :acl_id FROM capacls WHERE tag=:name; - if (sqlca.sqlcode < 0) return(MR_INGRES_ERR); - if (sqlca.sqlcode == 100) return(MR_PERM); + EXEC SQL SELECT list_id INTO :acl_id FROM capacls WHERE tag = :name; + if (sqlca.sqlcode < 0) return(MR_INGRES_ERR); + if (sqlca.sqlcode == 100) return(MR_PERM); q->acl = acl_id; /* check for default access */ - EXEC SQL SELECT member_id INTO :acl_id FROM imembers - WHERE list_id = :acl_id and member_type = "USER" and - member_id = :def_uid; - if (sqlca.sqlerrd[2] == 0) - q->everybody = 0; - else - q->everybody = 1; + EXEC SQL SELECT member_id INTO :acl_id FROM imembers + WHERE list_id = :acl_id AND member_type = 'USER' + AND member_id = :def_uid; + if (sqlca.sqlerrd[2] == 0) + q->everybody = 0; + else + q->everybody = 1; } if (q->everybody) @@ -603,16 +655,16 @@ get_client(cl, client_type, client_id) } find_member(list_type, list_id, member_type, member_id) -char *list_type; -EXEC SQL BEGIN DECLARE SECTION; -int list_id; -char *member_type; -int member_id; -EXEC SQL END DECLARE SECTION; + char *list_type; + EXEC SQL BEGIN DECLARE SECTION; + int list_id; + char *member_type; + int member_id; + EXEC SQL END DECLARE SECTION; { - EXEC SQL BEGIN DECLARE SECTION; + EXEC SQL BEGIN DECLARE SECTION; int flag, errorno; - EXEC SQL END DECLARE SECTION; + EXEC SQL END DECLARE SECTION; if (!strcmp(strtrim(list_type), strtrim(member_type)) && list_id == member_id) @@ -621,28 +673,26 @@ EXEC SQL END DECLARE SECTION; /* see if client is a direct member of list */ flag = 0; EXEC SQL SELECT member_id INTO :flag FROM imembers - WHERE list_id = :list_id and member_type = :member_type and - member_id = :member_id; + WHERE list_id = :list_id AND member_type = :member_type + AND member_id = :member_id; + if(flag!=0) flag=1; /** Not strictly necessary */ if (sqlca.sqlcode == 0) - return(flag); + return(flag); return(0); } -do_retrieve(q, pqual, psort, action, actarg) +do_retrieve(q, pqual, psort, action, actarg) register struct query *q; +EXEC SQL BEGIN DECLARE SECTION; char *pqual; char *psort; +EXEC SQL END DECLARE SECTION; int (*action)(); char *actarg; -##{ -## char *rvar; -## char *rtable; -## char *cqual; -## char *csort; -## int rowcount; -## int errorno; +{ static char **vaddrs = (char **)NULL; + int j, rowcount; if (!vaddrs) { register int i; @@ -651,56 +701,160 @@ do_retrieve(q, pqual, psort, action, actarg) com_err(whoami, MR_NO_MEM, "setting up static argv"); exit(1); } - for (i = 0; i < QMAXARGS; i++) { - if ((vaddrs[i] = malloc(QMAXARGSIZE)) == NULL) { - com_err(whoami, MR_NO_MEM, "setting up static argv"); - exit(1); - } + for (i = 0; i < QMAXARGS; i++) { + vaddrs[i]=SQLDA->sqlvar[i].sqldata; } } - if (q->rvar) { - rvar = q->rvar; - rtable = q->rtable; -## range of rvar is rtable + build_sql_stmt(stmt_buf,"SELECT",q->tlist,vaddrs,pqual); + if(psort) { strcat(stmt_buf," ORDER BY "); strcat(stmt_buf,psort); } + EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf; + if(sqlca.sqlcode) + return(MR_INTERNAL); + EXEC SQL DECLARE csr001 CURSOR FOR stmt; + EXEC SQL OPEN csr001; + rowcount = 0; + while(1) { + EXEC SQL FETCH csr001 USING DESCRIPTOR :SQLDA; + if(sqlca.sqlcode != 0) break; + (*action)(q->vcnt, vaddrs, actarg); + rowcount++; } + EXEC SQL CLOSE csr001; - if (psort) { - csort = psort; - if (pqual) { - cqual = pqual; -## retrieve unique (param (q->tlist, vaddrs)) where cqual -## sort by csort -## { - (*action)(q->vcnt, vaddrs, actarg); -## } - } else { -## retrieve unique (param (q->tlist, vaddrs)) -## sort by csort -## { - (*action)(q->vcnt, vaddrs, actarg); -## } + if (mr_errcode) return(mr_errcode); + return ((rowcount == 0) ? MR_NO_MATCH : MR_SUCCESS); +} + +char *sqlstrstr(str,pat) + char *str; + char *pat; +{ + register char *p=pat; + + do { + if(*str=='\'') { /* Skip over single-quote delimited substrings */ + while(*++str && (*str!='\'')) + ; + continue; + } + if(*str==*p) { + register char *s; + s=str; + while(*++p && (*++s==*p)) + ; + if(*p) p=pat; /* failed */ } + } while(*p && *++str); - } else { - if (pqual) { - cqual = pqual; -## retrieve unique (param (q->tlist, vaddrs)) where cqual -## { - (*action)(q->vcnt, vaddrs, actarg); -## } + if(!*str) str=NULL; + return(str); +} + +void optimize_sql_stmt(buf) +char *buf; +{ + char *point=buf, *pat, *eopat, *esc1, *esc2, *csr; + + for(point=buf; point=sqlstrstr(point,"LIKE"); point++) { + /* Now pointing to string "LIKE" */ + + /* Look at next word */ + for(pat=point+4; *pat==' '; pat++) ; + + /* Is it a single-quote delimited string? */ + if(*pat!='\'') continue; + + /* look for "escape" clause - save escape character */ + /* 1. Find end of pattern */ + for(eopat=pat+1; 1; eopat++) { + if(*eopat=='\'') { + if(eopat[1]=='\'') /* single-quote is self-escaping */ + eopat++; + else + break; + } + } + + /* 2. Look at next word */ + for(esc1=eopat; *++esc1==' ';) ; + + /* 3. esc1=0 if not "ESCAPE '?'", where the ? may be any character. */ + if(strncmp(esc1,"ESCAPE",6)) esc1=NULL; + + if(esc1) { + for(esc2=esc1+6; *esc2==' '; esc2++) ; + + if(*esc2++!='\'') continue; /* Bad SQL syntax. Skip. */ + /* esc2 now points at the escape character itself */ + if(esc2[1]!='\'') continue; /* Weird escape string. Skip. */ } else { -## retrieve unique (param (q->tlist, vaddrs)) -## { - (*action)(q->vcnt, vaddrs, actarg); -## } + esc2="\\"; + } + + /* Is pattern free from special characters? */ + for(csr=pat; csr % */ + *res++ = *fmt; + break; + case 's': + if(*argv[0]) { + *res='\0'; + strcat(res,*argv); + while(*++res) ; + } + argv++; + break; + case 'd': + sprintf(res,"%d",*(int *)*argv++); /* print to result buffer */ + while(*++res) ; + break; + default: /* Swallow other %? pairs */ + break; + } + } else break; + } else *res++ = *fmt; /* text -> result buffer */ + } + *res='\0'; + + optimize_sql_stmt(result_buf); +} do_update(q, argv, qual, action, actarg) register struct query *q; @@ -708,23 +862,12 @@ do_update(q, argv, qual, action, actarg) char *qual; int (*action)(); char *actarg; -##{ -## char *rvar; -## char *rtable; -## char *cqual; -## int errorno; - - rvar = q->rvar; - rtable = q->rtable; -## range of rvar is rtable - - cqual = qual; -## replace rvar (param (q->tlist, argv)) -## where cqual - +{ + build_sql_stmt(stmt_buf,"UPDATE",q->tlist,argv,qual); + EXEC SQL EXECUTE IMMEDIATE :stmt_buf; if (mr_errcode) return(mr_errcode); return(MR_SUCCESS); -##} +} do_append(q, argv, pqual, action, actarg) register struct query *q; @@ -732,48 +875,24 @@ do_append(q, argv, pqual, action, actarg) char *pqual; int (*action)(); char *actarg; -##{ -## char *rvar; -## char *rtable; -## char *cqual; -## int errorno; - - rvar = q->rvar; - rtable = q->rtable; -## range of rvar is rtable - - if (pqual) { - cqual = pqual; -## append to rtable (param (q->tlist, argv)) where cqual - } else { -## append to rtable (param (q->tlist, argv)) - } - +{ + build_sql_stmt(stmt_buf,"INSERT",q->tlist,argv,pqual); + EXEC SQL EXECUTE IMMEDIATE :stmt_buf; if (mr_errcode) return(mr_errcode); return(MR_SUCCESS); -##} +} do_delete(q, qual, action, actarg) register struct query *q; char *qual; int (*action)(); char *actarg; -##{ -## char *rvar; -## char *rtable; -## char *cqual; -## int errorno; - - rvar = q->rvar; - rtable = q->rtable; -## range of rvar is rtable - - cqual = qual; -## delete rvar where cqual - +{ + sprintf(stmt_buf,"DELETE FROM %s WHERE %s",q->rtable,qual); + EXEC SQL EXECUTE IMMEDIATE :stmt_buf; if (mr_errcode) return(mr_errcode); return(MR_SUCCESS); -##} +} /** @@ -781,45 +900,56 @@ do_delete(q, qual, action, actarg) ** ** Inputs: object - object name in values table and in objects ** table - name of table objects are found in + ** limit - should the ID be range limited ** ** - called before an APPEND operation to set the next object id to ** be used for the new record to the next free value ** **/ -set_next_object_id(object, table) -char *object; -char *table; +set_next_object_id(object, table_name, limit) + EXEC SQL BEGIN DECLARE SECTION; + char *object; + char *table_name; + int limit; + EXEC SQL END DECLARE SECTION; { - EXEC SQL BEGIN DECLARE SECTION; - char *name, *tbl, buf[257]; + EXEC SQL BEGIN DECLARE SECTION; int value; EXEC SQL END DECLARE SECTION; + int starting_value; + + EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :object; + if (sqlca.sqlerrd[2] != 1) + return(MR_NO_ID); - name = object; - tbl = table; - EXEC SQL SELECT value INTO :value FROM values_tbl WHERE name=:name; - if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1) - return(MR_NO_ID); - - EXEC SQL SELECT :name INTO :buf FROM :tbl WHERE :name = :value; - if (sqlca.sqlcode != 0 && sqlca.sqlcode != 100) - return(MR_NO_ID); + starting_value=value; + while (1) { + if (limit && value > MAX_ID_VALUE) + value = MIN_ID_VALUE; - while (sqlca.sqlerrd[2]) { + sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s=%d",object,table_name,object,value); + EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf; + if(sqlca.sqlcode) + return(MR_INTERNAL); + EXEC SQL DECLARE csr002 CURSOR FOR stmt; + EXEC SQL OPEN csr002; + EXEC SQL FETCH csr002 USING DESCRIPTOR :SQLDA; + if (sqlca.sqlcode < 0) return(mr_errcode); + if (sqlca.sqlcode == 100) break; + + EXEC SQL CLOSE csr002; value++; - if (value > MAX_ID_VALUE) - value = MIN_ID_VALUE; - EXEC SQL SELECT :name INTO :buf FROM :tbl WHERE :name = :value; - if (sqlca.sqlcode != 0 && sqlca.sqlcode != 100) - return(MR_NO_ID); + if (limit && value == starting_value) { + com_err(whoami,0,"All id values have been used"); + return(MR_NO_ID); + } } + EXEC SQL CLOSE csr002; if (LOG_RES) - com_err(whoami, 0, "setting ID %s to %d", name, value); - EXEC SQL UPDATE values_tbl SET value = :value WHERE name = :name; - if (sqlca.sqlcode != 0) - return(MR_NO_ID); + com_err(whoami, 0, "setting ID %s to %d", object, value); + EXEC SQL UPDATE numvalues SET value = :value WHERE name = :object; return(MR_SUCCESS); } @@ -835,22 +965,23 @@ int ok; int *kid; int *uid; { - EXEC SQL BEGIN DECLARE SECTION; - int u_id, k_id, rowcount; + EXEC SQL BEGIN DECLARE SECTION; + int u_id, k_id; char *krbname; - EXEC SQL END DECLARE SECTION; + EXEC SQL END DECLARE SECTION; krbname = name; *kid = 0; *uid = 0; - EXEC SQL SELECT krbmap.users_id, strings.string_id INTO :u_id, :k_id - FROM krbmap, strings - WHERE krbmap.string_id = strings.string_id and strings.string = :krbname; - rowcount = sqlca.sqlerrd[2]; + EXEC SQL SELECT km.users_id, km.string_id INTO :u_id, :k_id + FROM krbmap km, strings str + WHERE km.string_id = str.string_id AND str.string = :krbname; + EXEC SQL COMMIT WORK; + if (ingres_errno) return(mr_errcode); - if (rowcount == 1) { + if (sqlca.sqlerrd[2] == 1) { /* rowcount */ *kid = -k_id; *uid = u_id; return(MR_SUCCESS); @@ -859,7 +990,7 @@ int *uid; if (name_to_id(name, "STRINGS", &k_id) == MR_SUCCESS) *kid = -k_id; - if (!ok) { + if (!ok) { *uid = *kid; return(MR_SUCCESS); } @@ -907,3 +1038,5 @@ sanity_check_queries() exit(1); } } + +/* eof:qrtn.dc */