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

Defined functions

chk_att defined in line 305; used 1 times
create defined in line 100; used 4 times
dup_att defined in line 412; used 1 times
formck defined in line 510; used 1 times
initstructs defined in line 474; used 1 times
ins_att defined in line 363; used 1 times

Defined variables

CreateFn defined in line 18; never used

Defined struct's

domain defined in line 45; used 18 times
Last modified: 1986-04-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1313
Valid CSS Valid XHTML 1.0 Strict