# 2.11BSD#431 - /usr/ingres/source/dbu/modify.c

##### Functions

    bldindex          X
    fill_batch        X
    fill_rel          X
    getfill           X
    getkeys           X
    make_newrel       X
    modify            X
    modseqkey         X
    sortrel           X
    unspool           X

##### Variables

    F_fac             X
    Mn_pages          X
    Mod_info          X
    Modtab            X
    Mx_pages          X

##### struct's

    mod_info          X
    modtab            X

       1: # include   <stdio.h>
       2:
       3: # include   "../ingres.h"
       4: # include   "../aux.h"
       5: # include   "../access.h"
       6: # include   "../batch.h"
       7: # include   "../lock.h"
       8: # include   "../unix.h"
       9:
      10: /*
      11: **  MODIFY -- converts any relation to the specified
      12: **		storage structure
      13: **
      14: **	arguments:
      15: **	0 - relation name
      16: **	1 - storage structure ("heap", "cheap", "hash", "chash",
      17: **		"isam", "cisam")
      18: **	2 - "name" for attribute names, or "num" for numbers
      19: **	3 - key1
      20: **	4 - key2
      21: **	    .
      22: **	    .
      23: **	i - null
      24: **	i+1 - option name (e.g., "fillfactor")
      25: **	i+2 - option value
      26: **	    .
      27: **	    .
      28: **
      29: **	If all the options default, parameter i -> pc are omitted.
      30: **	If no keys are provided, parameter 2 is omitted.
      31: **
      32: **	History:
      33: **		6/2/80 (eric) -- moved formatpg call from make_newrel
      34: **			into modify so that it would not be necessary
      35: **			to have 3x space.
      36: **		12/28/78 (rse) -- added descending sort option
      37: **		9/25/78 -- (marc) 2 openr's replaced by one
      38: **			as view error code put in openr
      39: **		9/12/78 -- (marc) modified to give error message
      40: **			5519 when someone tries to modify a view.
      41: **			For this I split the openr mode 0 into 2,
      42: **			mode -1 then -2.
      43: */
      44:
      45: int     F_fac, Mn_pages, Mx_pages;
      46:
      47: struct modtab
      48: {
      49:     char    *type;
      50:     char    newrelspec;
      51:     char    yeskeys;
      52:     char    sortit;
      53:     char    yes_seq;
      54:     int f_fac;
      55:     int mn_pages;
      56:     int mx_pages;
      57: };
      58:
      59:
      60: struct modtab   Modtab[] =
      61: {
      62:     /* type		spec	keys	sort	seq	ffac	min	max */
      63:
      64:     "heap",     M_HEAP, FALSE,  FALSE,  FALSE,  0,  0,  0,
      65:     "cheap",    -M_HEAP,FALSE,  FALSE,  FALSE,  0,  0,  0,
      66:     "hash",     M_HASH, TRUE,   TRUE,   FALSE,  50, 10, -1,
      67:     "chash",    -M_HASH,TRUE,   TRUE,   FALSE,  75, 1,  -1,
      68:     "isam",     M_ISAM, TRUE,   TRUE,   FALSE,  80, 0,  0,
      69:     "cisam",    -M_ISAM,TRUE,   TRUE,   FALSE,  100,    0,  0,
      70:     "heapsort", M_HEAP, TRUE,   TRUE,   TRUE,   0,  0,  0,
      71:     "cheapsort",    -M_HEAP,TRUE,   TRUE,   TRUE,   0,  0,  0,
      72:     "truncated",    M_TRUNC,FALSE,  FALSE,  FALSE,  0,  0,  0,
      73:     0
      74: };
      75:
      76: struct mod_info
      77: {
      78:     char    outfile[MAXNAME + 4];   /* result file filled by ksort */
      79:     char    formfile[MAXNAME + 4];  /* file with descriptor for ksort */
      80:     char    infile[MAXNAME + 4];    /* input file for ksort (relation itself */
      81:     char    reltemp[MAXNAME + 4];   /* file holding new relation */
      82:     char    spfile[MAXNAME + 4], spflag;    /* isam spool file for overflow */
      83: };
      84:
      85: struct mod_info Mod_info;
      86:
      87: modify(pc, pv)
      88: int pc;
      89: char    **pv;
      90: {
      91:     register int        i;
      92:     register char       *rname;
      93:     register struct modtab  *mp;
      94:     int         sorted;
      95:     struct descriptor   dold, dnew;
      96:     char            namemode;
      97:     long            temptid;
      98:     extern int      Noupdt;
      99:
     100: #	ifdef xZTR1
     101:     if (tTf(20, -1))
     102:         printf("enter modify\n");
     103: #	endif
     104: #	ifdef xZTM
     105:     if (tTf(76, 1))
     106:         timtrace(15, 0);
     107: #	endif
     108:
     109:     /* check for nice parameters */
     110:     if (pc < 2)
     111:         syserr("MODIFY: pc %d", pc);
     112:
     113:     /* save relation name for error messages */
     114:     rname = *pv++;  /* *pv now pointes to storage spec */
     115:
     116:     /* check for good relation */
     117:     i = openr(&dold, 0, rname);
     118:     if (i == AMOPNVIEW_ERR)
     119:         return (error(5519, rname, 0));
     120:     if (i > 0)
     121:         /* reln does not exist */
     122:         return (error(5500, rname, 0));
     123:     else if (i < 0)
     124:         syserr("MODIFY: openr (%.14s) %d", rname, i);
     125:     /* can only modify a relation you own and isn't a sys rel */
     126:
     127:     if (!bequal(Usercode, dold.relowner, 2))
     128:     {
     129:         i = 5501;
     130:     }
     131:     if ((dold.relstat & S_CATALOG) && Noupdt)
     132:     {
     133:         i = 5504;
     134:     }
     135:     if (i)
     136:     {
     137:         closer(&dold);
     138:         return (error(i, rname, 0));
     139:     }
     140:
     141:     /*
     142: 	** Form descriptor for new relation. Here we need to
     143: 	** separate the pages from the old and new relations.
     144: 	** Since pages are identified by the TID of the relation
     145: 	** relation tuple, both old and new have the same identifiers.
     146: 	** To avoid this problem, a special TID is hand crafted for
     147: 	** the new relation.
     148: 	*/
     149:     bmove(&dold, &dnew, sizeof dnew);
     150:     ((struct tup_id *)&dnew.reltid)->line_id = -2;  /* choose impossible reltid */
     151:
     152:     /* In case of an interrupt from a previous modify,
     153: 	** there might be pages around. Get rid of them.
     154: 	*/
     155:     cleanrel(&dnew);
     156:
     157:     ingresname(dold.relid, dold.relowner, Mod_info.infile);
     158:
     159:     /* scan for entry in relspec table */
     160:     for (mp = Modtab; mp->type; mp++)
     161:         if (sequal(mp->type, *pv))
     162:             break;
     163:
     164:     /* if not found, error */
     165:     if (!mp->type)
     166:     {
     167:         closer(&dold);
     168:         return (error(5510, rname, *pv, 0));    /* bad relspec */
     169:     }
     170:     dnew.relspec = mp->newrelspec;
     171:     if (dnew.relspec == M_TRUNC)
     172:         dnew.relspec = M_HEAP;
     173:
     174:     pv++;   /* now points to first parameter */
     175:
     176:     F_fac = mp->f_fac;
     177:     Mn_pages = mp->mn_pages;
     178:     Mx_pages = mp->mx_pages;
     179:
     180:     /* get the key domains information */
     181:     if (i = getkeys(&pv, rname, &dnew, mp))
     182:     {
     183:         closer(&dold);
     184:         return (i); /* user error */
     185:     }
     186:
     187:     /* get fillfactor and other options if any */
     188:     if (i = getfill(pv, rname, mp))
     189:     {
     190:         closer(&dold);
     191:         return (i); /* user error */
     192:     }
     193:
     194:
     195:     /* lock the relation relation */
     196:     if (Lockrel)
     197:     {
     198:         get_p_tid(&dold, &temptid);
     199:         setrll(A_SLP, temptid, M_EXCL);
     200:     }
     201:
     202:     /* determine parameters & build descriptor for new relation */
     203:     make_newrel(&dnew);
     204:
     205:     if (sorted = (mp->sortit && dold.reltups != 0))
     206:         sortrel(&dold, &dnew);
     207:
     208:     /* actually create the new relation */
     209:     if (formatpg(&dnew, dnew.relprim) != 0)
     210:         syserr("modify: formatpg");
     211:
     212:     /* clear relgiven field; if heap remove any keys */
     213:     clearkeys(&dnew);
     214:     if (abs(dnew.relspec) == M_HEAP)
     215:         for (i = 1; i <= dnew.relatts; i++)
     216:             dnew.relxtra[i] = 0;
     217:
     218:     if (mp->newrelspec != M_TRUNC)
     219:         fill_rel(&dold, &dnew, sorted);
     220:
     221:     closer(&dold);  /* error return is impossible */
     222:     if (abs(dnew.relspec) == M_ISAM)
     223:     {
     224:         if (i = bldindex(&dnew))
     225:             syserr("bldindex: %.14s %d", dnew.relid, i);
     226:         unspool(&dnew);
     227:     }
     228:
     229:     /*
     230: 	** New relation is now complete. The system relations need to
     231: 	** be updated. First destroy all buffers with pages from the
     232: 	** new relation.
     233: 	*/
     234:     if (i = cleanrel(&dnew))
     235:         syserr("modify:clean new %d,%.14s", i, dnew.relid);
     236:
     237:     fill_batch(&dold, &dnew);
     238:
     239:     /*
     240: 	** Close the file for the new relation. This must be
     241: 	** done after the fill_batch in case we are modifing
     242: 	** the attribute relation.
     243: 	*/
     244:     close(dnew.relfp);
     245:     dnew.relopn = 0;
     246:     ruboff("modify");
     247:     modupdate();
     248:     rubon();
     249:
     250:     if (Lockrel)
     251:         unlrl(temptid);
     252:
     253: #	ifdef xZTM
     254:     if (tTf(76, 1))
     255:         timtrace(16, 0);
     256: #	endif
     257:     return (0);
     258: }
     259:
     260:
     261: getkeys(ppv, relname, desc, mp)
     262: char            ***ppv;
     263: char            *relname;
     264: struct descriptor   *desc;
     265: struct modtab       *mp;
     266: {
     267:     register char           **pv;
     268:     register char           *cp;
     269:     register struct descriptor  *d;
     270:     int             namemode, sort_only, as_ds;
     271:     int             i, keyno, keywid;
     272:     struct attribute        attkey, atttup;
     273:     struct tup_id           tid;
     274:     struct tup_id           atttid, attlim;
     275:     extern struct descriptor    Attdes;
     276:
     277:     pv = *ppv;  /* copy list of params */
     278:     d = desc;
     279:
     280:     /* zero key info */
     281:     for (i = 0; i <= d->relatts; i++)
     282:         d->relxtra[i] = d->relgiven[i] = 0;
     283:
     284:     /* determine whether there are any keys at all */
     285:     keyno = 0;
     286:     keywid = 0;
     287:     sort_only = FALSE;
     288:     cp = *pv;
     289:
     290:     if (cp == -1 || *cp == NULL)
     291:     {
     292:         /* no key information. default as needed */
     293:         if (mp->yeskeys)
     294:         {
     295:             cp = "\1";  /* default to first key */
     296:             namemode = FALSE;
     297:         }
     298:         else
     299:             pv++;   /* point one to far */
     300:     }
     301:     else
     302:     {
     303:         /* check for name mode */
     304:         if (namemode = sequal(cp, "name"))
     305:         {
     306:
     307:             /* check attribute names, and convert them to numbers */
     308:             opencatalog("attribute", 0);
     309:             setkey(&Attdes, &attkey, Mod_info.infile, ATTRELID);
     310:             setkey(&Attdes, &attkey, Usercode, ATTOWNER);
     311:         }
     312:         pv++;   /* inc to next key */
     313:         cp = *pv++; /* pick up first key */
     314:     }
     315:
     316:
     317:     /* scan for attribute names */
     318:     for ( ; cp != -1; cp = *pv++)
     319:     {
     320:         /* check for separator between keys & options */
     321:         if (*cp == NULL)
     322:         {
     323:             pv++;   /* point two past NULL */
     324:             break;
     325:         }
     326:
     327:         if (namemode)
     328:         {
     329:             /* check for "sort only" attribute */
     330:             if (*cp == '#')
     331:             {
     332:                 cp++;   /* inc to start of name */
     333:                 sort_only = TRUE;
     334:             }
     335:
     336:             /* check for ascending/descending modifier */
     337:             if ((as_ds = modseqkey(cp, relname, mp->yes_seq)) > 0)
     338:                 return (as_ds); /* error */
     339:
     340:             setkey(&Attdes, &attkey, cp, ATTNAME);
     341:             i = getequal(&Attdes, &attkey, &atttup, &tid);
     342:             if (i < 0)
     343:                 syserr("MODIFY: geteq(att) %d", i);
     344:             if (i > 0)
     345:             {
     346:                 return (error(5511, relname, cp, 0));   /* bad att name */
     347:             }
     348:             i = atttup.attid;
     349:         }
     350:         else
     351:         {
     352:             i = *cp;
     353:             as_ds = 0;
     354:         }
     355:
     356:         /* add new key to descriptor */
     357:         keyno++;
     358:         if (!sort_only)
     359:         {
     360:             d->relxtra[i] = keyno;
     361:             keywid += (d->relfrml[i] & I1MASK);
     362:         }
     363:         if (d->relgiven[i])
     364:             return (error(5507, relname, cp, 0));   /* duplicate attribute */
     365:         d->relgiven[i] = as_ds == 0 ? keyno : -keyno;
     366:     }
     367:     pv--;   /* back up one to point to "-1" terminator */
     368:
     369:
     370:     if (abs(d->relspec) == M_ISAM && keywid > (MAXTUP / 2 - 4))
     371:     {
     372:         return (error(5508, relname, iocv(keywid), 0));
     373:     }
     374:
     375:     /* if a heap, there can be no keys */
     376:     if (!mp->yeskeys && keyno != 0)
     377:     {
     378:         return (error(5502, relname, mp->type, 0)); /* no keys allowed on heap */
     379:     }
     380:
     381:     /* fill out default sort on remainder of keys */
     382:     if (mp->yeskeys)
     383:         for (i = 1; i <= d->relatts; i++)
     384:             if (d->relgiven[i] == 0)
     385:                 d->relgiven[i] = ++keyno;
     386:     *ppv = pv;
     387:     return (0);
     388: }
     389:
     390:
     391: modseqkey(domain, relname, seq_ok)
     392: char    *domain;
     393: char    *relname;
     394: int seq_ok;
     395: {
     396:     register char   *cp, c;
     397:     register int    ret;
     398:
     399:     ret = 0;
     400:
     401:     for (cp = domain; c = *cp++; )
     402:         if (c == ':')
     403:             break;
     404:
     405:     if (c != '\0')
     406:     {
     407:         /* replace ":" with null */
     408:         *(cp - 1) = '\0';
     409:
     410:         /* verify sequence is valid */
     411:         if (!seq_ok)
     412:             ret = error(5520, relname, cp, domain, 0);
     413:         else if (sequal("descending", cp) || sequal("d", cp))
     414:             ret = -1;
     415:         else if (!(sequal("ascending", cp) || sequal("a", cp)))
     416:             ret = error(5518, relname, cp, domain, 0);
     417:     }
     418:
     419:     return (ret);
     420: }
     421:
     422:
     423:
     424: /*
     425: **	GETFILL -- Get fill factor and minimum pages parameters
     426: **		from argument list, convert them from ascii to integer
     427: **		and store them in global variables.  If the global
     428: **		variable for the corresponding parameter is zero,
     429: **		it means that that parameter is not allowed and an
     430: **		error is generated.
     431: */
     432:
     433: getfill(pvx, rel, mp)
     434: char        **pvx;
     435: char        *rel;
     436: struct modinfo  *mp;
     437: {
     438:     register char   **pv, *p1;
     439:     register int    err;
     440:     char        *p2;
     441:     int     fill_flag, min_flag, max_flag;
     442:
     443:     pv = pvx;
     444:     err = 0;
     445:     fill_flag = min_flag = max_flag = FALSE;
     446:
     447:     while ((p1 = *pv++) != -1)
     448:     {
     449:         p2 = *pv++;
     450:         if (sequal(p1, "fillfactor"))
     451:         {
     452:             if (F_fac == 0 || fill_flag)
     453:             {
     454:                 err = 5512;
     455:                 break;
     456:             }
     457:             p1 = p2;
     458:             atoi(p1, &F_fac);
     459:             if (F_fac > 100 || F_fac < 1)
     460:             {
     461:                 err = 5513;
     462:                 break;
     463:             }
     464:             fill_flag = TRUE;
     465:             continue;
     466:         }
     467:         if (sequal(p1, "minpages"))
     468:         {
     469:             if (Mn_pages == 0 || min_flag)
     470:             {
     471:                 err = 5512;
     472:                 break;
     473:             }
     474:             p1 = p2;
     475:             atoi(p1, &Mn_pages);
     476:             if (Mn_pages < 1)
     477:             {
     478:                 err = 5514;
     479:                 break;
     480:             }
     481:             if (max_flag && (Mn_pages > Mx_pages))
     482:             {
     483:                 err = 5517;
     484:                 break;
     485:             }
     486:             min_flag = TRUE;
     487:             continue;
     488:         }
     489:         if (sequal(p1, "maxpages"))
     490:         {
     491:             if (Mx_pages == 0 || max_flag)
     492:             {
     493:                 err = 5512;
     494:                 break;
     495:             }
     496:             p1 = p2;
     497:             atoi(p1, &Mx_pages);
     498:             if (Mx_pages < 1)
     499:             {
     500:                 err = 5516;
     501:                 break;
     502:             }
     503:             if (min_flag && (Mn_pages > Mx_pages))
     504:             {
     505:                 err = 5517;
     506:                 break;
     507:             }
     508:             max_flag = TRUE;
     509:             continue;
     510:         }
     511:         err = 5515;
     512:         break;
     513:     }
     514:     if (err)
     515:         return (error(err, rel, p1, 0));
     516:     return (0);
     517: }
     518:
     519: /*
     520: **	MAKE_NEWREL -- Create a file for the modified relation
     521: **		and build one or more primary pages for the
     522: **		relation based on its storage structure and the
     523: **		number of tuples it must hold.
     524: **
     525: **	History:
     526: **		6/2/80 (eric, mod 11) -- removed formatpg call so
     527: **			that disk space will not be grabbed until
     528: **			sort is done.
     529: */
     530:
     531: make_newrel(descx)
     532: struct descriptor   *descx;
     533: {
     534:     register struct descriptor  *desc;
     535:     register int            i, tups_p_page;
     536:
     537:     desc = descx;
     538:     concat(MODTEMP, Fileset, Mod_info.reltemp);
     539:     close(creat(Mod_info.reltemp, FILEMODE));
     540:     if ((desc->relfp = open(Mod_info.reltemp, 2)) < 0)
     541:         syserr("MAKE_NEWREL: open %.14s %d", Mod_info.reltemp, desc->relfp);
     542:     desc->relopn = (desc->relfp + 1) * -5;
     543:     desc->relprim = 1;
     544:     if (abs(desc->relspec) == M_HASH && F_fac > 0 && Mn_pages > 0)
     545:     {
     546:         /*
     547: 		** Determine the number of primary pages. The following
     548: 		** first determines the number of tuples/page which the
     549: 		** relation should have in order to get the requested
     550: 		** fillfactor. Then that number is divided into the
     551: 		** number of tuples to get the number of primary pages.
     552: 		** To avoid round off, it must guaranteed that the
     553: 		** number of tuples per page must be at least 1.
     554: 		**
     555: 		** primary_pages = #tuples / (#tuples/page * fillfactor)
     556: 		*/
     557:         tups_p_page = (((MAXTUP+2) / (desc->relwid+2)) * F_fac) / 100;
     558:         if (tups_p_page == 0)
     559:             tups_p_page = 1;
     560:          /* we add one to simulate a ceiling function */
     561:         desc->relprim = desc->reltups / tups_p_page + 1;
     562:         if (desc->relprim < Mn_pages)
     563:             desc->relprim = Mn_pages;
     564:         if (Mx_pages > 0 && desc->relprim > Mx_pages)
     565:             desc->relprim = Mx_pages;
     566: #		ifdef xZTR1
     567:         if (tTf(22, 0))
     568:             printf("using %s prim pages\n", locv(desc->relprim));
     569: #		endif
     570:     }
     571:     desc->reltups = 0;
     572:     return (0);
     573: }
     574:
     575: /*
     576: **	SORTREL - Call KSORT to sort the given relation.  SORTREL
     577: **		sets up the descriptor struct specifying the sort
     578: **		keys and tells KSORT whether or not the hash key should
     579: **		be included as a sort key.
     580: */
     581:
     582: sortrel(odesc, descx)
     583: struct descriptor   *odesc, *descx;
     584: {
     585:     extern char         **Xparams;
     586:     register struct descriptor  *desc;
     587:     register int            fp, i;
     588:     char                savespec;
     589:
     590:     desc = descx;
     591:     concat(ISAM_SORTED, Fileset, Mod_info.outfile);
     592:     if (close(creat(Mod_info.outfile, FILEMODE)))
     593:         syserr("SORTREL: creat %.14s", Mod_info.outfile);
     594:     concat(ISAM_DESC, Fileset, Mod_info.formfile);
     595:     if ((fp = creat(Mod_info.formfile, FILEMODE)) < 0)
     596:         syserr("SORTREL: creat %.14s %d", Mod_info.formfile, fp);
     597:     if (abs(desc->relspec) == M_HASH)
     598:     {
     599:         /* sort on hash bucket first */
     600:         desc->relgiven[0] = 1;
     601:         for (i = 1; i <= desc->relatts; i++)
     602:             desc->relgiven[i]++;
     603:     }
     604:     savespec = desc->relspec;
     605:     desc->relspec = odesc->relspec;
     606:     if (write(fp, desc, sizeof *desc) != sizeof *desc)
     607:         syserr("SORTREL: desc write err");
     608:     close(fp);
     609:     desc->relspec = savespec;
     610:
     611:     i = fork();
     612:     if (i == -1)
     613:         syserr("SORTREL: fork");
     614:     if (i == 0)
     615:     {
     616:         for (i = 3; i < MAXFILES; i++)
     617:             close(i);
     618:         execl(Xparams[0], Xparams[0], Fileset, iocv(tTf(23, -1)),
     619:             Mod_info.formfile, Mod_info.infile,
     620:             Mod_info.outfile, 0);
     621:         syserr("SORTREL: exec %s", Xparams[0]);
     622:     }
     623:     if (fp = fullwait(i, "modify")) /* wait for ksort to complete */
     624:         syserr("modify:ksort failed %d", fp);
     625:
     626:     unlink(Mod_info.formfile);
     627:     return (0);
     628: }
     629:
     630: /*
     631: **	FILL_REL -- Fill the new relation with tuples from either
     632: **		the old relation or the output file of KSORT.
     633: */
     634:
     635: fill_rel(sdescx, descx, sortit)
     636: struct descriptor   *sdescx, *descx;
     637: char            sortit;
     638: {
     639:     register struct descriptor  *sdesc, *desc;
     640:     register int            i;
     641:     char                tup_buf[MAXTUP], last_tup[MAXTUP];
     642:     char                junk[4], newreltype, anytups, chkdups;
     643:     int             need, j;
     644:     long                lnum;
     645:     struct tup_id           tid, stid, stidlim;
     646:     FILE                *fp, *spfp;
     647:
     648:     sdesc = sdescx;
     649:     desc = descx;
     650:     newreltype = abs(desc->relspec);
     651:     if (sortit)
     652:     {
     653:         if ((fp = fopen(Mod_info.outfile, "r")) == NULL)
     654:             syserr("FILL_REL: fopen %.14s", Mod_info.outfile);
     655:     }
     656:     else
     657:     {
     658:         cleanrel(sdesc);    /* make sure each page is read fresh */
     659:         find(sdesc, NOKEY, &stid, &stidlim);
     660:     }
     661:     if (newreltype == M_ISAM)
     662:     {
     663:         lnum = 0;
     664:         stuff_page(&tid, &lnum);
     665:         tid.line_id = 0;
     666:         get_page(desc, &tid);
     667:         concat(ISAM_SPOOL, Fileset, Mod_info.spfile);
     668:         /* assume that spool file is not needed */
     669:         spfp = NULL;
     670:         Mod_info.spflag = FALSE;
     671:         if (F_fac == 0)
     672:             F_fac = 100;
     673:         /* setup relgiven field for kcompare later on */
     674:         for (i = 1; i <= desc->relatts; i++)
     675:             desc->relgiven[i] = desc->relxtra[i];
     676:     }
     677:     desc->reladds = 0;
     678:     anytups = FALSE;
     679:     chkdups = !sortit;
     680:     for (;;)
     681:     {
     682:         if (sortit)
     683:         {
     684:             i = fread(tup_buf, 1, desc->relwid, fp);
     685:             if (i == 0)
     686:                 break;
     687:             if (i != desc->relwid)
     688:                 syserr("FILL_REL: fread A %d", i);
     689:             if (newreltype == M_HASH)
     690:                 if (fread(junk, 1, 4, fp) != 4)
     691:                     syserr("FILL_REL: fread B");
     692:         }
     693:         else
     694:         {
     695: #			ifdef xZTR2
     696:             if (tTf(22, 1))
     697:             {
     698:                 printf("FILL_REL: stid ");
     699:                 dumptid(&stid);
     700:                 printf("FILL_REL: stidlim ");
     701:                 dumptid(&stidlim);
     702:             }
     703: #			endif
     704:             i = get(sdesc, &stid, &stidlim, tup_buf, TRUE);
     705: #			ifdef xZTR2
     706:             if (tTf(22, 1))
     707:             {
     708:                 printf("FILLREL: get %d ", i);
     709:                 printup(sdesc, tup_buf);
     710:             }
     711: #			endif
     712:             if (i < 0)
     713:                 syserr("FILL_REL: get %d", i);
     714:             if (i == 1)
     715:                 break;
     716:         }
     717:         if (newreltype != M_ISAM)
     718:         {
     719:             if ((i = insert(desc, &tid, tup_buf, chkdups)) < 0)
     720:                 syserr("FILL_REL: insert %d", i);
     721: #			ifdef xZTR2
     722:             if (tTf(22, 2))
     723:             {
     724:                 printf("FILL_REL: insert ");
     725:                 printup(desc, tup_buf);
     726:                 printf("FILL_REL: insert ret %d at", i);
     727:                 dumptid(&tid);
     728:             }
     729: #			endif
     730:             continue;
     731:         }
     732:         if (anytups)
     733:             i = kcompare(desc, tup_buf, last_tup);
     734:         else
     735:         {
     736:             anytups = TRUE;
     737:             i = 1;
     738:         }
     739:         bmove(tup_buf, last_tup, desc->relwid);
     740:         need = canonical(desc, tup_buf);
     741:         if (i == 0 && need > space_left(Acc_head))
     742:         {
     743:             /* spool out this tuple. will go on overflow page later */
     744:             if (spfp == NULL)
     745:             {
     746:                 if ((spfp = fopen(Mod_info.spfile, "w")) == NULL)
     747:                     syserr("FILL_REL: fopen %.14s", Mod_info.spfile);
     748:                 Mod_info.spflag = TRUE;
     749:             }
     750:             if (fwrite(tup_buf, 1, desc->relwid, spfp) != desc->relwid)
     751:                 syserr("FILL_REL: putb spool");
     752:             continue;
     753:         }
     754:         j = (100 - F_fac) * MAXTUP / 100;
     755:         if (j < need)
     756:             j = need;
     757:         if (i != 0 && j > space_left(Acc_head))
     758:         {
     759:             if (i = add_prim(desc, &tid))
     760:                 syserr("FILL_REL: force ovflo %d", i);
     761:         }
     762:         tid.line_id = newlino(need);
     763:         put_tuple(&tid, Acctuple, need);
     764:         desc->reladds++;
     765:     }
     766:     if (sortit)
     767:     {
     768:         fclose(fp);
     769:         unlink(Mod_info.outfile);
     770:     }
     771:     if (newreltype == M_ISAM)
     772:     {
     773:         if (i = pageflush(Acc_head))
     774:             syserr("fill_rel:pg clean %d", i);
     775:         if (spfp != NULL)
     776:             fclose(spfp);
     777:     }
     778:     desc->reltups = desc->reladds;
     779:     desc->reladds = 0;
     780:     return (0);
     781: }
     782:
     783:
     784: bldindex(dx)
     785: struct descriptor   *dx;
     786:
     787: {
     788:     register struct descriptor  *d;
     789:     register struct tup_id      *tid;
     790:     register int            tmp;
     791:     struct tup_id           tidx;
     792:     struct accbuf           dirbuf;
     793:     int             keywid, level, savespec, keyx[MAXDOM];
     794:     int             offset, len;
     795:     char                tuple[MAXTUP], temptup[MAXTUP], *key;
     796:     long                pageid, start, stop, newstart, newstop;
     797:
     798:     d = dx;
     799:     tid = &tidx;
     800:     keywid = 0;
     801:     for (tmp = 0; tmp < MAXDOM; tmp++)
     802:         keyx[tmp] = 0;
     803:     for (tmp = 1; tmp <= d->relatts; tmp++)
     804:         if (d->relxtra[tmp] > 0)
     805:         {
     806:             keyx[d->relxtra[tmp] - 1] = tmp;
     807:             keywid += d->relfrml[tmp] & I1MASK;
     808:         }
     809:
     810:     /* Determine the last page of the relation. This will
     811: 	** only work if all pages have been written out. Fill_rel
     812: 	** must guarantee that all pages have been written
     813: 	*/
     814:     level = 0;
     815:     last_page(d, tid, 0);
     816:     pluck_page(tid, &stop);
     817:     start = 0;
     818:     dirbuf.filedesc = d->relfp;
     819:     dirbuf.rel_tupid = d->reltid;
     820:     savespec = d->relspec;
     821:     for (;;)
     822:     {
     823: #		ifdef xZTR2
     824:         if (tTf(21, 7))
     825:             printf("isam: level %d\n", level);
     826: #		endif
     827:         dirbuf.ovflopg = start;
     828:         dirbuf.mainpg = level;
     829:         dirbuf.thispage = stop + 1;
     830:         offset = dirbuf.linetab[0] = dirbuf.firstup - &dirbuf;
     831:         dirbuf.bufstatus = BUF_DIRTY | BUF_DIRECT;
     832:
     833:         dirbuf.nxtlino = 0;
     834:         newstart = stop + 1;
     835:         newstop = newstart;
     836:         for (pageid = start; pageid <= stop; pageid++)
     837:         {
     838: #			ifdef xZTR2
     839:             if (tTf(21, 8))
     840:                 printf("isam:get key from %s\n", locv(pageid));
     841: #			endif
     842:             stuff_page(tid, &pageid);
     843:             tid->line_id = 0;
     844:             if (tmp = get(d, tid, tid, tuple, FALSE))
     845:             {
     846:                 /*
     847: 				** If the relation is empty, then page 0 will
     848: 				** return AMINVL_ERR on a get(). Form a blank tuple
     849: 				** and use it to create a one tuple directory
     850: 				*/
     851:                 if (pageid == 0 && tmp == AMINVL_ERR)
     852:                 {
     853:                     clr_tuple(d, tuple);
     854:                 }
     855:                 else
     856:                 {
     857:                     return (-2);
     858:                 }
     859:             }
     860:
     861:             /*
     862: 			** If this is the first level then form the tuple
     863: 			** from the mainpage of the relation. Otherwise
     864: 			** the tuple is the first tuple of a directory page
     865: 			** and it is already correctly formed.
     866: 			*/
     867:             if (level == 0)
     868:             {
     869:                 key = temptup;
     870:                 for (tmp = 0; keyx[tmp] != 0; tmp++)
     871:                 {
     872:                     len = d->relfrml[keyx[tmp]] & I1MASK;
     873:                     bmove(&tuple[d->reloff[keyx[tmp]]], key, len);
     874:                     key += len;
     875:                 }
     876:                 key = temptup;
     877:             }
     878:             else
     879:                 key = tuple;
     880:
     881:             if (keywid > space_left(&dirbuf))
     882:             {
     883:                 if (pageflush(&dirbuf))
     884:                     return (-3);
     885:                 dirbuf.thispage++;
     886:                 newstop = dirbuf.thispage;
     887:                 dirbuf.ovflopg = pageid;
     888:                 offset = dirbuf.linetab[0] = dirbuf.firstup - &dirbuf;
     889:                 dirbuf.bufstatus = BUF_DIRTY;
     890:                 dirbuf.nxtlino = 0;
     891:             }
     892:             /* copy key to directory page */
     893:             bmove(key, &(((struct raw_accbuf *)&dirbuf)->acc_buf[offset]), keywid);
     894:
     895:             /* update next line number */
     896:             offset += keywid;
     897:             dirbuf.nxtlino++;
     898:             dirbuf.linetab[-dirbuf.nxtlino] = offset;
     899:         }
     900:         if (pageflush(&dirbuf))
     901:             return (-4);
     902:         if (newstart == newstop)
     903:             break;
     904:         d->relspec = abs(d->relspec);
     905:         level++;
     906:         start = newstart;
     907:         stop = newstop;
     908:     }
     909:     d->relspec = savespec;
     910:     d->relprim = newstart;
     911:     return (0);
     912: }
     913:
     914: /*
     915: **	UNSPOOL -- Take tuples saved in spool file and insert them
     916: **		in new relation.  This is only for ISAM relations.
     917: */
     918:
     919: unspool(descx)
     920: struct descriptor   *descx;
     921: {
     922:     register struct descriptor  *desc;
     923:     register int            i;
     924:     struct tup_id           tid;
     925:     char                tup_buf[MAXTUP];
     926:     FILE                *spfp;
     927:
     928:     desc = descx;
     929:     if (Mod_info.spflag)
     930:     {
     931:         if ((spfp = fopen(Mod_info.spfile, "r")) == NULL)
     932:             syserr("UNSPOOL: fopen spool");
     933:         while ((i = fread(tup_buf, 1, desc->relwid, spfp)) == desc->relwid)
     934:             if ((i = insert(desc, &tid, tup_buf, FALSE)) < 0)
     935:                 syserr("UNSPOOL: insert %.14s %d", desc->relid, i);
     936:         if (i != 0)
     937:             syserr("UNSPOOL: read %d", i);
     938:         fclose(spfp);
     939:         unlink(Mod_info.spfile);
     940:     }
     941:     desc->reltups += desc->reladds;
     942:     desc->reladds = 0;
     943:     return (0);
     944: }
     945:
     946: /*
     947: **	FILL_BATCH -- Create and fill a batch file containing the
     948: **		updates for the system catalog so that MODIFY will
     949: **		be recoverable if the system crashes.
     950: */
     951:
     952: fill_batch(odesc, descx)
     953: struct descriptor   *odesc, *descx;
     954: {
     955:     register struct descriptor  *desc, *dessys;
     956:     register int            i;
     957:     struct relation         reltup, rkey;
     958:     struct tup_id           tid, lotid, hitid;
     959:     struct attribute        atttup, akey;
     960:     int             j;
     961:     char                prebatch[MAXNAME + 4], modbatch[MAXNAME + 4];
     962:
     963:     desc = descx;
     964:     if (bequal(desc->relid, "relation    ", 12))
     965:     {
     966:         clearkeys(desc);
     967:         setkey(desc, &rkey, desc->relid, RELID);
     968:         setkey(desc, &rkey, desc->relowner, RELOWNER);
     969:         if (i = getequal(desc, &rkey, &reltup, &tid))
     970:             syserr("FILL_BATCH: geteq rel rel %d", i);
     971:         bmove(&tid, &desc->reltid, sizeof desc->reltid);
     972:     }
     973:     else
     974:         bmove(&odesc->reltid, &desc->reltid, sizeof desc->reltid);
     975:     resetacc(Acc_head);
     976:     concat(MOD_PREBATCH, Fileset, prebatch);
     977:     close(creat(prebatch, FILEMODE));
     978:     if ((Batch_fp = open(prebatch, 2)) < 0)
     979:         syserr("FILL_BATCH: open %.14s %d", prebatch, Batch_fp);
     980:     smove(Fileset, Batchbuf.file_id);
     981:     Batch_cnt = 0;
     982:     wrbatch(desc, sizeof *desc);
     983:     if (bequal(desc->relid, "attribute   ", 12))
     984:         dessys = desc;
     985:     else
     986:         dessys = &Admin.adattd;
     987:     clearkeys(dessys);
     988:     setkey(dessys, &akey, desc->relid, ATTRELID);
     989:     setkey(dessys, &akey, desc->relowner, ATTOWNER);
     990:     if (i = find(dessys, EXACTKEY, &lotid, &hitid, &akey))
     991:         syserr("FILL_BATCH: find %d", i);
     992:     j = desc->relatts;
     993:     while(!(i = get(dessys, &lotid, &hitid, &atttup, TRUE)) && j > 0)
     994:         if (!kcompare(dessys, &akey, &atttup))
     995:         {
     996:             j--;
     997:             atttup.attxtra = desc->relxtra[atttup.attid];
     998:             wrbatch(&lotid, sizeof lotid);
     999:             wrbatch(&atttup, sizeof atttup);
    1000:         }
    1001:     if (i < 0 || j > 0)
    1002:         syserr("FILL_BATCH: get att %d count %d", i, j);
    1003:     /* get rid of attribute pages */
    1004:     cleanrel(dessys);
    1005:     flushbatch();
    1006:     close(Batch_fp);
    1007:     concat(MODBATCH, Fileset, modbatch);
    1008:     if (link(prebatch, modbatch) == -1)
    1009:         syserr("FILL_BATCH: can't link %.14s %.14s",
    1010:             prebatch, modbatch);
    1011:     unlink(prebatch);
    1012:     return (0);
    1013: }

