~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/quick_range_select.cc

  • Committer: Monty Taylor
  • Date: 2010-01-12 21:34:24 UTC
  • mto: This revision was merged to the branch mainline in revision 1268.
  • Revision ID: mordred@inaugust.com-20100112213424-6mslywtlca49mvnk
Updated to pandora-buld v0.94

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008-2009 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008-2009 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#include <config.h>
21
 
 
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>
26
 
#include <drizzled/current_session.h>
27
 
 
 
20
#include "config.h"
 
21
#include "drizzled/session.h"
 
22
#include "drizzled/optimizer/quick_range.h"
 
23
#include "drizzled/optimizer/quick_range_select.h"
 
24
#include "drizzled/sql_bitmap.h"
 
25
#include "drizzled/internal/m_string.h"
28
26
#include <fcntl.h>
 
27
#include "drizzled/memory/multi_malloc.h"
29
28
 
30
29
using namespace std;
31
 
 
32
 
namespace drizzled
33
 
{
 
30
using namespace drizzled;
34
31
 
35
32
 
36
33
optimizer::QuickRangeSelect::QuickRangeSelect(Session *session,
37
34
                                              Table *table,
38
35
                                              uint32_t key_nr,
39
36
                                              bool no_alloc,
40
 
                                              memory::Root *parent_alloc)
 
37
                                              memory::Root *parent_alloc,
 
38
                                              bool *create_error)
41
39
  :
42
40
    cursor(NULL),
43
41
    ranges(),
44
42
    in_ror_merged_scan(false),
45
 
    column_bitmap(NULL),
 
43
    column_bitmap(),
46
44
    save_read_set(NULL),
47
45
    save_write_set(NULL),
48
46
    free_file(false),
50
48
    last_range(NULL),
51
49
    qr_traversal_ctx(),
52
50
    mrr_buf_size(0),
 
51
    mrr_buf_desc(NULL),
53
52
    key_parts(NULL),
54
53
    dont_free(false),
55
54
    mrr_flags(0),
56
55
    alloc()
57
56
{
 
57
  my_bitmap_map *bitmap= NULL;
 
58
 
58
59
  sorted= 0;
59
60
  index= key_nr;
60
61
  head= table;
63
64
 
64
65
  /* 'session' is not accessible in QuickRangeSelect::reset(). */
65
66
  mrr_buf_size= session->variables.read_rnd_buff_size;
 
67
  mrr_buf_desc= NULL;
66
68
 
67
69
  if (! no_alloc && ! parent_alloc)
68
70
  {
79
81
  record= head->record[0];
80
82
  save_read_set= head->read_set;
81
83
  save_write_set= head->write_set;
82
 
  column_bitmap= new boost::dynamic_bitset<>(table->getShare()->sizeFields());
 
84
 
 
85
  /* Allocate a bitmap for used columns. Using memory::sql_alloc instead of malloc
 
86
     simply as a "fix" to the MySQL 6.0 code that also free()s it at the
 
87
     same time we destroy the mem_root.
 
88
   */
 
89
 
 
90
  bitmap= reinterpret_cast<my_bitmap_map*>(memory::sql_alloc(head->s->column_bitmap_size));
 
91
  if (! bitmap)
 
92
  {
 
93
    column_bitmap.setBitmap(NULL);
 
94
    *create_error= 1;
 
95
  }
 
96
  else
 
97
  {
 
98
    column_bitmap.init(bitmap, head->s->fields);
 
99
  }
83
100
}
84
101
 
85
102
 
87
104
{
88
105
  if (cursor->inited != Cursor::NONE)
89
106
    cursor->ha_index_or_rnd_end();
90
 
  return (cursor->startIndexScan(index, 1));
 
107
  return (cursor->ha_index_init(index, 1));
91
108
}
92
109
 
93
110
 
119
136
      }
120
137
    }
121
138
    delete_dynamic(&ranges); /* ranges are allocated in alloc */
122
 
    delete column_bitmap;
123
 
    alloc.free_root(MYF(0));
124
 
  }
125
 
  head->column_bitmaps_set(*save_read_set, *save_write_set);
 
139
    free_root(&alloc,MYF(0));
 
140
  }
 
141
  head->column_bitmaps_set(save_read_set, save_write_set);
 
142
  assert(mrr_buf_desc == NULL);
 
143
  if (mrr_buf_desc)
 
144
  {
 
145
    free(mrr_buf_desc);
 
146
  }
126
147
}
127
148
 
128
149
 
138
159
    {
139
160
      return 0;
140
161
    }
141
 
    head->column_bitmaps_set(*column_bitmap, *column_bitmap);
 
162
    head->column_bitmaps_set(&column_bitmap, &column_bitmap);
142
163
    goto end;
143
164
  }
