This commit is contained in:
Oliver Lehmann 1989-04-03 20:05:58 +00:00
parent 723a8a21af
commit df0b6aa23b
3 changed files with 527 additions and 0 deletions

View File

@ -0,0 +1,239 @@
# include <stdio.h>
# 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);
}

View File

@ -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);
}

View File

@ -0,0 +1,171 @@
# include <stdio.h>
# 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);
}