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];
/** Maybe this should be replaced by something like tytso's sql_error */
-#define INGRES_BAD_DATE1 41206
-#define INGRES_BAD_DATE2 40207
-#define INGRES_DEADLOCK 49900
-/*
-#define INGRES_BAD_INT
-#define INGRES_TIMEOUT
-#define INGRES_NO_RANGE
- */
+#define INGRES_BAD_DATE1 40206
+#define INGRES_BAD_DATE2 40207
+#define INGRES_DEADLOCK 49900
+#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.
*/
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_DATE1:
- case INGRES_BAD_DATE2:
+ 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;
* com_err(whoami, 0, "timed out getting lock");
* break;
*/
-/* This probably has no equivalent.
- * case INGRES_NO_RANGE:
- * mr_errcode = MR_INGRES_SOFTFAIL;
- * com_err(whoami, 0, "INGRES missing range statement");
- * break;
- */
+ case INGRES_NO_CURSOR:
+ mr_errcode = MR_INTERNAL;
+ com_err(whoami, 0, "Cursor not opened");
+ break;
+ 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:
+ 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;
+#endif
default:
- /** Add the INGRES error_text to the alert message ??? **/
mr_errcode = MR_INGRES_ERR;
- com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
+ com_err(whoami, MR_INGRES_ERR, " code %d\n", 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);
}
}
-/* This is declarative, not executed. Applies from here on, in the file */
+/* This is declarative, not executed. Applies from here on, in this file. */
EXEC SQL WHENEVER SQLERROR CALL ingerr;
int mr_open_database()
/* open the database */
#ifsql INGRES
EXEC SQL CONNECT moira;
+ 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;
#ifsql INFORMIX
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 */
+ if(ingres_errno)
+ return(mr_errcode);
+
+ return(MR_SUCCESS);
}
int mr_close_database()
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) {
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->rtable, v->object_id, v->object_id);
+ sprintf(qual, "%s.%s = %s",q->rtable, v->object_id,
+ Argv[q->argc+q->vcnt]);
incremental_after(q->rtable, qual, argv_ro);
} else
incremental_after(q->rtable, pqual, argv_ro);
register struct validate *v = q->validate;
register int i;
register int privileged = 0;
- int len;
+ register char *to,*fr,*stop;
/* 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);
}
com_err(whoami, MR_NO_MEM, "setting up static argv");
exit(1);
}
- for (i = 0; i < QMAXARGS; i++) {
+ for (i = 0; i < QMAXARGS; i++) {
vaddrs[i]=SQLDA->sqlvar[i].sqldata;
}
}
-/*
- * 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);
- * }
- * }
- *
- * } else {
- * if (pqual) {
- * cqual = pqual;
- * retrieve unique (param (q->tlist, vaddrs)) where cqual
- * {
- * (*action)(q->vcnt, vaddrs, actarg);
- * }
- * } else {
- * retrieve unique (param (q->tlist, vaddrs))
- * {
- * (*action)(q->vcnt, vaddrs, actarg);
- * }
- * }
- * }
- */
-
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((mr_errcode=mr_check_SQLDA(SQLDA)) != MR_SUCCESS)
- return(mr_errcode);
+ 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;
- mr_fix_nulls_in_SQLDA(SQLDA);
(*action)(q->vcnt, vaddrs, actarg);
rowcount++;
}
char *qual;
{
char fmt_buf[MR_STMTBUF_LEN];
- char tmp_buf[16];
- char *res=result_buf, *tmp=tmp_buf, *fmt=fmt_buf;
- int state;
-
- sprintf(fmt_buf,"%s %s",cmd,targetlist);
- if(qual) { strcat(fmt_buf," WHERE "); strcat(fmt_buf,qual); }
-
- for(state=0;*fmt != '\0';fmt++) {
- switch(state) {
- case 0:
- if(*fmt=='%') { /* formatting -> tmp */
- *tmp++ = *fmt;
- state=1;
- } else *res++ = *fmt; /* text -> res */
- break;
- case 1:
- if((*fmt=='%') && (tmp==tmp_buf+1)) { /* %% -> % */
- *res++ = *fmt;
- tmp=tmp_buf;
- state=0;
- } else if(isalpha(*fmt) && (*fmt!='h') && (*fmt!='l')) { /* end of formatting */
- *tmp++ = *fmt;
- *tmp='\0';
- tmp=tmp_buf;
- sprintf(res,tmp_buf,*argv++); /* print to result buffer */
- while(*res++) ;
- state=0;
- } else *tmp++ = *fmt; /* keep copying the formatting to tmp */
- break;
- }
+ 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';
}
EXEC SQL BEGIN DECLARE SECTION;
int value;
EXEC SQL END DECLARE SECTION;
- int rowcount=0;
-
+ int starting_value;
+
EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :object;
if (sqlca.sqlerrd[2] != 1)
return(MR_NO_ID);
-/*
- * retrieve (exists = any(tbl.name where tbl.name = value))
- */
- sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s=:value",object,table_name,object); /** Will this work??? */
- EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
- EXEC SQL DECLARE csr002 CURSOR FOR stmt;
-
- EXEC SQL OPEN csr002;
- EXEC SQL FETCH csr002 USING DESCRIPTOR :SQLDA;
- if(sqlca.sqlcode == 0) {
- rowcount++;
- EXEC SQL FETCH csr002 USING DESCRIPTOR :SQLDA;
- if(sqlca.sqlcode == 0) rowcount++;
- }
- EXEC SQL CLOSE csr002;
-
- if (rowcount != 1)
- return(MR_NO_ID);
+ starting_value=value;
while (1) {
- value++;
- if (limit && value > MAX_ID_VALUE) /* Potential infinite loop */
- value = MIN_ID_VALUE;
-/*
- * retrieve (exists = any(tbl.name where tbl.name = value))
- */
-
- /** Does the following work like I think it should ??? */
+ if (limit && value > MAX_ID_VALUE)
+ value = MIN_ID_VALUE;
+
+ 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 == 100) break;
+ 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 (limit && value == starting_value) {
+ com_err(whoami,0,"All id values have been used");
+ return(MR_NO_ID);
+ }
}
EXEC SQL CLOSE csr002;