|
|
1.1 ! root 1: # include <stdio.h> ! 2: # include <ingres.h> ! 3: # include <pv.h> ! 4: # include <aux.h> ! 5: # include <access.h> ! 6: # include <batch.h> ! 7: # include <lock.h> ! 8: # include <opsys.h> ! 9: # include <func.h> ! 10: # include <version.h> ! 11: # include <symbol.h> ! 12: # include <catalog.h> ! 13: # include <btree.h> ! 14: # include <sccs.h> ! 15: # include <errors.h> ! 16: ! 17: SCCSID(@(#)modify.c 8.8 5/7/85) ! 18: ! 19: extern short tTdbu[]; ! 20: extern int modify(); ! 21: extern int null_fn(); ! 22: ! 23: struct fn_def ModifyFn = ! 24: { ! 25: "MODIFY", ! 26: modify, ! 27: null_fn, ! 28: null_fn, ! 29: NULL, ! 30: 0, ! 31: tTdbu, ! 32: 100, ! 33: 'Z', ! 34: 0 ! 35: }; ! 36: ! 37: /* ! 38: ** MODIFY -- converts any relation to the specified ! 39: ** storage structure ! 40: ** ! 41: ** arguments: ! 42: ** 0 - relation name ! 43: ** 1 - storage structure ("heap", "cheap", "hash", "chash", ! 44: ** "isam", "cisam") ! 45: ** 2 - "name" for attribute names, or "num" for numbers ! 46: ** 3 - key1 ! 47: ** 4 - key2 ! 48: ** . ! 49: ** . ! 50: ** i - null ! 51: ** i+1 - option name (e.g., "fillfactor") ! 52: ** i+2 - option value ! 53: ** . ! 54: ** . ! 55: ** ! 56: ** If all the options default, parameter i -> pc are omitted. ! 57: ** If no keys are provided, parameter 2 is omitted. ! 58: */ ! 59: ! 60: int F_fac, Mn_pages, Mx_pages; ! 61: char Lid[MAXLID][MAXNAME]; ! 62: int NLidKeys; ! 63: int LidKey[MAXLID]; ! 64: ! 65: struct modtab ! 66: { ! 67: char *type; ! 68: char newrelspec; ! 69: char yeskeys; ! 70: char sortit; ! 71: char yes_seq; ! 72: int f_fac; ! 73: int mn_pages; ! 74: int mx_pages; ! 75: }; ! 76: ! 77: ! 78: struct modtab Modtab[] = ! 79: { ! 80: /* type spec keys sort seq ffac min max */ ! 81: ! 82: "heap", M_HEAP, FALSE, FALSE, FALSE, 0, 0, 0, ! 83: "cheap", -M_HEAP,FALSE, FALSE, FALSE, 0, 0, 0, ! 84: "hash", M_HASH, TRUE, TRUE, FALSE, 50, 10, -1, ! 85: "chash", -M_HASH,TRUE, TRUE, FALSE, 75, 1, -1, ! 86: "isam", M_ISAM, TRUE, TRUE, FALSE, 80, 0, 0, ! 87: "cisam", -M_ISAM,TRUE, TRUE, FALSE, 100, 0, 0, ! 88: "heapsort", M_HEAP, TRUE, TRUE, TRUE, 0, 0, 0, ! 89: "cheapsort", -M_HEAP,TRUE, TRUE, TRUE, 0, 0, 0, ! 90: "truncated", M_TRUNC,FALSE, FALSE, FALSE, 0, 0, 0, ! 91: "ordered", M_ORDER,TRUE, FALSE, FALSE, 0, 0, 0, ! 92: 0 ! 93: }; ! 94: ! 95: struct mod_info ! 96: { ! 97: char outfile[MAXNAME + 4]; /* result file filled by ksort */ ! 98: char formfile[MAXNAME + 4]; /* file with descriptor for ksort */ ! 99: char infile[MAXNAME + 4]; /* input file for ksort (relation itself */ ! 100: char reltemp[MAXNAME + 4]; /* file holding new relation */ ! 101: char spfile[MAXNAME + 4], spflag; /* isam spool file for overflow */ ! 102: char btree[MAXNAME + 4]; /* file holding temporary btree structure */ ! 103: char temp_sort[MAXNAME + 4]; /* file holding result of special isam ! 104: ** required when ordering on a field ! 105: */ ! 106: }; ! 107: ! 108: struct mod_info Mod_info; ! 109: ! 110: extern DESC Btreesec; ! 111: extern int Btree_fd; ! 112: ! 113: ! 114: ! 115: modify(pc, pv) ! 116: int pc; ! 117: PARM *pv; ! 118: { ! 119: register int i, j; ! 120: register char *rname; ! 121: register struct modtab *mp; ! 122: struct modtab *p; ! 123: int sorted, dim; ! 124: DESC dold, dnew; ! 125: long temptid; ! 126: extern int Noupdt; ! 127: extern DESC Attdes; ! 128: struct attribute atttup, attkey; ! 129: TID tid; ! 130: int lidkey, numatts; ! 131: extern char *trim_relname(); ! 132: extern char *iocv(); ! 133: ! 134: ! 135: # ifdef xZTR1 ! 136: if (tTf(34, -1)) ! 137: { ! 138: printf("enter modify\n"); ! 139: prvect(pc, pv); ! 140: } ! 141: # endif ! 142: ! 143: pv[pc].pv_val.pv_str = NULL; ! 144: ! 145: /* check for nice parameters */ ! 146: if (pc < 2) ! 147: syserr("MODIFY: pc %d", pc); ! 148: ! 149: /* save relation name for error messages */ ! 150: rname = (pv++)->pv_val.pv_str; /* *pv now pointes to storage spec */ ! 151: ! 152: /* check for good relation */ ! 153: i = openr(&dold, OR_READ, rname); ! 154: if (i == AMOPNVIEW_ERR) ! 155: return (error(NOMODVIEW, rname, 0)); ! 156: if (i > 0) ! 157: /* reln does not exist */ ! 158: return (error(NOREL, rname, 0)); ! 159: else if (i < 0) ! 160: syserr("MODIFY: openr (%.14s) %d", rname, i); ! 161: /* can only modify a relation you own and isn't a sys rel */ ! 162: ! 163: if (!bequal(Usercode, dold.reldum.relowner, UCODE_SZ)) ! 164: { ! 165: i = NOOWN; ! 166: } ! 167: if ((dold.reldum.relstat & S_CATALOG) && Noupdt) ! 168: { ! 169: i = NOMODSYSREL; ! 170: } ! 171: if (i) ! 172: { ! 173: closer(&dold); ! 174: return (error(i, rname, 0)); ! 175: } ! 176: ! 177: /* ! 178: ** Form descriptor for new relation. Here we need to ! 179: ** separate the pages from the old and new relations. ! 180: ** Since pages are identified by the TID of the relation ! 181: ** relation tuple, both old and new have the same identifiers. ! 182: ** To avoid this problem, a special TID is hand crafted for ! 183: ** the new relation. ! 184: */ ! 185: bmove(&dold, &dnew, sizeof dnew); ! 186: dnew.reltid.s_tupid.line_id = (char) -2; /* choose impossible reltid */ ! 187: /* assume new relation isn't ordered */ ! 188: if (dold.reldum.reldim) ! 189: { ! 190: dnew.reldum.relatts -= dold.reldum.reldim; ! 191: dnew.reldum.relwid -= dold.reldum.reldim * LIDSIZE; ! 192: dnew.reldum.reldim = 0; ! 193: } ! 194: ! 195: /* In case of an interrupt from a previous modify, ! 196: ** there might be pages around. Get rid of them. ! 197: */ ! 198: cleanrel(&dnew); ! 199: ! 200: ingresname(dold.reldum.relid, dold.reldum.relowner, Mod_info.infile); ! 201: dim = 0; ! 202: NLidKeys = 0; ! 203: ! 204: /* scan for entry in relspec table */ ! 205: for (mp = Modtab; mp->type; mp++) ! 206: { ! 207: if (bequal(mp->type, pv->pv_val.pv_str, 7) && bequal("ordered", pv->pv_val.pv_str, 7)) ! 208: { ! 209: if ((dim = atoi(pv->pv_val.pv_str + 7)) <= 0 || dim > MAXLID) ! 210: { ! 211: closer(&dold); ! 212: return(error(BADORDDIM, rname, iocv(dim), 0)); ! 213: } ! 214: break; ! 215: } ! 216: if (sequal(mp->type, pv->pv_val.pv_str)) ! 217: break; ! 218: } ! 219: ! 220: /* if not found, error */ ! 221: if (!mp->type) ! 222: { ! 223: closer(&dold); ! 224: return (error(BADSTORAGE, rname, pv->pv_val.pv_str, 0)); /* bad relspec */ ! 225: } ! 226: ! 227: if (mp->newrelspec == M_ORDER && dold.reldum.relindxd == SECINDEX) ! 228: /* can't order an index relation */ ! 229: { ! 230: closer(&dold); ! 231: return(error(NOORDINDX, rname,0)); ! 232: } ! 233: ! 234: if (mp->newrelspec == M_ORDER) ! 235: { ! 236: dnew.reldum.reldim = dim; ! 237: for (i = 0; i < dim; ++i) ! 238: { ! 239: ++dnew.reldum.relatts; ! 240: dnew.relxtra[dnew.reldum.relatts] = 0; ! 241: dnew.reloff[dnew.reldum.relatts] = dnew.reldum.relwid; ! 242: dnew.relfrmt[dnew.reldum.relatts] = INT; ! 243: dnew.relfrml[dnew.reldum.relatts] = LIDSIZE; ! 244: dnew.reldum.relwid += LIDSIZE; ! 245: } ! 246: concat(BTREE, Fileset, Mod_info.btree); ! 247: create_btree(Mod_info.btree); ! 248: dnew.btree_fd = Btree_fd; ! 249: /* ok to order ascending/descending */ ! 250: mp->yes_seq = TRUE; ! 251: } ! 252: else ! 253: { ! 254: dnew.reldum.relspec = mp->newrelspec; ! 255: if (dold.reldum.reldim) ! 256: { ! 257: dold.reldum.relatts -= dold.reldum.reldim; ! 258: dold.reldum.relwid -= dold.reldum.reldim * LIDSIZE; ! 259: dold.reldum.reldim = 0; ! 260: closer(dold.relbtree); ! 261: close(dold.btree_fd); ! 262: } ! 263: } ! 264: ! 265: if (dnew.reldum.relspec == M_TRUNC) ! 266: dnew.reldum.relspec = M_HEAP; ! 267: ! 268: pv++; /* now points to first parameter */ ! 269: ! 270: /* get the key domains information */ ! 271: if ((i = getkeys(&pv, rname, &dnew, mp)) > 0) ! 272: { ! 273: closer(&dold); ! 274: return (i); /* user error */ ! 275: } ! 276: ! 277: j = 0; ! 278: for (i = 0; i < NLidKeys; ++i) ! 279: if (LidKey[i] > dold.reldum.relatts - dold.reldum.reldim) ! 280: { ! 281: j = 1; ! 282: break; ! 283: } ! 284: ! 285: if (!j && dold.reldum.reldim) ! 286: /* treat old relation as if not ordered since lid field not needed */ ! 287: { ! 288: dold.reldum.relatts -= dold.reldum.reldim; ! 289: dold.reldum.relwid -= dold.reldum.reldim * LIDSIZE; ! 290: dold.reldum.reldim = 0; ! 291: closer(dold.relbtree); ! 292: close(dold.btree_fd); ! 293: } ! 294: ! 295: if (!dnew.reldum.reldim || !NLidKeys) ! 296: { ! 297: F_fac = mp->f_fac; ! 298: Mn_pages = mp->mn_pages; ! 299: Mx_pages = mp->mx_pages; ! 300: } ! 301: else ! 302: /* set parameters to that of storage type of relation to be ordered */ ! 303: { ! 304: for (p = Modtab; p->type; p++) ! 305: if (dnew.reldum.relspec == p->newrelspec) ! 306: break; ! 307: F_fac = p->f_fac; ! 308: Mn_pages = p->mn_pages; ! 309: Mx_pages = p->mx_pages; ! 310: } ! 311: ! 312: if (mp->newrelspec != M_ORDER) ! 313: for (i = 0; i < dnew.reldum.reldim; ++i) ! 314: Lid[i][0] = NULL; ! 315: else ! 316: for (i = 1; i <= dnew.reldum.reldim; ++i) ! 317: concat("lid", iocv(i), Lid[i-1]); ! 318: ! 319: /* get fillfactor and other options if any */ ! 320: if (i = getfill(&dnew, pv, rname, mp)) ! 321: { ! 322: closer(&dold); ! 323: return (i); /* user error */ ! 324: } ! 325: ! 326: /* check for duplicate attribute name */ ! 327: if (mp->newrelspec == M_ORDER) ! 328: { ! 329: opencatalog("attribute", OR_READ); ! 330: setkey(&Attdes, &attkey, dnew.reldum.relid, ATTRELID); ! 331: setkey(&Attdes, &attkey, dnew.reldum.relowner, ATTOWNER); ! 332: numatts = dold.reldum.relatts - dold.reldum.reldim; ! 333: for (i = 0; i < dnew.reldum.reldim; ++i) ! 334: { ! 335: setkey(&Attdes, &attkey, Lid[i], ATTNAME); ! 336: if (getequal(&Attdes, &attkey, &atttup, &tid) == 0) ! 337: { ! 338: if (atttup.attid <= numatts) ! 339: /* ok to duplicate attributes that will be removed */ ! 340: { ! 341: closer(&dold); ! 342: return(error(INVALIDATTR, rname, Lid[i], 0)); ! 343: } ! 344: } ! 345: } ! 346: } ! 347: ! 348: /* lock the relation relation */ ! 349: if (Lockrel) ! 350: { ! 351: get_p_tid(&dold, &temptid); ! 352: setrll(A_SLP, temptid, M_EXCL); ! 353: } ! 354: ! 355: if (!dnew.reldum.reldim || NLidKeys > 0) ! 356: /* compute new relation parameters & build descriptor */ ! 357: make_newrel(&dnew); ! 358: ! 359: if (sorted = ((mp->sortit || NLidKeys > 0) && (dold.reldum.reltups != 0))) ! 360: { ! 361: sortrel(&dold, &dnew); ! 362: dold.reldum.relindxd = 0; ! 363: } ! 364: ! 365: if (!dnew.reldum.reldim || NLidKeys > 0) ! 366: /* physically create the new relation */ ! 367: if (formatpg(&dnew, dnew.reldum.relprim) != 0) ! 368: syserr("modify: formatpg"); ! 369: ! 370: /* clear relgiven field; if heap remove any keys */ ! 371: clearkeys(&dnew); ! 372: ! 373: if (abs(dnew.reldum.relspec) == M_HEAP) ! 374: for (i = 1; i <= dnew.reldum.relatts; i++) ! 375: dnew.relxtra[i] = 0; ! 376: ! 377: if (NLidKeys > 0 && dnew.reldum.relspec == M_ISAM) ! 378: sort_isam(&dold, &dnew); ! 379: ! 380: if (mp->newrelspec != M_TRUNC) ! 381: fill_rel(&dold, &dnew, sorted); ! 382: ! 383: closer(&dold); /* error return is impossible */ ! 384: if (abs(dnew.reldum.relspec) == M_ISAM && (!dnew.reldum.reldim || NLidKeys > 0)) ! 385: { ! 386: j = dnew.reldum.reldim; ! 387: dnew.reldum.reldim = 0; ! 388: if (i = bldindex(&dnew)) ! 389: syserr("bldindex: %.14s %d", dnew.reldum.relid, i); ! 390: dnew.reldum.reldim = j; ! 391: unspool(&dold, &dnew); ! 392: } ! 393: ! 394: /* ! 395: ** New relation is now complete. The system relations need to ! 396: ** be updated. First destroy all buffers with pages from the ! 397: ** new relation. ! 398: */ ! 399: if (i = cleanrel(&dnew)) ! 400: syserr("modify:clean new %d,%.14s", i, dnew.reldum.relid); ! 401: ! 402: fill_batch(&dold, &dnew); ! 403: ! 404: /* ! 405: ** Close the file for the new relation. This must be ! 406: ** done after the fill_batch in case we are modifing ! 407: ** the attribute relation. ! 408: */ ! 409: if (!dnew.reldum.reldim || NLidKeys > 0) ! 410: close(dnew.relfp); ! 411: dnew.relopn = 0; ! 412: ruboff("modify"); ! 413: modupdate(); ! 414: if (mp->newrelspec == M_ORDER) ! 415: { ! 416: close(dnew.btree_fd); ! 417: make_bsec(dnew.reldum.relid, dim); ! 418: } ! 419: rubon(); ! 420: ! 421: if (Lockrel) ! 422: unlrl(temptid); ! 423: ! 424: return (0); ! 425: } ! 426: ! 427: ! 428: /* ! 429: ** GETKEYS - get key domains information ! 430: ** ! 431: ** Parameters: ! 432: ** ppv - parameter vector with info about keys ! 433: ** relname - relation name ! 434: ** d - new descriptor for the relation ! 435: ** mp - mod table ! 436: ** ! 437: ** Return Codes: ! 438: ** 0 - ok ! 439: ** >0 - error from modseqkey ! 440: */ ! 441: getkeys(ppv, relname, d, mp) ! 442: PARM **ppv; ! 443: char *relname; ! 444: register DESC *d; ! 445: struct modtab *mp; ! 446: { ! 447: register PARM *pv; ! 448: register char *cp; ! 449: int namemode, sort_only, as_ds; ! 450: int i, j, keyno, keywid; ! 451: struct attribute attkey, atttup; ! 452: struct index ikey, itup; ! 453: TID tid; ! 454: extern DESC Attdes, Inddes; ! 455: extern char *iocv(); ! 456: ! 457: pv = *ppv; /* copy list of params */ ! 458: ! 459: if (mp->newrelspec != M_ORDER) ! 460: /* zero key info (ordering does not change keyed fields) */ ! 461: for (i = 0; i <= d->reldum.relatts; i++) ! 462: d->relxtra[i] = 0; ! 463: for (i = 0; i <= d->reldum.relatts; ++i) ! 464: d->relgiven[i] = 0; ! 465: ! 466: /* determine whether there are any keys at all */ ! 467: keywid = 0; ! 468: keyno = 0; ! 469: sort_only = FALSE; ! 470: cp = pv->pv_val.pv_str; ! 471: ! 472: if (cp == NULL || *cp == NULL) ! 473: { ! 474: /* no key information. default as needed */ ! 475: if (mp->yeskeys && mp->newrelspec != M_ORDER) ! 476: { ! 477: cp = "\1"; /* default to first key */ ! 478: namemode = FALSE; ! 479: } ! 480: else ! 481: pv++; /* point one to far */ ! 482: } ! 483: else ! 484: { ! 485: /* check for name mode */ ! 486: if (namemode = sequal(cp, "name")) ! 487: { ! 488: ! 489: /* check attribute names, and convert them to numbers */ ! 490: opencatalog("attribute", OR_READ); ! 491: setkey(&Attdes, &attkey, Mod_info.infile, ATTRELID); ! 492: setkey(&Attdes, &attkey, Usercode, ATTOWNER); ! 493: } ! 494: pv++; /* inc to next key */ ! 495: cp = (pv++)->pv_val.pv_str; ! 496: } ! 497: ! 498: /* scan for attribute names */ ! 499: for (; cp != NULL; cp = (pv++)->pv_val.pv_str) ! 500: { ! 501: /* check for separator between keys & options */ ! 502: if (*cp == NULL) ! 503: { ! 504: pv++; /* point two past NULL */ ! 505: break; ! 506: } ! 507: ! 508: if (NLidKeys >= d->reldum.reldim && mp->newrelspec == M_ORDER) ! 509: { ! 510: /* more than one field specified as ordering key */ ! 511: closeall(0l, 0l); ! 512: return(error(TOOMANYORDKEYS, relname, 0)); ! 513: } ! 514: ! 515: if (namemode) ! 516: { ! 517: /* check for "sort only" attribute */ ! 518: if (*cp == '#') ! 519: { ! 520: cp++; /* inc to start of name */ ! 521: sort_only = TRUE; ! 522: } ! 523: ! 524: /* check for ascending/descending modifier */ ! 525: if ((as_ds = modseqkey(cp, relname, mp->yes_seq)) > 0) ! 526: return (as_ds); /* error */ ! 527: ! 528: setkey(&Attdes, &attkey, cp, ATTNAME); ! 529: i = getequal(&Attdes, &attkey, &atttup, &tid); ! 530: if (i < 0) ! 531: syserr("MODIFY: geteq(att) %d", i); ! 532: if (i > 0) ! 533: { ! 534: closeall(0l, 0l); ! 535: return (error(INVALIDATTR, relname, cp, 0)); /* bad att name */ ! 536: } ! 537: i = atttup.attid; ! 538: if (i > d->reldum.relatts) ! 539: { ! 540: /* attempting to key on lid field which will be ! 541: ** removed ! 542: */ ! 543: closeall(0l,0l); ! 544: return(error(ATTRREMV, relname, cp, 0)); ! 545: } ! 546: } ! 547: else ! 548: { ! 549: i = *cp; ! 550: as_ds = 0; ! 551: } ! 552: ! 553: keyno++; ! 554: /* add new key to descriptor */ ! 555: if (mp->newrelspec == M_ORDER) ! 556: LidKey[NLidKeys++] = i; ! 557: if (!sort_only && mp->newrelspec != M_ORDER) ! 558: { ! 559: d->relxtra[i] = keyno; ! 560: keywid += (d->relfrml[i] & I1MASK); ! 561: } ! 562: if (d->relgiven[i]) ! 563: { ! 564: closeall(0l, 0l); ! 565: return (error(DUPKEY, relname, cp, 0)); /* duplicate attribute */ ! 566: } ! 567: d->relgiven[i] = as_ds == 0 ? keyno : -keyno; ! 568: } ! 569: pv--; /* back up one to point to "-1" terminator */ ! 570: ! 571: ! 572: if (abs(d->reldum.relspec) == M_ISAM && keywid > (MAXTUP / 2 - 4)) ! 573: { ! 574: closeall(0l, 0l); ! 575: return (error(TOOWIDEISAM, relname, iocv(keywid), 0)); ! 576: } ! 577: ! 578: /* if a heap, there can be no keys */ ! 579: if (!mp->yeskeys && keyno != 0) ! 580: { ! 581: closeall(0l, 0l); ! 582: return (error(NOKEYSHEAP, relname, mp->type, 0)); /* no keys allowed on heap */ ! 583: } ! 584: /* fill out default sort on remainder of keys */ ! 585: if (mp->yeskeys) ! 586: for (i = 1; i <= d->reldum.relatts; i++) ! 587: if (d->relgiven[i] == 0) ! 588: d->relgiven[i] = ++keyno; ! 589: *ppv = pv; ! 590: return (0); ! 591: } ! 592: ! 593: ! 594: /* ! 595: ** MODSEQKEY - verify that sequence specified is valid ! 596: ** ! 597: ** Parameters: ! 598: ** domain - list of domains ! 599: ** relname - relation name ! 600: ** seq_ok - whether it is ok to specify the sequence ! 601: ** ascending or descending ! 602: ** ! 603: ** Return Codes: ! 604: ** 0 - ok ! 605: ** > 0 - error in sequence specified ! 606: ** ! 607: ** Called by: ! 608: ** getkeys ! 609: */ ! 610: modseqkey(domain, relname, seq_ok) ! 611: char *domain; ! 612: char *relname; ! 613: int seq_ok; ! 614: { ! 615: register char *cp, c; ! 616: register int ret; ! 617: ! 618: ret = 0; ! 619: ! 620: for (cp = domain; c = *cp++; ) ! 621: if (c == ':') ! 622: break; ! 623: ! 624: if (c != '\0') ! 625: { ! 626: /* replace ":" with null */ ! 627: *(cp - 1) = '\0'; ! 628: ! 629: /* verify sequence is valid */ ! 630: if (!seq_ok) ! 631: { ! 632: closeall(0l, 0l); ! 633: ret = error(BADSEQSPEC, relname, cp, domain, 0); ! 634: } ! 635: else if (sequal("descending", cp) || sequal("d", cp)) ! 636: ret = -1; ! 637: else if (!(sequal("ascending", cp) || sequal("a", cp))) ! 638: { ! 639: closeall(0l, 0l); ! 640: ret = error(INVALIDSEQ, relname, cp, domain, 0); ! 641: } ! 642: } ! 643: ! 644: return (ret); ! 645: } ! 646: /* ! 647: ** GETFILL -- Get fill factor and minimum pages parameters ! 648: ** from argument list, convert them from ascii to integer ! 649: ** and store them in global variables. If the global ! 650: ** variable for the corresponding parameter is zero, ! 651: ** it means that that parameter is not allowed and an ! 652: ** error is generated. ! 653: */ ! 654: ! 655: /*ARGSUSED*/ ! 656: getfill(d, pv, rel, mp) ! 657: DESC *d; ! 658: register PARM *pv; ! 659: char *rel; ! 660: struct modtab *mp; ! 661: { ! 662: register char *p1; ! 663: register int err; ! 664: char *p2; ! 665: int i, j; ! 666: int fill_flag, min_flag, max_flag, lid_flag[MAXLID]; ! 667: ! 668: err = 0; ! 669: fill_flag = min_flag = max_flag = FALSE; ! 670: for (i = 0; i < d->reldum.reldim; ++i) ! 671: lid_flag[i] = FALSE; ! 672: ! 673: while ((p1 = (pv++)->pv_val.pv_str) != NULL) ! 674: { ! 675: p2 = (pv++)->pv_val.pv_str; ! 676: if (sequal(p1, "fillfactor")) ! 677: { ! 678: if (F_fac == 0 || fill_flag) ! 679: { ! 680: err = NOTALLOWED; ! 681: break; ! 682: } ! 683: p1 = p2; ! 684: F_fac = atoi(p1); ! 685: if (F_fac > 100 || F_fac < 1) ! 686: { ! 687: err = FILLBOUND; ! 688: break; ! 689: } ! 690: fill_flag = TRUE; ! 691: continue; ! 692: } ! 693: if (sequal(p1, "minpages")) ! 694: { ! 695: if (Mn_pages == 0 || min_flag) ! 696: { ! 697: err = NOTALLOWED; ! 698: break; ! 699: } ! 700: p1 = p2; ! 701: Mn_pages = atoi(p1); ! 702: if (Mn_pages < 1) ! 703: { ! 704: err = MINPGBOUND; ! 705: break; ! 706: } ! 707: if (max_flag && (Mn_pages > Mx_pages)) ! 708: { ! 709: err = MINGTMAX; ! 710: break; ! 711: } ! 712: min_flag = TRUE; ! 713: continue; ! 714: } ! 715: if (sequal(p1, "maxpages")) ! 716: { ! 717: if (Mx_pages == 0 || max_flag) ! 718: { ! 719: err = NOTALLOWED; ! 720: break; ! 721: } ! 722: p1 = p2; ! 723: Mx_pages = atoi(p1); ! 724: if (Mx_pages < 1) ! 725: { ! 726: err = MAXPGBOUND; ! 727: break; ! 728: } ! 729: if (min_flag && (Mn_pages > Mx_pages)) ! 730: { ! 731: err = MINGTMAX; ! 732: break; ! 733: } ! 734: max_flag = TRUE; ! 735: continue; ! 736: } ! 737: for ( i = 1; i <= d->reldum.reldim && !err; ++i) ! 738: if (sequal(p1, ztack("lid", iocv(i)))) ! 739: { ! 740: if (lid_flag[i-1] || *Lid[i-1] == NULL) ! 741: { ! 742: err = NOTALLOWED; ! 743: break; ! 744: } ! 745: for (j = 0; j < d->reldum.reldim; ++j) ! 746: if (i - 1 != j && sequal(p2, Lid[j]) && lid_flag[j]) ! 747: { ! 748: err = NOTALLOWED; ! 749: break; ! 750: } ! 751: p1 = p2; ! 752: smove(p1, Lid[i - 1]); ! 753: lid_flag[i - 1] = TRUE; ! 754: break; ! 755: } ! 756: if (err) ! 757: break; ! 758: if (i <= d->reldum.reldim) ! 759: continue; ! 760: err = NEEDFILL; ! 761: break; ! 762: } ! 763: if (err) ! 764: { ! 765: closeall(0l, 0l); ! 766: return (error(err, rel, p1, 0)); ! 767: } ! 768: return (0); ! 769: } ! 770: /* ! 771: ** MAKE_NEWREL -- Create a file for the modified relation ! 772: ** and build one or more primary pages for the ! 773: ** relation based on its storage structure and the ! 774: ** number of tuples it must hold. ! 775: */ ! 776: ! 777: make_newrel(desc) ! 778: register DESC *desc; ! 779: { ! 780: register int tups_p_page; ! 781: int width; ! 782: ! 783: concat(MODTEMP, Fileset, Mod_info.reltemp); ! 784: close(creat(Mod_info.reltemp, FILEMODE)); ! 785: if ((desc->relfp = open(Mod_info.reltemp, O_RDWR)) < 0) ! 786: syserr("MAKE_NEWREL: open %.14s %d", Mod_info.reltemp, desc->relfp); ! 787: desc->relopn = (desc->relfp + 1) * -5; ! 788: desc->reldum.relprim = 1; ! 789: if (abs(desc->reldum.relspec) == M_HASH && F_fac > 0 && Mn_pages > 0) ! 790: { ! 791: /* ! 792: ** Determine the number of primary pages. The following ! 793: ** first determines the number of tuples/page which the ! 794: ** relation should have in order to get the requested ! 795: ** fillfactor. Then that number is divided into the ! 796: ** number of tuples to get the number of primary pages. ! 797: ** To avoid round off, it must guaranteed that the ! 798: ** number of tuples per page must be at least 1. ! 799: ** ! 800: ** primary_pages = #tuples / (#tuples/page * fillfactor) ! 801: */ ! 802: width = desc->reldum.relwid + 2 - LIDSIZE * desc->reldum.reldim; ! 803: tups_p_page = (((MAXTUP+2) / width) * F_fac) / 100; ! 804: if (tups_p_page == 0) ! 805: tups_p_page = 1; ! 806: /* we add one to simulate a ceiling function */ ! 807: desc->reldum.relprim = desc->reldum.reltups / tups_p_page + 1; ! 808: if (desc->reldum.relprim < Mn_pages) ! 809: desc->reldum.relprim = Mn_pages; ! 810: if (Mx_pages > 0 && desc->reldum.relprim > Mx_pages) ! 811: desc->reldum.relprim = Mx_pages; ! 812: # ifdef xZTR1 ! 813: if (tTf(36, 0)) ! 814: printf("using %ld prim pages\n", desc->reldum.relprim); ! 815: # endif ! 816: } ! 817: desc->reldum.reltups = 0; ! 818: return (0); ! 819: } ! 820: /* ! 821: ** SORTREL - Call KSORT to sort the given relation. SORTREL ! 822: ** sets up the descriptor struct specifying the sort ! 823: ** keys and tells KSORT whether or not the hash key should ! 824: ** be included as a sort key. ! 825: */ ! 826: ! 827: sortrel(odesc, desc) ! 828: DESC *odesc; ! 829: register DESC *desc; ! 830: { ! 831: extern char *Pathname; ! 832: register int i; ! 833: char buf[50]; ! 834: DESC tempdesc; ! 835: char *temp; ! 836: int len; ! 837: short smalli; ! 838: ! 839: concat(ISAM_SORTED, Fileset, Mod_info.outfile); ! 840: if (close(creat(Mod_info.outfile, FILEMODE))) ! 841: syserr("SORTREL: creat %.14s", Mod_info.outfile); ! 842: bmove(odesc, &tempdesc, sizeof *odesc); ! 843: for (i = 1; i <= desc->reldum.relatts; ++i) ! 844: /* set up temporary descriptor for ksort with new keyed fields */ ! 845: { ! 846: tempdesc.relxtra[i] = desc->relxtra[i]; ! 847: tempdesc.relgiven[i] = desc->relgiven[i]; ! 848: } ! 849: ! 850: if (abs(desc->reldum.relspec) == M_HASH && !desc->reldum.reldim) ! 851: { ! 852: /* sort on hash bucket first, (if ordering sort on ordering key, not bucket) */ ! 853: tempdesc.relgiven[0] = 1; ! 854: for (i = 1; i <= desc->reldum.relatts; i++) ! 855: tempdesc.relgiven[i]++; ! 856: } ! 857: ! 858: # ifdef xZTR2 ! 859: if (tTf(36, 4)) ! 860: { ! 861: printf("sortrel: "); ! 862: printdesc(&tempdesc); ! 863: } ! 864: # endif ! 865: ! 866: /* flush buffers used by modify so that ksort can't look at them */ ! 867: flush_rel(desc, TRUE); ! 868: resetacc(NULL); ! 869: ! 870: /* copy Fileset so it can't get trashed */ ! 871: ! 872: len = length(Fileset) + 1; ! 873: temp = (char *) need(Qbuf, len); ! 874: bmove(Fileset, temp, len); ! 875: ! 876: initp(); ! 877: setp(PV_STR, temp); ! 878: setp(PV_STR, Mod_info.infile); ! 879: setp(PV_STR, Mod_info.outfile); ! 880: ! 881: /* Descriptor for new relation */ ! 882: setp(PV_STR, tempdesc.reldum.relid); ! 883: setp(PV_STR, tempdesc.reldum.relowner); ! 884: setp(PV_INT, tempdesc.reldum.relspec); ! 885: setp(PV_INT, tempdesc.reldum.relindxd); ! 886: setp(PV_INT, tempdesc.reldum.relstat2); ! 887: setp(PV_INT, tempdesc.reldum.relstat); ! 888: setp(PV_INT, (short) tempdesc.reldum.relsave); ! 889: setp(PV_INT, (short) tempdesc.reldum.reltups); ! 890: setp(PV_INT, tempdesc.reldum.relatts); ! 891: setp(PV_INT, tempdesc.reldum.relwid); ! 892: setp(PV_INT, (short) tempdesc.reldum.relprim); ! 893: setp(PV_INT, (short) tempdesc.reldum.relfree); ! 894: setp(PV_INT, (short) tempdesc.reldum.relstamp); ! 895: setp(PV_INT, tempdesc.reldum.reldim); ! 896: ! 897: setp(PV_STR, tempdesc.relvname); ! 898: setp(PV_INT, tempdesc.relfp); ! 899: setp(PV_INT, tempdesc.relopn); ! 900: setp(PV_INT, (short) tempdesc.reladds); ! 901: setp(PV_INT, tempdesc.reltid.ltid); ! 902: for (i = 0; i <= tempdesc.reldum.relatts; ++i) ! 903: { ! 904: smalli = (short) tempdesc.reloff[i]; ! 905: setp(PV_INT, smalli); ! 906: smalli = (short) tempdesc.relfrmt[i]; ! 907: setp(PV_INT, smalli); ! 908: smalli = (short) tempdesc.relfrml[i]; ! 909: setp(PV_INT, smalli); ! 910: smalli = (short) tempdesc.relxtra[i]; ! 911: setp(PV_INT, smalli); ! 912: smalli = (short) tempdesc.relgiven[i]; ! 913: setp(PV_INT, smalli); ! 914: } ! 915: ! 916: if (tempdesc.reldum.reldim > 0) ! 917: { ! 918: setp(PV_STR, odesc->relbtree->reldum.relid); ! 919: setp(PV_STR, odesc->relbtree->reldum.relowner); ! 920: setp(PV_INT, odesc->relbtree->reldum.relspec); ! 921: setp(PV_INT, odesc->relbtree->reldum.relindxd); ! 922: setp(PV_INT, odesc->relbtree->reldum.relstat2); ! 923: setp(PV_INT, odesc->relbtree->reldum.relstat); ! 924: setp(PV_INT, (short) odesc->relbtree->reldum.relsave); ! 925: setp(PV_INT, (short) odesc->relbtree->reldum.reltups); ! 926: setp(PV_INT, odesc->relbtree->reldum.relatts); ! 927: setp(PV_INT, odesc->relbtree->reldum.relwid); ! 928: setp(PV_INT, (short) odesc->relbtree->reldum.relprim); ! 929: setp(PV_INT, (short) odesc->relbtree->reldum.relfree); ! 930: setp(PV_INT, (short) odesc->relbtree->reldum.relstamp); ! 931: setp(PV_INT, odesc->relbtree->reldum.reldim); ! 932: ! 933: setp(PV_STR, odesc->relbtree->relvname); ! 934: setp(PV_INT, odesc->relbtree->relfp); ! 935: setp(PV_INT, odesc->relbtree->relopn); ! 936: setp(PV_INT, (short) odesc->relbtree->reladds); ! 937: setp(PV_INT, odesc->relbtree->reltid.ltid); ! 938: ! 939: for (i = 0; i <= odesc->relbtree->reldum.relatts; ++i) ! 940: { ! 941: smalli = (short) odesc->relbtree->reloff[i]; ! 942: setp(PV_INT, smalli); ! 943: smalli = (short) odesc->relbtree->relfrmt[i]; ! 944: setp(PV_INT, smalli); ! 945: smalli = (short) odesc->relbtree->relfrml[i]; ! 946: setp(PV_INT, smalli); ! 947: smalli = (short) odesc->relbtree->relxtra[i]; ! 948: setp(PV_INT, smalli); ! 949: smalli = (short) odesc->relbtree->relgiven[i]; ! 950: setp(PV_INT, smalli); ! 951: } ! 952: } ! 953: ! 954: call(mdKSORT, NULL); ! 955: ! 956: /* flush buffers used by ksort so that modify can't look at them */ ! 957: flush_rel(desc, TRUE); ! 958: resetacc(NULL); ! 959: ! 960: # ifdef xZTR1 ! 961: if (tTf(36,9)) ! 962: printf("SORTREL: done calling ksort\n"); ! 963: #endif ! 964: return (0); ! 965: } ! 966: /* ! 967: ** SORT_ISAM -- Sorts an isam relation back to its original order ! 968: ** so that it will be inserted into the relation in the proper order. ! 969: ** It is presently not in order because it has been sorted according ! 970: ** to a specified field for ordering. ! 971: */ ! 972: sort_isam(sdesc, desc) ! 973: DESC *sdesc; ! 974: DESC *desc; ! 975: { ! 976: long lid[MAXLID]; ! 977: register int i, j, k; ! 978: char tup_buf[MAXTUP], last_tup[MAXTUP], *dp, *sp; ! 979: FILE *sfp, *fp; ! 980: TID tid, tidpos; ! 981: DESC tempdesc; ! 982: int w; ! 983: ! 984: if (desc->reldum.reldim > 0) ! 985: Btree_fd = desc->btree_fd; ! 986: concat(STEMP, Fileset, Mod_info.temp_sort); ! 987: if ((sfp = fopen(Mod_info.temp_sort, "w")) == NULL) ! 988: syserr("sort_isam: can't open %s", Mod_info.temp_sort); ! 989: if ((fp = fopen(Mod_info.outfile, "r")) == NULL) ! 990: syserr("sort_isam: can't open %s", Mod_info.outfile); ! 991: for (i = 0; i < desc->reldum.reldim; lid[i++] = 0); ! 992: /* create input file for sort with proper lid attached to each tuple */ ! 993: w = sdesc->reldum.relwid - LIDSIZE * sdesc->reldum.reldim; ! 994: for ( ; ; ) ! 995: { ! 996: i = fread(tup_buf, 1, sdesc->reldum.relwid, fp); ! 997: if (i == 0) ! 998: break; ! 999: if (i != sdesc->reldum.relwid) ! 1000: syserr("sort_isam: read error in %s", Mod_info.outfile); ! 1001: for (j = 0; j < desc->reldum.reldim; ++j) ! 1002: if (j < NLidKeys && j < desc->reldum.reldim - 1) ! 1003: { ! 1004: dp = tup_buf + (sdesc->reloff[LidKey[j]] & I1MASK); ! 1005: sp = last_tup + (sdesc->reloff[LidKey[j]] & I1MASK); ! 1006: if (!bequal(dp, sp, sdesc->relfrml[LidKey[j]]) || !lid[j]) ! 1007: { ! 1008: ++lid[j]; ! 1009: for (k = j + 1; k < desc->reldum.reldim; ++k) ! 1010: lid[k] = 0; ! 1011: break; ! 1012: } ! 1013: } ! 1014: else ! 1015: { ! 1016: if (!lid[0]) ! 1017: { ! 1018: lid[0] = 1; ! 1019: if (!(desc->reldum.reldim - 1)) ! 1020: break; ! 1021: } ! 1022: ++lid[desc->reldum.reldim - 1]; ! 1023: break; ! 1024: } ! 1025: bmove(tup_buf, last_tup, sdesc->reldum.relwid); ! 1026: /* reserve a slot in btree for tuple */ ! 1027: insert_mbtree(desc, Mod_info.btree, lid, &tid, &tidpos); ! 1028: bmove(lid, tup_buf + w, LIDSIZE * desc->reldum.reldim); ! 1029: if (fwrite(tup_buf, 1, sdesc->reldum.relwid + LIDSIZE * desc->reldum.reldim, sfp) != sdesc->reldum.relwid + LIDSIZE * desc->reldum.reldim) ! 1030: syserr("sort_isam: write error in %s", Mod_info.temp_sort); ! 1031: } ! 1032: fclose(fp); ! 1033: fclose(sfp); ! 1034: /* set up new descriptor accounting for lid field */ ! 1035: bmove(sdesc, &tempdesc, sizeof *sdesc); ! 1036: tempdesc.reldum.relspec = M_ORDER; ! 1037: for (i = 0; i < desc->reldum.reldim; ++i) ! 1038: { ! 1039: tempdesc.reldum.relwid += LIDSIZE; ! 1040: ++tempdesc.reldum.relatts; ! 1041: tempdesc.reloff[tempdesc.reldum.relatts] = tempdesc.reldum.relwid - LIDSIZE; ! 1042: tempdesc.relfrmt[tempdesc.reldum.relatts] = INT; ! 1043: tempdesc.relfrml[tempdesc.reldum.relatts] = LIDSIZE; ! 1044: } ! 1045: j = 0; ! 1046: /* use old keying attributes for specifying sort order */ ! 1047: clearkeys(&tempdesc); ! 1048: for (i = 1; i <= sdesc->reldum.relatts; ++i) ! 1049: if (sdesc->relxtra[i]) ! 1050: { ! 1051: tempdesc.relgiven[i] = sdesc->relxtra[i]; ! 1052: ++j; ! 1053: } ! 1054: for (i = 1; i <= tempdesc.reldum.relatts; ++i) ! 1055: if (!tempdesc.relgiven[i]) ! 1056: tempdesc.relgiven[i] = ++j; ! 1057: sortfile(Mod_info.temp_sort, &tempdesc, FALSE); ! 1058: if (unlink(Mod_info.outfile) < 0) ! 1059: syserr("can't unlink %s", Mod_info.outfile); ! 1060: if (link(ztack(REPL_OUT, Fileset), Mod_info.outfile) == -1) ! 1061: syserr("can't link %s to %s", ztack(REPL_OUT, Fileset), Mod_info.outfile); ! 1062: if (unlink(Mod_info.temp_sort) < 0) ! 1063: syserr("sort_isam: can't unlink %s", Mod_info.temp_sort); ! 1064: if (unlink(ztack(REPL_OUT, Fileset)) < 0) ! 1065: syserr("sort_isam: can't unlink replout file"); ! 1066: } ! 1067: /* ! 1068: ** FILL_REL -- Fill the new relation with tuples from either ! 1069: ** the old relation or the output file of KSORT. ! 1070: */ ! 1071: ! 1072: fill_rel(sdesc, desc, sortit) ! 1073: register DESC *sdesc, *desc; ! 1074: char sortit; ! 1075: { ! 1076: register int i; ! 1077: char tup_buf[MAXTUP], last_tup[MAXTUP], tup[2 * LIDSIZE]; ! 1078: char junk[4], newreltype, anytups, chkdups; ! 1079: int need, j, k; ! 1080: long lnum, lid[MAXLID], l, page, t; ! 1081: TID tid, stid, stidlim, ntid, tidpos, btid; ! 1082: FILE *fp, *spfp; ! 1083: char *dp, *sp; ! 1084: int w, temp; ! 1085: struct locator tidloc; ! 1086: ! 1087: newreltype = abs(desc->reldum.relspec); ! 1088: if (sortit) ! 1089: { ! 1090: if ((fp = fopen(Mod_info.outfile, "r")) == NULL) ! 1091: syserr("FILL_REL: fopen %.14s", Mod_info.outfile); ! 1092: } ! 1093: else ! 1094: { ! 1095: cleanrel(sdesc); /* make sure each page is read fresh */ ! 1096: find(sdesc, NOKEY, &stid, &stidlim); ! 1097: } ! 1098: if (newreltype == M_ISAM && (NLidKeys > 0 || !desc->reldum.reldim)) ! 1099: { ! 1100: lnum = 0; ! 1101: stuff_page(&tid, &lnum); ! 1102: tid.line_id = 0; ! 1103: get_page(desc, &tid); ! 1104: concat(ISAM_SPOOL, Fileset, Mod_info.spfile); ! 1105: /* assume that spool file is not needed */ ! 1106: spfp = NULL; ! 1107: Mod_info.spflag = FALSE; ! 1108: if (F_fac == 0) ! 1109: F_fac = 100; ! 1110: /* setup relgiven field for kcompare later on */ ! 1111: for (i = 1; i <= desc->reldum.relatts; i++) ! 1112: desc->relgiven[i] = desc->relxtra[i]; ! 1113: if (desc->reldum.reldim) ! 1114: Btree_fd = desc->btree_fd; ! 1115: } ! 1116: desc->reladds = 0; ! 1117: for (i = 0; i < desc->reldum.reldim; lid[i++] = 0) ! 1118: continue; ! 1119: anytups = FALSE; ! 1120: chkdups = !sortit && (newreltype != M_ORDER); ! 1121: # ifdef xZTR2 ! 1122: if (tTf(36, 3)) ! 1123: { ! 1124: printf(" FILLREL: "); ! 1125: printdesc(sdesc); ! 1126: printdesc(desc); ! 1127: } ! 1128: # endif ! 1129: for (;;) ! 1130: { ! 1131: w = (newreltype == M_ISAM) ? sdesc->reldum.relwid + desc->reldum.reldim * LIDSIZE : sdesc->reldum.relwid; ! 1132: if (sortit) ! 1133: { ! 1134: i = fread(tup_buf, 1, w, fp); ! 1135: if (i == 0) ! 1136: break; ! 1137: if (i != w) ! 1138: syserr("FILL_REL: fread A %d", i); ! 1139: if (newreltype == M_HASH && !desc->reldum.reldim) ! 1140: if (fread(junk, 1, 4, fp) != 4) ! 1141: syserr("FILL_REL: fread B"); ! 1142: } ! 1143: else ! 1144: { ! 1145: # ifdef xZTR2 ! 1146: if (tTf(36, 1)) ! 1147: { ! 1148: printf("FILL_REL: stid "); ! 1149: dumptid(&stid); ! 1150: printf("FILL_REL: stidlim "); ! 1151: dumptid(&stidlim); ! 1152: } ! 1153: # endif ! 1154: i = get(sdesc, &stid, &stidlim, tup_buf, TRUE); ! 1155: # ifdef xZTR2 ! 1156: if (tTf(36, 1)) ! 1157: { ! 1158: printf("FILLREL: get %d ", i); ! 1159: printup(sdesc, tup_buf); ! 1160: } ! 1161: # endif ! 1162: if (i < 0) ! 1163: syserr("FILL_REL: get %d", i); ! 1164: if (i == 1) ! 1165: break; ! 1166: } ! 1167: if (newreltype != M_ISAM || (newreltype == M_ISAM && NLidKeys == 0 && desc->reldum.reldim > 0)) ! 1168: { ! 1169: for (j = 0; j < desc->reldum.reldim; ++j) ! 1170: if (j < NLidKeys && j < desc->reldum.reldim - 1) ! 1171: { ! 1172: dp = tup_buf + (sdesc->reloff[LidKey[j]] & I1MASK); ! 1173: sp = last_tup + (sdesc->reloff[LidKey[j]] & I1MASK); ! 1174: if (!bequal(dp, sp, sdesc->relfrml[LidKey[j]]) || !lid[j]) ! 1175: { ! 1176: ++lid[j]; ! 1177: for (k = j + 1; k < desc->reldum.reldim; ++k) ! 1178: lid[k] = 0; ! 1179: break; ! 1180: } ! 1181: } ! 1182: else ! 1183: { ! 1184: if (!lid[0]) ! 1185: { ! 1186: lid[0] = 1; ! 1187: if (!(desc->reldum.reldim -1)) ! 1188: break; ! 1189: } ! 1190: ++lid[desc->reldum.reldim - 1]; ! 1191: break; ! 1192: } ! 1193: Btree_fd = desc->btree_fd; ! 1194: if (!desc->reldum.reldim || NLidKeys > 0) ! 1195: { ! 1196: /* assume unordered so btree inserts done ! 1197: ** separately */ ! 1198: temp = 0; ! 1199: if (desc->reldum.reldim > 0) ! 1200: { ! 1201: temp = desc->reldum.reldim; ! 1202: desc->reldum.reldim = 0; ! 1203: desc->reldum.relwid -= temp * LIDSIZE; ! 1204: } ! 1205: if ((i = insert(desc, &tid, tup_buf, chkdups)) < 0) ! 1206: syserr("FILL_REL: insert %d", i); ! 1207: if (NLidKeys > 0) ! 1208: { ! 1209: bmove(&tid, &stid, LIDSIZE); ! 1210: desc->reldum.reldim = temp; ! 1211: desc->reldum.relwid += temp * LIDSIZE; ! 1212: insert_mbtree(desc, Mod_info.btree, lid, &tid, &tidpos); ! 1213: } ! 1214: } ! 1215: if (desc->reldum.reldim && !NLidKeys) ! 1216: { ! 1217: /* new relation not changed, only lids added */ ! 1218: page = RT; ! 1219: for (j = 0; j < desc->reldum.reldim - 1; ++j) ! 1220: { ! 1221: if (!lid[j]) ! 1222: lid[j] = 1; ! 1223: if ((t = get_tid(page, lid[j], &tidloc)) < 0) ! 1224: { ! 1225: insert_btree(Mod_info.btree, page, lid[j], &ntid, &tidpos, j + 2); ! 1226: bmove(&ntid, &page, LIDSIZE); ! 1227: } ! 1228: else ! 1229: bmove(&t, &page, LIDSIZE); ! 1230: } ! 1231: insert_btree(Mod_info.btree, page, lid[abs(desc->reldum.reldim) - 1], &stid, &tidpos, FALSE); ! 1232: } ! 1233: bmove(tup_buf, last_tup, sdesc->reldum.relwid); ! 1234: if (desc->reldum.reldim > 0) ! 1235: { ! 1236: dp = tup_buf + desc->reldum.relwid - desc->reldum.reldim * LIDSIZE; ! 1237: bmove(lid, dp, LIDSIZE * desc->reldum.reldim); ! 1238: } ! 1239: # ifdef xZTR2 ! 1240: if (tTf(36, 2)) ! 1241: { ! 1242: printf("FILL_REL: insert "); ! 1243: printup(desc, tup_buf); ! 1244: printf("FILL_REL: insert ret %d at", i); ! 1245: dumptid(&tid); ! 1246: } ! 1247: # endif ! 1248: continue; ! 1249: } ! 1250: if (anytups) ! 1251: i = kcompare(desc, tup_buf, last_tup); ! 1252: else ! 1253: { ! 1254: anytups = TRUE; ! 1255: i = 1; ! 1256: } ! 1257: bmove(tup_buf, last_tup, desc->reldum.relwid); ! 1258: need = canonical(desc, tup_buf); ! 1259: if (i == 0 && need > space_left(Acc_head)) ! 1260: { ! 1261: /* spool out this tuple. will go on overflow page later */ ! 1262: if (spfp == NULL) ! 1263: { ! 1264: if ((spfp = fopen(Mod_info.spfile, "w")) == NULL) ! 1265: syserr("FILL_REL: fopen %.14s", Mod_info.spfile); ! 1266: Mod_info.spflag = TRUE; ! 1267: } ! 1268: if (fwrite(tup_buf, 1, desc->reldum.relwid, spfp) != desc->reldum.relwid) ! 1269: syserr("FILL_REL: putb spool"); ! 1270: continue; ! 1271: } ! 1272: j = (100 - F_fac) * MAXTUP / 100; ! 1273: if (j < need) ! 1274: j = need; ! 1275: if (i != 0 && j > space_left(Acc_head)) ! 1276: { ! 1277: if (i = add_prim(desc, &tid)) ! 1278: syserr("FILL_REL: force ovflo %d", i); ! 1279: } ! 1280: tid.line_id = newlino(need); ! 1281: put_tuple(&tid, Acctuple, need); ! 1282: if (NLidKeys > 0) ! 1283: { ! 1284: bmove(tup_buf + desc->reldum.relwid - LIDSIZE * desc->reldum.reldim, lid, LIDSIZE * desc->reldum.reldim); ! 1285: page = RT; ! 1286: for (j = 0; j < desc->reldum.reldim; ++j) ! 1287: { ! 1288: if ((t = get_tid(page, lid[j], &tidloc)) < 0) ! 1289: syserr("get_tid error in modify isam ordered"); ! 1290: page = t; ! 1291: } ! 1292: stuff_page(&btid, &tidloc.pageno); ! 1293: btid.line_id = tidloc.page.node.leafnode.tid_loc[tidloc.offset]; ! 1294: /* place proper tid in tree */ ! 1295: replace_btree(tid, &btid); ! 1296: } ! 1297: desc->reladds++; ! 1298: } ! 1299: if (sortit) ! 1300: { ! 1301: fclose(fp); ! 1302: unlink(Mod_info.outfile); ! 1303: } ! 1304: if (newreltype == M_ISAM && desc->reldum.reldim <= 0) ! 1305: { ! 1306: if (i = pageflush(Acc_head)) ! 1307: syserr("fill_rel:pg clean %d", i); ! 1308: if (spfp != NULL) ! 1309: fclose(spfp); ! 1310: } ! 1311: if (!desc->reldum.reldim || NLidKeys > 0) ! 1312: desc->reldum.reltups = desc->reladds; ! 1313: desc->reladds = 0; ! 1314: return (0); ! 1315: } ! 1316: ! 1317: ! 1318: /* ! 1319: ** BLDINDEX - ! 1320: ** ! 1321: ** Parameters: ! 1322: ** d - descriptor for relation ! 1323: ** ! 1324: ** Return Codes: ! 1325: ** 0 - ok ! 1326: ** <0 - error ! 1327: ** ! 1328: ** Trace Flags: ! 1329: ** Z38.7, Z38.8 ! 1330: ** ! 1331: ** Called by: ! 1332: ** modify ! 1333: ** ! 1334: */ ! 1335: bldindex(d) ! 1336: register DESC *d; ! 1337: { ! 1338: register TID *tid; ! 1339: register int tmp; ! 1340: TID tidx; ! 1341: struct accbuf dirbuf; ! 1342: int keywid, level, savespec, keyx[MAXDOM]; ! 1343: int offset, len; ! 1344: char tuple[MAXTUP], temptup[MAXTUP], *key; ! 1345: long pageid, start, stop, newstart, newstop; ! 1346: ! 1347: tid = &tidx; ! 1348: keywid = 0; ! 1349: for (tmp = 0; tmp < MAXDOM; tmp++) ! 1350: keyx[tmp] = 0; ! 1351: for (tmp = 1; tmp <= d->reldum.relatts; tmp++) ! 1352: if (d->relxtra[tmp] > 0) ! 1353: { ! 1354: keyx[d->relxtra[tmp] - 1] = tmp; ! 1355: keywid += d->relfrml[tmp] & I1MASK; ! 1356: } ! 1357: ! 1358: /* Determine the last page of the relation. This will ! 1359: ** only work if all pages have been written out. Fill_rel ! 1360: ** must guarantee that all pages have been written ! 1361: */ ! 1362: level = 0; ! 1363: last_page(d, tid, 0); ! 1364: pluck_page(tid, &stop); ! 1365: start = 0; ! 1366: dirbuf.filedesc = d->relfp; ! 1367: dirbuf.rel_tupid = d->reltid.ltid; ! 1368: savespec = d->reldum.relspec; ! 1369: for (;;) ! 1370: { ! 1371: # ifdef xZTR2 ! 1372: if (tTf(38, 7)) ! 1373: printf("isam: level %d\n", level); ! 1374: # endif ! 1375: dirbuf.ovflopg = start; ! 1376: dirbuf.mainpg = level; ! 1377: dirbuf.thispage = stop + 1; ! 1378: dirbuf.linetab[0] = (short) (dirbuf.firstup - (char *) &dirbuf); ! 1379: offset = dirbuf.linetab[0]; ! 1380: dirbuf.bufstatus = BUF_DIRTY | BUF_DIRECT; ! 1381: ! 1382: dirbuf.nxtlino = 0; ! 1383: newstart = stop + 1; ! 1384: newstop = newstart; ! 1385: for (pageid = start; pageid <= stop; pageid++) ! 1386: { ! 1387: # ifdef xZTR2 ! 1388: if (tTf(38, 8)) ! 1389: printf("isam:get key from %ld\n", pageid); ! 1390: # endif ! 1391: stuff_page(tid, &pageid); ! 1392: tid->line_id = 0; ! 1393: if (tmp = get(d, tid, tid, tuple, FALSE)) ! 1394: { ! 1395: /* ! 1396: ** If the relation is empty, then page 0 will ! 1397: ** return AMINVL_ERR on a get(). Form a blank tuple ! 1398: ** and use it to create a one tuple directory ! 1399: */ ! 1400: if (pageid == 0 && tmp == AMINVL_ERR) ! 1401: { ! 1402: clr_tuple(d, tuple); ! 1403: } ! 1404: else ! 1405: { ! 1406: return (-2); ! 1407: } ! 1408: } ! 1409: ! 1410: /* ! 1411: ** If this is the first level then form the tuple ! 1412: ** from the mainpage of the relation. Otherwise ! 1413: ** the tuple is the first tuple of a directory page ! 1414: ** and it is already correctly formed. ! 1415: */ ! 1416: if (level == 0) ! 1417: { ! 1418: key = temptup; ! 1419: for (tmp = 0; keyx[tmp] != 0; tmp++) ! 1420: { ! 1421: len = d->relfrml[keyx[tmp]] & I1MASK; ! 1422: bmove(&tuple[d->reloff[keyx[tmp]]], key, len); ! 1423: key += len; ! 1424: } ! 1425: key = temptup; ! 1426: } ! 1427: else ! 1428: key = tuple; ! 1429: ! 1430: if (keywid > space_left(&dirbuf)) ! 1431: { ! 1432: if (pageflush(&dirbuf)) ! 1433: return (-3); ! 1434: dirbuf.thispage++; ! 1435: newstop = dirbuf.thispage; ! 1436: dirbuf.ovflopg = pageid; ! 1437: dirbuf.linetab[0] = (short) (dirbuf.firstup - (char *) &dirbuf); ! 1438: offset = dirbuf.linetab[0]; ! 1439: dirbuf.bufstatus = BUF_DIRTY; ! 1440: dirbuf.nxtlino = 0; ! 1441: } ! 1442: /* copy key to directory page */ ! 1443: bmove(key, (char *) &dirbuf + offset, keywid); ! 1444: ! 1445: /* update next line number */ ! 1446: offset += keywid; ! 1447: dirbuf.nxtlino++; ! 1448: dirbuf.linetab[-dirbuf.nxtlino] = offset; ! 1449: } ! 1450: if (pageflush(&dirbuf)) ! 1451: return (-4); ! 1452: if (newstart == newstop) ! 1453: break; ! 1454: d->reldum.relspec = abs(d->reldum.relspec); ! 1455: level++; ! 1456: start = newstart; ! 1457: stop = newstop; ! 1458: } ! 1459: d->reldum.relspec = savespec; ! 1460: d->reldum.relprim = newstart; ! 1461: return (0); ! 1462: } ! 1463: /* ! 1464: ** UNSPOOL -- Take tuples saved in spool file and insert them ! 1465: ** in new relation. This is only for ISAM relations. ! 1466: */ ! 1467: ! 1468: unspool(sdesc, desc) ! 1469: register DESC *sdesc, *desc; ! 1470: { ! 1471: register int i, j; ! 1472: TID tid, btid; ! 1473: char tup_buf[MAXTUP], tup[2 * LIDSIZE]; ! 1474: FILE *spfp; ! 1475: long lid[MAXLID], page, t; ! 1476: int w; ! 1477: struct locator tidpos; ! 1478: ! 1479: w = sdesc->reldum.relwid + desc->reldum.reldim * LIDSIZE; ! 1480: if (Mod_info.spflag) ! 1481: { ! 1482: if ((spfp = fopen(Mod_info.spfile, "r")) == NULL) ! 1483: syserr("UNSPOOL: fopen spool"); ! 1484: while ((i = fread(tup_buf, 1, w, spfp)) == w) ! 1485: { ! 1486: if ((i = insert(desc, &tid, tup_buf, FALSE)) < 0) ! 1487: syserr("UNSPOOL: insert %.14s %d", desc->reldum.relid, i); ! 1488: if (NLidKeys > 0) ! 1489: { ! 1490: bmove(tup_buf + desc->reldum.relwid - LIDSIZE * desc->reldum.reldim, lid, LIDSIZE * desc->reldum.reldim); ! 1491: page = RT; ! 1492: for (j = 0; j < desc->reldum.reldim; ++j) ! 1493: { ! 1494: if ((t = get_tid(page, lid[j], &tidpos)) < 0) ! 1495: syserr("get_tid error in unspool"); ! 1496: page = t; ! 1497: } ! 1498: stuff_page(&btid, &tidpos.pageno); ! 1499: btid.line_id = tidpos.page.node.leafnode.tid_loc[tidpos.offset]; ! 1500: replace_btree(tid, &btid); ! 1501: } ! 1502: } ! 1503: if (i != 0) ! 1504: syserr("UNSPOOL: read %d", i); ! 1505: fclose(spfp); ! 1506: unlink(Mod_info.spfile); ! 1507: } ! 1508: desc->reldum.reltups += desc->reladds; ! 1509: desc->reladds = 0; ! 1510: return (0); ! 1511: } ! 1512: /* ! 1513: ** FILL_BATCH -- Create and fill a batch file containing the ! 1514: ** updates for the system catalog so that MODIFY will ! 1515: ** be recoverable if the system crashes. ! 1516: */ ! 1517: ! 1518: fill_batch(odesc, desc) ! 1519: DESC *odesc; ! 1520: register DESC *desc; ! 1521: { ! 1522: register DESC *dessys; ! 1523: register int i, k; ! 1524: struct relation reltup, rkey; ! 1525: TID tid, lotid, hitid; ! 1526: struct attribute atttup, akey; ! 1527: int numatts, j; ! 1528: char prebatch[MAXNAME + 4], modbatch[MAXNAME + 4]; ! 1529: ! 1530: if (bequal(desc->reldum.relid, "relation ", 12)) ! 1531: { ! 1532: clearkeys(desc); ! 1533: setkey(desc, &rkey, desc->reldum.relid, RELID); ! 1534: setkey(desc, &rkey, desc->reldum.relowner, RELOWNER); ! 1535: if (i = getequal(desc, &rkey, &reltup, &tid)) ! 1536: syserr("FILL_BATCH: geteq rel rel %d", i); ! 1537: bmove(&tid, &desc->reltid, sizeof desc->reltid); ! 1538: } ! 1539: else ! 1540: bmove(&odesc->reltid, &desc->reltid, sizeof desc->reltid); ! 1541: resetacc(Acc_head); ! 1542: concat(MOD_PREBATCH, Fileset, prebatch); ! 1543: close(creat(prebatch, FILEMODE)); ! 1544: if ((Batch_fp = open(prebatch, O_RDWR)) < 0) ! 1545: syserr("FILL_BATCH: open %.14s %d", prebatch, Batch_fp); ! 1546: smove(Fileset, Batchbuf.file_id); ! 1547: Batch_cnt = 0; ! 1548: wrbatch(desc, sizeof *desc); ! 1549: if (bequal(desc->reldum.relid, "attribute ", 12)) ! 1550: dessys = desc; ! 1551: else ! 1552: dessys = &Admin.adattd; ! 1553: clearkeys(dessys); ! 1554: setkey(dessys, &akey, desc->reldum.relid, ATTRELID); ! 1555: setkey(dessys, &akey, desc->reldum.relowner, ATTOWNER); ! 1556: if (i = find(dessys, EXACTKEY, &lotid, &hitid, &akey)) ! 1557: syserr("FILL_BATCH: find %d", i); ! 1558: ! 1559: /* if ordered relation, one of attributes is LID field */ ! 1560: numatts = j = desc->reldum.relatts - desc->reldum.reldim; ! 1561: ! 1562: while(!(i = get(dessys, &lotid, &hitid, &atttup, TRUE)) && j > 0) ! 1563: if (!kcompare(dessys, &akey, &atttup)) ! 1564: if (atttup.attid <= numatts) ! 1565: { ! 1566: j--; ! 1567: atttup.attxtra = desc->relxtra[atttup.attid]; ! 1568: wrbatch(&lotid, sizeof lotid); ! 1569: wrbatch(&atttup, sizeof atttup); ! 1570: } ! 1571: for (k = 1; k <= desc->reldum.reldim; ++k) ! 1572: /* create new tuple corresponding to LID field; LID field is the ! 1573: ** last field of relation, a 4-byte integer ! 1574: */ ! 1575: { ! 1576: smove(desc->reldum.relid, atttup.attrelid); ! 1577: bmove(desc->reldum.relowner, atttup.attowner, 2); ! 1578: atttup.attid = numatts + k; ! 1579: smove(Lid[k - 1], atttup.attname); ! 1580: pad(atttup.attname, MAXNAME); ! 1581: atttup.attoff = desc->reldum.relwid - (desc->reldum.reldim - k + 1) * LIDSIZE; ! 1582: atttup.attfrmt = INT; ! 1583: atttup.attfrml = LIDSIZE; ! 1584: atttup.attxtra = 0; ! 1585: wrbatch(&atttup, sizeof atttup); ! 1586: } ! 1587: if (i < 0 || j > 0) ! 1588: syserr("FILL_BATCH: get att %d count %d", i, j); ! 1589: /* get rid of attribute pages */ ! 1590: cleanrel(dessys); ! 1591: flushbatch(); ! 1592: close(Batch_fp); ! 1593: concat(MODBATCH, Fileset, modbatch); ! 1594: if (link(prebatch, modbatch) == -1) ! 1595: syserr("FILL_BATCH: can't link %.14s %.14s", ! 1596: prebatch, modbatch); ! 1597: unlink(prebatch); ! 1598: return (0); ! 1599: ! 1600: } ! 1601: ! 1602: /* ! 1603: ** MAKE_BSEC -- Creates the seecondary btree relation by first creating ! 1604: ** a heaped relation. The main relation tids are found by ! 1605: ** scanning the leaves of the btree. The relation is then ! 1606: ** modified to an isam relation. ! 1607: */ ! 1608: ! 1609: make_bsec(relname, dim) ! 1610: char *relname; ! 1611: int dim; ! 1612: { ! 1613: PARM pv[8]; ! 1614: register int i; ! 1615: DESC bdesc; ! 1616: TID tid, btid; ! 1617: long mtid, page, t, next; ! 1618: char tuple[2 * LIDSIZE], btree[MAXNAME], btreefile[MAXNAME + 4]; ! 1619: struct locator tidpos; ! 1620: extern char *iocv(); ! 1621: extern DESC Reldes; ! 1622: ! 1623: pv[0].pv_val.pv_str = "0000002"; ! 1624: capital(trim_relname(relname), btree); ! 1625: pv[1].pv_val.pv_str = btree; ! 1626: pv[2].pv_val.pv_str = "mtid"; ! 1627: pv[3].pv_val.pv_str = "i4"; ! 1628: pv[4].pv_val.pv_str = "btid"; ! 1629: pv[5].pv_val.pv_str = "i4"; ! 1630: pv[6].pv_type = PV_EOF; ! 1631: if (create(6, pv)) ! 1632: syserr("can't create btreesec %s", pv[1].pv_val.pv_str); ! 1633: ! 1634: if (noclose(&Reldes)) ! 1635: syserr("noclose in make_bsec"); ! 1636: ! 1637: if (i = openr(&bdesc, OR_WRITE, btree)) ! 1638: syserr("opening bsec relation %d", i); ! 1639: btreename(relname, btreefile); ! 1640: if ((Btree_fd = open(btreefile, O_RDWR)) < 0) ! 1641: syserr("make_bsec: can't open %s", btreefile); ! 1642: page = RT; ! 1643: for (i = 0; i < dim - 1; ++i) ! 1644: { ! 1645: t = get_tid(page, 1, &tidpos); ! 1646: if (t < 0) ! 1647: break; /* lid value doesn't exist */ ! 1648: bmove(&t, &page, LIDSIZE); ! 1649: } ! 1650: if (t >= 0) /* only do inserts if there are lids! */ ! 1651: { ! 1652: do ! 1653: { ! 1654: get_node(page, &tidpos.page); ! 1655: next = tidpos.page.nexttree; ! 1656: get_tid(page, 1, &tidpos); ! 1657: page = tidpos.pageno; ! 1658: for (;;) ! 1659: /* scan through leaves of btree */ ! 1660: { ! 1661: stuff_page(&btid, &page); ! 1662: for (i = 0; i < tidpos.page.nelmts; ++i) ! 1663: { ! 1664: btid.line_id = tidpos.page.node.leafnode.tid_loc[i]; ! 1665: mtid = tidpos.page.node.leafnode.tid_pos[btid.line_id]; ! 1666: /* form tuple */ ! 1667: bmove(&mtid, tuple, LIDSIZE); ! 1668: bmove(&btid, tuple + LIDSIZE, LIDSIZE); ! 1669: if (insert(&bdesc, &tid, tuple, TRUE) < 0) ! 1670: syserr("insert error in btreesec"); ! 1671: } ! 1672: page = tidpos.page.node.leafnode.nextleaf; ! 1673: if (page == NULL) ! 1674: break; ! 1675: else ! 1676: get_node(page, &tidpos.page); ! 1677: } ! 1678: } while (page = next); ! 1679: } ! 1680: close(Btree_fd); ! 1681: closer(&bdesc); ! 1682: ! 1683: /* modify to isam on mtid */ ! 1684: pv[0].pv_val.pv_str = btree; ! 1685: pv[1].pv_val.pv_str = "isam"; ! 1686: pv[2].pv_val.pv_str = "name"; ! 1687: pv[3].pv_val.pv_str = "mtid"; ! 1688: pv[4].pv_val.pv_str = "\0"; ! 1689: pv[5].pv_val.pv_str = "fillfactor"; ! 1690: /* use fillfactor provided for main relation */ ! 1691: if (F_fac == 0) ! 1692: pv[6].pv_val.pv_str = iocv(80); ! 1693: else ! 1694: pv[6].pv_val.pv_str = iocv(F_fac); ! 1695: pv[7].pv_type = PV_EOF; ! 1696: if (modify(7, pv)) ! 1697: syserr("can't modify btreesec to isam"); ! 1698: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.