Drizzled Public API Documentation

sel_tree.h
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