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: }