196 lines
4.6 KiB
C
196 lines
4.6 KiB
C
# include <stdio.h>
|
|
# include "gen.h"
|
|
# include "../h/dbs.h"
|
|
# include "../h/aux.h"
|
|
# include "../h/pipes.h"
|
|
# include "../h/catalog.h"
|
|
# include "../h/tree.h"
|
|
# include "../h/symbol.h"
|
|
# include "../h/lock.h"
|
|
# include "qrymod.h"
|
|
|
|
extern QTREE *Treeroot;
|
|
extern DESC Intdes;
|
|
extern DESC Reldes;
|
|
extern struct pipfrmt Pipe;
|
|
|
|
/*
|
|
** D_INTEG -- define integrity constraint
|
|
**
|
|
** An integrity constraint (as partially defined by the last
|
|
** tree defined by d_tree) is defined.
|
|
*/
|
|
d_integ()
|
|
{
|
|
register int i;
|
|
register QTREE *t; /* definition tree */
|
|
struct integrity inttup;
|
|
struct tup_id tid;
|
|
register int rv; /* result variable */
|
|
struct retcode *rc;
|
|
extern struct retcode *issueinvert();
|
|
struct relation relkey;
|
|
struct relation reltup;
|
|
|
|
t = Treeroot;
|
|
Treeroot = (QTREE *) 0;
|
|
rv = Resultvar;
|
|
|
|
/* pipe is not used, clear it out */
|
|
rdpipe(P_SYNC, &Pipe, R_up);
|
|
|
|
/*
|
|
** Check for valid environment.
|
|
** The tree must exist, have a qualification, and have
|
|
** no target list. The query mode must be mdDEFINE.
|
|
**
|
|
** User level stuff checks to see that this is single
|
|
** variable aggregate free, since that's all we know
|
|
** about thusfar. Also, the relation in question must
|
|
** not be a view.
|
|
*/
|
|
|
|
# ifdef xQTR3
|
|
if (!t)
|
|
AAsyserr(19000);
|
|
if ((i = t->right->sym.type) != AND)
|
|
AAsyserr(19001, i);
|
|
if ((i = t->left->sym.type) != TREE)
|
|
AAsyserr(19002, i);
|
|
if (Qmode != mdDEFINE)
|
|
AAsyserr(19003, Qmode);
|
|
# endif
|
|
|
|
/* check for aggregates */
|
|
if (aggcheck(t))
|
|
far_error(3490, -1, rv, (char *) 0); /* aggregates in qual */
|
|
|
|
/* check for multi-variable */
|
|
for (i = 0; i < MAXVAR + 1; i++)
|
|
{
|
|
if (!Rangev[i].rused)
|
|
continue;
|
|
if (i != rv)
|
|
{
|
|
# ifdef xQTR3
|
|
AAtTfp(49, 1, "D_INTEG: Rv %d(%.14s) i %d(%.14s)\n",
|
|
rv, Rangev[rv].relid, i, Rangev[i].relid);
|
|
# endif
|
|
far_error(3491, -1, rv, (char *) 0); /* too many vars */
|
|
}
|
|
}
|
|
|
|
/* check for the resultvariable being a real relation */
|
|
if (Rangev[rv].rstat & S_VIEW)
|
|
far_error(3493, -1, rv, (char *) 0); /* is a view */
|
|
|
|
/* no catalog */
|
|
if (Rangev[rv].rstat & S_CATALOG)
|
|
far_error(3496, -1, rv, (char *) 0); /* is a catalog */
|
|
|
|
/* and not an index */
|
|
if ((Rangev[rv].rstat & S_INDEX))
|
|
far_error(3495, -1, rv, (char *) 0); /* is an index */
|
|
|
|
/* guarantee that you own this relation */
|
|
if (!AAbequal(AAusercode, Rangev[rv].rowner, 2))
|
|
far_error(3494, -1, rv, (char *) 0); /* don't own reln */
|
|
|
|
/*
|
|
** Guarantee that the integrity constraint is true now.
|
|
** This involves issuing a retrieve statement for the
|
|
** inverse of the qualification. The target list is
|
|
** already null, so we will get nothing printed out
|
|
** (only a return status).
|
|
*/
|
|
|
|
Qmode = (int) mdRETR;
|
|
Resultvar = -1;
|
|
|
|
/* issue the invert of the query */
|
|
rc = issueinvert(t);
|
|
if (rc->rc_tupcount)
|
|
far_error(3492, -1, rv, (char *) 0); /* constraint not satisfied */
|
|
|
|
/*
|
|
** Set up the rest of the environment.
|
|
*/
|
|
|
|
opencatalog(AA_INTEG, 2);
|
|
clr_tuple(&Intdes, &inttup);
|
|
Resultvar = -1;
|
|
Qmode = -1;
|
|
|
|
/*
|
|
** Set up integrity relation tuple.
|
|
** The qualification will be scanned, and a set of
|
|
** domains referenced will be created. Other stuff
|
|
** is filled in from the range table and from the
|
|
** parser.
|
|
**
|
|
** The tree is actually inserted into the AA_TREE catalog
|
|
** in this step. Extra information is cleared here.
|
|
*/
|
|
|
|
inttup.intresvar = rv;
|
|
AAbmove(Rangev[rv].relid, inttup.intrelid, MAXNAME);
|
|
AAbmove(Rangev[rv].rowner, inttup.intrelowner, 2);
|
|
makeidset(rv, t, inttup.intdomset);
|
|
inttup.inttree = puttree(t, inttup.intrelid, inttup.intrelowner, mdINTEG);
|
|
|
|
/*
|
|
** Insert tuple into AA_INTEG catalog.
|
|
*/
|
|
|
|
if (AAam_insert(&Intdes, &tid, &inttup, FALSE) < 0)
|
|
AAsyserr(19004);
|
|
if (AAnoclose(&Intdes))
|
|
AAsyserr(19005);
|
|
|
|
/*
|
|
** Update relstat S_INTEG bit.
|
|
*/
|
|
|
|
if (!(Rangev[rv].rstat & S_INTEG))
|
|
{
|
|
opencatalog(AA_REL, 2);
|
|
AAam_setkey(&Reldes, &relkey, inttup.intrelid, RELID);
|
|
AAam_setkey(&Reldes, &relkey, inttup.intrelowner, RELOWNER);
|
|
if (AAgetequal(&Reldes, &relkey, &reltup, &tid))
|
|
AAsyserr(19006);
|
|
reltup.relstat |= S_INTEG;
|
|
if (AAsetusl(A_SLP, tid, M_EXCL) < 0)
|
|
AAsyserr(5000);
|
|
if (AAam_replace(&Reldes, &tid, &reltup, FALSE))
|
|
AAsyserr(19007);
|
|
AAunlus(tid);
|
|
if (AAnoclose(&Reldes))
|
|
AAsyserr(19008);
|
|
}
|
|
}
|
|
|
|
|
|
makeidset(varno, tree, dset)
|
|
int varno;
|
|
QTREE *tree;
|
|
short dset[8];
|
|
{
|
|
register int vn;
|
|
register QTREE *t;
|
|
|
|
vn = varno;
|
|
t = tree;
|
|
|
|
while (t)
|
|
{
|
|
if (t->sym.type == VAR && ((VAR_NODE *) t)->varno == vn)
|
|
lsetbit(((VAR_NODE *) t)->attno, dset);
|
|
|
|
/* handle left subtree recursively */
|
|
makeidset(vn, t->left, dset);
|
|
|
|
/* handle right subtree iteratively */
|
|
t = t->right;
|
|
}
|
|
}
|