P8000/WEGA/contrib/ingres/dbs/src/amx_cc/strategy.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);
}
}