1: # include "../ingres.h" 2: # include "../aux.h" 3: # include "../pipes.h" 4: # include "../catalog.h" 5: # include "../tree.h" 6: # include "../symbol.h" 7: # include "qrymod.h" 8: 9: 10: /* 11: ** D_INTEG -- define integrity constraint 12: ** 13: ** An integrity constraint (as partially defined by the last 14: ** tree defined by d_tree) is defined. 15: ** 16: ** Parameters: 17: ** none 18: ** 19: ** Returns: 20: ** none 21: ** 22: ** Side Effects: 23: ** Activity in 'relation' and 'integrities' catalogs. 24: ** 25: ** Requires: 26: ** issueinvert -- to check if the qualification is 27: ** initially satisfied. 28: ** 29: ** Called By: 30: ** define 31: ** 32: ** Trace Flags: 33: ** 49 34: ** 35: ** Diagnostics: 36: ** 3490 -- there are aggregates in the qualification. 37: ** 3491 -- multivariable constraint. 38: ** 39: ** Syserrs: 40: ** On inconsistancies. 41: ** 42: ** History: 43: ** 2/19/79 (eric) -- broken off from define.c. 44: */ 45: 46: extern QTREE *Treeroot; 47: extern struct descriptor Intdes; 48: extern struct descriptor Reldes; 49: extern struct pipfrmt Pipe; 50: 51: 52: 53: d_integ() 54: { 55: register int i; 56: register QTREE *t; /* definition tree */ 57: struct integrity inttup; 58: struct tup_id tid; 59: register int rv; /* result variable */ 60: struct retcode *rc; 61: extern struct retcode *issueinvert(); 62: struct relation relkey; 63: struct relation reltup; 64: 65: t = Treeroot; 66: Treeroot = NULL; 67: rv = Resultvar; 68: 69: /* pipe is not used, clear it out */ 70: rdpipe(P_SYNC, &Pipe, R_up); 71: 72: /* 73: ** Check for valid environment. 74: ** The tree must exist, have a qualification, and have 75: ** no target list. The query mode must be mdDEFINE. 76: ** 77: ** User level stuff checks to see that this is single 78: ** variable aggregate free, since that's all we know 79: ** about thusfar. Also, the relation in question must 80: ** not be a view. 81: */ 82: 83: # ifdef xQTR3 84: if (t == NULL) 85: syserr("d_integ: NULL tree"); 86: if ((i = t->right->sym.type) != AND) 87: syserr("d_integ: qual %d", i); 88: if ((i = t->left->sym.type) != TREE) 89: syserr("d_integ: TL %d", i); 90: if (Qmode != mdDEFINE) 91: syserr("d_integ: Qmode %d", Qmode); 92: # endif 93: 94: /* check for aggregates */ 95: if (aggcheck(t)) 96: ferror(3490, -1, rv, 0); /* aggregates in qual */ 97: 98: /* check for multi-variable */ 99: for (i = 0; i < MAXVAR + 1; i++) 100: { 101: if (!Rangev[i].rused) 102: continue; 103: if (i != rv) 104: { 105: # ifdef xQTR3 106: if (tTf(49, 1)) 107: printf("d_integ: Rv %d(%.14s) i %d(%.14s)\n", 108: rv, Rangev[rv].relid, i, Rangev[i].relid); 109: # endif 110: ferror(3491, -1, rv, 0); /* too many vars */ 111: } 112: } 113: 114: /* check for the resultvariable being a real relation */ 115: if ((Rangev[rv].rstat & S_VIEW) != 0) 116: ferror(3493, -1, rv, 0); /* is a view */ 117: 118: /* guarantee that you own this relation */ 119: if (!bequal(Usercode, Rangev[rv].rowner, 2)) 120: ferror(3494, -1, rv, 0); /* don't own reln */ 121: 122: /* 123: ** Guarantee that the integrity constraint is true now. 124: ** This involves issuing a retrieve statement for the 125: ** inverse of the qualification. The target list is 126: ** already null, so we will get nothing printed out 127: ** (only a return status). 128: */ 129: 130: Qmode = mdRETR; 131: Resultvar = -1; 132: 133: /* issue the invert of the query */ 134: rc = issueinvert(t); 135: if (rc->rc_tupcount != 0) 136: ferror(3492, -1, rv, 0); /* constraint not satisfied */ 137: 138: /* 139: ** Set up the rest of the environment. 140: */ 141: 142: opencatalog("integrities", 2); 143: clr_tuple(&Intdes, &inttup); 144: Resultvar = -1; 145: Qmode = -1; 146: 147: /* 148: ** Set up integrity relation tuple. 149: ** The qualification will be scanned, and a set of 150: ** domains referenced will be created. Other stuff 151: ** is filled in from the range table and from the 152: ** parser. 153: ** 154: ** The tree is actually inserted into the tree catalog 155: ** in this step. Extra information is cleared here. 156: */ 157: 158: inttup.intresvar = rv; 159: bmove(Rangev[rv].relid, inttup.intrelid, MAXNAME); 160: bmove(Rangev[rv].rowner, inttup.intrelowner, 2); 161: makeidset(rv, t, inttup.intdomset); 162: inttup.inttree = puttree(t, inttup.intrelid, inttup.intrelowner, mdINTEG); 163: 164: /* 165: ** Insert tuple into integrity catalog. 166: */ 167: 168: i = insert(&Intdes, &tid, &inttup, FALSE); 169: if (i < 0) 170: syserr("d_integ: insert"); 171: if (noclose(&Intdes) != 0) 172: syserr("d_integ: noclose int"); 173: 174: /* 175: ** Update relstat S_INTEG bit. 176: */ 177: 178: if ((Rangev[rv].rstat & S_INTEG) == 0) 179: { 180: opencatalog("relation", 2); 181: setkey(&Reldes, &relkey, inttup.intrelid, RELID); 182: setkey(&Reldes, &relkey, inttup.intrelowner, RELOWNER); 183: i = getequal(&Reldes, &relkey, &reltup, &tid); 184: if (i != 0) 185: syserr("d_integ: geteq"); 186: reltup.relstat |= S_INTEG; 187: i = replace(&Reldes, &tid, &reltup, FALSE); 188: if (i != 0) 189: syserr("d_integ: replace"); 190: if (noclose(&Reldes) != 0) 191: syserr("d_integ: noclose rel"); 192: } 193: } 194: 195: 196: makeidset(varno, tree, dset) 197: int varno; 198: QTREE *tree; 199: int dset[8]; 200: { 201: register int vn; 202: register QTREE *t; 203: 204: vn = varno; 205: t = tree; 206: 207: while (t != NULL) 208: { 209: if (t->sym.type == VAR && ((struct qt_var *)t)->varno == vn) 210: lsetbit(((struct qt_var *)t)->attno, dset); 211: 212: /* handle left subtree recursively */ 213: makeidset(vn, t->left, dset); 214: 215: /* handle right subtree iteratively */ 216: t = t->right; 217: } 218: }