# 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 tud_id *tid; char oldtuple[MAXTUP]; struct tup_id primtid; long primpage; int need, same; int len, oldlength; char *new, *old, *oldt; 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); }