This commit is contained in:
Oliver Lehmann 1989-04-03 19:32:49 +00:00
parent 33acf4a9ef
commit d86a2ba4c1
8 changed files with 1101 additions and 0 deletions

View File

@ -0,0 +1,229 @@
# include <stdio.h>
# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "../h/tree.h"
# include "../h/pipes.h"
# include "../h/symbol.h"
# include "parser.h"
/*
** fake attribute stash entries for tid nodes (and sid in dist version)
** these are provided by the system to a program only for debugging
** the system source and do not have well defined (over time) meanings.
*/
struct atstash Faketid =
{
0, INT, sizeof (long), "tid", 0
};
#ifdef DISTRIB
struct atstash Fakesid =
{
0, INT, sizeof (long), "sid", 0
};
#endif
/*
** ATTLOOKUP
** routine to look up atribute 'attrib' in the att stash
** for range table entry 'rptr'. If the attrib is not
** in the stash it is entered.
*/
struct atstash *attlookup(rptr1, attrib)
struct rngtab *rptr1;
char *attrib;
{
register struct rngtab *rptr;
register struct atstash *current;
struct atstash *ik;
int i;
struct attribute tuple;
register struct attribute *ktuple;
struct attribute ktup;
struct tup_id tid;
extern struct atstash *attfind();
extern struct atstash *attadd();
rptr = rptr1;
ktuple = &ktup;
# ifdef xPTR2
AAtTfp(10, 1, "attlookup: att = %s and rel= %s\n", attrib, rptr->relnm);
# endif
/* attribute called "tid" is phantom attribute, use fake */
if (AAsequal("tid", attrib))
return (&Faketid);
# ifdef DISTRIB
if (AAsequal("sid", attrib))
return (&Fakesid);
# endif
/* check to see if attrib is in stash */
if ((ik = attfind(rptr, attrib)) != (struct atstash *) 0)
return (ik);
# ifdef xPTR2
AAtTfp(10, 2, "getting att info from relation\n");
# endif
/* rel name, owner, attname is unique ident */
AAam_clearkeys(&Desc);
AAam_setkey(&Desc, ktuple, rptr->relnm, ATTRELID);
AAam_setkey(&Desc, ktuple, rptr->relnowner, ATTOWNER);
AAam_setkey(&Desc, ktuple, attrib, ATTNAME);
if (!(i = AAgetequal(&Desc, ktuple, &tuple, &tid)))
{
/* put attrib stuff into att stash */
current = attadd(rptr, &tuple);
return (current);
}
if (i == 1) /* attribute not in relation */
yyerror(NOATTRIN, attrib, rptr->relnm, (char *) 0);
AAsyserr(18000, i);
}
/*
** ATTADD
** add an attrib to the list
*/
struct atstash *attadd(rptr, tuple)
struct rngtab *rptr;
struct attribute *tuple;
{
register struct atstash *current;
register struct atstash *aptr;
register struct atstash *bptr;
int i;
extern struct atstash *attalloc();
current = attalloc();
current->atbid = tuple->attid;
current->atbfrmt = tuple->attfrmt;
current->atbfrml = tuple->attfrml;
AAbmove(tuple->attname, current->atbname, MAXNAME);
for (i = 0; i < MAXNAME; i++)
if (current->atbname[i] == ' ')
current->atbname[i] = '\0';
aptr = rptr->attlist;
bptr = 0;
while (aptr != 0)
{
if (aptr->atbid > current->atbid)
break;
bptr = aptr;
aptr = aptr->atbnext;
}
if (bptr == 0)
rptr->attlist = current;
else
bptr->atbnext = current;
current->atbnext = aptr;
return (current);
}
/*
** ATTFIND
** look in attribute stash to see if attrib info already there
** return pointer to attribute in attribute table else zero
*/
struct atstash *attfind(rptr, attrib1)
struct rngtab *rptr;
char *attrib1;
{
register struct atstash *aptr;
register char *attrib;
attrib = attrib1;
aptr = rptr->attlist;
while (aptr != 0)
{
if (!AAscompare(attrib, MAXNAME, aptr->atbname, MAXNAME))
return (aptr);
aptr = aptr->atbnext;
}
return (0);
}
/*
** ATTCHECK
** checks for type conflicts in the current query domain and
** attable entry
*/
attcheck(aptr1)
struct atstash *aptr1;
{
register struct atstash *aptr;
aptr = aptr1;
if ((Trfrmt == CHAR) != (aptr->atbfrmt == CHAR))
/* function type does not match attrib */
yyerror(RESTYPE, aptr->atbname, (char *) 0);
}
/*
** ATTFREE
** puts a list of attrib space back on the free list
*/
attfree(aptr)
struct atstash *aptr;
{
register struct atstash *att;
if (!(att = aptr))
return;
while (att->atbnext)
att = att->atbnext;
att->atbnext = Freeatt;
Freeatt = aptr;
}
/*
** ATTALLOC
** returns a pointer to a atstash type structure
*/
struct atstash *attalloc()
{
register struct atstash *aptr;
register struct rngtab *rptr;
register int i;
extern struct rngtab *rngatndx();
i = MAXVAR - 1;
while (!Freeatt)
{
/*
** search least recently used vbles for attrib stash space
** until at least one entry is found
*/
rptr = rngatndx(i);
Freeatt = rptr->attlist;
rptr->attlist = (struct atstash *) 0;
i = rptr->rposit - 1; /* try one newer than the current */
}
aptr = Freeatt;
Freeatt = Freeatt->atbnext;
aptr->atbnext = (struct atstash *) 0;
return (aptr);
}
/*
** ATTCOUNT
** returns a count fof the number of attributes already in the
** attrib stash
*/
attcount(rptr)
struct rngtab *rptr;
{
register int cntr;
register struct atstash *aptr;
cntr = 0;
aptr = rptr->attlist;
while (aptr)
{
cntr++;
aptr = aptr->atbnext;
}
return (cntr);
}

