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
21
#include "drizzled/session.h"
22
#include "drizzled/util/functors.h"
23
#include "drizzled/optimizer/range.h"
24
#include "drizzled/optimizer/quick_range_select.h"
25
#include "drizzled/optimizer/quick_ror_intersect_select.h"
26
#include "drizzled/internal/m_string.h"
36
optimizer::QuickRorIntersectSelect::QuickRorIntersectSelect(Session *session_param,
38
bool retrieve_full_rows,
39
memory::Root *parent_alloc)
42
session(session_param),
43
need_to_fetch_row(retrieve_full_rows),
48
record= head->record[0];
51
memory::init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
55
memset(&alloc, 0, sizeof(memory::Root));
57
last_rowid= (unsigned char*) alloc_root(parent_alloc ? parent_alloc : &alloc,
58
head->cursor->ref_length);
62
optimizer::QuickRorIntersectSelect::~QuickRorIntersectSelect()
64
for_each(quick_selects.begin(),
67
quick_selects.clear();
69
free_root(&alloc,MYF(0));
70
if (need_to_fetch_row && head->cursor->inited != Cursor::NONE)
72
head->cursor->ha_rnd_end();
78
int optimizer::QuickRorIntersectSelect::init()
80
/* Check if last_rowid was successfully allocated in ctor */
81
return (! last_rowid);
85
int optimizer::QuickRorIntersectSelect::init_ror_merged_scan(bool reuse_handler)
87
vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
89
/* Initialize all merged "children" quick selects */
90
assert(! need_to_fetch_row || reuse_handler);
91
if (! need_to_fetch_row && reuse_handler)
93
optimizer::QuickRangeSelect *quick= *it;
96
There is no use of this->cursor. Use it for the first of merged range
99
if (quick->init_ror_merged_scan(true))
101
quick->cursor->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
103
while (it != quick_selects.end())
105
if ((*it)->init_ror_merged_scan(false))
109
(*it)->cursor->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
110
/* All merged scans share the same record buffer in intersection. */
111
(*it)->record= head->record[0];
115
if (need_to_fetch_row && head->cursor->ha_rnd_init(1))
123
int optimizer::QuickRorIntersectSelect::reset()
125
if (! scans_inited && init_ror_merged_scan(true))
130
for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
131
it != quick_selects.end();
141
optimizer::QuickRorIntersectSelect::push_quick_back(optimizer::QuickRangeSelect *quick)
143
quick_selects.push_back(quick);
148
bool optimizer::QuickRorIntersectSelect::is_keys_used(const MyBitmap *fields)
150
for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
151
it != quick_selects.end();
154
if (is_key_used(head, (*it)->index, fields))
163
int optimizer::QuickRorIntersectSelect::get_next()
165
optimizer::QuickRangeSelect *quick= NULL;
166
vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
169
uint32_t last_rowid_count= 0;
173
/* Get a rowid for first quick and save it as a 'candidate' */
176
error= quick->get_next();
179
while (! error && ! cpk_quick->row_in_ranges())
180
error= quick->get_next();
185
quick->cursor->position(quick->record);
186
memcpy(last_rowid, quick->cursor->ref, head->cursor->ref_length);
189
while (last_rowid_count < quick_selects.size())
191
/** @todo: fix this madness!!!! */
192
if (it != quick_selects.end())
199
it= quick_selects.begin();
206
if ((error= quick->get_next()))
208
quick->cursor->position(quick->record);
209
cmp= head->cursor->cmp_ref(quick->cursor->ref, last_rowid);
212
/* Ok, current select 'caught up' and returned ref >= cur_ref */
215
/* Found a row with ref > cur_ref. Make it a new 'candidate' */
218
while (! cpk_quick->row_in_ranges())
220
if ((error= quick->get_next()))
224
memcpy(last_rowid, quick->cursor->ref, head->cursor->ref_length);
229
/* current 'candidate' row confirmed by this select */
234
/* We get here if we got the same row ref in all scans. */
235
if (need_to_fetch_row)
236
error= head->cursor->rnd_pos(head->record[0], last_rowid);
237
} while (error == HA_ERR_RECORD_DELETED);
242
void optimizer::QuickRorIntersectSelect::add_info_string(String *str)
245
str->append(STRING_WITH_LEN("intersect("));
246
for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
247
it != quick_selects.end();
250
KEY *key_info= head->key_info + (*it)->index;
255
str->append(key_info->name);
259
KEY *key_info= head->key_info + cpk_quick->index;
261
str->append(key_info->name);
267
void optimizer::QuickRorIntersectSelect::add_keys_and_lengths(String *key_names,
268
String *used_lengths)
273
for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
274
it != quick_selects.end();
277
KEY *key_info= head->key_info + (*it)->index;
284
key_names->append(',');
285
used_lengths->append(',');
287
key_names->append(key_info->name);
288
length= internal::int64_t2str((*it)->max_used_key_length, buf, 10) - buf;
289
used_lengths->append(buf, length);
294
KEY *key_info= head->key_info + cpk_quick->index;
295
key_names->append(',');
296
key_names->append(key_info->name);
297
length= internal::int64_t2str(cpk_quick->max_used_key_length, buf, 10) - buf;
298
used_lengths->append(',');
299
used_lengths->append(buf, length);
303
} /* namespace drizzled */