Drizzled Public API Documentation

scan.cc

00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2010 Padraig O'Sullivan
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; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 #include <config.h>
00022 #include <drizzled/session.h>
00023 #include <drizzled/join_table.h>
00024 #include <drizzled/table.h>
00025 #include <drizzled/sql_select.h>
00026 #include <drizzled/internal/my_sys.h>
00027 #include <drizzled/optimizer/access_method/scan.h>
00028 
00029 using namespace drizzled;
00030 
00031 static uint32_t make_join_orderinfo(Join *join);
00032 
00033 bool optimizer::Scan::getStats(Table *table,
00034                                JoinTable *join_tab)
00035 {
00036   Join *join= join_tab->join;
00037   bool statistics= test(! (join->select_options & SELECT_DESCRIBE));
00038   uint64_t options= (join->select_options &
00039                      (SELECT_DESCRIBE | SELECT_NO_JOIN_CACHE)) |
00040                      (0);
00041   uint32_t no_jbuf_after= make_join_orderinfo(join);
00042   uint32_t index= join_tab - join->join_tab;
00043 
00044   /*
00045    * If previous table use cache
00046    * If the incoming data set is already sorted don't use cache.
00047    */
00048   table->status= STATUS_NO_RECORD;
00049 
00050   if (index != join->const_tables && 
00051       ! (options & SELECT_NO_JOIN_CACHE) &&
00052       join_tab->use_quick != 2 && 
00053       ! join_tab->first_inner && 
00054       index <= no_jbuf_after &&
00055       ! join_tab->insideout_match_tab)
00056   {
00057     if ((options & SELECT_DESCRIBE) ||
00058         ! join_init_cache(join->session,
00059                           join->join_tab + join->const_tables,
00060                           index - join->const_tables))
00061     {
00062       join_tab[-1].next_select= sub_select_cache; /* Patch previous */
00063     }
00064   }
00065 
00066   /* These init changes read_record */
00067   if (join_tab->use_quick == 2)
00068   {
00069     join->session->server_status|= SERVER_QUERY_NO_GOOD_INDEX_USED;
00070     join_tab->read_first_record= join_init_quick_read_record;
00071     if (statistics)
00072     {
00073       join->session->status_var.select_range_check_count++;
00074     }
00075   }
00076   else
00077   {
00078     join_tab->read_first_record= join_init_read_record;
00079     if (index == join->const_tables)
00080     {
00081       if (join_tab->select && join_tab->select->quick)
00082       {
00083         if (statistics)
00084         {
00085           join->session->status_var.select_range_count++;
00086         }
00087       }
00088       else
00089       {
00090         join->session->server_status|= SERVER_QUERY_NO_INDEX_USED;
00091         if (statistics)
00092         {
00093           join->session->status_var.select_scan_count++;
00094         }
00095       }
00096     }
00097     else
00098     {
00099       if (join_tab->select && join_tab->select->quick)
00100       {
00101         if (statistics)
00102         {
00103           join->session->status_var.select_full_range_join_count++;
00104         }
00105       }
00106       else
00107       {
00108         join->session->server_status|= SERVER_QUERY_NO_INDEX_USED;
00109         if (statistics)
00110         {
00111           join->session->status_var.select_full_join_count++;
00112         }
00113       }
00114     }
00115     if (! table->no_keyread)
00116     {
00117       if (join_tab->select && 
00118           join_tab->select->quick &&
00119           join_tab->select->quick->index != MAX_KEY && //not index_merge
00120           table->covering_keys.test(join_tab->select->quick->index))
00121       {
00122         table->key_read= 1;
00123         table->cursor->extra(HA_EXTRA_KEYREAD);
00124       }
00125       else if (! table->covering_keys.none() &&
00126                ! (join_tab->select && join_tab->select->quick))
00127       { // Only read index tree
00128         if (! join_tab->insideout_match_tab)
00129         {
00130           /*
00131              See bug #26447: "Using the clustered index for a table scan
00132              is always faster than using a secondary index".
00133            */
00134           if (table->getShare()->hasPrimaryKey() &&
00135               table->cursor->primary_key_is_clustered())
00136           {
00137             join_tab->index= table->getShare()->getPrimaryKey();
00138           }
00139           else
00140           {
00141             join_tab->index= table->find_shortest_key(&table->covering_keys);
00142           }
00143         }
00144         join_tab->read_first_record= join_read_first;
00145         join_tab->type= AM_NEXT; // Read with index_first / index_next
00146       }
00147     }
00148   }
00149 
00150   return false;
00151 }
00152 
00162 static uint32_t make_join_orderinfo(Join *join)
00163 {
00164   uint32_t i= 0;
00165   if (join->need_tmp)
00166   {
00167     return join->tables;
00168   }
00169 
00170   for (i= join->const_tables ; i < join->tables ; i++)
00171   {
00172     JoinTable *tab= join->join_tab + i;
00173     Table *table= tab->table;
00174     if ((table == join->sort_by_table &&
00175         (! join->order || join->skip_sort_order)) ||
00176         (join->sort_by_table == (Table *) 1 &&  i != join->const_tables))
00177     {
00178       break;
00179     }
00180   }
00181   return i;
00182 }