X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/fbeb0263ec14eab847fe2f7471a3a5369dbcb26d..refs/heads/LOCKING:/server/qrtn.dc diff --git a/server/qrtn.dc b/server/qrtn.dc index 57d44c37..154e4007 100644 --- a/server/qrtn.dc +++ b/server/qrtn.dc @@ -14,6 +14,7 @@ static char *rcsid_qrtn_dc = "$Header$"; #endif lint #include +#include #include "query.h" #include "mr_server.h" EXEC SQL INCLUDE sqlca; /* SQL Communications Area */ @@ -28,22 +29,21 @@ 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; int query_timeout = 30; +char *database = "moira"; EXEC SQL END DECLARE SECTION; extern char *whoami; extern FILE *journal; -/** Maybe this should be replaced by something like tytso's sql_error */ - #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 @@ -69,32 +69,33 @@ void ingerr() mr_errcode = MR_DEADLOCK; com_err(whoami, 0, "INGRES deadlock detected"); break; -/* I just don't know what the equivalent to this is, yet. - * case INGRES_TIMEOUT: - * mr_errcode = MR_BUSY; - * com_err(whoami, 0, "timed out getting lock"); - * break; - */ - case INGRES_NO_CURSOR: - mr_errcode = MR_INTERNAL; + 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_STMT: + case INGRES_NO_STMT: mr_errcode = MR_INTERNAL; com_err(whoami, 0, "Statement not declared"); break; -#if 0 - /* Taking these out during development lets default: give me the INGRES text */ - case INGRES_BAD_COLUMN: + case INGRES_BAD_COLUMN: mr_errcode = MR_INTERNAL; com_err(whoami, 0, "Bad column name in query table"); break; - case INGRES_ASGN_ERR: + case INGRES_ASGN_ERR: mr_errcode = MR_INTERNAL; com_err(whoami, 0, "Error in SQL assignment statement"); break; -#endif - default: +/* Others ??? */ + default: mr_errcode = MR_INGRES_ERR; com_err(whoami, MR_INGRES_ERR, " code %d\n", ingres_errno); EXEC SQL INQUIRE_SQL(:err_msg = errortext); @@ -109,7 +110,6 @@ 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; @@ -131,7 +131,7 @@ int mr_open_database() /* open the database */ #ifsql INGRES - EXEC SQL CONNECT moira; + EXEC SQL CONNECT :database; if(ingres_errno) return (ingres_errno); EXEC SQL set lockmode session where level = table, timeout = :query_timeout; @@ -146,6 +146,7 @@ int mr_open_database() 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); @@ -321,16 +322,6 @@ mr_process_query(cl, name, argc, argv_ro, action, actarg) if (status != MR_NO_MATCH) break; } -#ifdef NEVER - /* This is now done by a valobj, which also fetches the id value */ - - /* increment id number if necessary */ - if (v->object_id) { - status = set_next_object_id(v->object_id, q->rtable, 0); - if (status != MR_SUCCESS) break; - } -#endif - /* build "where" clause if needed */ if (q->qual) { build_qual(q->qual, q->argc, Argv, qual); @@ -346,7 +337,7 @@ 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 = %s",q->rtable, 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 @@ -445,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++) { @@ -499,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; @@ -519,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; @@ -529,9 +524,10 @@ mr_verify_query(cl, q, argc, argv_ro) register int status; register struct validate *v = q->validate; register int i; - register int privileged = 0; register char *to,*fr,*stop; + privileged = 0; + /* copy the arguments into a local argv that we can modify */ if (argc >= QMAXARGS) return(MR_ARGS); @@ -574,7 +570,7 @@ mr_verify_query(cl, q, argc, argv_ro) if (status != MR_SUCCESS && status != MR_PERM) return(status); if (status == MR_SUCCESS) - privileged++; + return(MR_SUCCESS); } return(privileged ? MR_SUCCESS : MR_PERM); @@ -730,6 +726,91 @@ EXEC SQL END DECLARE SECTION; 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); + + 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 { + esc2="\\"; + } + + /* Is pattern free from special characters? */ + for(csr=pat; csr result buffer */ } *res='\0'; + + optimize_sql_stmt(result_buf); } do_update(q, argv, qual, action, actarg) @@ -894,6 +977,7 @@ int *uid; 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);