diff --git a/WEGA/contrib/ingres/dbs/src/ovqp/copyreturn.c b/WEGA/contrib/ingres/dbs/src/ovqp/copyreturn.c new file mode 100644 index 0000000..92680e2 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/ovqp/copyreturn.c @@ -0,0 +1,18 @@ +# include +# 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); +} diff --git a/WEGA/contrib/ingres/dbs/src/ovqp/interp1.c b/WEGA/contrib/ingres/dbs/src/ovqp/interp1.c new file mode 100644 index 0000000..043fd03 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/ovqp/interp1.c @@ -0,0 +1,251 @@ +# include +# 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 */ + } +} diff --git a/WEGA/contrib/ingres/dbs/src/ovqp/ovqp.c b/WEGA/contrib/ingres/dbs/src/ovqp/ovqp.c new file mode 100644 index 0000000..b74b769 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/ovqp/ovqp.c @@ -0,0 +1,95 @@ +# include +# 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 +} diff --git a/WEGA/contrib/ingres/dbs/src/ovqp/prsym.c b/WEGA/contrib/ingres/dbs/src/ovqp/prsym.c new file mode 100644 index 0000000..51f307b --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/ovqp/prsym.c @@ -0,0 +1,140 @@ +# include +# 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++; + } +} diff --git a/WEGA/contrib/ingres/dbs/src/ovqp/rdsym.c b/WEGA/contrib/ingres/dbs/src/ovqp/rdsym.c new file mode 100644 index 0000000..b86098b --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/ovqp/rdsym.c @@ -0,0 +1,113 @@ +# include +# 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 +} diff --git a/WEGA/contrib/ingres/dbs/src/ovqp/startovqp.c b/WEGA/contrib/ingres/dbs/src/ovqp/startovqp.c new file mode 100644 index 0000000..98dd86e --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/ovqp/startovqp.c @@ -0,0 +1,35 @@ +# include +# 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); +} diff --git a/WEGA/contrib/ingres/dbs/src/ovqp/strategy.c b/WEGA/contrib/ingres/dbs/src/ovqp/strategy.c new file mode 100644 index 0000000..69c445b --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/ovqp/strategy.c @@ -0,0 +1,231 @@ +# include +# 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); +}