opt_range.h 24.1 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

Sergey Petrunya's avatar
Sergey Petrunya committed
41 42 43 44 45 46
/*
  A "MIN_TUPLE < tbl.key_tuple < MAX_TUPLE" interval. 
  
  One of endpoints may be absent. 'flags' member has flags which tell whether
  the endpoints are '<' or '<='.
*/
unknown's avatar
unknown committed
47 48
class QUICK_RANGE :public Sql_alloc {
 public:
49
  uchar *min_key,*max_key;
unknown's avatar
unknown committed
50
  uint16 min_length,max_length,flag;
unknown's avatar
unknown committed
51 52
  key_part_map min_keypart_map, // bitmap of used keyparts in min_key
               max_keypart_map; // bitmap of used keyparts in max_key
53
#ifdef HAVE_valgrind
54 55
  uint16 dummy;					/* Avoid warnings on 'flag' */
#endif
unknown's avatar
unknown committed
56
  QUICK_RANGE();				/* Full range */
57
  QUICK_RANGE(const uchar *min_key_arg, uint min_length_arg,
unknown's avatar
unknown committed
58
              key_part_map min_keypart_map_arg,
59
	      const uchar *max_key_arg, uint max_length_arg,
unknown's avatar
unknown committed
60
              key_part_map max_keypart_map_arg,
unknown's avatar
unknown committed
61
	      uint flag_arg)
62 63
    : 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
64 65
      min_length((uint16) min_length_arg),
      max_length((uint16) max_length_arg),
unknown's avatar
unknown committed
66
      flag((uint16) flag_arg),
67
      min_keypart_map(min_keypart_map_arg),
unknown's avatar
unknown committed
68
      max_keypart_map(max_keypart_map_arg)
69
    {
70
#ifdef HAVE_valgrind
71 72 73
      dummy=0;
#endif
    }
unknown's avatar
unknown committed
74 75
};

unknown's avatar
unknown committed
76

unknown's avatar
unknown committed
77
/*
unknown's avatar
unknown committed
78
  Quick select interface.
79
  This class is a parent for all QUICK_*_SELECT and FT_SELECT classes.
unknown's avatar
unknown committed
80

unknown's avatar
unknown committed
81 82 83
  The usage scenario is as follows:
  1. Create quick select
    quick= new QUICK_XXX_SELECT(...);
unknown's avatar
unknown committed
84

unknown's avatar
unknown committed
85 86 87 88 89 90 91 92 93 94
  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
95

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

unknown's avatar
unknown committed
108 109 110 111 112 113
      // perform the scan
      do
      {
        res= quick->get_next();
      } while (res && ...)
    }
unknown's avatar
unknown committed
114

unknown's avatar
unknown committed
115 116
  4. Delete the select:
    delete quick;
unknown's avatar
unknown committed
117

unknown's avatar
unknown committed
118 119 120 121
*/

class QUICK_SELECT_I
{
unknown's avatar
unknown committed
122
public:
unknown's avatar
unknown committed
123
  bool sorted;
unknown's avatar
unknown committed
124 125 126 127
  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
128
    Index this quick select uses, or MAX_KEY for quick selects
129
    that use several indexes
unknown's avatar
unknown committed
130
  */
131
  uint index;
unknown's avatar
unknown committed
132 133

  /*
134 135
    Total length of first used_key_parts parts of the key.
    Applicable if index!= MAX_KEY.
unknown's avatar
unknown committed
136
  */
137 138 139 140 141 142
  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
143 144

    For QUICK_GROUP_MIN_MAX_SELECT it includes MIN/MAX argument keyparts.
145 146
  */
  uint used_key_parts;
unknown's avatar
unknown committed
147 148 149

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

151 152 153 154
  /*
    Do post-constructor initialization.
    SYNOPSIS
      init()
unknown's avatar
unknown committed
155 156 157

    init() performs initializations that should have been in constructor if
    it was possible to return errors from constructors. The join optimizer may
158 159 160
    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
161
    If init() call fails the only valid action is to delete this quick select,
162
    reset() and get_next() must not be called.
unknown's avatar
unknown committed
163

164 165 166
    RETURN
      0      OK
      other  Error code
unknown's avatar
unknown committed
167
  */
unknown's avatar
unknown committed
168
  virtual int  init() = 0;
unknown's avatar
unknown committed
169 170

