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 #include <drizzled/memory/sql_alloc.h> 00023 00024 namespace drizzled { 00025 namespace optimizer { 00026 00027 class SEL_TREE : public drizzled::memory::SqlAlloc 00028 { 00029 public: 00030 /* 00031 Starting an effort to document this field: 00032 (for some i, keys[i]->type == optimizer::SEL_ARG::IMPOSSIBLE) => 00033 (type == SEL_TREE::IMPOSSIBLE) 00034 */ 00035 enum Type 00036 { 00037 IMPOSSIBLE, 00038 ALWAYS, 00039 MAYBE, 00040 KEY, 00041 KEY_SMALLER 00042 } type; 00043 00044 SEL_TREE(enum Type type_arg) :type(type_arg) {} 00045 SEL_TREE() :type(KEY) 00046 { 00047 keys_map.reset(); 00048 memset(keys, 0, sizeof(keys)); 00049 } 00050 /* 00051 Note: there may exist SEL_TREE objects with sel_tree->type=KEY and 00052 keys[i]=0 for all i. (SergeyP: it is not clear whether there is any 00053 merit in range analyzer functions (e.g. get_mm_parts) returning a 00054 pointer to such SEL_TREE instead of NULL) 00055 */ 00056 SEL_ARG *keys[MAX_KEY]; 00057 key_map keys_map; /* bitmask of non-NULL elements in keys */ 00058 00059 /* 00060 Possible ways to read rows using index_merge. The list is non-empty only 00061 if type==KEY. Currently can be non empty only if keys_map.none(). 00062 */ 00063 List<SEL_IMERGE> merges; 00064 00065 /* The members below are filled/used only after get_mm_tree is done */ 00066 key_map ror_scans_map; /* bitmask of ROR scan-able elements in keys */ 00067 uint32_t n_ror_scans; /* number of set bits in ror_scans_map */ 00068 00069 RorScanInfo **ror_scans; /* list of ROR key scans */ 00070 RorScanInfo **ror_scans_end; /* last ROR scan */ 00071 /* Note that #records for each key scan is stored in table->quick_rows */ 00072 00073 }; 00074 00075 /* 00076 Check if two optimizer::SEL_TREES can be combined into one (i.e. a single key range 00077 read can be constructed for "cond_of_tree1 OR cond_of_tree2" ) without 00078 using index_merge. 00079 */ 00080 bool sel_trees_can_be_ored(const SEL_TREE&, const SEL_TREE&, const RangeParameter&); 00081 00082 SEL_TREE * 00083 tree_or(RangeParameter *param, SEL_TREE *tree1, SEL_TREE *tree2); 00084 00085 /* 00086 Remove the trees that are not suitable for record retrieval. 00087 SYNOPSIS 00088 param Range analysis parameter 00089 tree Tree to be processed, tree->type is KEY or KEY_SMALLER 00090 00091 DESCRIPTION 00092 This function walks through tree->keys[] and removes the SEL_ARG* trees 00093 that are not "maybe" trees (*) and cannot be used to construct quick range 00094 selects. 00095 (*) - have type MAYBE or MAYBE_KEY. Perhaps we should remove trees of 00096 these types here as well. 00097 00098 A SEL_ARG* tree cannot be used to construct quick select if it has 00099 tree->part != 0. (e.g. it could represent "keypart2 < const"). 00100 00101 WHY THIS FUNCTION IS NEEDED 00102 00103 Normally we allow construction of optimizer::SEL_TREE objects that have SEL_ARG 00104 trees that do not allow quick range select construction. For example for 00105 " keypart1=1 AND keypart2=2 " the execution will proceed as follows: 00106 tree1= optimizer::SEL_TREE { SEL_ARG{keypart1=1} } 00107 tree2= optimizer::SEL_TREE { SEL_ARG{keypart2=2} } -- can't make quick range select 00108 from this 00109 call tree_and(tree1, tree2) -- this joins SEL_ARGs into a usable SEL_ARG 00110 tree. 00111 00112 There is an exception though: when we construct index_merge optimizer::SEL_TREE, 00113 any SEL_ARG* tree that cannot be used to construct quick range select can 00114 be removed, because current range analysis code doesn't provide any way 00115 that tree could be later combined with another tree. 00116 Consider an example: we should not construct 00117 st1 = optimizer::SEL_TREE { 00118 merges = SEL_IMERGE { 00119 optimizer::SEL_TREE(t.key1part1 = 1), 00120 optimizer::SEL_TREE(t.key2part2 = 2) -- (*) 00121 } 00122 }; 00123 because 00124 - (*) cannot be used to construct quick range select, 00125 - There is no execution path that would cause (*) to be converted to 00126 a tree that could be used. 00127 00128 The latter is easy to verify: first, notice that the only way to convert 00129 (*) into a usable tree is to call tree_and(something, (*)). 00130 00131 Second look at what tree_and/tree_or function would do when passed a 00132 optimizer::SEL_TREE that has the structure like st1 tree has, and conlcude that 00133 tree_and(something, (*)) will not be called. 00134 00135 RETURN 00136 0 Ok, some suitable trees left 00137 1 No tree->keys[] left. 00138 */ 00139 bool remove_nonrange_trees(RangeParameter *param, SEL_TREE *tree); 00140 00141 } /* namespace optimizer */ 00142 00143 } /* namespace drizzled */ 00144