View File

@ -0,0 +1,69 @@
# include <stdio.h>
# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "../h/pipes.h"
# include "../h/symbol.h"
# include "../h/tree.h"
# include "parser.h"
# define PARGSIZE (MAXDOM * 2 + 10) /* max no of params to dbu */
char **Pv; /* ptr to list of dbu params */
int Pc; /* number of dbu commands */
static char Pbuffer[PARBUFSIZ]; /* buffer for dbu commands */
/*
** CALL_P -- send the buffered command
** the execid and funcid are given.
*/
call_p(qmode, execid)
int qmode;
int execid;
{
register struct pipfrmt *pp;
register int i;
struct pipfrmt p;
fflush(stdout);
pp = &p;
wrpipe(P_PRIME, pp, execid, (char *) 0, qmode);
for (i = 0; i < Pc; i++)
{
# ifdef xPTR2
AAtTfp(6, 0, "Pv[%d]=%s\n", i, Pv[i]);
# endif
wrpipe(P_NORM, pp, W_down, Pv[i], 0);
}
wrpipe(P_END, pp, W_down);
initp();
syncdn();
}
setp(msg)
register char *msg;
{
register char *p;
extern char *need();
p = need(Pbuffer, AAlength(msg) + 1);
AAsmove(msg, p);
Pv[Pc++] = p;
if (Pc >= PARGSIZE)
AAsyserr(18001, Pc);
}
initp()
{
extern int neederr();
extern char *need();
initbuf(Pbuffer, PARBUFSIZ, PBUFOFLO, neederr);
Pv = (char **) need(Pbuffer, PARGSIZE * (sizeof(*Pv)));
Pc = 0;
}

View File

@ -0,0 +1,43 @@
# include <stdio.h>
# include "gen.h"
# include "../h/dbs.h"
# include "../h/pipes.h"
/*
** GETSCR
** returns a single character from the R_up pipe.
** modes are:
** 0 = read normally
** 1 = prime the pipe
** 2 = sync (or flush) the pipe
*/
getscr(mode)
int mode;
{
extern int Pctr; /* vble for backup stack in scanner */
static struct pipfrmt a;
register int ctr;
char c;
if (!mode)
{
ctr = rdpipe(P_NORM, &a, R_up, &c, sizeof (char));
return (ctr ? c : 0);
}
if (mode == 1)
{
rdpipe(P_PRIME, &a);
Pctr = 0;
return (0);
}
if (mode == 2)
{
# ifdef xPTM
if (AAtTf(76, 1))
timtrace(2, 0);
# endif
rdpipe(P_SYNC, &a, R_up);
return (0);
}
AAsyserr(18010, mode);
}

View File

