opt_range.h 23.6 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000-2006 MySQL AB
unknown's avatar
unknown committed
2

unknown's avatar
unknown committed
3 4
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
6

unknown's avatar
unknown committed
7 8 9 10
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
unknown's avatar
unknown committed
11

unknown's avatar
unknown committed
12 13 14 15 16 17 18 19 20 21
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


/* classes to use when handling where clause */

#ifndef _opt_range_h
#define _opt_range_h

22
#ifdef USE_PRAGMA_INTERFACE
unknown's avatar
unknown committed
23 24 25 26
#pragma interface			/* gcc class implementation */
#endif

typedef struct st_key_part {
unknown's avatar
unknown committed
27 28 29
  uint16           key,part;
  /* See KEY_PART_INFO for meaning of the next two: */
  uint16           store_length, length;
30
  uint8            null_bit;
unknown's avatar
unknown committed
31 32 33 34
  /*
    Keypart flags (0 when this structure is used by partition pruning code
    for fake partitioning index description)
  */
35
  uint8 flag;
unknown's avatar
unknown committed
36 37
  Field            *field;
  Field::imagetype image_type;
unknown's avatar
unknown committed
38 39
} KEY_PART;

40

unknown's avatar
unknown committed
41 42
class QUICK_RANGE :public Sql_alloc {
 public:
43
  uchar *min_key,*max_key;
unknown's avatar
unknown committed
44
  uint16 min_length,max_length,flag;
unknown's avatar
unknown committed
45 46
  key_part_map min_keypart_map, // bitmap of used keyparts in min_key
               max_keypart_map; // bitmap of used keyparts in max_key
47 48 49
#ifdef HAVE_purify
  uint16 dummy;					/* Avoid warnings on 'flag' */
#endif
unknown's avatar
unknown committed
50
  QUICK_RANGE();				/* Full range */
51
  QUICK_RANGE(const uchar *min_key_arg, uint min_length_arg,
unknown's avatar
unknown committed
52
              key_part_map min_keypart_map_arg,
53
	      const uchar *max_key_arg, uint max_length_arg,
unknown's avatar
unknown committed
54
              key_part_map max_keypart_map_arg,
unknown's avatar
unknown committed
55
	      uint flag_arg)
56 57
    : min_key((uchar*) sql_memdup(min_key_arg,min_length_arg+1)),
      max_key((uchar*) sql_memdup(max_key_arg,max_length_arg+1)),
unknown's avatar
unknown committed
58 59
      min_length((uint16) min_length_arg),
      max_length((uint16) max_length_arg),
unknown's avatar
unknown committed
60
      flag((uint16) flag_arg),
61
      min_keypart_map(min_keypart_map_arg),
unknown's avatar
unknown committed
62
      max_keypart_map(max_keypart_map_arg)
63 64 65 66 67
    {
#ifdef HAVE_purify
      dummy=0;
#endif
    }
unknown's avatar
unknown committed
68 69
};

unknown's avatar
unknown committed
70

unknown's avatar
unknown committed
71
/*
unknown's avatar
unknown committed
72
  Quick select interface.
73
  This class is a parent for all QUICK_*_SELECT and FT_SELECT classes.
unknown's avatar
unknown committed
74

unknown's avatar
unknown committed
75 76 77
  The usage scenario is as follows:
  1. Create quick select
    quick= new QUICK_XXX_SELECT(...);
unknown's avatar
unknown committed
78

unknown's avatar
unknown committed
79 80 81 82 83 84 85 86 87 88
  2. Perform lightweight initialization. This can be done in 2 ways:
  2.a: Regular initialization
    if (quick->init())
    {
      //the only valid action after failed init() call is delete
      delete quick;
    }
  2.b: Special initialization for quick selects merged by QUICK_ROR_*_SELECT
    if (quick->init_ror_merged_scan())
      delete quick;
unknown's avatar
unknown committed
89

unknown's avatar
unknown committed
90 91 92 93
  3. Perform zero, one, or more scans.
    while (...)
    {
      // initialize quick select for scan. This may allocate
unknown's avatar
unknown committed
94
      // buffers and/or prefetch rows.
unknown's avatar
unknown committed
95 96 97 98 99 100
      if (quick->reset())
      {
        //the only valid action after failed reset() call is delete
        delete quick;
        //abort query
      }
unknown's avatar
unknown committed
101

unknown's avatar
unknown committed
102 103 104 105 106 107
      // perform the scan
      do
      {
        res= quick->get_next();
      } while (res && ...)
    }
unknown's avatar
unknown committed
108

unknown's avatar
unknown committed
109 110
  4. Delete the select:
    delete quick;
unknown's avatar
unknown committed
111

unknown's avatar
unknown committed
112 113 114 115
*/

