# include "gen.h" # include "../h/dbs.h" # include "../h/access.h" # include "../h/aux.h" # include "../h/bs.h" # include "../h/catalog.h" # include "../h/symbol.h" /* ** RMQM -- DBU to delete protection and integrity constraints ** ** Defines: ** dest_const ** dest_integ ** dest_prot ** i_cat ** dl_all ** del_int ** del_tree ** chk_const ** r_relstat ** tree_const ** tree_prot ** prot_protree ** int_inttree ** ** ** ** DEST_CONST -- destroy constraints ** ** Parameters: ** argc -- number of parameters in argv ** argv -- argv [0] == 5 destroy permission ** == 6 destroy integrity constraint ** argv [1] relation from which to destroy constrain ** argv [2] == if (argc != 2) relation from which to delete ** constraints ** argv[3] ... argv[argc - 1] == id of constraint ** ** Side Effects: ** destroys constraints. Involves activity on catalogs ** AA_REL, AA_PROTECT, AA_INTEG, and AA_TREE. */ dest_const(argc, argv) int argc; char **argv; { DESC d; register int i; short mode; extern struct admin AAdmin; # ifdef xZTR1 if (AAtTfp(13, 0, "DEST_CONST\n")) AAprargs(argc, argv); # endif if (!(AAdmin.adhdr.adflags & A_QRYMOD)) return (0); i = AArelopen(&d, -1, argv[1]); if (i < 0) AAsyserr(11138, argv[1], i); if (i == 1 || !AAbequal(AAusercode, d.reldum.relowner, 2)) { error(5202, argv[1], (char *) 0); return (0); } argv[argc] = 0; if (i = AA_atoi(argv[0], &mode)) AAsyserr(11139, argv[0]); if (mode == 5) dest_prot(&d, &argv[2]); else if (mode == 6) dest_integ(&d, &argv[2]); else AAsyserr(11140, mode); return (0); } /* ** DEST_INTEG -- directs destruction of integrity constraints ** ** Parameters: ** desc -- descriptor for relation ** intv -- 0 terminated list of id strings, if first element ** is 0 means "all" ** ** Side Effects: ** deletes integrity constraint. Activity on AA_REL, AA_INTEG, ** and AA_TREE. */ dest_integ(desc, intv) DESC *desc; char *intv[]; { register DESC *d; extern DESC Intdes; struct integrity tuple; struct integrity key; struct tree tkey; register int i; register int j; int tree_const(); int int_inttree(); d = desc; # ifdef xZTR1 AAtTfp(13, 1, "DEST_INTEG: (%s, %s)...\n", d->reldum.relid, d->reldum.relowner); # endif i_cat(AA_INTEG, &Intdes, &key, d->reldum.relid, INTRELID, d->reldum.relowner, INTRELOWNER, mdINTEG, &tkey); if (!intv[0]) { /* destroy integrity 'relation' ALL */ if (!(d->reldum.relstat & S_INTEG)) return (0); del_all(d, &Intdes, &key, &tuple, &tkey, S_INTEG, tree_const, int_inttree); return (0); } /* destroy integrity 'relation' int {, int} */ for (i = 0; intv[i]; i++) del_int(&Intdes, &key, &tuple, &tkey, intv[i], INTTREE, tree_const, int_inttree); /* rescan to output error messages */ for (j = 0; j < i; j++) if (*intv[j]) error(5203, intv[j], (char *) 0); /* finally, check that there are still integrity constraints ** on the relation, if not must reset the S_INTEG bit in the relation ** relation tuple for that relation. */ chk_const(d, &Intdes, &key, &tuple, d->reldum.relid, INTRELID, d->reldum.relowner, INTRELOWNER, S_INTEG); } /* ** DEST_PROT -- directs destruction of protection constraints ** ** Parameters: ** desc -- descriptor for relation ** intv -- 0 terminated list of id strings, if first element ** is 0 means "all" ** ** Side Effects: ** deletes protection constraint. Activity on catalogs ** AA_REL, AA_PROTECT, and AA_TREE. */ dest_prot(desc, intv) DESC *desc; char *intv[]; { register DESC *d; extern DESC Prodes; struct protect tuple; struct protect key; struct tree tkey; register int i; register int j; short propermid; int prot_protree(); int tree_prot(); d = desc; # ifdef xZTR1 AAtTfp(13, 2, "DEST_PROT: (%s, %s)...\n", d->reldum.relid, d->reldum.relowner); # endif i_cat(AA_PROTECT, &Prodes, &key, d->reldum.relid, PRORELID, d->reldum.relowner, PRORELOWN, mdPROT, &tkey); if (!intv[0]) { /* destroy permit 'relation' ALL */ if (!(d->reldum.relstat & S_PROTRET) || !(d->reldum.relstat & S_PROTALL)) r_relstat(d, S_PROTRET | S_PROTALL, 1); if (!(d->reldum.relstat & S_PROTUPS)) return (0); del_all(d, &Prodes, &key, &tuple, &tkey, S_PROTUPS, tree_prot, prot_protree); return (0); } /* destroy permit 'relation' int {, int} */ for (i = 0; intv[i]; i++) { if (j = AA_atoi(intv[i], &propermid)) AAsyserr(11141, intv[i], j); if (!propermid) { if (!(d->reldum.relstat & S_PROTALL)) { r_relstat(d, S_PROTALL, 1); *intv[i] = 0; } continue; } else if (propermid == 1) { if (!(d->reldum.relstat & S_PROTRET)) { r_relstat(d, S_PROTRET, 1); *intv[i] = 0; } continue; } del_int(&Prodes, &key, &tuple, &tkey, intv[i], PROPERMID, tree_prot, prot_protree); } /* rescan to output error messages */ for (j = 0; j < i; j++) if (*intv[j]) error(5204, intv[j], (char *) 0); /* finally, check that there are still permissions ** on the relation, if not must reset the S_PROTUPS bit in the relation ** relation tuple for that relation's relstat. */ chk_const(d, &Prodes, &key, &tuple, d->reldum.relid, PRORELID, d->reldum.relowner, PRORELOWN, S_PROTUPS); } /* ** I_CAT -- prepare catalogs for deletin of constraint ** ** Initializes treerelid, treeowner, and treetype fields ** of tree key. Also relation id and owner fields of ** appropriate catalog c_desc, with key 'key'. ** ** Parameters: ** c_name -- name of catalog for opencatalog ** c_desc -- descriptor of catalog ** key -- key for catalog ** relid -- relation.relid for relation to be de-constrained ** id_attno -- attno of relid in constraint catalog c_desc ** relowner -- relation.relowner for rel to be de-constrained ** own_attno -- attno of owner in constrain catalog ** type -- treetype for tree tuple (depends on catalog) ** tkey -- key for AA_TREE catalog ** ** Side Effects: ** opencatalogs the constraint catalog c_desc, and the AA_TREE rel ** for READ/WRITE. Sets keys. */ i_cat(c_name, c_desc, key, relid, id_attno, relowner, own_attno, type, tkey) char *c_name; DESC *c_desc; char *key; char *relid; int id_attno; char *relowner; int own_attno; char type; struct tree *tkey; { extern DESC Treedes; # ifdef xZTR1 AAtTfp(13, 3, "I_CAT: c_name \"%s\", relid %s id_attno %d relowner %s own_attno %d type %d\n", c_name, relid, id_attno, relowner, own_attno, type); # endif opencatalog(AA_TREE, 2); AAam_setkey(&Treedes, tkey, relid, TREERELID); AAam_setkey(&Treedes, tkey, relowner, TREEOWNER); AAam_setkey(&Treedes, tkey, &type, TREETYPE); opencatalog(c_name, 2); AAam_clearkeys(c_desc); AAam_setkey(c_desc, key, relid, id_attno); AAam_setkey(c_desc, key, relowner, own_attno); } /* ** DEL_ALL -- delete all constraints for a given relation ** ** Deletes all constraints of a given type given by a constraint ** catalog 'c_desc'. Note that Protection constraints 0 & 1, given ** by relation.relstat field are not deleted here. ** ** Parameters: ** r_desc -- descriptor for relation to de-constrain (for ** r_relstat) ** c_desc -- constraint catalog descriptor ** key -- c_desc's key ** tuple -- c_desc's tuple (needed because sizeof tuple is not ** known here, so must be allocated beforehand) ** tkey -- tree key with TREERELID and TREERELOWNER setkeyed ** bit -- bits in relstat to reset after deleting all constraints ** tree_pred -- called with constraint tuple to determine ** wether a tree tuple is present or not (as can happen ** for AA_PROTECT catalog) ** tree_field -- should return the treeid from tuple */ del_all(r_desc, c_desc, key, tuple, tkey, bit, tree_pred, tree_field) DESC *r_desc; DESC *c_desc; char *key; char *tuple; struct tree *tkey; int bit; int (*tree_pred)(); int (*tree_field)(); { struct tup_id lotid; struct tup_id hitid; register int i; # ifdef xZTR1 AAtTfp(13, 4, "DEL_ALL: bit=0%o\n", bit); # endif if (i = AAam_find(c_desc, EXACTKEY, &lotid, &hitid, key)) AAsyserr(11142, i); while (!(i = AAam_get(c_desc, &lotid, &hitid, tuple, TRUE))) { if (!AAkcompare(c_desc, tuple, key)) { /* for each constraint of for a relation */ if (i = AAam_delete(c_desc, &lotid)) AAsyserr(11143, i); /* for crash recovery */ if (i = AAam_flush_rel(c_desc, FALSE)) AAsyserr(11144, i); /* if there is a tree tuple, destroy it */ if ((*tree_pred)(tuple)) del_tree(tkey, (*tree_field)(tuple)); } } if (i != 1) AAsyserr(11145, i); /* turn off bit in relstat field */ r_relstat(r_desc, bit, 0); } /* ** DEL_INT -- delete from a constraint catalog a constraint ** ** Parameters: ** c_desc -- catalog descriptor ** key -- catalog key ** tuple -- catalog tuple (needed because tuple size unknown here) ** tkey -- tree key with TREERELID and TREERELOWNER setkeyed ** constid -- integer constraint id in string form ** constattno -- attno of comstraint number in c_desc ** tree_pred -- predicate on existence of tree tuple ** tree_field -- returns treeid from constrain tuple */ del_int(c_desc, key, tuple, tkey, constid, constattno, tree_pred, tree_field) DESC *c_desc; char *key; char *tuple; struct tree *tkey; char *constid; int constattno; int (*tree_pred)(); int (*tree_field)(); { struct tup_id tid; register int i; short constnum; # ifdef xZTR1 AAtTfp(13, 5, "DEL_INT: constid=%s, constattno=%d\n", constid, constattno); # endif if (i = AA_atoi(constid, &constnum)) AAsyserr(11146, constid, i); AAam_setkey(c_desc, key, &constnum, constattno); if (!(i = AAgetequal(c_desc, key, tuple, &tid))) { if (i = AAam_delete(c_desc, &tid)) AAsyserr(11147, constid, i); if ((*tree_pred)(tuple)) del_tree(tkey, (*tree_field)(tuple)); *constid = '\0'; return; } else if (i != 1) AAsyserr(11148, i); /* bad constnum */ } /* ** DEST_TREE -- destroy a tree tuple with for a given treeid ** ** Deletes all tuples from tree with 'treeid' and previously set ** keys. ** ** Parameters: ** key -- tre key ** treeid -- integer treeid */ del_tree(key, treeid) struct tree *key; short treeid; { register int i; register int flag; struct tree tuple; struct tup_id lotid; struct tup_id hitid; extern DESC Treedes; # ifdef xZTR1 AAtTfp(13, 6, "DEL_TREE: treeid=%d\n", treeid); # endif AAam_setkey(&Treedes, key, &treeid, TREEID); if (i = AAam_find(&Treedes, EXACTKEY, &lotid, &hitid, key)) AAsyserr(11149, i, treeid); flag = 0; while (!(i = AAam_get(&Treedes, &lotid, &hitid, &tuple, TRUE))) { if (!AAkcompare(&Treedes, &tuple, key)) { if (i = AAam_delete(&Treedes, &lotid)) AAsyserr(11150, treeid, i); if (!flag) flag++; } } if (i != 1) AAsyserr(11151, i); if (!flag) AAsyserr(11152, treeid); if (i = AAam_flush_rel(&Treedes, FALSE)) AAsyserr(11153, i); } /* ** CHK_CONST -- check constraint catlg for tuples for a rel, and reset relatin.relstat ** ** Parameters: ** r_desc -- relation desc for de-constrained relation ** c_desc -- catalog desc ** key -- catalog key (here unknown size) ** tuple -- " tuple space " " " " " ** relid -- relation name ** id_attno -- attno of relid ** relowner -- relation owner ** own_attno -- relowner attno ** bit -- bits to reset in relstat if there are no constraints left ** ** Side Effects: ** reads catalog, maybe changes relstat field of AA_REL ** r_desc tuple */ chk_const(r_desc, c_desc, key, tuple, relid, id_attno, relowner, own_attno, bit) DESC *r_desc; DESC *c_desc; char *key; char *tuple; char *relid; int id_attno; char *relowner; int own_attno; int bit; { struct tup_id tid; register int i; # ifdef xZTR1 AAtTfp(13, 7, "CHK_CONST: relid %s id_attno %d relowner %s own_attno %d bit 0%o)\n", relid, id_attno, relowner, own_attno, bit); # endif AAam_clearkeys(c_desc); AAam_setkey(c_desc, key, relid, id_attno); AAam_setkey(c_desc, key, relowner, own_attno); if ((i = AAgetequal(c_desc, key, tuple, &tid)) == 1) r_relstat(r_desc, bit, 0); else if (i < 0) AAsyserr(11154, i); } /* ** R_RELSTAT -- set or reset bits in the relation.relstat field ** ** Does the above for relation described by desc. ** ** Parameters: ** desc -- relation to have relation.relstat field changed ** bit -- bits to set or reset ** action -- 0 reset, 1 set ** ** Side Effects: ** relation is opened for READ/WRITE, relstat changed */ r_relstat(desc, bit, action) DESC *desc; int bit; int action; { struct relation tuple; struct relation key; struct tup_id tid; register int i; extern DESC Reldes; register DESC *d; d = desc; # ifdef xZTR1 AAtTfp(13, 8, "R_RELSTAT: bit=0%o, action %d\n", bit, action); # endif opencatalog(AA_REL, 2); AAam_clearkeys(&Reldes); AAam_setkey(&Reldes, &key, d->reldum.relid, RELID); AAam_setkey(&Reldes, &key, d->reldum.relowner, RELOWNER); if (i = AAgetequal(&Reldes, &key, &tuple, &tid)) AAsyserr(11155, d->reldum.relid, d->reldum.relowner, i); if (action) { if (tuple.relstat == (i = tuple.relstat | bit)) return; tuple.relstat = i; } else { if (tuple.relstat == (i = tuple.relstat & ~bit)) return; tuple.relstat = i; } if ((i = AAam_replace(&Reldes, &tid, &tuple, 0)) < 0) AAsyserr(11156, i); if (i = AAam_flush_rel(&Reldes, FALSE)) AAsyserr(11157, i); } /* ** TREE_CONST -- True predicate ** ** Called indirectly by routines wishing to know if ** a integrity constraint has an associated tree tuple. ** As this is always the case, returns TRUE always. ** ** Parameters: ** i -- integrity tuple */ tree_const() { # ifdef xZTR1 AAtTfp(13, 9, "TREE_CONST\n"); # endif return (TRUE); } /* ** TREE_PROT -- Protection tuple tree predicate ** ** Called indirectly by routines wishing to know if ** a protection constraint has an associated tree tuple. ** ** Parameters: ** p -- protection tuple ** ** Returns: ** TRUE -- if p->protree != -1 ** FLASE -- otherwise */ tree_prot(p) struct protect *p; { # ifdef xZTR1 AAtTfp(13, 9, "TREE_PROT: p->protree=%d\n", p->protree); # endif if (p->protree == -1) return (FALSE); else return (TRUE); } /* ** PROT_PROTREE -- get protree field of a protection tuple ** ** Parameters: ** p -- protection tuple ** ** Returns: ** p->protree */ prot_protree(p) struct protect *p; { # ifdef xZTR1 AAtTfp(13, 9, "PROT_PROTREE: protree=%d\n", p->protree); # endif return (p->protree); } /* ** INT_INTTREE -- get inttree field of a integrity tuple ** ** Parameters: ** i -- integrity tuple ** ** Returns: ** i->inttree */ int_inttree(i) struct integrity *i; { # ifdef xZTR1 AAtTfp(13, 9, "INT_INTTREE: inttree=%d\n", i->inttree); # endif return (i->inttree); }