ING_DB
This commit is contained in:
parent
f2bb944967
commit
692539a185
|
|
@ -0,0 +1,18 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "../h/tree.h"
|
||||
# include "../h/access.h"
|
||||
# include "../h/batch.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "ovqp.h"
|
||||
|
||||
copyreturn()
|
||||
{
|
||||
/* copy information from decomp back to parser */
|
||||
rdpipe(P_PRIME, &Inpipe);
|
||||
wrpipe(P_PRIME, &Outpipe, EXEC_PARSER, (char *) 0, 0);
|
||||
copypipes(&Inpipe, R_down, &Outpipe, W_up);
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
# 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 "ovqp.h"
|
||||
|
||||
|
||||
/*
|
||||
** INTERP1.C
|
||||
**
|
||||
** symbol I/O utility routines for OVQP interpreter.
|
||||
**
|
||||
*/
|
||||
|
||||
/*
|
||||
** GETSYMBOL
|
||||
**
|
||||
** Gets (type, len, value) symbols from list
|
||||
** A ptr to the list is advanced after
|
||||
** call. Symbols are moved to a target location
|
||||
** (typically a slot on the interpreter's Stack).
|
||||
** Legality of symbol type and length is checked.
|
||||
** Returns 1 if no more symbols in list
|
||||
** 0 otherwise
|
||||
**
|
||||
*/
|
||||
|
||||
getsymbol(ts, p)
|
||||
SYMBOL *ts; /* target location (on stack) */
|
||||
SYMBOL ***p; /* pointer to list */
|
||||
{
|
||||
register char *d; /* ptr to data for target symbol */
|
||||
register char *cp; /* the item in the list */
|
||||
register struct stacksym *tops; /* target location on stack */
|
||||
register int len; /*length of target symbol*/
|
||||
register char *val;
|
||||
extern char *AAbmove();
|
||||
|
||||
tops = (struct stacksym *) ts; /* copy stack pointer */
|
||||
cp = (char *) **p; /* get list pointer */
|
||||
# ifdef xOTR1
|
||||
if (AAtTfp(24, 0, "GETSYM:"))
|
||||
prsym(cp);
|
||||
# endif
|
||||
|
||||
if (((SYMBOL *) cp)->type == VAR || ((SYMBOL *) cp)->type == S_VAR)
|
||||
{
|
||||
((SYMBOL *) tops)->type = ((SVAR_NODE *) cp)->vtype;
|
||||
len = ((SYMBOL *) tops)->len = ((SVAR_NODE *) cp)->vlen;
|
||||
d = (char *) (((SVAR_NODE *) cp)->vpoint);
|
||||
if (((SYMBOL *) tops)->type == INT && len == sizeof (char))
|
||||
{
|
||||
val = (char *) ((SYMBOL *) tops)->value;
|
||||
((I2TYPE *) val)->i2type = ctoi(((I1TYPE *) d)->i1type);
|
||||
/* advance Qvect sequencing pointer p */
|
||||
*p += 1;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
((SYMBOL *) tops)->type = ((SYMBOL *) cp)->type;
|
||||
len = ((SYMBOL *) tops)->len = ((SYMBOL *) cp)->len;
|
||||
len = ctou(len);
|
||||
d = (char *) ((SYMBOL *) cp)->value;
|
||||
}
|
||||
/* advance Qvect sequencing pointer p */
|
||||
*p += 1;
|
||||
|
||||
val = (char *) ((SYMBOL *) tops)->value;
|
||||
switch (((SYMBOL *) tops)->type)
|
||||
{
|
||||
case INT:
|
||||
switch (len)
|
||||
{
|
||||
case sizeof (char):
|
||||
((I2TYPE *) val)->i2type = ((I2TYPE *) d)->i2type;
|
||||
break;
|
||||
|
||||
case sizeof (short):
|
||||
case sizeof (long):
|
||||
AAbmove(d, val, len);
|
||||
break;
|
||||
|
||||
default:
|
||||
AAsyserr(17007, len);
|
||||
}
|
||||
break;
|
||||
|
||||
case FLOAT:
|
||||
AAbmove(d, val, len);
|
||||
# ifndef NO_F4
|
||||
if (len == sizeof (float)) /* convert to f8 */
|
||||
{
|
||||
((F8TYPE *) val)->f8type = ((F4TYPE *) val)->f4type;
|
||||
((SYMBOL *) tops)->len = sizeof (double);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
if (len != sizeof (double))
|
||||
AAsyserr(17008, len);
|
||||
break;
|
||||
|
||||
case CHAR:
|
||||
((STRINGP *) val)->stringp = d;
|
||||
break;
|
||||
|
||||
case AOP:
|
||||
case BOP:
|
||||
case UOP:
|
||||
case COP:
|
||||
case RESDOM:
|
||||
/* all except aop are of length 1. aop is
|
||||
** length AOP_SIZ but the first byte is the aop value
|
||||
*/
|
||||
((I2TYPE *) val)->i2type = ((I2TYPE *) d)->i2type;
|
||||
break;
|
||||
|
||||
case AND:
|
||||
case OR:
|
||||
break;
|
||||
|
||||
case AGHEAD:
|
||||
case BYHEAD:
|
||||
case ROOT:
|
||||
case QLEND:
|
||||
return (1); /* all these are delimitors between lists */
|
||||
|
||||
default:
|
||||
AAsyserr(17009, ((SYMBOL *) tops)->type);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* TOUT
|
||||
*
|
||||
* Copies a symbol value into the Output tuple buffer.
|
||||
* Used to write target
|
||||
* list elements or aggregate values into the output tuple.
|
||||
*/
|
||||
|
||||
tout(sp, offp, rlen)
|
||||
SYMBOL *sp;
|
||||
char *offp;
|
||||
{
|
||||
register SYMBOL *s;
|
||||
register int i;
|
||||
register char *p;
|
||||
int slen;
|
||||
extern char *AAbmove();
|
||||
|
||||
s = sp; /* copy pointer */
|
||||
|
||||
# ifdef xOTR1
|
||||
if (AAtTfp(24, 3, "TOUT: s="))
|
||||
{
|
||||
prstack(s);
|
||||
printf(" offset=%d, rlen=%d\n", offp-Outtup, rlen);
|
||||
}
|
||||
# endif
|
||||
|
||||
p = (char *) ((SYMBOL *) s)->value;
|
||||
if (((SYMBOL *) s)->type == CHAR)
|
||||
{
|
||||
slen = ctou(((SYMBOL *) s)->len);
|
||||
rlen = ctou(rlen);
|
||||
i = rlen - slen; /* compute difference between sizes */
|
||||
if (i <= 0)
|
||||
AAbmove(((STRINGP *) p)->stringp, offp, rlen);
|
||||
else
|
||||
{
|
||||
p = AAbmove(((STRINGP *) p)->stringp, offp, slen);
|
||||
while (i--)
|
||||
*p++ = ' '; /* blank out remainder */
|
||||
}
|
||||
}
|
||||
else if (rlen == sizeof (char)) /* ((SYMBOL *) s)->type == INT */
|
||||
*offp = ((I2TYPE *) p)->i2type;
|
||||
else
|
||||
AAbmove(p, offp, rlen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
rcvt(tosp, restype, reslen)
|
||||
SYMBOL *tosp;
|
||||
int restype;
|
||||
int reslen;
|
||||
{
|
||||
register SYMBOL *tos;
|
||||
register int rtype;
|
||||
register int rlen;
|
||||
register int stype;
|
||||
register int slen;
|
||||
|
||||
tos = tosp;
|
||||
rtype = restype;
|
||||
rlen = reslen;
|
||||
stype = ((SYMBOL *) tos)->type;
|
||||
slen= ((SYMBOL *) tos)->len;
|
||||
# ifdef xOTR1
|
||||
if (AAtTfp(24, 6, "RCVT: rt=%d, rl=%d, tos=", rtype, rlen))
|
||||
prstack(tos);
|
||||
# endif
|
||||
|
||||
if (rtype != stype)
|
||||
{
|
||||
if (rtype == CHAR || stype == CHAR)
|
||||
ov_err(BADCONV); /* bad char to numeric conversion requested */
|
||||
if (rtype == FLOAT)
|
||||
{
|
||||
# ifndef NO_F4
|
||||
if (rlen == sizeof (float))
|
||||
itof4(tos);
|
||||
else
|
||||
# endif
|
||||
itof8(tos);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rlen == sizeof (long))
|
||||
ftoi4(tos);
|
||||
else
|
||||
ftoi2(tos);
|
||||
}
|
||||
((SYMBOL *) tos)->len = rlen; /* handles conversion to i1 */
|
||||
}
|
||||
|
||||
else
|
||||
if (rtype != CHAR && rlen != slen)
|
||||
{
|
||||
if (rtype == INT)
|
||||
{
|
||||
if (rlen == sizeof (long))
|
||||
i2toi4(tos);
|
||||
else if (slen == sizeof (long))
|
||||
i4toi2(tos);
|
||||
}
|
||||
# ifndef NO_F4
|
||||
else /* rtype == FLOAT && rlen == sizeof (float) */
|
||||
f8tof4(tos);
|
||||
# endif
|
||||
((SYMBOL *) tos)->len = rlen; /* handles conversion to i1 */
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h" /* needed for trace flag */
|
||||
# include "../h/symbol.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "ovqp.h"
|
||||
/*
|
||||
** OVQP -- the One Variable Query Processor
|
||||
**
|
||||
** accepts one variable queries from
|
||||
** decompostion. Queries are sent as a
|
||||
** list arranged in postfix order.
|
||||
** OVQP returns one of three
|
||||
** possible values for each query:
|
||||
**
|
||||
** EMPTY: no tuples satisfied the query
|
||||
**
|
||||
** NONEMPTY: at least one tuple satisfied
|
||||
** the query. if the query was
|
||||
** a simple aggregate then the
|
||||
** aggregate value will immediately
|
||||
** follow.
|
||||
**
|
||||
** ERROR (CODE): A user caused error occured
|
||||
** during query processing.
|
||||
**
|
||||
**/
|
||||
|
||||
char *Ovqpbuf; /* pointer to buffer area */
|
||||
|
||||
ovqp()
|
||||
{
|
||||
register int code;
|
||||
extern int Eql;
|
||||
extern long AAccuread;
|
||||
extern long AAccuwrite;
|
||||
extern long AAccusread;
|
||||
char qrybuf[LBUFSIZE];
|
||||
|
||||
# ifdef xOTR1
|
||||
AAtTfp(27, 0, "OVQP: Eql=%d\n", Eql);
|
||||
# endif
|
||||
# ifdef xOTM
|
||||
if (AAtTf(76, 1))
|
||||
timtrace(7, 0);
|
||||
# endif
|
||||
# ifdef xOTR1
|
||||
if (AAtTf(50, 0))
|
||||
AAccuread = AAccuwrite = AAccusread = 0;
|
||||
# endif
|
||||
|
||||
Ovqpbuf = qrybuf; /* global buffer is allocated from stack */
|
||||
|
||||
startovqp();
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
if (code = getqry()) /* get next logical query */
|
||||
break; /* query processing complete */
|
||||
|
||||
/* in certain very rare instances, the strategy
|
||||
** routine will detect the fact that no tuples
|
||||
** can satisfy the qualification. If that case
|
||||
** arrises then no scan need be performed.
|
||||
*/
|
||||
|
||||
if (strategy())
|
||||
{
|
||||
# ifdef xOTM
|
||||
if (AAtTf(76, 2))
|
||||
timtrace(9, 0);
|
||||
# endif
|
||||
code = scan(); /* scan the relation */
|
||||
# ifdef xOTM
|
||||
if (AAtTf(76, 2))
|
||||
timtrace(10, 0);
|
||||
# endif
|
||||
}
|
||||
else
|
||||
code = EMPTY; /* else query is false */
|
||||
|
||||
retdecomp(code); /* return result to decomp */
|
||||
}
|
||||
# ifdef xOTM
|
||||
if (AAtTf(76, 1))
|
||||
timtrace(8, 0);
|
||||
# endif
|
||||
|
||||
endqry(code); /* close all relations */
|
||||
|
||||
# ifdef xOTR1
|
||||
AAtTfp(50, 1, "OVQP read %ld pages,%ld catalog pages,wrote %ld pages\n",
|
||||
AAccuread, AAccusread, AAccuwrite);
|
||||
# endif
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
# 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 "ovqp.h"
|
||||
|
||||
prsym(ss)
|
||||
SYMBOL *ss;
|
||||
{
|
||||
char *p;
|
||||
register int i;
|
||||
register int j;
|
||||
register SYMBOL *s;
|
||||
char temp[sizeof (double)];
|
||||
|
||||
s = ss;
|
||||
i = s->type;
|
||||
j = ctou(s->len);
|
||||
p = (char *) s->value;
|
||||
if (i == S_VAR)
|
||||
{
|
||||
i = VAR; /* execute var portion */
|
||||
printf("s_"); /* first part of "s_var" message */
|
||||
}
|
||||
if (i == VAR)
|
||||
{
|
||||
/* beware : do S_VAR's have attno's? */
|
||||
printf("var:att#=%d:", ((I2TYPE *) p)->i2type);
|
||||
i = ((SVAR_NODE *) s)->vtype;
|
||||
j = ctou(((SVAR_NODE *) s)->vlen);
|
||||
p = (char *) (((SVAR_NODE *) s)->vpoint);
|
||||
if (i != CHAR)
|
||||
{
|
||||
/* move INT & FLOAT to word boundary */
|
||||
if (i == INT && j == sizeof (char))
|
||||
((I2TYPE *) temp)->i2type = ctoi(*p);
|
||||
else
|
||||
AAbmove(p, temp, j);
|
||||
p = temp;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%d:%d:value='", i, j);
|
||||
switch (i)
|
||||
{
|
||||
case AND:
|
||||
case AOP:
|
||||
case BOP:
|
||||
case OR:
|
||||
case RESDOM:
|
||||
case UOP:
|
||||
printf("%d (operator)", ((I2TYPE *) p)->i2type);
|
||||
break;
|
||||
|
||||
case INT:
|
||||
if (j == sizeof (long))
|
||||
printf("%ld", ((I4TYPE *) p)->i4type);
|
||||
else
|
||||
printf("%d", ((I2TYPE *) p)->i2type);
|
||||
break;
|
||||
|
||||
case FLOAT:
|
||||
# ifndef NO_F4
|
||||
if (j == sizeof (float))
|
||||
printf("%10.3f", ((F4TYPE *) p)->f4type);
|
||||
else
|
||||
# endif
|
||||
printf("%10.3f", ((F8TYPE *) p)->f8type);
|
||||
break;
|
||||
|
||||
case RESULTID:
|
||||
case SOURCEID:
|
||||
case CHAR:
|
||||
prstr(p, j);
|
||||
break;
|
||||
|
||||
case AGHEAD:
|
||||
case BYHEAD:
|
||||
case QLEND:
|
||||
case ROOT:
|
||||
case TREE:
|
||||
printf(" (delim)");
|
||||
break;
|
||||
|
||||
case CHANGESTRAT:
|
||||
case REOPENRES:
|
||||
case EXIT:
|
||||
case QMODE:
|
||||
case RETVAL:
|
||||
case USERQRY:
|
||||
if (j)
|
||||
printf("%d", ((I2TYPE *) p)->i2type);
|
||||
printf(" (status)");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("\n\tError in PRSYM: bad type= %d\n",i);
|
||||
}
|
||||
printf("'\n");
|
||||
}
|
||||
|
||||
|
||||
prstack(ss)
|
||||
SYMBOL *ss;
|
||||
{
|
||||
register SYMBOL *s;
|
||||
register char *p;
|
||||
|
||||
s = ss;
|
||||
|
||||
if (s->type == CHAR)
|
||||
{
|
||||
printf("%d:%d:value='", s->type, s->len);
|
||||
p = (char *) s->value;
|
||||
prstr(((STRINGP *) p)->stringp, ctou(s->len));
|
||||
printf("'\n");
|
||||
}
|
||||
else
|
||||
prsym(s);
|
||||
}
|
||||
|
||||
|
||||
prstr(pt, len)
|
||||
char *pt;
|
||||
int len;
|
||||
{
|
||||
register char *p;
|
||||
register int l;
|
||||
|
||||
l = len + 1;
|
||||
p = pt;
|
||||
while (--l)
|
||||
{
|
||||
putchar(*p);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "../h/tree.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "ovqp.h"
|
||||
|
||||
int Qvpointer;
|
||||
|
||||
static SYMBOL *Qvect[MAXNODES];
|
||||
|
||||
|
||||
/*
|
||||
** Reads one symbol from the pipe
|
||||
** and inserts it in the next slot
|
||||
** on the Ovqpbuf.
|
||||
**
|
||||
** returns address of list element.
|
||||
*/
|
||||
char *rdsym()
|
||||
{
|
||||
register SYMBOL *next;
|
||||
register int i;
|
||||
register int j;
|
||||
extern char *Ovqpbuf;
|
||||
extern char *need();
|
||||
|
||||
next = (SYMBOL *) need(Ovqpbuf, SYM_HDR_SIZ); /* get two bytes for type and length */
|
||||
|
||||
if (j = rdpipe(P_NORM, &Inpipe, R_decomp, next, TYP_LEN_SIZ) != TYP_LEN_SIZ) /* get type and length */
|
||||
AAsyserr(17010, j);
|
||||
i = ctou(next->len); /* get length of symbol */
|
||||
# ifdef xOTR1
|
||||
AAtTfp(29, 0, "RDSYM: sym %2.d len=%3.d\n", next->type, i);
|
||||
# endif
|
||||
|
||||
if (i)
|
||||
{
|
||||
/* if i is odd round up and allocate enought space. */
|
||||
/* alloc will guarantee an even byte adress */
|
||||
|
||||
need(Ovqpbuf, i); /* get space for value */
|
||||
if (next->type == INT && i == sizeof (char))
|
||||
i++;
|
||||
if (j = rdpipe(P_NORM, &Inpipe, R_decomp, next->value, i) != i)
|
||||
AAsyserr(17011, j);
|
||||
}
|
||||
|
||||
# ifdef xOTR1
|
||||
if (AAtTf(29, 1))
|
||||
if (next->type != VAR)
|
||||
prsym(next);
|
||||
# endif
|
||||
|
||||
if (Qvpointer >= MAXNODES)
|
||||
ov_err(NODOVFLOW);
|
||||
Qvect[Qvpointer++] = (SYMBOL *) next;
|
||||
return ((char *) next);
|
||||
}
|
||||
|
||||
/*
|
||||
** Sym_ad -- reasonable way of getting the address
|
||||
** of the last symbol read in.
|
||||
**
|
||||
*/
|
||||
|
||||
SYMBOL **sym_ad()
|
||||
{
|
||||
return (&Qvect[Qvpointer - 1]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** putvar is called to insert a tuple
|
||||
** pointer into the list. Desc is a
|
||||
** descriptor struc of an open relation.
|
||||
** Tup is the tuple buffer for the relation.
|
||||
*/
|
||||
|
||||
putvar(sym, d, tup)
|
||||
register SVAR_NODE *sym;
|
||||
char tup[];
|
||||
register DESC *d;
|
||||
{
|
||||
register int attnum;
|
||||
extern char *Ovqpbuf;
|
||||
|
||||
attnum = sym->vattno;
|
||||
need(Ovqpbuf, SVAR_SIZ);
|
||||
|
||||
if (attnum)
|
||||
{
|
||||
/* attnum is a real attribute number */
|
||||
if (attnum > d->reldum.relatts)
|
||||
AAsyserr(17012, attnum, d->reldum.relid);
|
||||
sym->vtype = d->relfrmt[attnum];
|
||||
sym->vlen = d->relfrml[attnum];
|
||||
sym->vpoint = (short *) (&tup[0] + d->reloff[attnum]); /* address within tuple buffer location */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* attnum refers to the tuple id */
|
||||
sym->vtype = TIDTYPE;
|
||||
sym->vlen = TIDLEN; /* tids are longs */
|
||||
sym->vpoint = (short *) &Intid; /* address of tid */
|
||||
}
|
||||
# ifdef xOTR1
|
||||
if (AAtTfp(29, 3, "PUTVAR: "))
|
||||
prsym(sym);
|
||||
# endif
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "../h/tree.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "../h/aux.h"
|
||||
# include "ovqp.h"
|
||||
|
||||
|
||||
/*
|
||||
** startovqp is called at the beginning of
|
||||
** the execution of ovqp.
|
||||
*/
|
||||
startovqp()
|
||||
{
|
||||
extern flptexcep();
|
||||
extern struct pipfrmt Eoutpipe;
|
||||
|
||||
if (Eql) /* prime the write pipe to EQL */
|
||||
wrpipe(P_PRIME, &Eoutpipe, 0, (char *) 0, 0);
|
||||
|
||||
Tupsfound = 0; /* counts the number of tuples which sat the qual */
|
||||
Retrieve = Bopen = FALSE;
|
||||
/* catch floating point signals */
|
||||
signal(8, flptexcep);
|
||||
}
|
||||
|
||||
/*
|
||||
** Give a user error for a floating point exceptions
|
||||
*/
|
||||
flptexcep()
|
||||
{
|
||||
ov_err(FLOATEXCEP);
|
||||
}
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "../h/catalog.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "../h/tree.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "ovqp.h"
|
||||
# include "strategy.h"
|
||||
|
||||
int Fmode; /* find-mode determined by strategy */
|
||||
DESC *Scanr; /* desc of reln to be scanned, */
|
||||
/* (i.e. either Srcdesc or Indesc) */
|
||||
DESC *Source; /* 0 if no source for qry, */
|
||||
/* else points to Srcdesc */
|
||||
DESC *Result; /* 0 if no result for qry, */
|
||||
/* else points to Reldesc */
|
||||
int Newq; /* flags new user query to OVQP */
|
||||
long Lotid; /* lo limits of scan in OVQP */
|
||||
long Hitid; /* hi limits of scan in OVQP */
|
||||
|
||||
char Keyl[MAXTUP];
|
||||
char Keyh[MAXTUP];
|
||||
struct key Lkey_struct[MAXDOM + 1];
|
||||
struct key Hkey_struct[MAXDOM + 1];
|
||||
|
||||
/*
|
||||
** STRATEGY
|
||||
**
|
||||
** Attempts to limit access scan to less than the entire Source
|
||||
** relation by finding a key which can be used for associative
|
||||
** access to the Source reln or an index thereon. The key is
|
||||
** constructed from domain-value specifications found in the
|
||||
** clauses of the qualification list using sub-routine findsimp
|
||||
** in findsimp.c and other subroutines in file key.c
|
||||
*/
|
||||
|
||||
|
||||
strategy()
|
||||
{
|
||||
register int i;
|
||||
register int allexact;
|
||||
struct accessparam sourceparm;
|
||||
struct accessparam indexparm;
|
||||
struct index itup;
|
||||
struct index rtup;
|
||||
struct key lowikey[MAXKEYS + 1];
|
||||
struct key highikey[MAXKEYS + 1];
|
||||
register DESC *d;
|
||||
extern DESC Inddes;
|
||||
extern DESC *openindex();
|
||||
|
||||
# ifdef xOTR1
|
||||
AAtTfp(31, 0, "STRATEGY\tSource=%.12s\tNewq=%d\n",
|
||||
Source ? Source->reldum.relid : "(none)", Newq);
|
||||
# endif
|
||||
|
||||
while (Newq) /* if Newq=TRUE then compute a new strategy */
|
||||
/* NOTE: This while loop is executed only once */
|
||||
{
|
||||
Scanr = Source;
|
||||
|
||||
if (!Scanr)
|
||||
return (1); /* return immediately if there is no source relation */
|
||||
|
||||
Fmode = NOKEY; /* assume a find mode with no key */
|
||||
|
||||
if (!Qlist)
|
||||
break; /* if no qualification then you must scan entire rel */
|
||||
|
||||
/* copy structure of source relation into sourceparm */
|
||||
AAdparam(Source, &sourceparm);
|
||||
|
||||
/* if source is unkeyed and has no sec index then give up */
|
||||
if (sourceparm.mode == NOKEY &&
|
||||
((i = ctoi(Source->reldum.relindxd)) == 0 || i == SECINDEX))
|
||||
break;
|
||||
|
||||
/* find all simple clauses if any */
|
||||
if (!findsimps())
|
||||
break; /* break if there are no simple clauses */
|
||||
|
||||
/* Four steps are now performed to try and find a key.
|
||||
** First if the relation is hashed then an exact key is search for
|
||||
**
|
||||
** Second if there are secondary indexes, then a search is made
|
||||
** for an exact key. If that fails then a check is made for
|
||||
** a range key. The result of the rangekey check is saved.
|
||||
**
|
||||
** Third if the relation is an ISAM a check is made for
|
||||
** an exact key or a range key.
|
||||
**
|
||||
** Fourth if there is a secondary index, then if step two
|
||||
** found a key, that key is used.
|
||||
**
|
||||
** Lastly, give up and scan the entire relation
|
||||
*/
|
||||
|
||||
/* step one. Try to find exact key on primary */
|
||||
if (exactkey(&sourceparm, Lkey_struct))
|
||||
{
|
||||
Fmode = EXACTKEY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* step two. If there is an index, try to find an exactkey on one of them */
|
||||
if (ctoi(Source->reldum.relindxd))
|
||||
{
|
||||
opencatalog(AA_INDEX, 0);
|
||||
AAam_setkey(&Inddes, &itup, Source->reldum.relid, IRELIDP);
|
||||
AAam_setkey(&Inddes, &itup, Source->reldum.relowner, IOWNERP);
|
||||
if (i = AAam_find(&Inddes, EXACTKEY, &Lotid, &Hitid, &itup))
|
||||
AAsyserr(17021, i);
|
||||
|
||||
while (!(i = AAam_get(&Inddes, &Lotid, &Hitid, &itup, NXTTUP)))
|
||||
{
|
||||
# ifdef xOTR1
|
||||
if (AAtTf(31, 3))
|
||||
AAprtup(&Inddes, &itup);
|
||||
# endif
|
||||
if (!AAbequal(itup.irelidp, Source->reldum.relid, MAXNAME) ||
|
||||
!AAbequal(itup.iownerp, Source->reldum.relowner, 2))
|
||||
continue;
|
||||
AAiparam(&itup, &indexparm);
|
||||
if (exactkey(&indexparm, Lkey_struct))
|
||||
{
|
||||
Fmode = EXACTKEY;
|
||||
d = openindex(itup.irelidi);
|
||||
/* temp check for 6.0 index */
|
||||
if (ctoi(d->reldum.relindxd) == -1)
|
||||
ov_err(BADSECINDX);
|
||||
Scanr = d;
|
||||
break;
|
||||
}
|
||||
if (Fmode == LRANGEKEY)
|
||||
continue; /* a range key on a s.i. has already been found */
|
||||
if (allexact = rangekey(&indexparm, lowikey, highikey))
|
||||
{
|
||||
AAbmove(&itup, &rtup, sizeof itup); /* save tuple */
|
||||
Fmode = LRANGEKEY;
|
||||
}
|
||||
}
|
||||
if (i < 0)
|
||||
AAsyserr(17022, i);
|
||||
/* If an exactkey on a secondary index was found, look no more. */
|
||||
if (Fmode == EXACTKEY)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* step three. Look for a range key on primary */
|
||||
if (i = rangekey(&sourceparm, Lkey_struct, Hkey_struct))
|
||||
{
|
||||
if (i < 0)
|
||||
Fmode = EXACTKEY;
|
||||
else
|
||||
Fmode = LRANGEKEY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* last step. If a secondary index range key was found, use it */
|
||||
if (Fmode == LRANGEKEY)
|
||||
{
|
||||
if (allexact < 0)
|
||||
Fmode = EXACTKEY;
|
||||
d = openindex(rtup.irelidi);
|
||||
/* temp check for 6.0 index */
|
||||
if (ctoi(d->reldum.relindxd) == -1)
|
||||
ov_err(BADSECINDX);
|
||||
Scanr = d;
|
||||
AAbmove(lowikey, Lkey_struct, sizeof lowikey);
|
||||
AAbmove(highikey, Hkey_struct, sizeof highikey);
|
||||
break;
|
||||
}
|
||||
|
||||
/* nothing will work. give up! */
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* check for Newq = FALSE and no source relation */
|
||||
if (!Scanr)
|
||||
return (1);
|
||||
/*
|
||||
** At this point the strategy is determined.
|
||||
**
|
||||
** If Fmode is EXACTKEY then Lkey_struct contains
|
||||
** the pointers to the keys.
|
||||
**
|
||||
** If Fmode is LRANGEKEY then Lkey_struct contains
|
||||
** the pointers to the low keys and Hkey_struct
|
||||
** contains pointers to the high keys.
|
||||
**
|
||||
** If Fmode is NOKEY, then a full scan will be performed
|
||||
*/
|
||||
# ifdef xOTR1
|
||||
AAtTfp(31, -1, "FMODE: %d\n", Fmode);
|
||||
# endif
|
||||
|
||||
/* set up the key tuples */
|
||||
if (Fmode != NOKEY)
|
||||
{
|
||||
if (setallkey(Lkey_struct, Keyl))
|
||||
return (0); /* query false. There is a simple
|
||||
** clause which can never be satisfied.
|
||||
** These simple clauses can be choosey!
|
||||
*/
|
||||
}
|
||||
|
||||
if (i = AAam_find(Scanr, Fmode, &Lotid, &Hitid, Keyl))
|
||||
AAsyserr(17023, Scanr->reldum.relid, i);
|
||||
|
||||
if (Fmode == LRANGEKEY)
|
||||
{
|
||||
setallkey(Hkey_struct, Keyh);
|
||||
if (i = AAam_find(Scanr, HRANGEKEY, &Lotid, &Hitid, Keyh))
|
||||
AAsyserr(17024, Scanr->reldum.relid, i);
|
||||
}
|
||||
|
||||
# ifdef xOTR1
|
||||
if (AAtTfp(31, 1, "Lo"))
|
||||
{
|
||||
AAdumptid(&Lotid);
|
||||
printf("Hi");
|
||||
AAdumptid(&Hitid);
|
||||
}
|
||||
# endif
|
||||
|
||||
return (1);
|
||||
}
|
||||
Loading…
Reference in New Issue