Ejemplo n.º 1
0
/*
**  REL_FILE -- copy from relation to file
*/
int
rel_file(void)
{
	int			j;
	struct tup_id		tid, limtid;
	char			*cp, save;
	register int		offset;
	register int		i;
	register struct map	*mp;

	/* set scan limits to scan the entire relation */
	if (find(&Des, NOKEY, &tid, &limtid, (void *) NULL))
		syserr("find error");

	while ((i = get(&Des, &tid, &limtid, Inbuf, 1)) == 0) {
		mp = Map;
		offset = 0;
		for (i = 0; i < Mapcount; i++) {
			/*
			** For cases of char to numeric conversion,
			** there must be a null byte at the end of the
			** string. The character just past the current
			** domain is saved an a null byte inserted 
			*/

			cp = &Inbuf[mp->roffset + mp->rlen];	/* compute address */
			save = *cp;	/* get the character */
			*cp = '\0';	/* insert a null */

			/*
			** Special case, we want to copy the tid
			*/
			if ( mp->roffset == -1 ) {
				j = transfer((ANYTYPE *)&tid,
						mp->rtype, mp->rlen,
						mp->ftype, mp->flen, offset);
			} else {
				j = transfer((ANYTYPE *)&Inbuf[mp->roffset],
						mp->rtype, mp->rlen,
						mp->ftype, mp->flen, offset);
			}
			if (j) {
				/* bad ascii to numeric conversion or field length too small */
				return (nferror(j, mp->paramname, &Inbuf[mp->roffset], locv(Tupcount), Relname, Filename, 0));
			}
			*cp = save;	/* restore the saved character */
			offset += mp->flen;
			mp++;
		}
		Tupcount++;
		if (fwrite(Outbuf, 1, offset, File_iop) != offset)
			syserr("copy:cant write to user file %s", Filename);
	}
	if (i < 0)
		syserr("bad get from rel %d", i);
	return (0);
}
Ejemplo n.º 2
0
/*
**	file_rel is called to transfer tuples from
**	the input file and append them to the relation
**
**	Char domains are initialized to blank and numeric
**	domains are initialized to zero.
*/
int
file_rel(void)
{
	register int		i, j;
	register struct map	*mp;
	struct tup_id		tid;

	clr_tuple(&Des, Outbuf);

	/* copy domains until an end of file or an error */
	for (;;) {
		mp = Map;
		for (i = 0; i < Mapcount; i++) {
			if ((j = bread(mp)) <= 0) {
				if (j < 0) {
					i = 1;	/* force an error */
					j = UNDETC0;	/* unterminated string */
				} else
					j = UNEXEOF;	/* end of file */
				if (i) {
					/* error only if end of file during a tuple or unterminated string */
					i = nferror(j, mp->paramname, locv(Tupcount), Filename, Relname, 0);
				}
				return (i);
			}
			j = transfer((ANYTYPE *) Inbuf, mp->ftype, mp->flen,
					mp->rtype, mp->rlen, mp->roffset);
			if (j) {
				/* bad ascii to numeric or field length too small */
				return (nferror(j, mp->paramname, Inbuf, locv(Tupcount), Filename, Relname, 0));
			}
			mp++;
		}
		Tupcount++;
		if ((j = insert(&Des, &tid, Outbuf, 1)) < 0)
			syserr("insert error %d rel=%s", j, Relname);
		if (j == 1)
			Duptuple++;
		mp++;
	}
	return(0); 
}
Ejemplo n.º 3
0
/*
**	Finish up and exit after a copy or interrupt
**
**	I is the return code. Since only a byte can be
**	returned, only the least significant 2 decimal
**	digits are returned. i is either 0 or a number like 58??
*/
RETSIGTYPE
copydone(int i)
{
	if (Lockrel)	/* unlock relation */
		unlrl(&Des.d_tid);
	if (Truncount)
		nferror(TRUNCCHARS, locv(Truncount), 0);	/* warning only */
	/*  force the updates to be flushed */
	cleanrel(&Des);
	if (File_iop)
		fclose(File_iop);
	if (write(Piped[1], &Des.d_addc, 4) != 4)
		syserr("copyc:can't writepipe");
	exit (i % 100);
}
Ejemplo n.º 4
0
void
trapquery(struct resp *resp, char *name)
{
	register FILE	*iop;
	static int	first;
	register char	*sp, c;
	time_t		timevec;

	if (first < 0)
		return;
	if (Trapfile == NULL) {
		if ((Trapfile = fopen(name, "a")) == NULL) {
			printf("can't trap query in %s\n", name);
			first = -1;
			return;
		}
	}
	if (first == 0) {
		(void) time(&timevec);
		sp = ctime(&timevec);
		while (*sp)
			putc(*sp++, Trapfile);
		first++;
	}

	if ((iop = fopen(Qbname, "r")) == NULL)
		syserr("go: open 1");
	macinit(fgetc, iop, 1);

	while ((c = macgetch()) > 0)
		putc(c, Trapfile);

	if (resp->resp_resp == 0) {
		sp = (char *) locv(resp->resp_tups);
		while (*sp)
			putc(*sp++, Trapfile);
		putc('\n', Trapfile);
	}

	fclose(iop);
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
/*
**	transfer copies data from "*in" to
**	Outbuf doing conversions whenever
**	necessary
*/
int
transfer(ANYTYPE *in, char sf, int sl, char df, int dl, int doff)
/* in - pointer to input chars */
/* sf - source format */
/* sl - source length */
/* df - destination format */
/* dl - destination length */
/* doff - destination offset */
{
	register char		*outp;
	register ANYTYPE	*inp;
	register int		i;
	int			j;
	short			smalli;
	char			temp[MAX_FIELD_SIZE];	/* holds char during conversions to ascii */
	float			f;
	double			d;
	long			l;


	outp = &Outbuf[doff];
	inp = in;

	if (sf == DUMMY)
		/* if source format is a dummy fields then
		   nothing else need be done */
		return (0);

	if (df == DUMMY) {
		/* fill field with dummy domain character */
		i = dl;	/* i equals the number of chars */
		while (i--)
			*outp++ = sf;	/* sf holds dummy char */
		return (0);
	}

	if (sf != CHAR_CONST) {
		if (df == CHAR_CONST) {
			/* numeric to char conversion */
			switch (sl) {
			  /* int of size 1 or 2 */
			  case 1:
				itoa(inp->i1type, temp);
				break;

			  case 2:
				itoa(inp->i2type, temp);	/* convert to ascii */
				break;

			  /* int or float of size 4 */
			  case 4:
				if (sf == INT_CONST) {
					smove(locv(inp->i4type), temp);	/* convert and copy */
				} else {
					ftoa(inp->f4type, temp, dl, Out_arg.f4prec, Out_arg.f4style);
				}
				break;

			  /* float of size 8 */
			  case 8:
				ftoa(inp->f8type, temp, dl, Out_arg.f8prec, Out_arg.f8style);
				break;

			  /* there is no possible default */
			  default:
				syserr("bad domain length %d",sl);
			}

			j = strlen(temp);
			if ((i = dl - j) < 0)
				return (5808);	/* field won't fit */

			/* blank pad from left. Number will be right justified */
			while (i--)
				*outp++ = ' ';

			bmove(temp, outp, j);
			return (0);
		}

		if (convert(inp, outp, sf, sl, df, dl))	/* numeric to numeric transfer */
			return (DOMTOOSMALL);	/* numeric truncation error */
		return (0);
	}

	/* character to numeric conversion */
	/* and character to character conversion */
	switch (df) {

	  case CHAR_CONST:
		i = sl;
		if (!i) {
			i = strlen(inp->c0type);
		}
		if (i > dl)
			i = dl;
		if (charmove(inp->c0type, outp, i))
			Baddoms++;
		for (outp += i; i<dl; i++)
			*outp++ = ' ';
		return (0);

	  case FLOAT_CONST:
		if (ingres_atof(inp->c0type, &d))
			return (BADINPUT);	/* bad conversion to numeric */
		if (dl == 8) {
			bmove(&d, outp, dl);
		} else {
			f = d;	/* f8 to f4 conversion */
			bmove(&f, outp, dl);
		}
		return (0);

	  case INT_CONST:
		if (dl == 4) {
			if (ingres_atol(inp->c0type, &l))
				return (5809);
			bmove(&l, outp, sizeof(l));
			return (0);
		}
		smalli = atoi(inp->c0type);
                if (dl == 1) {
                        if ((smalli < -128) || (smalli > 127))
                                return (5809);
                        df = smalli;
                        bmove(&df, outp, dl);
                } else
                        bmove(&smalli, outp, dl);
		return (0);
	}
	return(0);
}
Ejemplo n.º 7
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);
}
Ejemplo n.º 8
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 */
}