#### Defined functions

bldindex defined in line 784; used 1 times

- in line 224

fill_batch defined in line 952; used 1 times

- in line 237

fill_rel defined in line 635; used 1 times

- in line 219

getfill defined in line 433; used 1 times

- in line 188

getkeys defined in line 261; used 1 times

- in line 181

make_newrel defined in line 531; used 1 times

- in line 203

modify defined in line 87; used 5 times

- in /usr/ingres/source/dbu/overlayg.c line 9, 24
- in /usr/ingres/source/dbu/overlaym.c line 1, 8
- in /usr/ingres/source/support/sysmod.c line 218

modseqkey defined in line 391; used 1 times

- in line 337

sortrel defined in line 582; used 1 times

- in line 206

unspool defined in line 919; used 1 times

- in line 226

#### Defined variables

F_fac defined in line 45; used 10 times

- in line 176, 452, 458-459(3), 544, 557, 671-672(2), 754

Mn_pages defined in line 45; used 9 times

- in line 177, 469, 475-481(3), 503, 544, 562-563(2)

Mod_info defined in line 85; used 27 times

- in line 157, 309, 538-541(4), 591-596(6), 619-620(3), 626, 653-654(2), 667-670(2), 746-748(3), 769, 929-931(2), 939

Modtab defined in line 60; used 1 times

- in line 160

Mx_pages defined in line 45; used 9 times

- in line 178, 481, 491, 497-503(3), 564-565(3)

#### Defined struct's

mod_info defined in line 76; used 2 times

- in line 85(2)

modtab defined in line 47; used 6 times

- in line 60(2), 93(2), 265(2)

Last modified: 1995-02-12 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2158 |