@ -0,0 +1,231 @@
# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "../h/tree.h"
# include "parser.h"
# include "../h/catalog.h"
# include "../h/symbol.h"
/*
** P_UTIL -- parser utility functions
**
** These functions are generally unrelated except that they are
** needed to operate the parser and are too small to be considered
** seperate modules.
**
** Defines:
** timeofday -- convert arguments to minutes since midnight
** tlprepend -- attach two target list components
** header -- prints the header for a retrieve to terminal
** patmat -- converts pattern matching characters in a string
** permcom -- adds a command to the permit command vector
**
**
**
** TIMEOFDAY -- convert 2 integers to minutes since midnight
**
** Converts the hours and minutes parameters to minutes since midnight
** performing some error (bounds) checking on the time.
**
** To answer the question about what is midnight, both 0:00 and 24:00
** are handled, but not the same way. The former is zero minutes from
** midnight and the latter is 1440 minutes from midnight. (1440 is
** 24 hrs times 60 minutes, or 1 minute past the end of the day.)
**
** Parameters:
** hrs -- an integer pointer to the hour
** mins -- an integer pointer to the minutes
**
** Returns:
** integer time since midnight
**
** Side Effects:
** may detect an error and call yyerror which never returns.
*/
timeofday(hrs, mins)
int *hrs;
int *mins;
{
register int h;
register int m;
register int rtval;
h = *hrs;
m = *mins;
if (h > 24 || h < 0)
/* no such hour */
yyerror(BADHOURS, AA_iocv(h), (char *) 0);
if (m > 59 || h < 0)
/* no such minute */
yyerror(BADMINS, AA_iocv(m), (char *) 0);
if (h == 24)
{
h = 1440;
if (m != 0)
/* can only use 24:00 */
yyerror(BAD24TIME, AA_iocv(m), (char *) 0);
}
rtval = (h * 60) + m;
return (rtval);
}
/*
** TLPREPEND -- combine two target list components
**
** Attach two target list components to each other.
** Neither component need be a single element. The
** 'a' component will be attached at the extreme left
** of the 'b' component.
**
** Parameters:
** a -- tl component to attach
** b -- tl base for attaching
**
** Side Effects:
** this routine is a side effect. It attaches a to b
** and when it returns a is attached to b but the pointer
** to b never changes (neither does the pointer to a)
*/
QTREE *tlprepend(a, b)
QTREE *a;
QTREE *b;
{
register QTREE *q;
/* scan to the left end of b */
for (q = b; q->left; q = q->left)
continue; /* no action */
/* attach a to the end of b */
q->left = a;
return (b);
}
/*
** HEADER -- print header for retrieve to terminal
**
** header scans the parameter list managed with "initp" and
** "setp" to reconstruct the field names and types and passing
** them to the normal AAprhdr etc.
*/
header()
{
register int i;
short j;
AAbgnhdr();
for (i = 0; i < Pc; i += 2)
{
AA_atoi(&Pv[i + 1][1], &j);
AAprhdr(ctou(Pv[i + 1][0]), j, Pv[i]);
}
AApreol();
AAendhdr();
initp();
}
/*
** PATMAT -- converts pattern matching characters in a string
**
** Searches a string up to a null byte for one of the pattern
** matching characters '*', '?', '[', and ']'. It then converts
** these characters to their internal control character equivalents.
**
** Parameters:
** str -- the string to search
**
** Returns:
** 0 -- no pattern matching in string
** 1 -- at least one pattern matching character
*/
patmat(str)
char *str;
{
register char *p;
register char *q;
register int flag;
flag = 0;
q = str;
for (p = str; *p; p++)
{
if (*p == '\\')
{
*q++ = *++p;
continue;
}
switch (*p)
{
case '*':
*q++ = PAT_ANY;
flag = 1;
continue;
case '?':
*q++ = PAT_ONE;
flag = 1;
continue;
case '[':
*q++ = PAT_LBRAC;
flag = 1;
continue;
case ']':
*q++ = PAT_RBRAC;
flag = 1;
continue;
}
*q++ = *p;
}
*q = '\0';
return (flag);
}
/*
** PERMCOM -- map command allowed into AA_PROTECT catalog bits
**
** translates the QMODE type symbols into the appropriate counterparts
** for the permit statement allowed command vector. The manifest
** constants are designed to be inclusive or'd together to form a
** composite bit map of OK actions.
**
** Parameters:
** a -- the QMODE type symbol for the command to add
**
** Side Effects:
** changes the variable Permcomd to reflect the additional permission
*/
permcom(a)
register int a;
{
switch (a)
{
case mdRETR:
Permcomd |= PRO_RETR;
break;
case mdAPP:
Permcomd |= PRO_APP;
break;
case mdREPL:
Permcomd |= PRO_REPL;
break;
case mdDEL:
Permcomd |= PRO_DEL;
break;
case -1:
Permcomd |= 0177777; /* all bits set */
break;
default:
AAsyserr(18018, a);
}
}

