/*	SDB - operations on tuples		*/

#include "bdscio.h"
#include "dbqdefs.h"

int insert()
{
	struct scan *sptr;
	struct attribute *aptr;
	char aname[ANSIZE+1],avalue[STRINGMAX+1];
	int tcnt,astart,i;

	if (db_token() == ID)
		db_ntoken();
	else
		strcpy(dbv_tstring,"current");

	if (!db_flush(0))
		return (FALSE);

	if (!(sptr = db_ropen(dbv_tstring)))
		return (FALSE);

	for (tcnt = 0; ; tcnt++) {

		if (tcnt)
			printf("----\n");

		astart = 1;
		for (i = 0; i < NATTRS; i++) {
			aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

			if (!aptr->at_name[0])
				break;

			strncpy(aname,aptr->at_name,ANSIZE);
			aname[ANSIZE] = 0;

			db_prompt(NULL,NULL);

			while (TRUE) {
				if (!dbv_ifp) {
					if (strlen(aname) < 8)
						printf("%s\t\t",aname);
					else
						printf("%s\t",aname);
					inbrack(aptr->at_size,aptr->at_type,aptr->at_scale);
					}
				if (db_gline(avalue))
					break;
			}

			if (!i && !avalue[0])
				break;

			db_aput(aptr,&sptr->sc_tuple[astart],avalue);

			astart += aptr->at_size;
		}

		if (!avalue[0])
			break;

		if (!db_rstore(sptr)) {
			db_rclose(sptr);
			return (FALSE);
		}
	}

	db_rclose(sptr);

	pcount(tcnt,"inserted");

	return (TRUE);
}

int delete()
{
	struct sel *slptr;
	struct srel *srptr;
	int tcnt;

	if (!(slptr = db_retrieve(NULL)))
		return (FALSE);

	for (tcnt = 0; db_fetch(slptr); tcnt++)

		for (srptr = slptr->sl_rels; srptr != NULL;srptr = srptr->sr_next)
			if (!db_rdelete(srptr->sr_scan)) {
				db_done(slptr);
				return (FALSE);
			}
	db_done(slptr);

	pcount(tcnt,"deleted");

	return (TRUE);
}

int update()
{
	struct sel *slptr;
	struct sattr *saptr;
	struct attribute *aptr;
	char aname[ANSIZE+1],avalue[STRINGMAX+1],*ap;
	int tcnt;

	if (!(slptr = db_select(NULL)))
		return (FALSE);

	if (!db_flush(0)) {
		db_done(slptr);
		return (FALSE);
	}

	for (tcnt = 0; db_fetch(slptr); tcnt++) {
		if (tcnt)
			printf("----\n");

		for (saptr = slptr->sl_attrs; saptr ; saptr = saptr->sa_next) {

			aptr = saptr->sa_attr;

			strncpy(aname,aptr->at_name,ANSIZE);
			aname[ANSIZE] = 0;

			db_aget(aptr,saptr->sa_aptr,avalue);
			for (ap = avalue; isspace(*ap); ap++)
				;

			if (!dbv_ifp)
			  if (strlen(aname) < 8)
				printf("%s\t\t= %s\n",aname,ap); 
			  else
				printf("%s\t= %s\n",aname,ap); 

			db_prompt(NULL,NULL);

			while (TRUE) {
				if (!dbv_ifp) {
				   if (strlen(aname) < 8)
					printf("%s\t\t ",aname);
				   else
					printf("%s\t ",aname);
				   inbrack(aptr->at_size,aptr->at_type,aptr->at_scale);
				   }
				if (db_gline(avalue))
					break;
			}

			if (avalue[0]) {
				db_aput(aptr,saptr->sa_aptr,avalue);
				saptr->sa_srel->sr_update = TRUE;
			}
		}

		db_update(slptr);
	}

	db_done(slptr);

	pcount(tcnt,"updated");

	return (TRUE);
}

