~ubuntu-branches/ubuntu/maverick/drizzle/maverick

« back to all changes in this revision

Viewing changes to drizzled/optimizer/quick_ror_intersect_select.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

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) 2008-2009 Sun Microsystems
 
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; version 2 of the License.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 */
 
19
 
 
20
#include "config.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"
 
26
#include "drizzled/internal/m_string.h"
 
27
 
 
28
#include <vector>
 
29
 
 
30
using namespace std;
 
31
 
 
32
namespace drizzled
 
33
{
 
34
 
 
35
 
 
36
optimizer::QuickRorIntersectSelect::QuickRorIntersectSelect(Session *session_param,
 
37
                                                            Table *table,
 
38
                                                            bool retrieve_full_rows,
 
39
                                                            memory::Root *parent_alloc)
 
40
  :
 
41
    cpk_quick(NULL),
 
42
    session(session_param),
 
43
    need_to_fetch_row(retrieve_full_rows),
 
44
    scans_inited(false)
 
45
{
 
46
  index= MAX_KEY;
 
47
  head= table;
 
48
  record= head->record[0];
 
49
  if (! parent_alloc)
 
50
  {
 
51
    memory::init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
 
52
  }
 
53
  else
 
54
  {
 
55
    memset(&alloc, 0, sizeof(memory::Root));
 
56
  }
 
57
  last_rowid= (unsigned char*) alloc_root(parent_alloc ? parent_alloc : &alloc,
 
58
                                          head->cursor->ref_length);
 
59
}
 
60
 
 
61
 
 
62
optimizer::QuickRorIntersectSelect::~QuickRorIntersectSelect()
 
63
{
 
64
  for_each(quick_selects.begin(),
 
65
           quick_selects.end(),
 
66
           DeletePtr());
 
67
  quick_selects.clear();
 
68
  delete cpk_quick;
 
69
  free_root(&alloc,MYF(0));
 
70
  if (need_to_fetch_row && head->cursor->inited != Cursor::NONE)
 
71
  {
 
72
    head->cursor->ha_rnd_end();
 
73
  }
 
74
  return;
 
75
}
 
76
 
 
77
 
 
78
int optimizer::QuickRorIntersectSelect::init()
 
79
{
 
80
 /* Check if last_rowid was successfully allocated in ctor */
 
81
  return (! last_rowid);
 
82
}
 
83
 
 
84
 
 
85
int optimizer::QuickRorIntersectSelect::init_ror_merged_scan(bool reuse_handler)
 
86
{
 
87
  vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
 
88
 
 
89
  /* Initialize all merged "children" quick selects */
 
90
  assert(! need_to_fetch_row || reuse_handler);
 
91
  if (! need_to_fetch_row && reuse_handler)
 
92
  {
 
93
    optimizer::QuickRangeSelect *quick= *it;
 
94
    ++it;
 
95
    /*
 
96
      There is no use of this->cursor. Use it for the first of merged range
 
97
      selects.
 
98
    */
 
99
    if (quick->init_ror_merged_scan(true))
 
100
      return 0;
 
101
    quick->cursor->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
 
102
  }
 
103
  while (it != quick_selects.end())
 
104
  {
 
105
    if ((*it)->init_ror_merged_scan(false))
 
106
    {
 
107
      return 0;
 
108
    }
 
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];
 
112
    ++it;
 
113
  }
 
114
 
 
115
  if (need_to_fetch_row && head->cursor->ha_rnd_init(1))
 
116
  {
 
117
    return 0;
 
118
  }
 
119
  return 0;
 
120
}
 
121
 
 
122
 
 
123
int optimizer::QuickRorIntersectSelect::reset()
 
124
{
 
125
  if (! scans_inited && init_ror_merged_scan(true))
 
126
  {
 
127
    return 0;
 
128
  }
 
129
  scans_inited= true;
 
130
  for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
 
131
       it != quick_selects.end();
 
132
       ++it)
 
133
  {
 
134
    (*it)->reset();
 
135
  }
 
136
  return 0;
 
137
}
 
138
 
 
139
 
 
140
bool
 
141
optimizer::QuickRorIntersectSelect::push_quick_back(optimizer::QuickRangeSelect *quick)
 
142
{
 
143
  quick_selects.push_back(quick);
 
144
  return false;
 
145
}
 
146
 
 
147
 
 
148
bool optimizer::QuickRorIntersectSelect::is_keys_used(const MyBitmap *fields)
 
149
{
 
150
  for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
 
151
       it != quick_selects.end();
 
152
       ++it)
 
