This commit is contained in:
Oliver Lehmann 1989-06-26 19:16:21 +00:00
parent 7c1b854e02
commit d08f2d69ae
2 changed files with 730 additions and 0 deletions

View File

@ -0,0 +1,501 @@
# include "gen.h"
# include "../h/dbs.h"
# include "../h/access.h"
# include "../h/aux.h"
# include "../h/catalog.h"
# include "../h/symbol.h"
# include "../h/lock.h"
/*
** CREATE -- create new relation
**
** This module creates a brand new relation in the current
** directory (database). The relation is always created as
** a paged heap. It may not redefine an existing relation,
** or rename a system catalog.
**
** Defines:
** create -- driver
** chk_att -- check attribute for validity
** ins_att -- insert attribute into AA_ATT catalog
** dup_att -- check for duplicate attribute
** initstructs -- initialize relation and attribute
** tuples for insertion into catalog
** formck -- check for valid attribute type.
*/
struct domain
{
char *name;
char frmt;
char frml;
};
/*
** CREATE -- create new relation
**
** This routine is the driver for the create module.
**
** Parameters:
** pc -- parameter count
** pv -- parameter vector:
** 0 -- relation status (relstat) -- stored into
** the 'relstat' field in the relation
** relation, and used to determine the
** caller. Interesting bits are:
**
** S_INDEX -- means called by the index
** processor. If set, the 'relindxd'
** field will also be set to -1
** (SECINDEX) to indicate that this
** relation is a secondary index.
** S_CATALOG -- this is a system catalog.
** If set, this create was called
** from creatdb, and the physical
** file is not created. Also, the
** expiration date is set infinite.
** S_VIEW -- this is a view. Create has
** been called by the 'define'
** statement, rather than the
** 'create' statement. The physical
** file is not created.
**
** 1 -- relation name.
** 2 -- attname1
** 3 -- format1
** 4, etc -- attname, format pairs.
**
** Returns:
** zero -- successful create.
** else -- failure somewhere.
*/
create(pc, pv)
int pc;
char **pv;
{
register char **pp;
register int i;
int bad;
struct domain domain[MAXDOM];
struct domain *dom;
char *relname;
char tempname[MAXNAME + 3];
struct tup_id tid;
struct relation rel;
struct attribute att;
DESC desr;
extern char *AAusercode;
extern DESC Reldes;
extern DESC Attdes;
extern int errno;
register int relstat;
int critical_section;
long npages;
int fdes;
# ifdef xZTR1
AAtTfp(2, -1, "CREATE: %s\n", pv[1]);
# endif
pp = pv;
relstat = AA_oatoi(pp[0]);
/*
** If this database has query modification, then default
** to denial on all user relations.
** (Since views cannot be protected, this doesn't apply to them)
*/
if ((AAdmin.adhdr.adflags & A_QRYMOD) && (!(relstat & S_VIEW)))
relstat |= (S_PROTALL | S_PROTRET);
relname = *(++pp);
AApmove(relname, rel.relid, MAXNAME, ' ');
AAbmove(AAusercode, rel.relowner, 2);
AAbmove(rel.relid, att.attrelid, MAXNAME + 2);
opencatalog(AA_REL, 2);
/* check for duplicate relation name */
if (!(relstat & S_CATALOG))
{
if (!AArelopen(&desr, -1, relname))
{
if (AAbequal(desr.reldum.relowner, rel.relowner, 2))
{
return (error(5102, relname, (char *) 0)); /* bad relname */
}
if (desr.reldum.relstat & S_CATALOG)
{
return (error(5103, relname, (char *) 0)); /* attempt to rename system catalog */
}
}
}
opencatalog(AA_ATT, 2);
/* initialize structures for system catalogs */
initstructs(&att, &rel);
rel.relstat = relstat;
if (relstat & S_CATALOG)
rel.relsave = 0;
else if ((relstat & S_INDEX))
rel.relindxd = SECINDEX;
# ifdef xZTR3
if (AAtTf(2, 2))
AAprtup(&Reldes, &rel);
# endif
/* check attributes */
pp++;
for (i = pc - 2; i > 0; i -= 2)
{
bad = chk_att(&rel, pp[0], pp[1], domain);
if (bad)
{
return (error(bad, relname, pp[0], pp[1], (char *) 0));
}
pp += 2;
}
/*
** Create files if appropriate. Concurrency control for
** the create depends on the actual file. To prevent
** to users with the same usercode from creating the
** same relation at the same time, their is check
** on the existence of the file. The important events are
** (1) if a tuple exists in the relation relation then
** the relation really exists. (2) if the file exists then
** the relation is being created but will not exist for
** use until the relation relation tuple is present.
** For VIEWS, the file is used for concurrency control
** during the create but is removed afterwards.
*/
if (!(relstat & S_CATALOG))
{
/* for non system named temporary relations
** set a critical section lock while checking the
** existence of a file. If it exists, error return(5102)
** else create file.
*/
critical_section = 0;
if (!AAbequal(rel.relid, SYSNAME, s_SYSNAME))
{
critical_section++;
if (AAsetcsl(NO_REL) < 0)
return (error(5000, (char *) 0));
if ((fdes = open(rel.relid, 0)) >= 0)
{
close(fdes); /* file already exists */
AAunlcs(NO_REL);
return (error(5102, relname, (char *) 0));
}
errno = 0; /* file doesn't exist */
}
AAdbname(rel.relid, rel.relowner, tempname);
desr.relfp = creat(tempname, FILEMODE);
if (critical_section)
AAunlcs(NO_REL);
if (desr.relfp < 0)
AAsyserr(11012, rel.relid);
desr.reltid = -1; /* init reltid to unused */
if (!(relstat & S_VIEW))
{
npages = 1;
if (i = formatpg(&desr, npages))
AAsyserr(11013, i);
}
close(desr.relfp);
}
/* insert attributes into attribute relation */
pp = pv + 2;
dom = domain;
for (i = pc - 2; i > 0; i -= 2)
{
ins_att(&Attdes, &att, dom++);
pp += 2;
}
/*
** Flush the attributes. This is necessary for recovery reasons.
** If for some reason the relation relation is flushed and the
** machine crashes before the attributes are flushed, then recovery
** will not detect the error.
** The call below cannot be a "AAnoclose" without major changes to
** creatdb.
*/
if (i = AApageflush((ACCBUF *) 0))
AAsyserr(11014, i);
if (i = AAam_insert(&Reldes, &tid, &rel, FALSE))
AAsyserr(11015, rel.relid, i);
/*
** Flush the relation. This is necessary for recovery reasons.
*/
if (i = AApageflush((ACCBUF *) 0))
AAsyserr(11034, i);
if (relstat & S_VIEW)
unlink(tempname);
return (0);
}
/*
** CHK_ATT -- check attribute for validity
**
** The attribute is checked to see if
** * it's name is ok (within MAXNAME bytes)
** * it is not a duplicate name
** * the format specified is legal
** * there are not a ridiculous number of attributes
** (ridiculous being defined as anything over MAXDOM - 1)
** * the tuple is not too wide to fit on one page
**
** Parameters:
** r -- relation relation tuple for this relation.
** attname -- tentative name of attribute.
** format -- tentative format for attribute.
** d -- a 'struct domain' used to determine dupli-
** cation, and to store the resulting name and
** format in.
**
** Returns:
** zero -- OK
** 5104 -- bad attribute name.
** 5105 -- duplicate attribute name.
** 5106 -- bad attribute format.
** 5107 -- too many attributes.
** 5108 -- tuple too wide.
**
** Side Effects:
** 'r' has the relatts and relwid fields updated to
** reflect the new attribute.
*/
chk_att(r, attname, format, d)
register struct relation *r;
char *attname;
char *format;
register struct domain *d;
{
register int i;
# ifdef xZTR3
if (AAtTfp(2, 1, "CHK_ATT: %s ", attname))
{
AAxputchar(*format);
printf("%s\n", format + 1);
}
# endif
/*
** if (AAsequal(attname, "tidp"))
** return (5104);
*/
if ((i = dup_att(attname, r->relatts, d)) < 0)
return (5105); /* duplicate attribute */
if (formck(format, &d[i]))
return (5106); /* bad attribute format */
r->relatts++;
r->relwid += ctou(d[i].frml);
if (r->relatts >= MAXDOM)
return (5107); /* too many attributes */
if (r->relwid > AAmaxtup && !(r->relstat & S_VIEW))
return (5108); /* tuple too wide */
return (0);
}
/*
** INS_ATT -- insert attribute into attribute relation
**
** Parameters:
** des -- relation descriptor for the AA_ATT catalog.
** att -- attribute tuple, preinitialized with all sorts
** of good stuff (everything except 'attname',
** 'attfrmt', and 'attfrml'; 'attid' and 'attoff'
** must be initialized to zero before this routine
** is called the first time.
** dom -- 'struct domain' -- the information needed about
** each domain.
**
** Side Effects:
** The 'att' tuple is updated in the obvious ways.
** A tuple is added to the AA_ATT catalog.
*/
ins_att(des, att, dom)
DESC *des;
struct attribute *att;
struct domain *dom;
{
struct tup_id tid;
register struct domain *d;
d = dom;
AApmove(d->name, att->attname, MAXNAME, ' ');
att->attfrmt = d->frmt;
att->attfrml = d->frml;
att->attid++;
if (AAam_insert(des, &tid, att, FALSE))
AAsyserr(11016, d->name);
att->attoff += ctou(att->attfrml);
}
/*
** DUP_ATT -- check for duplicate attribute
**
** The attribute named 'name' is inserted into the 'attalias'
** vector at position 'count'. 'Count' should be the count
** of existing entries in 'attalias'. 'Attalias' is checked
** to see that 'name' is not already present.
**
** Parameters:
** name -- the name of the attribute.
** count -- the count of attributes so far.
** domain -- 'struct domain' -- the list of domains
** so far, names and types.
**
** Returns:
** -1 -- attribute name is a duplicate.
** else -- index in 'domain' for this attribute (also
** the attid).
**
** Side Effects:
** The 'domain' vector is extended.
*/
dup_att(name, count, domain)
char *name;
int count;
struct domain domain[];
{
register struct domain *d;
register int lim;
register int i;
lim = count;
d = domain;
for (i = 0; i < lim; i++)
if (AAsequal(name, d++->name))
return (-1);
if (count < MAXDOM)
d->name = name;
return (i);
}
/*
** INITSTRUCTS -- initialize relation and attribute tuples
**
** Structures containing images of AA_REL relation and
** AA_ATT relation tuples are initialized with all the
** information initially needed to do the create. Frankly,
** the only interesting part is the the expiration date
** computation; 604800 is exactly the number
** of seconds in one week.
**
** Parameters:
** att -- attribute relation tuple.
** rel -- relation relation tuple.
**
** Side Effects:
** 'att' and 'rel' are initialized.
*/
initstructs(att1, rel1)
struct attribute *att1;
struct relation *rel1;
{
register struct relation *rel;
register struct attribute *att;
rel = rel1;
att = att1;
/* setup expiration date (today + one week) */
time(&rel->relsave);
rel->relsave += 604800L;
rel->reltups = 0;
rel->relatts = 0;
rel->relwid = 0;
rel->relprim = 1;
rel->relspec = M_HEAP;
rel->relindxd = 0;
rel->relspare = 0;
att->attxtra = 0;
att->attid = 0;
att->attoff = 0;
}
/*
** CHECK ATTRIBUTE FORMAT AND CONVERT
**
** The string 'a' is checked for a valid attribute format
** and is converted to internal form.
**
** zero is returned if the format is good; one is returned
** if it is bad. If it is bad, the conversion into a is not
** made.
**
** A format of CHAR can be length zero but a format
** of 'c' cannot.
*/
formck(a, dom)
char *a;
struct domain *dom;
{
short len;
register int i;
char c;
register char *p;
register struct domain *d;
p = a;
c = *p++;
d = dom;
if (AA_atoi(p, &len))
return (1);
i = len;
switch (c)
{
case INT:
case 'i':
if (i == sizeof (char) || i == sizeof (short) || i == sizeof (long))
{
d->frmt = INT;
d->frml = i;
return (0);
}
return (1);
case FLOAT:
case 'f':
if
(
# ifndef NO_F4
i == sizeof (float) ||
# endif
i == sizeof (double)
)
{
d->frmt = FLOAT;
d->frml = i;
return (0);
}
return (1);
case 'c':
if (!i)
return (1);
case CHAR:
if (i > MAXFIELD || i < 0)
return (1);
d->frmt = CHAR;
d->frml = i;
return (0);
}
return (1);
}