class QUICK_SELECT_I
{
unknown's avatar
unknown committed
116
public:
unknown's avatar
unknown committed
117
  bool sorted;
unknown's avatar
unknown committed
118 119 120 121
  ha_rows records;  /* estimate of # of records to be retrieved */
  double  read_time; /* time to perform this retrieval          */
  TABLE   *head;
  /*
unknown's avatar
unknown committed
122
    Index this quick select uses, or MAX_KEY for quick selects
123
    that use several indexes
unknown's avatar
unknown committed
124
  */
125
  uint index;
unknown's avatar
unknown committed
126 127

  /*
128 129
    Total length of first used_key_parts parts of the key.
    Applicable if index!= MAX_KEY.
unknown's avatar
unknown committed
130
  */
131 132 133 134 135 136
  uint max_used_key_length;

  /*
    Max. number of (first) key parts this quick select uses for retrieval.
    eg. for "(key1p1=c1 AND key1p2=c2) OR key1p1=c2" used_key_parts == 2.
    Applicable if index!= MAX_KEY.
unknown's avatar
unknown committed
137 138

    For QUICK_GROUP_MIN_MAX_SELECT it includes MIN/MAX argument keyparts.
139 140
  */
  uint used_key_parts;
unknown's avatar
unknown committed
141 142 143

  QUICK_SELECT_I();
  virtual ~QUICK_SELECT_I(){};
unknown's avatar
unknown committed
144

145 146 147 148
  /*
    Do post-constructor initialization.
    SYNOPSIS
      init()
unknown's avatar
unknown committed
149 150 151

    init() performs initializations that should have been in constructor if
    it was possible to return errors from constructors. The join optimizer may
152 153 154
    create and then delete quick selects without retrieving any rows so init()
    must not contain any IO or CPU intensive code.

unknown's avatar
unknown committed
155
    If init() call fails the only valid action is to delete this quick select,
156
    reset() and get_next() must not be called.
unknown's avatar
unknown committed
157

158 159 160
    RETURN
      0      OK
      other  Error code
unknown's avatar
unknown committed
161
  */
unknown's avatar
unknown committed
162
  virtual int  init() = 0;
unknown's avatar
unknown committed
163 164

  /*
165 166 167
    Initialize quick select for row retrieval.
    SYNOPSIS
      reset()
unknown's avatar
unknown committed
168 169

    reset() should be called when it is certain that row retrieval will be
170 171
    necessary. This call may do heavyweight initialization like buffering first
    N records etc. If reset() call fails get_next() must not be called.
unknown's avatar
unknown committed
172 173 174 175
    Note that reset() may be called several times if 
     * the quick select is executed in a subselect
     * a JOIN buffer is used
    
176 177 178
    RETURN
      0      OK
      other  Error code
unknown's avatar
unknown committed
179
  */
180
  virtual int  reset(void) = 0;
unknown's avatar
unknown committed
181

unknown's avatar
unknown committed
182 183
  virtual int  get_next() = 0;   /* get next record to retrieve */

unknown's avatar
unknown committed
184 185
  /* Range end should be called when we have looped over the whole index */
  virtual void range_end() {}
unknown's avatar
unknown committed
186

unknown's avatar
unknown committed
187 188 189
  virtual bool reverse_sorted() = 0;
  virtual bool unique_key_range() { return false; }

unknown's avatar
unknown committed
190
  enum {
unknown's avatar
unknown committed
191 192 193
    QS_TYPE_RANGE = 0,
    QS_TYPE_INDEX_MERGE = 1,
    QS_TYPE_RANGE_DESC = 2,
194 195
    QS_TYPE_FULLTEXT   = 3,
    QS_TYPE_ROR_INTERSECT = 4,
196 197
    QS_TYPE_ROR_UNION = 5,
    QS_TYPE_GROUP_MIN_MAX = 6
unknown's avatar
unknown committed
198 199
  };

200 201 202 203
  /* Get type of this quick select - one of the QS_TYPE_* values */
  virtual int get_type() = 0;

