~drizzle-trunk/drizzle/development

1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2008-2009 Sun Microsystems, Inc.
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
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
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
20
#include <config.h>
2154.2.24 by Brian Aker
Merge in all changes for current_session, etc.
21
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
22
#include <drizzled/session.h>
23
#include <drizzled/optimizer/quick_range.h>
24
#include <drizzled/optimizer/quick_range_select.h>
25
#include <drizzled/internal/m_string.h>
2154.2.24 by Brian Aker
Merge in all changes for current_session, etc.
26
#include <drizzled/current_session.h>
2198.1.1 by Olaf van der Spek
Remove unnecessary alter* includes
27
#include <drizzled/key.h>
2234.1.3 by Olaf van der Spek
Refactor includes
28
#include <drizzled/table.h>
2239.1.9 by Olaf van der Spek
Refactor includes
29
#include <drizzled/util/test.h>
2241.3.2 by Olaf van der Spek
Refactor Session::variables
30
#include <drizzled/system_variables.h>
2154.2.24 by Brian Aker
Merge in all changes for current_session, etc.
31
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
32
#include <fcntl.h>
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
33
34
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
35
2241.3.2 by Olaf van der Spek
Refactor Session::variables
36
namespace drizzled {
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
37
38
1240.3.1 by Brian Aker
Merge Padraig.
39
optimizer::QuickRangeSelect::QuickRangeSelect(Session *session,
40
                                              Table *table,
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
41
                                              uint32_t key_nr,
1240.3.1 by Brian Aker
Merge Padraig.
42
                                              bool no_alloc,
1802.16.5 by Padraig O'Sullivan
Adding help method for dynamic bitset functions. Temporary until MyBitmap is removed. Got rid of another MyBitmap usage in the range optimizer.
43
                                              memory::Root *parent_alloc)
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
44
  :
45
    cursor(NULL),
46
    ranges(),
47
    in_ror_merged_scan(false),
1802.16.5 by Padraig O'Sullivan
Adding help method for dynamic bitset functions. Temporary until MyBitmap is removed. Got rid of another MyBitmap usage in the range optimizer.
48
    column_bitmap(NULL),
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
49
    save_read_set(NULL),
50
    save_write_set(NULL),
51
    free_file(false),
52
    cur_range(NULL),
53
    last_range(NULL),
54
    qr_traversal_ctx(),
55
    mrr_buf_size(0),
56
    key_parts(NULL),
1513 by Brian Aker
This patch reverts the ROR change which created a memory leak (bzr diff -r 1294..1293)
57
    dont_free(false),
58
    mrr_flags(0),
59
    alloc()
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
60
{
61
  sorted= 0;
62
  index= key_nr;
63
  head= table;
64
  key_part_info= head->key_info[index].key_part;
2385.3.7 by Olaf van der Spek
Refactor DYNAMIC_ARRAY
65
  ranges.init(sizeof(optimizer::QuickRange*), 16, 16);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
66
67
  /* 'session' is not accessible in QuickRangeSelect::reset(). */
68
  mrr_buf_size= session->variables.read_rnd_buff_size;
69
70
  if (! no_alloc && ! parent_alloc)
71
  {
72
    // Allocates everything through the internal memroot
2318.6.23 by Olaf van der Spek
Refactor
73
    alloc.init(session->variables.range_alloc_block_size);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
74
    session->mem_root= &alloc;
75
  }
76
  else
77
  {
78
    memset(&alloc, 0, sizeof(alloc));
79
  }
80
81
  cursor= head->cursor;
82
  record= head->record[0];
83
  save_read_set= head->read_set;
84
  save_write_set= head->write_set;
1802.16.5 by Padraig O'Sullivan
Adding help method for dynamic bitset functions. Temporary until MyBitmap is removed. Got rid of another MyBitmap usage in the range optimizer.
85
  column_bitmap= new boost::dynamic_bitset<>(table->getShare()->sizeFields());
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
86
}
87
88
89
int optimizer::QuickRangeSelect::init()
90
{
91
  if (cursor->inited != Cursor::NONE)
92
    cursor->ha_index_or_rnd_end();
1491.1.6 by Jay Pipes
Cursor::ha_index_init() -> Cursor::startIndexScan(). Cursor::ha_index_end() -> Cursor::endIndexScan()
93
  return (cursor->startIndexScan(index, 1));
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
94
}
95
96
97
void optimizer::QuickRangeSelect::range_end()
98
{
99
  if (cursor->inited != Cursor::NONE)
100
    cursor->ha_index_or_rnd_end();
101
}
102
103
104
optimizer::QuickRangeSelect::~QuickRangeSelect()
105
{
106
  if (! dont_free)
107
  {
108
    /* cursor is NULL for CPK scan on covering ROR-intersection */
109
    if (cursor)
110
    {
111
      range_end();
112
      if (head->key_read)
113
      {
114
        head->key_read= 0;
115
        cursor->extra(HA_EXTRA_NO_KEYREAD);
116
      }
117
      if (free_file)
118
      {
119
        cursor->ha_external_lock(current_session, F_UNLCK);
120
        cursor->close();
121
        delete cursor;
122
      }
123
    }
2385.3.7 by Olaf van der Spek
Refactor DYNAMIC_ARRAY
124
    ranges.free(); /* ranges are allocated in alloc */
1802.16.5 by Padraig O'Sullivan
Adding help method for dynamic bitset functions. Temporary until MyBitmap is removed. Got rid of another MyBitmap usage in the range optimizer.
125
    delete column_bitmap;
1487 by Brian Aker
More updates for memory::Root
126
    alloc.free_root(MYF(0));
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
127
  }
1802.16.8 by Padraig O'Sullivan
Removal of all MyBitmap from the code base. Compiles but test failures exist now.
128
  head->column_bitmaps_set(*save_read_set, *save_write_set);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
129
}
130
131
132
int optimizer::QuickRangeSelect::init_ror_merged_scan(bool reuse_handler)
133
{
2385.3.7 by Olaf van der Spek
Refactor DYNAMIC_ARRAY
134
  Cursor* org_file;
135
  Cursor* save_file= cursor;
136
  Session* session;
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
137
138
  in_ror_merged_scan= 1;
139
  if (reuse_handler)
140
  {
141
    if (init() || reset())
142
    {
143
      return 0;
144
    }
1802.16.5 by Padraig O'Sullivan
Adding help method for dynamic bitset functions. Temporary until MyBitmap is removed. Got rid of another MyBitmap usage in the range optimizer.
145
    head->column_bitmaps_set(*column_bitmap, *column_bitmap);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
146
    goto end;
147
  }
148
149
  /* Create a separate Cursor object for this quick select */
150
  if (free_file)
151
  {
152
    /* already have own 'Cursor' object. */
153
    return 0;
154
  }
155
156
  session= head->in_use;
2385.3.7 by Olaf van der Spek
Refactor DYNAMIC_ARRAY
157
  if (not (cursor= head->cursor->clone(session->mem_root)))
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
158
  {
159
    /*
160
      Manually set the error flag. Note: there seems to be quite a few
161
      places where a failure could cause the server to "hang" the client by
162
      sending no response to a query. ATM those are not real errors because
163
      the storage engine calls in question happen to never fail with the
164
      existing storage engines.
165
    */
166
    my_error(ER_OUT_OF_RESOURCES, MYF(0));
167
    /* Caller will free the memory */
168
    goto failure;
169
  }
170
1802.16.5 by Padraig O'Sullivan
Adding help method for dynamic bitset functions. Temporary until MyBitmap is removed. Got rid of another MyBitmap usage in the range optimizer.
171
  head->column_bitmaps_set(*column_bitmap, *column_bitmap);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
172
173
  if (cursor->ha_external_lock(session, F_RDLCK))
174
    goto failure;
175
176
  if (init() || reset())
177
  {
178
    cursor->ha_external_lock(session, F_UNLCK);
179
    cursor->close();
180
    goto failure;
181
  }
182
  free_file= true;
183
  last_rowid= cursor->ref;
184
185
end:
186
  /*
187
    We are only going to read key fields and call position() on 'cursor'
188
    The following sets head->tmp_set to only use this key and then updates
189
    head->read_set and head->write_set to use this bitmap.
190
    The now bitmap is stored in 'column_bitmap' which is used in ::get_next()
191
  */
192
  org_file= head->cursor;
193
  head->cursor= cursor;
194
  /* We don't have to set 'head->keyread' here as the 'cursor' is unique */
2385.3.7 by Olaf van der Spek
Refactor DYNAMIC_ARRAY
195
  if (not head->no_keyread)
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
196
  {
197
    head->key_read= 1;
198
    head->mark_columns_used_by_index(index);
199
  }
200
  head->prepare_for_position();
201
  head->cursor= org_file;
1802.16.11 by Padraig O'Sullivan
Remove cpp and header file with MyBitmap class and associated functions. No longer needed.
202
  *column_bitmap|= *head->read_set;
1802.16.5 by Padraig O'Sullivan
Adding help method for dynamic bitset functions. Temporary until MyBitmap is removed. Got rid of another MyBitmap usage in the range optimizer.
203
  head->column_bitmaps_set(*column_bitmap, *column_bitmap);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
204
205
  return 0;
206
207
failure:
1802.16.8 by Padraig O'Sullivan
Removal of all MyBitmap from the code base. Compiles but test failures exist now.
208
  head->column_bitmaps_set(*save_read_set, *save_write_set);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
209
  delete cursor;
210
  cursor= save_file;
211
  return 0;
212
}
213
214
215
void optimizer::QuickRangeSelect::save_last_pos()
216
{
217
  cursor->position(record);
218
}
219
220
1237.13.11 by Padraig O'Sullivan
Split the QUICK_ROR_INTERSECT_SELECT class out into its own header and implementation files.
221
bool optimizer::QuickRangeSelect::unique_key_range() const
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
222
{
2221.7.1 by Olaf van der Spek
DYNAMIC_ARRAY::size()
223
  if (ranges.size() == 1)
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
224
  {
225
    optimizer::QuickRange *tmp= *((optimizer::QuickRange**)ranges.buffer);
226
    if ((tmp->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE)
227
    {
1535 by Brian Aker
Rename of KEY to KeyInfo
228
      KeyInfo *key=head->key_info+index;
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
229
      return ((key->flags & (HA_NOSAME)) == HA_NOSAME &&
230
	      key->key_length == tmp->min_length);
231
    }
232
  }
233
  return false;
234
}
235
236
237
int optimizer::QuickRangeSelect::reset()
238
{
239
  int error= 0;
240
  last_range= NULL;
241
  cur_range= (optimizer::QuickRange**) ranges.buffer;
242
1491.1.6 by Jay Pipes
Cursor::ha_index_init() -> Cursor::startIndexScan(). Cursor::ha_index_end() -> Cursor::endIndexScan()
243
  if (cursor->inited == Cursor::NONE && (error= cursor->startIndexScan(index, 1)))
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
244
  {
245
    return error;
246
  }
247
1493 by Brian Aker
Remove dead call around "fixing" case where MRR lacked buffer.
248
  /*
249
    (in the past) Allocate buffer if we need one but haven't allocated it yet 
250
    There is a later assert in th code that hoped to catch random free() that might
251
    have done this.
252
  */
1682.1.1 by Stewart Smith
remove the unused HANDLER_BUFFER struct, typedef and members that were unused
253
  assert(not (mrr_buf_size));
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
254
255
  if (sorted)
256
  {
257
     mrr_flags|= HA_MRR_SORTED;
258
  }
259
  RANGE_SEQ_IF seq_funcs= {
1240.3.1 by Brian Aker
Merge Padraig.
260
    optimizer::quick_range_seq_init,
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
261
    optimizer::quick_range_seq_next
262
  };
1240.3.1 by Brian Aker
Merge Padraig.
263
  error= cursor->multi_range_read_init(&seq_funcs,
264
                                       (void*) this,
2221.7.1 by Olaf van der Spek
DYNAMIC_ARRAY::size()
265
                                       ranges.size(),
1491 by Brian Aker
Remove call bits in dead mrr caller.
266
                                       mrr_flags);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
267
  return error;
268
}
269
270
271
int optimizer::QuickRangeSelect::get_next()
272
{
273
  char *dummy= NULL;
274
  if (in_ror_merged_scan)
275
  {
276
    /*
277
      We don't need to signal the bitmap change as the bitmap is always the
278
      same for this head->cursor
279
    */
1802.16.5 by Padraig O'Sullivan
Adding help method for dynamic bitset functions. Temporary until MyBitmap is removed. Got rid of another MyBitmap usage in the range optimizer.
280
    head->column_bitmaps_set(*column_bitmap, *column_bitmap);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
281
  }
282
283
  int result= cursor->multi_range_read_next(&dummy);
284
285
  if (in_ror_merged_scan)
286
  {
287
    /* Restore bitmaps set on entry */
1802.16.8 by Padraig O'Sullivan
Removal of all MyBitmap from the code base. Compiles but test failures exist now.
288
    head->column_bitmaps_set(*save_read_set, *save_write_set);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
289
  }
290
  return result;
291
}
292
293
294
int optimizer::QuickRangeSelect::get_next_prefix(uint32_t prefix_length,
295
                                                 key_part_map keypart_map,
296
                                                 unsigned char *cur_prefix)
297
{
298
  for (;;)
299
  {
300
    int result;
301
    key_range start_key, end_key;
302
    if (last_range)
303
    {
304
      /* Read the next record in the same range with prefix after cur_prefix. */
305
      assert(cur_prefix != 0);
1240.3.1 by Brian Aker
Merge Padraig.
306
      result= cursor->index_read_map(record,
307
                                     cur_prefix,
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
308
                                     keypart_map,
309
                                     HA_READ_AFTER_KEY);
310
      if (result || (cursor->compare_key(cursor->end_range) <= 0))
311
        return result;
312
    }
313
2221.7.1 by Olaf van der Spek
DYNAMIC_ARRAY::size()
314
    uint32_t count= ranges.size() - (cur_range - (optimizer::QuickRange**) ranges.buffer);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
315
    if (count == 0)
316
    {
317
      /* Ranges have already been used up before. None is left for read. */
318
      last_range= 0;
319
      return HA_ERR_END_OF_FILE;
320
    }
321
    last_range= *(cur_range++);
322
323
    start_key.key= (const unsigned char*) last_range->min_key;
324
    start_key.length= min(last_range->min_length, (uint16_t)prefix_length);
325
    start_key.keypart_map= last_range->min_keypart_map & keypart_map;
326
    start_key.flag= ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
327
		                                                (last_range->flag & EQ_RANGE) ?
328
		                                                HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
329
    end_key.key= (const unsigned char*) last_range->max_key;
330
    end_key.length= min(last_range->max_length, (uint16_t)prefix_length);
331
    end_key.keypart_map= last_range->max_keypart_map & keypart_map;
332
    /*
333
      We use READ_AFTER_KEY here because if we are reading on a key
334
      prefix we want to find all keys with this prefix
335
    */
336
    end_key.flag= (last_range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
337
		                                             HA_READ_AFTER_KEY);
338
339
    result= cursor->read_range_first(last_range->min_keypart_map ? &start_key : 0,
340
				                             last_range->max_keypart_map ? &end_key : 0,
341
                                     test(last_range->flag & EQ_RANGE),
342
				                             sorted);
343
    if (last_range->flag == (UNIQUE_RANGE | EQ_RANGE))
344
      last_range= 0; // Stop searching
345
346
    if (result != HA_ERR_END_OF_FILE)
347
      return result;
348
    last_range= 0; // No matching rows; go to next range
349
  }
350
}
351
352
353
bool optimizer::QuickRangeSelect::row_in_ranges()
354
{
355
  optimizer::QuickRange *res= NULL;
356
  uint32_t min= 0;
2221.7.1 by Olaf van der Spek
DYNAMIC_ARRAY::size()
357
  uint32_t max= ranges.size() - 1;
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
358
  uint32_t mid= (max + min) / 2;
359
360
  while (min != max)
361
  {
2210.3.1 by Olaf van der Spek
Remove o
362
    if (cmp_next(reinterpret_cast<optimizer::QuickRange**>(ranges.buffer)[mid]))
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
363
    {
364
      /* current row value > mid->max */
365
      min= mid + 1;
366
    }
367
    else
368
      max= mid;
369
    mid= (min + max) / 2;
370
  }
2210.3.1 by Olaf van der Spek
Remove o
371
  res= reinterpret_cast<optimizer::QuickRange**>(ranges.buffer)[mid];
372
  return not cmp_next(res) && not cmp_prev(res);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
373
}
374
375
376
int optimizer::QuickRangeSelect::cmp_next(optimizer::QuickRange *range_arg)
377
{
378
  if (range_arg->flag & NO_MAX_RANGE)
379
    return 0;                                   /* key can't be to large */
380
381
  KEY_PART *key_part= key_parts;
382
  uint32_t store_length;
383
384
  for (unsigned char *key=range_arg->max_key, *end=key+range_arg->max_length;
385
       key < end;
386
       key+= store_length, key_part++)
387
  {
388
    int cmp;
389
    store_length= key_part->store_length;
390
    if (key_part->null_bit)
391
    {
392
      if (*key)
393
      {
394
        if (! key_part->field->is_null())
395
          return 1;
396
        continue;
397
      }
398
      else if (key_part->field->is_null())
399
        return 0;
400
      key++;					// Skip null byte
401
      store_length--;
402
    }
403
    if ((cmp= key_part->field->key_cmp(key, key_part->length)) < 0)
404
      return 0;
405
    if (cmp > 0)
406
      return 1;
407
  }
408
  return (range_arg->flag & NEAR_MAX) ? 1 : 0;          // Exact match
409
}
410
411
412
int optimizer::QuickRangeSelect::cmp_prev(optimizer::QuickRange *range_arg)
413
{
414
  if (range_arg->flag & NO_MIN_RANGE)
1237.13.25 by Padraig O'Sullivan
Replaced an instance of List with std::vector in the range optimizer.
415
    return 0; /* key can't be to small */
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
416
1237.13.25 by Padraig O'Sullivan
Replaced an instance of List with std::vector in the range optimizer.
417
  int cmp= key_cmp(key_part_info,
418
                   range_arg->min_key,
419
                   range_arg->min_length);
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
420
  if (cmp > 0 || (cmp == 0 && (range_arg->flag & NEAR_MIN) == false))
421
    return 0;
1237.13.25 by Padraig O'Sullivan
Replaced an instance of List with std::vector in the range optimizer.
422
  return 1; // outside of range
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
423
}
424
425
2170.4.5 by Stewart Smith
convert explain_plan extra String to std::string. This means that add_info_string() also gets converted to std::string
426
void optimizer::QuickRangeSelect::add_info_string(string *str)
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
427
{
1535 by Brian Aker
Rename of KEY to KeyInfo
428
  KeyInfo *key_info= head->key_info + index;
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
429
  str->append(key_info->name);
430
}
431
432
2170.4.3 by Stewart Smith
convert tmp2 in explain_plan to std::string instead of char[] buf and String, consequently also convert add_keys_and_length to deal with std::string for key_names parameter
433
void optimizer::QuickRangeSelect::add_keys_and_lengths(string *key_names,
2170.4.4 by Stewart Smith
tmp3 String to std::string in explain_plan (and used_lengths parameter to add_keys_and_lengths
434
                                                       string *used_lengths)
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
435
{
436
  char buf[64];
437
  uint32_t length;
1535 by Brian Aker
Rename of KEY to KeyInfo
438
  KeyInfo *key_info= head->key_info + index;
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
439
  key_names->append(key_info->name);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
440
  length= internal::int64_t2str(max_used_key_length, buf, 10) - buf;
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
441
  used_lengths->append(buf, length);
442
}
443
444
445
/*
446
  This is a hack: we inherit from QUICK_SELECT so that we can use the
447
  get_next() interface, but we have to hold a pointer to the original
448
  QUICK_SELECT because its data are used all over the place.  What
449
  should be done is to factor out the data that is needed into a base
450
  class (QUICK_SELECT), and then have two subclasses (_ASC and _DESC)
451
  which handle the ranges and implement the get_next() function.  But
452
  for now, this seems to work right at least.
453
 */
454
optimizer::QuickSelectDescending::QuickSelectDescending(optimizer::QuickRangeSelect *q, uint32_t, bool *)
455
  :
1237.13.25 by Padraig O'Sullivan
Replaced an instance of List with std::vector in the range optimizer.
456
    optimizer::QuickRangeSelect(*q)
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
457
{
1237.13.16 by Padraig O'Sullivan
Replaced List with std::vector in the QuickRorIntersectSelect class.
458
  optimizer::QuickRange **pr= (optimizer::QuickRange**) ranges.buffer;
2221.7.1 by Olaf van der Spek
DYNAMIC_ARRAY::size()
459
  optimizer::QuickRange **end_range= pr + ranges.size();
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
460
  for (; pr != end_range; pr++)
1237.13.25 by Padraig O'Sullivan
Replaced an instance of List with std::vector in the range optimizer.
461
  {
462
    rev_ranges.push_back(*pr);
463
  }
464
  rev_it= rev_ranges.begin();
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
465
466
  /* Remove EQ_RANGE flag for keys that are not using the full key */
2318.6.64 by Olaf van der Spek
Refactor
467
  BOOST_FOREACH(QuickRange* it, rev_ranges)
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
468
  {
2318.6.64 by Olaf van der Spek
Refactor
469
    if ((it->flag & EQ_RANGE) && head->key_info[index].key_length != it->max_length)
1237.13.25 by Padraig O'Sullivan
Replaced an instance of List with std::vector in the range optimizer.
470
    {
2318.6.64 by Olaf van der Spek
Refactor
471
      it->flag&= ~EQ_RANGE;
1237.13.25 by Padraig O'Sullivan
Replaced an instance of List with std::vector in the range optimizer.
472
    }
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
473
  }
1237.13.25 by Padraig O'Sullivan
Replaced an instance of List with std::vector in the range optimizer.
474
  q->dont_free= 1; // Don't free shared mem
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
475
  delete q;
476
}
477
478
479
int optimizer::QuickSelectDescending::get_next()
480
{
481
  /* The max key is handled as follows:
482
   *   - if there is NO_MAX_RANGE, start at the end and move backwards
483
   *   - if it is an EQ_RANGE, which means that max key covers the entire
484
   *     key, go directly to the key and read through it (sorting backwards is
485
   *     same as sorting forwards)
486
   *   - if it is NEAR_MAX, go to the key or next, step back once, and
487
   *     move backwards
488
   *   - otherwise (not NEAR_MAX == include the key), go after the key,
489
   *     step back once, and move backwards
490
   */
491
  for (;;)
492
  {
493
    int result;
494
    if (last_range)
495
    {						// Already read through key
496
      result= ((last_range->flag & EQ_RANGE) ?
497
		           cursor->index_next_same(record, last_range->min_key,
498
					                             last_range->min_length) :
499
		           cursor->index_prev(record));
500
      if (! result)
501
      {
1237.13.25 by Padraig O'Sullivan
Replaced an instance of List with std::vector in the range optimizer.
502
          if (cmp_prev(*(rev_it - 1)) == 0)
503
            return 0;
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
504
      }
505
      else if (result != HA_ERR_END_OF_FILE)
506
        return result;
507
    }
508
1237.13.25 by Padraig O'Sullivan
Replaced an instance of List with std::vector in the range optimizer.
509
    if (rev_it == rev_ranges.end())
510
    {
511
      return HA_ERR_END_OF_FILE; // All ranges used
512
    }
513
    last_range= *rev_it;
514
    ++rev_it;
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
515
516
    if (last_range->flag & NO_MAX_RANGE)        // Read last record
517
    {
518
      int local_error;
519
      if ((local_error= cursor->index_last(record)))
520
        return local_error;	// Empty table
521
      if (cmp_prev(last_range) == 0)
522
        return 0;
523
      last_range= 0; // No match; go to next range
524
      continue;
525
    }
526
527
    if (last_range->flag & EQ_RANGE)
528
    {
1240.3.1 by Brian Aker
Merge Padraig.
529
      result = cursor->index_read_map(record,
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
530
                                      last_range->max_key,
531
                                      last_range->max_keypart_map,
532
                                      HA_READ_KEY_EXACT);
533
    }
534
    else
535
    {
536
      assert(last_range->flag & NEAR_MAX ||
537
             range_reads_after_key(last_range));
1240.3.1 by Brian Aker
Merge Padraig.
538
      result= cursor->index_read_map(record,
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
539
                                     last_range->max_key,
540
                                     last_range->max_keypart_map,
541
                                     ((last_range->flag & NEAR_MAX) ?
542
                                      HA_READ_BEFORE_KEY :
543
                                      HA_READ_PREFIX_LAST_OR_PREV));
544
    }
545
    if (result)
546
    {
547
      if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE)
548
        return result;
549
      last_range= 0;                            // Not found, to next range
550
      continue;
551
    }
552
    if (cmp_prev(last_range) == 0)
553
    {
554
      if (last_range->flag == (UNIQUE_RANGE | EQ_RANGE))
555
        last_range= 0;				// Stop searching
556
      return 0;				// Found key is in range
557
    }
558
    last_range= 0;                              // To next range
559
  }
560
}
561
562
563
/*
564
 * true if this range will require using HA_READ_AFTER_KEY
565
   See comment in get_next() about this
566
 */
567
bool optimizer::QuickSelectDescending::range_reads_after_key(optimizer::QuickRange *range_arg)
568
{
569
  return ((range_arg->flag & (NO_MAX_RANGE | NEAR_MAX)) ||
570
	        ! (range_arg->flag & EQ_RANGE) ||
571
	        head->key_info[index].key_length != range_arg->max_length) ? 1 : 0;
572
}
573
574
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
575
} /* namespace drizzled */