View File

@ -0,0 +1,386 @@
# include <stdio.h>
# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "../h/pipes.h"
# include "../h/tree.h"
# include "../h/symbol.h"
# include "parser.h"
struct atstash *Freeatt; /* free list of attrib stash */
static struct rngtab Rngtab[MAXVAR + 1]; /* range table */
static struct atstash Attable[MAXATT]; /* attrib stash space, turned into a list later */
/*
** RNGINIT
** initializes the pointers in the range table
** it should be called prior to starting the parsing
** it also initializes the attrib stash stuff because
** the attrib stash is really part of the range table
*/
rnginit()
{
register int i;
register struct atstash *atptr;
register struct rngtab *rptr;
rptr = Rngtab; /* ptr to head of range table */
for (i = 0; i <= MAXVAR; i++, rptr++) /* ">=" includes the internal entry */
{
rptr->ractiv = 0;
rptr->rmark = 0;
rptr->rposit = i;
AAsmove("", rptr->varname);
AAsmove("", rptr->relnm);
rptr->rstat = 0;
rptr->ratts = 0;
rptr->attlist = (struct atstash *) 0;
}
rngreset();
atptr = Attable;
for (i = 0; i < MAXATT - 1; i++)
{
atptr->atbnext = atptr + 1;
atptr++;
}
atptr->atbnext = (struct atstash *) 0;
Freeatt = Attable;
}
/*
** RNGLOOK
** returns a pointer to the range table entry else 0
** type = LOOKREL lookup relation
** type = LOOKVAR lookup variable
*/
struct rngtab *rnglook(p, type)
char *p;
int type;
{
register struct rngtab *rptr;
register char *param;
register int i;
param = p;
rptr = Rngtab;
switch (type)
{
case LOOKVAR:
case LOOKREL:
break;
default:
AAsyserr(18019, type);
}
for (i = 0; i < MAXVAR; i++, rptr++) /* search external vbles only */
{
if (rptr->ractiv == 1 && AAscompare(param, MAXNAME, (type == LOOKVAR ? rptr->varname : rptr->relnm), MAXNAME) == 0)
{
rptr->rmark = 1;
# ifdef xPTR2
AAtTfp(21, 6, "fnd '%s' at '%d'\n", param, rptr->rentno);
# endif
rngfront(rptr);
return (rptr);
}
}
return ((struct rngtab *) 0);
}
/*
** RNGENT
** Insert variable and relation in range table.
*/
struct rngtab *rngent(type, var, rel, relown, atts, relstat)
int type;
char *var;
char *rel;
char *relown;
int atts;
int relstat;
{
register struct rngtab *rptr;
extern struct rngtab *rngat();
extern struct rngtab *rngatndx();
# ifdef xPTR2
AAtTfp(21, 0, "RNGENT:\ttyp=%d\tvar=%s\trel=%s\n\town=%.2s\tatts=%d\tstat=0%o\n",
type, var, rel, relown, atts, relstat);
# endif
if (type == R_INTERNAL)
rptr = &Rngtab[MAXVAR];
else if (type == R_EXTERNAL)
{
if (!(rptr = rnglook(var, LOOKVAR)))
{
/* not in range table */
rptr = rngatndx(MAXVAR - 1);
}
rngfront(rptr);
}
else
AAsyserr(18020, type);
if (AAscompare(rel, MAXNAME, rptr->relnm, MAXNAME) != 0 ||
!AAbequal(relown, rptr->relnowner, 2))
{
attfree(rptr->attlist);
rptr->attlist = (struct atstash *) 0;
}
AApmove(var, rptr->varname, MAXNAME, '\0');
AApmove(rel, rptr->relnm, MAXNAME, '\0');
AAbmove(relown, rptr->relnowner, 2);
rptr->ractiv = 1;
rptr->ratts = atts;
rptr->rstat = relstat;
return (rptr);
}
/*
** RNGDEL
** removes an entry from the range table
** removes all variables for the relation name
*/
rngdel(rel)
char *rel;
{
register struct rngtab *rptr;
while ((rptr = rnglook(rel, LOOKREL)))
{
AAsmove("", rptr->relnm);
AAsmove("", rptr->varname);
rptr->rmark = 0;
rptr->ractiv = 0;
rngback(rptr);
attfree(rptr->attlist);
rptr->attlist = (struct atstash *) 0;
}
}
/*
** RNGSEND
** Writes range table information needed by DECOMP and OVQP.
*/
rngsend()
{
register struct rngtab *rptr;
register int i;
rptr = Rngtab;
for (i = 0; i < MAXVAR; i++, rptr++)
{
if (rptr->rmark != 0)
{
rngwrite(rptr);
}
}
/* send result relation range entry if not already sent */
if (Resrng && Resrng->rentno == MAXVAR)
{
rngwrite(Resrng);
}
}
/*
** RNGFRONT
** move entry 'r' to head of range table list
*/
rngfront(r)
struct rngtab *r;
{
register struct rngtab *rptr;
register struct rngtab *fptr;
register int i;
fptr = r;
rptr = Rngtab;
for (i = 0; i < MAXVAR; i++, rptr++) /* check all external vbles */
{
if (rptr->rposit < fptr->rposit)
rptr->rposit++;
}
fptr->rposit = 0;
}
/*
** RNGBACK
** move entry 'r' to back of range table list
*/
rngback(r)
struct rngtab *r;
{
register struct rngtab *rptr;
register struct rngtab *bptr;
register int i;
bptr = r;
rptr = Rngtab;
for (i = 0; i < MAXVAR; i++, rptr++) /* check all external vbles */
{
if (rptr->rposit > bptr->rposit)
rptr->rposit--;
}
bptr->rposit = MAXVAR - 1;
}
/*
** RNGRESET
** reset the used marks to '0'
*/
rngreset()
{
register struct rngtab *rptr;
register int i;
rptr = Rngtab;
for (i = MAXVAR - 1; i >= 0; i--, rptr++) /* only do external ones */
{
rptr->rmark = 0;
rptr->rentno = i;
}
Rngtab[MAXVAR].rentno = MAXVAR; /* internal vble is always MAXVAR */
}
/*
** RNGOLD -- find least recently used vble entry
*/
struct rngtab *rngatndx(ndx)
int ndx;
{
register struct rngtab *rptr;
register int i;
rptr = Rngtab;
for (i = 0; i < MAXVAR; i++, rptr++) /* do external vbles */
{
if (rptr->rposit == ndx)
return (rptr);
}
AAsyserr(18021, ndx);
}
/*
** CHECKUPD
** checks to make sure that the user can update the relation 'name1'
** the 'open' parameter is set if 'Reldesc' contains the AArelopen info
** for the relation in question.
*/
checkupd(rptr)
struct rngtab *rptr;
{
if (!Noupdt)
return;
if (rptr->rstat & S_NOUPDT)
/* no updates allowed on this relation */
yyerror(CANTUPDATE, rptr->relnm, (char *) 0);
}
/*
** RNGFRESH -- check the range table relstat information for accuracy
**
** If the command specified could have changed the relstat info
** make the appropriate adjustments to the range table
*/
rngfresh(op)
int op;
{
register struct rngtab *rptr;
register int i;
DESC desc;
/* search the entire table! */
for (i = 0, rptr = Rngtab; i <= MAXVAR; i++, rptr++)
{
if (!rptr->ractiv)
continue;
switch (op)
{
case mdDESTROY:
case mdREMQM:
if ((rptr->rstat & (S_VBASE | S_INTEG | S_PROTUPS | S_INDEX)) != 0)
{
fixordel:
/*
** AArelopen the relation, if it doesn't exist make
** sure that all range table entries are gone
*/
if (!AArelopen(&desc, -1, rptr->relnm))
{
/* relation still there, copy bits anyway */
rptr->rstat = desc.reldum.relstat;
}
else
{
/* relation not there, purge table */
rngdel(rptr->relnm);
}
}
break;
case mdVIEW:
if ((rptr->rstat & S_VBASE) == 0)
{
fixorerr:
/*
** if the relation doesn't exist then it is
** a AAsyserr, otherwise, copy the bits.
*/
if (!AArelopen(&desc, -1, rptr->relnm))
{
/* exists, copy bits */
rptr->rstat = desc.reldum.relstat;
}
else /* not there, AAsyserr */
AAsyserr(18022, rptr->relnm);
}
break;
case mdPROT:
if ((rptr->rstat & S_PROTUPS) == 0)
goto fixorerr;
break;
case mdINTEG:
if ((rptr->rstat & S_INTEG) == 0)
goto fixorerr;
break;
case mdMODIFY:
if ((rptr->rstat & S_INDEX) != 0)
goto fixordel;
break;
default:
return; /* command ok, dont waste time on rest of table */
}
}
}
/*
** RNGPRINT
** prints the contents of the range table
*/
rngprint()
{
register short i;
register short j;
register struct rngtab *rptr;
printf(" relation\tvariable\n");
printf("----------------------------\n");
for (i = 0; i < MAXVAR; i++)
{
rptr = Rngtab;
for (j = 0; j < MAXVAR; j++, rptr++)
{
if (!rptr->ractiv || i != rptr->rposit)
continue;
printf("%12s\t%.12s\n", rptr->relnm, rptr->varname);
}
}
printf("----------------------------\n");
}

