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