]> andersk Git - moira.git/blobdiff - server/qrtn.dc
missing stubs
[moira.git] / server / qrtn.dc
index a5c10f8849f4a769c99890a4aa48e4c36efac894..f76e8df80a39ed9e499e0617457709d63ba4a51f 100644 (file)
-/* $Header$
+/*
+ *     $Source$
+ *     $Author$
+ *     $Header$
  *
- * Copyright (C) 1987, 1988, 1990 by the Massachusetts Institute of Technology
- * For copying and distribution information, please see the file
- * <mit-copyright.h>.
+ *     Copyright (C) 1987, 1988 by the Massachusetts Institute of Technology
+ *     For copying and distribution information, please see the file
+ *     <mit-copyright.h>.
+ * 
  */
 
 #ifndef lint
-static char *rcsid_qrtn_qc = "$Header$";
+static char *rcsid_qrtn_dc = "$Header$";
 #endif lint
 
 #include <mit-copyright.h>
+#include <string.h>
 #include "query.h"
 #include "mr_server.h"
 EXEC SQL INCLUDE sqlca;  /* SQL Communications Area */
-EXEC SQL INCLUDE SQLDA;  /* SQL Descriptor 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) {
@@ -83,7 +121,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();
     }
@@ -93,15 +132,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()
@@ -128,7 +178,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)
@@ -146,9 +196,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();
@@ -195,13 +245,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;
@@ -253,11 +303,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;
            }
        }
 
@@ -273,12 +323,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);
@@ -294,16 +338,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 */
@@ -321,15 +365,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 */
@@ -346,20 +390,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;
@@ -380,17 +414,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)");
@@ -419,6 +450,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:
@@ -440,6 +474,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);
 }
@@ -459,7 +498,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);
        }
@@ -472,6 +511,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;
@@ -482,18 +523,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) && (to<stop);) {
+           if(*fr=='\'') 
+             *to++ = *fr;
+           *to++ = *fr++;
+       }
+       if (*fr) 
+         return(MR_ARG_TOO_LONG);
+       *to='\0';
+
+       if (*--to == '\\')
          return(MR_BAD_CHAR);
     }
 
@@ -521,7 +569,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);
@@ -537,18 +585,20 @@ check_query_access(q, argv, cl)
     char *argv[];
     client *cl;
 {
-    EXEC SQL BEGIN DECLARE SECTION;
+    EXEC SQL BEGIN DECLARE SECTION; 
     char *name;
     int acl_id;
+    int rowcount;
+    int errorno;
     static int def_uid;
-    EXEC SQL END DECLARE SECTION;
+    EXEC SQL END DECLARE SECTION; 
     int status;
     int client_id;
     char *client_type;
 
     /* initialize default uid */
     if (def_uid == 0) {
-       EXEC SQL SELECT users_id INTO :def_uid FROM users WHERE login="default";
+        EXEC SQL SELECT users_id INTO :def_uid FROM users WHERE login='default';
     }
 
     /* get query access control list */
@@ -556,19 +606,19 @@ check_query_access(q, argv, cl)
       acl_id = q->acl;
     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)
@@ -604,16 +654,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)
@@ -622,28 +672,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;
@@ -652,56 +700,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<eopat; csr++) 
+           if((*csr=='%') || (*csr=='_') || (*csr==*esc2)) break;
+       if(csr!=eopat) continue; /* Uses pattern matching. Skip. */
+
+       /* Optimize the query statement */
+       /* 1. Change "LIKE" to " =  " */
+       memcpy(point," =  ",4);
+       
+       /* 2. Change "ESCAPE" to "      " */
+       if(esc1) {
+           memset(esc1,' ',6);
+           /* 3. Change  "'*'" to "   " */
+           /*    (Changes '''' to "    ") */
+           if(esc2) memset(esc2-1,' ',(*esc2=='\'')?4:3); 
        }
     }
+}
 
-    if (mr_errcode) return(mr_errcode);
-##  inquire_equel (rowcount = "rowcount")
-    return ((rowcount == 0) ? MR_NO_MATCH : MR_SUCCESS);
-##}
+build_sql_stmt(result_buf,cmd,targetlist,argv,qual)
+    char *result_buf;
+    char *cmd;
+    char *targetlist;
+    char *argv[];
+    char *qual;
+{
+    char fmt_buf[MR_STMTBUF_LEN];
+    register char *res, *fmt;
+
+    if(qual)
+      sprintf(fmt_buf,"%s %s WHERE %s",cmd,targetlist,qual);
+    else
+      sprintf(fmt_buf,"%s %s",cmd,targetlist);
+
+    for(res=result_buf, fmt=fmt_buf; *fmt; fmt++) {
+       if(*fmt=='%') {
+           if(*++fmt) {
+               switch(*fmt) {                       
+                 case '%':                              /* %% -> % */
+                   *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;
@@ -709,23 +861,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;
@@ -733,48 +874,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);
-##}
+}
 
 
 /**
@@ -782,59 +899,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;
-    char stmt_1_str[256];
     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);
 
-    EXEC SQL DECLARE stmt_1 STATEMENT;
-    EXEC SQL DECLARE cursor_1 CURSOR FOR stmt_1;
-
-    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);
-
-    sprintf(stmt_t_str, "SELECT %s INTO %s FROM %s WHERE %s = %d",
-           name, buf, tbl, name, value);
-
-    EXEC SQL PREPARE stmt_1 FROM :stmt_1_str;
-    EXEC SQL DESCRIBE stnt_1 INTO SQLDA;
-/*  EXEC SQL EXECUTE stmt_1;  -- wait on this use a cursor instead */
-
-    EXEC SQL OPEN cursor_1;
-    EXEC SQL FETCH cursor_1 USING DESCRIPTOR SQLDA;
-    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 (1) {
+       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 FETCH cursor_1 USING DESCRIPTOR SQLDA;
-       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 cursor_1;
+    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);
 }
 
@@ -850,22 +964,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);
@@ -874,7 +989,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);
     }
@@ -922,3 +1037,5 @@ sanity_check_queries()
        exit(1);
     }
 }
+
+/* eof:qrtn.dc */
This page took 0.223914 seconds and 4 git commands to generate.