P8000/WEGA/contrib/ingres/dbs/src/access/findbest.c

166 lines
4.1 KiB
C

# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "../h/access.h"
/*
** AAfindbest - find the "best" place to put a tuple.
** AAfindbest does not actually put the tuple but rather
** returns and allocates the tid for the tuple.
**
** The initial part of the algorithm depends on whether
** the relation is a heap or not.
**
** If the relation is a heap, if there is a current page
** with room for the tuple, that page is used. Otherwise
** the last page of the heap is considered.
**
** If the relation is hash or isam, then "find" is used
** to determine the primary page for the tuple.
**
** If necessary, AAfindbest will allocate an overflow page
** if there is not sufficient room for the tuple otherwise.
**
** If checkdups is TRUE and the relation is not a heap,
** AAfindbest will check for duplicates.
**
** Returns:
**
** 0 tuple not a duplicate, tid allocated
** 1 tuple a duplicate of the tuple at tid
*/
AAfindbest(d, tid, tuple, need, checkdups)
register DESC *d;
register struct tup_id *tid;
char *tuple;
int need;
int checkdups;
{
register int i;
struct tup_id temptid;
if (abs(ctoi(d->reldum.relspec)) == M_HEAP)
checkdups = FALSE;
else if (i = AAam_find(d, FULLKEY, tid, tid, tuple))
{
/* find a suitable page for isam or hash */
/* determine primary page */
return (i); /* fatal error */
}
/* If we are not checking for duplicates then take any
** convenient page linked to the main page current indicated
** in "tid"
*/
if (!checkdups)
AAfind_page(d, tid, need);
/* search the chain of pages looking for a spot */
for ( ; ; )
{
if (i = AAgetpage(d, tid))
break; /* fatal error */
/* if tuple is duplicate, drop out */
if (checkdups && AAdup_check(d, tid, tuple))
{
i = 1;
break;
}
/* is there space on this page */
if (AAspace_left(AAcc_head) >= need)
break; /* found a page to use */
/* no space yet. look on next overflow page */
if (AAcc_head->ovflopg)
{
AAstuff_page(tid, &AAcc_head->ovflopg);
continue;
}
/* no space. allocate new overflow page */
if (i = AAadd_ovflo(d, tid))
break; /* fatal error */
}
/* check for dups on remaining overflow pages */
/* check only if there hasn't been a dup or a page error */
if (!i && checkdups && AAcc_head->ovflopg)
{
AAstuff_page(&temptid, &AAcc_head->ovflopg);
if (i = AAscan_dups(d, &temptid, tuple))
AAbmove(&temptid, tid, sizeof(temptid)); /* tid of duplicate */
}
/* if tuple isn't a duplicate, allocate a line number */
if (!i)
tid->line_id = AAnewlino(need);
# ifdef xATR1
if (AAtTfp(88, 2, "FINDBEST: ret %d,", i))
AAdumptid(tid);
# endif
return (i);
}
/*
** AAfind_page
** Find an appropriate page to put a tuple.
** If HEAP then any page with room will do. If none
** can be found, then use the last page.
** If it is a user relation and a page was found but
** was full, use it anyway. This can happen only on a
** modify (which has checkdups turned off).
**
** For ISAM or HASH look for a page on the same mainpage
** chain. Duplicate checking must not be enforced.
**
** The first page to use will be returned in tid in either
** case.
*/
AAfind_page(d, tid, need)
register DESC *d;
struct tup_id *tid;
int need;
{
register ACCBUF *b;
register ACCBUF *maxbf;
register int heap;
long mainpg;
maxbf = (ACCBUF *) 0;
heap = abs(ctoi(d->reldum.relspec)) == M_HEAP;
AApluck_page(tid, &mainpg);
mainpg++; /* mainpage in buffer points to next higher mainpage */
/* scan all current buffers looking for one belonging to this relation */
for (b = AAcc_head; b; b = b->modf)
{
if (d->reltid == b->rel_tupid && !(b->bufstatus & BUF_DIRECT)
&& (heap || (b->mainpg == mainpg)))
{
if (AAspace_left(b) >= need)
{
/* use this page */
AAstuff_page(tid, &b->thispage);
return;
}
/* save buffer of largest page */
if (!maxbf || maxbf->thispage < b->thispage)
maxbf = b;
}
}
if (heap)
AAlast_page(d, tid, maxbf);
else
{
/* if we found a full page of a user's relation,use it */
if (maxbf && !(d->reldum.relstat & S_CATALOG))
AAstuff_page(tid, &maxbf->thispage);
}
}