1: # include <ingres.h> 2: # include <aux.h> 3: # include <catalog.h> 4: # include <tree.h> 5: # include <symbol.h> 6: # include <pv.h> 7: # include <resp.h> 8: # include <func.h> 9: # include "qrymod.h" 10: # include <sccs.h> 11: # include <errors.h> 12: 13: SCCSID(@(#)d_integ.c 8.3 2/8/85) 14: 15: 16: /* 17: ** D_INTEG -- define integrity constraint 18: ** 19: ** An integrity constraint (as partially defined by the last 20: ** tree defined by d_tree) is defined. 21: ** 22: ** Parameters: 23: ** none 24: ** 25: ** Returns: 26: ** none 27: ** 28: ** Side Effects: 29: ** Activity in 'relation' and 'integrities' catalogs. 30: ** 31: ** Trace Flags: 32: ** 49 33: */ 34: 35: extern DESC Intdes; 36: extern DESC Reldes; 37: 38: extern d_integ(), null_fn(); 39: extern short tTqm[80]; 40: 41: struct fn_def DefIntFn = 42: { 43: "DINTEG", 44: d_integ, 45: null_fn, 46: null_fn, 47: NULL, 48: 0, 49: tTqm, 50: 80, 51: 'Q', 52: 0 53: }; 54: 55: 56: 57: d_integ(pc, pv) 58: int pc; 59: PARM *pv; 60: { 61: register int i; 62: register QTREE *t; /* definition tree */ 63: struct integrity inttup; 64: struct tup_id tid; 65: register int rv; /* result variable */ 66: struct relation relkey; 67: struct relation reltup; 68: char relid[MAXNAME]; 69: char relowner[2]; 70: long relstat; 71: struct qthdr qt; 72: 73: if (pv[0].pv_type != PV_QTREE) 74: syserr("d_integ: tree"); 75: t = pv[0].pv_val.pv_qtree; 76: rv = Qt.qt_resvar; 77: 78: /* 79: ** Check for valid environment. 80: ** The tree must exist, have a qualification, and have 81: ** no target list. The query mode must be mdINTEG. 82: ** 83: ** User level stuff checks to see that this is single 84: ** variable aggregate free, since that's all we know 85: ** about thusfar. Also, the relation in question must 86: ** not be a view. 87: */ 88: 89: # ifdef xQTR3 90: if (t == NULL) 91: syserr("d_integ: NULL tree"); 92: if ((i = t->right->sym.type) != AND) 93: syserr("d_integ: qual %d", i); 94: if ((i = t->left->sym.type) != TREE) 95: syserr("d_integ: TL %d", i); 96: if (Qt.qt_qmode != mdINTEG) 97: syserr("d_integ: Qmode %d", Qt.qt_qmode); 98: # endif 99: 100: /* check for aggregates */ 101: if (aggcheck(t)) 102: qmerror(NOAGGINT, -1, rv, 0); /* aggregates in qual */ 103: 104: /* check for multi-variable */ 105: for (i = 0; i < MAXRANGE; i++) 106: { 107: if (Qt.qt_rangev[i].rngvdesc == NULL) 108: continue; 109: if (i != rv) 110: { 111: # ifdef xQTR3 112: if (tTf(49, 1)) 113: printf("d_integ: Rv %d(%.14s) i %d(%.14s)\n", 114: rv, Qt.qt_rangev[rv].rngvdesc->reldum.relid, 115: i, Qt.qt_rangev[i].rngvdesc->reldum.relid); 116: # endif 117: qmerror(NOMULTIVAR, -1, rv, 0); /* too many vars */ 118: } 119: } 120: 121: 122: /* check for the resultvariable being a real relation */ 123: if (bitset(S_VIEW, Qt.qt_rangev[rv].rngvdesc->reldum.relstat)) 124: qmerror(INTVIEW, -1, rv, 0); /* is a view */ 125: 126: /* guarantee that you own this relation */ 127: if (!bequal(Usercode, Qt.qt_rangev[rv].rngvdesc->reldum.relowner, UCODE_SZ)) 128: qmerror(MUSTOWN, -1, rv, 0); /* don't own reln */ 129: bmove(Qt.qt_rangev[rv].rngvdesc->reldum.relid, relid, MAXNAME); 130: bmove(Qt.qt_rangev[rv].rngvdesc->reldum.relowner, relowner, 2); 131: bmove(&Qt,&qt, sizeof (Qt)); 132: relstat = Qt.qt_rangev[rv].rngvdesc->reldum.relstat; 133: 134: /* 135: ** Guarantee that the integrity constraint is true now. 136: ** This involves issuing a retrieve statement for the 137: ** inverse of the qualification. The target list is 138: ** already null, so we will get nothing printed out 139: ** (only a return status). 140: ** 141: ** We reset resp_tups if ok so that the user isn't annoyed 142: ** by a tuple count. On error, it is a count of the 143: ** number of tuples that don't satisfy. 144: */ 145: 146: Qt.qt_qmode = mdRETR; 147: Qt.qt_resvar = -1; 148: 149: /* issue the invert of the query */ 150: issueinvert(t); 151: if (Resp.resp_tups != 0) 152: qmerror(INITCONST, -1, rv, 0); /* constraint not satisfied */ 153: Resp.resp_tups = -1; 154: bmove(&qt,&Qt, sizeof (Qt)); 155: 156: /* 157: ** Set up the rest of the environment. 158: */ 159: 160: opencatalog("integrities", OR_WRITE); 161: clr_tuple(&Intdes, &inttup); 162: Qt.qt_resvar = -1; 163: Qt.qt_qmode = -1; 164: 165: /* 166: ** Set up integrity relation tuple. 167: ** The qualification will be scanned, and a set of 168: ** domains referenced will be created. Other stuff 169: ** is filled in from the range table and from the 170: ** parser. 171: ** 172: ** The tree is actually inserted into the tree catalog 173: ** in this step. Extra information is cleared here. 174: */ 175: 176: inttup.intresvar = rv; 177: bmove(relid, inttup.intrelid, MAXNAME); 178: bmove(relowner, inttup.intrelowner, 2); 179: makeidset(rv, t, inttup.intdomset); 180: inttup.inttree = puttree(t, inttup.intrelid, inttup.intrelowner, mdINTEG); 181: 182: /* 183: ** Insert tuple into integrity catalog. 184: */ 185: 186: i = insert(&Intdes, &tid, &inttup, FALSE); 187: if (i < 0) 188: syserr("d_integ: insert"); 189: if (noclose(&Intdes) != 0) 190: syserr("d_integ: noclose int"); 191: 192: /* 193: ** Update relstat S_INTEG bit. 194: */ 195: 196: if (!bitset(S_INTEG, relstat)) 197: { 198: opencatalog("relation", OR_WRITE); 199: clearkeys(&Reldes); 200: setkey(&Reldes, &relkey, inttup.intrelid, RELID); 201: setkey(&Reldes, &relkey, inttup.intrelowner, RELOWNER); 202: i = getequal(&Reldes, &relkey, &reltup, &tid); 203: if (i != 0) 204: syserr("d_integ: geteq returns %d",i); 205: reltup.relstat |= S_INTEG; 206: i = replace(&Reldes, &tid, &reltup, FALSE); 207: if (i != 0) 208: syserr("d_integ: replace returns %d",i); 209: if (noclose(&Reldes) != 0) 210: syserr("d_integ: noclose rel"); 211: } 212: 213: return (0); 214: } 215: 216: 217: makeidset(varno, tree, dset) 218: int varno; 219: QTREE *tree; 220: int dset[8]; 221: { 222: register int vn; 223: register QTREE *t; 224: 225: vn = varno; 226: t = tree; 227: 228: while (t != NULL) 229: { 230: if (t->sym.type == VAR && t->sym.value.sym_var.varno == vn) 231: lsetbit(t->sym.value.sym_var.attno, dset); 232: 233: /* handle left subtree recursively */ 234: makeidset(vn, t->left, dset); 235: 236: /* handle right subtree iteratively */ 237: t = t->right; 238: } 239: }