  /*
204
    Initialize this quick select as a merged scan inside a ROR-union or a ROR-
unknown's avatar
unknown committed
205
    intersection scan. The caller must not additionally call init() if this
206 207 208
    function is called.
    SYNOPSIS
      init_ror_merged_scan()
209 210 211
        reuse_handler  If true, the quick select may use table->handler,
                       otherwise it must create and use a separate handler
                       object.
212 213
    RETURN
      0     Ok
unknown's avatar
unknown committed
214
      other Error
215
  */
216
  virtual int init_ror_merged_scan(bool reuse_handler)
217
  { DBUG_ASSERT(0); return 1; }
unknown's avatar
unknown committed
218

219 220 221
  /*
    Save ROWID of last retrieved row in file->ref. This used in ROR-merging.
  */
222 223
  virtual void save_last_pos(){};

unknown's avatar
unknown committed
224
  /*
225 226
    Append comma-separated list of keys this quick select uses to key_names;
    append comma-separated list of corresponding used lengths to used_lengths.
227 228
    This is used by select_describe.
  */
unknown's avatar
unknown committed
229
  virtual void add_keys_and_lengths(String *key_names,
230
                                    String *used_lengths)=0;
unknown's avatar
unknown committed
231 232 233

  /*
    Append text representation of quick select structure (what and how is
234 235 236 237 238 239
    merged) to str. The result is added to "Extra" field in EXPLAIN output.
    This function is implemented only by quick selects that merge other quick
    selects output and/or can produce output suitable for merging.
  */
  virtual void add_info_string(String *str) {};
  /*
unknown's avatar
unknown committed
240
    Return 1 if any index used by this quick select
241
    uses field which is marked in passed bitmap.
242
  */
243
  virtual bool is_keys_used(const MY_BITMAP *fields);
244 245

  /*
unknown's avatar
unknown committed
246 247
    rowid of last row retrieved by this quick select. This is used only when
    doing ROR-index_merge selects
248
  */
249
  uchar    *last_rowid;
250 251

  /*
unknown's avatar
unknown committed
252
    Table record buffer used by this quick select.
253
  */
254
  uchar    *record;
255 256
#ifndef DBUG_OFF
  /*
unknown's avatar
unknown committed
257
    Print quick select information to DBUG_FILE. Caller is responsible
258 259 260
    for locking DBUG_FILE before this call and unlocking it afterwards.
  */
  virtual void dbug_dump(int indent, bool verbose)= 0;
unknown's avatar
unknown committed
261
#endif
unknown's avatar
unknown committed
262 263
};

264

unknown's avatar
unknown committed
265
struct st_qsel_param;
unknown's avatar
unknown committed
266
class PARAM;
unknown's avatar
unknown committed
267 268
class SEL_ARG;

269
/*
unknown's avatar
unknown committed
270
  Quick select that does a range scan on a single key. The records are
271 272
  returned in key order.
*/
273
class QUICK_RANGE_SELECT : public QUICK_SELECT_I
unknown's avatar
unknown committed
274 275
{
protected:
276
  bool next,dont_free,in_ror_merged_scan;
unknown's avatar
unknown committed
277
public:
unknown's avatar
unknown committed
278
  int error;
279
protected:
unknown's avatar
unknown committed
280
  handler *file;
281 282 283 284 285
  /*
    If true, this quick select has its "own" handler object which should be
    closed no later then this quick select is deleted.
  */
  bool free_file;
unknown's avatar
unknown committed
286 287 288 289 290 291 292 293
  bool in_range;
  uint multi_range_count; /* copy from thd->variables.multi_range_count */
  uint multi_range_length; /* the allocated length for the array */
  uint multi_range_bufsiz; /* copy from thd->variables.read_rnd_buff_size */
  KEY_MULTI_RANGE *multi_range; /* the multi-range array (allocated and
                                       freed by QUICK_RANGE_SELECT) */
  HANDLER_BUFFER *multi_range_buff; /* the handler buffer (allocated and
                                       freed by QUICK_RANGE_SELECT) */
294
  MY_BITMAP column_bitmap, *save_read_set, *save_write_set;
295

unknown's avatar
unknown committed
296
  friend class TRP_ROR_INTERSECT;
297
  friend
unknown's avatar
unknown committed
298
  QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
unknown's avatar
unknown committed
299 300
                                               struct st_table_ref *ref,
                                               ha_rows records);
