Drizzled Public API Documentation

scan.cc
1 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2010 Padraig O'Sullivan
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <config.h>
22 #include <drizzled/join_table.h>
23 #include <drizzled/table.h>
24 #include <drizzled/sql_select.h>
25 #include <drizzled/internal/my_sys.h>
26 #include <drizzled/optimizer/access_method/scan.h>
27 #include <drizzled/util/test.h>
28 #include <drizzled/statistics_variables.h>
29 #include <drizzled/session.h>
30 
31 using namespace drizzled;
32 
33 static uint32_t make_join_orderinfo(Join *join);
34 
35 void optimizer::Scan::getStats(Table& table, JoinTable& join_tab)
36 {
37  Join *join= join_tab.join;
38  bool statistics= test(! (join->select_options & SELECT_DESCRIBE));
39  uint64_t options= (join->select_options &
40  (SELECT_DESCRIBE | SELECT_NO_JOIN_CACHE)) |
41  (0);
42  uint32_t no_jbuf_after= make_join_orderinfo(join);
43  uint32_t index= &join_tab - join->join_tab;
44 
45  /*
46  * If previous table use cache
47  * If the incoming data set is already sorted don't use cache.
48  */
49  table.status= STATUS_NO_RECORD;
50 
51  if (index != join->const_tables &&
52  ! (options & SELECT_NO_JOIN_CACHE) &&
53  join_tab.use_quick != 2 &&
54  ! join_tab.first_inner &&
55  index <= no_jbuf_after &&
56  ! join_tab.insideout_match_tab)
57  {
58  if ((options & SELECT_DESCRIBE) ||
59  ! join_init_cache(join->session,
60  join->join_tab + join->const_tables,
61  index - join->const_tables))
62  {
63  (&join_tab)[-1].next_select= sub_select_cache; /* Patch previous */
64  }
65  }
66 
67  /* These init changes read_record */
68  if (join_tab.use_quick == 2)
69  {
70  join->session->server_status|= SERVER_QUERY_NO_GOOD_INDEX_USED;
71  join_tab.read_first_record= join_init_quick_read_record;
72  if (statistics)
73  {
74  join->session->status_var.select_range_check_count++;
75  }
76  }
77  else
78  {
79  join_tab.read_first_record= join_init_read_record;
80  if (index == join->const_tables)
81  {
82  if (join_tab.select && join_tab.select->quick)
83  {
84  if (statistics)
85  join->session->status_var.select_range_count++;
86  }
87  else
88  {
89  join->session->server_status|= SERVER_QUERY_NO_INDEX_USED;
90  if (statistics)
91  join->session->status_var.select_scan_count++;
92  }
93  }
94  else
95  {
96  if (join_tab.select && join_tab.select->quick)
97  {
98  if (statistics)
99  join->session->status_var.select_full_range_join_count++;
100  }
101  else
102  {
103  join->session->server_status|= SERVER_QUERY_NO_INDEX_USED;
104  if (statistics)
105  join->session->status_var.select_full_join_count++;
106  }
107  }
108  if (! table.no_keyread)
109  {
110  if (join_tab.select &&
111  join_tab.select->quick &&
112  join_tab.select->quick->index != MAX_KEY && //not index_merge
113  table.covering_keys.test(join_tab.select->quick->index))
114  {
115  table.key_read= 1;
116  table.cursor->extra(HA_EXTRA_KEYREAD);
117  }
118  else if (! table.covering_keys.none() && ! (join_tab.select && join_tab.select->quick))
119  { // Only read index tree
120  if (! join_tab.insideout_match_tab)
121  {
122  /*
123  See bug #26447: "Using the clustered index for a table scan
124  is always faster than using a secondary index".
125  */
126  if (table.getShare()->hasPrimaryKey() &&
127  table.cursor->primary_key_is_clustered())
128  {
129  join_tab.index= table.getShare()->getPrimaryKey();
130  }
131  else
132  {
133  join_tab.index= table.find_shortest_key(&table.covering_keys);
134  }
135  }
136  join_tab.read_first_record= join_read_first;
137  join_tab.type= AM_NEXT; // Read with index_first / index_next
138  }
139  }
140  }
141 }
142 
152 static uint32_t make_join_orderinfo(Join *join)
153 {
154  if (join->need_tmp)
155  return join->tables;
156 
157  uint32_t i= join->const_tables;
158  for (; i < join->tables; i++)
159  {
160  JoinTable *tab= join->join_tab + i;
161  Table *table= tab->table;
162  if ((table == join->sort_by_table &&
163  (! join->order || join->skip_sort_order)) ||
164  (join->sort_by_table == (Table *) 1 && i != join->const_tables))
165  {
166  break;
167  }
168  }
169  return i;
170 }
enum access_method type
Definition: join_table.h:185
JoinTable * insideout_match_tab
Definition: join_table.h:207
TODO: Rename this file - func.h is stupid.
QuickSelectInterface * quick
Definition: range.h:277
Table * sort_by_table
Definition: join.h:64
JoinTable * first_inner
Definition: join_table.h:132
uint32_t tables
Definition: join.h:66
Cursor * cursor
Definition: table.h:68
bool skip_sort_order
Definition: join.h:113
void getStats(Table &, JoinTable &)
Definition: scan.cc:35