View File

@ -0,0 +1,43 @@
# include "gen.h"
# include "../h/dbs.h"
# include "../h/scanner.h"
/*
** COMMENT
** scans comments (as delimited by the tokens 'Tokens.bgncmnt'
** and 'Tokens.endcmnt') and removes them from the query text.
*/
comment()
{
register int i;
register int l;
register struct optab *op;
char buf[3];
/* find the end_of_comment operator */
for (op = Optab; op->term; op++)
if (op->token == Tokens.endcmnt)
break;
if (!op->term)
AAsyserr(20000);
/* scan for the end of the comment */
l = AAlength(op->term);
if (l > sizeof buf - 1)
AAsyserr(20001, l, op->term, sizeof buf - 1);
for (i = 0; i < l; i++) /* set up window on input */
if ((buf[i] = gtchar()) <= 0)
/* non-terminated comment */
yyerror(COMMTERM, (char *) 0);
while (!AAbequal(buf, op->term, l))
{
/* move window on input */
for (i = 0; i < l - 1; i++)
buf[i] = buf[i + 1];
if ((buf[l - 1] = gtchar()) <= 0)
/* non terminated comment */
yyerror(COMMTERM, (char *) 0);
}
return (0);
}

View File

@ -0,0 +1,35 @@
# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "../h/scanner.h"
static char Sbuf[SBUFSIZ]; /* symbol table buffer */
/*
** SYMENT
** enter a symbol into the symbol table
*/
char *syment(ptr, len1)
char *ptr;
int len1;
{
register int len;
register char *p;
extern char *need();
len = len1;
p = need(Sbuf, len);
AAbmove(ptr, p, len);
return (p);
}
/*
** FREESYM
** free all entries in the symbol table
*/
freesym()
{
extern int neederr();
initbuf(Sbuf, SBUFSIZ, SBUFOFLO, neederr);
}