unknown's avatar
unknown committed
301
  friend bool get_quick_keys(PARAM *param,
unknown's avatar
unknown committed
302
                             QUICK_RANGE_SELECT *quick,KEY_PART *key,
303
                             SEL_ARG *key_tree,
304 305
                             uchar *min_key, uint min_key_flag,
                             uchar *max_key, uint max_key_flag);
unknown's avatar
unknown committed
306
  friend QUICK_RANGE_SELECT *get_quick_select(PARAM*,uint idx,
unknown's avatar
unknown committed
307 308 309
                                              SEL_ARG *key_tree,
                                              MEM_ROOT *alloc);
  friend class QUICK_SELECT_DESC;
310
  friend class QUICK_INDEX_MERGE_SELECT;
311
  friend class QUICK_ROR_INTERSECT_SELECT;
312
  friend class QUICK_GROUP_MIN_MAX_SELECT;
313 314 315

  DYNAMIC_ARRAY ranges;     /* ordered array of range ptrs */
  QUICK_RANGE **cur_range;  /* current element in ranges  */
unknown's avatar
unknown committed
316

317
  QUICK_RANGE *last_range;
unknown's avatar
unknown committed
318
  KEY_PART *key_parts;
unknown's avatar
unknown committed
319
  KEY_PART_INFO *key_part_info;
unknown's avatar
unknown committed
320
  int cmp_next(QUICK_RANGE *range);
321 322
  int cmp_prev(QUICK_RANGE *range);
  bool row_in_ranges();
unknown's avatar
unknown committed
323
public:
324 325
  MEM_ROOT alloc;

unknown's avatar
unknown committed
326
  QUICK_RANGE_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0,
unknown's avatar
unknown committed
327 328
                     MEM_ROOT *parent_alloc=NULL);
  ~QUICK_RANGE_SELECT();
unknown's avatar
unknown committed
329

unknown's avatar
unknown committed
330
  int init();
unknown's avatar
unknown committed
331
  int reset(void);
unknown's avatar
unknown committed
332
  int get_next();
unknown's avatar
unknown committed
333
  void range_end();
unknown's avatar
unknown committed
334
  int get_next_prefix(uint prefix_length, key_part_map keypart_map,
335
                      uchar *cur_prefix);
unknown's avatar
unknown committed
336
  bool reverse_sorted() { return 0; }
unknown's avatar
unknown committed
337
  bool unique_key_range();
338
  int init_ror_merged_scan(bool reuse_handler);
339
  void save_last_pos()
340
  { file->position(record); }
unknown's avatar
unknown committed
341
  int get_type() { return QS_TYPE_RANGE; }
342 343
  void add_keys_and_lengths(String *key_names, String *used_lengths);
  void add_info_string(String *str);
344
#ifndef DBUG_OFF
345
  void dbug_dump(int indent, bool verbose);
346
#endif
unknown's avatar
unknown committed
347
private:
348
  /* Default copy ctor used by QUICK_SELECT_DESC */
unknown's avatar
unknown committed
349 350
};

351

unknown's avatar
unknown committed
352 353 354 355 356 357 358 359 360 361 362
class QUICK_RANGE_SELECT_GEOM: public QUICK_RANGE_SELECT
{
public:
  QUICK_RANGE_SELECT_GEOM(THD *thd, TABLE *table, uint index_arg,
                          bool no_alloc, MEM_ROOT *parent_alloc)
    :QUICK_RANGE_SELECT(thd, table, index_arg, no_alloc, parent_alloc)
    {};
  virtual int get_next();
};


