Annotation of 43BSD/ingres/source/dbu/create.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.