/* SDB - select items from database - part 2 */

#include "bdscio.h"
#include "dbqdefs.h"

get_srels(slptr)
	struct sel *slptr;
{
	char rname[KEYWORDMAX+1],*aname;

	while (TRUE) {

		if (db_ntoken() != ID)
			{ RETERR(SYNTAX) }
		strcpy(rname,dbv_tstring);

		if (db_token() == ID) {
			db_ntoken();
			aname = dbv_tstring;
		}
		else
			aname = NULL;

		if (!srelation(slptr,rname,aname))
			return (FALSE);

		if (db_token() != ',')
			break;
		db_ntoken();
	}

	return (TRUE);
}

srelation(slptr,rname,aname)
	struct sel *slptr; char *rname,*aname;
{
	struct srel *srptr,*newsrel;

	if ((newsrel = CALLOC(SRELSIZE)) == NULL)
		{ RETERR(INSMEM) }

	newsrel->sr_ctuple = FALSE;
	newsrel->sr_update = FALSE;
	newsrel->sr_next = NULL;

	if ((newsrel->sr_scan = db_ropen(rname)) == NULL) {
		CFREE(newsrel);
		return (FALSE);
	}

	if (aname != NULL) {
		if ((newsrel->sr_name = CALLOC(strlen(aname)+1)) == NULL) {
			CFREE(newsrel);
			RETERR(INSMEM)
		}
		strcpy(newsrel->sr_name,aname);
	}
	else
		newsrel->sr_name = NULL;

	for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
		if (srptr->sr_next == NULL)
			break;

	if (srptr == NULL)
		slptr->sl_rels = newsrel;
	else
		srptr->sr_next = newsrel;

	return (TRUE);
}

int check_attrs(slptr)
	struct sel *slptr;
{
	struct sattr *saptr;

	if (slptr->sl_rels == NULL)
		{ RETERR(RELFNF) }

	if (slptr->sl_attrs == NULL)
		return (all_attrs(slptr));

	for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
		if (!find_attr(slptr,saptr->sa_rname,saptr->sa_aname,
			&saptr->sa_aptr,&saptr->sa_srel,&saptr->sa_attr))
		return (FALSE);

	return (TRUE);
}


int all_attrs(slptr)
	struct sel *slptr;
{
	struct sattr *newsattr,*lastsattr;
	struct srel *srptr;
	struct attribute *aptr;
	int i,astart;

	lastsattr = NULL;
	for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {

		astart = 1;
		for (i = 0; i < NATTRS; i++) {

		    aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];
		    if (aptr->at_name[0] == 0)
			break;
			if ((newsattr = CALLOC(SATSIZE)) == NULL)
				{ RETERR(INSMEM) }
			newsattr->sa_name = NULL;
			newsattr->sa_total = NULL;
			newsattr->sa_srel = srptr;
			newsattr->sa_aptr = srptr->sr_scan->sc_tuple + astart;
			newsattr->sa_attr = aptr;
			newsattr->sa_next = NULL;

			if ((newsattr->sa_rname = CALLOC(RNSIZE+1)) == NULL) {
				CFREE(newsattr);
				RETERR(INSMEM)
			}
			strncpy(newsattr->sa_rname,
				srptr->sr_scan->sc_relation->rl_name,RNSIZE);
			newsattr->sa_rname[RNSIZE] = 0;

			if (dbv_total && (aptr->at_type == TNUM)) {
				if ((newsattr->sa_total = CALLOC(4)) == NULL) {
					if (newsattr->sa_rname != NULL)
						CFREE(newsattr->sa_rname);
					CFREE(newsattr);
					RETERR(INSMEM)
				}	
				setmem(newsattr->sa_total,4,NULL);
			} else
				newsattr->sa_total = NULL;
	
		
			if ((newsattr->sa_aname = CALLOC(ANSIZE+1)) == NULL) {
				CFREE(newsattr->sa_rname);
				CFREE(newsattr);
				RETERR(INSMEM)
			}

			strncpy(newsattr->sa_aname,
		srptr->sr_scan->sc_relation->rl_header.hd_attrs[i].at_name,
				ANSIZE);
			newsattr->sa_aname[ANSIZE] = 0;

			if (lastsattr == NULL)
				slptr->sl_attrs = newsattr;
			else
				lastsattr->sa_next = newsattr;
			lastsattr = newsattr;

			astart += aptr->at_size;
		}
	}

	return (TRUE);
}