unknown's avatar
unknown committed
363
/*
364
  QUICK_INDEX_MERGE_SELECT - index_merge access method quick select.
365

unknown's avatar
unknown committed
366
    QUICK_INDEX_MERGE_SELECT uses
367 368
     * QUICK_RANGE_SELECTs to get rows
     * Unique class to remove duplicate rows
369

370
  INDEX MERGE OPTIMIZER
unknown's avatar
unknown committed
371
    Current implementation doesn't detect all cases where index_merge could
372
    be used, in particular:
unknown's avatar
unknown committed
373
     * index_merge will never be used if range scan is possible (even if
374
       range scan is more expensive)
375

unknown's avatar
unknown committed
376
     * index_merge+'using index' is not supported (this the consequence of
377
       the above restriction)
unknown's avatar
unknown committed
378

379
     * If WHERE part contains complex nested AND and OR conditions, some ways
unknown's avatar
unknown committed
380 381
       to retrieve rows using index_merge will not be considered. The choice
       of read plan may depend on the order of conjuncts/disjuncts in WHERE
382 383
       part of the query, see comments near imerge_list_or_list and
       SEL_IMERGE::or_sel_tree_with_checks functions for details.
384

385 386
     * There is no "index_merge_ref" method (but index_merge on non-first
       table in join is possible with 'range checked for each record').
387

unknown's avatar
unknown committed
388
    See comments around SEL_IMERGE class and test_quick_select for more
389
    details.
390

391
  ROW RETRIEVAL ALGORITHM
392

393 394 395
    index_merge uses Unique class for duplicates removal.  index_merge takes
    advantage of Clustered Primary Key (CPK) if the table has one.
    The index_merge algorithm consists of two phases:
396

397 398
    Phase 1 (implemented in QUICK_INDEX_MERGE_SELECT::prepare_unique):
    prepare()
399
    {
400 401 402 403 404 405 406 407 408
      activate 'index only';
      while(retrieve next row for non-CPK scan)
      {
        if (there is a CPK scan and row will be retrieved by it)
          skip this row;
        else
          put its rowid into Unique;
      }
      deactivate 'index only';
409
    }
unknown's avatar
unknown committed
410

411 412
    Phase 2 (implemented as sequence of QUICK_INDEX_MERGE_SELECT::get_next
    calls):
413

414 415 416 417 418 419
    fetch()
    {
      retrieve all rows from row pointers stored in Unique;
      free Unique;
      retrieve all rows for CPK scan;
    }
unknown's avatar
unknown committed
420 421
*/

unknown's avatar
unknown committed
422
class QUICK_INDEX_MERGE_SELECT : public QUICK_SELECT_I
unknown's avatar
unknown committed
423 424 425 426 427 428
{
public:
  QUICK_INDEX_MERGE_SELECT(THD *thd, TABLE *table);
  ~QUICK_INDEX_MERGE_SELECT();

  int  init();
429
  int  reset(void);
unknown's avatar
unknown committed
430 431 432 433
  int  get_next();
  bool reverse_sorted() { return false; }
  bool unique_key_range() { return false; }
  int get_type() { return QS_TYPE_INDEX_MERGE; }
434 435
  void add_keys_and_lengths(String *key_names, String *used_lengths);
  void add_info_string(String *str);
436
  bool is_keys_used(const MY_BITMAP *fields);
437
#ifndef DBUG_OFF
438
  void dbug_dump(int indent, bool verbose);
439
#endif
unknown's avatar
unknown committed
440 441 442 443 444

  bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range);

  /* range quick selects this index_merge read consists of */
  List<QUICK_RANGE_SELECT> quick_selects;
unknown's avatar
unknown committed
445

446
  /* quick select that uses clustered primary key (NULL if none) */
447
  QUICK_RANGE_SELECT* pk_quick_select;
unknown's avatar
unknown committed
448

449
  /* true if this select is currently doing a clustered PK scan */
450
  bool  doing_pk_scan;
unknown's avatar
unknown committed
451

452 453
  MEM_ROOT alloc;
  THD *thd;
unknown's avatar
unknown committed
454
  int read_keys_and_merge();
unknown's avatar
unknown committed
455

456 457
  /* used to get rows collected in Unique */
  READ_RECORD read_record;
unknown's avatar
unknown committed
458 459
};

460 461 462

