This commit is contained in:
Oliver Lehmann 1989-05-10 09:43:19 +00:00
parent d0b956355c
commit 9ace144589
2 changed files with 398 additions and 0 deletions

View File

@ -0,0 +1,173 @@
# include <stdio.h>
# include "gen.h"
# include "../h/dbs.h"
# include "../h/access.h"
# include "../h/aux.h"
# include "../h/tree.h"
# include "../h/symbol.h"
# include "../h/pipes.h"
# include "../h/bs.h"
# include "decomp.h"
int Newq; /* flags new user query to OVQP */
/*
** CALL_OVQP -- Routines which interface to the One Variable Query Processor.
**
** This file contains the routines associated with sending queries
** and receiving results from OVQP. The interface to these routines is
** still messy. Call_ovqp is given the query, mode, and result relation
** as parameters and gets the source relation, and two flags
** (Newq, Newr) as globals. The routines include:
**
** Call_ovqp -- Sends a One-var query to ovqp, flushes the pipe,
** and reads result from ovqp.
**
** Endovqp -- Informs ovqp that the query is over. Helps to synchronize
** the batch file (if any).
**
** Pipesym -- Writes a token symbol to ovqp.
**
**
** Call_ovqp -- send query down pipe to ovqp and flush pipe.
** Inputs are:
** mode retrieve, append, etc.
** resultnum result relation id
** qtree the query
** Sourcevar (global) if >= 0 then source var
** Newq send NEWQ symbol
** Newr send NEWR symbol
*/
call_ovqp(qtree, mode, resultnum)
QTREE *qtree;
int mode;
int resultnum;
{
register QTREE *tree;
register int i;
char *rangename();
struct retcode ret;
SYMBOL s;
int j;
tree = qtree;
# ifdef xDTR1
AAtTfp(8, 0, "CALL_OVQP\n");
if (AAtTf(8, 1))
{
if (Newq)
printree(tree, "new query to ovqp");
else
printf("query same as previous\n");
}
if (AAtTfp(8, 2, "Sourcevar=%d\t", Sourcevar))
{
if (Sourcevar >= 0)
printf("relid=%s\t", rangename(Sourcevar));
if (resultnum >= 0)
printf("Resultname=%s", rnum_convert(resultnum));
if (((ROOT_NODE *) tree)->rootuser)
printf(", userquery");
putchar('\n');
}
# endif
/* header information needed by OVQP for each query */
wrpipe(P_PRIME, &Outpipe, EXEC_OVQP, (char *) 0, 0);
pipesym(QMODE, sizeof (short), mode);
if (Newq)
pipesym(CHANGESTRAT, 0);
if (Newr)
{
pipesym(REOPENRES, 0);
Newr = FALSE;
}
if (Sourcevar >= 0)
{
s.type = SOURCEID;
s.len = MAXNAME;
wrpipe(P_NORM, &Outpipe, W_ovqp, &s, TYP_LEN_SIZ);
wrpipe(P_NORM, &Outpipe, W_ovqp, rangename(Sourcevar), MAXNAME);
}
if (resultnum >= 0)
{
s.type = RESULTID;
s.len = MAXNAME;
wrpipe(P_NORM, &Outpipe, W_ovqp, &s, TYP_LEN_SIZ);
wrpipe(P_NORM, &Outpipe, W_ovqp, rnum_convert(resultnum), MAXNAME);
}
/* this symbol, USERQRY, should be sent last because OVQP
* requires the query mode and result relation when it
* encounters USERQRY.
*/
if (((ROOT_NODE *) tree)->rootuser)
{
pipesym(USERQRY, 0);
}
/* now write the query list itself */
pipesym(TREE, 0);
if (tree->sym.type == AGHEAD)
{
pipesym(AGHEAD, 0);
if (tree->left->sym.type == BYHEAD)
{
mklist(tree->left->right);
pipesym(BYHEAD, 0);
mklist(tree->left->left);
}
else
mklist(tree->left);
}
else
mklist(tree->left);
pipesym(ROOT, 0);
mklist(tree->right);
pipesym(QLEND, 0);
/* now flush the query to ovqp */
wrpipe(P_FLUSH, &Outpipe, W_ovqp);
/*
** Read the result of the query from ovqp. A Retcode
** struct is expected.
** The possble values of Retcode.rt_status are:
** EMPTY -- no tuples satisfied
** NONEMPTY -- at least one tuple satisfied
** error num -- ovqp user error
*/
rdpipe(P_PRIME, &Inpipe);
if (rdpipe(P_NORM, &Inpipe, R_ovqp, &ret, sizeof (ret)) != sizeof (ret))
AAsyserr(12002);
j = ret.rc_status;
switch (j)
{
case EMPTY:
i = FALSE;
break;
case NONEMPTY:
i = TRUE;
if (((ROOT_NODE *) tree)->rootuser)
Retcode.rc_tupcount = ret.rc_tupcount;
break;
default:
derror(j);
}
return (i);
}

View File

