4.3BSD/usr/ingres/source/ovqp/scan.c
# include <ingres.h>
# include <symbol.h>
# include <tree.h>
# include "../decomp/globs.h"
# include <sccs.h>
SCCSID(@(#)scan.c 8.1 12/31/84)
/*
** SCAN
**
** performs tuple by tuple scan of source reln or index reln
** within limits found by strategy routine.
** When the source reln tuple is obtained the interpreter is invoked
** to continue further processing
**
*/
scan()
{
register j, mode, domno;
struct symbol **rlist; /* "result" list of query */
long count;
long tid, temptid;
char agtup[MAXTUP], outtup1[MAXTUP];
int qualfound, ok, istarget;
struct symbol *interpret();
int getnxt;
long pageid, lpageid;
# ifdef xOTR1
if (tTf(71, -1))
{
printf("SCAN\tScanr=%.12s\n", De.ov_scanr ? De.ov_scanr->reldum.relid : "(none)");
printf("\tDe.ov_result %x\n", De.ov_result);
if (tTf(71, 4))
printf(" De.ov_alist=%x, De.ov_bylist=%x, De.ov_tlist=%x, De.ov_qlist=%x\n", De.ov_alist, De.ov_bylist, De.ov_tlist, De.ov_qlist);
if (De.ov_result)
printdesc(De.ov_result);
}
# endif
if (De.ov_result || De.ov_alist)
{
if (De.ov_result)
{
clr_tuple(De.ov_result, De.ov_outtup);
}
else
{
j = MAXTUP;
while (j--)
De.ov_outtup[j] = 0;
}
}
count = 0;
qualfound = EMPTY;
mode = De.de_qmode;
/*
** Check for identical source and result relations.
** For modes mdREPL and mdDEL, De.ov_origtup must point
** to the original (unmodified result tuple).
**
** If there is no De.ov_source or De.ov_result relations then
** the code has no effect.
*/
if (De.ov_source == NULL ||
!bequal(De.ov_source->reldum.relid, De.ov_result->reldum.relid, MAXNAME))
{
De.ov_diffrel = TRUE;
De.ov_origtup = outtup1;
}
else
{
De.ov_diffrel = FALSE;
De.ov_origtup = De.ov_intup;
}
/* determine type of result list */
/* the only valid combinations are:
**
** De.ov_tlist=no De.ov_alist=no De.ov_bylist=no
** De.ov_tlist=yes De.ov_alist=no De.ov_bylist=no
** De.ov_tlist=no De.ov_alist=yes De.ov_bylist=no
** De.ov_tlist=no De.ov_alist=yes De.ov_bylist=yes
*/
if (De.ov_tlist)
istarget = TRUE;
else
istarget = FALSE;
rlist = (De.ov_tlist? De.ov_tlist: De.ov_alist);
if (De.ov_bylist)
rlist = 0;
De.ov_counter= &count;
if (De.ov_bylist)
{
/*
** For aggregate functions the result relation
** is in the format:
** domain 1 = I4 (used as a counter)
** domain 2 through relatts - De.ov_agcount (by-domains)
** remaining domains (the actual aggregate values)
*/
/* set up keys for the getequal */
/* domno must end with the domain number of the first aggregate */
for (domno = 2; domno <= De.ov_result->reldum.relatts - De.ov_agcount; domno++)
De.ov_result->relgiven[domno] = 1;
De.ov_counter = (long *)De.ov_outtup; /* first four bytes of De.ov_outtup is counter for De.ov_bylist */
}
/*
** check for constant qualification.
** If the constant qual is true then remove
** the qual to save reprocessing it.
** If it is false then block further processing.
*/
ok = TRUE;
if (De.ov_qlist && De.ov_qualvc == 0)
if (interpret(FALSE, De.ov_qlist)->value.sym_data.i2type)
De.ov_qlist = 0; /* qual always true */
else
ok = FALSE; /* qual always false */
/* if no source relation, interpret target list */
if (!De.ov_scanr && ok)
{
/* there is no source relation and the qual is true */
qualfound = NONEMPTY;
De.ov_tend = De.ov_outtup;
/* if there is a rlist then process it. (There should always be one) */
if (rlist)
{
(*De.ov_counter)++;
interpret(istarget, rlist);
}
if (De.ov_tlist)
dispose(mode);
else
if (De.ov_userqry)
De.ov_tupsfound++;
}
if (De.ov_scanr && ok)
{
/* stop search if exact lid provided */
getnxt = (De.ov_fmode == BTREEKEY) ? CURTUP : NXTTUP;
/* There is a source relation. Iterate through each tuple */
pluck_page(&De.ov_hitid, &lpageid);
while (!(j = get(De.ov_scanr, &De.ov_lotid, &De.ov_hitid, De.ov_intup, getnxt)))
{
# ifdef xOTR1
if (tTf(71, 5))
{
if (De.ov_scanr != De.ov_source)
printf("Sec Index:");
else
printf("De.ov_intup:");
printup(De.ov_scanr, De.ov_intup);
dumptid(&De.ov_lotid);
}
# endif
if (De.ov_fmode == BTREERANGE && De.ov_scanr->reldum.relspec == M_HEAP)
{
pluck_page(&De.ov_lotid, &pageid);
if (pageid >= lpageid + 1)
break;
}
De.ov_intid = De.ov_lotid;
if (De.ov_scanr != De.ov_source)
{
/* make sure index tuple is part of the solution */
if (!indexcheck())
/* index keys don't match what we want */
continue;
bmove(De.ov_intup + De.ov_scanr->reldum.relwid - TIDLEN, (char *)&tid, TIDLEN);
if (j = get(De.ov_source, &tid, &temptid, De.ov_intup, CURTUP))
syserr("scan:indx get %d %.12s", j, De.ov_scanr->reldum.relid);
# ifdef xOTR1
if (tTf(71, 6))
{
printf("De.ov_intup:");
printup(De.ov_source, De.ov_intup);
}
# endif
De.ov_intid = tid;
}
if (!De.ov_qlist || interpret(FALSE,De.ov_qlist)->value.sym_data.i2type)
{
qualfound = NONEMPTY;
De.ov_tend = De.ov_outtup;
if (rlist)
{
(*De.ov_counter)++;
interpret(istarget,rlist);
}
if (De.ov_tlist)
dispose(mode);
else
if (De.ov_userqry)
De.ov_tupsfound++;
if (!De.ov_targvc) /* constant Target list */
break;
/* process De.ov_bylist if any */
if (De.ov_bylist)
{
interpret(istarget,De.ov_bylist);
if ((j = getequal(De.ov_result, De.ov_outtup, agtup, &De.ov_uptid)) < 0)
syserr("scan:getequal %d,%.12s", j, De.ov_result->reldum.relid);
if (!j)
{
/* match on bylist */
bmove(agtup, De.ov_outtup, De.ov_result->reldum.relwid);
mode = mdREPL;
(*De.ov_counter)++;
}
else
{
/* first of this bylist */
mode = mdAPP;
*De.ov_counter = 1;
}
De.ov_tend = De.ov_outtup + De.ov_result->reloff[domno];
interpret(istarget,De.ov_alist);
dispose(mode);
}
}
if (De.ov_fmode == BTREEKEY)
break;
}
if (j < 0 && De.ov_fmode != BTREEKEY)
syserr("scan:get prim %d %.12s", j, De.ov_source->reldum.relid);
}
if (De.ov_result)
{
if (j = noclose(De.ov_result))
syserr("scan:noclose %d %.12s", j, De.ov_result->reldum.relid);
}
return (qualfound);
}
/*
** DISPOSE
*/
dispose(mode)
{
register int i;
i = 0;
if (!De.ov_result)
{
if (Equel)
equeleol(EOTUP);
else
printeol();
}
else
{
# ifdef xOTR1
if (tTf(71, -1))
{
if (tTf(71, 1))
printf("mode=%d,",mode);
if (tTf(71, 2) && (mode == mdREPL || mode == mdDEL))
printf("De.ov_uptid:%ld, ",De.ov_uptid);
if (tTf(71, 3))
if (mode == mdDEL)
printup(De.ov_source, De.ov_intup);
else
printup(De.ov_result, De.ov_outtup);
}
# endif
/* SPOOL UPDATES OF EXISTING USER RELNS TO BATCH PROCESSOR */
if (De.de_buflag)
{
addbatch(&De.ov_uptid, De.ov_outtup, De.ov_origtup);
return;
}
/* PERFORM ALL OTHER OPERATIONS DIRECTLY */
switch (mode)
{
case mdRETR:
case mdAPP:
if ((i = insert(De.ov_result, &De.ov_uptid, De.ov_outtup, NODUPS)) < 0)
syserr("dispose:insert %d %.12s", i, De.ov_result->reldum.relid);
break;
case mdREPL:
if ((i = replace(De.ov_result, &De.ov_uptid, De.ov_outtup, NODUPS)) < 0)
syserr("dispose:replace %d %.12s", i, De.ov_result->reldum.relid);
break;
case mdDEL:
if ((i = delete(De.ov_result, &De.ov_uptid)) < 0)
syserr("dispose:delete %d %.12s", i, De.ov_result->reldum.relid);
break;
default:
syserr("dispose:bad mode %d", mode);
}
}
if (De.ov_userqry && i == 0)
De.ov_tupsfound++;
}