/*
  Rowid-Ordered Retrieval (ROR) index intersection quick select.
unknown's avatar
unknown committed
463
  This quick select produces intersection of row sequences returned
464
  by several QUICK_RANGE_SELECTs it "merges".
unknown's avatar
unknown committed
465 466

  All merged QUICK_RANGE_SELECTs must return rowids in rowid order.
467 468
  QUICK_ROR_INTERSECT_SELECT will return rows in rowid order, too.

unknown's avatar
unknown committed
469
  All merged quick selects retrieve {rowid, covered_fields} tuples (not full
470
  table records).
unknown's avatar
unknown committed
471 472
  QUICK_ROR_INTERSECT_SELECT retrieves full records if it is not being used
  by QUICK_ROR_INTERSECT_SELECT and all merged quick selects together don't
473
  cover needed all fields.
unknown's avatar
unknown committed
474

475 476
  If one of the merged quick selects is a Clustered PK range scan, it is
  used only to filter rowid sequence produced by other merged quick selects.
477
*/
478

unknown's avatar
unknown committed
479
class QUICK_ROR_INTERSECT_SELECT : public QUICK_SELECT_I
480 481
{
public:
unknown's avatar
unknown committed
482
  QUICK_ROR_INTERSECT_SELECT(THD *thd, TABLE *table,
483 484 485 486 487 488 489 490 491 492
                             bool retrieve_full_rows,
                             MEM_ROOT *parent_alloc);
  ~QUICK_ROR_INTERSECT_SELECT();

  int  init();
  int  reset(void);
  int  get_next();
  bool reverse_sorted() { return false; }
  bool unique_key_range() { return false; }
  int get_type() { return QS_TYPE_ROR_INTERSECT; }
493 494
  void add_keys_and_lengths(String *key_names, String *used_lengths);
  void add_info_string(String *str);
495
  bool is_keys_used(const MY_BITMAP *fields);
496
#ifndef DBUG_OFF
497
  void dbug_dump(int indent, bool verbose);
498
#endif
499
  int init_ror_merged_scan(bool reuse_handler);
500 501
  bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range);

unknown's avatar
unknown committed
502
  /*
503 504 505
    Range quick selects this intersection consists of, not including
    cpk_quick.
  */
506
  List<QUICK_RANGE_SELECT> quick_selects;
unknown's avatar
unknown committed
507 508 509

  /*
    Merged quick select that uses Clustered PK, if there is one. This quick
510 511
    select is not used for row retrieval, it is used for row retrieval.
  */
512
  QUICK_RANGE_SELECT *cpk_quick;
513 514 515 516

  MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */
  THD *thd;       /* current thread */
  bool need_to_fetch_row; /* if true, do retrieve full table records. */
unknown's avatar
unknown committed
517 518
  /* in top-level quick select, true if merged scans where initialized */
  bool scans_inited; 
519 520
};

521

522 523
/*
  Rowid-Ordered Retrieval index union select.
524 525
  This quick select produces union of row sequences returned by several
  quick select it "merges".
526

unknown's avatar
unknown committed
527
  All merged quick selects must return rowids in rowid order.
528 529 530 531
  QUICK_ROR_UNION_SELECT will return rows in rowid order, too.

  All merged quick selects are set not to retrieve full table records.
  ROR-union quick select always retrieves full records.
unknown's avatar
unknown committed
532

533
*/
534

unknown's avatar
unknown committed
535
class QUICK_ROR_UNION_SELECT : public QUICK_SELECT_I
536 537 538 539 540 541 542 543 544 545 546
{
public:
  QUICK_ROR_UNION_SELECT(THD *thd, TABLE *table);
  ~QUICK_ROR_UNION_SELECT();

  int  init();
  int  reset(void);
  int  get_next();
  bool reverse_sorted() { return false; }
  bool unique_key_range() { return false; }
  int get_type() { return QS_TYPE_ROR_UNION; }
547 548
  void add_keys_and_lengths(String *key_names, String *used_lengths);
  void add_info_string(String *str);
549
  bool is_keys_used(const MY_BITMAP *fields);
550
#ifndef DBUG_OFF
551
  void dbug_dump(int indent, bool verbose);
552 553 554 555
#endif

  bool push_quick_back(QUICK_SELECT_I *quick_sel_range);

556
  List<QUICK_SELECT_I> quick_selects; /* Merged quick selects */
unknown's avatar
unknown committed
557

558 559 560 561
  QUEUE queue;    /* Priority queue for merge operation */
  MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */

  THD *thd;             /* current thread */
562 563
  uchar *cur_rowid;      /* buffer used in get_next() */
  uchar *prev_rowid;     /* rowid of last row returned by get_next() */
564
  bool have_prev_rowid; /* true if prev_rowid has valid data */
unknown's avatar
unknown committed
565
  uint rowid_length;    /* table rowid length */
566
private:
567
  static int queue_cmp(void *arg, uchar *val1, uchar *val2);
unknown's avatar
unknown committed
568
  bool scans_inited; 
569 570 571
};


