1: # include "../ingres.h" 2: # include "../catalog.h" 3: # include "../symbol.h" 4: # include "../lock.h" 5: # include "../pipes.h" 6: # include "qrymod.h" 7: 8: /* 9: ** DEFINE -- define various types of qrymod constraints 10: ** 11: ** This module takes care of defining all the various types of 12: ** constraints that can be presented to qrymod. It makes sense 13: ** out of them by looking at the funcid in the pipe. They 14: ** correspond as follows: 15: ** 16: ** mdDEFINE -- a tree. This tree doesn't have any meaning yet; it is 17: ** just the raw tree. It must be immediately followed 18: ** by a type 1, 2, or three definition, which will link 19: ** that tree into some other catalog, thereby giving 20: ** it some sort of semantic meaning. 21: ** mdVIEW -- a view. This block has the view name in it. 22: ** mdPROT -- a protection constraint. 23: ** mdINTEG -- an integrity constraint. 24: ** 25: ** Defines: 26: ** define -- the driver: just calls one of the others. 27: ** d_tree -- read definition tree. 28: ** puttree -- write tree into tree catalog. 29: ** relntrwr -- the physical write routine for puttree. 30: ** 31: ** Requires: 32: ** Prodes -- ditto for protection relation. 33: ** Intdes -- ditto for integrities relation. 34: ** Treedes -- ditto for tree relation. 35: ** 36: ** Required By: 37: ** main 38: ** 39: ** History: 40: ** 2/19/79 (eric) -- split into four files. 41: ** 2/14/79 -- version 6.2, released. 42: */ 43: 44: 45: 46: 47: 48: QTREE *Treeroot; 49: /* 50: ** DEFINE -- define driver 51: ** 52: ** This function does very little exciting; in fact, it just 53: ** calls one of the other four functions to do the specific 54: ** funcid functions. 55: ** 56: ** Parameters: 57: ** func -- the function to perform: 58: ** mdDEFINE -- define tree (used by all). 59: ** mdVIEW -- define view. 60: ** mdPROT -- define protection constraint. 61: ** mdINTEG -- define integrity constraint. 62: ** 63: ** Returns: 64: ** none 65: ** 66: ** Side Effects: 67: ** none 68: ** 69: ** Requires: 70: ** d_tree 71: ** d_view 72: ** d_prot 73: ** d_integ 74: ** 75: ** Called By: 76: ** main 77: ** 78: ** Trace Flags: 79: ** none 80: ** 81: ** Diagnostics: 82: ** none 83: ** 84: ** Syserrs: 85: ** none 86: ** bad arg %c -- a bad argument was passed (not mdDEFINE, 87: ** mdVIEW, mdPROT, mdINTEG). 88: */ 89: 90: extern struct pipfrmt Pipe; 91: 92: 93: define(func) 94: char func; 95: { 96: switch (func) 97: { 98: case mdDEFINE: 99: d_tree(); 100: break; 101: 102: case mdVIEW: 103: d_view(); 104: break; 105: 106: case mdPROT: 107: d_prot(); 108: break; 109: 110: case mdINTEG: 111: d_integ(); 112: break; 113: 114: default: 115: syserr("define: bad arg %d", func); 116: } 117: } 118: /* 119: ** D_TREE -- insert tree into system catalogs 120: ** 121: ** This routine reads in and saves a tree for further use. 122: ** The root of this tree is saved in the global 'Treeroot'. 123: ** The tree will ultimately be written to the 'tree' catalog 124: ** using the 'puttree' routine. 125: ** 126: ** Parameters: 127: ** none 128: ** 129: ** Returns: 130: ** none 131: ** 132: ** Side Effects: 133: ** The input pipe is read and the tree found there 134: ** is built. A pointer to that tree is saved in 135: ** 'Treeroot'. Notice that 'Qbuf' and the range 136: ** table are clobbered. 137: ** 138: ** Requires: 139: ** pipetrrd(). 140: ** readqry(). 141: ** 142: ** Trace Flags: 143: ** 10 144: */ 145: 146: d_tree() 147: { 148: extern pipetrrd(); 149: QTREE *readqry(); 150: 151: Treeroot = readqry(&pipetrrd, TRUE); 152: rdpipe(P_SYNC, &Pipe, R_up); 153: # ifdef xQTR1 154: if (tTf(10, 0)) 155: treepr(Treeroot, "Treeroot"); 156: # endif 157: } 158: /* 159: ** PUTTREE -- put tree into 'tree' catalog 160: ** 161: ** The named tree is inserted into the 'tree' catalog. 162: ** 163: ** The algorithm is to lock up the entire catalog and try to 164: ** find the smallest unique id possible for the named relation. 165: ** 166: ** Parameters: 167: ** root -- the root of the tree to insert. 168: ** treerelid -- the relid of the relation for which 169: ** this tree applies. 170: ** treeowner -- the owner of the above relation. 171: ** treetype -- the type of this tree; uses the mdXXX 172: ** type (as mdPROT, mdINTEG, mdDISTR, etc.). 173: ** 174: ** Returns: 175: ** The treeid that was assigned to this tree. 176: ** 177: ** Side Effects: 178: ** The tree catalog gets locked, and information is 179: ** inserted. 180: ** 181: ** Requires: 182: ** Treedes -- a relation descriptor for the tree 183: ** catalog (also needed by gettrseg). 184: ** insert -- to insert tuples. 185: ** noclose -- to bring 'tree' up to date after mod. 186: ** writeqry -- to write the tree. 187: ** relntrwr -- to do the physical writes to the catalog. 188: ** getequal -- to test uniqueness of tree id's. 189: ** setrll -- to set the exclusive relation lock. 190: ** unlrl -- to unlock same. 191: ** 192: ** Called By: 193: ** d_view 194: ** d_integ 195: ** d_prot 196: ** 197: ** Trace Flags: 198: ** 10 199: ** 200: ** Diagnostics: 201: ** none 202: ** 203: */ 204: 205: puttree(root, treerelid, treeowner, treetype) 206: QTREE *root; 207: int treetype; 208: { 209: struct tree treekey; 210: struct tree treetup; 211: struct tup_id treetid; 212: register int i; 213: auto int treeid; 214: 215: opencatalog("tree", 2); 216: 217: /* 218: ** Find a unique tree identifier. 219: ** Lock the tree catalog, and scan until we find a 220: ** tuple which does not match. 221: */ 222: 223: setrll(A_SLP, Treedes.reltid, M_EXCL); 224: 225: setkey(&Treedes, &treekey, treerelid, TREERELID); 226: setkey(&Treedes, &treekey, treeowner, TREEOWNER); 227: setkey(&Treedes, &treekey, &treetype, TREETYPE); 228: for (treeid = 0;; treeid++) 229: { 230: setkey(&Treedes, &treekey, &treeid, TREEID); 231: i = getequal(&Treedes, &treekey, &treetup, &treetid); 232: if (i < 0) 233: syserr("d_tree: getequal"); 234: else if (i > 0) 235: break; 236: } 237: 238: /* 239: ** We have a unique tree id. 240: ** Insert the new tuple and the tree into the 241: ** tree catalog. 242: */ 243: 244: relntrwr(NULL, 0, treerelid, treeowner, treetype, treeid); 245: writeqry(root, &relntrwr); 246: relntrwr(NULL, 1); 247: 248: /* all inserted -- flush pages and unlock */ 249: if (noclose(&Treedes) != 0) 250: syserr("d_tree: noclose"); 251: unlrl(Treedes.reltid); 252: 253: return(treeid); 254: } 255: /* 256: ** RELNTRWR -- physical tree write to relation 257: ** 258: ** This is the routine called from writeqry to write trees 259: ** to the 'tree' relation (rather than the W_down pipe). 260: ** 261: ** It is assumed that the (treerelid, treeowner, treetype, 262: ** treeid) combination is unique in the tree catalog, and that 263: ** the tree catalog is locked. 264: ** 265: ** Parameters: 266: ** ptr -- a pointer to the data. If NULL, this is 267: ** a control call. 268: ** len -- the length of the data. If ptr == NULL, this 269: ** field is a control code: zero means 270: ** initialize (thus taking the next two param- 271: ** eters); one means flush. 272: ** treerelid -- the name of the relation for which this 273: ** tree applies (init only). 274: ** treeowner -- the owner of this relation (init only). 275: ** treetype -- on initialization, this tells what the 276: ** tree is used for. 277: ** treeid -- on initialization, this is the tree id we 278: ** want to use. 279: ** 280: ** Returns: 281: ** The number of bytes written ('len'). 282: ** 283: ** Side Effects: 284: ** Well, yes. Activity occurs in the tree catalog. 285: ** 286: ** Requires: 287: ** insert -- to insert tuples. 288: ** Treedes -- open for read/write. 289: ** 290: ** Trace Flags: 291: ** none 292: ** 293: ** Diagnostics: 294: ** none 295: */ 296: 297: relntrwr(ptr, len, treerelid, treeowner, treetype, treeid) 298: char *ptr; 299: int len; 300: char *treerelid; 301: char *treeowner; 302: int treetype; 303: int treeid; 304: { 305: static struct tree treetup; 306: struct tup_id treetid; 307: register char *p; 308: register int l; 309: static char *tptr; 310: 311: p = ptr; 312: l = len; 313: 314: /* check for special function */ 315: if (p == NULL) 316: { 317: switch (l) 318: { 319: case 0: 320: clr_tuple(&Treedes, &treetup); 321: bmove(treerelid, treetup.treerelid, MAXNAME); 322: bmove(treeowner, treetup.treeowner, 2); 323: treetup.treetype = treetype; 324: treetup.treeid = treeid; 325: tptr = treetup.treetree; 326: break; 327: 328: case 1: 329: if (tptr != treetup.treetree) 330: { 331: if (insert(&Treedes, &treetid, &treetup, FALSE) < 0) 332: syserr("relntrwr: insert 1"); 333: } 334: break; 335: 336: default: 337: syserr("relntrwr: ctl %d", l); 338: } 339: return; 340: } 341: 342: /* output bytes */ 343: while (l-- > 0) 344: { 345: *tptr++ = *p++; 346: 347: /* check for buffer overflow */ 348: if (tptr < &treetup.treetree[sizeof treetup.treetree]) 349: continue; 350: 351: /* yep, flush buffer to relation */ 352: if (insert(&Treedes, &treetid, &treetup, FALSE) < 0) 353: syserr("relntrwr: insert 2"); 354: treetup.treeseq++; 355: tptr = treetup.treetree; 356: 357: /* clear out the rest of the tuple for aesthetic reasons */ 358: *tptr = ' '; 359: bmove(tptr, tptr + 1, sizeof treetup.treetree - 1); 360: } 361: 362: return (len); 363: }