inbrack(fldsize,fldtype,fldscale)
int fldsize,fldscale; char fldtype;
{
	int i;

	i = fldsize;
	if (fldtype == TNUM)
		putchar('<');
	else
		putchar('[');
	while (i--) putchar(' ');
	if (fldtype == TNUM) {
		putchar('>');
		if (fldscale) printf(" %d\b\b",fldscale);
	}
	else
		putchar(']');
	putchar('\b');
	while (fldsize--) putchar('\b');
}

int print()
{
	struct sel *slptr;
	char *ffp;
	FILE *ofp;
	int tcnt;

	if (!using(&ffp,".fmt"))
		return (FALSE);

	if (!(slptr = db_select(NULL)))
		return (FALSE);

	if (!db_to(&ofp,".rep")) {
		db_done(slptr);
		return (FALSE);
	}

	dbv_page = 0;
	dbv_lnct = dbv_pgln;

	if (ffp)
		tcnt = form(ofp,slptr,ffp);
	else
		tcnt = table(ofp,slptr);

	db_done(slptr);

	if (ffp) {
		CFREE(ffp);
		}

	if (ofp != STDOUT) {
		putc(CPMEOF,ofp);
		fclose(ofp);
		}

	pcount(tcnt,"found");

	return (TRUE);
}

int select()
{
	struct sel *slptr;
	struct relation *rptr;
	struct sattr *saptr;
	char *aname,*tbuf;
	int tcnt,abase,i;

	if (!(slptr = db_select(NULL)))
		return (FALSE);

	if (!(rptr = db_rcreate("current"))) {
		db_done(slptr);
		return(FALSE);
	}

	for (saptr = slptr->sl_attrs; saptr; saptr = saptr->sa_next) {

		if (!(aname = saptr->sa_name))
			aname = saptr->sa_aname;

		if (!db_rcattr(rptr,aname,saptr->sa_attr->at_type,
		   saptr->sa_attr->at_size,saptr->sa_attr->at_scale)) {

			CFREE(rptr);
			db_done(slptr);
			return (FALSE);
		}
	}

	if (!db_rcheader(rptr)) {
		db_done(slptr);
		return (FALSE);
	}

	if (!(tbuf = CALLOC(rptr->rl_size))) {
		db_rcdone(rptr);
		RETERR(INSMEM)
	}

	tbuf[0] = ACTIVE;

	for (tcnt = 0; db_fetch(slptr); tcnt++) {

		abase = 1;
		for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
			for (i = 0; i < saptr->sa_attr->at_size; i++)
				tbuf[abase + i] = saptr->sa_aptr[i];

			abase += i;
		}

		if (cwrite(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) {
			db_rcdone(rptr);
			CFREE(tbuf);
			RETERR(INSBLK)
		}
		rptr->rl_tcnt++;
		rptr->rl_tmax++;
	}

	db_done(slptr);

	if (!db_rcdone(rptr))
		return (FALSE);

	pcount(tcnt,"found");

	return (TRUE);
}

pcount(tcnt, mess)
	int tcnt; char *mess;
{
	if (tcnt)
		printf("[ %d records %s ]\n",tcnt,mess);
	else
		printf("[ No records %s ]\n",mess);
	return (TRUE);
}

int db_to(pfp,ext)
	FILE **pfp; char *ext;
{

	*pfp = STDOUT;

	if (db_token() != INTO)
		return (TRUE);
	db_ntoken();
	if (db_ntoken() == ID)
		strcat(dbv_tstring,ext);
	else if (dbv_token != STRING)
		{ RETERR(SYNTAX) }

	if (db_scmp(dbv_tstring,"lst.rep") == 0) {
		*pfp = STDLST;
		return (TRUE);
		}

	*pfp = &obuf;
	fcreat(dbv_tstring,&obuf);

	if (*pfp == -1)
		{ RETERR(OUTCRE) }

	return (TRUE);
}

