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/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"
30
using namespace drizzled;
33
optimizer::QuickRorIntersectSelect::QuickRorIntersectSelect(Session *session_param,
35
bool retrieve_full_rows,
36
MEM_ROOT *parent_alloc)
39
session(session_param),
40
need_to_fetch_row(retrieve_full_rows),
45
record= head->record[0];
48
init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
52
memset(&alloc, 0, sizeof(MEM_ROOT));
54
last_rowid= (unsigned char*) alloc_root(parent_alloc ? parent_alloc : &alloc,
55
head->cursor->ref_length);
59
optimizer::QuickRorIntersectSelect::~QuickRorIntersectSelect()
61
for_each(quick_selects.begin(),
64
quick_selects.clear();
66
free_root(&alloc,MYF(0));
67
if (need_to_fetch_row && head->cursor->inited != Cursor::NONE)
69
head->cursor->ha_rnd_end();
75
int optimizer::QuickRorIntersectSelect::init()
77
/* Check if last_rowid was successfully allocated in ctor */
78
return (! last_rowid);
82
int optimizer::QuickRorIntersectSelect::init_ror_merged_scan(bool reuse_handler)
84
vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
86
/* Initialize all merged "children" quick selects */
87
assert(! need_to_fetch_row || reuse_handler);
88
if (! need_to_fetch_row && reuse_handler)
90
optimizer::QuickRangeSelect *quick= *it;
93
There is no use of this->cursor. Use it for the first of merged range
96
if (quick->init_ror_merged_scan(true))
98
quick->cursor->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
100
while (it != quick_selects.end())
102
if ((*it)->init_ror_merged_scan(false))
106
(*it)->cursor->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
107
/* All merged scans share the same record buffer in intersection. */
108
(*it)->record= head->record[0];
112
if (need_to_fetch_row && head->cursor->ha_rnd_init(1))
120
int optimizer::QuickRorIntersectSelect::reset()
122
if (! scans_inited && init_ror_merged_scan(true))
127
for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
128
it != quick_selects.end();
138
optimizer::QuickRorIntersectSelect::push_quick_back(optimizer::QuickRangeSelect *quick)
140
quick_selects.push_back(quick);
145
bool optimizer::QuickRorIntersectSelect::is_keys_used(const MyBitmap *fields)
147
for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
148
it != quick_selects.end();
151
if (is_key_used(head, (*it)->index, fields))
160
int optimizer::QuickRorIntersectSelect::get_next()
162
optimizer::QuickRangeSelect *quick= NULL;
163
vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
166
uint32_t last_rowid_count= 0;
170
/* Get a rowid for first quick and save it as a 'candidate' */
173
error= quick->get_next();
176
while (! error && ! cpk_quick->row_in_ranges())
177
error= quick->get_next();
182
quick->cursor->position(quick->record);
183
memcpy(last_rowid, quick->cursor->ref, head->cursor->ref_length);
186
while (last_rowid_count < quick_selects.size())
188
/** @todo: fix this madness!!!! */
189
if (it != quick_selects.end())
196
it= quick_selects.begin();
203
if ((error= quick->get_next()))
205
quick->cursor->position(quick->record);
206
cmp= head->cursor->cmp_ref(quick->cursor->ref, last_rowid);
209
/* Ok, current select 'caught up' and returned ref >= cur_ref */
212
/* Found a row with ref > cur_ref. Make it a new 'candidate' */
215
while (! cpk_quick->row_in_ranges())
217
if ((error= quick->get_next()))
221
memcpy(last_rowid, quick->cursor->ref, head->cursor->ref_length);
226
/* current 'candidate' row confirmed by this select */
231
/* We get here if we got the same row ref in all scans. */
232
if (need_to_fetch_row)
233
error= head->cursor->rnd_pos(head->record[0], last_rowid);
234
} while (error == HA_ERR_RECORD_DELETED);
239
void optimizer::QuickRorIntersectSelect::add_info_string(String *str)
242
str->append(STRING_WITH_LEN("intersect("));
243
for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
244
it != quick_selects.end();
247
KEY *key_info= head->key_info + (*it)->index;
252
str->append(key_info->name);
256
KEY *key_info= head->key_info + cpk_quick->index;
258
str->append(key_info->name);
264
void optimizer::QuickRorIntersectSelect::add_keys_and_lengths(String *key_names,
265
String *used_lengths)
270
for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
271
it != quick_selects.end();
274
KEY *key_info= head->key_info + (*it)->index;
281
key_names->append(',');
282
used_lengths->append(',');
284
key_names->append(key_info->name);
285
length= int64_t2str((*it)->max_used_key_length, buf, 10) - buf;
286
used_lengths->append(buf, length);
291
KEY *key_info= head->key_info + cpk_quick->index;
292
key_names->append(',');
293
key_names->append(key_info->name);
294
length= int64_t2str(cpk_quick->max_used_key_length, buf, 10) - buf;
295
used_lengths->append(',');
296
used_lengths->append(buf, length);