572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
/*
  Index scan for GROUP-BY queries with MIN/MAX aggregate functions.

  This class provides a specialized index access method for GROUP-BY queries
  of the forms:

       SELECT A_1,...,A_k, [B_1,...,B_m], [MIN(C)], [MAX(C)]
         FROM T
        WHERE [RNG(A_1,...,A_p ; where p <= k)]
         [AND EQ(B_1,...,B_m)]
         [AND PC(C)]
         [AND PA(A_i1,...,A_iq)]
       GROUP BY A_1,...,A_k;

    or

       SELECT DISTINCT A_i1,...,A_ik
         FROM T
        WHERE [RNG(A_1,...,A_p ; where p <= k)]
         [AND PA(A_i1,...,A_iq)];

  where all selected fields are parts of the same index.
  The class of queries that can be processed by this quick select is fully
  specified in the description of get_best_trp_group_min_max() in opt_range.cc.

  The get_next() method directly produces result tuples, thus obviating the
  need to call end_send_group() because all grouping is already done inside
  get_next().

  Since one of the requirements is that all select fields are part of the same
  index, this class produces only index keys, and not complete records.
*/

class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I
{
private:
  handler *file;         /* The handler used to get data. */
  JOIN *join;            /* Descriptor of the current query */
  KEY  *index_info;      /* The index chosen for data access */
611 612 613
  uchar *record;          /* Buffer where the next record is returned. */
  uchar *tmp_record;      /* Temporary storage for next_min(), next_max(). */
  uchar *group_prefix;    /* Key prefix consisting of the GROUP fields. */
614
  uint group_prefix_len; /* Length of the group prefix. */
unknown's avatar
unknown committed
615
  uint group_key_parts;  /* A number of keyparts in the group prefix */
616
  uchar *last_prefix;     /* Prefix of the last group for detecting EOF. */
617 618 619 620 621 622
  bool have_min;         /* Specify whether we are computing */
  bool have_max;         /*   a MIN, a MAX, or both.         */
  bool seen_first_key;   /* Denotes whether the first key was retrieved.*/
  KEY_PART_INFO *min_max_arg_part; /* The keypart of the only argument field */
                                   /* of all MIN/MAX functions.              */
  uint min_max_arg_len;  /* The length of the MIN/MAX argument field */
623
  uchar *key_infix;       /* Infix of constants from equality predicates. */
624 625 626
  uint key_infix_len;
  DYNAMIC_ARRAY min_max_ranges; /* Array of range ptrs for the MIN/MAX field. */
  uint real_prefix_len; /* Length of key prefix extended with key_infix. */
unknown's avatar
unknown committed
627
  uint real_key_parts;  /* A number of keyparts in the above value.      */
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
  List<Item_sum> *min_functions;
  List<Item_sum> *max_functions;
  List_iterator<Item_sum> *min_functions_it;
  List_iterator<Item_sum> *max_functions_it;
public:
  /*
    The following two members are public to allow easy access from
    TRP_GROUP_MIN_MAX::make_quick()
  */
  MEM_ROOT alloc; /* Memory pool for this and quick_prefix_select data. */
  QUICK_RANGE_SELECT *quick_prefix_select;/* For retrieval of group prefixes. */
private:
  int  next_prefix();
  int  next_min_in_range();
  int  next_max_in_range();
  int  next_min();
  int  next_max();
  void update_min_result();
  void update_max_result();
public:
  QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join, bool have_min,
                             bool have_max, KEY_PART_INFO *min_max_arg_part,
650 651 652
                             uint group_prefix_len, uint group_key_parts,
                             uint used_key_parts, KEY *index_info, uint
                             use_index, double read_cost, ha_rows records, uint
653
                             key_infix_len, uchar *key_infix, MEM_ROOT
654
                             *parent_alloc);
