~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/opt_range.cc

Removed dead variable, sorted authors file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
103
103
           subject and may omit some details.
104
104
*/
105
105
 
106
 
#include <drizzled/server_includes.h>
107
 
#include <drizzled/sql_select.h>
 
106
#ifdef USE_PRAGMA_IMPLEMENTATION
 
107
#pragma implementation                          // gcc: Class implementation
 
108
#endif
 
109
 
 
110
#include "mysql_priv.h"
 
111
#include <m_ctype.h>
 
112
#include "sql_select.h"
108
113
 
109
114
#ifndef EXTRA_DEBUG
110
115
#define test_rb_tree(A,B) {}
117
122
*/
118
123
#define double2rows(x) ((ha_rows)(x))
119
124
 
120
 
static int sel_cmp(Field *f,unsigned char *a,unsigned char *b,uint8_t a_flag,uint8_t b_flag);
 
125
static int sel_cmp(Field *f,uchar *a,uchar *b,uint8 a_flag,uint8 b_flag);
121
126
 
122
 
static unsigned char is_null_string[2]= {1,0};
 
127
static uchar is_null_string[2]= {1,0};
123
128
 
124
129
class RANGE_OPT_PARAM;
125
130
/*
295
300
class SEL_ARG :public Sql_alloc
296
301
{
297
302
public:
298
 
  uint8_t min_flag,max_flag,maybe_flag;
299
 
  uint8_t part;                                 // Which key part
300
 
  uint8_t maybe_null;
 
303
  uint8 min_flag,max_flag,maybe_flag;
 
304
  uint8 part;                                   // Which key part
 
305
  uint8 maybe_null;
301
306
  /* 
302
307
    Number of children of this element in the RB-tree, plus 1 for this
303
308
    element itself.
304
309
  */
305
 
  uint16_t elements;
 
310
  uint16 elements;
306
311
  /*
307
312
    Valid only for elements which are RB-tree roots: Number of times this
308
313
    RB-tree is referred to (it is referred by SEL_ARG::next_key_part or by
311
316
  ulong use_count;
312
317
 
313
318
  Field *field;
314
 
  unsigned char *min_value,*max_value;                  // Pointer to range
 
319
  uchar *min_value,*max_value;                  // Pointer to range
315
320
 
316
321
  /*
317
322
    eq_tree() requires that left == right == 0 if the type is MAYBE_KEY.
327
332
 
328
333
  SEL_ARG() {}
329
334
  SEL_ARG(SEL_ARG &);
330
 
  SEL_ARG(Field *,const unsigned char *, const unsigned char *);
331
 
  SEL_ARG(Field *field, uint8_t part, unsigned char *min_value, unsigned char *max_value,
332
 
          uint8_t min_flag, uint8_t max_flag, uint8_t maybe_flag);
 
335
  SEL_ARG(Field *,const uchar *, const uchar *);
 
336
  SEL_ARG(Field *field, uint8 part, uchar *min_value, uchar *max_value,
 
337
          uint8 min_flag, uint8 max_flag, uint8 maybe_flag);
333
338
  SEL_ARG(enum Type type_arg)
334
339
    :min_flag(0),elements(1),use_count(1),left(0),right(0),next_key_part(0),
335
340
    color(BLACK), type(type_arg)
364
369
  }
365
370
  SEL_ARG *clone_and(SEL_ARG* arg)
366
371
  {                                             // Get overlapping range
367
 
    unsigned char *new_min,*new_max;
368
 
    uint8_t flag_min,flag_max;
 
372
    uchar *new_min,*new_max;
 
373
    uint8 flag_min,flag_max;
369
374
    if (cmp_min_to_min(arg) >= 0)
370
375
    {
371
376
      new_min=min_value; flag_min=min_flag;
438
443
    min_flag=arg->max_flag & NEAR_MAX ? 0 : NEAR_MIN;
439
444
  }
440
445
  /* returns a number of keypart values (0 or 1) appended to the key buffer */
441
 
  int store_min(uint32_t length, unsigned char **min_key,uint32_t min_key_flag)
 
446
  int store_min(uint length, uchar **min_key,uint min_key_flag)
442
447
  {
443
448
    /* "(kp1 > c1) AND (kp2 OP c2) AND ..." -> (kp1 > c1) */
444
449
    if ((!(min_flag & NO_MIN_RANGE) &&
447
452
      if (maybe_null && *min_value)
448
453
      {
449
454
        **min_key=1;
450
 
        memset(*min_key+1, 0, length-1);
 
455
        bzero(*min_key+1,length-1);
451
456
      }
452
457
      else
453
458
        memcpy(*min_key,min_value,length);
457
462
    return 0;
458
463
  }
459
464
  /* returns a number of keypart values (0 or 1) appended to the key buffer */
460
 
  int store_max(uint32_t length, unsigned char **max_key, uint32_t max_key_flag)
 
465
  int store_max(uint length, uchar **max_key, uint max_key_flag)
461
466
  {
462
467
    if (!(max_flag & NO_MAX_RANGE) &&
463
468
        !(max_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
465
470
      if (maybe_null && *max_value)
466
471
      {
467
472
        **max_key=1;
468
 
        memset(*max_key+1, 0, length-1);
 
473
        bzero(*max_key+1,length-1);
469
474
      }
470
475
      else
471
476
        memcpy(*max_key,max_value,length);
476
481
  }
477
482
 
478
483
  /* returns a number of keypart values appended to the key buffer */
479
 
  int store_min_key(KEY_PART *key, unsigned char **range_key, uint32_t *range_key_flag)
 
484
  int store_min_key(KEY_PART *key, uchar **range_key, uint *range_key_flag)
480
485
  {
481
486
    SEL_ARG *key_tree= first();
482
 
    uint32_t res= key_tree->store_min(key[key_tree->part].store_length,
 
487
    uint res= key_tree->store_min(key[key_tree->part].store_length,
483
488
                                  range_key, *range_key_flag);
484
489
    *range_key_flag|= key_tree->min_flag;
485
490
    
493
498
  }
494
499
 
495
500
  /* returns a number of keypart values appended to the key buffer */
496
 
  int store_max_key(KEY_PART *key, unsigned char **range_key, uint32_t *range_key_flag)
 
501
  int store_max_key(KEY_PART *key, uchar **range_key, uint *range_key_flag)
497
502
  {
498
503
    SEL_ARG *key_tree= last();
499
 
    uint32_t res=key_tree->store_max(key[key_tree->part].store_length,
 
504
    uint res=key_tree->store_max(key[key_tree->part].store_length,
500
505
                                 range_key, *range_key_flag);
501
506
    (*range_key_flag)|= key_tree->max_flag;
502
507
    if (key_tree->next_key_part &&
575
580
    */
576
581
    if (min_flag || max_flag)
577
582
      return false;
578
 
    unsigned char *min_val= min_value;
579
 
    unsigned char *max_val= max_value;
 
583
    uchar *min_val= min_value;
 
584
    uchar *max_val= max_value;
580
585
 
581
586
    if (maybe_null)
582
587
    {
610
615
  SEL_TREE() :type(KEY)
611
616
  {
612
617
    keys_map.clear_all();
613
 
    memset(keys, 0, sizeof(keys));
 
618
    bzero((char*) keys,sizeof(keys));
614
619
  }
615
620
  /*
616
621
    Note: there may exist SEL_TREE objects with sel_tree->type=KEY and
629
634
 
630
635
  /* The members below are filled/used only after get_mm_tree is done */
631
636
  key_map ror_scans_map;   /* bitmask of ROR scan-able elements in keys */
632
 
  uint32_t    n_ror_scans;     /* number of set bits in ror_scans_map */
 
637
  uint    n_ror_scans;     /* number of set bits in ror_scans_map */
633
638
 
634
639
  struct st_ror_scan_info **ror_scans;     /* list of ROR key scans */
635
640
  struct st_ror_scan_info **ror_scans_end; /* last ROR scan */
640
645
{
641
646
public:
642
647
  THD   *thd;   /* Current thread handle */
643
 
  Table *table; /* Table being analyzed */
 
648
  TABLE *table; /* Table being analyzed */
644
649
  COND *cond;   /* Used inside get_mm_tree(). */
645
650
  table_map prev_tables;
646
651
  table_map read_tables;
655
660
    Number of indexes used in range analysis (In SEL_TREE::keys only first
656
661
    #keys elements are not empty)
657
662
  */
658
 
  uint32_t keys;
 
663
  uint keys;
659
664
  
660
665
  /* 
661
666
    If true, the index descriptions describe real indexes (and it is ok to
670
675
    used_key_no -> table_key_no translation table. Only makes sense if
671
676
    using_real_indexes==true
672
677
  */
673
 
  uint32_t real_keynr[MAX_KEY];
 
678
  uint real_keynr[MAX_KEY];
674
679
  /* Number of SEL_ARG objects allocated by SEL_ARG::clone_tree operations */
675
 
  uint32_t alloced_sel_args; 
 
680
  uint alloced_sel_args; 
676
681
  bool force_default_mrr;
677
682
};
678
683
 
681
686
public:
682
687
  KEY_PART *key[MAX_KEY]; /* First key parts of keys used in the query */
683
688
  int64_t baseflag;
684
 
  uint32_t max_key_part;
 
689
  uint max_key_part;
685
690
  /* Number of ranges in the last checked tree->key */
686
 
  uint32_t range_count;
687
 
  unsigned char min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
 
691
  uint range_count;
 
692
  uchar min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
688
693
    max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
689
694
  bool quick;                           // Don't calulate possible keys
690
695
 
691
 
  uint32_t fields_bitmap_size;
 
696
  uint fields_bitmap_size;
692
697
  MY_BITMAP needed_fields;    /* bitmask of fields needed by the query */
693
698
  MY_BITMAP tmp_covered_fields;
694
699
 
695
700
  key_map *needed_reg;        /* ptr to SQL_SELECT::needed_reg */
696
701
 
697
 
  uint32_t *imerge_cost_buff;     /* buffer for index_merge cost estimates */
698
 
  uint32_t imerge_cost_buff_size; /* size of the buffer */
 
702
  uint *imerge_cost_buff;     /* buffer for index_merge cost estimates */
 
703
  uint imerge_cost_buff_size; /* size of the buffer */
699
704
 
700
705
  /* true if last checked tree->key can be used for ROR-scan */
701
706
  bool is_ror_scan;
702
707
  /* Number of ranges in the last checked tree->key */
703
 
  uint32_t n_ranges;
 
708
  uint n_ranges;
704
709
};
705
710
 
706
711
class TABLE_READ_PLAN;
720
725
                            Item_func::Functype type,Item *value);
721
726
static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond);
722
727
 
723
 
static bool is_key_scan_ror(PARAM *param, uint32_t keynr, uint8_t nparts);
724
 
static ha_rows check_quick_select(PARAM *param, uint32_t idx, bool index_only,
 
728
static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts);
 
729
static ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
725
730
                                  SEL_ARG *tree, bool update_tbl_stats, 
726
 
                                  uint32_t *mrr_flags, uint32_t *bufsize,
 
731
                                  uint *mrr_flags, uint *bufsize,
727
732
                                  COST_VECT *cost);
728
733
                                  //bool update_tbl_stats);
729
 
/*static ha_rows check_quick_keys(PARAM *param,uint32_t index,SEL_ARG *key_tree,
730
 
                                unsigned char *min_key, uint32_t min_key_flag, int,
731
 
                                unsigned char *max_key, uint32_t max_key_flag, int);
 
734
/*static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree,
 
735
                                uchar *min_key, uint min_key_flag, int,
 
736
                                uchar *max_key, uint max_key_flag, int);
732
737
*/
733
738
 
734
 
QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint32_t index,
735
 
                                     SEL_ARG *key_tree, uint32_t mrr_flags, 
736
 
                                     uint32_t mrr_buf_size, MEM_ROOT *alloc);
 
739
QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index,
 
740
                                     SEL_ARG *key_tree, uint mrr_flags, 
 
741
                                     uint mrr_buf_size, MEM_ROOT *alloc);
737
742
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
738
743
                                       bool index_read_must_be_used,
739
744
                                       bool update_tbl_stats,
754
759
 
755
760
static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
756
761
                           const char *msg);
757
 
static void print_ror_scans_arr(Table *table, const char *msg,
 
762
static void print_ror_scans_arr(TABLE *table, const char *msg,
758
763
                                struct st_ror_scan_info **start,
759
764
                                struct st_ror_scan_info **end);
760
765
 
763
768
static SEL_ARG *sel_add(SEL_ARG *key1,SEL_ARG *key2);
764
769
static SEL_ARG *key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2);
765
770
static SEL_ARG *key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2,
766
 
                        uint32_t clone_flag);
 
771
                        uint clone_flag);
767
772
static bool get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1);
768
773
bool get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
769
 
                    SEL_ARG *key_tree, unsigned char *min_key,uint32_t min_key_flag,
