1: # include "../ingres.h" 2: # include "../access.h" 3: # include "../aux.h" 4: # include "../catalog.h" 5: # include "../symbol.h" 6: # include "../lock.h" 7: 8: 9: /* 10: ** CREATE -- create new relation 11: ** 12: ** This module creates a brand new relation in the current 13: ** directory (database). The relation is always created as 14: ** a paged heap. It may not redefine an existing relation, 15: ** or rename a system catalog. 16: ** 17: ** Defines: 18: ** create -- driver 19: ** chk_att -- check attribute for validity 20: ** ins_att -- insert attribute into 'attribute' catalog 21: ** dup_att -- check for duplicate attribute 22: ** initstructs -- initialize relation and attribute 23: ** tuples for insertion into catalog 24: ** formck -- check for valid attribute type. 25: ** 26: ** Requires: 27: ** ingresname 28: ** opencatalog 29: ** openr 30: ** insert 31: ** setcsl, unlcs 32: ** creat -- to create physical file 33: ** Usercode -- to find out the current user. 34: ** Reldes, Attdes -- from opencatalog 35: ** 36: ** Required By: 37: ** overlaya 38: ** overlaym.c 39: ** 40: ** Files: 41: ** relname....cc -- where cc is the Usercode. 42: ** 43: ** Trace Flags: 44: ** 2 45: ** 46: ** Diagnostics: 47: ** 5102 -- duplicate relation name %0 48: ** The relation named already exists (and is 49: ** owned by you. 50: ** 5103 -- %0 is a system catalog 51: ** It is not OK to declare a relation name which 52: ** is the same as that of a system catalog, even 53: ** if you do not own the system catalog. This is 54: ** so that when other parts of the system do an 55: ** openr on system-catalog type stuff, it will not 56: ** accidently get something it didn't expect. 57: ** 5104 -- %0: invalid attribute name %1 58: ** An attribute name may not be called "tid", 59: ** since that is magic. 60: ** 5105 -- %0: duplicate attribute name %1 61: ** Naturally, all attribute names must be unique. 62: ** 5106 -- %0: invalid attribute format %2 on %1 63: ** Attribute formats can only be the usual 'i1', 64: ** 'i2', 'i4', 'f4', 'f8', or 'cN', with N from 65: ** one to 255. N can be zero if the relation is 66: ** generated internally ("_SYS..."); this is used 67: ** by decomp to avoid some nasty bugs. 68: ** 5107 -- %0: excessive domain count on %1 69: ** There is a magic number (MAXDOM - 1) of domains 70: ** which is the maximum that may occur in a single 71: ** relation. As the error documentation says: 72: ** "The origin of this magic number is obscure. 73: ** This is very difficult to change." Oh well. 74: ** 5108 -- %0: excessive relation width on attr %1 75: ** I wonder who came up with these AWFUL error messages. 76: ** Tuple widths may not exceed a magic number, 77: ** based heavily on the size of a page in UNIX. 78: ** The current value of THIS magic number (MAXTUP) 79: ** is 498 bytes. 80: ** 81: ** History: 82: ** 10/23/79 (6.2/8) (eric) -- null terminated relation filename 83: ** before creat() call so that systems which check 84: ** for names too long won't balk. 85: ** 12/7/78 (rse) -- removed call to sys_catalog and put code 86: ** in line. 87: ** 11/3/78 (rse) -- formatpg now resets the page itself so 88: ** call to resetacc removed. 89: ** 11/1/78 (rse) -- views have no limit on tuple width. 90: ** 10/30/78 (rse) -- added pageflush after inserting attributes. 91: ** 8/17/78 (rse) -- fixed call to formatpg(). 92: ** Changed calls to error() to have full error number 93: ** 8/1/78 (eric) -- call to 'noclose' (for concurrency 94: ** reasons) moved to index.c, which is the only 95: ** place it was needed. This made creatdb 96: ** simpler. 97: ** 2/27/78 (eric) -- modified to take 'relstat' as param 98: ** zero, instead of the (ignored) storage struc- 99: ** ture. 100: */ 101: 102: 103: 104: 105: 106: struct domain 107: { 108: char *name; 109: char frmt; 110: char frml; 111: }; 112: 113: /* 114: ** CREATE -- create new relation 115: ** 116: ** This routine is the driver for the create module. 117: ** 118: ** Parameters: 119: ** pc -- parameter count 120: ** pv -- parameter vector: 121: ** 0 -- relation status (relstat) -- stored into 122: ** the 'relstat' field in the relation 123: ** relation, and used to determine the 124: ** caller. Interesting bits are: 125: ** 126: ** S_INDEX -- means called by the index 127: ** processor. If set, the 'relindxd' 128: ** field will also be set to -1 129: ** (SECINDEX) to indicate that this 130: ** relation is a secondary index. 131: ** S_CATALOG -- this is a system catalog. 132: ** If set, this create was called 133: ** from creatdb, and the physical 134: ** file is not created. Also, the 135: ** expiration date is set infinite. 136: ** S_VIEW -- this is a view. Create has 137: ** been called by the 'define' 138: ** statement, rather than the 139: ** 'create' statement. The physical 140: ** file is not created. 141: ** 142: ** 1 -- relation name. 143: ** 2 -- attname1 144: ** 3 -- format1 145: ** 4, etc -- attname, format pairs. 146: ** 147: ** Returns: 148: ** zero -- successful create. 149: ** else -- failure somewhere. 150: ** 151: ** Side Effects: 152: ** A relation is created (this is a side effect?). This 153: ** means entries in the 'relation' and 'attribute' cata- 154: ** logs, and (probably) a physical file somewhere, with 155: ** one page already in it. 156: ** 157: ** Requires: 158: ** opencatalog -- to open the 'relation' and 'attribute' 159: ** catalogs into 'Reldes' and 'Attdes' resp. 160: ** initstructs -- to initialize relation and attribute 161: ** tuples. 162: ** chk_att -- to check each attribute for validity: 163: ** good name, correct format, no dups, etc. 164: ** setcsl -- to set a critical section lock around the 165: ** section of code to physically create a file. 166: ** For concurrency reasons, this is the "true" 167: ** test for existance of a relation. 168: ** unlcs -- to remove locks, of course. 169: ** formatpg -- a mystic routine that outputs the initial 170: ** page of the relation (empty) so that the 171: ** access methods will not choke later. 172: ** insert -- to insert tuples into the 'relation' and 173: ** 'attribute' catalogs. 174: ** 175: ** Called By: 176: ** overlaya, overlaym 177: ** (maybe other overlay?) 178: ** creatdb 179: ** index 180: ** 181: ** Trace Flags: 182: ** 2.* -- entry message 183: ** 184: ** Diagnostics: 185: ** 5102 -- duplicate relation name 186: ** 5103 -- renaming system catalog 187: ** 5104 -- invalid attribute name 188: ** 5105 -- duplicate attribute name 189: ** 5106 -- invalid attribute format spec 190: ** 5107 -- too many domains 191: ** 5108 -- tuple too wide 192: ** 193: ** Syserrs: 194: ** create: creat %s 195: ** The 'creat' call failed, probably meaning 196: ** that the directory is not writable, the file 197: ** exists mode zero, or this process is not 198: ** running as 'ingres'. 199: ** create: formatpg %d 200: ** The 'formatpg' routine failed. Could be 201: ** because of a lack of disk space. The number 202: ** is the return from formatpg; check it for 203: ** more details. 204: ** create: insert(rel, %s) %d 205: ** The insert for relid %s into the 'relation' 206: ** catalog failed; %d is the return from insert. 207: ** Check insert for details. 208: ** 209: ** History: 210: ** 8/1/78 (eric) -- 'noclose' call moved to index.c. 211: ** 2/27/78 (eric) -- changed to take 'relstat' as pv[0] 212: ** instead of the (ignored) relspec. 213: */ 214: 215: create(pc, pv) 216: int pc; 217: char **pv; 218: { 219: register char **pp; 220: register int i; 221: int bad; 222: struct domain domain[MAXDOM]; 223: struct domain *dom; 224: char *relname, tempname[MAXNAME+3]; 225: struct tup_id tid; 226: struct relation rel, key; 227: struct attribute att; 228: struct descriptor desr; 229: extern char *Usercode; 230: extern struct descriptor Reldes, Attdes; 231: extern int errno; 232: register int relstat; 233: long temptid; 234: long npages; 235: int fdes; 236: 237: # ifdef xZTR1 238: if (tTf(2, -1)) 239: printf("creating %s\n", pv[1]); 240: # endif 241: pp = pv; 242: relstat = oatoi(pp[0]); 243: /* 244: ** If this database has query modification, then default 245: ** to denial on all user relations. 246: ** (Since views cannot be protected, this doesn't apply to them) 247: */ 248: if ((Admin.adhdr.adflags & A_QRYMOD) && ((relstat & (S_VIEW || S_CATALOG)) == 0)) 249: relstat |= (S_PROTALL | S_PROTRET); 250: relname = *(++pp); 251: ingresname(relname, Usercode, rel.relid); 252: bmove(rel.relid, att.attrelid, MAXNAME + 2); 253: opencatalog("relation", 2); 254: 255: /* check for duplicate relation name */ 256: if ((relstat & S_CATALOG) == 0) 257: { 258: if (openr(&desr, -1, relname) == 0) 259: { 260: if (bequal(desr.relowner, rel.relowner, 2)) 261: { 262: return (error(5102, relname, 0)); /* bad relname */ 263: } 264: if (desr.relstat & S_CATALOG) 265: { 266: return (error(5103, relname, 0)); /* attempt to rename system catalog */ 267: } 268: } 269: } 270: opencatalog("attribute", 2); 271: 272: /* initialize structures for system catalogs */ 273: initstructs(&att, &rel); 274: rel.relstat = relstat; 275: if ((relstat & S_CATALOG) != 0) 276: rel.relsave = 0; 277: else if ((relstat & S_INDEX) != 0) 278: rel.relindxd = SECINDEX; 279: 280: # ifdef xZTR3 281: if (tTf(2, 2)) 282: printup(&Reldes, &rel); 283: # endif 284: 285: /* check attributes */ 286: pp++; 287: for (i = pc - 2; i > 0; i -= 2) 288: { 289: bad = chk_att(&rel, pp[0], pp[1], domain); 290: if (bad != 0) 291: { 292: return (error(bad, relname, pp[0], pp[1], 0)); 293: } 294: pp += 2; 295: } 296: 297: /* 298: ** Create files if appropriate. Concurrency control for 299: ** the create depends on the actual file. To prevent 300: ** to users with the same usercode from creating the 301: ** same relation at the same time, their is check 302: ** on the existence of the file. The important events are 303: ** (1) if a tuple exists in the relation relation then 304: ** the relation really exists. (2) if the file exists then 305: ** the relation is being created but will not exist for 306: ** use until the relation relation tuple is present. 307: ** For VIEWS, the file is used for concurrency control 308: ** during the create but is removed afterwards. 309: */ 310: if ((relstat & S_CATALOG) == 0) 311: { 312: /* for non system named temporary relations 313: ** set a critical section lock while checking the 314: ** existence of a file. If it exists, error return(5102) 315: ** else create file. 316: */ 317: temptid = 0; 318: if (Lockrel && (!bequal(rel.relid,"_SYS",4))) 319: { 320: temptid = -1; 321: setcsl(temptid); /* set critical section lock */ 322: if ((fdes = open(rel.relid,0)) >= 0) 323: { 324: /* file already exists */ 325: close(fdes); 326: unlcs(temptid); /* release critical section lock */ 327: return (error(5102, relname, 0)); 328: } 329: errno = 0; /* file doesn't exist */ 330: } 331: ingresname(rel.relid, rel.relowner, tempname); 332: desr.relfp = creat(tempname, FILEMODE); 333: if (temptid != 0) 334: unlcs(temptid); /* release critical section lock */ 335: if (desr.relfp < 0) 336: syserr("create: creat %s", rel.relid); 337: desr.reltid = -1; /* init reltid to unused */ 338: if ((relstat & S_VIEW) == 0) 339: { 340: npages = 1; 341: if (i = formatpg(&desr, npages)) 342: syserr("syserr: formatpg %d", i); 343: } 344: 345: close(desr.relfp); 346: } 347: 348: /* insert attributes into attribute relation */ 349: pp = pv + 2; 350: dom = domain; 351: for (i = pc - 2; i > 0; i -= 2) 352: { 353: ins_att(&Attdes, &att, dom++); 354: pp += 2; 355: } 356: 357: /* 358: ** Flush the attributes. This is necessary for recovery reasons. 359: ** If for some reason the relation relation is flushed and the 360: ** machine crashes before the attributes are flushed, then recovery 361: ** will not detect the error. 362: ** The call below cannot be a "noclose" without major changes to 363: ** creatdb. 364: */ 365: if (i = pageflush(0)) 366: syserr("create:flush att %d", i); 367: 368: if (i = insert(&Reldes, &tid, &rel, FALSE)) 369: syserr("create: insert(rel, %.14s) %d", rel.relid, i); 370: 371: if (relstat & S_VIEW) 372: unlink(tempname); 373: return (0); 374: } 375: 376: 377: 378: /* 379: ** CHK_ATT -- check attribute for validity 380: ** 381: ** The attribute is checked to see if 382: ** * it's name is ok (within MAXNAME bytes) 383: ** * it is not a duplicate name 384: ** * the format specified is legal 385: ** * there are not a ridiculous number of attributes 386: ** (ridiculous being defined as anything over MAXDOM - 1) 387: ** * the tuple is not too wide to fit on one page 388: ** 389: ** Parameters: 390: ** rel -- relation relation tuple for this relation. 391: ** attname -- tentative name of attribute. 392: ** format -- tentative format for attribute. 393: ** domain -- a 'struct domain' used to determine dupli- 394: ** cation, and to store the resulting name and 395: ** format in. 396: ** 397: ** Returns: 398: ** zero -- OK 399: ** 5104 -- bad attribute name. 400: ** 5105 -- duplicate attribute name. 401: ** 5106 -- bad attribute format. 402: ** 5107 -- too many attributes. 403: ** 5108 -- tuple too wide. 404: ** 405: ** Side Effects: 406: ** 'rel' has the relatts and relwid fields updated to 407: ** reflect the new attribute. 408: ** 409: ** Requires: 410: ** length -- to check length of 'attname' against MAXNAME. 411: ** dup_att -- to check for duplicate attribute and 412: ** initialize 'name' field of 'domain' struct. 413: ** formck -- to check and convert the attribute format. 414: ** 415: ** Called By: 416: ** create 417: ** 418: ** Trace Flags: 419: ** 2.1 -- entry print 420: ** 421: ** Diagnostics: 422: ** as noted in the return. 423: ** 424: ** Syserrs: 425: ** none 426: ** 427: ** History: 428: ** 11/1/78 (rse) -- views have no limit on tuple width. 429: ** 2/27/78 (eric) -- documented. 430: */ 431: 432: chk_att(rel, attname, format, domain) 433: struct relation *rel; 434: char *attname, *format; 435: struct domain domain[]; 436: { 437: register int i; 438: register struct relation *r; 439: 440: r = rel; 441: 442: # ifdef xZTR3 443: if (tTf(2, 1)) 444: printf("chk_att %s %s\n", attname, format); 445: # endif 446: 447: if (sequal(attname, "tid")) 448: return (5104); /* bad attribute name */ 449: if ((i = dup_att(attname, r->relatts, domain)) < 0) 450: return (5105); /* duplicate attribute */ 451: if (formck(format, &domain[i])) 452: return (5106); /* bad attribute format */ 453: r->relatts++; 454: r->relwid += domain[i].frml & 0377; 455: if (r->relatts >= MAXDOM) 456: return (5107); /* too many attributes */ 457: if (r->relwid > MAXTUP && (r->relstat & S_VIEW) == 0) 458: return (5108); /* tuple too wide */ 459: return (0); 460: } 461: 462: 463: 464: 465: /* 466: ** INS_ATT -- insert attribute into attribute relation 467: ** 468: ** Parameters: 469: ** des -- relation descriptor for the attribute catalog. 470: ** att -- attribute tuple, preinitialized with all sorts 471: ** of good stuff (everything except 'attname', 472: ** 'attfrmt', and 'attfrml'; 'attid' and 'attoff' 473: ** must be initialized to zero before this routine 474: ** is called the first time. 475: ** dom -- 'struct domain' -- the information needed about 476: ** each domain. 477: ** 478: ** Returns: 479: ** none 480: ** 481: ** Side Effects: 482: ** The 'att' tuple is updated in the obvious ways. 483: ** A tuple is added to the 'attribute' catalog. 484: ** 485: ** Requires: 486: ** insert 487: ** pmove -- to make the attribute name nice and clean. 488: ** 489: ** Called By: 490: ** create 491: ** 492: ** Trace Flags: 493: ** none currently 494: ** 495: ** Diagnostics: 496: ** none 497: ** 498: ** Syserrs: 499: ** ins_att: insert(att, %s) 500: ** The insert into the attribute catalog failed. 501: ** 502: ** History: 503: ** 2/27/78 (eric) -- result of insert checked. 504: */ 505: 506: ins_att(des, att, dom) 507: struct descriptor *des; 508: struct attribute *att; 509: struct domain *dom; 510: { 511: register int i; 512: struct tup_id tid; 513: register struct domain *d; 514: 515: d = dom; 516: 517: pmove(d->name, att->attname, MAXNAME, ' '); 518: att->attfrmt = d->frmt; 519: att->attfrml = d->frml; 520: att->attid++; 521: if (insert(des, &tid, att, FALSE)) 522: syserr("ins_att: insert(att, %s)", d->name); 523: att->attoff += att->attfrml & 0377; 524: } 525: 526: 527: 528: 529: /* 530: ** DUP_ATT -- check for duplicate attribute 531: ** 532: ** The attribute named 'name' is inserted into the 'attalias' 533: ** vector at position 'count'. 'Count' should be the count 534: ** of existing entries in 'attalias'. 'Attalias' is checked 535: ** to see that 'name' is not already present. 536: ** 537: ** Parameters: 538: ** name -- the name of the attribute. 539: ** count -- the count of attributes so far. 540: ** domain -- 'struct domain' -- the list of domains 541: ** so far, names and types. 542: ** 543: ** Returns: 544: ** -1 -- attribute name is a duplicate. 545: ** else -- index in 'domain' for this attribute (also 546: ** the attid). 547: ** 548: ** Side Effects: 549: ** The 'domain' vector is extended. 550: ** 551: ** Requires: 552: ** none 553: ** 554: ** Called By: 555: ** chk_att 556: ** 557: ** Trace Flags: 558: ** none 559: ** 560: ** History: 561: ** 2/27/78 (eric) -- documented. 562: */ 563: 564: dup_att(name, count, domain) 565: char *name; 566: int count; 567: struct domain domain[]; 568: { 569: register struct domain *d; 570: register int lim; 571: register int i; 572: 573: lim = count; 574: d = domain; 575: 576: for (i = 0; i < lim; i++) 577: if (sequal(name, d++->name)) 578: return (-1); 579: if (count < MAXDOM) 580: d->name = name; 581: return (i); 582: } 583: 584: 585: 586: 587: /* 588: ** INITSTRUCTS -- initialize relation and attribute tuples 589: ** 590: ** Structures containing images of 'relation' relation and 591: ** 'attribute' relation tuples are initialized with all the 592: ** information initially needed to do the create. Frankly, 593: ** the only interesting part is the the expiration date 594: ** computation; longconst(9, 14976) is exactly the number 595: ** of seconds in one week. 596: ** 597: ** Parameters: 598: ** att -- attribute relation tuple. 599: ** rel -- relation relation tuple. 600: ** 601: ** Returns: 602: ** none 603: ** 604: ** Side Effects: 605: ** 'att' and 'rel' are initialized. 606: ** 607: ** Requires: 608: ** time -- to get the current date. 609: ** 610: ** Called By: 611: ** create 612: ** 613: ** Trace Flags: 614: ** none 615: ** 616: ** Diagnostics: 617: ** none 618: ** 619: ** Syserrs: 620: ** none 621: ** 622: ** History: 623: ** 2/27/78 (eric) -- documented. 624: */ 625: 626: initstructs(att1, rel1) 627: struct attribute *att1; 628: struct relation *rel1; 629: { 630: register struct relation *rel; 631: register struct attribute *att; 632: extern long longconst(); 633: 634: rel = rel1; 635: att = att1; 636: 637: /* setup expiration date (today + one week) */ 638: time(&rel->relsave); 639: rel->relsave += longconst(9, 14976); 640: 641: rel->reltups = 0; 642: rel->relatts = 0; 643: rel->relwid = 0; 644: rel->relprim = 1; 645: rel->relspec = M_HEAP; 646: rel->relindxd = 0; 647: rel->relspare = 0; 648: 649: att->attxtra = 0; 650: att->attid = 0; 651: att->attoff = 0; 652: } 653: 654: 655: 656: /* 657: ** CHECK ATTRIBUTE FORMAT AND CONVERT 658: ** 659: ** The string 'a' is checked for a valid attribute format 660: ** and is converted to internal form. 661: ** 662: ** zero is returned if the format is good; one is returned 663: ** if it is bad. If it is bad, the conversion into a is not 664: ** made. 665: ** 666: ** A format of CHAR can be length zero but a format 667: ** of 'c' cannot. 668: */ 669: 670: formck(a, dom) 671: char *a; 672: struct domain *dom; 673: { 674: int len; 675: register int i; 676: char c; 677: register char *p; 678: register struct domain *d; 679: 680: p = a; 681: c = *p++; 682: d = dom; 683: 684: if (atoi(p, &len) != 0) 685: return (1); 686: i = len; 687: 688: switch (c) 689: { 690: 691: case INT: 692: case 'i': 693: if (i == 1 || i == 2 || i == 4) 694: { 695: d->frmt = INT; 696: d->frml = i; 697: return (0); 698: } 699: return (1); 700: 701: case FLOAT: 702: case 'f': 703: if (i == 4 || i == 8) 704: { 705: d->frmt = FLOAT; 706: d->frml = i; 707: return (0); 708: } 709: return (1); 710: 711: case 'c': 712: if (i == 0) 713: return (1); 714: case CHAR: 715: if (i > 255 || i < 0) 716: return (1); 717: d->frmt = CHAR; 718: d->frml = i; 719: return (0); 720: } 721: return (1); 722: }