int using(pfp,ext)
 char **pfp; char *ext;
{
	FILE *ffd;
	unsigned ffsize;

	*pfp = NULL;

	if (db_token() != USING)
		return (TRUE);
	db_ntoken();
	if (db_ntoken() == ID)
		strcat(dbv_tstring,ext);
	else if (dbv_token != STRING)
		{ RETERR(SYNTAX) }

	if ((ffd = open(dbv_tstring,0)) == -1) {
		RETERR(INPFNF)
		}

	ffsize = cfsize(ffd);

	if ((*pfp = CALLOC(ffsize*128)) == NULL) {
		close(ffd);
		RETERR(INSMEM)
		}
	
	if (read(ffd,*pfp,ffsize) != ffsize) {
		close(ffd);
		CFREE(*pfp);
		RETERR(INPFNF)
		}

	close(ffd);
	return(TRUE);
}

int table(fp,slptr)
	FILE *fp; struct sel *slptr;
{
	int tcnt;

	for (tcnt = 0; db_fetch(slptr); tcnt++) {

		if (!tcnt)
			db_thead(fp,slptr);

		db_tentry(fp,slptr);
	}

	if (tcnt)
		db_tfoot(fp,slptr);

	return (tcnt);
}

int form(ofp,slptr,ffp)
	FILE *ofp; struct sel *slptr; char *ffp;
{
	char aname[ANSIZE+1];
	char *anptr;
	int ch,tcnt,rsf,kbrep;

	char *fbs,*fhs;	/* form buffer,header start */

	fhs = fbs = ffp;	/* stash them */
	kbrep = 0;	/* indicate o.k. */

	if ((ch = *ffp) == '%') {		/* see if heading */
		*ffp = 0;		/* make it a null */
		ffp++;
		while (((ch = *ffp++) != '%') && (ch != CPMEOF))
			;
		if (ch == '%') {
			ffp--;
			*ffp++ = 0;	/* make it a null */
			fbs = ffp;	/* not if eof! */
			}
		}
	
	dbv_lnct = 0;	/* force first heading */

	for (tcnt = 0; db_fetch(slptr); tcnt++) {

		if (dbv_lnct == 0) {
			dbv_lnct = dbv_pgln;
			dbv_page++;
			ffp = fhs;
		} else
			ffp = fbs;	/* reposition at start */
		dbv_lnct--;

		while ((ch = *ffp++) != CPMEOF)
			if ((ch == '<') || (ch == '>')) {
				rsf = FALSE;
				anptr = &aname;
				while (((ch = *ffp++) != '>') && (ch != '<')
					&& (ch != CPMEOF))
					if (!isspace(ch))
						*anptr++ = ch;
				if (ch == '>') rsf = TRUE;
				*anptr = 0;
				if (aname[0] == '#')
					fprintf(ofp,"%d",dbv_page);
				else
					put_avalue(ofp,slptr,aname,rsf);
			}
			else if (ch == '?') {		/* indicates pause */
				printf("Press ENTER to continue, ^Z to abort\n");
				kbrep = getchar();
			}
			else
				putc(ch,ofp);
		if (kbrep == -1) break;
	}

	return (tcnt);
}

put_avalue(fp,slptr,aname,rsf)
	char *fp; struct sel *slptr; char *aname; int rsf;
{
	struct sattr *saptr;
	char *saname;
	int i,fpd;

	for (saptr = slptr->sl_attrs; saptr ; saptr = saptr->sa_next) {

		if (!(saname = saptr->sa_name))
			saname = saptr->sa_aname;
		if (!db_scmp(saname,aname))
			break;
	}

	if (!saptr) {
		fprintf(fp,"<*****>");
		return;
	}

	fpd = FALSE;
	for (i = 0; i < saptr->sa_attr->at_size; i++) 
		if (saptr->sa_aptr[i]) {
			if (saptr->sa_aptr[i] == ' ') {
				if ((rsf) || (fpd))
					putc(saptr->sa_aptr[i],fp);
				}
			else {			
				putc(saptr->sa_aptr[i],fp);
				fpd = TRUE;
				}
			}
		else
		    if (rsf)
			putc(' ',fp);
}

}
			else {			
				putc(saptr->sa_aptr[i],fp);
				fpd = TRUE;