~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/quick_range_select.h

Split some classes from the range optimizer out in to their own header and implementation files.
Corrected the case on these classes also to adhere to the coding standards. Cleaned up any style
issues in any code I came across while moving code.

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
#ifndef DRIZZLED_OPTIMIZER_QUICK_RANGE_SELECT_H
 
21
#define DRIZZLED_OPTIMIZER_QUICK_RANGE_SELECT_H
 
22
 
 
23
#include "drizzled/optimizer/range.h"
 
24
 
 
25
class Cursor;
 
26
 
 
27
namespace drizzled
 
28
{
 
29
 
 
30
namespace optimizer
 
31
{
 
32
 
 
33
/**
 
34
 * Quick select that does a range scan on a single key. 
 
35
 *
 
36
 * The records are returned in key order.
 
37
 * 
 
38
 */
 
39
class QuickRangeSelect : public QuickSelectInterface
 
40
{
 
41
protected:
 
42
  Cursor *cursor;
 
43
  DYNAMIC_ARRAY ranges; /**< ordered array of range ptrs */
 
44
 
 
45
  /** Members to deal with case when this quick select is a ROR-merged scan */
 
46
  bool in_ror_merged_scan;
 
47
  MyBitmap column_bitmap;
 
48
  MyBitmap *save_read_set;
 
49
  MyBitmap *save_write_set;
 
50
  bool free_file; /**< True when this->file is "owned" by this quick select */
 
51
 
 
52
  /* Range pointers to be used when not using MRR interface */
 
53
  QuickRange **cur_range; /**< current element in ranges  */
 
54
  QuickRange *last_range;
 
55
 
 
56
  /** Members needed to use the MRR interface */
 
57
  QuickRangeSequenceContext qr_traversal_ctx;
 
58
  uint32_t mrr_buf_size; /**< copy from session->variables.read_rnd_buff_size */
 
59
  HANDLER_BUFFER *mrr_buf_desc; /**< the Cursor buffer */
 
60
 
 
61
  /** Info about index we're scanning */
 
62
  KEY_PART *key_parts;
 
63
  KEY_PART_INFO *key_part_info;
 
64
 
 
65
  bool dont_free; /**< Used by QuickSelectDescending */
 
66
 
 
67
  /**
 
68
   * Compare if found key is over max-value
 
69
   * @return 0 if key <= range->max_key
 
70
   * @todo: Figure out why can't this function be as simple as cmp_prev().
 
71
   */
 
72
  int cmp_next(QuickRange *range);
 
73
 
 
74
  /**
 
75
   * @return 0 if found key is inside range (found key >= range->min_key).
 
76
   */
 
77
  int cmp_prev(QuickRange *range);
 
78
 
 
79
  /**
 
80
   * Check if current row will be retrieved by this QuickRangeSelect
 
81
   *
 
82
   * NOTES
 
83
   * It is assumed that currently a scan is being done on another index
 
84
   * which reads all necessary parts of the index that is scanned by this
 
85
   * quick select.
 
86
   * The implementation does a binary search on sorted array of disjoint
 
87
   * ranges, without taking size of range into account.
 
88
   *
 
89
   * This function is used to filter out clustered PK scan rows in
 
90
   * index_merge quick select.
 
91
   *
 
92
   * RETURN
 
93
   * @retval true  if current row will be retrieved by this quick select
 
94
   * false if not
 
95
   */
 
96
  bool row_in_ranges();
 
97
 
 
98
public:
 
99
 
 
100
  uint32_t mrr_flags; /**< Flags to be used with MRR interface */
 
101
 
 
102
  MEM_ROOT alloc;
 
103
 
 
104
  QuickRangeSelect(Session *session,
 
105
                     Table *table,
 
106
                     uint32_t index_arg,
 
107
                     bool no_alloc,
 
108
                     MEM_ROOT *parent_alloc,
 
109
                     bool *create_err);
 
110
 
 
111
  ~QuickRangeSelect();
 
112
 
 
113
  int init();
 
114
 
 
115
  int reset(void);
 
116
 
 
117
  /**
 
118
   * Get next possible record using quick-struct.
 
119
   *
 
120
   * SYNOPSIS
 
121
   * QuickRangeSelect::get_next()
 
122
   *
 
123
   * NOTES
 
124
   * Record is read into table->record[0]
 
125
   *
 
126
   * RETURN
 
127
   * @retval 0                  Found row
 
128
   * @retval HA_ERR_END_OF_FILE No (more) rows in range
 
129
   * @retaval # Error code
 
130
   */
 
131
  int get_next();
 
132
 
 
133
  void range_end();
 
134
 
 
135
  /**
 
136
   * Get the next record with a different prefix.
 
137
   *
 
138
   * SYNOPSIS
 
139
   * QuickRangeSelect::get_next_prefix()
 
140
   * @param[in] prefix_length  length of cur_prefix
 
141
   * @param[in] cur_prefix     prefix of a key to be searched for
 
142
   *
 
143
   * DESCRIPTION
 
144
   * Each subsequent call to the method retrieves the first record that has a
 
145
   * prefix with length prefix_length different from cur_prefix, such that the
 
146
   * record with the new prefix is within the ranges described by
 
147
   * this->ranges. The record found is stored into the buffer pointed by
 
148
   * this->record.
 
149
   * The method is useful for GROUP-BY queries with range conditions to
 
150
   * discover the prefix of the next group that satisfies the range conditions.
 
151
   *
 
152
   * @todo
 
153
   * This method is a modified copy of QuickRangeSelect::get_next(), so both
 
154
   * methods should be unified into a more general one to reduce code
 
155
   * duplication.
 
156
   *
 
157
   * RETURN
 
158
   * @retval 0                  on success
 
159
   * @retval HA_ERR_END_OF_FILE if returned all keys
 
160
   * @retval other              if some error occurred
 
161
   */
 
162
  int get_next_prefix(uint32_t prefix_length,
 
163
                      key_part_map keypart_map,
 
164
                      unsigned char *cur_prefix);
 
165
 
 
166
  bool reverse_sorted()
 
167
  {
 
168
    return false;
 
169
  }
 
170
 
 
171
  /**
 
172
   * @return true if there is only one range and this uses the whole primary key
 
173
   */
 
174
  bool unique_key_range();
 
175
 
 
176
  /**
 
177
   * Initialize this quick select to be a ROR-merged scan.
 
178
   *
 
179
   * SYNOPSIS
 
180
   * QuickRangeSelect::init_ror_merged_scan()
 
181
   * @param[in] reuse_handler If true, use head->cursor, otherwise create a separate Cursor object
 
182
   *
 
183
   * NOTES
 
184
   * This function creates and prepares for subsequent use a separate Cursor
 
185
   * object if it can't reuse head->cursor. The reason for this is that during
 
186
   * ROR-merge several key scans are performed simultaneously, and a single
 
187
   * Cursor is only capable of preserving context of a single key scan.
 
188
   *
 
189
   * In ROR-merge the quick select doing merge does full records retrieval,
 
190
   * merged quick selects read only keys.
 
191
   *
 
192
   * RETURN
 
193
   * @reval 0  ROR child scan initialized, ok to use.
 
194
   * @retval 1  error
 
195
   */
 
196
  int init_ror_merged_scan(bool reuse_handler);
 
197
 
 
198
  void save_last_pos();
 
199
 
 
200
  int get_type()
 
201
  {
 
202
    return QS_TYPE_RANGE;
 
203
  }
 
204
 
 
205
  void add_keys_and_lengths(String *key_names, String *used_lengths);
 
206
 
 
207
  void add_info_string(String *str);
 
208
 
 
209
  void resetCursor()
 
210
  {
 
211
    cursor= NULL;
 
212
  }
 
213
 
 
214
private:
 
215
 
 
216
  /* Used only by QuickSelectDescending */
 
217
  QuickRangeSelect(const QuickRangeSelect& org) : QuickSelectInterface()
 
218
  {
 
219
    memmove(this, &org, sizeof(*this));
 
220
    /*
 
221
      Use default MRR implementation for reverse scans. No table engine
 
222
      currently can do an MRR scan with output in reverse index order.
 
223
    */
 
224
    mrr_buf_desc= NULL;
 
225
    mrr_flags|= HA_MRR_USE_DEFAULT_IMPL;
 
226
    mrr_buf_size= 0;
 
227
  }
 
228
 
 
229
  friend class ::TRP_ROR_INTERSECT; 
 
230
 
 
231
  friend
 
232
  QuickRangeSelect *get_quick_select_for_ref(Session *session, Table *table,
 
233
                                             struct table_reference_st *ref,
 
234
                                             ha_rows records);
 
235
 
 
236
  friend bool get_quick_keys(PARAM *param, 
 
237
                             QuickRangeSelect *quick,
 
238
                             KEY_PART *key, 
 
239
                             SEL_ARG *key_tree,
 
240
                             unsigned char *min_key, 
 
241
                             uint32_t min_key_flag,
 
242
                             unsigned char *max_key, 
 
243
                             uint32_t max_key_flag);
 
244
 
 
245
  friend QuickRangeSelect *get_quick_select(PARAM*,uint32_t idx,
 
246
                                            SEL_ARG *key_tree,
 
247
                                            uint32_t mrr_flags,
 
248
                                            uint32_t mrr_buf_size,
 
249
                                            MEM_ROOT *alloc);
 
250
  friend class QuickSelectDescending;
 
251
 
 
252
  friend class QuickIndexMergeSelect;
 
253
 
 
254
  friend class QUICK_ROR_INTERSECT_SELECT;
 
255
 
 
256
  friend class QUICK_GROUP_MIN_MAX_SELECT;
 
257
 
 
258
  friend uint32_t quick_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range);
 
259
 
 
260
  friend range_seq_t quick_range_seq_init(void *init_param,
 
261
                                          uint32_t n_ranges, 
 
262
                                          uint32_t flags);
 
263
 
 
264
  friend void select_describe(JOIN *join, 
 
265
                              bool need_tmp_table, 
 
266
                              bool need_order,
 
267
                              bool distinct,
 
268
                              const char *message);
 
269
};
 
270
 
 
271
class QuickSelectDescending : public QuickRangeSelect
 
272
{
 
273
public:
 
274
 
 
275
  QuickSelectDescending(QuickRangeSelect *q, 
 
276
                        uint32_t used_key_parts,
 
277
                        bool *create_err);
 
278
 
 
279
  int get_next();
 
280
 
 
281
  bool reverse_sorted() 
 
282
  { 
 
283
    return true; 
 
284
  }
 
285
 
 
286
  int get_type() 
 
287
  { 
 
288
    return QS_TYPE_RANGE_DESC;
 
289
  }
 
290
 
 
291
private:
 
292
 
 
293
  bool range_reads_after_key(QuickRange *range);
 
294
 
 
295
  int reset(void) 
 
296
  { 
 
297
    rev_it.rewind(); 
 
298
    return QuickRangeSelect::reset();
 
299
  }
 
300
 
 
301
  List<QuickRange> rev_ranges;
 
302
 
 
303
  List_iterator<QuickRange> rev_it;
 
304
 
 
305
};
 
306
 
 
307
} /* namespace optimizer */
 
308
 
 
309
} /* namespace drizzled */
 
310
 
 
311
#endif /* DRIZZLED_OPTIMIZER_QUICK_RANGE_SELECT_H */