144
165
 
164
185
    goto failure;
165
186
  }
166
187
 
167
 
  head->column_bitmaps_set(*column_bitmap, *column_bitmap);
 
188
  head->column_bitmaps_set(&column_bitmap, &column_bitmap);
168
189
 
169
190
  if (cursor->ha_external_lock(session, F_RDLCK))
170
191
    goto failure;
195
216
  }
196
217
  head->prepare_for_position();
197
218
  head->cursor= org_file;
198
 
  *column_bitmap|= *head->read_set;
199
 
  head->column_bitmaps_set(*column_bitmap, *column_bitmap);
 
219
  column_bitmap= *head->read_set;
 
220
  head->column_bitmaps_set(&column_bitmap, &column_bitmap);
200
221
 
201
222
  return 0;
202
223
 
203
224
failure:
204
 
  head->column_bitmaps_set(*save_read_set, *save_write_set);
 
225
  head->column_bitmaps_set(save_read_set, save_write_set);
205
226
  delete cursor;
206
227
  cursor= save_file;
207
228
  return 0;
221
242
    optimizer::QuickRange *tmp= *((optimizer::QuickRange**)ranges.buffer);
222
243
    if ((tmp->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE)
223
244
    {
224
 
      KeyInfo *key=head->key_info+index;
 
245
      KEY *key=head->key_info+index;
225
246
      return ((key->flags & (HA_NOSAME)) == HA_NOSAME &&
226
247
              key->key_length == tmp->min_length);
227
248
    }
232
253
 
233
254
int optimizer::QuickRangeSelect::reset()
234
255
{
 
256
  uint32_t buf_size= 0;
 
257
  unsigned char *mrange_buff= NULL;
235
258
  int error= 0;
 
259
  HANDLER_BUFFER empty_buf;
236
260
  last_range= NULL;
237
261
  cur_range= (optimizer::QuickRange**) ranges.buffer;
238
262
 
239
 
  if (cursor->inited == Cursor::NONE && (error= cursor->startIndexScan(index, 1)))
 
263
  if (cursor->inited == Cursor::NONE && (error= cursor->ha_index_init(index, 1)))
240
264
  {
241
265
    return error;
242
266
  }
243
267
 
244
 
  /*
245
 
    (in the past) Allocate buffer if we need one but haven't allocated it yet 
246
 
    There is a later assert in th code that hoped to catch random free() that might
247
 
    have done this.
248
 
  */
249
 
  assert(not (mrr_buf_size));
 
268
  /* Allocate buffer if we need one but haven't allocated it yet */
 
269
  if (mrr_buf_size && ! mrr_buf_desc)
 
270
  {
 
271
    buf_size= mrr_buf_size;
 
272
    while (buf_size && ! memory::multi_malloc(false,
 
273
                                              &mrr_buf_desc,
 
274
                                              sizeof(*mrr_buf_desc),
 
275
                                              &mrange_buff,
 
276
                                              buf_size,
 
277
                                              NULL))
 
278
    {
 
279
      /* Try to shrink the buffers until both are 0. */
 
280
      buf_size/= 2;
 
281
    }
 
282
    if (! mrr_buf_desc)
 
283
    {
 
284
      return HA_ERR_OUT_OF_MEM;
 
285
    }
 
286
 
 
287
    /* Initialize the Cursor buffer. */
 
288
    mrr_buf_desc->buffer= mrange_buff;
 
289
    mrr_buf_desc->buffer_end= mrange_buff + buf_size;
 
290
    mrr_buf_desc->end_of_used_area= mrange_buff;
 
291
  }
 
292
 
 
293
  if (! mrr_buf_desc)
 
294
  {
 
295
    empty_buf.buffer= NULL;
 
296
    empty_buf.buffer_end= NULL;
 
297
    empty_buf.end_of_used_area= NULL;
 
298
  }
250
299
 
251
300
  if (sorted)
252
301
  {
259
308
  error= cursor->multi_range_read_init(&seq_funcs,
260
309
                                       (void*) this,
261
310
                                       ranges.elements,
262
 
                                       mrr_flags);
 
311
                                       mrr_flags,
 
312
                                       mrr_buf_desc ? mrr_buf_desc : &empty_buf);
263
313
  return error;
264
314
}
265
315
 
273
323
      We don't need to signal the bitmap change as the bitmap is always the
274
324
      same for this head->cursor
275
325
    */
276
 
    head->column_bitmaps_set(*column_bitmap, *column_bitmap);
 
326
    head->column_bitmaps_set(&column_bitmap, &column_bitmap);
277
327
  }
278
328
 
279
329
  int result= cursor->multi_range_read_next(&dummy);
281
331
  if (in_ror_merged_scan)
