From df0b6aa23ba9c12727607ce85ebdc2d17e62b25c Mon Sep 17 00:00:00 2001 From: Oliver Lehmann Date: Mon, 3 Apr 1989 20:05:58 +0000 Subject: [PATCH] ING_DB --- WEGA/contrib/ingres/dbs/src/ovqp/support.c | 239 +++++++++++++++++++ WEGA/contrib/ingres/dbs/src/parser/yyerror.y | 117 +++++++++ WEGA/contrib/ingres/dbs/src/qrymod/issue.c | 171 +++++++++++++ 3 files changed, 527 insertions(+) create mode 100644 WEGA/contrib/ingres/dbs/src/ovqp/support.c create mode 100644 WEGA/contrib/ingres/dbs/src/parser/yyerror.y create mode 100644 WEGA/contrib/ingres/dbs/src/qrymod/issue.c diff --git a/WEGA/contrib/ingres/dbs/src/ovqp/support.c b/WEGA/contrib/ingres/dbs/src/ovqp/support.c new file mode 100644 index 0000000..a4d9967 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/ovqp/support.c @@ -0,0 +1,239 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "../h/symbol.h" +# include "../h/tree.h" +# include "../h/pipes.h" +# include "../h/bs.h" +# include "ovqp.h" + +extern DESC Reldesc; +extern DESC Srcdesc; + +static DESC Indesc; + +/* +** Endqry is called at the end of a query, either +** in response to getqry receiving an EXIT or as a +** result of a user error +*/ +endqry(code) +int code; +{ + register int i; + + i = code; + + if (Eql && Retrieve) + eqleol(EXIT); /* signal end of query to EQL process */ + if (i == ACK) + { + if (Bopen) + i = UPDATE; + else + i = NOUPDATE; + + closeall(); + retdecomp(i); + } + else + { + if (i == NOACK) + { + if (Bopen) + { + /* remove the batch file */ + rmbatch(); + Bopen = FALSE; + } + } + else + AAsyserr(17025, code); + closeall(); + } +} + + + + +ov_err(code) +int code; +/* +** Usererr is called when a user generated +** error is detected. The error number is +** sent to DECOMP for processing. The read pipe +** is flushed. A non-local goto (reset) returns +** to main.c (see setexit()). +*/ +{ + retdecomp(code); /* send error message to decomp */ + endqry(NOACK); /* end the query with no ack to decomp */ + /* and close all relations */ + rdpipe(P_SYNC, &Inpipe, R_decomp); /* flush the pipe */ + + /* copy the error message from decomp to the parser */ + copyreturn(); + reset(); /* return to main.c */ + AAsyserr(17026); +} + + + +closeall() +{ + closerel(&Srcdesc); + closerel(&Reldesc); + closecatalog(FALSE); + closerel(&Indesc); + if (Bopen) + { + closebatch(); + Bopen = FALSE; + } +} + +retdecomp(code) +int code; +/* +** writes a RETVAL symbol with value "code". +** if code = EMPTY then retdecomp will wait +** for an EOP acknowledgement from DECOM before +** returning. +** If the query was a simple +** aggregate, then the aggregate values are also written. +*/ + +{ + struct retcode ret; + register int i; + register int t; + register int l; + register char *p; + struct stacksym ressym; + SYMBOL **alist; + struct _aop_ + { + char type; + char len; + int aoper; + char atype; + char alen; + }; + +# ifdef xOTR1 + AAtTfp(33, 1, "RETDECOMP: returning %d\n", code); +# endif + ret.rc_status = code; + ret.rc_tupcount = Tupsfound; + wrpipe(P_NORM, &Outpipe, W_decomp, &ret, sizeof (ret)); + + if (Alist && !Bylist) + { + alist = Alist; + i = Agcount; + Tend = Outtup; + + while (i--) + { + + /* find next AOP */ + while ((t = ((SYMBOL *) *++alist)->type) != AOP) + if (t == ROOT) + AAsyserr(17027, i); + + t = ((SYMBOL *) &ressym)->type = ((struct _aop_ *) *alist)->atype; + l = ((SYMBOL *) &ressym)->len = ((struct _aop_ *) *alist)->alen; + l = ctou(l); + p = (char *) ((SYMBOL *) &ressym)->value; + if (t == CHAR) + { + ((STRINGP *) p)->stringp = Tend; + /* make sure it is blank padded */ + AApad(Tend, l); + } + else + { + AAbmove(Tend, p, sizeof (double)); + if (t == INT && l == sizeof (char)) + ((I1TYPE *) p)->i1type = ((I2TYPE *) p)->i2type; +# ifndef NO_F4 + if (t == FLOAT && l == sizeof (float)) + ((F4TYPE *) p)->f4type = ((F8TYPE *) p)->f8type; +# endif + } + Tend += l; + +# ifdef xOTR1 + if (AAtTfp(33, 2, "returning aggregate:")) + prstack(&ressym); +# endif + /* write top of stack to decomp */ + pwritesym(&Outpipe, W_decomp, &ressym); + } + } + + wrpipe(P_END, &Outpipe, W_decomp); +} +openrel(desc, relname, mode) +DESC *desc; +char *relname; +int mode; + +/* +** openrel checks to see if the descriptor already +** holds the relation to be opened. If so it returns. +** Otherwise it closes the relation and opens the new one +*/ + +{ + register DESC *d; + register char *name; + register int i; + + d = desc; + name = relname; +# ifdef xOTR1 + AAtTfp(33, 4, "OPENREL: open=%d current=%.12s, new=%.12s\n", + d->relopn, d->reldum.relid, name); +# endif + + if (d->relopn) + { + if (AAbequal(d->reldum.relid, name, MAXNAME)) + return; +# ifdef xOTR1 + AAtTfp(33, 5, "OPENREL: closing the old\n"); +# endif + closerel(d); + } + if (i = AArelopen(d, mode, name)) + AAsyserr(17028, name, i); +} + + +closerel(desc) +DESC *desc; + +/* +** close the relation +*/ + +{ + register DESC *d; + register int i; + + d = desc; +# ifdef xOTR1 + AAtTfp(33, 6, "CLOSEREL: open=%d rel=%.12s\n", d->relopn, d->reldum.relid); +# endif + if (d->relopn) + if (i = AArelclose(d)) + AAsyserr(17029, d->reldum.relid, i); +} +DESC *openindex(relid) +char *relid; +{ + openrel(&Indesc, relid, 0); + return (&Indesc); +} diff --git a/WEGA/contrib/ingres/dbs/src/parser/yyerror.y b/WEGA/contrib/ingres/dbs/src/parser/yyerror.y new file mode 100644 index 0000000..73c6e46 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/parser/yyerror.y @@ -0,0 +1,117 @@ +/* +** This is the QL syntax-error diagnostic routine. Yyerror() is +** called whenever the parser is unable to recognize the syntax of a +** user query, or the scanner discovers a lexical error. +** It returns via reset(); +*/ + +/* +** The vector following is used to map error numbers for +** incomplete commands. The partial command is identified +** by 'Opflag' and is used to index the vector. The contents +** of the vector location is the error number. The 0 entries +** are for those command which can never be incomplete without +** generating a syntax error from the yacc parser. In other +** words, they should never happen. +*/ +int Messages[] = +{ + 0, /* mdRETTERM */ + 2502, /* mdRETR */ + 2503, /* mdAPP */ + 2504, /* mdREPL */ + 2505, /* mdDEL */ + 0, /* mdCOPY */ + 0, /* mdCREATE */ + 2506, /* mdDESTROY */ + 2507, /* mdHELP */ + 0, /* mdINDEX */ + 2508, /* mdMODIFY */ + 2509, /* mdPRINT */ + 0, /* mdRANGE */ + 0, /* mdSAVE */ + 0, /* mdDEFINE, not user specifiable */ + 2510, /* mdRET_UNI */ + 2511, /* mdVIEW */ + 0, /* mdUPDATE, not user specifiable */ + 0, /* mdRESETREL, not user specifiable */ + 2512, /* mdDISPLAY, help view, help integrity, help permit */ + 0, /* mdNETQRY, reserved for distr DBS */ + 0, /* mdMOVEREL, reserved for distr DBS */ + 2513, /* mdPROT */ + 2514, /* mdINTEG */ + 0, /* mdDCREATE, reserved for distr DBS */ + 0, /* mdWAITQRY, reserved for distr DBS */ + 2515 /* mdREMQM, destroy permit, destroy integrity */ +}; + +yyerror(num, a, b, c) +int num; +char *a, *b, *c; +{ + char buff[30]; + register char *buf; + extern char *AA_iocv(); + extern char *AA_locv(); + + buf = buff; + if (num == SYMERR || num == NXTCMDERR) + { + /* syntax error */ + a = buf; + b = 0; + switch (Lastok.toktyp) + { + case I2CONST: + AA_itoa(((I2TYPE *) Lastok.tok)->i2type, buf); + break; + + case I4CONST: + AAsmove(AA_locv(((I4TYPE *) Lastok.tok)->i4type), buf); + break; + +# ifndef NO_F4 + case F4CONST: + AA_ftoa(((F4TYPE *) Lastok.tok)->f4type, buf, 10, 3, 'n'); + break; +# endif + + case F8CONST: + AA_ftoa(((F8TYPE *) Lastok.tok)->f8type, buf, 10, 3, 'n'); + break; + + case SCONST: + AAsmove(Lastok.tok, buf); + break; + + case 0: + a = "EOF"; + break; + + default: + AAsyserr(18025); + } + } +# ifdef xPTR3 + AAtTfp(13, 0, "YYERROR: %d\n", num); +# endif + if (num == NXTCMDERR) + { + num = Messages[Opflag]; + b = 0; + } + error(num, AA_iocv(yyline), a, b, c, (char *) 0); + + /* clean up and sync with monitor */ + endgo(); + + /* execute non-local goto */ + reset(); +} + + +int neederr(errnum) +int errnum; +{ + yyerror(errnum, (char *) 0); +} diff --git a/WEGA/contrib/ingres/dbs/src/qrymod/issue.c b/WEGA/contrib/ingres/dbs/src/qrymod/issue.c new file mode 100644 index 0000000..6519ae7 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/qrymod/issue.c @@ -0,0 +1,171 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "../h/symbol.h" +# include "../h/tree.h" +# include "../h/pipes.h" +# include "qrymod.h" + +extern struct pipfrmt Outpipe; + +/* +** ISSUE -- issue query to rest of system +** +** This function issues a query to the rest of the DBS. +** It can deal with true queries (that is, a tree), or with a +** DBU request (which must already be in the pipe). +** +** The sync from below is read, but not passed up; a pointer +** to it (or NULL if none) is returned. +** +** Parameters: +** execid -- the execid to call. +** funcid -- the function to call. +** tree -- NULL -- just sync from below. +** else -- pointer to tree to issue. +** +** Returns: +** The resultcode of the query. +** +** Side Effects: +** A query is executed. +*/ +struct retcode *issue(execid, funcid, tree) +char execid; +char funcid; +QTREE *tree; +{ + register QTREE *t; + extern pipetrwr(); + static struct retcode rc; + register int i; + register struct retcode *r; + + t = tree; + r = &rc; + +# ifdef xQTR2 + AAtTfp(13, 1, "ISSUE:\n"); +# endif + + /* write query tree if given */ + if (t) + { + wrpipe(P_PRIME, &Outpipe, execid, (char *) 0, funcid); + writeqry(t, pipetrwr); + wrpipe(P_END, &Outpipe, W_down); + fflush(stdout); + } + + /* sync with below */ +# ifdef xQTR2 + AAtTfp(13, 2, "ISSUE: response:\n"); +# endif + rdpipe(P_PRIME, &Outpipe); + i = rdpipe(P_NORM, &Outpipe, R_down, r, sizeof *r); + rdpipe(P_SYNC, &Outpipe, R_down); + if (i == 0) + return ((struct retcode *) 0); + else + return (r); +} + + +/* +** ISSUEINVERT -- issue a query, but invert the qualification +** +** This routine is similar to 'issue', except that it issues +** a query with the qualification inverted. The inversion +** (and subsequent tree normalization) is done on a duplicate +** of the tree. +** +** Parameters: +** root -- the root of the tree to issue. +** +** Returns: +** pointer to retcode struct. +*/ +struct retcode *issueinvert(root) +QTREE *root; +{ + register QTREE *t; + extern QTREE *tree(); + extern QTREE *treedup(); + extern QTREE *trimqlend(); + extern QTREE *norml(); + register struct retcode *r; + extern struct retcode *issue(); + + /* make duplicate of tree */ + t = treedup(root); + + /* prepend NOT node to qualification */ + t->right = tree((QTREE *) 0, t->right, UOP, OP_SIZ, opNOT); + + /* normalize and issue */ + t->right = norml(trimqlend(t->right)); + r = issue(EXEC_DECOMP, 0, t); + +# ifdef xQTR3 + /* check for valid return */ + if (!r) + AAsyserr(19040); +# endif + + return (r); +} + + +/* +** PIPETRWR -- write tree to W_down pipe +** +** Acts like a 'wrpipe' call, with some arguments included +** implicitly. +** +** Parameters: +** val -- the value to write. +** len -- the length. +** +** Returns: +** same as wrpipe. +*/ +pipetrwr(val, len) +register char *val; +register int len; +{ + return (wrpipe(P_NORM, &Outpipe, W_down, val, len)); +} + + +/* +** NULLSYNC -- send null query to sync EQL program +** +** On a RETRIEVE to terminal, EQL is left reading the data +** pipe by the time we get to this point; on an error (which +** will prevent the running of the original query) we must +** somehow unhang it. The solution is to send a completely +** null query, as so: +** +** ROOT +** / \ +** TREE QLEND +** +** This will cause OVQP to send a sync back to the EQL program, +** incuring an incredible amount of overhead in the process +** (but it was his own fault!). +** +** Side Effects: +** A query is sent. +*/ +struct retcode *nullsync() +{ + register QTREE *t; + extern struct retcode *issue(); + register struct retcode *rc; + extern QTREE *tree(); + + t = tree(tree((QTREE *) 0, (QTREE *) 0, TREE, 0), tree((QTREE *) 0, (QTREE *) 0, QLEND, 0), ROOT, 0); + rc = issue(EXEC_DECOMP, '0', t); + return (rc); +}