|
|
1.1 root 1: # include <ingres.h>
2: # include <aux.h>
3: # include <catalog.h>
4: # include <symbol.h>
5: # include <tree.h>
6: # include "../decomp/globs.h"
7: # include "strategy.h"
8: # include <btree.h>
9: # include <sccs.h>
10: # include <errors.h>
11:
12: SCCSID(@(#)strategy.c 8.4 2/8/85)
13:
14: /*
15: ** STRATEGY
16: **
17: ** Attempts to limit access scan to less than the entire De.ov_source
18: ** relation by finding a key which can be used for associative
19: ** access to the De.ov_source reln or an index thereon. The key is
20: ** constructed from domain-value specifications found in the
21: ** clauses of the qualification list using sub-routine findsimp
22: ** in findsimp.c and other subroutines in file key.c
23: */
24:
25: strategy()
26: {
27: register int i, j, allexact;
28: struct accessparam sourceparm, indexparm;
29: struct index itup, rtup;
30: struct key lowikey[MAXKEYS+1], highikey[MAXKEYS+1];
31: struct key lowbkey[MAXKEYS+1], highbkey[MAXKEYS+1];
32: register DESC *d;
33: DESC *openindex();
34: extern DESC Inddes;
35: char *tp;
36: long l_lid[MAXLID], h_lid[MAXLID];
37: int keytype;
38: long last_lid();
39: long page, l, t;
40: int lidsize;
41: struct locator tidloc;
42: extern int Btree_fd;
43:
44: # ifdef xOTR1
45: if (tTf(70, 0))
46: printf("STRATEGY\tSource=%.12s\tNewq = %d\n",
47: De.ov_source ? De.ov_source->reldum.relid : "(none)",
48: De.de_newq);
49: # endif
50:
51: while (De.de_newq) /* if De.de_newq=TRUE then compute a new strategy */
52: /* NOTE: This while loop is executed only once */
53: {
54: De.ov_scanr = De.ov_source;
55:
56: if (!De.ov_scanr)
57: return (1); /* return immediately if there is no source relation */
58:
59: De.ov_fmode = NOKEY; /* assume a find mode with no key */
60:
61: if (!De.ov_qlist)
62: break; /* if no qualification then you must scan entire rel */
63: /*
64: ** Here we check for the special condition
65: ** of a where clause consisting only of a tid.
66: */
67: if (tid_only_test())
68: return(1);
69:
70: /* copy structure of source relation into sourceparm */
71: paramd(De.ov_source, &sourceparm);
72:
73: /* if source is unkeyed and has no sec index then give up */
74: if (sourceparm.mode == NOKEY && De.ov_source->reldum.relindxd <= 0 && !De.ov_source->reldum.reldim)
75: break;
76:
77: /* find all simple clauses if any */
78: if (!findsimps())
79: break; /* break if there are no simple clauses */
80:
81: /* Four steps are now performed to try and find a key.
82: ** First if the relation is hashed then an exact key is search for
83: **
84: ** Second if there are secondary indexes, then a search is made
85: ** for an exact key. If that fails then a check is made for
86: ** a range key. The result of the rangekey check is saved.
87: **
88: ** A step to check for possible use of Btrees is made here,
89: ** although in actuality, an exact btreekey search is used
90: ** after an exact range key search but before a range key search.
91: ** A BTree range search is used only as a last alternative
92: ** to a no key search.
93: **
94: ** Third if the relation is an ISAM a check is made for
95: ** an exact key or a range key.
96: **
97: ** Fourth if there is a secondary index, then if step two
98: ** found a key, that key is used.
99: **
100: ** Lastly, give up and scan the entire relation
101: */
102:
103: /* step one. Try to find exact key on primary */
104: if (exactkey(&sourceparm, De.ov_lkey_struct))
105: {
106: De.ov_fmode = EXACTKEY;
107: break;
108: }
109:
110: /* step two. If there is an index, try to find an exactkey on one of them */
111: if (De.ov_source->reldum.relindxd > 0)
112: {
113:
114: opencatalog("indexes", OR_READ);
115: setkey(&Inddes, &itup, De.ov_source->reldum.relid, IRELIDP);
116: setkey(&Inddes, &itup, De.ov_source->reldum.relowner, IOWNERP);
117: if (i = find(&Inddes, EXACTKEY, &De.ov_lotid, &De.ov_hitid, (char *)&itup))
118: syserr("strategy:find indexes %d", i);
119:
120: while (!(i = get(&Inddes, &De.ov_lotid, &De.ov_hitid, (char *)&itup, NXTTUP)))
121: {
122: # ifdef xOTR1
123: if (tTf(70, 3))
124: printup(&Inddes, (char *)&itup);
125: # endif
126: if (!bequal(itup.irelidp, De.ov_source->reldum.relid, MAXNAME) ||
127: !bequal(itup.iownerp, De.ov_source->reldum.relowner, 2))
128: continue;
129: parami(&itup, &indexparm);
130: if (exactkey(&indexparm, De.ov_lkey_struct))
131: {
132: De.ov_fmode = EXACTKEY;
133: d = openindex(itup.irelidi);
134: /* temp check for 6.0 index */
135: if ((int) d->reldum.relindxd == -1)
136: ov_err(BADSECINDX);
137: De.ov_scanr = d;
138: break;
139: }
140: if (De.ov_fmode == LRANGEKEY)
141: continue; /* a range key on a s.i. has already been found */
142: if (allexact = rangekey(&indexparm, lowikey, highikey))
143: {
144: bmove((char *)&itup, (char *)&rtup, sizeof itup); /* save tuple */
145: De.ov_fmode = LRANGEKEY;
146: }
147: }
148: if (i < 0)
149: syserr("stragery:bad get from index-rel %d", i);
150: /* If an exactkey on a secondary index was found, look no more. */
151: if (De.ov_fmode == EXACTKEY)
152: break;
153: }
154:
155: /* attempt to use Btree in aiding search */
156: if (i = btreekey(lowbkey, highbkey))
157: {
158: if (i > 0)
159: De.ov_fmode = BTREEKEY;
160: else if (De.ov_fmode != LRANGEKEY)
161: /* use range key search over btree range search */
162: {
163: keytype = i;
164: De.ov_fmode = BTREERANGE;
165: }
166: }
167:
168: /* step three. Look for a range key on primary */
169: if (i = rangekey(&sourceparm, De.ov_lkey_struct, De.ov_hkey_struct))
170: {
171: if (i < 0)
172: De.ov_fmode = EXACTKEY;
173: else if (De.ov_fmode == BTREEKEY)
174: /* use exact btree search over range search */
175: {
176: bmove((char *) lowbkey, (char *) De.ov_lkey_struct, sizeof lowbkey);
177: bmove((char *) highbkey, (char *) De.ov_hkey_struct, sizeof highbkey);
178: }
179: else
180: De.ov_fmode = LRANGEKEY;
181: break;
182: }
183:
184: if (De.ov_fmode == BTREEKEY)
185: {
186: bmove((char *) lowbkey, (char *) De.ov_lkey_struct, sizeof lowbkey);
187: bmove((char *) highbkey, (char *) De.ov_hkey_struct, sizeof highbkey);
188: break;
189: }
190:
191: /* last step. If a secondary index range key was found, use it */
192: if (De.ov_fmode == LRANGEKEY)
193: {
194: if (allexact < 0)
195: De.ov_fmode = EXACTKEY;
196: d = openindex(rtup.irelidi);
197: /* temp check for 6.0 index */
198: if ((int) d->reldum.relindxd == -1)
199: ov_err(BADSECINDX);
200: De.ov_scanr = d;
201: bmove((char *)lowikey, (char *)De.ov_lkey_struct, sizeof lowikey);
202: bmove((char *)highikey, (char *)De.ov_hkey_struct, sizeof highikey);
203: break;
204: }
205:
206: /* nothing will work. give up! */
207: break;
208:
209: }
210:
211: /* check for De.de_newq = FALSE and no source relation */
212: if (!De.ov_scanr)
213: return (1);
214: /*
215: ** At this point the strategy is determined.
216: **
217: ** If De.ov_fmode is EXACTKEY then De.ov_lkey_struct contains
218: ** the pointers to the keys.
219: **
220: ** If De.ov_fmode is LRANGEKEY then De.ov_lkey_struct contains
221: ** the pointers to the low keys and De.ov_hkey_struct
222: ** contains pointers to the high keys.
223: **
224: ** If De.ov_fmode is BTREEKEY then De.ov_lkey_struct contains
225: ** pointers to the key lid.
226: **
227: ** If De.ov_fmode is BTREERANGE then lowbkey contains pointers
228: ** to the low key lid and highbkey contains pointers to the
229: ** high key lid.
230: **
231: ** If De.ov_fmode is NOKEY, then a full scan will be performed
232: */
233: # ifdef xOTR1
234: if (tTf(70, -1))
235: printf("De.ov_fmode= %d\n",De.ov_fmode);
236: # endif
237:
238: if (De.ov_fmode == BTREERANGE)
239: /* requires special type of search to limit tid scan */
240: {
241: for (i = 0; i < De.ov_scanr->reldum.reldim; ++i)
242: {
243: l_lid[i] = 0;
244: h_lid[i] = 0;
245: }
246: lidsize = LIDSIZE * De.ov_scanr->reldum.reldim;
247: /* get low lids */
248: if (keytype == -1 || keytype == -3)
249: {
250: tp = De.ov_keyl + De.ov_scanr->reldum.relwid - lidsize;
251: bmove(l_lid, tp, lidsize);
252: setallkey(lowbkey, De.ov_keyl);
253: bmove(tp, l_lid, lidsize);
254: }
255: /* get high lids */
256: if (keytype == -2 || keytype == -3)
257: {
258: tp = De.ov_keyh + De.ov_scanr->reldum.relwid - lidsize;
259: bmove(h_lid, tp, lidsize);
260: setallkey(highbkey, De.ov_keyh);
261: bmove(tp, h_lid, lidsize);
262: }
263: Btree_fd = De.ov_scanr->btree_fd;
264: /* scan through lids to fill in unprovided lids and to check
265: ** for lids that are too big
266: */
267: page = RT;
268: for (i = 0; i < De.ov_scanr->reldum.reldim; ++i)
269: {
270: if (l_lid[i] <= 0)
271: l_lid[i] = 1;
272: l = last_lid(page) - 1;
273: if (h_lid < 0)
274: return(0);
275: if (!h_lid[i] || h_lid[i] > l)
276: h_lid[i] = l;
277: if ((t = get_tid(page, h_lid[i], &tidloc)) < 0)
278: syserr("bad gettid in strategy, lid = %ld\n", h_lid[i]);
279: page = t;
280: }
281: /* check whether lo > hi */
282: for (i = 0; i < De.ov_scanr->reldum.reldim; ++i)
283: if (l_lid[i] < h_lid[i])
284: break;
285: else if (l_lid[i] > h_lid[i])
286: return(0);
287: # ifdef xOTR1
288: if (tTf(70,0))
289: for (i = 0 ; i < De.ov_scanr->reldum.reldim; ++i)
290: printf("hi = %ld, lo = %ld\n", h_lid[i], l_lid[i]);
291: # endif
292: /* find the smallest and largest possible tids of the lids
293: ** within the provided range */
294: btreerange(De.ov_scanr, l_lid, h_lid, &De.ov_lotid, &De.ov_hitid);
295: }
296: else
297: {
298: /* set up the key tuples */
299: if (De.ov_fmode != NOKEY)
300: {
301: if (setallkey(De.ov_lkey_struct, De.ov_keyl))
302: return (0); /* query false. There is a simple
303: ** clause which can never be satisfied.
304: ** These simple clauses can be choosey!
305: */
306: }
307:
308: if (i = find(De.ov_scanr, De.ov_fmode, &De.ov_lotid, &De.ov_hitid, De.ov_keyl))
309: syserr("strategy:find1 %.12s, %d", De.ov_scanr->reldum.relid, i);
310:
311: if (De.ov_fmode == LRANGEKEY)
312: {
313: setallkey(De.ov_hkey_struct, De.ov_keyh);
314: if (i = find(De.ov_scanr, HRANGEKEY, &De.ov_lotid, &De.ov_hitid, De.ov_keyh))
315: syserr("strategy:find2 %.12s, %d", De.ov_scanr->reldum.relid, i);
316: }
317: }
318:
319: # ifdef xOTR1
320: if (tTf(70, 1))
321: {
322: printf("Lo");
323: dumptid(&De.ov_lotid);
324: printf("Hi");
325: dumptid(&De.ov_hitid);
326: }
327: # endif
328:
329: return (1);
330: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.