|
|
1.1 root 1: # include <pv.h>
2: # include <ingres.h>
3: # include <access.h>
4: # include <aux.h>
5: # include <catalog.h>
6: # include <symbol.h>
7: # include <lock.h>
8: # include <func.h>
9: # include <sccs.h>
10:
11: SCCSID(@(#)create.c 7.2 5/31/83)
12:
13: extern short tTdbu[];
14: extern int create();
15: extern int null_fn();
16:
17: struct fn_def CreateFn =
18: {
19: "CREATE",
20: create,
21: null_fn,
22: null_fn,
23: NULL,
24: 0,
25: tTdbu,
26: 100,
27: 'Z',
28: 0
29: };
30:
31: /*
32: ** CREATE -- create new relation
33: **
34: ** This module creates a brand new relation in the current
35: ** directory (database). The relation is always created as
36: ** a paged heap. It may not redefine an existing relation,
37: ** or rename a system catalog.
38: **
39: ** Trace Flags:
40: ** 31
41: */
42:
43:
44: struct domain
45: {
46: char *name;
47: char frmt;
48: char frml;
49: };
50:
51: /*
52: ** CREATE -- create new relation
53: **
54: ** This routine is the driver for the create module.
55: **
56: ** Parameters:
57: ** pc -- parameter count
58: ** pv -- parameter vector:
59: ** 0 -- relation status (relstat) -- stored into
60: ** the 'relstat' field in the relation
61: ** relation, and used to determine the
62: ** caller. Interesting bits are:
63: **
64: ** S_INDEX -- means called by the index
65: ** processor. If set, the 'relindxd'
66: ** field will also be set to -1
67: ** (SECINDEX) to indicate that this
68: ** relation is a secondary index.
69: ** S_CATALOG -- this is a system catalog.
70: ** If set, this create was called
71: ** from creatdb, and the physical
72: ** file is not created. Also, the
73: ** expiration date is set infinite.
74: ** S_VIEW -- this is a view. Create has
75: ** been called by the 'define'
76: ** statement, rather than the
77: ** 'create' statement. The physical
78: ** file is not created.
79: **
80: ** 1 -- relation name.
81: ** 2 -- attname1
82: ** 3 -- format1
83: ** 4, etc -- attname, format pairs.
84: **
85: ** Returns:
86: ** zero -- successful create.
87: ** else -- failure somewhere.
88: **
89: ** Side Effects:
90: ** A relation is created (this is a side effect?). This
91: ** means entries in the 'relation' and 'attribute' cata-
92: ** logs, and (probably) a physical file somewhere, with
93: ** one page already in it.
94: **
95: ** Trace Flags:
96: ** 31
97: */
98:
99: create(pc, pv)
100: int pc;
101: PARM pv[];
102: {
103: register PARM *pp;
104: register int i;
105: int bad;
106: struct domain domain[MAXDOM];
107: struct domain *dom;
108: char *relname, tempname[MAXNAME+3];
109: struct tup_id tid;
110: struct relation rel, key;
111: struct attribute att;
112: DESC desr;
113: extern char *Usercode;
114: extern DESC Reldes, Attdes;
115: extern int errno;
116: register int relstat;
117: long temptid;
118: long npages;
119: int fdes;
120: bool internal;
121:
122: # ifdef xZTR1
123: if (tTf(31, -1))
124: {
125: printf("creating %s\n", pv[1].pv_val.pv_str);
126: }
127: # endif
128: pp = pv;
129: relstat = oatoi(pp[0].pv_val.pv_str);
130: /*
131: ** If this database has query modification, then default
132: ** to denial on all user relations.
133: ** (Since views cannot be protected, this doesn't apply to them)
134: */
135: if ((Admin.adhdr.adflags & A_QRYMOD) && ((relstat & (S_VIEW || S_CATALOG)) == 0))
136: relstat |= (S_PROTALL | S_PROTRET);
137: relname = (++pp)->pv_val.pv_str;
138: internal = bequal(relname, "_SYS", 4);
139: ingresname(relname, Usercode, rel.relid);
140: bmove(rel.relid, att.attrelid, MAXNAME + 2);
141: opencatalog("relation", 2);
142:
143: /* check for duplicate relation name */
144: if ((relstat & S_CATALOG) == 0)
145: {
146: if (openr(&desr, -1, relname) == 0)
147: {
148: if (bequal(desr.reldum.relowner, rel.relowner, 2))
149: {
150: return (error(5102, relname, 0)); /* bad relname */
151: }
152: if (desr.reldum.relstat & S_CATALOG)
153: {
154: return (error(5103, relname, 0)); /* attempt to rename system catalog */
155: }
156: }
157: }
158: opencatalog("attribute", 2);
159:
160: /* initialize structures for system catalogs */
161: initstructs(&att, &rel);
162: rel.relstat = relstat;
163: if ((relstat & S_CATALOG) != 0)
164: rel.relsave = 0;
165: else if ((relstat & S_INDEX) != 0)
166: rel.relindxd = SECINDEX;
167:
168: # ifdef xZTR3
169: if (tTf(31, 2))
170: {
171: printf("\nrel->relprim = %D\n", rel.relprim);
172: printup(&Reldes, &rel);
173: }
174: # endif
175:
176: /* check attributes */
177: pp++;
178: for (i = pc - 2; i > 0; i -= 2)
179: {
180: bad = chk_att(&rel, pp[0].pv_val.pv_str, pp[1].pv_val.pv_str, domain, internal);
181: if (bad != 0)
182: {
183: return (error(bad, relname, pp[0].pv_val.pv_str, pp[1].pv_val.pv_str, 0));
184: }
185: pp += 2;
186: }
187:
188: /*
189: ** Create files if appropriate. Concurrency control for
190: ** the create depends on the actual file. To prevent
191: ** to users with the same usercode from creating the
192: ** same relation at the same time, their is check
193: ** on the existence of the file. The important events are
194: ** (1) if a tuple exists in the relation relation then
195: ** the relation really exists. (2) if the file exists then
196: ** the relation is being created but will not exist for
197: ** use until the relation relation tuple is present.
198: ** For VIEWS, the file is used for concurrency control
199: ** during the create but is removed afterwards.
200: */
201: if ((relstat & S_CATALOG) == 0)
202: {
203: /* for non system named temporary relations
204: ** set a critical section lock while checking the
205: ** existence of a file. If it exists, error return(5102)
206: ** else create file.
207: */
208: temptid = 0;
209: if (Lockrel && (!bequal(rel.relid,"_SYS",4)))
210: {
211: temptid = -1;
212: setcsl(temptid); /* set critical section lock */
213: if ((fdes = open(rel.relid,0)) >= 0)
214: {
215: /* file already exists */
216: close(fdes);
217: unlcs(temptid); /* release critical section lock */
218: return (error(5102, relname, 0));
219: }
220: errno = 0; /* file doesn't exist */
221: }
222: ingresname(rel.relid, rel.relowner, tempname);
223: desr.relfp = creat(tempname, FILEMODE);
224: if (temptid != 0)
225: unlcs(temptid); /* release critical section lock */
226: if (desr.relfp < 0)
227: syserr("create: creat %s", rel.relid);
228: desr.reltid.ltid = -1L; /* init reltid to unused */
229: if ((relstat & S_VIEW) == 0)
230: {
231: npages = 1;
232: if (i = formatpg(&desr, npages))
233: syserr("create: formatpg %d", i);
234: }
235:
236: close(desr.relfp);
237: }
238:
239: /* insert attributes into attribute relation */
240: pp = pv + 2;
241: dom = domain;
242: for (i = pc - 2; i > 0; i -= 2)
243: {
244: ins_att(&Attdes, &att, dom++);
245: pp += 2;
246: }
247:
248: /*
249: ** Flush the attributes. This is necessary for recovery reasons.
250: ** If for some reason the relation relation is flushed and the
251: ** machine crashes before the attributes are flushed, then recovery
252: ** will not detect the error.
253: ** The call below cannot be a "noclose" without major changes to
254: ** creatdb.
255: */
256: if (i = pageflush(0))
257: syserr("create:flush att %d", i);
258:
259: if (i = insert(&Reldes, &tid, &rel, FALSE))
260: syserr("create: insert(rel, %.14s) %d", rel.relid, i);
261:
262: if (relstat & S_VIEW)
263: unlink(tempname);
264: return (0);
265: }
266:
267:
268:
269: /*
270: ** CHK_ATT -- check attribute for validity
271: **
272: ** The attribute is checked to see if
273: ** * it's name is ok (within MAXNAME bytes)
274: ** * it is not a duplicate name
275: ** * the format specified is legal
276: ** * there are not a ridiculous number of attributes
277: ** (ridiculous being defined as anything over MAXDOM - 1)
278: ** * the tuple is not too wide to fit on one page
279: **
280: ** Parameters:
281: ** rel -- relation relation tuple for this relation.
282: ** attname -- tentative name of attribute.
283: ** format -- tentative format for attribute.
284: ** domain -- a 'struct domain' used to determine dupli-
285: ** cation, and to store the resulting name and
286: ** format in.
287: **
288: ** Returns:
289: ** zero -- OK
290: ** 5104 -- bad attribute name.
291: ** 5105 -- duplicate attribute name.
292: ** 5106 -- bad attribute format.
293: ** 5107 -- too many attributes.
294: ** 5108 -- tuple too wide.
295: **
296: ** Side Effects:
297: ** 'rel' has the relatts and relwid fields updated to
298: ** reflect the new attribute.
299: **
300: ** Trace Flags:
301: ** 31
302: */
303:
304: chk_att(rel, attname, format, domain, internal)
305: struct relation *rel;
306: char *attname, *format;
307: struct domain domain[];
308: bool internal;
309: {
310: register int i;
311: register struct relation *r;
312:
313: r = rel;
314:
315: # ifdef xZTR3
316: if (tTf(31, 1))
317: printf("chk_att %s %s\n", attname, format);
318: # endif
319:
320: if (sequal(attname, "tid"))
321: return (5104); /* bad attribute name */
322: if ((i = dup_att(attname, r->relatts, domain)) < 0)
323: return (5105); /* duplicate attribute */
324: if (formck(format, &domain[i], internal))
325: return (5106); /* bad attribute format */
326: r->relatts++;
327: r->relwid += domain[i].frml & 0377;
328: if (r->relatts >= MAXDOM)
329: return (5107); /* too many attributes */
330: if (r->relwid > MAXTUP && (r->relstat & S_VIEW) == 0)
331: return (5108); /* tuple too wide */
332: return (0);
333: }
334:
335:
336:
337:
338: /*
339: ** INS_ATT -- insert attribute into attribute relation
340: **
341: ** Parameters:
342: ** des -- relation descriptor for the attribute catalog.
343: ** att -- attribute tuple, preinitialized with all sorts
344: ** of good stuff (everything except 'attname',
345: ** 'attfrmt', and 'attfrml'; 'attid' and 'attoff'
346: ** must be initialized to zero before this routine
347: ** is called the first time.
348: ** dom -- 'struct domain' -- the information needed about
349: ** each domain.
350: **
351: ** Returns:
352: ** none
353: **
354: ** Side Effects:
355: ** The 'att' tuple is updated in the obvious ways.
356: ** A tuple is added to the 'attribute' catalog.
357: **
358: ** Trace Flags:
359: ** none currently
360: */
361:
362: ins_att(des, att, dom)
363: DESC *des;
364: struct attribute *att;
365: struct domain *dom;
366: {
367: register int i;
368: struct tup_id tid;
369: register struct domain *d;
370:
371: d = dom;
372:
373: pmove(d->name, att->attname, MAXNAME, ' ');
374: att->attfrmt = d->frmt;
375: att->attfrml = d->frml;
376: att->attid++;
377: if (insert(des, &tid, att, FALSE))
378: syserr("ins_att: insert(att, %s)", d->name);
379: att->attoff += att->attfrml & 0377;
380: }
381:
382:
383:
384:
385: /*
386: ** DUP_ATT -- check for duplicate attribute
387: **
388: ** The attribute named 'name' is inserted into the 'attalias'
389: ** vector at position 'count'. 'Count' should be the count
390: ** of existing entries in 'attalias'. 'Attalias' is checked
391: ** to see that 'name' is not already present.
392: **
393: ** Parameters:
394: ** name -- the name of the attribute.
395: ** count -- the count of attributes so far.
396: ** domain -- 'struct domain' -- the list of domains
397: ** so far, names and types.
398: **
399: ** Returns:
400: ** -1 -- attribute name is a duplicate.
401: ** else -- index in 'domain' for this attribute (also
402: ** the attid).
403: **
404: ** Side Effects:
405: ** The 'domain' vector is extended.
406: **
407: ** Trace Flags:
408: ** none
409: */
410:
411: dup_att(name, count, domain)
412: char *name;
413: int count;
414: struct domain domain[];
415: {
416: register struct domain *d;
417: register int lim;
418: register int i;
419:
420: lim = count;
421: d = domain;
422:
423: for (i = 0; i < lim; i++)
424: if (sequal(name, d++->name))
425: return (-1);
426: if (count < MAXDOM)
427: d->name = name;
428: return (i);
429: }
430:
431:
432:
433:
434: /*
435: ** INITSTRUCTS -- initialize relation and attribute tuples
436: **
437: ** Structures containing images of 'relation' relation and
438: ** 'attribute' relation tuples are initialized with all the
439: ** information initially needed to do the create. Frankly,
440: ** the only interesting part is the the expiration date
441: ** computation; longconst(9, 14976) is exactly the number
442: ** of seconds in one week.
443: **
444: ** Parameters:
445: ** att -- attribute relation tuple.
446: ** rel -- relation relation tuple.
447: **
448: ** Returns:
449: ** none
450: **
451: ** Side Effects:
452: ** 'att' and 'rel' are initialized.
453: **
454: ** Requires:
455: ** time -- to get the current date.
456: **
457: ** Called By:
458: ** create
459: **
460: ** Trace Flags:
461: ** none
462: **
463: ** Diagnostics:
464: ** none
465: **
466: ** Syserrs:
467: ** none
468: **
469: ** History:
470: ** 2/27/78 (eric) -- documented.
471: */
472:
473: initstructs(att, rel)
474: register struct attribute *att;
475: register struct relation *rel;
476: {
477: /* setup expiration date (today + one week) */
478: time(&rel->relstamp);
479: rel->relsave = rel->relstamp + 604800L;
480: rel->relfree = 0;
481: rel->reltups = 0;
482: rel->relatts = 0;
483: rel->relwid = 0;
484: rel->relprim = 1;
485: rel->relspec = M_HEAP;
486: rel->relindxd = 0;
487: att->attxtra = 0;
488: att->attid = 0;
489: att->attoff = 0;
490: }
491:
492:
493:
494: /*
495: ** CHECK ATTRIBUTE FORMAT AND CONVERT
496: **
497: ** The string 'a' is checked for a valid attribute format
498: ** and is converted to internal form.
499: **
500: ** zero is returned if the format is good; one is returned
501: ** if it is bad. If it is bad, the conversion into a is not
502: ** made.
503: **
504: ** A format of CHAR can be length zero only if this
505: ** create was generated internally.
506: */
507:
508: formck(a, dom, internal)
509: char *a;
510: struct domain *dom;
511: bool internal;
512: {
513: int len;
514: register int i;
515: char c;
516: register char *p;
517: register struct domain *d;
518:
519: p = a;
520: c = *p++;
521: d = dom;
522:
523: len = atoi(p);
524: i = len;
525:
526: switch (c)
527: {
528:
529: case INT:
530: if (i == 1 || i == 2 || i == 4)
531: {
532: d->frmt = INT;
533: d->frml = i;
534: return (0);
535: }
536: return (1);
537:
538: case FLOAT:
539: if (i == 4 || i == 8)
540: {
541: d->frmt = FLOAT;
542: d->frml = i;
543: return (0);
544: }
545: return (1);
546:
547: /* note: should disallow c0 from user (but needed internally) */
548: case CHAR:
549: if (i > 255 || i < 0 || (i == 0 && !internal))
550: return (1);
551: d->frmt = CHAR;
552: d->frml = i;
553: return (0);
554: }
555: return (1);
556:
557: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.