1: # include "../ingres.h" 2: # include "../aux.h" 3: # include "../catalog.h" 4: # include "../symbol.h" 5: # include "../tree.h" 6: # include "../pipes.h" 7: # include "ovqp.h" 8: # include "strategy.h" 9: 10: /** 11: ** STRATEGY 12: ** 13: ** Attempts to limit access scan to less than the entire Source 14: ** relation by finding a key which can be used for associative 15: ** access to the Source reln or an index thereon. The key is 16: ** constructed from domain-value specifications found in the 17: ** clauses of the qualification list using sub-routine findsimp 18: ** in findsimp.c and other subroutines in file key.c 19: **/ 20: 21: 22: 23: strategy() 24: { 25: register int i, allexact; 26: struct accessparam sourceparam, indexparam; 27: struct index itup, rtup; 28: struct key lowikey[MAXKEYS+1], highikey[MAXKEYS+1]; 29: register struct descriptor *d; 30: extern struct descriptor Inddes; 31: struct descriptor *openindex(); 32: 33: # ifdef xOTR1 34: if (tTf(31, 0)) 35: printf("STRATEGY\tSource=%.12s\tNewq = %d\n", Source ? Source->relid : "(none)", Newq); 36: # endif 37: 38: while (Newq) /* if Newq=TRUE then compute a new strategy */ 39: /* NOTE: This while loop is executed only once */ 40: { 41: Scanr = Source; 42: 43: if (!Scanr) 44: return (1); /* return immediately if there is no source relation */ 45: 46: Fmode = NOKEY; /* assume a find mode with no key */ 47: 48: if (!Qlist) 49: break; /* if no qualification then you must scan entire rel */ 50: 51: /* copy structure of source relation into sourceparam */ 52: paramd(Source, &sourceparam); 53: 54: /* if source is unkeyed and has no sec index then give up */ 55: if (sourceparam.mode == NOKEY && Source->relindxd <= 0) 56: break; 57: 58: /* find all simple clauses if any */ 59: if (!findsimps()) 60: break; /* break if there are no simple clauses */ 61: 62: /* Four steps are now performed to try and find a key. 63: ** First if the relation is hashed then an exact key is search for 64: ** 65: ** Second if there are secondary indexes, then a search is made 66: ** for an exact key. If that fails then a check is made for 67: ** a range key. The result of the rangekey check is saved. 68: ** 69: ** Third if the relation is an ISAM a check is made for 70: ** an exact key or a range key. 71: ** 72: ** Fourth if there is a secondary index, then if step two 73: ** found a key, that key is used. 74: ** 75: ** Lastly, give up and scan the entire relation 76: */ 77: 78: /* step one. Try to find exact key on primary */ 79: if (exactkey(&sourceparam, &Lkey_struct)) 80: { 81: Fmode = EXACTKEY; 82: break; 83: } 84: 85: /* step two. If there is an index, try to find an exactkey on one of them */ 86: if (Source->relindxd) 87: { 88: 89: opencatalog("indexes", 0); 90: setkey(&Inddes, &itup, Source->relid, IRELIDP); 91: setkey(&Inddes, &itup, Source->relowner, IOWNERP); 92: if (i = find(&Inddes, EXACTKEY, &Lotid, &Hitid, &itup)) 93: syserr("strategy:find indexes %d", i); 94: 95: while (!(i = get(&Inddes, &Lotid, &Hitid, &itup, NXTTUP))) 96: { 97: # ifdef xOTR1 98: if (tTf(31, 3)) 99: printup(&Inddes, &itup); 100: # endif 101: if (!bequal(itup.irelidp, Source->relid, MAXNAME) || 102: !bequal(itup.iownerp, Source->relowner, 2)) 103: continue; 104: parami(&itup, &indexparam); 105: if (exactkey(&indexparam, &Lkey_struct)) 106: { 107: Fmode = EXACTKEY; 108: d = openindex(itup.irelidi); 109: /* temp check for 6.0 index */ 110: if (d->relindxd == -1) 111: ov_err(BADSECINDX); 112: Scanr = d; 113: break; 114: } 115: if (Fmode == LRANGEKEY) 116: continue; /* a range key on a s.i. has already been found */ 117: if (allexact = rangekey(&indexparam, &lowikey, &highikey)) 118: { 119: bmove(&itup, &rtup, sizeof itup); /* save tuple */ 120: Fmode = LRANGEKEY; 121: } 122: } 123: if (i < 0) 124: syserr("stragery:bad get from index-rel %d", i); 125: /* If an exactkey on a secondary index was found, look no more. */ 126: if (Fmode == EXACTKEY) 127: break; 128: } 129: 130: 131: /* step three. Look for a range key on primary */ 132: if (i = rangekey(&sourceparam, &Lkey_struct, &Hkey_struct)) 133: { 134: if (i < 0) 135: Fmode = EXACTKEY; 136: else 137: Fmode = LRANGEKEY; 138: break; 139: } 140: 141: /* last step. If a secondary index range key was found, use it */ 142: if (Fmode == LRANGEKEY) 143: { 144: if (allexact < 0) 145: Fmode = EXACTKEY; 146: d = openindex(rtup.irelidi); 147: /* temp check for 6.0 index */ 148: if (d->relindxd == -1) 149: ov_err(BADSECINDX); 150: Scanr = d; 151: bmove(&lowikey, &Lkey_struct, sizeof lowikey); 152: bmove(&highikey, &Hkey_struct, sizeof highikey); 153: break; 154: } 155: 156: /* nothing will work. give up! */ 157: break; 158: 159: } 160: 161: /* check for Newq = FALSE and no source relation */ 162: if (!Scanr) 163: return (1); 164: /* 165: ** At this point the strategy is determined. 166: ** 167: ** If Fmode is EXACTKEY then Lkey_struct contains 168: ** the pointers to the keys. 169: ** 170: ** If Fmode is LRANGEKEY then Lkey_struct contains 171: ** the pointers to the low keys and Hkey_struct 172: ** contains pointers to the high keys. 173: ** 174: ** If Fmode is NOKEY, then a full scan will be performed 175: */ 176: # ifdef xOTR1 177: if (tTf(31, -1)) 178: printf("Fmode= %d\n",Fmode); 179: # endif 180: 181: /* set up the key tuples */ 182: if (Fmode != NOKEY) 183: { 184: if (setallkey(&Lkey_struct, Keyl)) 185: return (0); /* query false. There is a simple 186: ** clause which can never be satisfied. 187: ** These simple clauses can be choosey! 188: */ 189: } 190: 191: if (i = find(Scanr, Fmode, &Lotid, &Hitid, Keyl)) 192: syserr("strategy:find1 %.12s, %d", Scanr->relid, i); 193: 194: if (Fmode == LRANGEKEY) 195: { 196: setallkey(&Hkey_struct, Keyh); 197: if (i = find(Scanr, HRANGEKEY, &Lotid, &Hitid, Keyh)) 198: syserr("strategy:find2 %.12s, %d", Scanr->relid, i); 199: } 200: 201: # ifdef xOTR1 202: if (tTf(31, 1)) 203: { 204: printf("Lo"); 205: dumptid(&Lotid); 206: printf("Hi"); 207: dumptid(&Hitid); 208: } 209: # endif 210: 211: return (1); 212: }