284 lines
5.6 KiB
C
284 lines
5.6 KiB
C
# include "amx.h"
|
|
|
|
static struct amx_key AP_key[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.
|
|
*/
|
|
strategy(over)
|
|
AMX_REL *over;
|
|
{
|
|
register AMX_REL *r;
|
|
register int mode;
|
|
register int i;
|
|
extern AMX_REL *getrel();
|
|
|
|
/* check user suggested access path */
|
|
if (over)
|
|
{
|
|
if ((r = Relation) == over)
|
|
goto ap_primary;
|
|
|
|
while (r = getrel(r->rel_index, 0))
|
|
{
|
|
if (r == over)
|
|
{
|
|
AP_index = r->rel_uniq;
|
|
i_param(r);
|
|
if ((AP_mode = getkeys(r)) == AP_NOKEY)
|
|
goto ap_primary;
|
|
goto ap_done;
|
|
}
|
|
}
|
|
amxerror(89, Relation->rel_id, over->rel_id);
|
|
}
|
|
|
|
AP_mode = AP_NOKEY; /* assume a find mode with no key */
|
|
|
|
if (!Domains)
|
|
{ /* if no qualification then you must scan entire rel */
|
|
AP_key[0].key_cond = 0; /* primary relation */
|
|
AP_key[1].key_dom = 0; /* no domains */
|
|
goto ap_done;
|
|
}
|
|
|
|
/* copy structure of primary relation into AP_key */
|
|
p_param(r = Relation);
|
|
|
|
/* Try to find exact key on primary */
|
|
if ((AP_mode = getkeys(r)) == AP_FULLKEY)
|
|
goto ap_done;
|
|
|
|
/* if primary has no sec index then give up */
|
|
if (r->rel_index == MAX_RELS)
|
|
goto ap_done;
|
|
|
|
/* check indexed access paths */
|
|
mode = AP_NOKEY; /* assume found no useable index */
|
|
while (r = getrel(r->rel_index, 0))
|
|
{ /* copy structure of index relation into AP_key */
|
|
i_param(r);
|
|
if ((i = getkeys(r)) == AP_LOWKEY)
|
|
i = AP_HIGHKEY;
|
|
if (i > mode)
|
|
{
|
|
/* found better index */
|
|
AP_index = r->rel_uniq;
|
|
|
|
/* If an fullkey on a sec index was found, */
|
|
/* look no more. */
|
|
if ((mode = i) == AP_FULLKEY)
|
|
{
|
|
AP_mode = mode;
|
|
goto ap_done;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Look for a range key on primary */
|
|
/* or no indexed access path */
|
|
if (AP_mode != AP_NOKEY || mode == AP_NOKEY)
|
|
{
|
|
ap_primary:
|
|
/* access via primary relation */
|
|
AP_index = MAX_RELS;
|
|
p_param(r = Relation);
|
|
}
|
|
else /* access via index relation */
|
|
{
|
|
r = getrel(AP_index, 0);
|
|
i_param(r);
|
|
}
|
|
AP_mode = getkeys(r);
|
|
|
|
ap_done:
|
|
/*
|
|
** At this point the strategy is determined.
|
|
**
|
|
** If AP_mode is AP_NOKEY, then a full scan will be performed
|
|
*/
|
|
|
|
p_len();
|
|
if (AP_index != MAX_RELS)
|
|
{
|
|
r = getrel(AP_index, 0);
|
|
i_len(r);
|
|
}
|
|
}
|
|
|
|
|
|
static getkeys(r)
|
|
register AMX_REL *r;
|
|
{
|
|
register AMX_KEY *k;
|
|
register int key;
|
|
register int cond;
|
|
|
|
/* if relation is unkeyed then give up */
|
|
if (abs(ctoi(r->rel_spec)) == M_HEAP)
|
|
return (AP_NOKEY);
|
|
|
|
k = &AP_key[1];
|
|
cond = ctou(k->key_cond);
|
|
|
|
key = AP_FULLKEY;
|
|
for ( ; k->key_dom; k++)
|
|
{
|
|
if (!bitset(AP_EQ, k->key_cond))
|
|
{
|
|
key = AP_NOKEY;
|
|
break;
|
|
}
|
|
}
|
|
if (key)
|
|
return (AP_FULLKEY);
|
|
|
|
/* if relation is hashed then give up */
|
|
if (abs(ctoi(r->rel_spec)) == M_HASH)
|
|
return (AP_NOKEY);
|
|
|
|
if (bitset(AP_EQ, cond))
|
|
return (AP_RANGEKEY | AP_LOWKEY | AP_HIGHKEY);
|
|
|
|
if (bitset(AP_GT, cond))
|
|
key = AP_LOWKEY;
|
|
|
|
if (bitset(AP_LT, cond))
|
|
return(key? (AP_RANGEKEY | AP_LOWKEY | AP_HIGHKEY): AP_HIGHKEY);
|
|
|
|
return (key);
|
|
}
|
|
|
|
|
|
static p_param(r)
|
|
register AMX_REL *r;
|
|
{
|
|
register AMX_KEY *k;
|
|
register int dom;
|
|
|
|
for (dom = 0, k = AP_key; dom <= MAXDOM; dom++, k++)
|
|
k->key_dom = k->key_cond = 0;
|
|
|
|
for (dom = 1; dom <= ctou(r->rel_atts); dom++)
|
|
{
|
|
k = &AP_key[r->rel_dom[dom - 1].att_key];
|
|
k->key_dom = dom;
|
|
k->key_cond = Dom_set[dom];
|
|
}
|
|
}
|
|
|
|
|
|
static p_len()
|
|
{
|
|
register AMX_REL *r;
|
|
register AMX_ATT *a;
|
|
register int dom;
|
|
register int qual;
|
|
register int len;
|
|
|
|
AP_low = AP_high = 0;
|
|
AP_ilow = AP_ihigh = 0;
|
|
r = Relation;
|
|
|
|
for (dom = 1; dom < MAXDOM; dom++)
|
|
{
|
|
if (!(qual = Dom_set[dom]))
|
|
continue;
|
|
|
|
a = &r->rel_dom[dom - 1];
|
|
len = a->att_off + ctou(a->att_len);
|
|
if (len > AP_low) /* update length of first key tuple */
|
|
AP_low = len;
|
|
if ((bitset(AP_LT, qual) && bitset(AP_GT, qual)) ||
|
|
(bitset(AP_LT, qual) && bitset(AP_NE, qual)) ||
|
|
(bitset(AP_GT, qual) && bitset(AP_NE, qual)))
|
|
if (len > AP_high) /* update length of second key tuple */
|
|
AP_high = len;
|
|
}
|
|
}
|
|
|
|
|
|
static i_param(r)
|
|
register AMX_REL *r;
|
|
{
|
|
register AMX_KEY *k;
|
|
register int dom;
|
|
register char *p;
|
|
|
|
k = AP_key;
|
|
k->key_dom = 0;
|
|
k++->key_cond = 1; /* secondary index */
|
|
|
|
for (p = r->ind_dom; dom = ctou(*p); p++)
|
|
{
|
|
k->key_dom = dom;
|
|
k++->key_cond = Dom_set[dom];
|
|
}
|
|
k->key_dom = 0;
|
|
}
|
|
|
|
|
|
static i_len(r)
|
|
register AMX_REL *r;
|
|
{
|
|
register AMX_ATT *a;
|
|
register char *dom;
|
|
register int len;
|
|
register int qual;
|
|
register int qual2;
|
|
register int i;
|
|
|
|
AP_ilow = AP_ihigh = 0;
|
|
fprintf(FILE_scn, msg(180), r->rel_uniq, r->rel_uniq);
|
|
|
|
for (dom = r->ind_dom; *dom; dom++)
|
|
{
|
|
i = ctou(*dom);
|
|
if (!(qual = Dom_set[i]))
|
|
continue;
|
|
|
|
qual2 = 0;
|
|
a = &r->rel_dom[dom - r->ind_dom];
|
|
len = a->att_off + ctou(a->att_len);
|
|
if (len > AP_ilow) /* update length of first key tuple */
|
|
AP_ilow = len;
|
|
if ((bitset(AP_LT, qual) && bitset(AP_GT, qual)) ||
|
|
(bitset(AP_LT, qual) && bitset(AP_NE, qual)) ||
|
|
(bitset(AP_GT, qual) && bitset(AP_NE, qual)))
|
|
{
|
|
if (len > AP_ihigh) /* update length of second key tuple */
|
|
AP_ihigh = len;
|
|
|
|
if (bitset(AP_NE, qual))
|
|
{
|
|
clrbit(AP_NE, qual);
|
|
qual2 = AP_NE;
|
|
}
|
|
else if (bitset(AP_GT, qual))
|
|
{
|
|
clrbit(AP_GT, qual);
|
|
qual2 = AP_GT;
|
|
if (bitset(AP_GE, qual))
|
|
{
|
|
clrbit(AP_GE, qual);
|
|
qual2 |= AP_GE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* call AAsetind(desc, key_tup, key_val, dom, qual) */
|
|
i = ctou(*dom);
|
|
a = &Relation->rel_dom[i - 1];
|
|
len = a->att_off;
|
|
fprintf(FILE_scn, msg(55), r->rel_uniq, len, dom - r->ind_dom + 1, qual);
|
|
if (qual2)
|
|
fprintf(FILE_scn, msg(64), r->rel_uniq, len, dom - r->ind_dom + 1, qual2);
|
|
}
|
|
}
|