770
 
                    unsigned char *max_key,uint32_t max_key_flag);
 
774
                    SEL_ARG *key_tree, uchar *min_key,uint min_key_flag,
 
775
                    uchar *max_key,uint max_key_flag);
771
776
static bool eq_tree(SEL_ARG* a,SEL_ARG *b);
772
777
 
773
778
static SEL_ARG null_element(SEL_ARG::IMPOSSIBLE);
774
 
static bool null_part_in_key(KEY_PART *key_part, const unsigned char *key,
775
 
                             uint32_t length);
 
779
static bool null_part_in_key(KEY_PART *key_part, const uchar *key,
 
780
                             uint length);
776
781
bool sel_trees_can_be_ored(SEL_TREE *tree1, SEL_TREE *tree2, RANGE_OPT_PARAM* param);
777
782
 
778
783
 
828
833
  if (trees_next == trees_end)
829
834
  {
830
835
    const int realloc_ratio= 2;         /* Double size for next round */
831
 
    uint32_t old_elements= (trees_end - trees);
832
 
    uint32_t old_size= sizeof(SEL_TREE**) * old_elements;
833
 
    uint32_t new_size= old_size * realloc_ratio;
 
836
    uint old_elements= (trees_end - trees);
 
837
    uint old_size= sizeof(SEL_TREE**) * old_elements;
 
838
    uint new_size= old_size * realloc_ratio;
834
839
    SEL_TREE **new_trees;
835
840
    if (!(new_trees= (SEL_TREE**)alloc_root(param->mem_root, new_size)))
836
841
      return -1;
999
1004
           1 = Got some error (out of memory?)
1000
1005
           */
1001
1006
 
1002
 
SQL_SELECT *make_select(Table *head, table_map const_tables,
 
1007
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
1003
1008
                        table_map read_tables, COND *conds,
1004
1009
                        bool allow_null_cond,
1005
1010
                        int *error)
1025
1030
    select->file= *head->sort.io_cache;
1026
1031
    select->records=(ha_rows) (select->file.end_of_file/
1027
1032
                               head->file->ref_length);
1028
 
    free(head->sort.io_cache);
 
1033
    my_free(head->sort.io_cache, MYF(0));
1029
1034
    head->sort.io_cache=0;
1030
1035
  }
1031
1036
  return(select);
1063
1068
   used_key_parts(0)
1064
1069
{}
1065
1070
 
1066
 
QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, Table *table, uint32_t key_nr,
 
1071
QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
1067
1072
                                       bool no_alloc, MEM_ROOT *parent_alloc,
1068
1073
                                       bool *create_error)
1069
1074
  :free_file(0),cur_range(NULL),last_range(0),dont_free(0)
1088
1093
    thd->mem_root= &alloc;
1089
1094
  }
1090
1095
  else
1091
 
    memset(&alloc, 0, sizeof(alloc));
 
1096
    bzero((char*) &alloc,sizeof(alloc));
1092
1097
  file= head->file;
1093
1098
  record= head->record[0];
1094
1099
  save_read_set= head->read_set;
1144
1149
    }
1145
1150
    delete_dynamic(&ranges); /* ranges are allocated in alloc */
1146
1151
    free_root(&alloc,MYF(0));
1147
 
    free((char*) column_bitmap.bitmap);
 
1152
    my_free((char*) column_bitmap.bitmap, MYF(MY_ALLOW_ZERO_PTR));
1148
1153
  }
1149
1154
  head->column_bitmaps_set(save_read_set, save_write_set);
1150
 
  if (mrr_buf_desc)
1151
 
    free(mrr_buf_desc);
 
1155
  x_free(mrr_buf_desc);
1152
1156
  return;
1153
1157
}
1154
1158
 
1155
1159
 
1156
1160
QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param,
1157
 
                                                   Table *table)
 
1161
                                                   TABLE *table)
1158
1162
  :pk_quick_select(NULL), thd(thd_param)
1159
1163
{
1160
1164
  index= MAX_KEY;
1161
1165
  head= table;
1162
 
  memset(&read_record, 0, sizeof(read_record));
 
1166
  bzero(&read_record, sizeof(read_record));
1163
1167
  init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
1164
1168
  return;
1165
1169
}
1204
1208
 
1205
1209
 
1206
1210
QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
1207
 
                                                       Table *table,
 
1211
                                                       TABLE *table,
1208
1212
                                                       bool retrieve_full_rows,
1209
1213
                                                       MEM_ROOT *parent_alloc)
1210
1214
  : cpk_quick(NULL), thd(thd_param), need_to_fetch_row(retrieve_full_rows),
1216
1220
  if (!parent_alloc)
1217
1221
    init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
1218
1222
  else
1219
 
    memset(&alloc, 0, sizeof(MEM_ROOT));
1220
 
  last_rowid= (unsigned char*) alloc_root(parent_alloc? parent_alloc : &alloc,
 
1223
    bzero(&alloc, sizeof(MEM_ROOT));
 
1224
  last_rowid= (uchar*) alloc_root(parent_alloc? parent_alloc : &alloc,
1221
1225
                                  head->file->ref_length);
1222
1226
}
1223
1227
 
1443
1447
 
1444
1448
 
1445
1449
QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
1446
 
                                               Table *table)
 
1450
                                               TABLE *table)
1447
1451
  : thd(thd_param), scans_inited(false)
1448
1452
{
1449
1453
  index= MAX_KEY;
1471
1475
                 false , QUICK_ROR_UNION_SELECT::queue_cmp,
1472
1476
                 (void*) this))
1473
1477
  {
1474
 
    memset(&queue, 0, sizeof(QUEUE));
 
1478
    bzero(&queue, sizeof(QUEUE));
1475
1479
    return(1);
1476
1480
  }
1477
1481
 
1478
 
  if (!(cur_rowid= (unsigned char*) alloc_root(&alloc, 2*head->file->ref_length)))
 
1482
  if (!(cur_rowid= (uchar*) alloc_root(&alloc, 2*head->file->ref_length)))
1479
1483
    return(1);
1480
1484
  prev_rowid= cur_rowid + head->file->ref_length;
1481
1485
  return(0);
1493
1497
      val2  Second merged select
1494
1498
*/
1495
1499
 
1496
 
int QUICK_ROR_UNION_SELECT::queue_cmp(void *arg, unsigned char *val1, unsigned char *val2)
 
1500
int QUICK_ROR_UNION_SELECT::queue_cmp(void *arg, uchar *val1, uchar *val2)
1497
1501
{
1498
1502
  QUICK_ROR_UNION_SELECT *self= (QUICK_ROR_UNION_SELECT*)arg;
1499
1503
  return self->head->file->cmp_ref(((QUICK_SELECT_I*)val1)->last_rowid,
1543
1547
      return(error);
1544
1548
    }
1545
1549
    quick->save_last_pos();
1546
 
    queue_insert(&queue, (unsigned char*)quick);
 
1550
    queue_insert(&queue, (uchar*)quick);
1547
1551
  }
1548
1552
 
1549
1553
  if (head->file->ha_rnd_init(1))
1602
1606
  use_count=0; elements=1;
1603
1607
}
1604
1608
 
1605
 
SEL_ARG::SEL_ARG(Field *f,const unsigned char *min_value_arg,
1606
 
                 const unsigned char *max_value_arg)
 
1609
SEL_ARG::SEL_ARG(Field *f,const uchar *min_value_arg,
 
1610
                 const uchar *max_value_arg)
1607
1611
  :min_flag(0), max_flag(0), maybe_flag(0), maybe_null(f->real_maybe_null()),
1608
 
   elements(1), use_count(1), field(f), min_value((unsigned char*) min_value_arg),
1609
 
   max_value((unsigned char*) max_value_arg), next(0),prev(0),
 
1612
   elements(1), use_count(1), field(f), min_value((uchar*) min_value_arg),
 
1613
   max_value((uchar*) max_value_arg), next(0),prev(0),
1610
1614
   next_key_part(0),color(BLACK),type(KEY_RANGE)
1611
1615
{
1612
1616
  left=right= &null_element;
1613
1617
}
1614
1618
 
1615
 
SEL_ARG::SEL_ARG(Field *field_,uint8_t part_,
1616
 
                 unsigned char *min_value_, unsigned char *max_value_,
1617
 
                 uint8_t min_flag_,uint8_t max_flag_,uint8_t maybe_flag_)
 
1619
SEL_ARG::SEL_ARG(Field *field_,uint8 part_,
 
1620
                 uchar *min_value_, uchar *max_value_,
 
1621
                 uint8 min_flag_,uint8 max_flag_,uint8 maybe_flag_)
1618
1622
  :min_flag(min_flag_),max_flag(max_flag_),maybe_flag(maybe_flag_),
1619
1623
   part(part_),maybe_null(field_->real_maybe_null()), elements(1),use_count(1),
1620
1624
   field(field_), min_value(min_value_), max_value(max_value_),
1691
1695
  Returns -2 or 2 if the ranges where 'joined' like  < 2 and >= 2
1692
1696
*/
1693
1697
 
1694
 
static int sel_cmp(Field *field, unsigned char *a, unsigned char *b, uint8_t a_flag,
1695
 
                   uint8_t b_flag)
 
1698
static int sel_cmp(Field *field, uchar *a, uchar *b, uint8 a_flag,
 
1699
                   uint8 b_flag)