  /*
171 172 173
    Initialize quick select for row retrieval.
    SYNOPSIS
      reset()
unknown's avatar
unknown committed
174 175

    reset() should be called when it is certain that row retrieval will be
176 177
    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
178 179 180 181
    Note that reset() may be called several times if 
     * the quick select is executed in a subselect
     * a JOIN buffer is used
    
182 183 184
    RETURN
      0      OK
      other  Error code
unknown's avatar
unknown committed
185
  */
186
  virtual int  reset(void) = 0;
unknown's avatar
unknown committed
187

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

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

unknown's avatar
unknown committed
193 194 195
  virtual bool reverse_sorted() = 0;
  virtual bool unique_key_range() { return false; }

unknown's avatar
unknown committed
196
  enum {
unknown's avatar
unknown committed
197 198 199
    QS_TYPE_RANGE = 0,
    QS_TYPE_INDEX_MERGE = 1,
    QS_TYPE_RANGE_DESC = 2,
200 201
    QS_TYPE_FULLTEXT   = 3,
    QS_TYPE_ROR_INTERSECT = 4,
202 203
    QS_TYPE_ROR_UNION = 5,
    QS_TYPE_GROUP_MIN_MAX = 6
unknown's avatar
unknown committed
204 205
  };

206 207 208 209
  /* Get type of this quick select - one of the QS_TYPE_* values */
  virtual int get_type() = 0;

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

225 226 227
  /*
    Save ROWID of last retrieved row in file->ref. This used in ROR-merging.
  */
228 229
  virtual void save_last_pos(){};

unknown's avatar
unknown committed
230
  /*
231 232
    Append comma-separated list of keys this quick select uses to key_names;
    append comma-separated list of corresponding used lengths to used_lengths.
233 234
    This is used by select_describe.
  */
unknown's avatar
unknown committed
235
  virtual void add_keys_and_lengths(String *key_names,
236
                                    String *used_lengths)=0;
unknown's avatar
unknown committed
237 238 239

  /*
    Append text representation of quick select structure (what and how is
240 241 242 243 244 245
    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
246
    Return 1 if any index used by this quick select
247
    uses field which is marked in passed bitmap.
248
  */
249
  virtual bool is_keys_used(const MY_BITMAP *fields);
250 251

  /*
unknown's avatar
unknown committed
252 253
    rowid of last row retrieved by this quick select. This is used only when
    doing ROR-index_merge selects
254
  */
255
  uchar    *last_rowid;
256 257

  /*
unknown's avatar
unknown committed
258
    Table record buffer used by this quick select.
259
  */
260
  uchar    *record;
261 262
#ifndef DBUG_OFF
  /*
unknown's avatar
unknown committed
263
    Print quick select information to DBUG_FILE. Caller is responsible
264 265 266
    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
267
#endif
unknown's avatar
unknown committed
268 269
};

270

unknown's avatar
unknown committed
271
struct st_qsel_param;
unknown's avatar
unknown committed
272
class PARAM;
unknown's avatar
unknown committed
273 274
class SEL_ARG;

275
/*
unknown's avatar
unknown committed
276
  Quick select that does a range scan on a single key. The records are
277 278
  returned in key order.
*/
279
class QUICK_RANGE_SELECT : public QUICK_SELECT_I
unknown's avatar
unknown committed
280 281
{
protected:
282
  bool next,dont_free,in_ror_merged_scan;
283 284
  /* true if we enabled key only reads */
  bool doing_key_read;
unknown's avatar
unknown committed
285
public:
unknown's avatar
unknown committed
286
  int error;
287
protected:
unknown's avatar
unknown committed
288
  handler *file;
289 290 291 292 293
  /*
    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
294 295 296 297 298 299 300 301
  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) */
302
  MY_BITMAP column_bitmap, *save_read_set, *save_write_set;
303

unknown's avatar
unknown committed
304
  friend class TRP_ROR_INTERSECT;
305
  friend
unknown's avatar
unknown committed
306
  QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
unknown's avatar
unknown committed
307 308
                                               struct st_table_ref *ref,
                                               ha_rows records);
unknown's avatar
unknown committed
309
  friend bool get_quick_keys(PARAM *param,
unknown's avatar
unknown committed
310
                             QUICK_RANGE_SELECT *quick,KEY_PART *key,
311
                             SEL_ARG *key_tree,
312 313
                             uchar *min_key, uint min_key_flag,
                             uchar *max_key, uint max_key_flag);
unknown's avatar
unknown committed
314
  friend QUICK_RANGE_SELECT *get_quick_select(PARAM*,uint idx,
unknown's avatar
unknown committed
315 316 317
                                              SEL_ARG *key_tree,
                                              MEM_ROOT *alloc);
  friend class QUICK_SELECT_DESC;
318
  friend class QUICK_INDEX_MERGE_SELECT;
319
  friend class QUICK_ROR_INTERSECT_SELECT;
320
  friend class QUICK_GROUP_MIN_MAX_SELECT;
321 322 323

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

325
  QUICK_RANGE *last_range;
unknown's avatar
unknown committed
326
  KEY_PART *key_parts;
unknown's avatar
unknown committed
327
  KEY_PART_INFO *key_part_info;
unknown's avatar
unknown committed
328
  int cmp_next(QUICK_RANGE *range);
329 330
  int cmp_prev(QUICK_RANGE *range);
  bool row_in_ranges();
unknown's avatar
unknown committed
331
public:
332 333
  MEM_ROOT alloc;

unknown's avatar
unknown committed
334
  QUICK_RANGE_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0,
unknown's avatar
unknown committed
335 336
                     MEM_ROOT *parent_alloc=NULL);
  ~QUICK_RANGE_SELECT();