View File

@ -0,0 +1,65 @@
# include <stdio.h>
# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "../h/tree.h"
# include "../h/pipes.h"
# include "../h/symbol.h"
# include "parser.h"
/*
** XDOT
** add to attribute stash any missing attributes in the
** source relation and then build tree with all attribs
** in the 'attid' order. This algorithm assumes that
** the function 'attadd' insert attributes into the list
** in 'attid' order from 1 -> N.
*/
QTREE *xdot(rptr)
struct rngtab *rptr;
{
struct attribute tuple;
register struct attribute *ktuple;
struct attribute ktup;
struct tup_id tid;
struct tup_id limtid;
QTREE *tempt;
register QTREE *vnode;
int ik;
register struct atstash *aptr;
extern QTREE *tree();
extern QTREE *addresdom();
# ifdef xPTR2
AAtTfp(15, 0, "ALL being processed for %s\n", rptr->relnm);
# endif
/* if attstash is missing any attribs then fill in list */
if (rptr->ratts != attcount(rptr))
{
/* get all entries in attrib relation */
AAam_clearkeys(&Desc);
ktuple = &ktup;
AAam_setkey(&Desc, ktuple, rptr->relnm, ATTRELID);
AAam_setkey(&Desc, ktuple, rptr->relnowner, ATTOWNER);
if (ik = AAam_find(&Desc, EXACTKEY, &tid, &limtid, ktuple))
AAsyserr(18024, ik);
while (!AAam_get(&Desc, &tid, &limtid, &tuple, 1))
if (!AAkcompare(&Desc, &tuple, ktuple))
/* add any that are not in the stash */
if (!attfind(rptr, tuple.attname))
attadd(rptr, &tuple);
}
/* build tree for ALL */
tempt = (QTREE *) 0;
aptr = rptr->attlist;
while (aptr != 0)
{
vnode = tree((QTREE *) 0, (QTREE *) 0, VAR, VAR_SIZ, CAST(rptr->rentno), aptr);
Trname = aptr->atbname;
tempt = addresdom(tempt, vnode);
aptr = aptr->atbnext;
}
return (tempt);
}