# include	"../ingres.h"
# include	"../access.h"
# define	SAMETUP		0
# define	SAMEKEYS	1
# define	DIFFTUP		2

/* tTf flag 95		TTF */
/*
**	Replace - replace an already existing tuple
**
**	Replace will replace the tuple specified by TID
**	with the new tuple. An attempt is made to not
**	move the tuple if at all possible.
**
**	Three separate conditions are delt with. If the
**	new tuple is the same as the old tuple, a return 
**	of zero occures and the page is not changed.
**
**	If the keys(if any) are the same and the canonical
**	tuple lengths are the same, then the new tuple will
**	be placed in the same location.
**
**	If the lengths or the keys are different, then the
**	tuple is deleted and the new tuple inserted
**
**	Checkdups specifies whether to check for duplicates.
**	If the new tuple is a duplicate of one already there,
**	then the tuple at TID is deleted
**	returns:
**		<0  fatal error
**		 1  new tuple was duplicate of returned tid
**		 2  tuple identified by tid has been deleted
**
**		If replace returns 1 then tid is set to the
**		duplicate tuple. This is necessary for updating
**		secondary indices.
*/


replace(dx, tidx, tuple, checkdups)	
struct descriptor	*dx;
struct tup_id		*tidx;
char			*tuple;
int			checkdups;
{
	register struct descriptor	*d;
	register int			i;
	register struct tup_id		*tid;
	char				oldtuple[MAXTUP];
	struct tup_id			primtid;
	long				primpage;
	int				need, same;
	int				len, oldlength;
	char				*new, *old, *oldt;
	char				*getint_tuple();

	d = dx;
	tid = tidx;
#	ifdef xATR1
	if (tTf(95, 0))
	{
		printf("replace: %.14s,", d->relid);
		dumptid(tid);
		printf("replace: ");
		printup(d, tuple);
	}
#	endif

	/* make tuple canonical */
	need = canonical(d, tuple);

	/* if heap, no dup checking */
	if (abs(d->relspec) == M_HEAP)
		checkdups = FALSE;

	if (i = get_page(d, tid))
		return (i);	/* fatal error */

	/* check if tid exists */
	if (i = invalid(tid))
		return (i);	/* already deleted or invalid */

	oldt = getint_tuple(d, tid, oldtuple);
	oldlength = tup_len(tid);

	/* check whether tuples are the same, different lengths, different keys */
	same = DIFFTUP;	/* assume diff lengths or keys */
	if (oldlength == need)
	{
		/* same size. check for same domains */
		same = SAMETUP;	/* assume identical */
		new = tuple;
		old = oldt;
		for (i = 1; i <= d->relatts; i++)
		{
			len = d->relfrml[i] & I1MASK;
			if (icompare(new, old, d->relfrmt[i], len))
			{
				if (d->relxtra[i])
				{
					same = DIFFTUP;
					break;
				}
				same = SAMEKEYS;
			}
			old += len;
			new += len;
		}
	}

#	ifdef xATR2
	if (tTf(95, 1))
		printf("replace:same=%d\n", same);
#	endif
	switch (same)
	{

	  case SAMETUP:
		/* new tuple same as old tuple */
		i = 1;	/* flag as duplicate */
		/* though character strings may compare equal,
		**  they can look different, so if they do look different
		**  go ahead and do the replace using put_tuple.  */
		if (!bequal(tuple, oldt, d->relwid))
			goto puttuple;
		break;

	  case SAMEKEYS:
		/* keys the same, lengths the same, tuples different */
		if (checkdups)
		{
			/* This is either an ISAM or HASH file. If mainpg
			** is non-zero, then the primary page=mainpg -1.
			** Otherwise, "find" must be called to determine
			** the primary page
			*/
			if (Acc_head->mainpg)
			{
				primpage = Acc_head->mainpg -1;
				stuff_page(&primtid, &primpage);
			}
			else
			{
				if (i = find(d, FULLKEY, &primtid, &primtid, tuple))
					return (i);	/* fatal error */
				if (i = get_page(d, tid))	/* restore page for tuple */
					return (i);
			}
	
			if (i = scan_dups(d, &primtid, tuple))
			{
				if (i == 1)
				{
					del_tuple(tid, oldlength);	/* tuple a duplicate */
					d->reladds--;
					/* copy tid of duplicate tuple */
					bmove(&primtid, tid, sizeof(primtid));
				}
				break;
			}
		}
		goto puttuple;

	  case DIFFTUP:
		/* keys different or lengths different */
		del_tuple(tid, oldlength);

		/* find where to put tuple */
		if (i = findbest(d, tid, tuple, need, checkdups))
		{
			d->reladds--;
			break;
		}

		/* place new tuple in page */
	puttuple:
		put_tuple(tid, Acctuple, need);
		i = 0;
	}

#	ifdef xATR1
	if (tTf(95, 2))
	{
		printf("replace rets %d,", i);
		dumptid(tid);
	}
#	endif

	return (i);
}
