00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*- 00002 * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: 00003 * 00004 * Copyright (C) 2008-2009 Sun Microsystems, Inc. 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; version 2 of the License. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 */ 00019 00020 #pragma once 00021 00022 namespace drizzled { 00023 namespace optimizer { 00024 00025 /* 00026 A construction block of the SEL_ARG-graph. 00027 00028 The following description only covers graphs of SEL_ARG objects with 00029 sel_arg->type==KEY_RANGE: 00030 00031 One SEL_ARG object represents an "elementary interval" in form 00032 00033 min_value <=? table.keypartX <=? max_value 00034 00035 The interval is a non-empty interval of any kind: with[out] minimum/maximum 00036 bound, [half]open/closed, single-point interval, etc. 00037 00038 1. SEL_ARG GRAPH STRUCTURE 00039 00040 SEL_ARG objects are linked together in a graph. The meaning of the graph 00041 is better demostrated by an example: 00042 00043 tree->keys[i] 00044 | 00045 | $ $ 00046 | part=1 $ part=2 $ part=3 00047 | $ $ 00048 | +-------+ $ +-------+ $ +--------+ 00049 | | kp1<1 |--$-->| kp2=5 |--$-->| kp3=10 | 00050 | +-------+ $ +-------+ $ +--------+ 00051 | | $ $ | 00052 | | $ $ +--------+ 00053 | | $ $ | kp3=12 | 00054 | | $ $ +--------+ 00055 | +-------+ $ $ 00056 \->| kp1=2 |--$--------------$-+ 00057 +-------+ $ $ | +--------+ 00058 | $ $ ==>| kp3=11 | 00059 +-------+ $ $ | +--------+ 00060 | kp1=3 |--$--------------$-+ | 00061 +-------+ $ $ +--------+ 00062 | $ $ | kp3=14 | 00063 ... $ $ +--------+ 00064 00065 The entire graph is partitioned into "interval lists". 00066 00067 An interval list is a sequence of ordered disjoint intervals over the same 00068 key part. SEL_ARG are linked via "next" and "prev" pointers. Additionally, 00069 all intervals in the list form an RB-tree, linked via left/right/parent 00070 pointers. The RB-tree root SEL_ARG object will be further called "root of the 00071 interval list". 00072 00073 In the example pic, there are 4 interval lists: 00074 "kp<1 OR kp1=2 OR kp1=3", "kp2=5", "kp3=10 OR kp3=12", "kp3=11 OR kp3=13". 00075 The vertical lines represent SEL_ARG::next/prev pointers. 00076 00077 In an interval list, each member X may have SEL_ARG::next_key_part pointer 00078 pointing to the root of another interval list Y. The pointed interval list 00079 must cover a key part with greater number (i.e. Y->part > X->part). 00080 00081 In the example pic, the next_key_part pointers are represented by 00082 horisontal lines. 00083 00084 2. SEL_ARG GRAPH SEMANTICS 00085 00086 It represents a condition in a special form (we don't have a name for it ATM) 00087 The SEL_ARG::next/prev is "OR", and next_key_part is "AND". 00088 00089 For example, the picture represents the condition in form: 00090 (kp1 < 1 AND kp2=5 AND (kp3=10 OR kp3=12)) OR 00091 (kp1=2 AND (kp3=11 OR kp3=14)) OR 00092 (kp1=3 AND (kp3=11 OR kp3=14)) 00093 00094 00095 3. SEL_ARG GRAPH USE 00096 00097 Use get_mm_tree() to construct SEL_ARG graph from WHERE condition. 00098 Then walk the SEL_ARG graph and get a list of dijsoint ordered key 00099 intervals (i.e. intervals in form 00100 00101 (constA1, .., const1_K) < (keypart1,.., keypartK) < (constB1, .., constB_K) 00102 00103 Those intervals can be used to access the index. The uses are in: 00104 - check_quick_select() - Walk the SEL_ARG graph and find an estimate of 00105 how many table records are contained within all 00106 intervals. 00107 - get_quick_select() - Walk the SEL_ARG, materialize the key intervals, 00108 and create QuickRangeSelect object that will 00109 read records within these intervals. 00110 00111 4. SPACE COMPLEXITY NOTES 00112 00113 SEL_ARG graph is a representation of an ordered disjoint sequence of 00114 intervals over the ordered set of index tuple values. 00115 00116 For multi-part keys, one can construct a WHERE expression such that its 00117 list of intervals will be of combinatorial size. Here is an example: 00118 00119 (keypart1 IN (1,2, ..., n1)) AND 00120 (keypart2 IN (1,2, ..., n2)) AND 00121 (keypart3 IN (1,2, ..., n3)) 00122 00123 For this WHERE clause the list of intervals will have n1*n2*n3 intervals 00124 of form 00125 00126 (keypart1, keypart2, keypart3) = (k1, k2, k3), where 1 <= k{i} <= n{i} 00127 00128 SEL_ARG graph structure aims to reduce the amount of required space by 00129 "sharing" the elementary intervals when possible (the pic at the 00130 beginning of this comment has examples of such sharing). The sharing may 00131 prevent combinatorial blowup: 00132 00133 There are WHERE clauses that have combinatorial-size interval lists but 00134 will be represented by a compact SEL_ARG graph. 00135 Example: 00136 (keypartN IN (1,2, ..., n1)) AND 00137 ... 00138 (keypart2 IN (1,2, ..., n2)) AND 00139 (keypart1 IN (1,2, ..., n3)) 00140 00141 but not in all cases: 00142 00143 - There are WHERE clauses that do have a compact SEL_ARG-graph 00144 representation but get_mm_tree() and its callees will construct a 00145 graph of combinatorial size. 00146 Example: 00147 (keypart1 IN (1,2, ..., n1)) AND 00148 (keypart2 IN (1,2, ..., n2)) AND 00149 ... 00150 (keypartN IN (1,2, ..., n3)) 00151 00152 - There are WHERE clauses for which the minimal possible SEL_ARG graph 00153 representation will have combinatorial size. 00154 Example: 00155 By induction: Let's take any interval on some keypart in the middle: 00156 00157 kp15=c0 00158 00159 Then let's AND it with this interval 'structure' from preceding and 00160 following keyparts: 00161 00162 (kp14=c1 AND kp16=c3) OR keypart14=c2) (*) 00163 00164 We will obtain this SEL_ARG graph: 00165 00166 kp14 $ kp15 $ kp16 00167 $ $ 00168 +---------+ $ +---------+ $ +---------+ 00169 | kp14=c1 |--$-->| kp15=c0 |--$-->| kp16=c3 | 00170 +---------+ $ +---------+ $ +---------+ 00171 | $ $ 00172 +---------+ $ +---------+ $ 00173 | kp14=c2 |--$-->| kp15=c0 | $ 00174 +---------+ $ +---------+ $ 00175 $ $ 00176 00177 Note that we had to duplicate "kp15=c0" and there was no way to avoid 00178 that. 00179 The induction step: AND the obtained expression with another "wrapping" 00180 expression like (*). 00181 When the process ends because of the limit on max. number of keyparts 00182 we'll have: 00183 00184 WHERE clause length is O(3*#max_keyparts) 00185 SEL_ARG graph size is O(2^(#max_keyparts/2)) 00186 00187 (it is also possible to construct a case where instead of 2 in 2^n we 00188 have a bigger constant, e.g. 4, and get a graph with 4^(31/2)= 2^31 00189 nodes) 00190 00191 We avoid consuming too much memory by setting a limit on the number of 00192 SEL_ARG object we can construct during one range analysis invocation. 00193 */ 00194 00195 class SEL_ARG :public memory::SqlAlloc 00196 { 00197 public: 00198 uint8_t min_flag,max_flag,maybe_flag; 00199 uint8_t part; // Which key part 00200 uint8_t maybe_null; 00201 /* 00202 Number of children of this element in the RB-tree, plus 1 for this 00203 element itself. 00204 */ 00205 uint16_t elements; 00206 /* 00207 Valid only for elements which are RB-tree roots: Number of times this 00208 RB-tree is referred to (it is referred by SEL_ARG::next_key_part or by 00209 SEL_TREE::keys[i] or by a temporary SEL_ARG* variable) 00210 */ 00211 ulong use_count; 00212 00213 Field *field; 00214 unsigned char *min_value,*max_value; // Pointer to range 00215 00216 /* 00217 eq_tree() requires that left == right == 0 if the type is MAYBE_KEY. 00218 */ 00219 SEL_ARG *left,*right; /* R-B tree children */ 00220 SEL_ARG *next,*prev; /* Links for bi-directional interval list */ 00221 SEL_ARG *parent; /* R-B tree parent */ 00222 SEL_ARG *next_key_part; 00223 enum leaf_color { BLACK,RED } color; 00224 enum Type { IMPOSSIBLE, MAYBE, MAYBE_KEY, KEY_RANGE } type; 00225 00226 enum 00227 { 00228 MAX_SEL_ARGS = 16000 00229 }; 00230 00231 SEL_ARG() {} 00232 00233 SEL_ARG(SEL_ARG &); 00234 00235 SEL_ARG(Field *,const unsigned char *, const unsigned char *); 00236 00237 SEL_ARG(Field *field, 00238 uint8_t part, 00239 unsigned char *min_value, 00240 unsigned char *max_value, 00241 uint8_t min_flag, 00242 uint8_t max_flag, 00243 uint8_t maybe_flag); 00244 00245 SEL_ARG(enum Type type_arg) 00246 : 00247 min_flag(0), 00248 elements(1), 00249 use_count(1), 00250 left(0), 00251 right(0), 00252 next_key_part(0), 00253 color(BLACK), 00254 type(type_arg) 00255 {} 00256 00257 int size() const 00258 { 00259 return elements; 00260 } 00261 00262 inline bool is_same(SEL_ARG *arg) 00263 { 00264 if (type != arg->type || part != arg->part) 00265 return 0; 00266 if (type != KEY_RANGE) 00267 return 1; 00268 return (cmp_min_to_min(arg) == 0 && cmp_max_to_max(arg) == 0); 00269 } 00270 00271 inline void merge_flags(SEL_ARG *arg) 00272 { 00273 maybe_flag|= arg->maybe_flag; 00274 } 00275 00276 inline void maybe_smaller() 00277 { 00278 maybe_flag= 1; 00279 } 00280 00281 /* Return true iff it's a single-point null interval */ 00282 inline bool is_null_interval() 00283 { 00284 return (maybe_null && max_value[0] == 1); 00285 } 00286 00287 inline int cmp_min_to_min(SEL_ARG *arg) 00288 { 00289 return sel_cmp(field,min_value, arg->min_value, min_flag, arg->min_flag); 00290 } 00291 00292 inline int cmp_min_to_max(SEL_ARG *arg) 00293 { 00294 return sel_cmp(field,min_value, arg->max_value, min_flag, arg->max_flag); 00295 } 00296 00297 inline int cmp_max_to_max(SEL_ARG *arg) 00298 { 00299 return sel_cmp(field,max_value, arg->max_value, max_flag, arg->max_flag); 00300 } 00301 00302 inline int cmp_max_to_min(SEL_ARG *arg) 00303 { 00304 return sel_cmp(field,max_value, arg->min_value, max_flag, arg->min_flag); 00305 } 00306 00307 SEL_ARG *clone_and(SEL_ARG *arg); 00308 00309 SEL_ARG *clone_first(SEL_ARG *arg); 00310 00311 SEL_ARG *clone_last(SEL_ARG *arg); 00312 00313 SEL_ARG *clone(RangeParameter *param, SEL_ARG *new_parent, SEL_ARG **next); 00314 00315 bool copy_min(SEL_ARG *arg); 00316 00317 bool copy_max(SEL_ARG *arg); 00318 00319 void copy_min_to_min(SEL_ARG *arg); 00320 00321 void copy_min_to_max(SEL_ARG *arg); 00322 00323 void copy_max_to_min(SEL_ARG *arg); 00324 00325 /* returns a number of keypart values (0 or 1) appended to the key buffer */ 00326 int store_min(uint32_t length, unsigned char **min_key, uint32_t min_key_flag); 00327 00328 /* returns a number of keypart values (0 or 1) appended to the key buffer */ 00329 int store_max(uint32_t length, unsigned char **max_key, uint32_t max_key_flag); 00330 00331 /* returns a number of keypart values appended to the key buffer */ 00332 int store_min_key(KEY_PART *key, unsigned char **range_key, uint32_t *range_key_flag); 00333 00334 /* returns a number of keypart values appended to the key buffer */ 00335 int store_max_key(KEY_PART *key, unsigned char **range_key, uint32_t *range_key_flag); 00336 00337 SEL_ARG *insert(SEL_ARG *key); 00338 SEL_ARG *tree_delete(SEL_ARG *key); 00339 SEL_ARG *find_range(SEL_ARG *key); 00340 SEL_ARG *rb_insert(SEL_ARG *leaf); 00341 00342 friend SEL_ARG *rb_delete_fixup(SEL_ARG *root,SEL_ARG *key, SEL_ARG *par); 00343 00344 SEL_ARG *first(); 00345 00346 SEL_ARG *last(); 00347 00348 void make_root(); 00349 00350 inline bool simple_key() 00351 { 00352 return (! next_key_part && elements == 1); 00353 } 00354 00355 void increment_use_count(long count) 00356 { 00357 if (next_key_part) 00358 { 00359 next_key_part->use_count+= count; 00360 count*= (next_key_part->use_count - count); 00361 for (SEL_ARG *pos= next_key_part->first(); pos; pos= pos->next) 00362 if (pos->next_key_part) 00363 pos->increment_use_count(count); 00364 } 00365 } 00366 00367 void free_tree() 00368 { 00369 for (SEL_ARG *pos= first(); pos; pos= pos->next) 00370 if (pos->next_key_part) 00371 { 00372 pos->next_key_part->use_count--; 00373 pos->next_key_part->free_tree(); 00374 } 00375 } 00376 00377 inline SEL_ARG **parent_ptr() 00378 { 00379 return parent->left == this ? &parent->left : &parent->right; 00380 } 00381 00382 00383 /* 00384 Check if this SEL_ARG object represents a single-point interval 00385 00386 SYNOPSIS 00387 is_singlepoint() 00388 00389 DESCRIPTION 00390 Check if this SEL_ARG object (not tree) represents a single-point 00391 interval, i.e. if it represents a "keypart = const" or 00392 "keypart IS NULL". 00393 00394 RETURN 00395 true This SEL_ARG object represents a singlepoint interval 00396 false Otherwise 00397 */ 00398 00399 bool is_singlepoint() 00400 { 00401 /* 00402 Check for NEAR_MIN ("strictly less") and NO_MIN_RANGE (-inf < field) 00403 flags, and the same for right edge. 00404 */ 00405 if (min_flag || max_flag) 00406 return false; 00407 unsigned char *min_val= min_value; 00408 unsigned char *max_val= max_value; 00409 00410 if (maybe_null) 00411 { 00412 /* First byte is a NULL value indicator */ 00413 if (*min_val != *max_val) 00414 return false; 00415 00416 if (*min_val) 00417 return true; /* This "x IS NULL" */ 00418 min_val++; 00419 max_val++; 00420 } 00421 return ! field->key_cmp(min_val, max_val); 00422 } 00423 00424 SEL_ARG *clone_tree(RangeParameter *param); 00425 00426 private: 00427 00428 /* 00429 Check if a compare is ok, when one takes ranges in account 00430 Returns -2 or 2 if the ranges where 'joined' like < 2 and >= 2 00431 */ 00432 int sel_cmp(Field *in_field, 00433 unsigned char *a, 00434 unsigned char *b, 00435 uint8_t a_flag, 00436 uint8_t b_flag) 00437 { 00438 int cmp= 0; 00439 /* First check if there was a compare to a min or max element */ 00440 if (a_flag & (NO_MIN_RANGE | NO_MAX_RANGE)) 00441 { 00442 if ((a_flag & (NO_MIN_RANGE | NO_MAX_RANGE)) == 00443 (b_flag & (NO_MIN_RANGE | NO_MAX_RANGE))) 00444 return 0; 00445 return (a_flag & NO_MIN_RANGE) ? -1 : 1; 00446 } 00447 if (b_flag & (NO_MIN_RANGE | NO_MAX_RANGE)) 00448 return (b_flag & NO_MIN_RANGE) ? 1 : -1; 00449 00450 if (in_field->real_maybe_null()) // If null is part of key 00451 { 00452 if (*a != *b) 00453 { 00454 return *a ? -1 : 1; 00455 } 00456 if (*a) 00457 goto end; // NULL where equal 00458 a++; b++; // Skip NULL marker 00459 } 00460 cmp= in_field->key_cmp(a , b); 00461 if (cmp) return cmp < 0 ? -1 : 1; // The values differed 00462 00463 // Check if the compared equal arguments was defined with open/closed range 00464 end: 00465 if (a_flag & (NEAR_MIN | NEAR_MAX)) 00466 { 00467 if ((a_flag & (NEAR_MIN | NEAR_MAX)) == (b_flag & (NEAR_MIN | NEAR_MAX))) 00468 return 0; 00469 if (! (b_flag & (NEAR_MIN | NEAR_MAX))) 00470 return (a_flag & NEAR_MIN) ? 2 : -2; 00471 return (a_flag & NEAR_MIN) ? 1 : -1; 00472 } 00473 if (b_flag & (NEAR_MIN | NEAR_MAX)) 00474 return (b_flag & NEAR_MIN) ? -2 : 2; 00475 return 0; // The elements where equal 00476 } 00477 00478 00479 }; 00480 00481 SEL_ARG *rb_delete_fixup(SEL_ARG *root, 00482 SEL_ARG *key, 00483 SEL_ARG *par); 00484 00485 extern SEL_ARG null_element; 00486 00487 } /* namespace optimizer */ 00488 00489 } /* namespace drizzled */ 00490