655 656 657
  ~QUICK_GROUP_MIN_MAX_SELECT();
  bool add_range(SEL_ARG *sel_range);
  void update_key_stat();
658
  void adjust_prefix_ranges();
659 660 661 662 663 664 665 666 667 668 669 670 671 672
  bool alloc_buffers();
  int init();
  int reset();
  int get_next();
  bool reverse_sorted() { return false; }
  bool unique_key_range() { return false; }
  int get_type() { return QS_TYPE_GROUP_MIN_MAX; }
  void add_keys_and_lengths(String *key_names, String *used_lengths);
#ifndef DBUG_OFF
  void dbug_dump(int indent, bool verbose);
#endif
};


unknown's avatar
unknown committed
673
class QUICK_SELECT_DESC: public QUICK_RANGE_SELECT
674 675
{
public:
unknown's avatar
unknown committed
676
  QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, uint used_key_parts);
677
  int get_next();
678
  bool reverse_sorted() { return 1; }
unknown's avatar
unknown committed
679
  int get_type() { return QS_TYPE_RANGE_DESC; }
680 681
private:
  bool range_reads_after_key(QUICK_RANGE *range);
unknown's avatar
unknown committed
682
  int reset(void) { rev_it.rewind(); return QUICK_RANGE_SELECT::reset(); }
683 684
  List<QUICK_RANGE> rev_ranges;
  List_iterator<QUICK_RANGE> rev_it;
685
  uint used_key_parts;
686 687
};

688

unknown's avatar
unknown committed
689 690
class SQL_SELECT :public Sql_alloc {
 public:
unknown's avatar
unknown committed
691
  QUICK_SELECT_I *quick;	// If quick-select used
unknown's avatar
unknown committed
692 693 694 695 696 697 698 699 700 701 702 703
  COND		*cond;		// where condition
  TABLE	*head;
  IO_CACHE file;		// Positions to used records
  ha_rows records;		// Records in use if read from file
  double read_time;		// Time to read rows
  key_map quick_keys;		// Possible quick keys
  key_map needed_reg;		// Possible quick keys after prev tables.
  table_map const_tables,read_tables;
  bool	free_cond;

  SQL_SELECT();
  ~SQL_SELECT();
704
  void cleanup();
unknown's avatar
unknown committed
705
  bool check_quick(THD *thd, bool force_quick_range, ha_rows limit)
706 707 708 709 710
  {
    key_map tmp;
    tmp.set_all();
    return test_quick_select(thd, tmp, 0, limit, force_quick_range) < 0;
  }
711
  inline bool skip_record() { return cond ? cond->val_int() == 0 : 0; }
712
  int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
713
			ha_rows limit, bool force_quick_range);
unknown's avatar
unknown committed
714 715
};

unknown's avatar
unknown committed
716

unknown's avatar
unknown committed
717
class FT_SELECT: public QUICK_RANGE_SELECT {
unknown's avatar
unknown committed
718
public:
unknown's avatar
unknown committed
719
  FT_SELECT(THD *thd, TABLE *table, uint key) :
720
      QUICK_RANGE_SELECT (thd, table, key, 1) { VOID(init()); }
721
  ~FT_SELECT() { file->ft_end(); }
unknown's avatar
unknown committed
722
  int init() { return error=file->ft_init(); }
unknown's avatar
unknown committed
723
  int reset() { return 0; }
unknown's avatar
unknown committed
724 725
  int get_next() { return error=file->ft_read(record); }
  int get_type() { return QS_TYPE_FULLTEXT; }
unknown's avatar
unknown committed
726 727
};

unknown's avatar
unknown committed
728
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
unknown's avatar
unknown committed
729 730
                                             struct st_table_ref *ref,
                                             ha_rows records);
731 732
uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit);

unknown's avatar
unknown committed
733 734
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond);
735
void store_key_image_to_rec(Field *field, uchar *ptr, uint len);
unknown's avatar
unknown committed
736 737
#endif

unknown's avatar
unknown committed
738
#endif