282
332
  {
283
333
    /* Restore bitmaps set on entry */
284
 
    head->column_bitmaps_set(*save_read_set, *save_write_set);
 
334
    head->column_bitmaps_set(save_read_set, save_write_set);
285
335
  }
286
336
  return result;
287
337
}
407
457
 
408
458
int optimizer::QuickRangeSelect::cmp_prev(optimizer::QuickRange *range_arg)
409
459
{
 
460
  int cmp;
410
461
  if (range_arg->flag & NO_MIN_RANGE)
411
 
    return 0; /* key can't be to small */
 
462
    return 0;                                   /* key can't be to small */
412
463
 
413
 
  int cmp= key_cmp(key_part_info,
414
 
                   range_arg->min_key,
415
 
                   range_arg->min_length);
 
464
  cmp= key_cmp(key_part_info,
 
465
               range_arg->min_key,
 
466
               range_arg->min_length);
416
467
  if (cmp > 0 || (cmp == 0 && (range_arg->flag & NEAR_MIN) == false))
417
468
    return 0;
418
 
  return 1; // outside of range
 
469
  return 1;                                     // outside of range
419
470
}
420
471
 
421
472
 
422
 
void optimizer::QuickRangeSelect::add_info_string(string *str)
 
473
void optimizer::QuickRangeSelect::add_info_string(String *str)
423
474
{
424
 
  KeyInfo *key_info= head->key_info + index;
 
475
  KEY *key_info= head->key_info + index;
425
476
  str->append(key_info->name);
426
477
}
427
478
 
428
479
 
429
 
void optimizer::QuickRangeSelect::add_keys_and_lengths(string *key_names,
430
 
                                                       string *used_lengths)
 
480
void optimizer::QuickRangeSelect::add_keys_and_lengths(String *key_names,
 
481
                                                       String *used_lengths)
431
482
{
432
483
  char buf[64];
433
484
  uint32_t length;
434
 
  KeyInfo *key_info= head->key_info + index;
 
485
  KEY *key_info= head->key_info + index;
435
486
  key_names->append(key_info->name);
436
 
  length= internal::int64_t2str(max_used_key_length, buf, 10) - buf;
 
487
  length= int64_t2str(max_used_key_length, buf, 10) - buf;
437
488
  used_lengths->append(buf, length);
438
489
}
439
490
 
449
500
 */
450
501
optimizer::QuickSelectDescending::QuickSelectDescending(optimizer::QuickRangeSelect *q, uint32_t, bool *)
451
502
  :
452
 
    optimizer::QuickRangeSelect(*q)
 
503
    optimizer::QuickRangeSelect(*q),
 
504
    rev_it(rev_ranges)
453
505
{
 
506
  optimizer::QuickRange *r= NULL;
 
507
 
454
508
  optimizer::QuickRange **pr= (optimizer::QuickRange**) ranges.buffer;
455
509
  optimizer::QuickRange **end_range= pr + ranges.elements;
456
510
  for (; pr != end_range; pr++)
457
 
  {
458
 
    rev_ranges.push_back(*pr);
459
 
  }
460
 
  rev_it= rev_ranges.begin();
 
511
    rev_ranges.push_front(*pr);
461
512
 
462
513
  /* Remove EQ_RANGE flag for keys that are not using the full key */
463
 
  for (vector<optimizer::QuickRange *>::iterator it= rev_ranges.begin();
464
 
       it != rev_ranges.end();
465
 
       ++it)
 
514
  for (r = rev_it++; r; r= rev_it++)
466
515
  {
467
 
    optimizer::QuickRange *r= *it;
468
516
    if ((r->flag & EQ_RANGE) &&
469
517
        head->key_info[index].key_length != r->max_length)
470
 
    {
471
518
      r->flag&= ~EQ_RANGE;
472
 
    }
473
519
  }
474
 
  q->dont_free= 1; // Don't free shared mem
 
520
  rev_it.rewind();
 
521
  q->dont_free= 1;                              // Don't free shared mem
475
522
  delete q;
476
523
}
477
524
 
499
546
                           cursor->index_prev(record));
500
547
      if (! result)
501
548
      {
502
 
          if (cmp_prev(*(rev_it - 1)) == 0)
503
 
            return 0;
 
549
        if (cmp_prev(*rev_it.ref()) == 0)
 
550
          return 0;
504
551
      }
505
552
      else if (result != HA_ERR_END_OF_FILE)
506
553
        return result;
507
554
    }
508
555
 
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;
 
556
    if (! (last_range= rev_it++))
 
557
      return HA_ERR_END_OF_FILE;                // All ranges used
515
558
 
516
559
    if (last_range->flag & NO_MAX_RANGE)        // Read last record
517
560
    {
572
615
}
573
616
 
574
617
 
575
 
} /* namespace drizzled */