# include	<ingres.h>
# include	<aux.h>
# include	<tree.h>
# include	<symbol.h>
# include	<pv.h>
# include	"globs.h"
# include	<sccs.h>

SCCSID(@(#)exec_sq.c	8.1	12/31/84)

/*
** DECOMP2 -- Routines for executing detached sub-queries appearing
**	in sqlist. These routines include:
**
**	exec_sq -- execute sub-queries and update range table.
**
**	undo_sq -- restore range table and destroy temp rels.
**
**	reset_sq - restore range table and reset temp rels.
**
**	execsq1 -- call ovqp with subquery.
*/
/*
**  EXEC_SQ
**
**	Execute the subqueries in sqlist. Associated with
**	each sub-query is a relation number stored in sqrange.
**	If the sub-query has a non-null target list, the range
**	table is updated to reflect the new range of the relation.
**
**	If any sub-query is false, all subsequent ones are ignored
**	by ovqp and exec_sq returns the var number of the false subquery.
**
**	As a side effect, "disj" is incremented for each disjoint sub-query
**
**	Trace Flags:
**		35
*/

exec_sq(sqlist, sqrange, disj)
QTREE	*sqlist[];
int	sqrange[];
int	*disj;
{
	register QTREE	*sq;
	register int	i, qualfound;
	extern DESC	*openr1();

#	ifdef xDTR1
	if (tTf(35, 0))
		printf("EXEC_SQ--\n");
#	endif

	*disj = 0;

	for (i = 0; i < MAXRANGE; i++)
	{
		if (sq = sqlist[i])
		{
#			ifdef xDTR1
			if (tTf(35, 1))
				printf("sq[%d]=%x\n", i, sq);
#			endif
			qualfound = execsq1(sq, i, sqrange[i]);

#			ifdef xDTR1
			if (tTf(35, 2))
				printf("qualfound=%d\n", qualfound);
#			endif
			if (!qualfound)
			{
				return(i);
			}
			if (sq->left->sym.type != TREE)
			{
				/*
				** Update the range table and open
				** the relation's restricted replacement.
				*/
				new_range(i, sqrange[i]);
				openr1(i);
			}
			else
			{
				(*disj)++;
			}
		}
	}
	return (-1);
}
/*
**  UNDO_SQ
**
**	Undo the effects of one variable detachment on
**	the range table. The two parameters "limit" and
**	"maxlimit" describe how far down the list of
**	subqueries were processed.  Maxlimit represents
**	the furthest every attained and limit represents
**	the last variable processed the last time.
**
**	Trace Flags:
**		36
*/

undo_sq(sqlist, locrang, sqrange, limit, maxlimit, reopen)
QTREE	*sqlist[];
int	locrang[];
int	sqrange[];
int	limit;
int	maxlimit;
int	reopen;
{
	register QTREE	*sq;
	register int	i, lim;
	bool		dstr_flag;

#	ifdef xDTR1
	if (tTf(36, 0))
		printf("UNDO_SQ--\n");
#	endif

	initp();	/* setup parm vector for destroys */
	lim = limit == -1 ? MAXRANGE : limit;
	if (maxlimit == -1)
		maxlimit = MAXRANGE;

	for (i = 0; i < MAXRANGE; i++)
		if (sq = sqlist[i])
		{
			if (sq->left->sym.type != TREE)
			{
				if (i < lim)
				{
					/* The query was run. Close the temp rel */
					closer1(i);
				}

				/* mark the temporary to be destroyed */
				dstr_mark(sqrange[i]);
				dstr_flag = TRUE;

				/* reopen the original relation. If maxlimit
				** never reached the variable "i" then the
				** original relation was never closed and thus
				** doesn't need to be reopened.
				*/
				rstrang(locrang, i);
				if (reopen && i < maxlimit)
					openr1(i);
			}
		}
	/* Only call destroy if there's something to destroy */
	if (dstr_flag)
		call_dbu(mdDESTROY, FALSE);
	else
		resetp();

}
/*
** Execsq1 -- call ovqp with mdRETR on temp relation
*/

execsq1(sq, var, relnum)
QTREE 	*sq;
int	var;
int	relnum;
{
	register int	qualfound;

	De.de_sourcevar = var;
	De.de_newq = 1;
	qualfound = call_ovqp(sq, mdRETR, relnum);
	return (qualfound);
}
/*
**	Reset each relation until limit.
**	Reset will remove all tuples from the
**	relation but not destroy the relation.
**	The descriptor for the relation will be removed
**	from the cache.
**
**	The original relation is returned to
**	the range table.
**
**	If limit is -1 then all relations are done.
*/

reset_sq(sqlist, locrang, limit)
QTREE	*sqlist[];
int	locrang[];
int	limit;
{
	register QTREE	*sq;
	register int	i, lim;
	int		old, reset;
	extern char	*rnum_convert();

	lim = limit == -1 ? MAXRANGE : limit;
	reset = FALSE;
	initp();

	for (i = 0; i < lim; i++)
		if ((sq = sqlist[i]) && sq->left->sym.type != TREE)
		{
			old = new_range(i, locrang[i]);
			setp(PV_STR, rnum_convert(old));
			specclose(old);
			reset = TRUE;
		}

	if (reset)
	{
		/*
		** Guarantee that OVQP will not reuse old
		** page of relation being reset
		*/
		De.de_newr = TRUE;
		call_dbu(mdRESETREL, FALSE);
	}
	else
		resetp();
}