unknown's avatar
unknown committed
337

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

359

unknown's avatar
unknown committed
360 361 362 363 364 365 366 367 368 369 370
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
371
/*
372
  QUICK_INDEX_MERGE_SELECT - index_merge access method quick select.
373

unknown's avatar
unknown committed
374
    QUICK_INDEX_MERGE_SELECT uses
375 376
     * QUICK_RANGE_SELECTs to get rows
     * Unique class to remove duplicate rows
377

378
  INDEX MERGE OPTIMIZER
unknown's avatar
unknown committed
379
    Current implementation doesn't detect all cases where index_merge could
380
    be used, in particular:
unknown's avatar
unknown committed
381
     * index_merge will never be used if range scan is possible (even if
382
       range scan is more expensive)
383

unknown's avatar
unknown committed
384
     * index_merge+'using index' is not supported (this the consequence of
385
       the above restriction)
unknown's avatar
unknown committed
386

387
     * If WHERE part contains complex nested AND and OR conditions, some ways
unknown's avatar
unknown committed
388 389
       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
390 391
       part of the query, see comments near imerge_list_or_list and
       SEL_IMERGE::or_sel_tree_with_checks functions for details.
392

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

unknown's avatar
unknown committed
396
    See comments around SEL_IMERGE class and test_quick_select for more
397
    details.
398

399
  ROW RETRIEVAL ALGORITHM
400

401 402 403
    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:
404

405 406
    Phase 1 (implemented in QUICK_INDEX_MERGE_SELECT::prepare_unique):
    prepare()
407
    {
408 409 410 411 412 413 414 415 416
      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';
417
    }
unknown's avatar
unknown committed
418

419 420
    Phase 2 (implemented as sequence of QUICK_INDEX_MERGE_SELECT::get_next
    calls):
421

422 423 424 425 426 427
    fetch()
    {
      retrieve all rows from row pointers stored in Unique;
      free Unique;
      retrieve all rows for CPK scan;
    }
unknown's avatar
unknown committed
428 429
*/

unknown's avatar
unknown committed
430
class QUICK_INDEX_MERGE_SELECT : public QUICK_SELECT_I
unknown's avatar
unknown committed
431 432 433 434 435 436
{
public:
  QUICK_INDEX_MERGE_SELECT(THD *thd, TABLE *table);
  ~QUICK_INDEX_MERGE_SELECT();

  int  init();
437
  int  reset(void);
unknown's avatar
unknown committed
438 439 440 441
  int  get_next();
  bool reverse_sorted() { return false; }
  bool unique_key_range() { return false; }
  int get_type() { return QS_TYPE_INDEX_MERGE; }
442 443
  void add_keys_and_lengths(String *key_names, String *used_lengths);
  void add_info_string(String *str);
444
  bool is_keys_used(const MY_BITMAP *fields);
445
#ifndef DBUG_OFF
446
  void dbug_dump(int indent, bool verbose);
447
#endif
unknown's avatar
unknown committed
448 449 450 451 452

  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
453

454
  /* quick select that uses clustered primary key (NULL if none) */
455
  QUICK_RANGE_SELECT* pk_quick_select;
unknown's avatar
unknown committed
456

457
  /* true if this select is currently doing a clustered PK scan */
458
  bool  doing_pk_scan;
unknown's avatar
unknown committed
459

460 461
  MEM_ROOT alloc;
  THD *thd;
unknown's avatar
unknown committed
462
  int read_keys_and_merge();
unknown's avatar
unknown committed
463

464 465
  /* used to get rows collected in Unique */
  READ_RECORD read_record;
unknown's avatar
unknown committed
466 467
};

