~stewart/drizzle/embedded-innodb-autoincrement

« back to all changes in this revision

Viewing changes to drizzled/optimizer/access_method/scan.cc

merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/session.h"
 
23
#include "drizzled/join_table.h"
 
24
#include "drizzled/table.h"
 
25
#include "drizzled/sql_select.h"
 
26
#include "drizzled/internal/my_sys.h"
 
27
#include "drizzled/optimizer/access_method/scan.h"
 
28
 
 
29
using namespace drizzled;
 
30
 
 
31
static uint32_t make_join_orderinfo(JOIN *join);
 
32
 
 
33
bool optimizer::Scan::getStats(Table *table,
 
34
                               JoinTable *join_tab)
 
35
{
 
36
  JOIN *join= join_tab->join;
 
37
  bool statistics= test(! (join->select_options & SELECT_DESCRIBE));
 
38
  uint64_t options= (join->select_options &
 
39
                     (SELECT_DESCRIBE | SELECT_NO_JOIN_CACHE)) |
 
40
                     (0);
 
41
  uint32_t no_jbuf_after= make_join_orderinfo(join);
 
42
  uint32_t index= join_tab - join->join_tab;
 
43
 
 
44
  /*
 
45
   * If previous table use cache
 
46
   * If the incoming data set is already sorted don't use cache.
 
47
   */
 
48
  table->status= STATUS_NO_RECORD;
 
49
 
 
50
  if (index != join->const_tables && 
 
51
      ! (options & SELECT_NO_JOIN_CACHE) &&
 
52
      join_tab->use_quick != 2 && 
 
53
      ! join_tab->first_inner && 
 
54
      index <= no_jbuf_after &&
 
55
      ! join_tab->insideout_match_tab)
 
56
  {
 
57
    if ((options & SELECT_DESCRIBE) ||
 
58
        ! join_init_cache(join->session,
 
59
                          join->join_tab + join->const_tables,
 
60
                          index - join->const_tables))
 
61
    {
 
62
      join_tab[-1].next_select= sub_select_cache; /* Patch previous */
 
63
    }
 
64
  }
 
65
 
 
66
  /* These init changes read_record */
 
67
  if (join_tab->use_quick == 2)
 
68
  {
 
69
    join->session->server_status|= SERVER_QUERY_NO_GOOD_INDEX_USED;
 
70
    join_tab->read_first_record= join_init_quick_read_record;
 
71
    if (statistics)
 
72
    {
 
73
      status_var_increment(join->session->status_var.select_range_check_count);
 
74
    }
 
75
  }
 
76
  else
 
77
  {
 
78
    join_tab->read_first_record= join_init_read_record;
 
79
    if (index == join->const_tables)
 
80
    {
 
81
      if (join_tab->select && join_tab->select->quick)
 
82
      {
 
83
        if (statistics)
 
84
        {
 
85
          status_var_increment(join->session->status_var.select_range_count);
 
86
        }
 
87
      }
 
88
      else
 
89
      {
 
90
        join->session->server_status|= SERVER_QUERY_NO_INDEX_USED;
 
91
        if (statistics)
 
92
        {
 
93
          status_var_increment(join->session->status_var.select_scan_count);
 
94
        }
 
95
      }
 
96
    }
 
97
    else
 
98
    {
 
99
      if (join_tab->select && join_tab->select->quick)
 
100
      {
 
101
        if (statistics)
 
102
        {
 
103
          status_var_increment(join->session->status_var.select_full_range_join_count);
 
104
        }
 
105
      }
 
106
      else
 
107
      {
 
108
        join->session->server_status|= SERVER_QUERY_NO_INDEX_USED;
 
109
        if (statistics)
 
110
        {
 
111
          status_var_increment(join->session->status_var.select_full_join_count);
 
112
        }
 
113
      }
 
114
    }
 
115
    if (! table->no_keyread)
 
116
    {
 
117
      if (join_tab->select && 
 
118
          join_tab->select->quick &&
 
119
          join_tab->select->quick->index != MAX_KEY && //not index_merge
 
120
          table->covering_keys.test(join_tab->select->quick->index))
 
121
      {
 
122
        table->key_read= 1;
 
123
        table->cursor->extra(HA_EXTRA_KEYREAD);
 
124
      }
 
125
      else if (! table->covering_keys.none() &&
 
126
               ! (join_tab->select && join_tab->select->quick))
 
127
      { // Only read index tree
 
128
        if (! join_tab->insideout_match_tab)
 
129
        {
 
130
          /*
 
131
             See bug #26447: "Using the clustered index for a table scan
 
132
             is always faster than using a secondary index".
 
133
           */
 
134
          if (table->s->primary_key != MAX_KEY &&
 
135
              table->cursor->primary_key_is_clustered())
 
136
          {
 
137
            join_tab->index= table->s->primary_key;
 
138
          }
 
139
          else
 
140
          {
 
141
            join_tab->index= table->find_shortest_key(&table->covering_keys);
 
142
          }
 
143
        }
 
144
        join_tab->read_first_record= join_read_first;
 
145
        join_tab->type= AM_NEXT; // Read with index_first / index_next
 
146
      }
 
147
    }
 
148
  }
 
149
  return false;
 
150
}
 
151
 
 
152
/**
 
153
  Determine if the set is already ordered for order_st BY, so it can
 
154
  disable join cache because it will change the ordering of the results.
 
155
  Code handles sort table that is at any location (not only first after
 
156
  the const tables) despite the fact that it's currently prohibited.
 
157
  We must disable join cache if the first non-const table alone is
 
158
  ordered. If there is a temp table the ordering is done as a last
 
159
  operation and doesn't prevent join cache usage.
 
160
*/
 
161
static uint32_t make_join_orderinfo(JOIN *join)
 
162
{
 
163
  uint32_t i= 0;
 
164
  if (join->need_tmp)
 
165
  {
 
166
    return join->tables;
 
167
  }
 
168
 
 
169
  for (i= join->const_tables ; i < join->tables ; i++)
 
170
  {
 
171
    JoinTable *tab= join->join_tab + i;
 
172
    Table *table= tab->table;
 
173
    if ((table == join->sort_by_table &&
 
174
        (! join->order || join->skip_sort_order)) ||
 
175
        (join->sort_by_table == (Table *) 1 &&  i != join->const_tables))
 
176
    {
 
177
      break;
 
178
    }
 
179
  }
 
180
  return i;
 
181
}