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;
28
static int refpos_order_cmp(void *arg, const void *a, const void *b)
30
Cursor *cursor= (Cursor*)arg;
31
return cursor->cmp_ref((const unsigned char *) a, (const unsigned char *) b);
34
optimizer::QuickIndexMergeSelect::QuickIndexMergeSelect(Session *session_param,
37
pk_quick_select(NULL),
38
session(session_param)
42
memset(&read_record, 0, sizeof(read_record));
43
init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
47
int optimizer::QuickIndexMergeSelect::init()
52
int optimizer::QuickIndexMergeSelect::reset()
54
return (read_keys_and_merge());
58
optimizer::QuickIndexMergeSelect::push_quick_back(optimizer::QuickRangeSelect *quick_sel_range)
61
Save quick_select that does scan on clustered primary key as it will be
64
if (head->cursor->primary_key_is_clustered() &&
65
quick_sel_range->index == head->s->primary_key)
67
pk_quick_select= quick_sel_range;
71
return quick_selects.push_back(quick_sel_range);
76
optimizer::QuickIndexMergeSelect::~QuickIndexMergeSelect()
78
List_iterator_fast<optimizer::QuickRangeSelect> quick_it(quick_selects);
79
optimizer::QuickRangeSelect* quick;
81
while ((quick= quick_it++))
85
quick_selects.delete_elements();
86
delete pk_quick_select;
87
free_root(&alloc,MYF(0));
92
int optimizer::QuickIndexMergeSelect::read_keys_and_merge()
94
List_iterator_fast<optimizer::QuickRangeSelect> cur_quick_it(quick_selects);
95
optimizer::QuickRangeSelect* cur_quick;
98
Cursor *cursor= head->cursor;
100
cursor->extra(HA_EXTRA_KEYREAD);
101
head->prepare_for_position();
103
cur_quick_it.rewind();
104
cur_quick= cur_quick_it++;
105
assert(cur_quick != 0);
108
We reuse the same instance of Cursor so we need to call both init and
111
if (cur_quick->init() || cur_quick->reset())
114
unique= new Unique(refpos_order_cmp,
117
session->variables.sortbuff_size);
122
while ((result= cur_quick->get_next()) == HA_ERR_END_OF_FILE)
124
cur_quick->range_end();
125
cur_quick= cur_quick_it++;
129
if (cur_quick->cursor->inited != Cursor::NONE)
130
cur_quick->cursor->ha_index_end();
131
if (cur_quick->init() || cur_quick->reset())
137
if (result != HA_ERR_END_OF_FILE)
139
cur_quick->range_end();
148
/* skip row if it will be retrieved by clustered PK scan */
149
if (pk_quick_select && pk_quick_select->row_in_ranges())
152
cur_quick->cursor->position(cur_quick->record);
153
result= unique->unique_add((char*)cur_quick->cursor->ref);
159
/* ok, all row ids are in Unique */
160
result= unique->get(head);
162
doing_pk_scan= false;
163
/* index_merge currently doesn't support "using index" at all */
164
cursor->extra(HA_EXTRA_NO_KEYREAD);
165
/* start table scan */
166
init_read_record(&read_record, session, head, (optimizer::SqlSelect*) 0, 1, 1);
171
int optimizer::QuickIndexMergeSelect::get_next()
176
return(pk_quick_select->get_next());
178
if ((result= read_record.read_record(&read_record)) == -1)
180
result= HA_ERR_END_OF_FILE;
181
end_read_record(&read_record);
182
/* All rows from Unique have been retrieved, do a clustered PK scan */
186
if ((result= pk_quick_select->init()) ||
187
(result= pk_quick_select->reset()))
189
return(pk_quick_select->get_next());
196
bool optimizer::QuickIndexMergeSelect::is_keys_used(const MyBitmap *fields)
198
optimizer::QuickRangeSelect *quick= NULL;
199
List_iterator_fast<QuickRangeSelect> it(quick_selects);
200
while ((quick= it++))
202
if (is_key_used(head, quick->index, fields))
209
void optimizer::QuickIndexMergeSelect::add_info_string(String *str)
211
optimizer::QuickRangeSelect *quick= NULL;
213
List_iterator_fast<optimizer::QuickRangeSelect> it(quick_selects);
214
str->append(STRING_WITH_LEN("sort_union("));
215
while ((quick= it++))
221
quick->add_info_string(str);
226
pk_quick_select->add_info_string(str);
232
void optimizer::QuickIndexMergeSelect::add_keys_and_lengths(String *key_names,
233
String *used_lengths)
238
optimizer::QuickRangeSelect *quick= NULL;
240
List_iterator_fast<optimizer::QuickRangeSelect> it(quick_selects);
241
while ((quick= it++))
247
key_names->append(',');
248
used_lengths->append(',');
251
KEY *key_info= head->key_info + quick->index;
252
key_names->append(key_info->name);
253
length= int64_t2str(quick->max_used_key_length, buf, 10) - buf;
254
used_lengths->append(buf, length);
258
KEY *key_info= head->key_info + pk_quick_select->index;
259
key_names->append(',');
260
key_names->append(key_info->name);
261
length= int64_t2str(pk_quick_select->max_used_key_length, buf, 10) - buf;
262
used_lengths->append(',');
263
used_lengths->append(buf, length);