# include # include # include # include # include # include # include SCCSID(@(#)destroy.c 8.3 2/8/85) extern short tTdbu[]; extern int destroy(); extern int null_fn(); struct fn_def DstroyFn = { "DESTROY", destroy, null_fn, null_fn, NULL, 0, tTdbu, 100, 'Z', 0 }; /* ** DESTROY RELATION ** ** The relations in pv are destroyed. This involves three steps: ** 1 - remove tuple from relation relation ** 2 - remove tuples from attribute relation ** 3 - unlink physical file ** ** If the relation is a secondary index, the entry is removed ** from the index relation, and the primary relation is set to ** be "not indexed" (unless there is another index on it). ** ** If the relation has an index, all its indexes are also ** destroyed. ** ** If any errors occured while destroying the relations, ** then the last error number is returned, otherwise ** 0 is returned. ** ** If any query modification was defined on the relation, ** the qrymod catalogues are updated. ** ** Trace Flags: ** 32 */ destroy(pc, pv) int pc; PARM *pv; { register int i, ret; register char *name; opencatalog("relation", OR_WRITE); opencatalog("attribute", OR_WRITE); for (ret = 0; pc-- > 0; ) { name = ((pv++)->pv_val).pv_str; if (i = des(name)) ret = i; } return (ret); } des(name) char *name; { register int i; register char *relname; struct tup_id tid; char newrelname[MAXNAME + 3]; extern DESC Reldes, Attdes, Inddes, Treedes; struct relation relt, relk; relname = name; # ifdef xZTR1 tTfp(32, -1, "destroy: %s\n", relname); # endif newrelname[MAXNAME + 2] = 0; /* get the tuple from relation relation */ setkey(&Reldes, &relk, relname, RELID); setkey(&Reldes, &relk, Usercode, RELOWNER); if ((i = getequal(&Reldes, &relk, &relt, &tid)) != 0) { if (i < 0) syserr("DESTROY: geteq(rel/%s) %d", relname, i); return (nferror(RELNOEXIST, relname, 0)); /* nonexistant relation */ } /* don't allow a system relation to be destroyed */ if (relt.relstat & S_CATALOG) return (nferror(NODESTSYSREL, relname, 0)); /* attempt to destroy system catalog */ if ((i = delete(&Reldes, &tid)) != 0) syserr("DESTROY: delete(rel) %d", i); /* ** for concurrency reasons, flush the relation-relation page ** where the tuple was just deleted. This will prevent anyone ** from being able to "openr" the relation while it is being ** destroyed. It also allows recovery to finish the destroy ** it the system crashes during this destroy. */ if (i = flush_rel(&Reldes, FALSE)) syserr("destroy:flush rel %d", i); purgetup(&Attdes, relt.relid, ATTRELID, relt.relowner, ATTOWNER, 0); /* ** If this is a user relation, then additional processing ** might be needed to clean up indicies, protection constraints ** etc. */ if ((relt.relstat & S_CATALOG) == 0) userdestroy(&relt); if ((relt.relstat & S_VIEW) == 0) { ingresname(relname, Usercode, newrelname); if (unlink(newrelname) < 0) syserr("destroy: unlink(%.14s)", newrelname); } return (0); }