1696
1700
{
1697
1701
  int cmp;
1698
1702
  /* First check if there was a compare to a min or max element */
1778
1782
    MAX_KEY if no such index was found.
1779
1783
*/
1780
1784
 
1781
 
uint32_t get_index_for_order(Table *table, order_st *order, ha_rows limit)
 
1785
uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit)
1782
1786
{
1783
 
  uint32_t idx;
1784
 
  uint32_t match_key= MAX_KEY, match_key_len= MAX_KEY_LENGTH + 1;
1785
 
  order_st *ord;
 
1787
  uint idx;
 
1788
  uint match_key= MAX_KEY, match_key_len= MAX_KEY_LENGTH + 1;
 
1789
  ORDER *ord;
1786
1790
  
1787
1791
  for (ord= order; ord; ord= ord->next)
1788
1792
    if (!ord->asc)
1793
1797
    if (!(table->keys_in_use_for_query.is_set(idx)))
1794
1798
      continue;
1795
1799
    KEY_PART_INFO *keyinfo= table->key_info[idx].key_part;
1796
 
    uint32_t n_parts=  table->key_info[idx].key_parts;
1797
 
    uint32_t partno= 0;
 
1800
    uint n_parts=  table->key_info[idx].key_parts;
 
1801
    uint partno= 0;
1798
1802
    
1799
1803
    /* 
1800
1804
      The below check is sufficient considering we now have either BTREE 
1882
1886
  /* Table read plans are allocated on MEM_ROOT and are never deleted */
1883
1887
  static void *operator new(size_t size, MEM_ROOT *mem_root)
1884
1888
  { return (void*) alloc_root(mem_root, (uint) size); }
1885
 
  static void operator delete(void *ptr __attribute__((unused)),
1886
 
                              size_t size __attribute__((unused)))
 
1889
  static void operator delete(void *ptr __attribute__((__unused__)),
 
1890
                              size_t size __attribute__((__unused__)))
1887
1891
    { TRASH(ptr, size); }
1888
 
  static void operator delete(void *ptr __attribute__((unused)),
1889
 
                              MEM_ROOT *mem_root __attribute__((unused)))
 
1892
  static void operator delete(void *ptr __attribute__((__unused__)),
 
1893
                              MEM_ROOT *mem_root __attribute__((__unused__)))
1890
1894
    { /* Never called */ }
1891
1895
  virtual ~TABLE_READ_PLAN() {}               /* Remove gcc warning */
1892
1896
 
1908
1912
{
1909
1913
public:
1910
1914
  SEL_ARG *key; /* set of intervals to be used in "range" method retrieval */
1911
 
  uint32_t     key_idx; /* key number in PARAM::key */
1912
 
  uint32_t     mrr_flags; 
1913
 
  uint32_t     mrr_buf_size;
 
1915
  uint     key_idx; /* key number in PARAM::key */
 
1916
  uint     mrr_flags; 
 
1917
  uint     mrr_buf_size;
1914
1918
 
1915
 
  TRP_RANGE(SEL_ARG *key_arg, uint32_t idx_arg, uint32_t mrr_flags_arg)
 
1919
  TRP_RANGE(SEL_ARG *key_arg, uint idx_arg, uint mrr_flags_arg)
1916
1920
   : key(key_arg), key_idx(idx_arg), mrr_flags(mrr_flags_arg)
1917
1921
  {}
1918
1922
  virtual ~TRP_RANGE() {}                     /* Remove gcc warning */
1919
1923
 
1920
1924
  QUICK_SELECT_I *make_quick(PARAM *param,
1921
 
                             bool retrieve_full_rows __attribute__((unused)),
 
1925
                             bool retrieve_full_rows __attribute__((__unused__)),
1922
1926
                             MEM_ROOT *parent_alloc)
1923
1927
  {
1924
1928
    QUICK_RANGE_SELECT *quick;
1997
2001
private:
1998
2002
  bool have_min, have_max;
1999
2003
  KEY_PART_INFO *min_max_arg_part;
2000
 
  uint32_t group_prefix_len;
2001
 
  uint32_t used_key_parts;
2002
 
  uint32_t group_key_parts;
 
2004
  uint group_prefix_len;
 
2005
  uint used_key_parts;
 
2006
  uint group_key_parts;
2003
2007
  KEY *index_info;
2004
 
  uint32_t index;
2005
 
  uint32_t key_infix_len;
2006
 
  unsigned char key_infix[MAX_KEY_LENGTH];
 
2008
  uint index;
 
2009
  uint key_infix_len;
 
2010
  uchar key_infix[MAX_KEY_LENGTH];
2007
2011
  SEL_TREE *range_tree; /* Represents all range predicates in the query. */
2008
2012
  SEL_ARG  *index_tree; /* The SEL_ARG sub-tree corresponding to index_info. */
2009
 
  uint32_t param_idx; /* Index of used key in param->key. */
 
2013
  uint param_idx; /* Index of used key in param->key. */
2010
2014
  /* Number of records selected by the ranges in index_tree. */
2011
2015
public:
2012
2016
  ha_rows quick_prefix_records;
2013
2017
public:
2014
2018
  TRP_GROUP_MIN_MAX(bool have_min_arg, bool have_max_arg,
2015
2019
                    KEY_PART_INFO *min_max_arg_part_arg,
2016
 
                    uint32_t group_prefix_len_arg, uint32_t used_key_parts_arg,
2017
 
                    uint32_t group_key_parts_arg, KEY *index_info_arg,
2018
 
                    uint32_t index_arg, uint32_t key_infix_len_arg,
2019
 
                    unsigned char *key_infix_arg,
 
2020
                    uint group_prefix_len_arg, uint used_key_parts_arg,
 
2021
                    uint group_key_parts_arg, KEY *index_info_arg,
 
2022
                    uint index_arg, uint key_infix_len_arg,
 
2023
                    uchar *key_infix_arg,
2020
2024
                    SEL_TREE *tree_arg, SEL_ARG *index_tree_arg,
2021
 
                    uint32_t param_idx_arg, ha_rows quick_prefix_records_arg)
 
2025
                    uint param_idx_arg, ha_rows quick_prefix_records_arg)
2022
2026
  : have_min(have_min_arg), have_max(have_max_arg),
2023
2027
    min_max_arg_part(min_max_arg_part_arg),
2024
2028
    group_prefix_len(group_prefix_len_arg), used_key_parts(used_key_parts_arg),
2053
2057
 
2054
2058
static int fill_used_fields_bitmap(PARAM *param)
2055
2059
{
2056
 
  Table *table= param->table;
 
2060
  TABLE *table= param->table;
2057
2061
  my_bitmap_map *tmp;
2058
 
  uint32_t pk;
 
2062
  uint pk;
2059
2063
  param->tmp_covered_fields.bitmap= 0;
2060
2064
  param->fields_bitmap_size= table->s->column_bitmap_size;
2061
2065
  if (!(tmp= (my_bitmap_map*) alloc_root(param->mem_root,
2151
2155
                                  ha_rows limit, bool force_quick_range, 
2152
2156
                                  bool ordered_output)
2153
2157
{
2154
 
  uint32_t idx;
 
2158
  uint idx;
2155
2159
  double scan_time;
2156
2160
  delete quick;
2157
2161
  quick=0;
2226
2230
 
2227
2231
      param.key[param.keys]=key_parts;
2228
2232
      key_part_info= key_info->key_part;
2229
 
      for (uint32_t part=0 ; part < key_info->key_parts ;
 
2233
      for (uint part=0 ; part < key_info->key_parts ;
2230
2234
           part++, key_parts++, key_part_info++)
2231
2235
      {
2232
2236
        key_parts->key=          param.keys;
2237
2241
        key_parts->null_bit=     key_part_info->null_bit;
2238
2242
        key_parts->image_type =  Field::itRAW;
2239
2243
        /* Only HA_PART_KEY_SEG is used */
2240
 
        key_parts->flag=         (uint8_t) key_part_info->key_part_flag;
 
2244
        key_parts->flag=         (uint8) key_part_info->key_part_flag;
2241
2245
      }
2242
2246
      param.real_keynr[param.keys++]=idx;
2243
2247
    }
2247
2251
    /* Calculate cost of full index read for the shortest covering index */
2248
2252
    if (!head->covering_keys.is_clear_all())
2249
2253
    {
2250
 
      int key_for_use= head->find_shortest_key(&head->covering_keys);
 
2254
      int key_for_use= find_shortest_key(head, &head->covering_keys);
2251
2255
      double key_read_time= 
2252
2256
        param.table->file->index_only_read_time(key_for_use, 
2253
2257
                                                rows2double(records)) +
2286
2290
    group_trp= get_best_group_min_max(&param, tree);
2287
2291
    if (group_trp)
2288
2292
    {
2289
 
      param.table->quick_condition_rows= cmin(group_trp->records,
 
2293
      param.table->quick_condition_rows= min(group_trp->records,
2290
2294
                                             head->file->stats.records);
2291
2295
      if (group_trp->read_cost < best_read_time)
2292
2296
      {
2460
2464
{
2461
2465
  SEL_TREE **ptree;
2462
2466
  TRP_INDEX_MERGE *imerge_trp= NULL;
2463
 
  uint32_t n_child_scans= imerge->trees_next - imerge->trees;
 
2467
  uint n_child_scans= imerge->trees_next - imerge->trees;
2464
2468
  TRP_RANGE **range_scans;
2465
2469
  TRP_RANGE **cur_child;
2466
2470
  TRP_RANGE **cpk_scan= NULL;
2471
2475
  bool pk_is_clustered= param->table->file->primary_key_is_clustered();
2472
2476
  bool all_scans_ror_able= true;
2473
2477
  bool all_scans_rors= true;
2474
 
  uint32_t unique_calc_buff_size;
 
2478
  uint unique_calc_buff_size;
2475
2479
  TABLE_READ_PLAN **roru_read_plans;
2476
2480
  TABLE_READ_PLAN **cur_roru_plan;
2477
2481
  double roru_index_costs;
2577
2581
    {
2578
2582
      imerge_trp->read_cost= imerge_cost;
2579
2583
      imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
2580
 
      imerge_trp->records= cmin(imerge_trp->records,
 
2584
      imerge_trp->records= min(imerge_trp->records,
2581
2585
                               param->table->file->stats.records);
2582
2586
      imerge_trp->range_scans= range_scans;
2583
2587
      imerge_trp->range_scans_end= range_scans + n_child_scans;
2689
2693
 
2690
2694
typedef struct st_ror_scan_info
2691
2695
{
2692
 
  uint32_t      idx;      /* # of used key in param->keys */
2693
 
  uint32_t      keynr;    /* # of used key in table */
 
2696
  uint      idx;      /* # of used key in param->keys */
 
2697
  uint      keynr;    /* # of used key in table */
2694
2698
  ha_rows   records;  /* estimate of # records this scan will return */
2695
2699
 
2696
2700
  /* Set of intervals over key fields that will be used for row retrieval. */
2698
2702
 
2699
2703
  /* Fields used in the query and covered by this ROR scan. */
2700
2704
  MY_BITMAP covered_fields;
2701
 
  uint32_t      used_fields_covered; /* # of set bits in covered_fields */
 
2705
  uint      used_fields_covered; /* # of set bits in covered_fields */
2702
2706
  int       key_rec_length; /* length of key record (including rowid) */
2703
2707
 
2704
2708
  /*
2706
2710
    (assuming there is no need to access full table records)
2707
2711
  */
2708
2712
  double    index_read_cost;
2709
 
  uint32_t      first_uncovered_field; /* first unused bit in covered_fields */
2710
 
  uint32_t      key_components; /* # of parts in the key */
 
2713
  uint      first_uncovered_field; /* first unused bit in covered_fields */
 
2714
  uint      key_components; /* # of parts in the key */
2711
2715
} ROR_SCAN_INFO;
2712
2716
 
2713
2717
 
2731
2735
{
2732
2736
  ROR_SCAN_INFO *ror_scan;
2733
2737
  my_bitmap_map *bitmap_buf;
2734
 
  uint32_t keynr;
 
2738
  uint keynr;
2735
2739
 
2736
2740
  if (!(ror_scan= (ROR_SCAN_INFO*)alloc_root(param->mem_root,
2737
2741
                                             sizeof(ROR_SCAN_INFO))))
2986
2990
{
2987
2991
  double selectivity_mult= 1.0;
2988
2992
  KEY_PART_INFO *key_part= info->param->table->key_info[scan->keynr].key_part;
2989
 
  unsigned char key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; /* key values tuple */
2990
 
  unsigned char *key_ptr= key_val;
 
2993
  uchar key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; /* key values tuple */
 
2994
  uchar *key_ptr= key_val;
2991
2995
  SEL_ARG *sel_arg, *tuple_arg= NULL;
2992
2996
  key_part_map keypart_map= 0;
2993
2997
  bool cur_covered;
3208
3212
                                          double read_time,
3209
3213
                                          bool *are_all_covering)
3210
3214
{
3211
 
  uint32_t idx;
 
3215
  uint idx;
3212
3216
  double min_cost= DBL_MAX;
3213
3217
 
3214
3218
  if ((tree->n_ror_scans < 2) || !param->table->file->stats.records)
3220
3224
  */
3221
3225
  ROR_SCAN_INFO **cur_ror_scan;
3222
3226
  ROR_SCAN_INFO *cpk_scan= NULL;
3223
 
  uint32_t cpk_no;
 
3227
  uint cpk_no;
3224
3228
  bool cpk_scan_used= false;
3225
3229
 
3226
3230
  if (!(tree->ror_scans= (ROR_SCAN_INFO**)alloc_root(param->mem_root,
3310
3314
                                          intersect_scans_best);
3311
3315
 
3312
3316
  *are_all_covering= intersect->is_covering;
3313
 
  uint32_t best_num= intersect_scans_best - intersect_scans;
 
3317
  uint best_num= intersect_scans_best - intersect_scans;
3314
3318
  ror_intersect_cpy(intersect, intersect_best);
3315
3319
 
3316
3320
  /*
3481
3485
  TRP_ROR_INTERSECT *trp;
3482
3486
  if (!(trp= new (param->mem_root) TRP_ROR_INTERSECT))
3483
3487
    return(trp);
3484
 
  uint32_t best_num= (ror_scan_mark - tree->ror_scans);
 
3488
  uint best_num= (ror_scan_mark - tree->ror_scans);
3485
3489
  if (!(trp->first_scan= (ROR_SCAN_INFO**)alloc_root(param->mem_root,
3486
3490
                                                     sizeof(ROR_SCAN_INFO*)*
3487
3491
                                                     best_num)))
3529
3533
                                       bool update_tbl_stats,
3530
3534
                                       double read_time)
3531
3535
{
3532
 
  uint32_t idx;
 
3536
  uint idx;
3533
3537
  SEL_ARG **key,**end, **key_to_read= NULL;
3534
3538
  ha_rows best_records= 0;
3535
 
  uint32_t    best_mrr_flags= 0, best_buf_size= 0;
 
3539
  uint    best_mrr_flags= 0, best_buf_size= 0;
3536
3540
  TRP_RANGE* read_plan= NULL;
3537
3541
  /*
3538
3542
    Note that there may be trees that have type SEL_TREE::KEY but contain no
3549
3553
      ha_rows found_records;
3550
3554
      COST_VECT cost;
3551
3555
      double found_read_time;
3552
 
      uint32_t mrr_flags, buf_size;
3553
 
      uint32_t keynr= param->real_keynr[idx];
 
3556
      uint mrr_flags, buf_size;
 
3557
      uint keynr= param->real_keynr[idx];
3554
3558
      if ((*key)->type == SEL_ARG::MAYBE_KEY ||
3555
3559
          (*key)->maybe_flag)
3556
3560
        param->needed_reg->set_bit(keynr);
3597
3601
 
3598
3602
 
3599
3603
QUICK_SELECT_I *TRP_INDEX_MERGE::make_quick(PARAM *param,
3600
 
                                            bool retrieve_full_rows __attribute__((unused)),
3601
 
                                            MEM_ROOT *parent_alloc __attribute__((unused)))
 
3604
                                            bool retrieve_full_rows __attribute__((__unused__)),
 
3605
                                            MEM_ROOT *parent_alloc __attribute__((__unused__)))
3602
3606
{
3603
3607
  QUICK_INDEX_MERGE_SELECT *quick_imerge;
3604
3608
  QUICK_RANGE_SELECT *quick;
3674
3678
 
3675
3679
 
3676
3680
QUICK_SELECT_I *TRP_ROR_UNION::make_quick(PARAM *param,
3677
 
                                          bool retrieve_full_rows __attribute__((unused)),
3678
 
                                          MEM_ROOT *parent_alloc __attribute__((unused)))
 
3681
                                          bool retrieve_full_rows __attribute__((__unused__)),
 
3682
                                          MEM_ROOT *parent_alloc __attribute__((__unused__)))
3679
3683
{
3680
3684
  QUICK_ROR_UNION_SELECT *quick_roru;
3681
3685
  TABLE_READ_PLAN **scan;
3856
3860
          break;
3857
3861
 
3858
3862
        /* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval.  */
3859
 
        uint32_t i=0;
 
3863
        uint i=0;
3860
3864
        do 
3861
3865
        {
3862
3866
          func->array->value_to_item(i, value_item);
3889
3893
            }
3890
3894
 
3891
3895
            /* Change all intervals to be "c_{i-1} < X < c_i" */
3892
 
            for (uint32_t idx= 0; idx < param->keys; idx++)
 
3896
            for (uint idx= 0; idx < param->keys; idx++)
3893
3897
            {
3894
3898
              SEL_ARG *new_interval, *last_val;
3895
3899
              if (((new_interval= tree2->keys[idx])) &&
4055
4059
  table_map param_comp= ~(param->prev_tables | param->read_tables |
4056
4060
                          param->current_table);
4057
4061
 
4058
 
  for (uint32_t i= 0; i < cond_func->arg_count; i++)
 
4062
  for (uint i= 0; i < cond_func->arg_count; i++)
4059
4063
  {
4060
4064
    Item *arg= cond_func->arguments()[i]->real_item();
4061
4065
    if (arg != field_item)
4183
4187
      Concerning the code below see the NOTES section in
4184
4188
      the comments for the function get_full_func_mm_tree()
4185
4189
    */
4186
 
    for (uint32_t i= 1 ; i < cond_func->arg_count ; i++)
 
4190
    for (uint i= 1 ; i < cond_func->arg_count ; i++)
4187
4191
    {
4188
4192
      if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM)
4189
4193
      {
4260
4264
get_mm_parts(RANGE_OPT_PARAM *param, COND *cond_func, Field *field,
4261
4265
             Item_func::Functype type,
4262
4266
             Item *value,
4263
 
             Item_result cmp_type __attribute__((unused)))
 
4267
             Item_result cmp_type __attribute__((__unused__)))
4264
4268
{
4265
4269
  if (field->table != param->table)
4266
4270
    return(0);
4296
4300
        if (!(sel_arg= new SEL_ARG(SEL_ARG::MAYBE_KEY)))
4297
4301
          return(0);                    // OOM
4298
4302
      }
4299
 
      sel_arg->part=(unsigned char) key_part->part;
 
4303
      sel_arg->part=(uchar) key_part->part;
4300
4304
      tree->keys[key_part->key]=sel_add(tree->keys[key_part->key],sel_arg);
4301
4305
      tree->keys_map.set_bit(key_part->key);
4302
4306
    }
4310
4314
get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
4311
4315
            KEY_PART *key_part, Item_func::Functype type,Item *value)
4312
4316
{
4313
 
  uint32_t maybe_null=(uint) field->real_maybe_null();
 
4317
  uint maybe_null=(uint) field->real_maybe_null();
4314
4318
  bool optimize_range;
4315
4319
  SEL_ARG *tree= 0;
4316
4320
  MEM_ROOT *alloc= param->mem_root;
4317
 
  unsigned char *str;
 
4321
  uchar *str;
4318
4322
  ulong orig_sql_mode;
4319
4323
  int err;
4320
4324
 
4376
4380
  {
4377
4381
    bool like_error;
4378
4382
    char buff1[MAX_FIELD_WIDTH];
4379
 
    unsigned char *min_str,*max_str;
 
4383
    uchar *min_str,*max_str;
4380
4384
    String tmp(buff1,sizeof(buff1),value->collation.collation),*res;
4381
4385
    size_t length, offset, min_length, max_length;
4382
 
    uint32_t field_length= field->pack_length()+maybe_null;
 
4386
    uint field_length= field->pack_length()+maybe_null;
4383
4387
 
4384
4388
    if (!optimize_range)
4385
4389
      goto end;
4425
4429
        field_length= length;
4426
4430
    }
4427
4431
    length+=offset;
4428
 
    if (!(min_str= (unsigned char*) alloc_root(alloc, length*2)))
 
4432
    if (!(min_str= (uchar*) alloc_root(alloc, length*2)))
4429
4433
      goto end;
4430
4434
 
4431
4435
    max_str=min_str+length;
4468
4472
  /* For comparison purposes allow invalid dates like 2000-01-32 */
4469
4473
  orig_sql_mode= field->table->in_use->variables.sql_mode;
4470
4474
  if (value->real_item()->type() == Item::STRING_ITEM &&
4471
 
      (field->type() == DRIZZLE_TYPE_NEWDATE ||
4472
 
       field->type() == DRIZZLE_TYPE_DATETIME))
 
4475
      (field->type() == MYSQL_TYPE_NEWDATE ||
 
4476
       field->type() == MYSQL_TYPE_DATETIME))
4473
4477
    field->table->in_use->variables.sql_mode|= MODE_INVALID_DATES;
4474
4478
  err= value->save_in_field_no_warnings(field, 1);
4475
4479
  if (err > 0)
4491
4495
          for the cases like int_field > 999999999999999999999999 as well.
4492
4496
        */
4493
4497
        tree= 0;
4494
 
        if (err == 3 && field->type() == DRIZZLE_TYPE_NEWDATE &&
 
4498
        if (err == 3 && field->type() == FIELD_TYPE_NEWDATE &&
4495
4499
            (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC ||
4496
4500
             type == Item_func::LT_FUNC || type == Item_func::LE_FUNC) )
4497
4501
        {
4543
4547
    goto end;
4544
4548
  }
4545
4549
  field->table->in_use->variables.sql_mode= orig_sql_mode;
4546
 
  str= (unsigned char*) alloc_root(alloc, key_part->store_length+1);
 
4550
  str= (uchar*) alloc_root(alloc, key_part->store_length+1);
4547
4551
  if (!str)
4548
4552
    goto end;
4549
4553
  if (maybe_null)
4550
 
    *str= (unsigned char) field->is_real_null();        // Set to 1 if null
 
4554
    *str= (uchar) field->is_real_null();        // Set to 1 if null
4551
4555
  field->get_key_image(str+maybe_null, key_part->length,
4552
4556
                       key_part->image_type);
4553
4557
  if (!(tree= new (alloc) SEL_ARG(field, str, str)))
4699
4703
  for (key1= tree1->keys,key2= tree2->keys,end=key1+param->keys ;
4700
4704
       key1 != end ; key1++,key2++)
4701
4705
  {
4702
 
    uint32_t flag=0;
 
4706
    uint flag=0;
4703
4707
    if (*key1 || *key2)
4704
4708
    {
4705
4709
      if (*key1 && !(*key1)->simple_key())
4750
4754
 
4751
4755
  /* trees have a common key, check if they refer to same key part */
4752
4756
  SEL_ARG **key1,**key2;
4753
 
  for (uint32_t key_no=0; key_no < param->keys; key_no++)
 
4757
  for (uint key_no=0; key_no < param->keys; key_no++)
4754
4758
  {
4755
4759
    if (common_keys.is_set(key_no))
4756
4760
    {
4824
4828
static bool remove_nonrange_trees(RANGE_OPT_PARAM *param, SEL_TREE *tree)
4825
4829
{
4826
4830
  bool res= false;
4827
 
  for (uint32_t i=0; i < param->keys; i++)
 
4831
  for (uint i=0; i < param->keys; i++)
4828
4832
  {
4829
4833
    if (tree->keys[i])
4830
4834
    {
4912
4916
    {
4913
4917
      /* one tree is index merge tree and another is range tree */
4914
4918
      if (tree1->merges.is_empty())
4915
 
        std::swap(tree1, tree2);
 
4919
        swap_variables(SEL_TREE*, tree1, tree2);
4916
4920
      
4917
4921
      if (param->remove_jump_scans && remove_nonrange_trees(param, tree2))
4918
4922
         return(new SEL_TREE(SEL_TREE::ALWAYS));
4931
4935
 
4932
4936
static SEL_ARG *
4933
4937
and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, 
4934
 
             uint32_t clone_flag)
 
4938
             uint clone_flag)
4935
4939
{
4936
4940
  SEL_ARG *next;
4937
4941
  ulong use_count=key1->use_count;
4988
4992
*/
4989
4993
 
4990
4994
static SEL_ARG *
4991
 
key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, uint32_t clone_flag)
 
4995
key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
4992
4996
{
4993
4997
  if (!key1)
4994
4998
    return key2;
4998
5002
  {
4999
5003
    if (key1->part > key2->part)
5000
5004
    {
5001
 
      std::swap(key1, key2);
 
5005
      swap_variables(SEL_ARG *, key1, key2);
5002
5006
      clone_flag=swap_clone_flag(clone_flag);
5003
5007
    }
5004
5008
    // key1->part < key2->part
5014
5018
       key2->type != SEL_ARG::MAYBE_KEY) ||
5015
5019
      key1->type == SEL_ARG::MAYBE_KEY)
5016
5020
  {                                             // Put simple key in key2
5017
 
    std::swap(key1, key2);
 
5021
    swap_variables(SEL_ARG *, key1, key2);
5018
5022
    clone_flag=swap_clone_flag(clone_flag);
5019
5023
  }
5020
5024
 
5157
5161
  {
5158
5162
    if (key2->use_count == 0 || key1->elements > key2->elements)
5159
5163
    {
5160
 
      std::swap(key1,key2);
 
5164
      swap_variables(SEL_ARG *,key1,key2);
5161
5165
    }
5162
5166
    if (key1->use_count > 0 || !(key1=key1->clone_tree(param)))
5163
5167
      return 0;                                 // OOM
5242
5246
      }
5243
5247
    }
5244
5248
 
5245
 
    // tmp.max >= key2.min && tmp.min <= key.cmax(overlapping ranges)
 
5249
    // tmp.max >= key2.min && tmp.min <= key.max  (overlapping ranges)
5246
5250
    if (eq_tree(tmp->next_key_part,key2->next_key_part))
5247
5251
    {
5248
5252
      if (tmp->is_same(key2))
5834
5838
 
5835
5839
void SEL_ARG::test_use_count(SEL_ARG *root)
5836
5840
{
5837
 
  uint32_t e_count=0;
 
5841
  uint e_count=0;
5838
5842
  if (this == root && use_count != 1)
5839
5843
  {
5840
5844
    sql_print_information("Use_count: Wrong count %lu for root",use_count);
5876
5880
    Pointers in min and max keys. They point to right-after-end of key
5877
5881
    images. The 0-th entry has these pointing to key tuple start.
5878
5882
  */
5879
 
  unsigned char *min_key, *max_key;
 
5883
  uchar *min_key, *max_key;
5880
5884
  
5881
5885
  /* 
5882
5886
    Flags, for {keypart0, keypart1, ... this_keypart} subtuple.
5883
5887
    min_key_flag may have NULL_RANGE set.
5884
5888
  */
5885
 
  uint32_t min_key_flag, max_key_flag;
 
5889
  uint min_key_flag, max_key_flag;
5886
5890
  
5887
5891
  /* Number of key parts */
5888
 
  uint32_t min_key_parts, max_key_parts;
 
5892
  uint min_key_parts, max_key_parts;
5889
5893
  SEL_ARG *key_tree;
5890
5894
} RANGE_SEQ_ENTRY;
5891
5895
 
5895
5899
*/
5896
5900
typedef struct st_sel_arg_range_seq
5897
5901
{
5898
 
  uint32_t keyno;      /* index of used tree in SEL_TREE structure */
5899
 
  uint32_t real_keyno; /* Number of the index in tables */
 
5902
  uint keyno;      /* index of used tree in SEL_TREE structure */
 
5903
  uint real_keyno; /* Number of the index in tables */
5900
5904
  PARAM *param;
5901
5905
  SEL_ARG *start; /* Root node of the traversed SEL_ARG* graph */
5902
5906
  
5921
5925
*/
5922
5926
 
5923
5927
range_seq_t sel_arg_range_seq_init(void *init_param,
5924
 
                                   uint32_t n_ranges __attribute__((unused)),
5925
 
                                   uint32_t flags __attribute__((unused)))
 
5928
                                   uint n_ranges __attribute__((__unused__)),
 
5929
                                   uint flags __attribute__((__unused__)))
5926
5930
{
5927
5931
  SEL_ARG_RANGE_SEQ *seq= (SEL_ARG_RANGE_SEQ*)init_param;
5928
5932
  seq->at_start= true;
5950
5954
  cur->min_key_parts= prev->min_key_parts;
5951
5955
  cur->max_key_parts= prev->max_key_parts;
5952
5956
 
5953
 
  uint16_t stor_length= arg->param->key[arg->keyno][key_tree->part].store_length;
 
5957
  uint16 stor_length= arg->param->key[arg->keyno][key_tree->part].store_length;
5954
5958
  cur->min_key_parts += key_tree->store_min(stor_length, &cur->min_key,
5955
5959
                                            prev->min_key_flag);
5956
5960
  cur->max_key_parts += key_tree->store_max(stor_length, &cur->max_key,
5989
5993
*/
5990
5994
 
5991
5995
//psergey-merge-todo: support check_quick_keys:max_keypart
5992
 
uint32_t sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
 
5996
uint sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
5993
5997
{
5994
5998
  SEL_ARG *key_tree;
5995
5999
  SEL_ARG_RANGE_SEQ *seq= (SEL_ARG_RANGE_SEQ*)rseq;
6045
6049
  {
6046
6050
    {
6047
6051
      RANGE_SEQ_ENTRY *cur= &seq->stack[seq->i];
6048
 
      uint32_t min_key_length= cur->min_key - seq->param->min_key;
6049
 
      uint32_t max_key_length= cur->max_key - seq->param->max_key;
6050
 
      uint32_t len= cur->min_key - cur[-1].min_key;
 
6052
      uint min_key_length= cur->min_key - seq->param->min_key;
 
6053
      uint max_key_length= cur->max_key - seq->param->max_key;
 
6054
      uint len= cur->min_key - cur[-1].min_key;
6051
6055
      if (!(min_key_length == max_key_length &&
6052
6056
            !memcmp(cur[-1].min_key, cur[-1].max_key, len) &&
6053
6057
            !key_tree->min_flag && !key_tree->max_flag))
6128
6132
    }
6129
6133
  }
6130
6134
  seq->param->range_count++;
6131
 
  seq->param->max_key_part=cmax(seq->param->max_key_part,(uint)key_tree->part);
 
6135
  seq->param->max_key_part=max(seq->param->max_key_part,key_tree->part);
6132
6136
  return 0;
6133
6137
}
6134
6138
 
6161
6165
*/
6162
6166
 
6163
6167
static
6164
 
ha_rows check_quick_select(PARAM *param, uint32_t idx, bool index_only,
 
6168
ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
6165
6169
                           SEL_ARG *tree, bool update_tbl_stats, 
6166
 
                           uint32_t *mrr_flags, uint32_t *bufsize, COST_VECT *cost)
 
6170
                           uint *mrr_flags, uint *bufsize, COST_VECT *cost)
6167
6171
{
6168
6172
  SEL_ARG_RANGE_SEQ seq;
6169
6173
  RANGE_SEQ_IF seq_if = {sel_arg_range_seq_init, sel_arg_range_seq_next};
6170
6174
  handler *file= param->table->file;
6171
6175
  ha_rows rows;
6172
 
  uint32_t keynr= param->real_keynr[idx];
 
6176
  uint keynr= param->real_keynr[idx];
6173
6177
  
6174
6178
  /* Handle cases when we don't have a valid non-empty list of range */
6175
6179
  if (!tree)
6215
6219
      param->table->quick_key_parts[keynr]=param->max_key_part+1;
6216
6220
      param->table->quick_n_ranges[keynr]= param->range_count;
6217
6221
      param->table->quick_condition_rows=
6218
 
        cmin(param->table->quick_condition_rows, rows);
 
6222
        min(param->table->quick_condition_rows, rows);
6219
6223
    }
6220
6224
  }
6221
6225
  /* Figure out if the key scan is ROR (returns rows in ROWID order) or not */
6277
6281
    false  Otherwise
6278
6282
*/
6279
6283
 
6280
 
static bool is_key_scan_ror(PARAM *param, uint32_t keynr, uint8_t nparts)
 
6284
static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts)
6281
6285
{
6282
6286
  KEY *table_key= param->table->key_info + keynr;
6283
6287
  KEY_PART_INFO *key_part= table_key->key_part + nparts;
6284
6288
  KEY_PART_INFO *key_part_end= (table_key->key_part +
6285
6289
                                table_key->key_parts);
6286
 
  uint32_t pk_number;
 
6290
  uint pk_number;
6287
6291
  
6288
6292
  for (KEY_PART_INFO *kp= table_key->key_part; kp < key_part; kp++)
6289
6293
  {
6290
 
    uint16_t fieldnr= param->table->key_info[keynr].
 
6294
    uint16 fieldnr= param->table->key_info[keynr].
6291
6295
                    key_part[kp - table_key->key_part].fieldnr - 1;
6292
6296
    if (param->table->field[fieldnr]->key_length() != kp->length)
6293
6297
      return false;
6339
6343
*/
6340
6344
 
6341
6345
QUICK_RANGE_SELECT *
6342
 
get_quick_select(PARAM *param,uint32_t idx,SEL_ARG *key_tree, uint32_t mrr_flags,
6343
 
                 uint32_t mrr_buf_size, MEM_ROOT *parent_alloc)
 
6346
get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree, uint mrr_flags,
 
6347
                 uint mrr_buf_size, MEM_ROOT *parent_alloc)
6344
6348
{
6345
6349
  QUICK_RANGE_SELECT *quick;
6346
6350
  bool create_err= false;
6378
6382
*/
6379
6383
bool
6380
6384
get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
6381
 
               SEL_ARG *key_tree, unsigned char *min_key,uint32_t min_key_flag,
6382
 
               unsigned char *max_key, uint32_t max_key_flag)
 
6385
               SEL_ARG *key_tree, uchar *min_key,uint min_key_flag,
 
6386
               uchar *max_key, uint max_key_flag)
6383
6387
{
6384
6388
  QUICK_RANGE *range;
6385
 
  uint32_t flag;
 
6389
  uint flag;
6386
6390
  int min_part= key_tree->part-1, // # of keypart values in min_key buffer
6387
6391
      max_part= key_tree->part-1; // # of keypart values in max_key buffer
6388
6392
 
6392
6396
                       min_key,min_key_flag, max_key, max_key_flag))
6393
6397
      return 1;
6394
6398
  }
6395
 
  unsigned char *tmp_min_key=min_key,*tmp_max_key=max_key;
 
6399
  uchar *tmp_min_key=min_key,*tmp_max_key=max_key;
6396
6400
  min_part+= key_tree->store_min(key[key_tree->part].store_length,
6397
6401
                                 &tmp_min_key,min_key_flag);
6398
6402
  max_part+= key_tree->store_max(key[key_tree->part].store_length,
6413
6417
      goto end;                                 // Ugly, but efficient
6414
6418
    }
6415
6419
    {
6416
 
      uint32_t tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag;
 
6420
      uint tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag;
6417
6421
      if (!tmp_min_flag)
6418
6422
        min_part+= key_tree->next_key_part->store_min_key(key, &tmp_min_key,
6419
6423
                                                          &tmp_min_flag);
6444
6448
  }
6445
6449
  if (flag == 0)
6446
6450
  {
6447
 
    uint32_t length= (uint) (tmp_min_key - param->min_key);
 
6451
    uint length= (uint) (tmp_min_key - param->min_key);
6448
6452
    if (length == (uint) (tmp_max_key - param->max_key) &&
6449
6453
        !memcmp(param->min_key,param->max_key,length))
6450
6454
    {
6477
6481
  set_if_bigger(quick->max_used_key_length, range->min_length);
6478
6482
  set_if_bigger(quick->max_used_key_length, range->max_length);
6479
6483
  set_if_bigger(quick->used_key_parts, (uint) key_tree->part+1);
6480
 
  if (insert_dynamic(&quick->ranges, (unsigned char*) &range))
 
6484
  if (insert_dynamic(&quick->ranges, (uchar*) &range))
6481
6485
    return 1;
6482
6486
 
6483
6487
 end:
6523
6527
    false  Otherwise
6524
6528
*/
6525
6529
 
6526
 
static bool null_part_in_key(KEY_PART *key_part, const unsigned char *key, uint32_t length)
 
6530
static bool null_part_in_key(KEY_PART *key_part, const uchar *key, uint length)
6527
6531
{
6528
 
  for (const unsigned char *end=key+length ;
 
6532
  for (const uchar *end=key+length ;
6529
6533
       key < end;
6530
6534
       key+= key_part++->store_length)
6531
6535
  {
6597
6601
    NULL on error.
6598
6602
*/
6599
6603
 
6600
 
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, Table *table,
 
6604
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
6601
6605
                                             TABLE_REF *ref, ha_rows records)
6602
6606
{
6603
6607
  MEM_ROOT *old_root, *alloc;
6605
6609
  KEY *key_info = &table->key_info[ref->key];
6606
6610
  KEY_PART *key_part;
6607
6611
  QUICK_RANGE *range;
6608
 
  uint32_t part;
 
6612
  uint part;
6609
6613
  bool create_err= false;
6610
6614
  COST_VECT cost;
6611
6615
 
6626
6630
    goto err;
6627
6631
  quick->records= records;
6628
6632
 
6629
 
  if ((cp_buffer_from_ref(thd, ref) && thd->is_fatal_error) ||
 
6633
  if ((cp_buffer_from_ref(thd, table, ref) && thd->is_fatal_error) ||
6630
6634
      !(range= new(alloc) QUICK_RANGE()))
6631
6635
    goto err;                                   // out of memory
6632
6636
 
6648
6652
    key_part->length=       key_info->key_part[part].length;
6649
6653
    key_part->store_length= key_info->key_part[part].store_length;
6650
6654
    key_part->null_bit=     key_info->key_part[part].null_bit;
6651
 
    key_part->flag=         (uint8_t) key_info->key_part[part].key_part_flag;
 
6655
    key_part->flag=         (uint8) key_info->key_part[part].key_part_flag;
6652
6656
  }
6653
 
  if (insert_dynamic(&quick->ranges,(unsigned char*)&range))
 
6657
  if (insert_dynamic(&quick->ranges,(uchar*)&range))
6654
6658
    goto err;
6655
6659
 
6656
6660
  /*
6671
6675
                      make_prev_keypart_map(ref->key_parts), EQ_RANGE)))
6672
6676
      goto err;
6673
6677
    *ref->null_ref_key= 0;              // Clear null byte
6674
 
    if (insert_dynamic(&quick->ranges,(unsigned char*)&null_range))
 
6678
    if (insert_dynamic(&quick->ranges,(uchar*)&null_range))
6675
6679
      goto err;
6676
6680
  }
6677
6681
 
6849
6853
  List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects);
6850
6854
  QUICK_RANGE_SELECT* quick;
6851
6855
  int error, cmp;
6852
 
  uint32_t last_rowid_count=0;
 
6856
  uint last_rowid_count=0;
6853
6857
 
6854
6858
  do
6855
6859
  {
6933
6937
{
6934
6938
  int error, dup_row;
6935
6939
  QUICK_SELECT_I *quick;
6936
 
  unsigned char *tmp;
 
6940
  uchar *tmp;
6937
6941
 
6938
6942
  do
6939
6943
  {
6981
6985
 
6982
6986
int QUICK_RANGE_SELECT::reset()
6983
6987
{
6984
 
  uint32_t  buf_size;
6985
 
  unsigned char *mrange_buff;
 
6988
  uint  buf_size;
 
6989
  uchar *mrange_buff;
6986
6990
  int   error;
6987
6991
  HANDLER_BUFFER empty_buf;
6988
6992
  last_range= NULL;
6998
7002
    while (buf_size && !my_multi_malloc(MYF(MY_WME),
6999
7003
                                        &mrr_buf_desc, sizeof(*mrr_buf_desc),
7000
7004
                                        &mrange_buff, buf_size,
7001
 
                                        NULL))
 
7005
                                        NullS))
7002
7006
    {
7003
7007
      /* Try to shrink the buffers until both are 0. */
7004
7008
      buf_size/= 2;
7039
7043
*/
7040
7044
 
7041
7045
range_seq_t quick_range_seq_init(void *init_param,
7042
 
                                 uint32_t n_ranges __attribute__((unused)),
7043
 
                                 uint32_t flags __attribute__((unused)))
 
7046
                                 uint n_ranges __attribute__((__unused__)),
 
7047
                                 uint flags __attribute__((__unused__)))
7044
7048
{
7045
7049
  QUICK_RANGE_SELECT *quick= (QUICK_RANGE_SELECT*)init_param;
7046
7050
  quick->qr_traversal_ctx.first=  (QUICK_RANGE**)quick->ranges.buffer;
7064
7068
    1  No more ranges in the sequence
7065
7069
*/
7066
7070
 
7067
 
uint32_t quick_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
 
7071
uint quick_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
7068
7072
{
7069
7073
  QUICK_RANGE_SEQ_CTX *ctx= (QUICK_RANGE_SEQ_CTX*)rseq;
7070
7074
 
7116
7120
    Reference to range_flag associated with range number #idx
7117
7121
*/
7118
7122
 
7119
 
uint16_t &mrr_persistent_flag_storage(range_seq_t seq, uint32_t idx)
 
7123
uint16 &mrr_persistent_flag_storage(range_seq_t seq, uint idx)
7120
7124
{
7121
7125
  QUICK_RANGE_SEQ_CTX *ctx= (QUICK_RANGE_SEQ_CTX*)seq;
7122
7126
  return ctx->first[idx]->flag;
7148
7152
    Reference to range-associated data
7149
7153
*/
7150
7154
 
7151
 
char* &mrr_get_ptr_by_idx(range_seq_t seq __attribute__((unused)),
7152
 
                          uint32_t idx __attribute__((unused)))
 
7155
char* &mrr_get_ptr_by_idx(range_seq_t seq __attribute__((__unused__)),
 
7156
                          uint idx __attribute__((__unused__)))
7153
7157
{
7154
7158
  static char *dummy;
7155
7159
  return dummy;
7222
7226
    other              if some error occurred
7223
7227
*/
7224
7228
 
7225
 
int QUICK_RANGE_SELECT::get_next_prefix(uint32_t prefix_length,
 
7229
int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length,
7226
7230
                                        key_part_map keypart_map,
7227
 
                                        unsigned char *cur_prefix)
 
7231
                                        uchar *cur_prefix)
7228
7232
{
7229
7233
  for (;;)
7230
7234
  {
7240
7244
        return(result);
7241
7245
    }
7242
7246
 
7243
 
    uint32_t count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer);
 
7247
    uint count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer);
7244
7248
    if (count == 0)
7245
7249
    {
7246
7250
      /* Ranges have already been used up before. None is left for read. */
7249
7253
    }
7250
7254
    last_range= *(cur_range++);
7251
7255
 
7252
 
    start_key.key=    (const unsigned char*) last_range->min_key;
7253
 
    start_key.length= cmin(last_range->min_length, (uint16_t)prefix_length);
 
7256
    start_key.key=    (const uchar*) last_range->min_key;
 
7257
    start_key.length= min(last_range->min_length, prefix_length);
7254
7258
    start_key.keypart_map= last_range->min_keypart_map & keypart_map;
7255
7259
    start_key.flag=   ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
7256
7260
                       (last_range->flag & EQ_RANGE) ?
7257
7261
                       HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
7258
 
    end_key.key=      (const unsigned char*) last_range->max_key;
7259
 
    end_key.length=   cmin(last_range->max_length, (uint16_t)prefix_length);
 
7262
    end_key.key=      (const uchar*) last_range->max_key;
 
7263
    end_key.length=   min(last_range->max_length, prefix_length);
7260
7264
    end_key.keypart_map= last_range->max_keypart_map & keypart_map;
7261
7265
    /*
7262
7266
      We use READ_AFTER_KEY here because if we are reading on a key
7300
7304
bool QUICK_RANGE_SELECT::row_in_ranges()
7301
7305
{
7302
7306
  QUICK_RANGE *res;
7303
 
  uint32_t min= 0;
7304
 
  uint32_t max= ranges.elements - 1;
7305
 
  uint32_t mid= (max + min)/2;
 
7307
  uint min= 0;
 
7308
  uint max= ranges.elements - 1;
 
7309
  uint mid= (max + min)/2;
7306
7310
 
7307
7311
  while (min != max)
7308
7312
  {
7330
7334
 */
7331
7335
 
7332
7336
QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q,
7333
 
                                     uint32_t used_key_parts_arg __attribute__((unused)),
7334
 
                                     bool *create_err __attribute__((unused)))
 
7337
                                     uint used_key_parts_arg __attribute__((__unused__)),
 
7338
                                     bool *create_err __attribute__((__unused__)))
7335
7339
 :QUICK_RANGE_SELECT(*q), rev_it(rev_ranges)
7336
7340
{
7337
7341
  QUICK_RANGE *r;
7445
7449
    return 0;                                   /* key can't be to large */
7446
7450
 
7447
7451
  KEY_PART *key_part=key_parts;
7448
 
  uint32_t store_length;
 
7452
  uint store_length;
7449
7453
 
7450
 
  for (unsigned char *key=range_arg->max_key, *end=key+range_arg->max_length;
 
7454
  for (uchar *key=range_arg->max_key, *end=key+range_arg->max_length;
7451
7455
       key < end;
7452
7456
       key+= store_length, key_part++)
7453
7457
  {
7580
7584
                                              String *used_lengths)
7581
7585
{
7582
7586
  char buf[64];
7583
 
  uint32_t length;
 
7587
  uint length;
7584
7588
  KEY *key_info= head->key_info + index;
7585
7589
  key_names->append(key_info->name);
7586
7590
  length= int64_t2str(max_used_key_length, buf, 10) - buf;
7591
7595
                                                    String *used_lengths)
7592
7596
{
7593
7597
  char buf[64];
7594
 
  uint32_t length;
 
7598
  uint length;
7595
7599
  bool first= true;
7596
7600
  QUICK_RANGE_SELECT *quick;
7597
7601
 
7626
7630
                                                      String *used_lengths)
7627
7631
{
7628
7632
  char buf[64];
7629
 
  uint32_t length;
 
7633
  uint length;
7630
7634
  bool first= true;
7631
7635
  QUICK_RANGE_SELECT *quick;
7632
7636
  List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
7680
7684
* Implementation of QUICK_GROUP_MIN_MAX_SELECT
7681
7685
*******************************************************************************/
7682
7686
 
7683
 
static inline uint32_t get_field_keypart(KEY *index, Field *field);
7684
 
static inline SEL_ARG * get_index_range_tree(uint32_t index, SEL_TREE* range_tree,
7685
 
                                             PARAM *param, uint32_t *param_idx);
 
7687
static inline uint get_field_keypart(KEY *index, Field *field);
 
7688
static inline SEL_ARG * get_index_range_tree(uint index, SEL_TREE* range_tree,
 
7689
                                             PARAM *param, uint *param_idx);
7686
7690
static bool get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
7687
7691
                       KEY_PART_INFO *first_non_group_part,
7688
7692
                       KEY_PART_INFO *min_max_arg_part,
7689
7693
                       KEY_PART_INFO *last_part, THD *thd,
7690
 
                       unsigned char *key_infix, uint32_t *key_infix_len,
 
7694
                       uchar *key_infix, uint *key_infix_len,
7691
7695
                       KEY_PART_INFO **first_non_infix_part);
7692
7696
static bool
7693
7697
check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item,
7694
7698
                               Field::imagetype image_type);
7695
7699
 
7696
7700
static void
7697
 
cost_group_min_max(Table* table, KEY *index_info, uint32_t used_key_parts,
7698
 
                   uint32_t group_key_parts, SEL_TREE *range_tree,
 
7701
cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
 
7702
                   uint group_key_parts, SEL_TREE *range_tree,
7699
7703
                   SEL_ARG *index_tree, ha_rows quick_prefix_records,
7700
7704
                   bool have_min, bool have_max,
7701
7705
                   double *read_cost, ha_rows *records);
7834
7838
{
7835
7839
  THD *thd= param->thd;
7836
7840
  JOIN *join= thd->lex->current_select->join;
7837
 
  Table *table= param->table;
 
7841
  TABLE *table= param->table;
7838
7842
  bool have_min= false;              /* true if there is a MIN function. */
7839
7843
  bool have_max= false;              /* true if there is a MAX function. */
7840
7844
  Item_field *min_max_arg_item= NULL; // The argument of all MIN/MAX functions
7841
7845
  KEY_PART_INFO *min_max_arg_part= NULL; /* The corresponding keypart. */
7842
 
  uint32_t group_prefix_len= 0; /* Length (in bytes) of the key prefix. */
 
7846
  uint group_prefix_len= 0; /* Length (in bytes) of the key prefix. */
7843
7847
  KEY *index_info= NULL;    /* The index chosen for data access. */
7844
 
  uint32_t index= 0;            /* The id of the chosen index. */
7845
 
  uint32_t group_key_parts= 0;  // Number of index key parts in the group prefix.
7846
 
  uint32_t used_key_parts= 0;   /* Number of index key parts used for access. */
7847
 
  unsigned char key_infix[MAX_KEY_LENGTH]; /* Constants from equality predicates.*/
7848
 
  uint32_t key_infix_len= 0;          /* Length of key_infix. */
 
7848
  uint index= 0;            /* The id of the chosen index. */
 
7849
  uint group_key_parts= 0;  // Number of index key parts in the group prefix.
 
7850
  uint used_key_parts= 0;   /* Number of index key parts used for access. */
 
7851
  uchar key_infix[MAX_KEY_LENGTH]; /* Constants from equality predicates.*/
 
7852
  uint key_infix_len= 0;          /* Length of key_infix. */
7849
7853
  TRP_GROUP_MIN_MAX *read_plan= NULL; /* The eventually constructed TRP. */
7850
 
  uint32_t key_part_nr;
7851
 
  order_st *tmp_group;
 
7854
  uint key_part_nr;
 
7855
  ORDER *tmp_group;
7852
7856
  Item *item;
7853
7857
  Item_field *item_field;
7854
7858
 
7926
7930
  KEY_PART_INFO *last_part= NULL;
7927
7931
  KEY_PART_INFO *first_non_group_part= NULL;
7928
7932
  KEY_PART_INFO *first_non_infix_part= NULL;
7929
 
  uint32_t key_infix_parts= 0;
7930
 
  uint32_t cur_group_key_parts= 0;
7931
 
  uint32_t cur_group_prefix_len= 0;
 
7933
  uint key_infix_parts= 0;
 
7934
  uint cur_group_key_parts= 0;
 
7935
  uint cur_group_prefix_len= 0;
7932
7936
  /* Cost-related variables for the best index so far. */
7933
7937
  double best_read_cost= DBL_MAX;
7934
7938
  ha_rows best_records= 0;
7935
7939
  SEL_ARG *best_index_tree= NULL;
7936
7940
  ha_rows best_quick_prefix_records= 0;
7937
 
  uint32_t best_param_idx= 0;
 
7941
  uint best_param_idx= 0;
7938
7942
  double cur_read_cost= DBL_MAX;
7939
7943
  ha_rows cur_records;
7940
7944
  SEL_ARG *cur_index_tree= NULL;
7941
7945
  ha_rows cur_quick_prefix_records= 0;
7942
 
  uint32_t cur_param_idx=MAX_KEY;
 
7946
  uint cur_param_idx=MAX_KEY;
7943
7947
  key_map cur_used_key_parts;
7944
 
  uint32_t pk= param->table->s->primary_key;
 
7948
  uint pk= param->table->s->primary_key;
7945
7949
 
7946
 
  for (uint32_t cur_index= 0 ; cur_index_info != cur_index_info_end ;
 
7950
  for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ;
7947
7951
       cur_index_info++, cur_index++)
7948
7952
  {
7949
7953
    /* Check (B1) - if current index is covering. */
7963
7967
        (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
7964
7968
    {
7965
7969
      /* For each table field */
7966
 
      for (uint32_t i= 0; i < table->s->fields; i++)
 
7970
      for (uint i= 0; i < table->s->fields; i++)
7967
7971
      {
7968
7972
        Field *cur_field= table->field[i];
7969
7973
        /*
8006
8010
    }
8007
8011
    /*
8008
8012
      Check (GA2) if this is a DISTINCT query.
8009
 
      If GA2, then Store a new order_st object in group_fields_array at the
8010
 
      position of the key part of item_field->field. Thus we get the order_st
 
8013
      If GA2, then Store a new ORDER object in group_fields_array at the
 
8014
      position of the key part of item_field->field. Thus we get the ORDER
8011
8015
      objects for each field ordered as the corresponding key parts.
8012
 
      Later group_fields_array of order_st objects is used to convert the query
 
8016
      Later group_fields_array of ORDER objects is used to convert the query
8013
8017
      to a GROUP query.
8014
8018
    */
8015
8019
    else if (join->select_distinct)
8016
8020
    {
8017
8021
      select_items_it.rewind();
8018
8022
      cur_used_key_parts.clear_all();
8019
 
      uint32_t max_key_part= 0;
 
8023
      uint max_key_part= 0;
8020
8024
      while ((item= select_items_it++))
8021
8025
      {
8022
8026
        item_field= (Item_field*) item; /* (SA5) already checked above. */
8034
8038
        cur_group_prefix_len+= cur_part->store_length;
8035
8039
        cur_used_key_parts.set_bit(key_part_nr);
8036
8040
        ++cur_group_key_parts;
8037
 
        max_key_part= cmax(max_key_part,key_part_nr);
 
8041
        max_key_part= max(max_key_part,key_part_nr);
8038
8042
      }
8039
8043
      /*
8040
8044
        Check that used key parts forms a prefix of the index.
8089
8093
    {
8090
8094
      if (tree)
8091
8095
      {
8092
 
        uint32_t dummy;
 
8096
        uint dummy;
8093
8097
        SEL_ARG *index_range_tree= get_index_range_tree(cur_index, tree, param,
8094
8098
                                                        &dummy);
8095
8099
        if (!get_constant_key_infix(cur_index_info, index_range_tree,
8127
8131
 
8128
8132
        /* Check if cur_part is referenced in the WHERE clause. */
8129
8133
        if (join->conds->walk(&Item::find_item_in_field_list_processor, 0,
8130
 
                              (unsigned char*) key_part_range))
 
8134
                              (uchar*) key_part_range))
8131
8135
          goto next_index;
8132
8136
      }
8133
8137
    }
8160
8164
                                           &cur_param_idx);
8161
8165
      /* Check if this range tree can be used for prefix retrieval. */
8162
8166
      COST_VECT dummy_cost;
8163
 
      uint32_t mrr_flags= HA_MRR_USE_DEFAULT_IMPL;
8164
 
      uint32_t mrr_bufsize=0;
 
8167
      uint mrr_flags= HA_MRR_USE_DEFAULT_IMPL;
 
8168
      uint mrr_bufsize=0;
8165
8169
      cur_quick_prefix_records= check_quick_select(param, cur_param_idx, 
8166
8170
                                                   false /*don't care*/, 
8167
8171
                                                   cur_index_tree, true,
8200
8204
 
8201
8205
  /* Check (SA3) for the where clause. */
8202
8206
  if (join->conds && min_max_arg_item &&
8203
 
      !check_group_min_max_predicates(join->conds, min_max_arg_item, Field::itRAW))
 
8207
      !check_group_min_max_predicates(join->conds, min_max_arg_item,
 
8208
                                      (index_info->flags & HA_SPATIAL) ?
 
8209
                                      Field::itMBR : Field::itRAW))
8204
8210
    return(NULL);
8205
8211
 
8206
8212
  /* The query passes all tests, so construct a new TRP object. */
8287
8293
  Item_func *pred= (Item_func*) cond;
8288
8294
  Item **arguments= pred->arguments();
8289
8295
  Item *cur_arg;
8290
 
  for (uint32_t arg_idx= 0; arg_idx < pred->argument_count (); arg_idx++)
 
8296
  for (uint arg_idx= 0; arg_idx < pred->argument_count (); arg_idx++)
8291
8297
  {
8292
8298
    cur_arg= arguments[arg_idx]->real_item();
8293
8299
    if (cur_arg->type() == Item::FIELD_ITEM)
8313
8319
 
8314
8320
        /* Check that pred compares min_max_arg_item with a constant. */
8315
8321
        Item *args[3];
8316
 
        memset(args, 0, 3 * sizeof(Item*));
 
8322
        bzero(args, 3 * sizeof(Item*));
8317
8323
        bool inv;
8318
8324
        /* Test if this is a comparison of a field and a constant. */
8319
8325
        if (!simple_pred(pred, args, &inv))
8389
8395
*/
8390
8396
 
8391
8397
static bool
8392
 
get_constant_key_infix(KEY *index_info __attribute__((unused)),
 
8398
get_constant_key_infix(KEY *index_info __attribute__((__unused__)),
8393
8399
                       SEL_ARG *index_range_tree,
8394
8400
                       KEY_PART_INFO *first_non_group_part,
8395
8401
                       KEY_PART_INFO *min_max_arg_part,
8396
8402
                       KEY_PART_INFO *last_part,
8397
 
                       THD *thd __attribute__((unused)),
8398
 
                       unsigned char *key_infix, uint32_t *key_infix_len,
 
8403
                       THD *thd __attribute__((__unused__)),
 
8404
                       uchar *key_infix, uint *key_infix_len,
8399
8405
                       KEY_PART_INFO **first_non_infix_part)
8400
8406
{
8401
8407
  SEL_ARG       *cur_range;
8404
8410
  KEY_PART_INFO *end_part= min_max_arg_part ? min_max_arg_part : last_part;
8405
8411
 
8406
8412
  *key_infix_len= 0;
8407
 
  unsigned char *key_ptr= key_infix;
 
8413
  uchar *key_ptr= key_infix;
8408
8414
  for (cur_part= first_non_group_part; cur_part != end_part; cur_part++)
8409
8415
  {
8410
8416
    /*
8436
8442
        (cur_range->min_flag & NEAR_MIN) || (cur_range->max_flag & NEAR_MAX))
8437
8443
      return false;
8438
8444
 
8439
 
    uint32_t field_length= cur_part->store_length;
 
8445
    uint field_length= cur_part->store_length;
8440
8446
    if ((cur_range->maybe_null &&
8441
8447
         cur_range->min_value[0] && cur_range->max_value[0]) ||
8442
8448
        !memcmp(cur_range->min_value, cur_range->max_value, field_length))
8511
8517
    Pointer to the SEL_ARG subtree that corresponds to index.
8512
8518
*/
8513
8519
 
8514
 
SEL_ARG * get_index_range_tree(uint32_t index, SEL_TREE* range_tree, PARAM *param,
8515
 
                               uint32_t *param_idx)
 
8520
SEL_ARG * get_index_range_tree(uint index, SEL_TREE* range_tree, PARAM *param,
 
8521
                               uint *param_idx)
8516
8522
{
8517
 
  uint32_t idx= 0; /* Index nr in param->key_parts */
 
8523
  uint idx= 0; /* Index nr in param->key_parts */
8518
8524
  while (idx < param->keys)
8519
8525
  {
8520
8526
    if (index == param->real_keynr[idx])
8586
8592
    None
8587
8593
*/
8588
8594
 
8589
 
void cost_group_min_max(Table* table, KEY *index_info, uint32_t used_key_parts,
8590
 
                        uint32_t group_key_parts, SEL_TREE *range_tree,
8591
 
                        SEL_ARG *index_tree __attribute__((unused)),
 
8595
void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
 
8596
                        uint group_key_parts, SEL_TREE *range_tree,
 
8597
                        SEL_ARG *index_tree __attribute__((__unused__)),
8592
8598
                        ha_rows quick_prefix_records,
8593
8599
                        bool have_min, bool have_max,
8594
8600
                        double *read_cost, ha_rows *records)
8595
8601
{
8596
8602
  ha_rows table_records;
8597
 
  uint32_t num_groups;
8598
 
  uint32_t num_blocks;
8599
 
  uint32_t keys_per_block;
8600
 
  uint32_t keys_per_group;
8601
 
  uint32_t keys_per_subgroup; /* Average number of keys in sub-groups */
 
8603
  uint num_groups;
 
8604
  uint num_blocks;
 
8605
  uint keys_per_block;
 
8606
  uint keys_per_group;
 
8607
  uint keys_per_subgroup; /* Average number of keys in sub-groups */
8602
8608
                          /* formed by a key infix. */
8603
8609
  double p_overlap; /* Probability that a sub-group overlaps two blocks. */
8604
8610
  double quick_prefix_selectivity;
8639
8645
    {
8640
8646
      double blocks_per_group= (double) num_blocks / (double) num_groups;
8641
8647
      p_overlap= (blocks_per_group * (keys_per_subgroup - 1)) / keys_per_group;
8642
 
      p_overlap= cmin(p_overlap, 1.0);
 
8648
      p_overlap= min(p_overlap, 1.0);
8643
8649
    }
8644
 
    io_cost= (double) cmin(num_groups * (1 + p_overlap), (double)num_blocks);
 
8650
    io_cost= (double) min(num_groups * (1 + p_overlap), num_blocks);
8645
8651
  }
8646
8652
  else
8647
8653
    io_cost= (keys_per_group > keys_per_block) ?
8685
8691
 
8686
8692
QUICK_SELECT_I *
8687
8693
TRP_GROUP_MIN_MAX::make_quick(PARAM *param,
8688
 
                              bool retrieve_full_rows __attribute__((unused)),
 
8694
                              bool retrieve_full_rows __attribute__((__unused__)),
8689
8695
                              MEM_ROOT *parent_alloc)
8690
8696
{
8691
8697
  QUICK_GROUP_MIN_MAX_SELECT *quick;
8783
8789
*/
8784
8790
 
8785
8791
QUICK_GROUP_MIN_MAX_SELECT::
8786
 
QUICK_GROUP_MIN_MAX_SELECT(Table *table, JOIN *join_arg, bool have_min_arg,
 
8792
QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
8787
8793
                           bool have_max_arg,
8788
8794
                           KEY_PART_INFO *min_max_arg_part_arg,
8789
 
                           uint32_t group_prefix_len_arg, uint32_t group_key_parts_arg,
8790
 
                           uint32_t used_key_parts_arg, KEY *index_info_arg,
8791
 
                           uint32_t use_index, double read_cost_arg,
8792
 
                           ha_rows records_arg, uint32_t key_infix_len_arg,
8793
 
                           unsigned char *key_infix_arg, MEM_ROOT *parent_alloc)
 
8795
                           uint group_prefix_len_arg, uint group_key_parts_arg,
 
8796
                           uint used_key_parts_arg, KEY *index_info_arg,
 
8797
                           uint use_index, double read_cost_arg,
 
8798
                           ha_rows records_arg, uint key_infix_len_arg,
 
8799
                           uchar *key_infix_arg, MEM_ROOT *parent_alloc)
8794
8800
  :join(join_arg), index_info(index_info_arg),
8795
8801
   group_prefix_len(group_prefix_len_arg),
8796
8802
   group_key_parts(group_key_parts_arg), have_min(have_min_arg),
8823
8829
    join->thd->mem_root= &alloc;
8824
8830
  }
8825
8831
  else
8826
 
    memset(&alloc, 0, sizeof(MEM_ROOT));  // ensure that it's not used
 
8832
    bzero(&alloc, sizeof(MEM_ROOT));            // ensure that it's not used
8827
8833
}
8828
8834
 
8829
8835
 
8849
8855
  if (group_prefix) /* Already initialized. */
8850
8856
    return 0;
8851
8857
 
8852
 
  if (!(last_prefix= (unsigned char*) alloc_root(&alloc, group_prefix_len)))
 
8858
  if (!(last_prefix= (uchar*) alloc_root(&alloc, group_prefix_len)))
8853
8859
      return 1;
8854
8860
  /*
8855
8861
    We may use group_prefix to store keys with all select fields, so allocate
8856
8862
    enough space for it.
8857
8863
  */
8858
 
  if (!(group_prefix= (unsigned char*) alloc_root(&alloc,
 
8864
  if (!(group_prefix= (uchar*) alloc_root(&alloc,
8859
8865
                                         real_prefix_len + min_max_arg_len)))
8860
8866
    return 1;
8861
8867
 
8865
8871
      The memory location pointed to by key_infix will be deleted soon, so
8866
8872
      allocate a new buffer and copy the key_infix into it.
8867
8873
    */
8868
 
    unsigned char *tmp_key_infix= (unsigned char*) alloc_root(&alloc, key_infix_len);
 
8874
    uchar *tmp_key_infix= (uchar*) alloc_root(&alloc, key_infix_len);
8869
8875
    if (!tmp_key_infix)
8870
8876
      return 1;
8871
8877
    memcpy(tmp_key_infix, this->key_infix, key_infix_len);
8956
8962
bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
8957
8963
{
8958
8964
  QUICK_RANGE *range;
8959
 
  uint32_t range_flag= sel_range->min_flag | sel_range->max_flag;
 
8965
  uint range_flag= sel_range->min_flag | sel_range->max_flag;
8960
8966
 
8961
8967
  /* Skip (-inf,+inf) ranges, e.g. (x < 5 or x > 4). */
8962
8968
  if ((range_flag & NO_MIN_RANGE) && (range_flag & NO_MAX_RANGE))
8979
8985
                         range_flag);
8980
8986
  if (!range)
8981
8987
    return true;
8982
 
  if (insert_dynamic(&min_max_ranges, (unsigned char*)&range))
 
8988
  if (insert_dynamic(&min_max_ranges, (uchar*)&range))
8983
8989
    return true;
8984
8990
  return false;
8985
8991
}
9008
9014
      group_prefix_len < quick_prefix_select->max_used_key_length)
9009
9015
  {
9010
9016
    DYNAMIC_ARRAY *arr;
9011
 
    uint32_t inx;
 
9017
    uint inx;
9012
9018
 
9013
9019
    for (inx= 0, arr= &quick_prefix_select->ranges; inx < arr->elements; inx++)
9014
9020
    {
9015
9021
      QUICK_RANGE *range;
9016
9022
 
9017
 
      get_dynamic(arr, (unsigned char*)&range, inx);
 
9023
      get_dynamic(arr, (uchar*)&range, inx);
9018
9024
      range->flag &= ~(NEAR_MIN | NEAR_MAX);
9019
9025
    }
9020
9026
  }
9050
9056
    QUICK_RANGE *cur_range;
9051
9057
    if (have_min)
9052
9058
    { /* Check if the right-most range has a lower boundary. */
9053
 
      get_dynamic(&min_max_ranges, (unsigned char*)&cur_range,
 
9059
      get_dynamic(&min_max_ranges, (uchar*)&cur_range,
9054
9060
                  min_max_ranges.elements - 1);
9055
9061
      if (!(cur_range->flag & NO_MIN_RANGE))
9056
9062
      {
9061
9067
    }
9062
9068
    if (have_max)
9063
9069
    { /* Check if the left-most range has an upper boundary. */
9064
 
      get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, 0);
 
9070
      get_dynamic(&min_max_ranges, (uchar*)&cur_range, 0);
9065
9071
      if (!(cur_range->flag & NO_MAX_RANGE))
9066
9072
      {
9067
9073
        max_used_key_length+= min_max_arg_len;
9372
9378
 
9373
9379
  if (quick_prefix_select)
9374
9380
  {
9375
 
    unsigned char *cur_prefix= seen_first_key ? group_prefix : NULL;
 
9381
    uchar *cur_prefix= seen_first_key ? group_prefix : NULL;
9376
9382
    if ((result= quick_prefix_select->get_next_prefix(group_prefix_len,
9377
9383
                         make_prev_keypart_map(group_key_parts), cur_prefix)))
9378
9384
      return(result);
9440
9446
 
9441
9447
  assert(min_max_ranges.elements > 0);
9442
9448
 
9443
 
  for (uint32_t range_idx= 0; range_idx < min_max_ranges.elements; range_idx++)
 
9449
  for (uint range_idx= 0; range_idx < min_max_ranges.elements; range_idx++)
9444
9450
  { /* Search from the left-most range to the right. */
9445
 
    get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, range_idx);
 
9451
    get_dynamic(&min_max_ranges, (uchar*)&cur_range, range_idx);
9446
9452
 
9447
9453
    /*
9448
9454
      If the current value for the min/max argument is bigger than the right
9449
9455
      boundary of cur_range, there is no need to check this range.
9450
9456
    */
9451
9457
    if (range_idx != 0 && !(cur_range->flag & NO_MAX_RANGE) &&
9452
 
        (key_cmp(min_max_arg_part, (const unsigned char*) cur_range->max_key,
 
9458
        (key_cmp(min_max_arg_part, (const uchar*) cur_range->max_key,
9453
9459
                 min_max_arg_len) == 1))
9454
9460
      continue;
9455
9461
 
9510
9516
    if ( !(cur_range->flag & NO_MAX_RANGE) )
9511
9517
    {
9512
9518
      /* Compose the MAX key for the range. */
9513
 
      unsigned char *max_key= (unsigned char*) my_alloca(real_prefix_len + min_max_arg_len);
 
9519
      uchar *max_key= (uchar*) my_alloca(real_prefix_len + min_max_arg_len);
9514
9520
      memcpy(max_key, group_prefix, real_prefix_len);
9515
9521
      memcpy(max_key + real_prefix_len, cur_range->max_key,
9516
9522
             cur_range->max_length);
9571
9577
 
9572
9578
  assert(min_max_ranges.elements > 0);
9573
9579
 
9574
 
  for (uint32_t range_idx= min_max_ranges.elements; range_idx > 0; range_idx--)
 
9580
  for (uint range_idx= min_max_ranges.elements; range_idx > 0; range_idx--)
9575
9581
  { /* Search from the right-most range to the left. */
9576
 
    get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, range_idx - 1);
 
9582
    get_dynamic(&min_max_ranges, (uchar*)&cur_range, range_idx - 1);
9577
9583
 
9578
9584
    /*
9579
9585
      If the current value for the min/max argument is smaller than the left
9581
9587
    */
9582
9588
    if (range_idx != min_max_ranges.elements &&
9583
9589
        !(cur_range->flag & NO_MIN_RANGE) &&
9584
 
        (key_cmp(min_max_arg_part, (const unsigned char*) cur_range->min_key,
 
9590
        (key_cmp(min_max_arg_part, (const uchar*) cur_range->min_key,
9585
9591
                 min_max_arg_len) == -1))
9586
9592
      continue;
9587
9593
 
9627
9633
    if ( !(cur_range->flag & NO_MIN_RANGE) )
9628
9634
    {
9629
9635
      /* Compose the MIN key for the range. */
9630
 
      unsigned char *min_key= (unsigned char*) my_alloca(real_prefix_len + min_max_arg_len);
 
9636
      uchar *min_key= (uchar*) my_alloca(real_prefix_len + min_max_arg_len);
9631
9637
      memcpy(min_key, group_prefix, real_prefix_len);
9632
9638
      memcpy(min_key + real_prefix_len, cur_range->min_key,
9633
9639
             cur_range->min_length);
9729
9735
                                                      String *used_lengths)
9730
9736
{
9731
9737
  char buf[64];
9732
 
  uint32_t length;
 
9738
  uint length;
9733
9739
  key_names->append(index_info->name);
9734
9740
  length= int64_t2str(max_used_key_length, buf, 10) - buf;
9735
9741
  used_lengths->append(buf, length);
9736
9742
}
9737
9743
 
9738
9744
static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
9739
 
                           const char *msg __attribute__((unused)))
 
9745
                           const char *msg __attribute__((__unused__)))
9740
9746
{
9741
9747
  SEL_ARG **key,**end;
9742
9748
  int idx;
9750
9756
  {
9751
9757
    if (tree_map->is_set(idx))
9752
9758
    {
9753
 
      uint32_t keynr= param->real_keynr[idx];
 
9759
      uint keynr= param->real_keynr[idx];
9754
9760
      if (tmp.length())
9755
9761
        tmp.append(',');
9756
9762
      tmp.append(param->table->key_info[keynr].name);
9763
9769
}
9764
9770
 
9765
9771
 
9766
 
static void print_ror_scans_arr(Table *table,
9767
 
                                const char *msg __attribute__((unused)),
 
9772
static void print_ror_scans_arr(TABLE *table,
 
9773
                                const char *msg __attribute__((__unused__)),
9768
9774
                                struct st_ror_scan_info **start,
9769
9775
                                struct st_ror_scan_info **end)
9770
9776
{