# include # include # include # include # include # include SCCSID(@(#)replace.c 8.2 2/8/85) # define SAMETUP 0 # define SAMEKEYS 1 # define DIFFTUP 2 /* ** 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 dealt 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(DUPTUP) new tuple was duplicate of returned tid ** 2(DELTUP) tuple identified by tid has been deleted ** 3(BADLID) bad lid ** ** If replace returns 1 then tid is set to the ** duplicate tuple. This is necessary for updating ** secondary indices. ** ** Trace Flags: ** 24.4-7 */ replace(d, tid, tuple, checkdups) register DESC *d; register TID *tid; char *tuple; int checkdups; { register int i; int j; char oldtuple[MAXTUP]; TID primtid, tidloc, tidpos; long primpage, old_lid[MAXLID], new_lid[MAXLID], page, t; int need, same, numatts; int len, oldlength; char *new, *old, *oldt; char *getint_tuple(); char btree[MAXNAME + 4]; long oldtid; int lidwid, compare; struct locator temp; # ifdef xATR1 if (tTf(24, 4)) { printf("replace: %.14s,", d->reldum.relid); dumptid(tid); printf("replace: "); printup(d, tuple); } # endif /* make tuple canonical */ need = canonical(d, tuple); /* if heap or ordered, no dup checking */ if (abs(d->reldum.relspec) == M_HEAP || d->reldum.reldim > 0) 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); /* reset page back to main relation page */ if (i = get_page(d, tid)) return(i); oldlength = tup_len(tid); lidwid = LIDSIZE * d->reldum.reldim; if (d->reldum.reldim > 0) { /* extract lid values from tuples */ btreename(d->reldum.relid, btree); old = oldt + d->reldum.relwid - lidwid; bmove(old, old_lid, lidwid); new = tuple + d->reldum.relwid - lidwid; bmove(new, new_lid, lidwid); compare = 0; for (i = 0; i < d->reldum.reldim; ++i) { if (new_lid[i] > old_lid[i]) { compare = 1; break; } else if (new_lid[i] == old_lid[i]) compare = -1; else { compare = 0; break; } } if (compare >= 0) { /* do insertion and deletion of new lid and old values in ** order that insures that they will be placed in the proper ** place */ if (compare == 1) { if (insert_mbtree(d, btree, new_lid, tid, &tidpos) < 0) return(BADLID); if (fwrite(old_lid, 1, lidwid, Del_infp) != lidwid) syserr("write error in replace"); ++Del_cnt; } else if (compare == 0) { page = RT; for (j = 0; j < d->reldum.reldim; ++j) { if (new_lid[j] > 0 && (t = get_tid(page, new_lid[j], &temp)) > 0) page = t; else if (t == -1) { for (i = j + 1; i < d->reldum.reldim; ++i) { if (new_lid[i] != 1 && new_lid[i] != 0) return(BADLID); } break; } else if (new_lid[j] == 0) { for (i = j + 1; i < d->reldum.reldim; ++i) { if (new_lid[i] != 0) return(BADLID); } break; } else return(BADLID); } for (i = 0; i < d->reldum.reldim; ++i) if (new_lid[i] < 0) return(BADLID); delete_btree(old_lid, d->reldum.reldim); if (insert_mbtree(d, btree, new_lid, tid, &tidpos) < 0) return(BADLID); } } } /* 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; /* ignore lid field */ numatts = d->reldum.relatts - d->reldum.reldim; for (i = 1; i <= numatts; 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(24, 5)) printf("replace:same=%d\n", same); # endif switch (same) { case SAMETUP: /* new tuple same as old tuple */ i = DUPTUP; /* 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->reldum.relwid - lidwid)) 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 == DUPTUP) { 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 */ get_page(d, tid); del_tuple(tid, oldlength); bmove(tid, &oldtid, LIDSIZE); /* 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 = NEWTUP; if (same == DIFFTUP && d->reldum.reldim > 0) { /* main tid value has changed, update btree */ if (compare < 0) search_btree(oldtid, &tidpos); /* tid different, must be reflected in BTree */ replace_btree(*tid, &tidpos); } } # ifdef xATR1 if (tTf(24, 6)) { printf("replace rets %d,", i); dumptid(tid); } # endif return (i); }