# include "../ingres.h" # include "../catalog.h" # include "../symbol.h" # include "../lock.h" # include "../pipes.h" # include "qrymod.h" /* ** DEFINE -- define various types of qrymod constraints ** ** This module takes care of defining all the various types of ** constraints that can be presented to qrymod. It makes sense ** out of them by looking at the funcid in the pipe. They ** correspond as follows: ** ** mdDEFINE -- a tree. This tree doesn't have any meaning yet; it is ** just the raw tree. It must be immediately followed ** by a type 1, 2, or three definition, which will link ** that tree into some other catalog, thereby giving ** it some sort of semantic meaning. ** mdVIEW -- a view. This block has the view name in it. ** mdPROT -- a protection constraint. ** mdINTEG -- an integrity constraint. ** ** Defines: ** define -- the driver: just calls one of the others. ** d_tree -- read definition tree. ** puttree -- write tree into tree catalog. ** relntrwr -- the physical write routine for puttree. ** ** Requires: ** Prodes -- ditto for protection relation. ** Intdes -- ditto for integrities relation. ** Treedes -- ditto for tree relation. ** ** Required By: ** main ** ** History: ** 2/19/79 (eric) -- split into four files. ** 2/14/79 -- version 6.2, released. */ QTREE *Treeroot; /* ** DEFINE -- define driver ** ** This function does very little exciting; in fact, it just ** calls one of the other four functions to do the specific ** funcid functions. ** ** Parameters: ** func -- the function to perform: ** mdDEFINE -- define tree (used by all). ** mdVIEW -- define view. ** mdPROT -- define protection constraint. ** mdINTEG -- define integrity constraint. ** ** Returns: ** none ** ** Side Effects: ** none ** ** Requires: ** d_tree ** d_view ** d_prot ** d_integ ** ** Called By: ** main ** ** Trace Flags: ** none ** ** Diagnostics: ** none ** ** Syserrs: ** none ** bad arg %c -- a bad argument was passed (not mdDEFINE, ** mdVIEW, mdPROT, mdINTEG). */ extern struct pipfrmt Pipe; define(func) char func; { switch (func) { case mdDEFINE: d_tree(); break; case mdVIEW: d_view(); break; case mdPROT: d_prot(); break; case mdINTEG: d_integ(); break; default: syserr("define: bad arg %d", func); } } /* ** D_TREE -- insert tree into system catalogs ** ** This routine reads in and saves a tree for further use. ** The root of this tree is saved in the global 'Treeroot'. ** The tree will ultimately be written to the 'tree' catalog ** using the 'puttree' routine. ** ** Parameters: ** none ** ** Returns: ** none ** ** Side Effects: ** The input pipe is read and the tree found there ** is built. A pointer to that tree is saved in ** 'Treeroot'. Notice that 'Qbuf' and the range ** table are clobbered. ** ** Requires: ** pipetrrd(). ** readqry(). ** ** Trace Flags: ** 10 */ d_tree() { extern pipetrrd(); QTREE *readqry(); Treeroot = readqry(&pipetrrd, TRUE); rdpipe(P_SYNC, &Pipe, R_up); # ifdef xQTR1 if (tTf(10, 0)) treepr(Treeroot, "Treeroot"); # endif } /* ** PUTTREE -- put tree into 'tree' catalog ** ** The named tree is inserted into the 'tree' catalog. ** ** The algorithm is to lock up the entire catalog and try to ** find the smallest unique id possible for the named relation. ** ** Parameters: ** root -- the root of the tree to insert. ** treerelid -- the relid of the relation for which ** this tree applies. ** treeowner -- the owner of the above relation. ** treetype -- the type of this tree; uses the mdXXX ** type (as mdPROT, mdINTEG, mdDISTR, etc.). ** ** Returns: ** The treeid that was assigned to this tree. ** ** Side Effects: ** The tree catalog gets locked, and information is ** inserted. ** ** Requires: ** Treedes -- a relation descriptor for the tree ** catalog (also needed by gettrseg). ** insert -- to insert tuples. ** noclose -- to bring 'tree' up to date after mod. ** writeqry -- to write the tree. ** relntrwr -- to do the physical writes to the catalog. ** getequal -- to test uniqueness of tree id's. ** setrll -- to set the exclusive relation lock. ** unlrl -- to unlock same. ** ** Called By: ** d_view ** d_integ ** d_prot ** ** Trace Flags: ** 10 ** ** Diagnostics: ** none ** */ puttree(root, treerelid, treeowner, treetype) QTREE *root; int treetype; { struct tree treekey; struct tree treetup; struct tup_id treetid; register int i; auto int treeid; opencatalog("tree", 2); /* ** Find a unique tree identifier. ** Lock the tree catalog, and scan until we find a ** tuple which does not match. */ setrll(A_SLP, Treedes.reltid, M_EXCL); setkey(&Treedes, &treekey, treerelid, TREERELID); setkey(&Treedes, &treekey, treeowner, TREEOWNER); setkey(&Treedes, &treekey, &treetype, TREETYPE); for (treeid = 0;; treeid++) { setkey(&Treedes, &treekey, &treeid, TREEID); i = getequal(&Treedes, &treekey, &treetup, &treetid); if (i < 0) syserr("d_tree: getequal"); else if (i > 0) break; } /* ** We have a unique tree id. ** Insert the new tuple and the tree into the ** tree catalog. */ relntrwr(NULL, 0, treerelid, treeowner, treetype, treeid); writeqry(root, &relntrwr); relntrwr(NULL, 1); /* all inserted -- flush pages and unlock */ if (noclose(&Treedes) != 0) syserr("d_tree: noclose"); unlrl(Treedes.reltid); return(treeid); } /* ** RELNTRWR -- physical tree write to relation ** ** This is the routine called from writeqry to write trees ** to the 'tree' relation (rather than the W_down pipe). ** ** It is assumed that the (treerelid, treeowner, treetype, ** treeid) combination is unique in the tree catalog, and that ** the tree catalog is locked. ** ** Parameters: ** ptr -- a pointer to the data. If NULL, this is ** a control call. ** len -- the length of the data. If ptr == NULL, this ** field is a control code: zero means ** initialize (thus taking the next two param- ** eters); one means flush. ** treerelid -- the name of the relation for which this ** tree applies (init only). ** treeowner -- the owner of this relation (init only). ** treetype -- on initialization, this tells what the ** tree is used for. ** treeid -- on initialization, this is the tree id we ** want to use. ** ** Returns: ** The number of bytes written ('len'). ** ** Side Effects: ** Well, yes. Activity occurs in the tree catalog. ** ** Requires: ** insert -- to insert tuples. ** Treedes -- open for read/write. ** ** Trace Flags: ** none ** ** Diagnostics: ** none */ relntrwr(ptr, len, treerelid, treeowner, treetype, treeid) char *ptr; int len; char *treerelid; char *treeowner; int treetype; int treeid; { static struct tree treetup; struct tup_id treetid; register char *p; register int l; static char *tptr; p = ptr; l = len; /* check for special function */ if (p == NULL) { switch (l) { case 0: clr_tuple(&Treedes, &treetup); bmove(treerelid, treetup.treerelid, MAXNAME); bmove(treeowner, treetup.treeowner, 2); treetup.treetype = treetype; treetup.treeid = treeid; tptr = treetup.treetree; break; case 1: if (tptr != treetup.treetree) { if (insert(&Treedes, &treetid, &treetup, FALSE) < 0) syserr("relntrwr: insert 1"); } break; default: syserr("relntrwr: ctl %d", l); } return; } /* output bytes */ while (l-- > 0) { *tptr++ = *p++; /* check for buffer overflow */ if (tptr < &treetup.treetree[sizeof treetup.treetree]) continue; /* yep, flush buffer to relation */ if (insert(&Treedes, &treetid, &treetup, FALSE) < 0) syserr("relntrwr: insert 2"); treetup.treeseq++; tptr = treetup.treetree; /* clear out the rest of the tuple for aesthetic reasons */ *tptr = ' '; bmove(tptr, tptr + 1, sizeof treetup.treetree - 1); } return (len); }