153
  {
 
154
    if (is_key_used(head, (*it)->index, fields))
 
155
    {
 
156
      return 1;
 
157
    }
 
158
  }
 
159
  return 0;
 
160
}
 
161
 
 
162
 
 
163
int optimizer::QuickRorIntersectSelect::get_next()
 
164
{
 
165
  optimizer::QuickRangeSelect *quick= NULL;
 
166
  vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
 
167
  int error;
 
168
  int cmp;
 
169
  uint32_t last_rowid_count= 0;
 
170
 
 
171
  do
 
172
  {
 
173
    /* Get a rowid for first quick and save it as a 'candidate' */
 
174
    quick= *it;
 
175
    ++it;
 
176
    error= quick->get_next();
 
177
    if (cpk_quick)
 
178
    {
 
179
      while (! error && ! cpk_quick->row_in_ranges())
 
180
        error= quick->get_next();
 
181
    }
 
182
    if (error)
 
183
      return error;
 
184
 
 
185
    quick->cursor->position(quick->record);
 
186
    memcpy(last_rowid, quick->cursor->ref, head->cursor->ref_length);
 
187
    last_rowid_count= 1;
 
188
 
 
189
    while (last_rowid_count < quick_selects.size())
 
190
    {
 
191
      /** @todo: fix this madness!!!! */
 
192
      if (it != quick_selects.end())
 
193
      {
 
194
        quick= *it;
 
195
        ++it;
 
196
      }
 
197
      else
 
198
      {
 
199
        it= quick_selects.begin();
 
200
        quick= *it;
 
201
        ++it;
 
202
      }
 
203
 
 
204
      do
 
205
      {
 
206
        if ((error= quick->get_next()))
 
207
          return error;
 
208
        quick->cursor->position(quick->record);
 
209
        cmp= head->cursor->cmp_ref(quick->cursor->ref, last_rowid);
 
210
      } while (cmp < 0);
 
211
 
 
212
      /* Ok, current select 'caught up' and returned ref >= cur_ref */
 
213
      if (cmp > 0)
 
214
      {
 
215
        /* Found a row with ref > cur_ref. Make it a new 'candidate' */
 
216
        if (cpk_quick)
 
217
        {
 
218
          while (! cpk_quick->row_in_ranges())
 
219
          {
 
220
            if ((error= quick->get_next()))
 
221
              return error;
 
222
          }
 
223
        }
 
224
        memcpy(last_rowid, quick->cursor->ref, head->cursor->ref_length);
 
225
        last_rowid_count= 1;
 
226
      }
 
227
      else
 
228
      {
 
229
        /* current 'candidate' row confirmed by this select */
 
230
        last_rowid_count++;
 
231
      }
 
232
    }
 
233
 
 
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);
 
238
  return error;
 
239
}
 
240
 
 
241
 
 
242
void optimizer::QuickRorIntersectSelect::add_info_string(String *str)
 
243
{
 
244
  bool first= true;
 
245
  str->append(STRING_WITH_LEN("intersect("));
 
246
  for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
 
247
       it != quick_selects.end();
 
248
       ++it)
 
249
  {
 
250
    KEY *key_info= head->key_info + (*it)->index;
 
251
    if (! first)
 
252
      str->append(',');
 
253
    else
 
254
      first= false;
 
255
    str->append(key_info->name);
 
256
  }
 
257
  if (cpk_quick)
 
258
  {
 
259
    KEY *key_info= head->key_info + cpk_quick->index;
 
260
    str->append(',');
 
261
    str->append(key_info->name);
 
262
  }
 
263
  str->append(')');
 
264
}
 
265
 
 
266
 
 
267
void optimizer::QuickRorIntersectSelect::add_keys_and_lengths(String *key_names,
 
268
                                                              String *used_lengths)
 
269
{
 
270
  char buf[64];
 
271
  uint32_t length;
 
272
  bool first= true;
 
273
  for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
 
274
       it != quick_selects.end();
 
275
       ++it)
 
276
  {
 
277
    KEY *key_info= head->key_info + (*it)->index;
 
278
    if (first)
 
279
    {
 
280
      first= false;
 
281
    }
 
282
    else
 
283
    {
 
284
      key_names->append(',');
 
285
      used_lengths->append(',');
 
286
    }
 
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);
 
290
  }
 
291
 
 
292
  if (cpk_quick)
 
293
  {
 
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);
 
300
  }
 
301
}
 
302
 
 
303
} /* namespace drizzled */