468 469 470

/*
  Rowid-Ordered Retrieval (ROR) index intersection quick select.
unknown's avatar
unknown committed
471
  This quick select produces intersection of row sequences returned
472
  by several QUICK_RANGE_SELECTs it "merges".
unknown's avatar
unknown committed
473 474

  All merged QUICK_RANGE_SELECTs must return rowids in rowid order.
475 476
  QUICK_ROR_INTERSECT_SELECT will return rows in rowid order, too.

unknown's avatar
unknown committed
477
  All merged quick selects retrieve {rowid, covered_fields} tuples (not full
478
  table records).
unknown's avatar
unknown committed
479 480
  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
481
  cover needed all fields.
unknown's avatar
unknown committed
482

483 484
  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.
485
*/
486

unknown's avatar
unknown committed
487
class QUICK_ROR_INTERSECT_SELECT : public QUICK_SELECT_I
488 489
{
public:
unknown's avatar
unknown committed
490
  QUICK_ROR_INTERSECT_SELECT(THD *thd, TABLE *table,
491 492 493 494 495 496 497 498 499 500
                             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; }
501 502
  void add_keys_and_lengths(String *key_names, String *used_lengths);
  void add_info_string(String *str);
503
  bool is_keys_used(const MY_BITMAP *fields);
504
#ifndef DBUG_OFF
505
  void dbug_dump(int indent, bool verbose);
506
#endif
507
  int init_ror_merged_scan(bool reuse_handler);
508 509
  bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range);

unknown's avatar
unknown committed
510
  /*
511 512 513
    Range quick selects this intersection consists of, not including
    cpk_quick.
  */
514
  List<QUICK_RANGE_SELECT> quick_selects;
unknown's avatar
unknown committed
515 516 517

  /*
    Merged quick select that uses Clustered PK, if there is one. This quick
518 519
    select is not used for row retrieval, it is used for row retrieval.
  */
520
  QUICK_RANGE_SELECT *cpk_quick;
521 522 523 524

  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
525 526
  /* in top-level quick select, true if merged scans where initialized */
  bool scans_inited; 
527 528
};

529

530 531
/*
  Rowid-Ordered Retrieval index union select.
532 533
  This quick select produces union of row sequences returned by several
  quick select it "merges".
534

unknown's avatar
unknown committed
535
  All merged quick selects must return rowids in rowid order.
536 537 538 539
  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
540

541
*/
542

unknown's avatar
unknown committed
543
class QUICK_ROR_UNION_SELECT : public QUICK_SELECT_I
544 545 546 547 548 549 550 551 552 553 554
{
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; }
555 556
  void add_keys_and_lengths(String *key_names, String *used_lengths);
  void add_info_string(String *str);
557
  bool is_keys_used(const MY_BITMAP *fields);
558
#ifndef DBUG_OFF
559
  void dbug_dump(int indent, bool verbose);
560 561 562 563
#endif

  bool push_quick_back(QUICK_SELECT_I *quick_sel_range);

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

566 567 568 569
  QUEUE queue;    /* Priority queue for merge operation */
  MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */

  THD *thd;             /* current thread */
570 571
  uchar *cur_rowid;      /* buffer used in get_next() */
  uchar *prev_rowid;     /* rowid of last row returned by get_next() */
572
  bool have_prev_rowid; /* true if prev_rowid has valid data */
unknown's avatar
unknown committed
573
  uint rowid_length;    /* table rowid length */
574
private:
575
  static int queue_cmp(void *arg, uchar *val1, uchar *val2);
