/* ** STRATEGY ** ** Attempts to limit access scan to less than the entire De.ov_source ** relation by finding a key which can be used for associative ** access to the De.ov_source reln or an index thereon. The key is ** constructed from domain-value specifications found in the ** clauses of the qualification list using sub-routine findsimp ** in findsimp.c and other subroutines in file key.c */ int strategy(void) { register int i, allexact; acc_param_t sourceparm, indexparm; index_t itup, rtup; key_t lowikey[MAX_2ND_KEYS+1], highikey[MAX_2ND_KEYS+1]; key_t lowbkey[MAX_2ND_KEYS+1], highbkey[MAX_2ND_KEYS+1]; register desc_t *d; extern desc_t Inddes; char *tp; long l_lid[MAXLID], h_lid[MAXLID]; int keytype; long page, l, t; int lidsize; locator_t tidloc; keytype = allexact = 0; #ifdef xOTR1 if (tTf(70, 0)) printf("STRATEGY\tSource=%.12s\tNewq = %d\n", De.ov_source ? De.ov_source->d_r.r_id : "(none)", De.de_newq); #endif while (De.de_newq) /* if De.de_newq=TRUE then compute a new strategy */ /* NOTE: This while loop is executed only once */ { De.ov_scanr = De.ov_source; if (!De.ov_scanr) return (1); /* return immediately if there is no source relation */ De.ov_fmode = NOKEY; /* assume a find mode with no key */ if (!De.ov_qlist) break; /* if no qualification then you must scan entire rel */ /* ** Here we check for the special condition ** of a where clause consisting only of a tid. */ if (tid_only_test()) return(1); /* copy structure of source relation into sourceparm */ paramd(De.ov_source, &sourceparm); /* if source is unkeyed and has no sec index then give up */ if (sourceparm.mode == NOKEY && De.ov_source->d_r.r_indexed <= 0 && !De.ov_source->d_r.r_dim) break; /* find all simple clauses if any */ if (!findsimps()) break; /* break if there are no simple clauses */ /* Four steps are now performed to try and find a key. ** First if the relation is hashed then an exact key is search for ** ** Second if there are secondary indices, then a search is made ** for an exact key. If that fails then a check is made for ** a range key. The result of the rangekey check is saved. ** ** A step to check for possible use of Btrees is made here, ** although in actuality, an exact btreekey search is used ** after an exact range key search but before a range key search. ** A BTree range search is used only as a last alternative ** to a no key search. ** ** Third if the relation is an ISAM a check is made for ** an exact key or a range key. ** ** Fourth if there is a secondary index, then if step two ** found a key, that key is used. ** ** Lastly, give up and scan the entire relation */ /* step one. Try to find exact key on primary */ if (exactkey(&sourceparm, De.ov_lkey_struct)) { De.ov_fmode = EXACTKEY; break; } /* step two. If there is an index, try to find an exactkey on one of them */ if (De.ov_source->d_r.r_indexed > 0) { opencatalog("indices", OR_READ); ingres_setkey(&Inddes, &itup, De.ov_source->d_r.r_id, IRELIDP); ingres_setkey(&Inddes, &itup, De.ov_source->d_r.r_owner, IOWNERP); if ((i = find(&Inddes, EXACTKEY, &De.ov_lotid, &De.ov_hitid, (char *)&itup)) != 0) syserr("strategy:find indices %d", i); while (!(i = get(&Inddes, &De.ov_lotid, &De.ov_hitid, (char *)&itup, NXTTUP))) { #ifdef xOTR1 if (tTf(70, 3)) printup(&Inddes, (char *)&itup); #endif if (!bequal(itup.i_relname, De.ov_source->d_r.r_id, MAX_NAME_SIZE) || !bequal(itup.i_owner, De.ov_source->d_r.r_owner, 2)) continue; parami(&itup, &indexparm); if (exactkey(&indexparm, De.ov_lkey_struct)) { De.ov_fmode = EXACTKEY; d = openindex(itup.i_index); /* temp check for 6.0 index */ if ((int) d->d_r.r_indexed == -1) ov_err(BADSECINDX); De.ov_scanr = d; break; } if (De.ov_fmode == LRANGEKEY) continue; /* a range key on a s.i. has already been found */ if ((allexact = rangekey(&indexparm, lowikey, highikey)) != 0) { bmove((char *)&itup, (char *)&rtup, sizeof(itup)); /* save tuple */ De.ov_fmode = LRANGEKEY; } } if (i < 0) syserr("stragery:bad get from index-rel %d", i); /* If an exactkey on a secondary index was found, look no more. */ if (De.ov_fmode == EXACTKEY) break; } /* attempt to use Btree in aiding search */ if ((i = btreekey(lowbkey, highbkey)) != 0) { if (i > 0) De.ov_fmode = BTREEKEY; else if (De.ov_fmode != LRANGEKEY) { /* use range key search over btree range search */ keytype = i; De.ov_fmode = BTREERANGE; } } /* step three. Look for a range key on primary */ if ((i = rangekey(&sourceparm, De.ov_lkey_struct, De.ov_hkey_struct)) != 0) { if (i < 0) De.ov_fmode = EXACTKEY; else if (De.ov_fmode == BTREEKEY) { /* use exact btree search over range search */ bmove((char *) lowbkey, (char *) De.ov_lkey_struct, sizeof(lowbkey)); bmove((char *) highbkey, (char *) De.ov_hkey_struct, sizeof(highbkey)); } else De.ov_fmode = LRANGEKEY; break; } if (De.ov_fmode == BTREEKEY) { bmove((char *) lowbkey, (char *) De.ov_lkey_struct, sizeof(lowbkey)); bmove((char *) highbkey, (char *) De.ov_hkey_struct, sizeof(highbkey)); break; } /* last step. If a secondary index range key was found, use it */ if (De.ov_fmode == LRANGEKEY) { if (allexact < 0) De.ov_fmode = EXACTKEY; d = openindex(rtup.i_index); /* temp check for 6.0 index */ if ((int) d->d_r.r_indexed == -1) ov_err(BADSECINDX); De.ov_scanr = d; bmove((char *)lowikey, (char *)De.ov_lkey_struct, sizeof(lowikey)); bmove((char *)highikey, (char *)De.ov_hkey_struct, sizeof(highikey)); break; } /* nothing will work. give up! */ break; } /* check for De.de_newq = FALSE and no source relation */ if (!De.ov_scanr) return (1); /* ** At this point the strategy is determined. ** ** If De.ov_fmode is EXACTKEY then De.ov_lkey_struct contains ** the pointers to the keys. ** ** If De.ov_fmode is LRANGEKEY then De.ov_lkey_struct contains ** the pointers to the low keys and De.ov_hkey_struct ** contains pointers to the high keys. ** ** If De.ov_fmode is BTREEKEY then De.ov_lkey_struct contains ** pointers to the key lid. ** ** If De.ov_fmode is BTREERANGE then lowbkey contains pointers ** to the low key lid and highbkey contains pointers to the ** high key lid. ** ** If De.ov_fmode is NOKEY, then a full scan will be performed */ #ifdef xOTR1 if (tTf(70, -1)) printf("De.ov_fmode= %d\n",De.ov_fmode); #endif if (De.ov_fmode == BTREERANGE) { /* requires special type of search to limit tid scan */ for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i) { l_lid[i] = 0; h_lid[i] = 0; } lidsize = LIDSIZE * De.ov_scanr->d_r.r_dim; /* get low lids */ if (keytype == -1 || keytype == -3) { tp = De.ov_keyl + De.ov_scanr->d_r.r_width - lidsize; bmove(l_lid, tp, lidsize); setallkey(lowbkey, De.ov_keyl); bmove(tp, l_lid, lidsize); } /* get high lids */ if (keytype == -2 || keytype == -3) { tp = De.ov_keyh + De.ov_scanr->d_r.r_width - lidsize; bmove(h_lid, tp, lidsize); setallkey(highbkey, De.ov_keyh); bmove(tp, h_lid, lidsize); } setglobalint(BTREE_FD_NAME, De.ov_scanr->d_btreefd); /* scan through lids to fill in unprovided lids and to check ** for lids that are too big */ page = RT; for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i) { if (l_lid[i] <= 0) l_lid[i] = 1; l = last_lid(page) - 1; if (h_lid[i] < 0) return(0); if (!h_lid[i] || h_lid[i] > l) h_lid[i] = l; if ((t = get_tid(page, h_lid[i], &tidloc)) < 0) syserr("bad gettid in strategy, lid = %ld\n", h_lid[i]); page = t; } /* check whether lo > hi */ for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i) if (l_lid[i] < h_lid[i]) break; else if (l_lid[i] > h_lid[i]) return(0); #ifdef xOTR1 if (tTf(70,0)) for (i = 0 ; i < De.ov_scanr->d_r.r_dim; ++i) printf("hi = %ld, lo = %ld\n", h_lid[i], l_lid[i]); #endif /* find the smallest and largest possible tids of the lids ** within the provided range */ btreerange(De.ov_scanr, l_lid, h_lid, &De.ov_lotid, &De.ov_hitid); } else { /* set up the key tuples */ if (De.ov_fmode != NOKEY) { if (setallkey(De.ov_lkey_struct, De.ov_keyl)) return (0); /* query false. There is a simple ** clause which can never be satisfied. ** These simple clauses can be choosey! */ } if ((i = find(De.ov_scanr, De.ov_fmode, &De.ov_lotid, &De.ov_hitid, De.ov_keyl)) != 0) syserr("strategy:find1 %.12s, %d", De.ov_scanr->d_r.r_id, i); if (De.ov_fmode == LRANGEKEY) { setallkey(De.ov_hkey_struct, De.ov_keyh); if ((i = find(De.ov_scanr, HRANGEKEY, &De.ov_lotid, &De.ov_hitid, De.ov_keyh)) != 0) syserr("strategy:find2 %.12s, %d", De.ov_scanr->d_r.r_id, i); } } #ifdef xOTR1 if (tTf(70, 1)) { printf("Lo"); dumptid(&De.ov_lotid); printf("Hi"); dumptid(&De.ov_hitid); } #endif return (1); }
strategy() { register int i, allexact; struct accessparam sourceparam, indexparam; struct index itup, rtup; struct key lowikey[MAXKEYS+1], highikey[MAXKEYS+1]; register struct descriptor *d; extern struct descriptor Inddes; struct descriptor *openindex(); # ifdef xOTR1 if (tTf(31, 0)) printf("STRATEGY\tSource=%.12s\tNewq = %d\n", Source ? Source->relid : "(none)", Newq); # endif while (Newq) /* if Newq=TRUE then compute a new strategy */ /* NOTE: This while loop is executed only once */ { Scanr = Source; if (!Scanr) return (1); /* return immediately if there is no source relation */ Fmode = NOKEY; /* assume a find mode with no key */ if (!Qlist) break; /* if no qualification then you must scan entire rel */ /* copy structure of source relation into sourceparam */ paramd(Source, &sourceparam); /* if source is unkeyed and has no sec index then give up */ if (sourceparam.mode == NOKEY && Source->relindxd <= 0) break; /* find all simple clauses if any */ if (!findsimps()) break; /* break if there are no simple clauses */ /* Four steps are now performed to try and find a key. ** First if the relation is hashed then an exact key is search for ** ** Second if there are secondary indexes, then a search is made ** for an exact key. If that fails then a check is made for ** a range key. The result of the rangekey check is saved. ** ** Third if the relation is an ISAM a check is made for ** an exact key or a range key. ** ** Fourth if there is a secondary index, then if step two ** found a key, that key is used. ** ** Lastly, give up and scan the entire relation */ /* step one. Try to find exact key on primary */ if (exactkey(&sourceparam, &Lkey_struct)) { Fmode = EXACTKEY; break; } /* step two. If there is an index, try to find an exactkey on one of them */ if (Source->relindxd) { opencatalog("indexes", 0); setkey(&Inddes, &itup, Source->relid, IRELIDP); setkey(&Inddes, &itup, Source->relowner, IOWNERP); if (i = find(&Inddes, EXACTKEY, &Lotid, &Hitid, &itup)) syserr("strategy:find indexes %d", i); while (!(i = get(&Inddes, &Lotid, &Hitid, &itup, NXTTUP))) { # ifdef xOTR1 if (tTf(31, 3)) printup(&Inddes, &itup); # endif if (!bequal(itup.irelidp, Source->relid, MAXNAME) || !bequal(itup.iownerp, Source->relowner, 2)) continue; parami(&itup, &indexparam); if (exactkey(&indexparam, &Lkey_struct)) { Fmode = EXACTKEY; d = openindex(itup.irelidi); /* temp check for 6.0 index */ if (d->relindxd == -1) ov_err(BADSECINDX); Scanr = d; break; } if (Fmode == LRANGEKEY) continue; /* a range key on a s.i. has already been found */ if (allexact = rangekey(&indexparam, &lowikey, &highikey)) { bmove(&itup, &rtup, sizeof itup); /* save tuple */ Fmode = LRANGEKEY; } } if (i < 0) syserr("stragery:bad get from index-rel %d", i); /* If an exactkey on a secondary index was found, look no more. */ if (Fmode == EXACTKEY) break; } /* step three. Look for a range key on primary */ if (i = rangekey(&sourceparam, &Lkey_struct, &Hkey_struct)) { if (i < 0) Fmode = EXACTKEY; else Fmode = LRANGEKEY; break; } /* last step. If a secondary index range key was found, use it */ if (Fmode == LRANGEKEY) { if (allexact < 0) Fmode = EXACTKEY; d = openindex(rtup.irelidi); /* temp check for 6.0 index */ if (d->relindxd == -1) ov_err(BADSECINDX); Scanr = d; bmove(&lowikey, &Lkey_struct, sizeof lowikey); bmove(&highikey, &Hkey_struct, sizeof highikey); break; } /* nothing will work. give up! */ break; } /* check for Newq = FALSE and no source relation */ if (!Scanr) return (1); /* ** At this point the strategy is determined. ** ** If Fmode is EXACTKEY then Lkey_struct contains ** the pointers to the keys. ** ** If Fmode is LRANGEKEY then Lkey_struct contains ** the pointers to the low keys and Hkey_struct ** contains pointers to the high keys. ** ** If Fmode is NOKEY, then a full scan will be performed */ # ifdef xOTR1 if (tTf(31, -1)) printf("Fmode= %d\n",Fmode); # endif /* set up the key tuples */ if (Fmode != NOKEY) { if (setallkey(&Lkey_struct, Keyl)) return (0); /* query false. There is a simple ** clause which can never be satisfied. ** These simple clauses can be choosey! */ } if (i = find(Scanr, Fmode, &Lotid, &Hitid, Keyl)) syserr("strategy:find1 %.12s, %d", Scanr->relid, i); if (Fmode == LRANGEKEY) { setallkey(&Hkey_struct, Keyh); if (i = find(Scanr, HRANGEKEY, &Lotid, &Hitid, Keyh)) syserr("strategy:find2 %.12s, %d", Scanr->relid, i); } # ifdef xOTR1 if (tTf(31, 1)) { printf("Lo"); dumptid(&Lotid); printf("Hi"); dumptid(&Hitid); } # endif return (1); }