void
itof(register sym_t *p)
{

#ifdef xOTR3
	if (tTf(87, 2)) {
		printf("itof: ");
		prsym(p);
	}
#endif

	if (p->len == 4)
		p->value.sym_data.f8type = p->value.sym_data.i4type;
	else if (p->len == 2)
		p->value.sym_data.f8type = p->value.sym_data.i2type;
	else
		p->value.sym_data.f8type = p->value.sym_data.i1type;
	p->type = FLOAT_CONST;
	p->len= 8;
#ifdef xOTR3
	if (tTf(87, 2)) {
		printf("itof rets: ");
		prsym(p);
	}
#endif
}
Beispiel #2
0
int
get(desc_t *d, tid_t *tid, tid_t *limtid, void *tuple, int getnxt)
{
	register int	i;
	long		pageid, lpageid;

#ifdef xATR1
	if (tTf(23, 0)) {
		printf("get: %.14s,", d->d_r.r_id);
		dumptid(tid);
		printf("get: lim");
		dumptid(limtid);
	}
#endif
	if (get_page(d, tid)) {
		return (-1);
	}
	if (getnxt) {
		pluck_page(limtid, &lpageid);
		do {
			while (((++(tid->line_id)) & I1MASK) >= Acc_head->am_nextline) {
				tid->line_id = -1;
				pageid = Acc_head->am_overflowpg;
				stuff_page(tid, &pageid);
				if (pageid == 0) {
					pageid = Acc_head->am_mainpg;
					stuff_page(tid, &pageid);
					if (pageid == 0 || pageid == lpageid + 1)
						return (1);
				}
				if ((i = resetacc(Acc_head)) != 0)
					return (i);
				if ((i = get_page(d, tid)) != 0)
					return (i);
			}
		} while (!Acc_head->am_linev[-(tid->line_id & I1MASK)]);
	} else {
		if ((i = invalid(tid)) != 0)
			return (i);
	}
	get_tuple(d, tid, tuple);
#ifdef xATR2
	if (tTf(23, 1)) {
		printf("get: ");
		printup(d, tuple);
	}
#endif
	return (0);
}
int
display(int pc, paramv_t *pv)
{
	register int	ac;
	register paramv_t	*av;
	int		err;
	char		err_array[PV_MAXPC];
	int	mode;

#ifdef xZTR1
	if (tTf(50, -1)) {
		printf("display: ");
		prvect(pc, pv);
	}
#endif

	err = 0;
	if (pc % 2 != 0)
		syserr("display: bad param count %d", pc);
	opencatalog("tree", OR_READ);

	for (ac = 0, av = pv; ac < pc; av++, ac++) {
		mode = atoi(av->pv_val.pv_str);
		av++;
		err_array[ac++] = 0;
		err_array[ac] = disp(av->pv_val.pv_str, mode);
	}
	for (ac = 0, av = pv; ac < pc; av++, ac++) {
		if (err_array[ac])
			err = error(DISPERRBASE + err_array[ac], (av->pv_val).pv_str, 0);
	}
	return (err);
}
/*
**	Check the range table to see if any
**	relations changed since the last call
**	to newquery. If so, they were caused
**	by reformat. Restore back the orig relation
**	Reopen it if reopen == TRUE.
*/
void
endquery(int *locrang, int reopen)
{
	register struct rang_tab	*rp;
	register int			*ip, i;
	int				old;
	bool				dstr_flag;

	rp = De.de_rangev;
	ip = locrang;

	dstr_flag = FALSE;
	initp();
	for (i = 0; i < MAX_RANGES; i++) {
		if (rp->relnum != *ip) {
#ifdef xDTR1
			if (tTf(63, -1))
			printf("reformat or reduct changed var %d (%d,%d)\n", i, *ip, rp->relnum);
#endif

			old = new_range(i, *ip);
			dstr_flag |= dstr_mark(old);
			if (reopen)
				openr1(i);
		}

		ip++;
		rp++;
	}

	if (dstr_flag)
		call_dbu(mdDESTROY, FALSE);
	else
		resetp();
}
/*
**  PR_INTEGRITY -- print out integrity constraints on a relation
**
**	Finds all integrity tuples for this unique relation, and
**	calls pr_int() to print a query from them.
**
**	Parameters:
**		relid -- rel name
**		relowner -- 2 byte owner id
**
**	Returns:
**		none
**
**	Side Effects:
**		file activity, query printing
**
**	Trace Flags:
**		33, 9
*/
void
pr_integrity(char *relid, char *relowner)
{
	extern desc_t		Intdes;
	tid_t			hitid, lotid;
	struct integrity	key, tuple;
	register int		i;


#ifdef xZTR1
	if (tTf(50, 9))
		printf("pr_integrity(relid =%s, relowner=%s)\n", 
			relid, relowner);
#endif

	printf("Integrity constraints on %s are:\n\n", relid);
	opencatalog("integrities", OR_READ);

	/* get integrities tuples for relid, relowner */
	clearkeys(&Intdes);
	ingres_setkey(&Intdes, &key, relid, INTRELID);
	ingres_setkey(&Intdes, &key, relowner, INTRELOWNER);
	if ((i = find(&Intdes, EXACTKEY, &lotid, &hitid, &key)) != 0)
		syserr("pr_integrity: find %d", i);
	for (;;) {
		if ((i = get(&Intdes, &lotid, &hitid, &tuple, TRUE)) != 0)
			break;
		if (kcompare(&Intdes, &tuple, &key) == 0)
			pr_int(&tuple, relid);
	}
	if (i != 1)
		syserr("pr_integrity: get %d", i);
}
Beispiel #6
0
branch()
{
	register char	c;
	register int	i;
	extern char	getch();

#	ifdef xMTR2
	if (tTf(16, -1))
		printf(">>branch: ");
#	endif

	/* see if conditional */
	while ((c = getch()) > 0)
		if (c != ' ' && c != '\t')
			break;
	if (c == '?')
	{
		/* got a conditional; evaluate it */
		Oneline = TRUE;
		macinit(&getch, 0, 0);
		i = expr();

		if (i <= 0)
		{
			/* no branch */
#			ifdef xMTR2
			if (tTf(16, 0))
				printf("no branch\n");
#			endif
			getfilename();
			return;
		}
	}
	else
	{
		Peekch = c;
	}

	/* get the target label */
	if (branchto(getfilename()) == 0)
		if (branchto(macro("{default}")) == 0)
		{
			Peekch = -1;
			printf("Cannot branch\n");
		}
	return;
}
/*
**  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
*/
int
exec_sq(qtree_t **sqlist, int *sqrange, int *disj)
{
	register qtree_t	*sq;
	register int	i, qualfound;

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

	*disj = 0;

	for (i = 0; i < MAX_RANGES; i++) {
		if ((sq = sqlist[i]) != 0) {
#ifdef xDTR1
			if (tTf(35, 1))
				printf("sq[%d]=%p\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);
}
void
i4toi2(sym_t *pp)
{
	register sym_t	*p;

#ifdef xOTR3
	if (tTf(87, 1)) {
		printf("i4toi2: ");
		prsym(pp);
	}
#endif
	p = pp;

	*(i2type *)&p->value = *(i4type *)&p->value;
	p->len = 2;
#ifdef xOTR3
	if (tTf(87, 1)) {
		printf("i4toi2 rets: ");
		prsym(p);
	}
#endif
}
void
i2toi4(sym_t *pp)
{
	register sym_t	*p;

#ifdef xOTR3
	if (tTf(87, 0)) {
		printf("i2toi4: ");
		prsym(pp);
	}
#endif
	p = pp;

	*(i4type *)&p->value = *(i2type *)&p->value;
	p->len = 4;
#ifdef xOTR3
	if (tTf(87, 0)) {
		printf("i2toi4 rets: ");
		prsym(p);
	}
#endif
}
void
ftoi4(register sym_t *p)
{
#ifdef xOTR3
	if (tTf(87, 4)) {
		printf("ftoi4: ");
		prsym(p);
	}
#endif

	if (p->len == 4)
		p->value.sym_data.i4type = p->value.sym_data.f4type;
	else
		p->value.sym_data.i4type = p->value.sym_data.f8type;
	p->type = INT_CONST;
	p->len = 4;
#ifdef xOTR3
	if (tTf(87, 4)) {
		printf("ftoi4 rets: ");
		prsym(p);
	}
#endif
}
/*
**  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
*/
void
undo_sq(qtree_t **sqlist, int *locrang, int *sqrange, int limit, int maxlimit, int reopen)
{
	register qtree_t	*sq;
	register int	i, lim;
	bool		dstr_flag;

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

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

	for (i = 0; i < MAX_RANGES; i++)
		if ((sq = sqlist[i]) != 0) {
			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();

}
Beispiel #12
0
/*
**  MERGEVAR -- merge variable numbers to link terms
**
**	One specified variable gets mapped into another, effectively
**	merging those two variables.  This is used for protection
**	and integrity, since the constraint read from the tree
**	must coincide with one of the variables in the query tree.
**
**	Parameters:
**		va -- the variable which will dissappear.
**		vb -- the variable which 'va' gets mapped into.
**		root -- the root of the tree to map.
**
**	Returns:
**		none
**
**	Side Effects:
**		The tree pointed at by 'root' gets VAR and RESDOM
**			nodes mapped.
**		Range table entry for 'va' is deallocated.
**		The 'Qt.qt_remap' vector gets reset and left in an
**			undefined state.
**
**	Trace Flags:
**		72
*/
void
mergevar(register int a, register int b, qtree_t *root)
{
	register int	i;

#ifdef xQTR1
	if (tTf(72, 0)) {
		printf("\nmergevar(%d->%d)", a, b);
		treepr(root);
	}
#endif

	/*
	**  Insure that 'a' and 'b' are consistant, that is,
	**  that they both are in range, are defined, and range over
	**  the same relation.
	*/

	if (a < 0 || b < 0 || a >= MAX_VARS + 1 || b >= MAX_VARS + 1)
		syserr("mergevar: range %d %d", a, b);
	if (Qt.qt_rangev[a].rngvdesc == NULL || Qt.qt_rangev[b].rngvdesc == NULL)
		syserr("mergevar: undef %d %d", a, b);
	if (!bequal(Qt.qt_rangev[a].rngvdesc->d_r.r_id,
		    Qt.qt_rangev[b].rngvdesc->d_r.r_id, MAX_NAME_SIZE) ||
	    !bequal(Qt.qt_rangev[a].rngvdesc->d_r.r_owner,
		    Qt.qt_rangev[b].rngvdesc->d_r.r_owner, 2)) {
		syserr("mergevar: incon %.14s %.14s",
		    Qt.qt_rangev[a].rngvdesc->d_r.r_id,
		    Qt.qt_rangev[b].rngvdesc->d_r.r_id);
	}
	
	/*
	**  To do the actual mapping, we will set up 'Qt.qt_remap' and
	**  call 'mapvars()'.  This is because I am too lazy to
	**  do it myself.
	*/

	for (i = 0; i < MAX_RANGES; i++)
		Qt.qt_remap[i] = i;
	Qt.qt_remap[a] = b;
	mapvars(root);

	/* delete a from the range table */
	declare(a, NULL);
}
/*
**  PR_DEF -- Print "define view" query of a view
**
**	Parameters:
**		relation -- relation in question
**		owner -- relowner
**
**	Returns:
**		none
**
**	Side Effects:
**		reads a tree, clears range table
**
**	Trace Flags:
**		33, 9
*/
void
pr_def(char *relation, char *owner)
{
	register qtree_t	*t;

#ifdef xZTR1
	if (tTf(50, 9))
		printf("pr_def(relation=\"%s\", owner=%s)\n", relation, owner);
#endif

	printf("View %s defined:\n\n", relation);
	clrrange();

	/* Treeid == 0 because views have only one definition */
	t = gettree(relation, owner, mdVIEW, 0,FALSE);
	pr_range();
	printf("define view ");
	pr_tree(t);
}
/* 
** DISP -- display integrity, permit, or define query on a relation
**
**	Finds a relation owned by the user or the DBA and passes
**	the name and owner to the appropritae routine depending on
**	mode.
**
**	Parameters:
**		relation -- relation on which query is to be printed
**		mode -- the print mode:
**			4 -- view
**			5 -- permit
**			6 -- integrity
**
**	Returns:
**		0 -- success
**		1 -- no such relation, or none seeable by the user.
**		3 -- VIEW mode and relation not a view
**		4 -- PERMIT and no permissions on relation
**		5 -- INTEGRITY mode and no integrity constraints
**
**	Trace Flags:
**		33, 8
*/
int
disp(char *relation, int mode)
{
	desc_t		d;
	register int	i;
	extern char	*Resrel;

#ifdef xZTR1
	if (tTf(50, 8))
		printf("disp: relation %s\n", relation);
#endif

	Resrel = relation;
	i = openr(&d, OR_RELTID, relation);
	if (i > 0)
		return (1);
	else if (i < 0)
		syserr("disp: openr(%s) ret %d", relation, i);
	switch (mode) {
	  case 4:		/* View query */
		if (d.d_r.r_status & S_VIEW)
			pr_def(relation, d.d_r.r_owner);
		else 
			return (3);
		break;

	  case 5:
		if (pr_prot(relation, (relation_t *) &d))
			return (4);
		break;

	  case 6:
		if (d.d_r.r_status & S_INTEG)
			pr_integrity(relation, d.d_r.r_owner);
		else
			return (5);
		break;

	  default:
		syserr("disp: mode == %d", mode);
	}
	return (0);
}
/*
**  CM_CLEANUP -- cleanup after interrupt or error.
**
**	This routine does things like call the interrupt cleanup
**	function, reset the input, etc.
**
**	Parameters:
**		typ -- the type of cleanup:
**			1 -- fatal error (from error [error.c]).
**			2 -- keyboard interrupt.
**
**	Returns:
**		never (uses non-local jump to ctlmod/main.c).
**
**	Side Effects:
**		Proc_name & Cm.cm_input are reset.
**
**	Trace Flags:
**		0
*/
void
cm_cleanup(int typ)
{
	register int		i;
	register func_t	*f;
	extern jmp_buf		CmReset;
	register ctx_t		*ctx;

#ifdef xCTR2
	if (tTf(0, 13))
		printf("cm_cleanup: %d\n", typ);
#endif

	/*
	**  Call all interrupt cleanup functions for active
	**	modules.
	*/

	for (i = 0; i < NumFunc; i++) {
		f = FuncVect[i];
		if (f->fn_active > 0) {
			setprocname(Ctx.ctx_name = f->fn_name);
			(*f->fn_cleanup)(typ);
		}
	}

	/* clean up memory */
	for (ctx = &Ctx; ctx != NULL; ctx = ctx->ctx_link) {
		if (ctx->ctx_qt != NULL) {
			xfree(ctx->ctx_qt);
		}
		if (ctx->ctx_glob != NULL) {
			bmove(ctx->ctx_glob, ctx->ctx_fn->fn_gptr, ctx->ctx_fn->fn_gsize);
			xfree(ctx->ctx_glob);
		}
	}

	/* return to top of loop */
	longjmp(CmReset, typ);
}
Beispiel #16
0
/*
**  PB_PUT -- buffered put on pipe
**
**	This routine puts the named data out onto the pipe
**	determined by ppb->pb_proc.
**
**	Parameters:
**		dp -- a pointer to the data to write.
**		len -- the length of the data to write.
**		ppb -- a pointer to the pipe block.
**
**	Returns:
**		none
**
**	Side Effects:
**		none
**
**	Trace Flags:
**		18.8 - 18.15
*/
void
pb_put(register char *dp, register int len, register pb_t *ppb)
{
	register int	i;

#ifdef xCTR2
	if (tTf(18, 9))
		lprintf("pb_put: len %d\n", len);
#endif

	/*
	**  Top loop.
	**	Loop until we have run out of things to write.
	*/

	while (len > 0) {
		/* compute the length to move */
		i = min(ppb->pb_nleft, len);
#ifdef xCM_DEBUG
		if (i <= 0)
			syserr("pb_put: zero");
#endif

		/* move data into buffer and adjust ptrs & counts */
		bmove(dp, ppb->pb_xptr, i);
		dp += i;
		len -= i;
		ppb->pb_xptr += i;
		ppb->pb_nleft -= i;
		ppb->pb_nused += i;

		/* flush block if full */
		if (ppb->pb_nleft <= 0)
			pb_write(ppb);
	}
}
Beispiel #17
0
int
copy(int pc, paramv_t *pv)
{
	extern char	*Usercode;
	extern int	Noupdt;
	register int	i, pid;
	register char	*cp;
	int		stat;
	int		op;

#ifdef xZTR1
	if (tTf(30,1)) {
		printf("entered copy\n");
		prvect(pc, pv);
	}
#endif
	Duptuple = 0;
	Truncount = 0;
	Tupcount = 0;
	Baddoms = 0;
	Relname = pv[0].pv_val.pv_str;
	Into = (pv[pc-2].pv_val.pv_str[0] == 'i');
	Filename = pv[pc-1].pv_val.pv_str;

	/* relation must exist and not be a system relation */
	/* in addition a copy "from" can't be done if the user */
	/* doesn't own the relation */
	/* and furthermore it can't have an index */
	i = 0;	/* assume all is well */
	if ((op = openr(&Des, OR_WRITE, Relname)) != 0) {
		if (op == AMOPNVIEW_ERR)
			i = NOCPVIEW;
		else {
			if (op < 0)
				syserr("COPY: openr 1 (%.14s) %d", Relname, op);
			else
				/* non-existant relation */
				i = NOEXIST;
		}
	} else {
		if (Into) {
			if ((Des.d_r.r_status & S_PROTALL)
				&& (Des.d_r.r_status & S_PROTRET)
				&& !bequal(Usercode, Des.d_r.r_owner, USERCODE_SIZE))
				i = RELPROTECT;
		} else {
			/* extra checking if this is a copy "from" */

			/* must be owned by the user */
			if (!bequal(Usercode, Des.d_r.r_owner, USERCODE_SIZE))
				i = NOTOWNER;
			else
				/* must be updateable */
				if ((Des.d_r.r_status & S_NOUPDT) && Noupdt)
					i = NOUPDT;
				else
					/* must not be indexed */
					if (Des.d_r.r_indexed > 0)
						i = DESTINDEX;
		}
	}
	if (i) {
		closer(&Des);
		return (error(i, Relname, 0));	/* relation doesn't exist for this user */
	}

	/* check that file name begins with a "/" */
	cp = Filename;
	while (*cp == ' ')
		cp++;
	if (*cp != '/') {
		closer(&Des);
		return (error(FULLPATH, Filename, 0));
	}

	/* fill map structures with transfer information */
	if ((i = mapfill(&pv[1])) != 0) {
		closer(&Des);
		return (i);	/* error in user semantics */
	}

	/* fork a child process which will run as the real user */
	/* that child will complete the copy and exit */
	if (pipe(Piped))
		syserr("copy:can't make pipe");
	if ((pid = fork()) < 0)
		syserr("copy:can't fork");
	if (pid) {
		/* the ingres parent */
		close(Piped[1]);
		ruboff(0);	/* interrupts off */
		stat = fullwait(pid, "copy");
		if (read(Piped[0], &Des.d_addc, 4) != 4)
			syserr("copy:can't read pipe");
		close(Piped[0]);
		closer(&Des);	/* close the rel */
		rubon();
		/* if stat is != 0 then add on 5800 for error */
		if (stat)
			stat += 5800;
		return (stat);	/* done */
	}

	/* the child. change to run as the real user */
	if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
		signal(SIGINT, copydone);	/* clean up on rubout */
	}
	setuid(getuid());
	setgid(getgid());
	if (Into) {
		/* from relation into file */
		if ((File_iop = fopen(Filename, "w")) == NULL) /* create file for user */
			i = nferror(NOFILECRT, Filename, 0);	/* cant create file */
		else {
			if (Lockrel)	/* set a shared lock on relation*/
				setrll(A_SLP, &Des.d_tid, M_SHARE);
			i = rel_file();
		}
	} else {
		/* from UNIX file into relation */
		if ((File_iop = fopen(Filename, "r")) == NULL)
			i = nferror(NOFILEOPN, Filename, 0);	/* cant open user file */
		else {
			if (Lockrel)	/* set an exclusive lock on relat*/
				setrll(A_SLP, &Des.d_tid, M_EXCL);
			i = file_rel();
			if (Duptuple)
				nferror(DUPTUPS, locv(Duptuple), 0);	/* warning only */
			if (Baddoms)
				nferror(BADDOMS, locv(Baddoms), 0);	/* warning only */
		}
	}
	copydone(i);
	return(0);
}
Beispiel #18
0
qryproc()
{
	register struct querytree	*root, *q;
	register int			i;
	int				mode, result_num, retr_uniq;
	struct querytree		*trbuild();
	extern long			Accuread, Accuwrite, Accusread;
	extern int			derror();
	extern struct querytree		*readqry();

#	ifdef xDTM
	if (tTf(76, 1))
		timtrace(23, 0);
#	endif
#	ifdef xDTR1
	if (tTf(50, 0))
	{
		Accuread = 0;
		Accusread = 0;
		Accuwrite = 0;
	}
#	endif

	/* initialize query buffer */
	initbuf(Qbuf, QBUFSIZ, QBUFFULL, &derror);

	/* init various variables in decomp for start of this query */
	startdecomp();

	/* Read in query, range table and mode */
	root = readqry();
	mode = Qmode;

	/* Initialize relation descriptors */
	initdesc(mode);

	/* re-build the tree */
	root = trbuild(root);
	if (root == NULL)
		derror(STACKFULL);


	/* locate pointers to QLEND and TREE nodes */
	for (q = root->right; q->sym.type != QLEND; q = q->right);
	Qle = q;

	for (q = root->left; q->sym.type != TREE; q = q->left);
	Tr = q;


	/* map the complete tree */
	mapvar(root, 0);

	/* set logical locks */
	if (Lockrel)
		lockit(root, Resultvar);

	/* If there is no result variable then this must be a retrieve to the terminal */
	Qry_mode = Resultvar < 0 ? mdRETTERM : mode;

	/* if the mode is retrieve_unique, then make a result rel */
	retr_uniq = mode == mdRET_UNI;
	if (retr_uniq)
	{
		mk_unique(root);
		mode = mdRETR;
	}

	/* get id of result relation */
	if (Resultvar < 0)
		result_num = NORESULT;
	else
		result_num = Rangev[Resultvar].relnum;

	/* evaluate aggregates in query */
	aggregate(root);

	/* decompose and process aggregate free query */
	decomp(root, mode, result_num);

	/* If this is a retrieve unique, then retrieve results */
	if (retr_uniq)
		pr_unique(root, Resultvar);

	if (mode != mdRETR)
		i = ACK;
	else
		i = NOACK;
	i = endovqp(i);

	/* call update processor if batch mode */
	if (i == UPDATE)
	{
		initp();
		call_dbu(mdUPDATE, -1);
	}


	/*
	** send eop back to parser to indicate completion
	** if UPDATE then return block comes from dbu else
	** return block comes from decomp
	*/
	writeback(i == UPDATE ? -1 : 1);

#	ifdef xDTM
	if(tTf(76, 1))
		timtrace(24,0);
#	endif
#	ifdef xDTR1
	if (tTf(50, 1))
	{
		printf("DECOMP read %s pages,", locv(Accuread));
		printf("%s catalog pages,", locv(Accusread));
		printf("wrote %s pages\n", locv(Accuwrite));
	}
#	endif

	/* clean decomp */
	reinit();

	/* return */
}
/*
** STRATEGY
**
**	Attempts to limit access scan to less than the entire De.ov_source
**	relation by finding a key which can be used for associative
**	access to the De.ov_source reln or an index thereon.  The key is
**	constructed from domain-value specifications found in the
**	clauses of the qualification list using sub-routine findsimp
**	in findsimp.c and other subroutines in file key.c
*/
int
strategy(void)
{
	register int		i, allexact;
	acc_param_t	sourceparm, indexparm;
	index_t		itup, rtup;
	key_t		lowikey[MAX_2ND_KEYS+1], highikey[MAX_2ND_KEYS+1];
	key_t		lowbkey[MAX_2ND_KEYS+1], highbkey[MAX_2ND_KEYS+1];
	register desc_t		*d;
	extern desc_t		Inddes;
	char 			*tp;
	long			l_lid[MAXLID], h_lid[MAXLID];
	int			keytype;
	long			page, l, t;
	int			lidsize;
	locator_t		tidloc;

	keytype = allexact = 0;
#ifdef xOTR1
	if (tTf(70, 0))
		printf("STRATEGY\tSource=%.12s\tNewq = %d\n",
		       De.ov_source ? De.ov_source->d_r.r_id : "(none)",
		       De.de_newq);
#endif

	while (De.de_newq)	/* if De.de_newq=TRUE then compute a new strategy */
			/* NOTE: This while loop is executed only once */ {
		De.ov_scanr = De.ov_source;
	
		if (!De.ov_scanr)
			return (1);	/* return immediately if there is no source relation */
	
		De.ov_fmode = NOKEY;	/* assume a find mode with no key */
	
		if (!De.ov_qlist)
			break;	/* if no qualification then you must scan entire rel */
		/*
		** Here we check for the special condition
		** of a where clause consisting only of a tid.
		*/
		if (tid_only_test())
			return(1);

		/* copy structure of source relation into sourceparm */
		paramd(De.ov_source, &sourceparm);
	
		/* if source is unkeyed and has no sec index then give up */
		if (sourceparm.mode == NOKEY && De.ov_source->d_r.r_indexed <= 0 && !De.ov_source->d_r.r_dim)
			break;

		/* find all simple clauses if any */
		if (!findsimps())
			break;	/* break if there are no simple clauses */
	
		/* Four steps are now performed to try and find a key.
		** First if the relation is hashed then an exact key is search for
		**
		** Second if there are secondary indices, then a search is made
		** for an exact key. If that fails then a  check is made for
		** a range key. The result of the rangekey check is saved.
		**
		** A step to check for possible use of Btrees is made here,
		** although in actuality, an exact btreekey search is used
		** after an exact range key search but before a range key search.
		** A BTree range search is used only as a last alternative
		** to a no key search.
		**
		** Third if the relation is an ISAM a check is  made for
		** an exact key or a range key.
		**
		** Fourth if there is a secondary index, then if step two
		** found a key, that key is used.
		**
		**  Lastly, give up and scan the  entire relation
		*/
	
		/* step one. Try to find exact key on primary */
		if (exactkey(&sourceparm, De.ov_lkey_struct)) {
			De.ov_fmode = EXACTKEY;
			break;
		}
	
		/* step two. If there is an index, try to find an exactkey on one of them */
		if (De.ov_source->d_r.r_indexed > 0) {
	
			opencatalog("indices", OR_READ);
			ingres_setkey(&Inddes, &itup, De.ov_source->d_r.r_id, IRELIDP);
			ingres_setkey(&Inddes, &itup, De.ov_source->d_r.r_owner, IOWNERP);
			if ((i = find(&Inddes, EXACTKEY, &De.ov_lotid, &De.ov_hitid, (char *)&itup)) != 0)
				syserr("strategy:find indices %d", i);
	
			while (!(i = get(&Inddes, &De.ov_lotid, &De.ov_hitid, (char *)&itup, NXTTUP))) {
#ifdef xOTR1
				if (tTf(70, 3))
					printup(&Inddes, (char *)&itup);
#endif
				if (!bequal(itup.i_relname, De.ov_source->d_r.r_id, MAX_NAME_SIZE) ||
				    !bequal(itup.i_owner, De.ov_source->d_r.r_owner, 2))
					continue;
				parami(&itup, &indexparm);
				if (exactkey(&indexparm, De.ov_lkey_struct)) {
					De.ov_fmode = EXACTKEY;
					d = openindex(itup.i_index);
					/* temp check for 6.0 index */
					if ((int) d->d_r.r_indexed == -1)
						ov_err(BADSECINDX);
					De.ov_scanr = d;
					break;
				}
				if (De.ov_fmode == LRANGEKEY)
					continue;	/* a range key on a s.i. has already been found */
				if ((allexact = rangekey(&indexparm, lowikey, highikey)) != 0) {
					bmove((char *)&itup, (char *)&rtup, sizeof(itup));	/* save tuple */
					De.ov_fmode = LRANGEKEY;
				}
			}
			if (i < 0)
				syserr("stragery:bad get from index-rel %d", i);
			/* If an exactkey on a secondary index was found, look no more. */
			if (De.ov_fmode == EXACTKEY)
				break;
		}
	
		/* attempt to use Btree in aiding search */
		if ((i = btreekey(lowbkey, highbkey)) != 0) {
			if (i > 0)
				De.ov_fmode = BTREEKEY; 
			else if (De.ov_fmode != LRANGEKEY) {
			/* use range key search over btree range search */
				keytype = i;
				De.ov_fmode = BTREERANGE;
			}
		}

		/* step three. Look for a range key on primary */
		if ((i = rangekey(&sourceparm, De.ov_lkey_struct, De.ov_hkey_struct)) != 0) {
			if (i < 0)
				De.ov_fmode = EXACTKEY;
			else if (De.ov_fmode == BTREEKEY) {
			/* use exact btree search over range search */
				bmove((char *) lowbkey, (char *) De.ov_lkey_struct, sizeof(lowbkey));
				bmove((char *) highbkey, (char *) De.ov_hkey_struct, sizeof(highbkey));
			}
			else
				De.ov_fmode = LRANGEKEY;
			break;
		}

		if (De.ov_fmode == BTREEKEY) {
			bmove((char *) lowbkey, (char *) De.ov_lkey_struct, sizeof(lowbkey));
			bmove((char *) highbkey, (char *) De.ov_hkey_struct, sizeof(highbkey));
			break;
		}
	
		/* last step. If a secondary index range key was found, use it */
		if (De.ov_fmode == LRANGEKEY) {
			if (allexact < 0)
				De.ov_fmode = EXACTKEY;
			d = openindex(rtup.i_index);
			/* temp check for 6.0 index */
			if ((int) d->d_r.r_indexed == -1)
				ov_err(BADSECINDX);
			De.ov_scanr = d;
			bmove((char *)lowikey, (char *)De.ov_lkey_struct, sizeof(lowikey));
			bmove((char *)highikey, (char *)De.ov_hkey_struct, sizeof(highikey));
			break;
		}

		/* nothing will work. give up! */
		break;
	
	}

	/* check for De.de_newq = FALSE and no source relation */
	if (!De.ov_scanr)
		return (1);
	/*
	** At this point the strategy is determined.
	**
	** If De.ov_fmode is EXACTKEY then De.ov_lkey_struct contains
	** the pointers to the keys.
	**
	** If De.ov_fmode is LRANGEKEY then De.ov_lkey_struct contains
	** the pointers to the low keys and De.ov_hkey_struct
	** contains pointers to the high keys.
	**
	** If De.ov_fmode is BTREEKEY then De.ov_lkey_struct contains
	** pointers to the key lid.
	**
	** If De.ov_fmode is BTREERANGE then lowbkey contains pointers
	** to the low key lid and highbkey contains pointers to the
	** high key lid.
	**
	** If De.ov_fmode is NOKEY, then a full scan will be performed
	*/
#ifdef xOTR1
	if (tTf(70, -1))
		printf("De.ov_fmode= %d\n",De.ov_fmode);
#endif

	if (De.ov_fmode == BTREERANGE) {
	/* requires special type of search to limit tid scan */
		for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i) {
			l_lid[i] = 0;
			h_lid[i] = 0;
		}
		lidsize = LIDSIZE * De.ov_scanr->d_r.r_dim;
		/* get low lids */
		if (keytype == -1 || keytype == -3) {
			tp = De.ov_keyl + De.ov_scanr->d_r.r_width - lidsize;
			bmove(l_lid, tp, lidsize);
			setallkey(lowbkey, De.ov_keyl);
			bmove(tp, l_lid, lidsize);
		}
		/* get high lids */
		if (keytype == -2 || keytype == -3) {
			tp = De.ov_keyh + De.ov_scanr->d_r.r_width - lidsize;
			bmove(h_lid, tp, lidsize);
			setallkey(highbkey, De.ov_keyh);
			bmove(tp, h_lid, lidsize);
		}
		setglobalint(BTREE_FD_NAME, De.ov_scanr->d_btreefd);
		/* scan through lids to fill in unprovided lids and to check
		** for lids that are too big
		*/
		page = RT;
		for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i) {
			if (l_lid[i] <= 0) 
				l_lid[i] = 1;
			l = last_lid(page) - 1;
			if (h_lid[i] < 0)
				return(0);
			if (!h_lid[i] || h_lid[i] > l)
				h_lid[i] = l;
			if ((t = get_tid(page, h_lid[i], &tidloc)) < 0)
				syserr("bad gettid in strategy, lid = %ld\n", h_lid[i]);
			page = t;
		}
		/* check whether lo > hi */
		for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i)
			if (l_lid[i] < h_lid[i])
				break;
			else if (l_lid[i] > h_lid[i])
				return(0);
#ifdef xOTR1
		if (tTf(70,0))
			for (i = 0 ; i < De.ov_scanr->d_r.r_dim; ++i)
				printf("hi = %ld, lo = %ld\n", h_lid[i], l_lid[i]);
#endif
		/* find the smallest and largest possible tids of the lids
		** within the provided range */
		btreerange(De.ov_scanr, l_lid, h_lid, &De.ov_lotid, &De.ov_hitid);
	} else {
		/* set up the key tuples */
		if (De.ov_fmode != NOKEY) {
			if (setallkey(De.ov_lkey_struct, De.ov_keyl))
				return (0);	/* query false. There is a simple
						** clause which can never be satisfied.
						** These simple clauses can be choosey!
						*/
		}
	
		if ((i = find(De.ov_scanr, De.ov_fmode, &De.ov_lotid, &De.ov_hitid, De.ov_keyl)) != 0)
			syserr("strategy:find1 %.12s, %d", De.ov_scanr->d_r.r_id, i);

		if (De.ov_fmode == LRANGEKEY) {
			setallkey(De.ov_hkey_struct, De.ov_keyh);
		if ((i = find(De.ov_scanr, HRANGEKEY, &De.ov_lotid, &De.ov_hitid, De.ov_keyh)) != 0)
				syserr("strategy:find2 %.12s, %d", De.ov_scanr->d_r.r_id, i);
		}
	}
	
#ifdef xOTR1
	if (tTf(70, 1)) {
		printf("Lo");
		dumptid(&De.ov_lotid);
		printf("Hi");
		dumptid(&De.ov_hitid);
	}
#endif

	return (1);
}
Beispiel #20
0
/*{
** Name: opn_ukey	- useable key - can inner node be probed
**
** Description:
**
** 	Returns TRUE if there are enough attributes
**	to use the key of the relation.
**
**	The jeqc must be the first element in the ordering that is not 
**	satisfied by a boolfact.  This is because all in order for this 
**	routine to return true, keys 0..N were present in the join node.
**	In opn_sjeqc, we will select the join eqc after reviewing all 
**      possibilities. One of the joined eqc's will be the first in the 
**      order list. If we only return true for this one, it will be joined.
**	This only matters in the BTREE case.  The prnode, in this case is 
**	also sorted on the first equiv class.
**	If we picked an arbitrary eqc as keyed, we may do a needless sort.
**
** Inputs:
**      subquery                        ptr to subquery being analyzed
**      oeqcmp                          available equivalence class map of 
**                                      outer node
**      jeqc                            primary attribute's eqc of key
**      keyedvar		        joinop range variable number of 
**                                      possibly keyed relation
**      primkey                         TRUE - if jeqc must be first joined 
**                                      element of orderlist
**
** Outputs:
**	Returns:
**	    TRUE - if keyed access can be used for join
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	31-may-86 (seputis)
**          initial creation
**	10-jun-96 (inkdo01)
**	    Support for Rtree inners of Kjoins.
[@history_line@]...
*/
bool
opn_ukey(
	OPS_SUBQUERY       *subquery,
	OPE_BMEQCLS        *oeqcmp,
	OPO_ISORT	   jeqc,
	OPV_IVARS          keyedvar,
	bool               primkey)
{
    OPO_STORAGE         storage;	/* storage structure of relation */
    OPV_VARS            *varp;		/* ptr to range variable element to
                                        ** be checked */
    i4                  ordercount;     /* number of attributes that the
                                        ** relation is ordered on */
    i4                  orderindex;     /* index into the OPB_MBF structure
                                        ** of the range variable element */
    OPZ_AT              *abase;         /* ptr to base of array of ptrs to
                                        ** joinop attribute elements */
    bool                ret_val;        /* TRUE is we can do keyed lookup */

    /* Relation must be disk resident */
    if (keyedvar < 0)
	return (FALSE);

    ret_val = FALSE;
    varp = subquery->ops_vars.opv_base->opv_rt[keyedvar]; /* get ptr to range
					** variable element */

    storage = varp->opv_tcop->opo_storage; /* get storage structure 
					** of relation */
    abase = subquery->ops_attrs.opz_base; /* ptr to base of array of ptrs to
                                        ** joinop attribute elements */
#if 0
/* FIXME - why is this check here */    
    if ((storage) < 0)
	storage = -storage;
#endif
# ifdef xNTR1
    if (tTf (1, 0))
    {
	TRdisplay("Checking for possible keyed lookup into %s.\n", Jn.Range[keyedvar]->xrelid);
	TRdisplay("We %s looking for primary join key eqc %d.\n", (primkey ? "are" : "are not"), jeqc);
	TRdisplay("The joinop order eqcs are:");
	for (i = 0; (att = order[i]) > -1; i++)
		TRdisplay("%d ", (i4) Jn.Attnums[att]->equcls);
	TRdisplay("\n");
	uflush();
    }
# endif

    /* Each attribute in the ordering must be available from the outer
    ** or from the boolfacts
    */
    ordercount = varp->opv_mbf.opb_count; /* number of attributes that the
					** relation is ordered on */
    for (orderindex = 0; orderindex < ordercount; orderindex++)
    {
	OPZ_IATTS	       attr;	/* current ordering attribute being
                                        ** analyzed */
	OPE_IEQCLS             eqcls;   /* equivalence class of 
                                        ** of ordering attribute */

	attr = varp->opv_mbf.opb_kbase->opb_keyorder[orderindex].opb_attno;
	eqcls = abase->opz_attnums[attr]->opz_equcls;

	if (storage == DB_RTRE_STORE)	/* special Rtree inner logic */
	{
	    OPB_IBF	bfi;
	    OPB_BOOLFACT *bfp;
	    for (bfi = 0; bfi < subquery->ops_bfs.opb_bv; bfi++)
	     if ((bfp = subquery->ops_bfs.opb_base->opb_boolfact[bfi])->
		opb_mask & OPB_SPATJ && BTtest((i4)eqcls, 
		(char *)&bfp->opb_eqcmap))
	    {
		OPE_IEQCLS	eqc1;
		if ((eqc1 = BTnext((i4)-1, (char *)&bfp->opb_eqcmap,
		    (i4)subquery->ops_eclass.ope_ev)) == eqcls) 
		 eqc1 = BTnext((i4)eqc1, (char *)&bfp->opb_eqcmap, 
		    (i4)subquery->ops_eclass.ope_ev);
		if (BTtest((i4)eqc1, (char *)oeqcmp))
		{
		    eqcls = eqc1;
		    break;	/* kinda silly to let this drop into 
				** same test again - any alternative will
				** be even uglier! */
		}
	    }
	}

	if (BTtest((i4)eqcls, (char *)oeqcmp) == TRUE)
	{
	    /* Look no further if the first eqcls in the outer
	    ** that exists in the order for the relation is not the 
	    ** joining eqcls (if primkey)
	    */
	    if (primkey && (jeqc != eqcls))
	    {
#ifdef			xNTR1
		if (tTf(1, 0))
		{
		    TRdisplay("We tried to join on eqcls %d but realized that it\n", eqcls);
		    TRdisplay("was not the the primary attribute in the ordering and\n");
		    TRdisplay("that the primary attribute is available from the outer.\n");
		    uflush();
		}
#endif
		    break;
	    }
	    /* Condition satisfied. If non-hash we are keyed */
	    ret_val = TRUE;
	    primkey = FALSE;
	    if (storage != DB_HASH_STORE)
		break;
	    /* we are hashed and need all attrs in the key */
	    continue;
	}
	if (subquery->ops_bfs.opb_bfeqc
	    &&
	    BTtest((i4)eqcls, (char *)subquery->ops_bfs.opb_bfeqc))
	    continue;			/* check if constant key is
                                        ** available for this attribute*/
	/* eqcls is not available. If we haven't gotten all
	** of the hashed key, we can't use the key.
	*/
	if (storage == DB_HASH_STORE)
	{
#	ifdef		xNTR1
	    if (tTf(1, 0))
	    {
		TRdisplay("Not all keys for hashed lookup were found.\n");
		uflush();
	    }
#	endif
	    ret_val = FALSE;
	}
	break;
    }
# ifdef	xNTR1
    if (tTf(1, 0))
    {
	if (ret_val == TRUE)
		TRdisplay("We can do keyed lookup.\n");
	else
		TRdisplay("We can NOT do keyed lookup.\n");
	uflush();
    }
# endif
    return (ret_val);
}
Beispiel #21
0
update()
{
	register int		i, mode;
	struct descriptor	rel;
	long			oldtid, tupcnt;
	char			oldtup[MAXTUP], newtup[MAXTUP];
	char			*batchname();
	extern int		Dburetflag;
	extern struct retcode	Dburetcode;

#	ifdef xZTR1
	if (tTf(15, -1))
		printf("Update on %s\n", batchname());
#	endif
	/* set up to read batchhd */
	Batch_cnt = BATCHSIZE;	/* force a read on next getbatch */
	Batch_dirty = FALSE;
	if ((Batch_fp = open(batchname(), 2)) < 0)
		syserr("prim:can't open %s", batchname());
	getbatch(&Batchhd, sizeof Batchhd);

	tupcnt = Batchhd.num_updts;
#	ifdef xZTR1
	if (tTf(15, 0))
		printf("rel=%s tups=%s\n", Batchhd.rel_name, locv(tupcnt));
#	endif
	Dburetflag = TRUE;
	Dburetcode.rc_tupcount = 0;
	if (!tupcnt)
	{
		rmbatch();
		return (1);
	}

	/* update the primary relation */
	if (i = openr(&rel, 2, Batchhd.rel_name))
		syserr("prim:can't openr %s %d", Batchhd.rel_name, i);
	mode = Batchhd.mode_up;

	while (tupcnt--)
	{
		getbatch(&oldtid, Batchhd.tido_size);	/* read old tid */
		getbatch(oldtup, Batchhd.tupo_size);	/* and portions of old tuple */
		getbatch(newtup, Batchhd.tupn_size);	/* and the newtup */

		switch (mode)
		{

		  case mdDEL:
			if ((i = delete(&rel, &oldtid)) < 0)
				syserr("prim:bad del %d %s", i, Batchhd.rel_name);
			break;

		  case mdREPL:
			if (i = replace(&rel, &oldtid, newtup, TRUE))
			{
				/* if newtuple is a duplicate, then ok */
				if (i == 1)
					break;
				/* if this is recovery and oldtup not there, try to insert newtup */
				if (Batch_recovery && i == 2)
					goto upinsert;
				syserr("prim:Non-functional replace on %s (%d)", i, Batchhd.rel_name);
			}
			Dburetcode.rc_tupcount++;
			break;

		  case mdAPP:
		  upinsert:
			if ((i = insert(&rel, &oldtid, newtup, TRUE)) < 0)
				syserr("prim:bad insert %d %s", i, Batchhd.rel_name);
			break;

		  default:
			syserr("prim:impossible mode %d", mode);
		}
		putbatch(&oldtid, Batchhd.tidn_size);	/* write new tid if necessary */
	}
	/* fix the tupchanged count if delete or append */
	if (mode != mdREPL)
		Dburetcode.rc_tupcount = rel.reladds >= 0 ? rel.reladds : -rel.reladds;
	/* close the relation but secupdate will still use the decriptor */
	if (i = closer(&rel))
		syserr("prim:close err %d %s", i, Batchhd.rel_name);
	batchflush();

	/* if this relation is indexed, update the indexes */
	if (rel.relindxd > 0)
		secupdate(&rel);
	rmbatch();

#	ifdef xZTR1
	if (tTf(15, 2))
		printf("%s tups changed\n", locv(Dburetcode.rc_tupcount));
#	endif
	return (0);
}
void
readinput(register pb_t *ppb)
{
	register int	i;
	resp_t		*rp;

	/*
	**  Top Loop.
	**	Executed once for each complete block read.  Normally
	**	only executed once, but can be more if an error
	**	block is read.
	**
	**	We mark Qbuf first, so we can free any parameters
	**	when they are no longer needed (such as when they
	**	are passed to another process).
	*/

	Ctx.ctx_pmark = markbuf(Qbuf);
#ifdef xCTR1
	if (tTf(10, 0))
		lprintf("readinput: mark %d, errfn %x, ppb %x\n", Ctx.ctx_pmark, Ctx.ctx_errfn, ppb);
#endif
	rp = getresp();
	for (;;) {
		/* prime the input (reads first block) */
		pb_prime(ppb, PB_NOTYPE);
#ifdef xCTR2
		if (tTf(10, 1))
			lprintf("readinput: type %d\n", ppb->pb_type);
#endif

		/* if this is a response block, return immediately */
		if (ppb->pb_type == PB_RESP) {
			i = pb_get(ppb, (char *) rp, sizeof(resp_t));
			if (i != sizeof(resp_t))
				syserr("readinput: resp_t sz %d", i);
/*
			read_arg(ppb, &rp->resp_rval);
*/
			break;
		}

		/*
		**  Parameter Loop.
		**	Wander through and start reading parameters.
		*/

		for (Ctx.ctx_pc = 0; Ctx.ctx_pc < PV_MAXPC; Ctx.ctx_pc++) {
			if (read_arg(ppb, &Ctx.ctx_pv[Ctx.ctx_pc]) == PV_EOF)
				break;
		}

		/* out of loop, check for vector overflow */
		if (Ctx.ctx_pc >= PV_MAXPC)
			syserr("readinput: overflow");

		/* check for error blocks */
		if (ppb->pb_type == PB_ERR) {
			proc_err(ppb, Ctx.ctx_pc, Ctx.ctx_pv);
			syserr("readinput: proc_err");
		}


		/* non-error block */
#ifdef xCM_DEBUG
		if (ppb->pb_type != PB_REG)
			syserr("readinput: pb_type %d", ppb->pb_type);
#endif
		Ctx.ctx_resp = ppb->pb_resp;
		break;
	}
#ifdef xCTR1
	if (tTf(10, 4)) {
		lprintf("readinput: ");
		pb_dump(ppb, FALSE);
	}
#endif
}
Beispiel #23
0
strategy()
{
	register int			i, allexact;
	struct accessparam		sourceparam, indexparam;
	struct index			itup, rtup;
	struct key			lowikey[MAXKEYS+1], highikey[MAXKEYS+1];
	register struct descriptor	*d;
	extern struct descriptor	Inddes;
	struct descriptor		*openindex();

#	ifdef xOTR1
	if (tTf(31, 0))
		printf("STRATEGY\tSource=%.12s\tNewq = %d\n", Source ? Source->relid : "(none)", Newq);
#	endif

	while (Newq)	/* if Newq=TRUE then compute a new strategy */
			/* NOTE: This while loop is executed only once */
	{
		Scanr = Source;
	
		if (!Scanr)
			return (1);	/* return immediately if there is no source relation */
	
		Fmode = NOKEY;	/* assume a find mode with no key */
	
		if (!Qlist)
			break;	/* if no qualification then you must scan entire rel */
	
		/* copy structure of source relation into sourceparam */
		paramd(Source, &sourceparam);
	
		/* if source is unkeyed and has no sec index then give up */
		if (sourceparam.mode == NOKEY && Source->relindxd <= 0)
			break;

		/* find all simple clauses if any */
		if (!findsimps())
			break;	/* break if there are no simple clauses */
	
		/* Four steps are now performed to try and find a key.
		** First if the relation is hashed then an exact key is search for
		**
		** Second if there are secondary indexes, then a search is made
		** for an exact key. If that fails then a  check is made for
		** a range key. The result of the rangekey check is saved.
		**
		** Third if the relation is an ISAM a check is  made for
		** an exact key or a range key.
		**
		** Fourth if there is a secondary index, then if step two
		** found a key, that key is used.
		**
		**  Lastly, give up and scan the  entire relation
		*/
	
		/* step one. Try to find exact key on primary */
		if (exactkey(&sourceparam, &Lkey_struct))
		{
			Fmode = EXACTKEY;
			break;
		}
	
		/* step two. If there is an index, try to find an exactkey on one of them */
		if (Source->relindxd)
		{
	
			opencatalog("indexes", 0);
			setkey(&Inddes, &itup, Source->relid, IRELIDP);
			setkey(&Inddes, &itup, Source->relowner, IOWNERP);
			if (i = find(&Inddes, EXACTKEY, &Lotid, &Hitid, &itup))
				syserr("strategy:find indexes %d", i);
	
			while (!(i = get(&Inddes, &Lotid, &Hitid, &itup, NXTTUP)))
			{
#				ifdef xOTR1
				if (tTf(31, 3))
					printup(&Inddes, &itup);
#				endif
				if (!bequal(itup.irelidp, Source->relid, MAXNAME) ||
				    !bequal(itup.iownerp, Source->relowner, 2))
					continue;
				parami(&itup, &indexparam);
				if (exactkey(&indexparam, &Lkey_struct))
				{
					Fmode = EXACTKEY;
					d = openindex(itup.irelidi);
					/* temp check for 6.0 index */
					if (d->relindxd == -1)
						ov_err(BADSECINDX);
					Scanr = d;
					break;
				}
				if (Fmode == LRANGEKEY)
					continue;	/* a range key on a s.i. has already been found */
				if (allexact = rangekey(&indexparam, &lowikey, &highikey))
				{
					bmove(&itup, &rtup, sizeof itup);	/* save tuple */
					Fmode = LRANGEKEY;
				}
			}
			if (i < 0)
				syserr("stragery:bad get from index-rel %d", i);
			/* If an exactkey on a secondary index was found, look no more. */
			if (Fmode == EXACTKEY)
				break;
		}
	

		/* step three. Look for a range key on primary */
		if (i = rangekey(&sourceparam, &Lkey_struct, &Hkey_struct))
		{
			if (i < 0)
				Fmode = EXACTKEY;
			else
				Fmode = LRANGEKEY;
			break;
		}
	
		/* last step. If a secondary index range key was found, use it */
		if (Fmode == LRANGEKEY)
		{
			if (allexact < 0)
				Fmode = EXACTKEY;
			d = openindex(rtup.irelidi);
			/* temp check for 6.0 index */
			if (d->relindxd == -1)
				ov_err(BADSECINDX);
			Scanr = d;
			bmove(&lowikey, &Lkey_struct, sizeof lowikey);
			bmove(&highikey, &Hkey_struct, sizeof highikey);
			break;
		}

		/* nothing will work. give up! */
		break;
	
	}

	/* check for Newq = FALSE and no source relation */
	if (!Scanr)
		return (1);
	/*
	** At this point the strategy is determined.
	**
	** If Fmode is EXACTKEY then Lkey_struct contains
	** the pointers to the keys.
	**
	** If Fmode is LRANGEKEY then Lkey_struct contains
	** the pointers to the low keys and Hkey_struct
	** contains pointers to the high keys.
	**
	** If Fmode is NOKEY, then a full scan will be performed
	*/
#	ifdef xOTR1
	if (tTf(31, -1))
		printf("Fmode= %d\n",Fmode);
#	endif

	/* set up the key tuples */
	if (Fmode != NOKEY)
	{
		if (setallkey(&Lkey_struct, Keyl))
			return (0);	/* query false. There is a simple
					** clause which can never be satisfied.
					** These simple clauses can be choosey!
					*/
	}

	if (i = find(Scanr, Fmode, &Lotid, &Hitid, Keyl))
		syserr("strategy:find1 %.12s, %d", Scanr->relid, i);

	if (Fmode == LRANGEKEY)
	{
		setallkey(&Hkey_struct, Keyh);
		if (i = find(Scanr, HRANGEKEY, &Lotid, &Hitid, Keyh))
			syserr("strategy:find2 %.12s, %d", Scanr->relid, i);
	}

#	ifdef xOTR1
	if (tTf(31, 1))
	{
		printf("Lo");
		dumptid(&Lotid);
		printf("Hi");
		dumptid(&Hitid);
	}
#	endif

	return (1);
}
int
proc_err(pb_t *ppb, int pc, paramv_t *pv)
{
	register func_t	*f;
	register int		i;
	register ctx_t		*ctx;

#ifdef xCTR2
	if (tTf(6, 8))
		lprintf("proc_err: new = %d\n", Ctx.ctx_new);
#endif
	pb_prime(ppb, PB_ERR);

	/*
	**  Scan back on the list of context dependencies.
	**	If we come to someone who can process this message,
	**	we go ahead and do it.  We also take this
	**	opportunity to unwind the context list & call the
	**	cleanup functions.
	*/

	for (ctx = &Ctx; ctx != NULL; ctx = ctx->ctx_link) {
		setprocname(ctx->ctx_name);
		f = ctx->ctx_fn;
#ifdef xCTR2
		if (tTf(6, 9))
			lprintf("proc_err: unwinding %s: errfn=%x, ppb=%x, link=%x, resp=%d, fn=%x\n",
			    getprocname(), ctx->ctx_errfn, ctx->ctx_ppb,
			    ctx->ctx_link, ctx->ctx_resp, f);
#endif

		/*  Do the actual error processing. */
		ppb->pb_proc = ctx->ctx_resp;
		if (ctx->ctx_errfn != NULL)
			i = (*ctx->ctx_errfn)(pc, pv);
		else
			i = -1;

#ifdef xCTR2
		if (tTf(6, 11))
			lprintf("proc_err: errcode %d\n", i);
#endif
		if (i == 0)
			break;
		else if (i > 0) {
			/* turn into nonfatal error */
			ppb->pb_stat |= PB_INFO;
			ppb->pb_proc = PB_FRONT;
		} else {
			/* call the cleanup function */
			if (f != NULL && f->fn_active > 0) {
				(*f->fn_cleanup)(1);
			}
		}

		/* arrange to leave if parent not in this process */
		if (ppb->pb_proc != Cm.cm_myproc) {
			send_off(ppb, pc, pv);
			pb_flush(ppb);

			/* throw away dead contexts and exit */
			break;
		}
	}
	if (ctx == NULL) {
		syserr("proc_err: no parent");
	}

#ifdef xCTR3
	MonPpb = getmonppb();
	if (tTf(6, 12)) {
		lprintf("proc_err: cleanup: ctx=%x, ->_link=%x, MonPpb = ", ctx, ctx->ctx_link);
		pb_dump(MonPpb, TRUE);
	}
#endif
	/* pop contexts down to ctx and exit */
	ctx = ctx->ctx_link;
	while (Ctx.ctx_link != ctx) {
		if (Ctx.ctx_link == NULL)
			syserr("proc_err: underflow");
		Ctx.ctx_new = TRUE;
		resetp();
	}

	/*
	**  Flush input pipe.
	**	THIS CODE IS ONLY NEEDED TO MAKE READMON WORK, AND
	**	SHOULD BE REMOVED WHEN READMON GOES AWAY!!
	*/

	if (ctx == NULL) {
		Cm.cm_input = Cm.cm_rinput;
		MonPpb = getmonppb();
		while (!BITISSET(PB_EOF, MonPpb->pb_stat)) {
			pb_read(MonPpb);
		}
		MonPpb->pb_st = PB_UNKNOWN;
	}

	longjmp(Ctx.ctx_jbuf, 1);
}
Beispiel #25
0
int
indexx(int pc, paramv_t *pv)
{
	register int		i;
	int			j;
	register struct dom	*dom;
	register paramv_t	*p;
	char			*primary, *indx;
	int			ndoms, newpc;
	struct tup_id		tid, hitid;
	struct tup_id		xtid;
	paramv_t		newpv[MAX_2ND_KEYS * 2 + 4];
	char			primtup[MAX_TUP_SIZE], systup[MAX_TUP_SIZE];
	desc_t			desc, pridesc;
	extern desc_t		Reldes;
	extern desc_t		Attdes;
	extern desc_t		Inddes;
	relation_t		relkey, reltup;
	attr_t			attkey, atttup;
	index_t			indtup;
	struct dom		domain[MAX_2ND_KEYS];

	primary = pv[0].pv_val.pv_str;
	indx = pv[1].pv_val.pv_str;
#ifdef xZTR1
	if (tTf(33, -1))
		printf("index: (pri %s ind %s)\n", primary, indx);
#endif
	i = openr(&pridesc, OR_READ, primary);
	if (i == AMOPNVIEW_ERR)
		return (error(NOINDVIEW, primary, 0));
	if (i > 0)
		return (error(NOPRIMREL, primary, 0));
	if (i < 0)
		syserr("INDEX : openr (%.14s) %d", primary, i);

	if (!bequal(pridesc.d_r.r_owner, Usercode, USERCODE_SIZE)) {
		i = NOTOWNED;
	} else if (pridesc.d_r.r_status & S_CATALOG) {
		i = NOINDXSYSREL;
	} else if (pridesc.d_r.r_indexed == SECINDEX) {
		i = ALREADYINDX;
	}

	if (i) {
		closer(&pridesc);
		return (error(i, primary, 0));
	}
	/*
	**  GATHER INFO. ON DOMAINS
	*/
	opencatalog("attribute", OR_WRITE);
	ingres_setkey(&Attdes, &attkey, primary, ATTRELID);
	ingres_setkey(&Attdes, &attkey, pridesc.d_r.r_owner, ATTOWNER);
	pc -= 2;
	p = &pv[2];
	dom = domain;
	for (i = 0; i < pc; i++) {
		if (i >= MAX_2ND_KEYS) {
			closer(&pridesc);
			return (error(TOOMUCHDOMS, (p->pv_val).pv_str, primary, 0));	/* too many keys */
		}
		ingres_setkey(&Attdes, &attkey, (p->pv_val).pv_str, ATTNAME);
		j = getequal(&Attdes, &attkey, &atttup, &tid);
		if (j < 0)
			syserr("INDEX: geteq att %d", j);
		if (j) {
			closer(&pridesc);
			return (error(NODOM, (p->pv_val).pv_str, 0));	/* key not in relation */
		}
		if (pridesc.d_r.r_dim > 0 && atttup.a_id == pridesc.d_r.r_attrc) {
			/* attempting to use lid field as part of index */
			closer(&pridesc);
			return(error(NOINDXLID, primary, (p->pv_val).pv_str, 0));
		}
		dom->id = atttup.a_id;
		dom->off = atttup.a_off;
		dom->frml = atttup.a_len & I1MASK;
		dom->frm[0] = atttup.a_fmt;
		p++;
		dom++;
	}
	ndoms = i;
	noclose(&Attdes);

	/*
	** The "order" of the steps have been altered to improve
	** recovery possibilities
	*/
	/*
	**  STEP 1 & 2: CREATE INDEX RELATION.
	*/
	newpv[0].pv_val.pv_str = "0202";
	newpv[1].pv_val.pv_str = indx;
	newpc = 2;
	p = &pv[2];
	dom = domain;
	for (i = 0; i < pc; i++) {
		newpv[newpc++].pv_val.pv_str = (p->pv_val).pv_str;
		itoa(dom->frml, &dom->frm[1]);
		newpv[newpc++].pv_val.pv_str = dom->frm;
		dom++;
		p++;
	}
	newpv[newpc++].pv_val.pv_str = "tidp";
	newpv[newpc++].pv_val.pv_str = "i4";
	newpv[newpc].pv_type = PV_EOF;

	if (create(newpc, newpv)) {
		closer(&pridesc);
		return (-1);
	}

	/* This is done for concurrency reasons */
	if (noclose(&Reldes))
		syserr("index: noclose");

	/*
	**  STEP 5: FILL UP THE SECONDARY INDEX FILE ITSELF
	*/
	if (Lockrel) {
		/* set a shared relation lock */
		setrll(A_SLP, &pridesc.d_tid, M_SHARE);
	}
	if ((i = openr(&desc, OR_WRITE, indx)) != 0)
		syserr("INDEX: openr %.14s %d", indx, i);
	find(&pridesc, NOKEY, &tid, &hitid, (void *) NULL);
	while ((i = get(&pridesc, &tid, &hitid, primtup, TRUE)) == 0) {
		dom = domain;
		for (i = j = 0; j < ndoms; j++) {
#ifdef BIG_ENDIAN
			if (dom->frm[0] != 'c')
				i = ((i-1)|(dom->frml-1))+1;
#endif
			bmove(&primtup[dom->off], &systup[i], dom->frml);
			i += dom->frml;
			dom++;
		}
#ifdef BIG_ENDIAN
		i = ((i-1)|3)+1;
#endif
		/* move in pointer */
		bmove(&tid, &systup[i], sizeof(tid));
		if ((j = insert(&desc, &xtid, systup, TRUE)) < 0) {
			syserr("INDEX: insert %.14s %d", indx, j);
		}
	}
	if (i < 0) {
		syserr("INDEX: get %.14s %d", primary, i);
	}
	closer(&pridesc);
	closer(&desc);


	/*
	**  STEP 3: ENTRIES TO INDEX-REL
	*/
	/* mv in primary name  */
	pmove(primary, indtup.i_relname, MAX_NAME_SIZE, ' ');
	/* primary owner */
	bmove(pridesc.d_r.r_owner, indtup.i_owner, sizeof(pridesc.d_r.r_owner));
	/* index name */
	pmove(indx, indtup.i_index, MAX_NAME_SIZE, ' ');
	indtup.i_indrelspec = M_HEAP;
	for (i = 0; i < MAX_2ND_KEYS; i++) {
		indtup.i_dom[i] = (i < ndoms) ? domain[i].id : 0;
	}
	opencatalog("indices", OR_WRITE);
	if ((i = insert(&Inddes, &tid, (char *) &indtup, TRUE)) < 0)
		syserr("INDEX: insert ix %d", i);

	/*
	**  STEP 4: TURN BIT ON IN PRIMARY RELATION TO SHOW IT IS BEING INDEXED
	*/
	opencatalog("relation", OR_WRITE);
	ingres_setkey(&Reldes, &relkey, primary, RELID);
	ingres_setkey(&Reldes, &relkey, pridesc.d_r.r_owner, RELOWNER);
	if ((i = getequal(&Reldes, &relkey, &reltup, &tid)) != 0)
		syserr("INDEX: geteq rel %d", i);
	reltup.r_indexed = SECBASE;
	if ((i = replace(&Reldes, &tid, &reltup, TRUE)) < 0)
		syserr("INDEX: replace rel %d", i);

	if (Lockrel)
		unlrl(&pridesc.d_tid);	/* release relation lock */

	return (0);
}