unknown's avatar
unknown committed
576
  bool scans_inited; 
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 611 612 613 614 615 616 617 618
/*
  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 */
619 620 621
  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. */
622
  uint group_prefix_len; /* Length of the group prefix. */
unknown's avatar
unknown committed
623
  uint group_key_parts;  /* A number of keyparts in the group prefix */
624
  uchar *last_prefix;     /* Prefix of the last group for detecting EOF. */
625 626 627
  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.*/
628 629
  bool doing_key_read;   /* true if we enabled key only reads */

630 631 632
  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 */
633
  uchar *key_infix;       /* Infix of constants from equality predicates. */
634 635 636
  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
637
  uint real_key_parts;  /* A number of keyparts in the above value.      */
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
  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,
660 661 662
                             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
663
                             key_infix_len, uchar *key_infix, MEM_ROOT
664
                             *parent_alloc);
665 666 667
  ~QUICK_GROUP_MIN_MAX_SELECT();
  bool add_range(SEL_ARG *sel_range);
  void update_key_stat();
668
  void adjust_prefix_ranges();
669 670 671 672 673 674 675 676 677 678 679 680 681 682
  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
683
class QUICK_SELECT_DESC: public QUICK_RANGE_SELECT
684 685
{
public:
unknown's avatar
unknown committed
686
  QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, uint used_key_parts);
687
  int get_next();
688
  bool reverse_sorted() { return 1; }
unknown's avatar
unknown committed
689
  int get_type() { return QS_TYPE_RANGE_DESC; }
690 691
private:
  bool range_reads_after_key(QUICK_RANGE *range);
unknown's avatar
unknown committed
692
  int reset(void) { rev_it.rewind(); return QUICK_RANGE_SELECT::reset(); }
693 694
  List<QUICK_RANGE> rev_ranges;
  List_iterator<QUICK_RANGE> rev_it;
695
  uint used_key_parts;
696 697
};

698

unknown's avatar
unknown committed
699 700
class SQL_SELECT :public Sql_alloc {
 public:
unknown's avatar
unknown committed
701
  QUICK_SELECT_I *quick;	// If quick-select used
unknown's avatar
unknown committed
702 703 704 705 706 707 708 709 710 711 712 713
  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();
714
  void cleanup();
unknown's avatar
unknown committed
715
  bool check_quick(THD *thd, bool force_quick_range, ha_rows limit)
716 717 718 719 720
  {
    key_map tmp;
    tmp.set_all();
    return test_quick_select(thd, tmp, 0, limit, force_quick_range) < 0;
  }
721 722 723 724 725 726 727 728 729 730 731 732 733
  /* 
    RETURN
      0   if record must be skipped <-> (cond && cond->val_int() == 0)
     -1   if error
      1   otherwise
  */   
  inline int skip_record(THD *thd)
  {
    int rc= test(!cond || cond->val_int());
    if (thd->is_error())
      rc= -1;
    return rc;
  }
734
  int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
735
			ha_rows limit, bool force_quick_range);
unknown's avatar
unknown committed
736 737
};

unknown's avatar
unknown committed
738

unknown's avatar
unknown committed
739
class FT_SELECT: public QUICK_RANGE_SELECT {
unknown's avatar
unknown committed
740
public:
unknown's avatar
unknown committed
741
  FT_SELECT(THD *thd, TABLE *table, uint key) :
742
      QUICK_RANGE_SELECT (thd, table, key, 1) { VOID(init()); }
743
  ~FT_SELECT() { file->ft_end(); }
unknown's avatar
unknown committed
744
  int init() { return error=file->ft_init(); }
unknown's avatar
unknown committed
745
  int reset() { return 0; }
unknown's avatar
unknown committed
746 747
  int get_next() { return error=file->ft_read(record); }
  int get_type() { return QS_TYPE_FULLTEXT; }
unknown's avatar
unknown committed
748 749
};

unknown's avatar
unknown committed
750
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
unknown's avatar
unknown committed
751 752
                                             struct st_table_ref *ref,
                                             ha_rows records);
753 754
uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit);

unknown's avatar
unknown committed
755 756
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond);
757
void store_key_image_to_rec(Field *field, uchar *ptr, uint len);
unknown's avatar
unknown committed
758 759
#endif

unknown's avatar
unknown committed
760
#endif