@ -0,0 +1,225 @@
# include <stdio.h>
# include "gen.h"
# include "../h/dbs.h"
# include "../h/access.h"
# include "../h/aux.h"
# include "../h/tree.h"
# include "../h/symbol.h"
# include "../h/pipes.h"
# include "../h/bs.h"
# include "decomp.h"
/*
** Readagg_result -- read results from ovqp from a simple aggregate.
*/
readagg_result(result)
QTREE *result[];
{
register QTREE **r;
register QTREE *aop;
register int vallen;
int i;
r = result;
while (aop = *r++)
{
vallen = ctou(aop->sym.len);
if (rdpipe(P_NORM, &Inpipe, R_ovqp, &aop->sym, TYP_LEN_SIZ) != TYP_LEN_SIZ)
AAsyserr(12003);
if (vallen != ctou(aop->sym.len))
AAsyserr(12004, vallen, aop->sym.len);
if ((i = rdpipe(P_NORM, &Inpipe, R_ovqp, aop->sym.value, vallen)) != vallen)
AAsyserr(12005, i, vallen);
# ifdef xDTR1
if (AAtTf(8, 3))
writenod(aop);
# endif
}
}
/*
** Endovqp -- Inform ovqp that processing is complete. "Ack" indicates
** whether to wait for an acknowledgement from ovqp. The overall
** mode of the query is sent followed by an EXIT command.
**
** Ovqp decides whether to use batch update or not. If ack == ACK
** then endovqp will read a RETVAL symbol from ovqp and return
** a token which specifies whether to call the update processor or not.
*/
endovqp(ack)
int ack;
{
register int j;
struct retcode ret;
extern int Qry_mode;
extern DESC Inddes;
if (ack != RUBACK)
{
wrpipe(P_PRIME, &Outpipe, EXEC_OVQP, (char *) 0, 0);
/* send mode of the query */
pipesym(QMODE, sizeof (short), Qry_mode);
/* send exit code */
pipesym(EXIT, sizeof (short), ack);
wrpipe(P_END, &Outpipe, W_ovqp);
}
j = NOUPDATE;
if (ack == ACK)
{
/* read acknowledgement from ovqp */
rdpipe(P_PRIME, &Inpipe);
if (rdpipe(P_NORM, &Inpipe, R_ovqp, &ret, sizeof (ret)) != sizeof (ret))
AAsyserr(12006);
j = ret.rc_status;
if (j != UPDATE && j != NOUPDATE)
AAsyserr(12007, j);
rdpipe(P_SYNC, &Inpipe, R_ovqp);
}
cleanrel(&Inddes); /* could be closecatalog(FALSE) except for
** text space limitations */
return (j);
}
pipesym(token, length, val)
register int token;
register int length;
short val;
{
register SYMBOL *s;
char temp[TYP_LEN_SIZ];
s = (SYMBOL *) temp;
s->type = token;
s->len = length;
wrpipe(P_NORM, &Outpipe, W_ovqp, s, TYP_LEN_SIZ);
if (length)
wrpipe(P_NORM, &Outpipe, W_ovqp, &val, length);
}
ovqpnod(node)
QTREE *node;
{
register int typ;
register QTREE *q;
register SYMBOL *s;
short i;
register char *p;
char temp[SYM_HDR_SIZ + sizeof (short)];
extern QTREE *ckvar();
q = node;
s = (SYMBOL *) temp;
s->type = typ = q->sym.type;
switch (typ)
{
case VAR:
q = ckvar(q);
/* check to see if this variable has been substituted for.
** if so, pass the constant value to OVQP */
if (p = ((VAR_NODE *) q)->valptr)
{
s->type = ((VAR_NODE *) q)->frmt;
s->len = ((VAR_NODE *) q)->frml;
if (s->type == INT && s->len == sizeof (char))
{
s->len = sizeof (short);
i = ctoi(*p);
p = (char *) &i;
}
wrpipe(P_NORM, &Outpipe, W_ovqp, s, TYP_LEN_SIZ);
wrpipe(P_NORM, &Outpipe, W_ovqp, p, ctou(s->len));
return;
}
else
{
/* double check that variable is sourcevar */
if (((VAR_NODE *) q)->varno != Sourcevar)
AAsyserr(12008, Sourcevar, ((VAR_NODE *) q)->varno);
s->len = sizeof (short);
s->value[0] = ctou(((VAR_NODE *) q)->attno);
break;
}
case TREE:
return;
case AND:
case OR:
s->len = 0;
break;
case BOP:
case RESDOM:
case UOP:
s->len = OP_SIZ;
s->value[0] = *(q->sym.value);
break;
default:
wrpipe(P_NORM, &Outpipe, W_ovqp, &q->sym, TYP_LEN_SIZ);
if (i = ctou(q->sym.len))
wrpipe(P_NORM, &Outpipe, W_ovqp, q->sym.value, i);
return;
}
wrpipe(P_NORM, &Outpipe, W_ovqp, s, TYP_LEN_SIZ);
if (s->len)
wrpipe(P_NORM, &Outpipe, W_ovqp, s->value, s->len);
}
/*
** Use "AAinpclose()" for closing relations. See
** desc_close in openrs.c for details.
*/
extern int AAinpclose();
int (*Des_closefunc)() = AAinpclose;
init_decomp()
{
# ifdef XTRA
static ACCBUF xtrabufs[XTRABUFS];
AAam_addbuf(xtrabufs, XTRABUFS);
# endif
}
startdecomp()
{
/* called at the start of each user query */
Retcode.rc_tupcount = 0;
initrange();
rnum_init();
}
/*
** Files_avail -- returns how many file descriptors are available
** for decomposition. For decomp running by itself the fixed
** overhead for files is:
**
** 4 -- pipes
** 1 -- relation relation
** 1 -- attribute relation
** 1 -- AA_INDEX relation
** 1 -- standard output
** 1 -- concurrency
*/
files_avail()
{
return (MAXFILES - 9);
}