int find_attr(slptr,rname,aname,paptr,psrel,pattr)
	struct sel *slptr; char *rname,*aname;
	char **paptr; struct attribute **pattr;
{
	if (rname == NULL)
		return (uattr(slptr,aname,paptr,psrel,pattr));
	else
		return (qattr(slptr,rname,aname,paptr,psrel,pattr));
}

int uattr(slptr,aname,paptr,psrel,pattr)
	struct sel *slptr; char *aname;
	char **paptr; struct srel **psrel; struct attribute **pattr;
{
	struct srel *srptr;
	struct attribute *aptr;
	int i,astart;

	*pattr = NULL;
	for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {

		astart = 1;
		for (i = 0; i < NATTRS; i++) {

		aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];
		if (aptr->at_name[0] == 0)
			break;

		if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
			if (*pattr != NULL)
				{ RETERR(ATAMBG) }
			*paptr = srptr->sr_scan->sc_tuple + astart;
			*psrel = srptr;
			*pattr = aptr;
		}

		astart += aptr->at_size;
		}
	}

	if (*pattr == NULL)
		{ RETERR(ATUNDF) }

	return (TRUE);
}


int qattr(slptr,rname,aname,paptr,psrel,pattr)
	struct sel *slptr; char *rname,*aname;
	char **paptr; struct srel **psrel; struct attribute **pattr;
{
	struct srel *srptr;
	struct attribute *aptr;
	char *crname;
	int i,astart;

	*pattr = NULL;
	for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {

		if ((crname = srptr->sr_name) == NULL)
			crname = srptr->sr_scan->sc_relation->rl_name;

		if (db_sncmp(rname,crname,RNSIZE) == 0) {

			astart = 1;
			for (i = 0; i < NATTRS; i++) {

		aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];
		if (aptr->at_name[0] == 0)
			break;

		if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
			*paptr = srptr->sr_scan->sc_tuple + astart;
			*psrel = srptr;
			*pattr = aptr;
			return (TRUE);
		}

		astart += aptr->at_size;
		}

		RETERR(ATUNDF)
		}
	}


	RETERR(RLUNDF)
}


int process(srptr)
	struct srel *srptr;
{

	if (srptr->sr_next == NULL) {

		if (!srptr->sr_ctuple)
			db_rbegin(srptr->sr_scan);

		return (srptr->sr_ctuple = db_rfetch(srptr->sr_scan));
	}

	if (!srptr->sr_ctuple) {
		db_rbegin(srptr->sr_scan);

		if (!db_rfetch(srptr->sr_scan))
			return (FALSE);
	}

	while (!process(srptr->sr_next))

		if (!db_rfetch(srptr->sr_scan))
			return (srptr->sr_ctuple = FALSE);

	return (srptr->sr_ctuple = TRUE);
}

db_aget(aptr,vptr,avalue)
	struct attribute *aptr; char *vptr,*avalue;
{
	int i;

	for (i = 0;i < aptr->at_size; i++)
		*avalue++ = vptr[i];
	*avalue = EOS;
}

db_aput(aptr,vptr,avalue)
	struct attribute *aptr; char *vptr,*avalue;
{
	int i;

	i = 0;

	if (aptr->at_type == TNUM)
		for (; i < aptr->at_size - strlen(avalue); i++)
			vptr[i] = ' ';

	for (; i < aptr->at_size; i++)
		if (*avalue == 0)
			vptr[i] = 0;
		else
			vptr[i] = *avalue++;
}

vptr[i] = ' ';

	for (; i < aptr->at_size; i++)
		if (*avalue == 0)
			vptr[i