|
|
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.