/* SDB - select data from database */

#include "bdscio.h"
#include "dbqdefs.h"

struct sel *db_select(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
	char *fmt;

{
	struct sel *slptr;
	char rname[KEYWORDMAX+1];	/* save first att - maybe rel */
	int sav_err;			/* save error code */
#ifdef DBPI
	if (fmt != NULL)
		db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
#endif
	if ((slptr = CALLOC(SELSIZE)) == NULL)
		{ RETERR(INSMEM) }

	slptr->sl_rels = NULL;
	slptr->sl_attrs = NULL;
	slptr->sl_where = NULL;
	slptr->sl_bindings = NULL;

	if (!get_sattrs(slptr)) {
		db_done(slptr);
		return (NULL);
	}

	if (db_token() == FROM) {
		db_ntoken();
		if (!get_srels(slptr)) {
			db_done(slptr);
			return (NULL);
		}
	}
	else {
/*		if (!srelation(slptr,"current",NULL)) {
			db_done(slptr);
			return (NULL);
		}
*/
		srelation(slptr,"current",NULL);
	}

	if (!check_attrs(slptr)) {
		sav_err = dbv_errcode;
		strcpy(rname,slptr->sl_attrs->sa_aname); /* maybe rname */
		db_done(slptr);
		if ((slptr = CALLOC(SELSIZE)) == NULL)
			{ RETERR(INSMEM) }

		slptr->sl_rels = NULL;
		slptr->sl_attrs = NULL;
		slptr->sl_where = NULL;
		slptr->sl_bindings = NULL;
		if (!srelation(slptr,rname,NULL)) {
			db_done(slptr);
			dbv_errcode = sav_err;
			return(NULL);
		}

		if (!check_attrs(slptr)) {
			db_done(slptr);
			return (NULL);
		}
	}

	if (db_token() == WHERE) {
		db_ntoken();
		if (!db_compile(slptr)) {
			db_done(slptr);
			return (FALSE);
		}
	}

	return (slptr);
}

struct sel *db_retrieve(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
	char *fmt;

{
	struct sel *slptr;
#ifdef DBPI
	if (fmt != NULL)
		db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
#endif
	if ((slptr = CALLOC(SELSIZE)) == NULL)
		{ RETERR(INSMEM) }

	
	slptr->sl_rels = NULL;
	slptr->sl_attrs = NULL;
	slptr->sl_where = NULL;
	slptr->sl_bindings = NULL;

	if (db_token() == ID) {
		if (!get_srels(slptr)) {
			db_done(slptr);
			return (NULL);
		}
	}
	else {
		if (!srelation(slptr,"current",NULL)) {
			db_done(slptr);
			return (NULL);
		}
	}

	if (!check_attrs(slptr)) {
		db_done(slptr);
		return (NULL);
	}

	if (db_token() == WHERE) {
		db_ntoken();
		if (!db_compile(slptr)) {
			db_done(slptr);
			return (FALSE);
		}
	}

	return (slptr);
}

db_done(slptr)
	struct sel *slptr;
{
	struct sattr *saptr,*nxtsa;
	struct srel *srptr,*nxtsr;
#ifdef DBPI
	struct binding *bdptr,*nxtbd;
#endif

	for (saptr = slptr->sl_attrs; saptr != NULL; saptr = nxtsa) {
		nxtsa = saptr->sa_next;
		if (saptr->sa_rname != NULL)
			CFREE(saptr->sa_rname);
		CFREE(saptr->sa_aname);
		if (saptr->sa_name != NULL)
			CFREE(saptr->sa_name);
		if (saptr->sa_total != NULL)
			CFREE(saptr->sa_total);
		CFREE(saptr);
	}

	for (srptr = slptr->sl_rels; srptr != NULL; srptr = nxtsr) {
		nxtsr = srptr->sr_next;
		if (srptr->sr_name != NULL)
			CFREE(srptr->sr_name);
		db_rclose(srptr->sr_scan);
		CFREE(srptr);
	}

	db_fcode(slptr);
	dbv_total = FALSE;
#ifdef DBPI
	for (bdptr = slptr->sl_bindings; bdptr != NULL; bdptr = nxtbd) {
		nxtbd = bdptr->bd_next;
		CFREE(bdptr);
	}
#endif
	CFREE(slptr);
}

int db_fetch(slptr)
	struct sel *slptr;
{
	struct srel *srptr;
	struct binding *bdptr;

	for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
		srptr->sr_update = FALSE;

	while (process(slptr->sl_rels))
	  if (db_interpret(slptr)) {
#ifdef DBPI
	for (bdptr = slptr->sl_bindings; bdptr != NULL; bdptr = bdptr->bd_next)
		db_aget(bdptr->bd_attr,bdptr->bd_vtuple,bdptr->bd_vuser);
#endif
		return (TRUE);
	  }
	return (FALSE);
}

int db_update(slptr)
	struct sel *slptr;
{
	struct srel *srptr;

	for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
		if (srptr->sr_update)
			if (!db_rupdate(srptr->sr_scan))
				return (FALSE);
	return (TRUE);
}

int db_store(slptr)
	struct sel *slptr;
{
	struct srel *srptr;

	for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
		if (srptr->sr_update)
			if (!db_rstore(srptr->sr_scan))
				return (FALSE);
	return (TRUE);
}
#ifdef DBPI
int db_bind(slptr,rname,aname,avalue)
	struct sel *slptr; char *rname,*aname,*avalue;
{
	struct binding *newbd;
	struct srel *srptr;

	if ((newbd = CALLOC(BINDSIZE)) == NULL)
		{ RETERR(INSMEM) }
	newbd->bd_vuser = avalue;

	if (!find_attr(slptr,rname,aname,&newbd->bd_vtuple,&srptr,&newbd->bd_attr))
		return (FALSE);

	newbd->bd_next = slptr->sl_bindings;
	slptr->sl_bindings = newbd;

	return (TRUE);
}
#endif

int db_get(slptr,rname,aname,avalue)
	struct sel *slptr; char *rname,*aname,*avalue;
{
	struct srel *srptr;
	struct attribute *aptr;
	char *vptr;

	if (!find_attr(slptr,rname,aname,&vptr,&srptr,&aptr))
		return (FALSE);

	db_aget(aptr,vptr,avalue);

	return (TRUE);
}


int db_put(slptr,rname,aname,avalue)
	struct sel *slptr; char *rname,*aname,*avalue;
{
	struct srel *srptr;
	struct attribute *aptr;
	char *vptr;

	if (!find_attr(slptr,rname,aname,&vptr,&srptr,&aptr))
		return (FALSE);

	db_aput(aptr,vptr,avalue);

	srptr->sr_update = TRUE;

	return (TRUE);
}


int db_sattr(slptr,rname,aname,ptype,pptr,plen)
	struct sel *slptr; char *rname,*aname;
	int *ptype; char **pptr; int *plen;
{
	struct srel *srptr;
	struct attribute *aptr;

	if (!find_attr(slptr,rname,aname,pptr,&srptr,&aptr))
		return (FALSE);

	*ptype = aptr->at_type;
	*plen = aptr->at_size;

	return (TRUE);
}

get_sattrs(slptr)
	struct sel *slptr;
{
	struct sattr *newsattr,*lastsattr;

	if (db_token() == '*') {
		db_ntoken();
		if (db_token() == PLUS) {
			db_ntoken();
			dbv_total = TRUE;
		}
		return (TRUE);
	}
	else if (db_token() != ID)
		return (TRUE);

	lastsattr = NULL;
	while (TRUE) {

		if (db_ntoken() != ID)
			{ RETERR(SYNTAX) }

		if ((newsattr = CALLOC(SATSIZE)) == NULL)
			{ RETERR(INSMEM) }

		newsattr->sa_next = NULL;

		if ((newsattr->sa_aname =
			CALLOC(strlen(dbv_tstring)+1)) == NULL) {
			CFREE(newsattr);
			RETERR(INSMEM)
		}
		strcpy(newsattr->sa_aname,dbv_tstring);

		if (db_token() == '.') {
			db_ntoken();

			newsattr->sa_rname = newsattr->sa_aname;

			if (db_ntoken() != ID) {
				CFREE(newsattr->sa_aname); CFREE(newsattr);
				RETERR(SYNTAX)
			}

			if ((newsattr->sa_aname =
				CALLOC(strlen(dbv_tstring)+1)) == NULL) {
				CFREE(newsattr->sa_aname); CFREE(newsattr);
				RETERR(INSMEM)
			}

			strcpy(newsattr->sa_aname,dbv_tstring);
		}
		else
			newsattr->sa_rname = NULL;

		if (db_token() == PLUS) {
			db_ntoken();
			if ((newsattr->sa_total = CALLOC(4)) == NULL) {
				if (newsattr->sa_rname != NULL)
					CFREE(newsattr->sa_rname);
				CFREE(newsattr->sa_aname); CFREE(newsattr);
				RETERR(INSMEM)
			}	
			setmem(newsattr->sa_total,4,NULL);
		} else
			newsattr->sa_total = NULL;
	

		if (db_token() == ID) {
			db_ntoken();

			if ((newsattr->sa_name =
				CALLOC(strlen(dbv_tstring)+1)) == NULL) {
				if (newsattr->sa_rname != NULL)
					CFREE(newsattr->sa_rname);
				if (newsattr->sa_total != NULL)
					CFREE(newsattr->sa_total);
				CFREE(newsattr->sa_aname); CFREE(newsattr);
				RETERR(INSMEM)
			}
			strcpy(newsattr->sa_name,dbv_tstring);
		}
		else
			newsattr->sa_name = NULL;

		if (lastsattr == NULL)
			slptr->sl_attrs = newsattr;
		else
			lastsattr->sa_next = newsattr;
		lastsattr = newsattr;

		if (db_token() != ',')
			break;
		db_ntoken();
	}

	return (TRUE);
}

/* from dbqmth */

int db_cmp(arg1,arg2)
	char *arg1,*arg2;
{
	char farg1[4],farg2[4];

	atols(farg1,arg1,4);
	atols(farg2,arg2,4);
	return (lcomp(farg1,farg2));
}

*arg1,*arg2;
{
	char farg1[4],farg2[4];

	atols(farg1,arg1,4);
	atols(farg2,arg2,4);
	re