-/* $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;
+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) {
for (i = 0; i < 16; i++)
Argv[i] = malloc(ARGLEN);
- EXEC SQL WHENEVER SQLERROR CALL ingerr;
+ SQLDA = mr_alloc_SQLDA();
+
incremental_init();
flush_cache();
}
/* 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()
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)
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();
/* 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;
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;
}
}
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);
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 */
/* 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 */
}
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;
}
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)");
register char *c;
register int i;
char *args[4];
- char *index();
c = fmt;
for (i = 0; i < argc; i++) {
else
return(MR_INGRES_ERR);
}
+ if (c = index(c, '%')) {
+ args[i] = args[i - 1];
+ }
switch (argc) {
case 0:
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);
}
register struct valobj *vo;
register int n;
char elem[16];
+#ifdef _DEBUG_MALLOC_INC
+#undef index
+#endif
n = v->objcnt;
vo = v->valobj;
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);
}
/* Build arguement vector, verify query and arguments */
+int privileged;
+
mr_verify_query(cl, q, argc, argv_ro)
client *cl;
struct query *q;
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);
}
if (status != MR_SUCCESS && status != MR_PERM)
return(status);
if (status == MR_SUCCESS)
- privileged++;
+ return(MR_SUCCESS);
}
return(privileged ? MR_SUCCESS : MR_PERM);
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 */
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)
}
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)
/* 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;
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;
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;
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);
-##}
+}
/**
**
** 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);
}
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);
if (name_to_id(name, "STRINGS", &k_id) == MR_SUCCESS)
*kid = -k_id;
- if (!ok) {
+ if (!ok) {
*uid = *kid;
return(MR_SUCCESS);
}
exit(1);
}
}
+
+/* eof:qrtn.dc */