View File

@ -0,0 +1,229 @@
/*
** STRUCTURES USED IN THE NODES OF THE QUERYTREE
**
**
** SUNDRY CONSTANTS
**
** There are several differences in the handling of data
** structures on 16 and 32 bit machines:
** 1). A pointer to memory is either 2 or 4 bytes.
** 2). Padding is inserted in structures to insure
** alignment of 16 and 32 bit numbers.
**
** For these reasons the following constant definitions
** are useful for machine independent allocation.
**
** These are based on the BIT_32 compile flag.
**
** QT_HDR_SIZ -- size of left and right pointers, typ,
** len and padding
** QT_PTR_SIZ -- size of left and right pointers
** SYM_HDR_SIZ -- size of type and len in symbol
** structure -- includes any padding before
** the value field
** TYP_LEN_SIZ -- size of type and len in symbol
** structure -- without padding
**
** DBS FOLKS: don't change these back to sizeof's !!!
** The PDP-11 compiler doesn't understand!
*/
/* Basic symbol structure. "Type" is one of the symbols */
/* in "symbol.h", "len" is the length of the "value" */
/* field (0 to MAXFIELD bytes), "value" is variable length and */
/* holds the actual value (if len != 0) of the node. */
struct symbol
{
char type; /* type codes in symbol.h */
char len; /* length in bytes of value field */
# ifdef BIT_32
short aligned; /* align value to 32-bit offset */
# endif
short value[1]; /* variable length (0 - MAXFIELD bytes) */
};
typedef struct symbol SYMBOL;
# ifdef BIT_32
# define TYP_LEN_SIZ 2
# define SYM_HDR_SIZ 4
# else
# define TYP_LEN_SIZ 2
# define SYM_HDR_SIZ 2
# endif
/* Basic node in the querytree. Each node has a left and */
/* right descendent. If the node is a leaf node then the */
/* left and right pointers will be NULL. Depending on the */
/* "type" field of the symbol structure, there may be additional */
/* information. The cases are itemized below. */
struct querytree
{
struct querytree *left;
struct querytree *right;
struct symbol sym;
};
typedef struct querytree QTREE;
# ifdef BIT_32
# define QT_PTR_SIZ 8
# define QT_HDR_SIZ 12
# else
# define QT_PTR_SIZ 4
# define QT_HDR_SIZ 6
# endif
/* Variable nodes of the form: */
/* varno.attno */
/* "Varno" is the variable number which can be translated */
/* to a relation name by indexing into the range table. */
/* "Attno" is the attribute number specifically the */
/* "attid" field in the attribute tuple for the attribute. */
/* "Frmt" and "frml" are the type and length of the attribute. */
/* "Valptr" is used only in decomposition. If the variable */
/* is tuple substituted then "valptr" will have a pointer to */
/* the substituted value for the attribute; otherwise it will */
/* be NULL. If reduction or one variable restriction has changed */
/* the attribute number, then "valptr" will point to the next */
/* active VAR node for this VAR. */
struct var_node
{ char qt_hdr[QT_HDR_SIZ];
/* QTREE *left; */
/* QTREE *right; */
/* char type; */
/* char len; */
# ifdef BIT_32
/* short aligned; */
# endif
char varno;
char attno;
char frmt;
char frml;
char *valptr;
};
typedef struct var_node VAR_NODE;
# ifdef BIT_32
# define VAR_SIZ 8
# else
# define VAR_SIZ 6
# endif
# define VAR_HDR_SIZ 4
/* Structure for ROOT, AGHEAD, and AND nodes. In the parser and */
/* qrymod these nodes are of length zero and none of this */
/* information is present. Decomp maintains information about */
/* the variables in the left and right descendents of the nodes. */
/* The "rootuser" flag is present only in ROOT and AGHEAD nodes. */
/* It is TRUE only in the original ROOT node of the query. */
struct root_node
{ char qt_hdr[QT_HDR_SIZ];
/* QTREE *left; */
/* QTREE *right; */
/* char type; */
/* char len; */
# ifdef BIT_32
/* short aligned; */
# endif
char tvarc; /* total of var's in sub-tree */
char lvarc; /* # of variables in left branch */
short lvarm; /* bit map of var's in left branch */
short rvarm; /* bit map of var's in right branc */
short rootuser; /* TRUE if root of user generated query */
};
typedef struct root_node ROOT_NODE;
# define ROOT_SIZ 8
# define AND_SIZ 6
/* RESDOM node */
struct res_node
{ char qt_hdr[QT_HDR_SIZ];
/* QTREE *left; */
/* QTREE *right; */
/* char type; */
/* char len; */
# ifdef BIT_32
/* short aligned; */
# endif
short resno; /* result domain number */
/* char frmt; */
/* char frml; */
};
typedef struct res_node RES_NODE;
# define RES_SIZ 4
/* AOP node */
struct aop_node
{ char qt_hdr[QT_HDR_SIZ];
/* QTREE *left; */
/* QTREE *right; */
/* char type; */
/* char len; */
# ifdef BIT_32
/* short aligned; */
# endif
char var_hdr[VAR_HDR_SIZ];
/* char varno; */
/* char attno; */
/* char frmt; */
/* char frml; */
char agfrmt; /* result format type */
char agfrml; /* and length for aggregates */
};
typedef struct aop_node AOP_NODE;
# define AOP_SIZ 6
/* OP node */
struct op_node
{ char qt_hdr[QT_HDR_SIZ];
/* QTREE *left; */
/* QTREE *right; */
/* char type; */
/* char len; */
# ifdef BIT_32
/* short aligned; */
# endif
short opno; /* operator number */
};
typedef struct op_node OP_NODE;
# define OP_SIZ 2
struct svar_node
{ char sym_hdr[SYM_HDR_SIZ];
/* char type; */
/* char len; */
# ifdef BIT_32
/* short aligned; */
# endif
short vattno; /* variable attribute no */
char vtype; /* variable type */
char vlen; /* variable length */
short *vpoint; /* variable pointer to value */
};
typedef struct svar_node SVAR_NODE;
# define SVAR_SIZ VAR_SIZ
/* structure for referencing a SOURCEID type symbol for */
/* pipe transmission */
/* */
/* SOURCEID is a range table element. */
struct srcid
{ char sym_hdr[SYM_HDR_SIZ];
/* char type; */
/* char len; */
# ifdef BIT_32
/* short aligned; */
# endif
short srcvar; /* variable number */
char srcname[MAXNAME]; /* relation name */
char srcown[2]; /* relation owner usercode */
short srcstat; /* relstat field */
};
typedef struct srcid SRCID;
# define SRC_SIZ (6 + MAXNAME)