1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008-2009 Sun Microsystems
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; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
#include "drizzled/server_includes.h"
21
#include "drizzled/session.h"
22
#include "drizzled/records.h"
23
#include "drizzled/optimizer/quick_range_select.h"
24
#include "drizzled/optimizer/quick_index_merge_select.h"
26
using namespace drizzled;
29
int refpos_order_cmp(void *arg, const void *a, const void *b);
32
int refpos_order_cmp(void *arg, const void *a, const void *b)
34
Cursor *cursor= (Cursor*)arg;
35
return cursor->cmp_ref((const unsigned char *) a, (const unsigned char *) b);
38
optimizer::QuickIndexMergeSelect::QuickIndexMergeSelect(Session *session_param,
41
pk_quick_select(NULL),
42
session(session_param)
46
memset(&read_record, 0, sizeof(read_record));
47
init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
51
int optimizer::QuickIndexMergeSelect::init()
56
int optimizer::QuickIndexMergeSelect::reset()
58
return (read_keys_and_merge());
62
optimizer::QuickIndexMergeSelect::push_quick_back(optimizer::QuickRangeSelect *quick_sel_range)
65
Save quick_select that does scan on clustered primary key as it will be
68
if (head->cursor->primary_key_is_clustered() &&
69
quick_sel_range->index == head->s->primary_key)
71
pk_quick_select= quick_sel_range;
75
return quick_selects.push_back(quick_sel_range);
80
optimizer::QuickIndexMergeSelect::~QuickIndexMergeSelect()
82
List_iterator_fast<optimizer::QuickRangeSelect> quick_it(quick_selects);
83
optimizer::QuickRangeSelect* quick;
85
while ((quick= quick_it++))
89
quick_selects.delete_elements();
90
delete pk_quick_select;
91
free_root(&alloc,MYF(0));
96
int optimizer::QuickIndexMergeSelect::read_keys_and_merge()
98
List_iterator_fast<optimizer::QuickRangeSelect> cur_quick_it(quick_selects);
99
optimizer::QuickRangeSelect* cur_quick;
102
Cursor *cursor= head->cursor;
104
cursor->extra(HA_EXTRA_KEYREAD);
105
head->prepare_for_position();
107
cur_quick_it.rewind();
108
cur_quick= cur_quick_it++;
109
assert(cur_quick != 0);
112
We reuse the same instance of Cursor so we need to call both init and
115
if (cur_quick->init() || cur_quick->reset())
118
unique= new Unique(refpos_order_cmp,
121
session->variables.sortbuff_size);
126
while ((result= cur_quick->get_next()) == HA_ERR_END_OF_FILE)
128
cur_quick->range_end();
129
cur_quick= cur_quick_it++;
133
if (cur_quick->cursor->inited != Cursor::NONE)
134
cur_quick->cursor->ha_index_end();
135
if (cur_quick->init() || cur_quick->reset())
141
if (result != HA_ERR_END_OF_FILE)
143
cur_quick->range_end();
152
/* skip row if it will be retrieved by clustered PK scan */
153
if (pk_quick_select && pk_quick_select->row_in_ranges())
156
cur_quick->cursor->position(cur_quick->record);
157
result= unique->unique_add((char*)cur_quick->cursor->ref);
163
/* ok, all row ids are in Unique */
164
result= unique->get(head);
166
doing_pk_scan= false;
167
/* index_merge currently doesn't support "using index" at all */
168
cursor->extra(HA_EXTRA_NO_KEYREAD);
169
/* start table scan */
170
init_read_record(&read_record, session, head, (optimizer::SqlSelect*) 0, 1, 1);
175
int optimizer::QuickIndexMergeSelect::get_next()
180
return(pk_quick_select->get_next());
182
if ((result= read_record.read_record(&read_record)) == -1)
184
result= HA_ERR_END_OF_FILE;
185
end_read_record(&read_record);
186
/* All rows from Unique have been retrieved, do a clustered PK scan */
190
if ((result= pk_quick_select->init()) ||
191
(result= pk_quick_select->reset()))
193
return(pk_quick_select->get_next());
200
bool optimizer::QuickIndexMergeSelect::is_keys_used(const MyBitmap *fields)
202
optimizer::QuickRangeSelect *quick= NULL;
203
List_iterator_fast<QuickRangeSelect> it(quick_selects);
204
while ((quick= it++))
206
if (is_key_used(head, quick->index, fields))
213
void optimizer::QuickIndexMergeSelect::add_info_string(String *str)
215
optimizer::QuickRangeSelect *quick= NULL;
217
List_iterator_fast<optimizer::QuickRangeSelect> it(quick_selects);
218
str->append(STRING_WITH_LEN("sort_union("));
219
while ((quick= it++))
225
quick->add_info_string(str);
230
pk_quick_select->add_info_string(str);
236
void optimizer::QuickIndexMergeSelect::add_keys_and_lengths(String *key_names,
237
String *used_lengths)
242
optimizer::QuickRangeSelect *quick= NULL;
244
List_iterator_fast<optimizer::QuickRangeSelect> it(quick_selects);
245
while ((quick= it++))
251
key_names->append(',');
252
used_lengths->append(',');
255
KEY *key_info= head->key_info + quick->index;
256
key_names->append(key_info->name);
257
length= int64_t2str(quick->max_used_key_length, buf, 10) - buf;
258
used_lengths->append(buf, length);
262
KEY *key_info= head->key_info + pk_quick_select->index;
263
key_names->append(',');
264
key_names->append(key_info->name);
265
length= int64_t2str(pk_quick_select->max_used_key_length, buf, 10) - buf;
266
used_lengths->append(',');
267
used_lengths->append(buf, length);