This commit is contained in:
Oliver Lehmann 1989-12-11 11:13:03 +00:00
parent 71b63a8731
commit 30af3311d4
1 changed files with 361 additions and 0 deletions

View File

@ -0,0 +1,361 @@
# 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"
# include "strategy.h"
/*
** Exactkey checks to see if the relation described
** by "ap" can be used in a hashed scan.
** All the key domains of the relation must
** have simple clauses of equality associated
** with them in the qualification.
**
** Returns 0 if the relation can't be used.
**
** Returns > 0 if it can.
*/
exactkey(ap, key)
struct accessparam *ap;
struct key *key;
{
register struct accessparam *a;
register struct key *k;
register struct simp *s;
int d;
int i;
int j;
# ifdef xOTR1
AAtTfp(25, -1, "EXACTKEY\n");
# endif
a = ap;
k = key;
i = 0;
if (a->mode == EXACTKEY)
{
for (i = 0; d = a->keydno[i]; i++)
{
s = Simp;
for (j = 0; j < Nsimp; j++)
{
if (s->relop == (int) opEQ && s->att == d)
{
k->keysym = s->konst;
k->dnumber = (a->sec_index == TRUE) ? i+1 : d;
k++;
# ifdef xOTR1
if (AAtTfp(25, 1, "exact key on dom %d\tvalue=", d))
prsym(s->konst);
# endif
break;
}
s++;
}
if (j == Nsimp)
{
i = 0; /* failure. at lease one key isn't used */
break;
}
}
k->dnumber = 0; /* mark end of list */
}
# ifdef xOTR1
AAtTfp(25, 9, "EXACTKEY: rets %d\n", i);
# endif
return (i);
}
/*
** Range key checks if the relation described by
** "ap" is ISAM and there are simple clauses
** on the first key and any additional keys.
**
** Rangekey accumulates both high and low keys,
** which are not necessary the same. If it
** every finds a high or a low key on the first
** domain of the relation then success=TRUE.
**
** Returns 1 if Rangekey ok
** 0 if Rangekey is not ok
** -1 if Rangekey ok and all clauses are equality clauses
*/
rangekey(ap, l, h)
struct accessparam *ap;
struct key *l;
struct key *h;
{
register struct key *low;
register struct key *high;
register struct simp *s;
struct accessparam *a;
int sec_indx;
int d;
int i;
int rel;
int success;
int ns;
int lowkey;
int allexact;
# ifdef xOTR1
AAtTfp(25, 5, "RANGEKEY\n");
# endif
a = ap;
sec_indx = a->sec_index == TRUE;
low = l;
high = h;
allexact = -1; /* assume all clauses equality clauses */
s = Simp;
success = FALSE;
if (a->mode == LRANGEKEY)
{
for (ns = 0; ns < Nsimp; ns++)
{
rel = s->relop;
for (i = 0; d = a->keydno[i]; i++)
{
if (d == s->att)
{
/* this is either a high range value or low range value */
lowkey = (rel == (int) opGTGE);
if (lowkey || rel == (int) opEQ)
{
/* low range key */
# ifdef xOTR1
AAtTfp(25, 6, "low key on dom %d\t", d);
# endif
low->keysym = s->konst;
low->dnumber = sec_indx ? i+1 : d;
low++;
}
if (!lowkey || rel == (int) opEQ)
{
/* high range key */
# ifdef xOTR1
AAtTfp(25, 6, "high key on dom %d\t", d);
# endif
high->keysym = s->konst;
high->dnumber = sec_indx ? i+1 : d;
high++;
}
# ifdef xOTR1
if (AAtTf(25, 6))
prsym(s->konst);
# endif
if (i == 0)
success = TRUE;
if (rel != (int) opEQ)
allexact = 1; /* at least one inequality */
break;
}
}
s++; /* try next simple clause */
}
}
high->dnumber = 0; /* mark end of list */
low->dnumber = 0; /* mask end of list */
/* if success then return whether all clauses were equality */
if (success)
success = allexact;
# ifdef xOTR1
AAtTfp(25, 5, "RANGEKEY: rets %d\n", success);
# endif
return (success);
}
setallkey(relkey, keytuple)
struct key *relkey;
char *keytuple;
/*
** Setallkey takes a key struct, decodes it and
** calls setkey with each value.
**
** Called from strategy().
**
** returns 0 if ok.
** returns -1 in the special case of a deblanked hashkey
** being bigger than the corresponding domain.
*/
{
register struct key *k;
register SYMBOL *sy;
register int dnum;
SYMBOL **s;
char *p;
char temp[MAXFIELD + 1];
int l;
AAam_clearkeys(Scanr);
k = relkey;
while (dnum = k->dnumber)
{
s = &k->keysym;
sy = (SYMBOL *) Stack;
getsymbol(sy, &s); /* copy symbol to stack. caution:getsym changes the value of s. */
rcvt(sy, Scanr->relfrmt[dnum], Scanr->relfrml[dnum]); /* convert key to correct type */
p = (char *) (sy->value);
if (sy->type == CHAR)
{
/*
** The length of a character key must
** be made equal to the domain length.
** The key is copied to a temp place
** and a null byte is inserted at the
** end. In addition, if the key without
** blanks is longer than the domain and
** this is an exactkey, then the query
** is false.
*/
p = temp;
l = cmove(sy, p); /* copy symbol to temp removing blanks & nulls */
# ifdef xOTR1
AAtTfp(26, 9, "length is %d\n", l);
# endif
if (Fmode == EXACTKEY && l > ctou(Scanr->relfrml[dnum]))
/* key too large. qualification is false */
return (-1);
}
if (sy->type == INT && sy->len == sizeof (char))
{
*temp = ((I2TYPE *) p)->i2type;
p = temp;
}
AAam_setkey(Scanr, keytuple, p, dnum); /* set the key */
k++;
}
# ifdef xOTR1
if (AAtTf(26, 8))
AAprkey(Scanr, keytuple);
# endif
return (0);
}
cmove(sym, dest)
struct stacksym *sym;
char *dest;
/*
** Cmove copies a char symbol into "dest".
** It stops when the length is reached or
** when a null byte is found.
**
** returns the number of non-blank chars
** in the string.
*/
{
register char *d;
register char *s;
register int l;
int blank;
s = (char *) ((SYMBOL *) sym)->value;
s = ((STRINGP *) s)->stringp; /* s points to the char string */
d = dest;
blank = 0;
for (l = (ctou(((SYMBOL *) sym)->len)); l--; s++)
{
*d++ = *s;
if (*s == ' ')
blank++;
if (*s == '\0')
{
d--;
break;
}
}
*d = '\0';
return ((d - dest) - blank); /* return length of string */
}
indexcheck()
/*
** Indexcheck is called by scan() to check whether
** a secondary index tuple satisfies the simple
** clauses under which it was scanned.
**
** Returns 1 if the tuple is ok,
** 0 otherwise.
*/
{
register int i;
if (Fmode == EXACTKEY)
i = keycheck(Lkey_struct, Keyl, 0); /* check for equality */
else
{
i = keycheck(Lkey_struct, Keyl, 1); /* check for >= */
/* If the lowkey passed, check the highkey also */
if (i)
i = keycheck(Hkey_struct, Keyh, -1); /* check for <= */
}
# ifdef xOTR1
AAtTfp(26, 10, "INDEXCHECK: rets %d\n", i);
# endif
return (i);
}
keycheck(keys, keytuple, mode)
struct key *keys;
char *keytuple;
int mode;
/*
** Keycheck compares Intup with keytuple
** according to the domains specified in the
** "keys" struct.
**
** mode is either >0, =0, <0 depending on
** whether check is for Intup >= keytuple,
** Intup == keytuple, Intup <= keytuple respectively
**
** returns TRUE or FALSE accordingly.
*/
{
register struct key *k;
register char *kp;
register int dnum;
register int offset;
register int i;
register int success;
kp = keytuple;
success = TRUE;
for (k = keys; dnum = k->dnumber; k++)
{
offset = Scanr->reloff[dnum];
if (i = AAicompare(&Intup[offset], &kp[offset], Scanr->relfrmt[dnum], ctou(Scanr->relfrml[dnum])))
{
if (i < 0 && mode < 0 || i > 0 && mode > 0)
continue;
success = FALSE;
break;
}
}
return (success);
}