~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/range.cc

  • Committer: Mark Atwood
  • Date: 2011-08-11 03:05:03 UTC
  • mfrom: (2385.1.12 refactor4)
  • Revision ID: me@mark.atwood.name-20110811030503-rp9xjihc5x3y0x4q
merge lp:~olafvdspek/drizzle/refactor4

Show diffs side-by-side

added added

removed removed

Lines of Context:
100
100
           subject and may omit some details.
101
101
*/
102
102
 
103
 
#include "config.h"
 
103
#include <config.h>
104
104
 
105
105
#include <math.h>
106
106
#include <float.h>
111
111
 
112
112
#include <boost/dynamic_bitset.hpp>
113
113
 
114
 
#include "drizzled/check_stack_overrun.h"
115
 
#include "drizzled/error.h"
116
 
#include "drizzled/field/num.h"
117
 
#include "drizzled/internal/iocache.h"
118
 
#include "drizzled/internal/my_sys.h"
119
 
#include "drizzled/item/cmpfunc.h"
120
 
#include "drizzled/optimizer/cost_vector.h"
121
 
#include "drizzled/optimizer/quick_group_min_max_select.h"
122
 
#include "drizzled/optimizer/quick_index_merge_select.h"
123
 
#include "drizzled/optimizer/quick_range.h"
124
 
#include "drizzled/optimizer/quick_range_select.h"
125
 
#include "drizzled/optimizer/quick_ror_intersect_select.h"
126
 
#include "drizzled/optimizer/quick_ror_union_select.h"
127
 
#include "drizzled/optimizer/range.h"
128
 
#include "drizzled/optimizer/range_param.h"
129
 
#include "drizzled/optimizer/sel_arg.h"
130
 
#include "drizzled/optimizer/sel_imerge.h"
131
 
#include "drizzled/optimizer/sel_tree.h"
132
 
#include "drizzled/optimizer/sum.h"
133
 
#include "drizzled/optimizer/table_read_plan.h"
134
 
#include "drizzled/plugin/storage_engine.h"
135
 
#include "drizzled/records.h"
136
 
#include "drizzled/sql_base.h"
137
 
#include "drizzled/sql_select.h"
138
 
#include "drizzled/table_reference.h"
139
 
 
140
 
#include "drizzled/temporal.h" /* Needed in get_mm_leaf() for timestamp -> datetime comparisons */
 
114
#include <drizzled/check_stack_overrun.h>
 
115
#include <drizzled/error.h>
 
116
#include <drizzled/field/num.h>
 
117
#include <drizzled/internal/iocache.h>
 
118
#include <drizzled/internal/my_sys.h>
 
119
#include <drizzled/item/cmpfunc.h>
 
120
#include <drizzled/optimizer/cost_vector.h>
 
121
#include <drizzled/optimizer/quick_group_min_max_select.h>
 
122
#include <drizzled/optimizer/quick_index_merge_select.h>
 
123
#include <drizzled/optimizer/quick_range.h>
 
124
#include <drizzled/optimizer/quick_range_select.h>
 
125
#include <drizzled/optimizer/quick_ror_intersect_select.h>
 
126
#include <drizzled/optimizer/quick_ror_union_select.h>
 
127
#include <drizzled/optimizer/range.h>
 
128
#include <drizzled/optimizer/range_param.h>
 
129
#include <drizzled/optimizer/sel_arg.h>
 
130
#include <drizzled/optimizer/sel_imerge.h>
 
131
#include <drizzled/optimizer/sel_tree.h>
 
132
#include <drizzled/optimizer/sum.h>
 
133
#include <drizzled/optimizer/table_read_plan.h>
 
134
#include <drizzled/plugin/storage_engine.h>
 
135
#include <drizzled/records.h>
 
136
#include <drizzled/sql_base.h>
 
137
#include <drizzled/sql_select.h>
 
138
#include <drizzled/table_reference.h>
 
139
#include <drizzled/session.h>
 
140
#include <drizzled/key.h>
 
141
#include <drizzled/unique.h>
 
142
#include <drizzled/temporal.h> /* Needed in get_mm_leaf() for timestamp -> datetime comparisons */
 
143
#include <drizzled/sql_lex.h>
 
144
#include <drizzled/system_variables.h>
141
145
 
142
146
using namespace std;
143
 
namespace drizzled
144
 
{
 
147
 
 
148
namespace drizzled {
145
149
 
146
150
#define HA_END_SPACE_KEY 0
147
151
 
215
219
  else
216
220
  {
217
221
    double n_blocks=
218
 
      ceil(uint64_t2double(table->cursor->stats.data_file_length) / IO_SIZE);
 
222
      ceil(static_cast<double>(table->cursor->stats.data_file_length) / IO_SIZE);
219
223
    double busy_blocks=
220
 
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
 
224
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, static_cast<double>(nrows)));
221
225
    if (busy_blocks < 1.0)
222
226
      busy_blocks= 1.0;
223
227
 
287
291
static
288
292
optimizer::GroupMinMaxReadPlan *get_best_group_min_max(optimizer::Parameter *param, optimizer::SEL_TREE *tree);
289
293
 
290
 
static optimizer::SEL_TREE *tree_and(optimizer::RangeParameter *param, 
291
 
                                     optimizer::SEL_TREE *tree1, 
 
294
static optimizer::SEL_TREE *tree_and(optimizer::RangeParameter *param,
 
295
                                     optimizer::SEL_TREE *tree1,
292
296
                                     optimizer::SEL_TREE *tree2);
293
297
 
294
298
static optimizer::SEL_ARG *sel_add(optimizer::SEL_ARG *key1, optimizer::SEL_ARG *key2);
306
310
                             const unsigned char *key,
307
311
                             uint32_t length);
308
312
 
309
 
bool sel_trees_can_be_ored(optimizer::SEL_TREE *tree1, 
310
 
                           optimizer::SEL_TREE *tree2, 
 
313
bool sel_trees_can_be_ored(optimizer::SEL_TREE *tree1,
 
314
                           optimizer::SEL_TREE *tree2,
311
315
                           optimizer::RangeParameter *param);
312
316
 
313
317
 
342
346
                                             bool allow_null_cond,
343
347
                                             int *error)
344
348
{
345
 
  optimizer::SqlSelect *select= NULL;
346
 
 
347
349
  *error= 0;
348
350
 
349
351
  if (! conds && ! allow_null_cond)
350
352
  {
351
353
    return 0;
352
354
  }
353
 
  if (! (select= new optimizer::SqlSelect()))
354
 
  {
355
 
    *error= 1;                  // out of memory
356
 
    return 0;
357
 
  }
 
355
  optimizer::SqlSelect* select= new optimizer::SqlSelect;
358
356
  select->read_tables=read_tables;
359
357
  select->const_tables=const_tables;
360
358
  select->head=head;
362
360
 
363
361
  if (head->sort.io_cache)
364
362
  {
365
 
    memcpy(select->file, head->sort.io_cache, sizeof(internal::IO_CACHE));
 
363
    memcpy(select->file, head->sort.io_cache, sizeof(internal::io_cache_st));
366
364
    select->records=(ha_rows) (select->file->end_of_file/
367
365
                               head->cursor->ref_length);
368
366
    delete head->sort.io_cache;
372
370
}
373
371
 
374
372
 
375
 
optimizer::SqlSelect::SqlSelect() 
 
373
optimizer::SqlSelect::SqlSelect()
376
374
  :
377
375
    quick(NULL),
378
376
    cond(NULL),
379
 
    file(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
 
377
    file(static_cast<internal::io_cache_st *>(memory::sql_calloc(sizeof(internal::io_cache_st)))),
380
378
    free_cond(false)
381
379
{
382
380
  quick_keys.reset();
387
385
 
388
386
void optimizer::SqlSelect::cleanup()
389
387
{
390
 
  if (quick)
391
 
  {
392
 
    delete quick;
393
 
    quick= NULL;
394
 
  }
 
388
 
 
389
  delete quick;
 
390
  quick= NULL;
395
391
 
396
392
  if (free_cond)
397
393
  {
409
405
}
410
406
 
411
407
 
412
 
bool optimizer::SqlSelect::check_quick(Session *session, 
 
408
bool optimizer::SqlSelect::check_quick(Session *session,
413
409
                                       bool force_quick_range,
414
410
                                       ha_rows limit)
415
411
{
416
412
  key_map tmp;
417
413
  tmp.set();
418
 
  return (test_quick_select(session, 
419
 
                           tmp, 
420
 
                           0, 
 
414
  return (test_quick_select(session,
 
415
                           tmp,
 
416
                           0,
421
417
                           limit,
422
 
                           force_quick_range, 
 
418
                           force_quick_range,
423
419
                           false) < 0);
424
420
}
425
421
 
642
638
{
643
639
  uint32_t idx;
644
640
  double scan_time;
645
 
  if (quick)
646
 
  {
647
 
    delete quick;
648
 
    quick= NULL;
649
 
  }
 
641
 
 
642
  delete quick;
 
643
  quick= NULL;
 
644
 
650
645
  needed_reg.reset();
651
646
  quick_keys.reset();
652
647
  if (keys_to_use.none())
691
686
    param.force_default_mrr= ordered_output;
692
687
 
693
688
    session->no_errors=1;                               // Don't warn about NULL
694
 
    memory::init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
695
 
    if (!(param.key_parts= (KEY_PART*) alloc.alloc_root( sizeof(KEY_PART) * head->getShare()->key_parts)) ||
696
 
        fill_used_fields_bitmap(&param))
 
689
    alloc.init(session->variables.range_alloc_block_size);
 
690
    param.key_parts= new (alloc) KEY_PART[head->getShare()->key_parts];
 
691
    if (fill_used_fields_bitmap(&param))
697
692
    {
698
693
      session->no_errors=0;
699
694
      alloc.free_root(MYF(0));                  // Return memory & allocator
739
734
    {
740
735
      int key_for_use= head->find_shortest_key(&head->covering_keys);
741
736
      double key_read_time=
742
 
        param.table->cursor->index_only_read_time(key_for_use,
743
 
                                                rows2double(records)) +
 
737
        param.table->cursor->index_only_read_time(key_for_use, records) +
744
738
        (double) records / TIME_FOR_COMPARE;
745
739
      if (key_read_time < read_time)
746
740
        read_time= key_read_time;
810
804
          objects are not allowed so don't use ROR-intersection for
811
805
          table deletes.
812
806
        */
813
 
        if ((session->lex->sql_command != SQLCOM_DELETE))
 
807
        if ((session->lex().sql_command != SQLCOM_DELETE))
814
808
        {
815
809
          /*
816
810
            Get best non-covering ROR-intersection plan and prepare data for
838
832
        optimizer::SEL_IMERGE *imerge= NULL;
839
833
        optimizer::TableReadPlan *best_conj_trp= NULL;
840
834
        optimizer::TableReadPlan *new_conj_trp= NULL;
841
 
        List_iterator_fast<optimizer::SEL_IMERGE> it(tree->merges);
 
835
        List<optimizer::SEL_IMERGE>::iterator it(tree->merges.begin());
842
836
        while ((imerge= it++))
843
837
        {
844
838
          new_conj_trp= get_best_disjunct_quick(session, &param, imerge, best_read_time);
862
856
      records= best_trp->records;
863
857
      if (! (quick= best_trp->make_quick(&param, true)) || quick->init())
864
858
      {
865
 
        /* quick can already be free here */
866
 
        if (quick)
867
 
        {
868
 
          delete quick;
869
 
          quick= NULL;
870
 
        }
 
859
        delete quick;
 
860
        quick= NULL;
871
861
      }
872
862
    }
873
863
 
976
966
  ha_rows roru_total_records;
977
967
  double roru_intersect_part= 1.0;
978
968
 
979
 
  if (! (range_scans= (optimizer::RangeReadPlan**)param->mem_root->alloc_root(sizeof(optimizer::RangeReadPlan*)* n_child_scans)))
980
 
  {
981
 
    return NULL;
982
 
  }
 
969
  range_scans= new (*param->mem_root) optimizer::RangeReadPlan*[n_child_scans];
983
970
 
984
971
  /*
985
972
    Collect best 'range' scan for each of disjuncts, and, while doing so,
986
973
    analyze possibility of ROR scans. Also calculate some values needed by
987
974
    other parts of the code.
988
975
  */
989
 
  for (ptree= imerge->trees, cur_child= range_scans;
990
 
       ptree != imerge->trees_next;
991
 
       ptree++, cur_child++)
 
976
  for (ptree= imerge->trees, cur_child= range_scans; ptree != imerge->trees_next; ptree++, cur_child++)
992
977
  {
993
978
    if (!(*cur_child= get_key_scans_params(session, param, *ptree, true, false, read_time)))
994
979
    {
1043
1028
  /* Calculate cost(rowid_to_row_scan) */
1044
1029
  {
1045
1030
    optimizer::CostVector sweep_cost;
1046
 
    Join *join= param->session->lex->select_lex.join;
 
1031
    Join *join= param->session->lex().select_lex.join;
1047
1032
    bool is_interrupted= test(join && join->tables == 1);
1048
1033
    get_sweep_read_cost(param->table, non_cpk_scan_records, is_interrupted,
1049
1034
                        &sweep_cost);
1059
1044
                                    param->session->variables.sortbuff_size);
1060
1045
  if (param->imerge_cost_buff_size < unique_calc_buff_size)
1061
1046
  {
1062
 
    if (!(param->imerge_cost_buff= (uint*)param->mem_root->alloc_root(unique_calc_buff_size)))
1063
 
    {
1064
 
      return NULL;
1065
 
    }
1066
 
 
 
1047
    param->imerge_cost_buff= (uint*)param->mem_root->alloc(unique_calc_buff_size);
1067
1048
    param->imerge_cost_buff_size= unique_calc_buff_size;
1068
1049
  }
1069
1050
 
1073
1054
                         param->session->variables.sortbuff_size);
1074
1055
  if (imerge_cost < read_time)
1075
1056
  {
1076
 
    if ((imerge_trp= new (param->mem_root) optimizer::IndexMergeReadPlan))
1077
 
    {
1078
 
      imerge_trp->read_cost= imerge_cost;
1079
 
      imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
1080
 
      imerge_trp->records= min(imerge_trp->records,
1081
 
                               param->table->cursor->stats.records);
1082
 
      imerge_trp->range_scans= range_scans;
1083
 
      imerge_trp->range_scans_end= range_scans + n_child_scans;
1084
 
      read_time= imerge_cost;
1085
 
    }
 
1057
    imerge_trp= new (*param->mem_root) optimizer::IndexMergeReadPlan;
 
1058
    imerge_trp->read_cost= imerge_cost;
 
1059
    imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
 
1060
    imerge_trp->records= min(imerge_trp->records, param->table->cursor->stats.records);
 
1061
    imerge_trp->range_scans= range_scans;
 
1062
    imerge_trp->range_scans_end= range_scans + n_child_scans;
 
1063
    read_time= imerge_cost;
1086
1064
  }
1087
1065
 
1088
1066
build_ror_index_merge:
1089
 
  if (!all_scans_ror_able || param->session->lex->sql_command == SQLCOM_DELETE)
 
1067
  if (!all_scans_ror_able || param->session->lex().sql_command == SQLCOM_DELETE)
1090
1068
    return(imerge_trp);
1091
1069
 
1092
1070
  /* Ok, it is possible to build a ROR-union, try it. */
1093
1071
  bool dummy;
1094
 
  if (! (roru_read_plans=
1095
 
          (optimizer::TableReadPlan **) param->mem_root->alloc_root(sizeof(optimizer::TableReadPlan*) * n_child_scans)))
1096
 
  {
1097
 
    return imerge_trp;
1098
 
  }
 
1072
  roru_read_plans= new (*param->mem_root) optimizer::TableReadPlan*[n_child_scans];
1099
1073
skip_to_ror_scan:
1100
1074
  roru_index_costs= 0.0;
1101
1075
  roru_total_records= 0;
1119
1093
      cost= param->table->cursor->
1120
1094
              read_time(param->real_keynr[(*cur_child)->key_idx], 1,
1121
1095
                        (*cur_child)->records) +
1122
 
              rows2double((*cur_child)->records) / TIME_FOR_COMPARE;
 
1096
              static_cast<double>((*cur_child)->records) / TIME_FOR_COMPARE;
1123
1097
    }
1124
1098
    else
1125
1099
      cost= read_time;
1161
1135
  double roru_total_cost;
1162
1136
  {
1163
1137
    optimizer::CostVector sweep_cost;
1164
 
    Join *join= param->session->lex->select_lex.join;
 
1138
    Join *join= param->session->lex().select_lex.join;
1165
1139
    bool is_interrupted= test(join && join->tables == 1);
1166
1140
    get_sweep_read_cost(param->table, roru_total_records, is_interrupted,
1167
1141
                        &sweep_cost);
1168
1142
    roru_total_cost= roru_index_costs +
1169
 
                     rows2double(roru_total_records)*log((double)n_child_scans) /
 
1143
                     static_cast<double>(roru_total_records)*log((double)n_child_scans) /
1170
1144
                     (TIME_FOR_COMPARE_ROWID * M_LN2) +
1171
1145
                     sweep_cost.total_cost();
1172
1146
  }
1174
1148
  optimizer::RorUnionReadPlan *roru= NULL;
1175
1149
  if (roru_total_cost < read_time)
1176
1150
  {
1177
 
    if ((roru= new (param->mem_root) optimizer::RorUnionReadPlan))
 
1151
    if ((roru= new (*param->mem_root) optimizer::RorUnionReadPlan))
1178
1152
    {
1179
1153
      roru->first_ror= roru_read_plans;
1180
1154
      roru->last_ror= roru_read_plans + n_child_scans;
1206
1180
static
1207
1181
optimizer::RorScanInfo *make_ror_scan(const optimizer::Parameter *param, int idx, optimizer::SEL_ARG *sel_arg)
1208
1182
{
1209
 
  optimizer::RorScanInfo *ror_scan= NULL;
1210
 
 
1211
1183
  uint32_t keynr;
1212
 
 
1213
 
  if (!(ror_scan= (optimizer::RorScanInfo*)param->mem_root->alloc_root(sizeof(optimizer::RorScanInfo))))
1214
 
    return NULL;
 
1184
  optimizer::RorScanInfo* ror_scan= new (*param->mem_root) optimizer::RorScanInfo;
1215
1185
 
1216
1186
  ror_scan->idx= idx;
1217
1187
  ror_scan->keynr= keynr= param->real_keynr[idx];
1232
1202
    if (param->needed_fields.test(key_part->fieldnr-1))
1233
1203
      tmp_bitset.set(key_part->fieldnr-1);
1234
1204
  }
1235
 
  double rows= rows2double(param->table->quick_rows[ror_scan->keynr]);
 
1205
  double rows= param->table->quick_rows[ror_scan->keynr];
1236
1206
  ror_scan->index_read_cost=
1237
1207
    param->table->cursor->index_only_read_time(ror_scan->keynr, rows);
1238
1208
  ror_scan->covered_fields= tmp_bitset.to_ulong();
1255
1225
 
1256
1226
static int cmp_ror_scan_info(optimizer::RorScanInfo** a, optimizer::RorScanInfo** b)
1257
1227
{
1258
 
  double val1= rows2double((*a)->records) * (*a)->key_rec_length;
1259
 
  double val2= rows2double((*b)->records) * (*b)->key_rec_length;
 
1228
  double val1= static_cast<double>((*a)->records) * (*a)->key_rec_length;
 
1229
  double val2= static_cast<double>((*b)->records) * (*b)->key_rec_length;
1260
1230
  return (val1 < val2)? -1: (val1 == val2)? 0 : 1;
1261
1231
}
1262
1232
 
1492
1462
      if (cur_covered)
1493
1463
      {
1494
1464
        /* uncovered -> covered */
1495
 
        double tmp= rows2double(records)/rows2double(prev_records);
1496
 
        selectivity_mult *= tmp;
 
1465
        selectivity_mult *= static_cast<double>(records) / prev_records;
1497
1466
        prev_records= HA_POS_ERROR;
1498
1467
      }
1499
1468
      else
1506
1475
  }
1507
1476
  if (!prev_covered)
1508
1477
  {
1509
 
    double tmp= rows2double(info->param->table->quick_rows[scan->keynr]) /
1510
 
                rows2double(prev_records);
1511
 
    selectivity_mult *= tmp;
 
1478
    selectivity_mult *= static_cast<double>(info->param->table->quick_rows[scan->keynr]) / prev_records;
1512
1479
  }
1513
 
  return(selectivity_mult);
 
1480
  return selectivity_mult;
1514
1481
}
1515
1482
 
1516
1483
 
1571
1538
      each record of every scan. Assuming 1/TIME_FOR_COMPARE_ROWID
1572
1539
      per check this gives us:
1573
1540
    */
1574
 
    info->index_scan_costs += rows2double(info->index_records) /
 
1541
    info->index_scan_costs += static_cast<double>(info->index_records) /
1575
1542
                              TIME_FOR_COMPARE_ROWID;
1576
1543
  }
1577
1544
  else
1590
1557
  if (! info->is_covering)
1591
1558
  {
1592
1559
    optimizer::CostVector sweep_cost;
1593
 
    Join *join= info->param->session->lex->select_lex.join;
 
1560
    Join *join= info->param->session->lex().select_lex.join;
1594
1561
    bool is_interrupted= test(join && join->tables == 1);
1595
1562
    get_sweep_read_cost(info->param->table, double2rows(info->out_rows),
1596
1563
                        is_interrupted, &sweep_cost);
1704
1671
    cost total_cost.
1705
1672
  */
1706
1673
  /* Add priority queue use cost. */
1707
 
  total_cost += rows2double(records)*
 
1674
  total_cost += static_cast<double>(records) *
1708
1675
                log((double)(ror_scan_mark - tree->ror_scans)) /
1709
1676
                (TIME_FOR_COMPARE_ROWID * M_LN2);
1710
1677
 
1711
1678
  if (total_cost > read_time)
1712
1679
    return NULL;
1713
1680
 
1714
 
  optimizer::RorIntersectReadPlan *trp= NULL;
1715
 
  if (! (trp= new (param->mem_root) optimizer::RorIntersectReadPlan))
1716
 
  {
1717
 
    return trp;
1718
 
  }
 
1681
  optimizer::RorIntersectReadPlan* trp= new (*param->mem_root) optimizer::RorIntersectReadPlan;
1719
1682
 
1720
1683
  uint32_t best_num= (ror_scan_mark - tree->ror_scans);
1721
 
  if (!(trp->first_scan= (optimizer::RorScanInfo**)param->mem_root->alloc_root(sizeof(optimizer::RorScanInfo*)* best_num)))
1722
 
    return NULL;
 
1684
  trp->first_scan= new (*param->mem_root) optimizer::RorScanInfo*[best_num];
1723
1685
  memcpy(trp->first_scan, tree->ror_scans, best_num*sizeof(optimizer::RorScanInfo*));
1724
1686
  trp->last_scan=  trp->first_scan + best_num;
1725
1687
  trp->is_covering= true;
1817
1779
  uint32_t cpk_no= 0;
1818
1780
  bool cpk_scan_used= false;
1819
1781
 
1820
 
  if (! (tree->ror_scans= (optimizer::RorScanInfo**)param->mem_root->alloc_root(sizeof(optimizer::RorScanInfo*)* param->keys)))
1821
 
  {
1822
 
    return NULL;
1823
 
  }
1824
 
  cpk_no= ((param->table->cursor->primary_key_is_clustered()) ?
1825
 
           param->table->getShare()->getPrimaryKey() : MAX_KEY);
 
1782
  tree->ror_scans= new (*param->mem_root) optimizer::RorScanInfo*[param->keys];
 
1783
  cpk_no= ((param->table->cursor->primary_key_is_clustered()) ? param->table->getShare()->getPrimaryKey() : MAX_KEY);
1826
1784
 
1827
1785
  for (idx= 0, cur_ror_scan= tree->ror_scans; idx < param->keys; idx++)
1828
1786
  {
1850
1808
                     (qsort_cmp)cmp_ror_scan_info);
1851
1809
 
1852
1810
  optimizer::RorScanInfo **intersect_scans= NULL; /* ROR scans used in index intersection */
1853
 
  optimizer::RorScanInfo **intersect_scans_end= NULL;
1854
 
  if (! (intersect_scans= (optimizer::RorScanInfo**)param->mem_root->alloc_root(sizeof(optimizer::RorScanInfo*) * tree->n_ror_scans)))
1855
 
    return NULL;
 
1811
  optimizer::RorScanInfo **intersect_scans_end= intersect_scans=  new (*param->mem_root) optimizer::RorScanInfo*[tree->n_ror_scans];
1856
1812
  intersect_scans_end= intersect_scans;
1857
1813
 
1858
1814
  /* Create and incrementally update ROR intersection. */
1911
1867
  optimizer::RorIntersectReadPlan *trp= NULL;
1912
1868
  if (min_cost < read_time && (cpk_scan_used || best_num > 1))
1913
1869
  {
1914
 
    if (! (trp= new (param->mem_root) optimizer::RorIntersectReadPlan))
1915
 
      return trp;
1916
 
 
1917
 
    if (! (trp->first_scan=
1918
 
           (optimizer::RorScanInfo**)param->mem_root->alloc_root(sizeof(optimizer::RorScanInfo*)*best_num)))
1919
 
      return NULL;
 
1870
    trp= new (*param->mem_root) optimizer::RorIntersectReadPlan;
 
1871
    trp->first_scan= new (*param->mem_root) optimizer::RorScanInfo*[best_num];
1920
1872
    memcpy(trp->first_scan, intersect_scans, best_num*sizeof(optimizer::RorScanInfo*));
1921
1873
    trp->last_scan=  trp->first_scan + best_num;
1922
1874
    trp->is_covering= intersect_best.is_covering;
2022
1974
  if (key_to_read)
2023
1975
  {
2024
1976
    idx= key_to_read - tree->keys;
2025
 
    if ((read_plan= new (param->mem_root) optimizer::RangeReadPlan(*key_to_read, idx,
2026
 
                                                                   best_mrr_flags)))
2027
 
    {
2028
 
      read_plan->records= best_records;
2029
 
      read_plan->is_ror= tree->ror_scans_map.test(idx);
2030
 
      read_plan->read_cost= read_time;
2031
 
      read_plan->mrr_buf_size= best_buf_size;
2032
 
    }
 
1977
    read_plan= new (*param->mem_root) optimizer::RangeReadPlan(*key_to_read, idx, best_mrr_flags);
 
1978
    read_plan->records= best_records;
 
1979
    read_plan->is_ror= tree->ror_scans_map.test(idx);
 
1980
    read_plan->read_cost= read_time;
 
1981
    read_plan->mrr_buf_size= best_buf_size;
2033
1982
  }
2034
 
 
2035
 
  return(read_plan);
 
1983
  return read_plan;
2036
1984
}
2037
1985
 
2038
1986
 
2039
1987
optimizer::QuickSelectInterface *optimizer::IndexMergeReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *)
2040
1988
{
2041
 
  optimizer::QuickIndexMergeSelect *quick_imerge;
2042
 
  optimizer::QuickRangeSelect *quick= NULL;
2043
1989
  /* index_merge always retrieves full rows, ignore retrieve_full_rows */
2044
 
  if (! (quick_imerge= new optimizer::QuickIndexMergeSelect(param->session, param->table)))
2045
 
  {
2046
 
    return NULL;
2047
 
  }
2048
 
 
 
1990
  optimizer::QuickIndexMergeSelect* quick_imerge= new optimizer::QuickIndexMergeSelect(param->session, param->table);
2049
1991
  quick_imerge->records= records;
2050
1992
  quick_imerge->read_time= read_cost;
2051
 
  for (optimizer::RangeReadPlan **range_scan= range_scans; 
2052
 
       range_scan != range_scans_end;
2053
 
       range_scan++)
 
1993
  for (optimizer::RangeReadPlan **range_scan= range_scans; range_scan != range_scans_end; range_scan++)
2054
1994
  {
2055
 
    if (! (quick= (optimizer::QuickRangeSelect*)
2056
 
          ((*range_scan)->make_quick(param, false, &quick_imerge->alloc))) ||
2057
 
        quick_imerge->push_quick_back(quick))
 
1995
    optimizer::QuickRangeSelect* quick= (optimizer::QuickRangeSelect*)((*range_scan)->make_quick(param, false, &quick_imerge->alloc));
 
1996
    if (not quick)
2058
1997
    {
2059
1998
      delete quick;
2060
1999
      delete quick_imerge;
2061
2000
      return NULL;
2062
2001
    }
 
2002
    quick_imerge->push_quick_back(quick);
2063
2003
  }
2064
2004
  return quick_imerge;
2065
2005
}
2086
2026
                                                (*first_scan)->sel_arg,
2087
2027
                                                HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED,
2088
2028
                                                0,
2089
 
                                                alloc)) ||
2090
 
          quick_intersect->push_quick_back(quick))
 
2029
                                                alloc)))
2091
2030
      {
2092
2031
        delete quick_intersect;
2093
2032
        return NULL;
2094
2033
      }
 
2034
      quick_intersect->push_quick_back(quick);
2095
2035
    }
2096
2036
    if (cpk_scan)
2097
2037
    {
2117
2057
 
2118
2058
optimizer::QuickSelectInterface *optimizer::RorUnionReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *)
2119
2059
{
2120
 
  optimizer::QuickRorUnionSelect *quick_roru= NULL;
2121
 
  optimizer::TableReadPlan **scan= NULL;
2122
 
  optimizer::QuickSelectInterface *quick= NULL;
2123
2060
  /*
2124
2061
    It is impossible to construct a ROR-union that will not retrieve full
2125
2062
    rows, ignore retrieve_full_rows parameter.
2126
2063
  */
2127
 
  if ((quick_roru= new optimizer::QuickRorUnionSelect(param->session, param->table)))
 
2064
  optimizer::QuickRorUnionSelect* quick_roru= new optimizer::QuickRorUnionSelect(param->session, param->table);
 
2065
  for (optimizer::TableReadPlan** scan= first_ror; scan != last_ror; scan++)
2128
2066
  {
2129
 
    for (scan= first_ror; scan != last_ror; scan++)
2130
 
    {
2131
 
      if (! (quick= (*scan)->make_quick(param, false, &quick_roru->alloc)) ||
2132
 
          quick_roru->push_quick_back(quick))
2133
 
      {
2134
 
        return NULL;
2135
 
      }
2136
 
    }
2137
 
    quick_roru->records= records;
2138
 
    quick_roru->read_time= read_cost;
 
2067
    optimizer::QuickSelectInterface* quick= (*scan)->make_quick(param, false, &quick_roru->alloc);
 
2068
    if (not quick)
 
2069
      return NULL;
 
2070
    quick_roru->push_quick_back(quick);
2139
2071
  }
 
2072
  quick_roru->records= records;
 
2073
  quick_roru->read_time= read_cost;
2140
2074
  return quick_roru;
2141
2075
}
2142
2076
 
2197
2131
*/
2198
2132
static optimizer::SEL_TREE *get_func_mm_tree(optimizer::RangeParameter *param,
2199
2133
                                  Item_func *cond_func,
2200
 
                                  Field *field, 
 
2134
                                  Field *field,
2201
2135
                                  Item *value,
2202
 
                                  Item_result cmp_type, 
 
2136
                                  Item_result cmp_type,
2203
2137
                                  bool inv)
2204
2138
{
2205
2139
  optimizer::SEL_TREE *tree= NULL;
2206
2140
 
2207
 
  switch (cond_func->functype()) 
 
2141
  switch (cond_func->functype())
2208
2142
  {
2209
2143
 
2210
2144
  case Item_func::NE_FUNC:
2217
2151
    {
2218
2152
      if (inv)
2219
2153
      {
2220
 
        tree= get_ne_mm_tree(param, 
2221
 
                             cond_func, 
2222
 
                             field, 
 
2154
        tree= get_ne_mm_tree(param,
 
2155
                             cond_func,
 
2156
                             field,
2223
2157
                             cond_func->arguments()[1],
2224
 
                             cond_func->arguments()[2], 
 
2158
                             cond_func->arguments()[2],
2225
2159
                             cmp_type);
2226
2160
      }
2227
2161
      else
2228
2162
      {
2229
 
        tree= get_mm_parts(param, 
2230
 
                           cond_func, 
2231
 
                           field, 
 
2163
        tree= get_mm_parts(param,
 
2164
                           cond_func,
 
2165
                           field,
2232
2166
                           Item_func::GE_FUNC,
2233
2167
                                       cond_func->arguments()[1],
2234
2168
                           cmp_type);
2235
2169
        if (tree)
2236
2170
        {
2237
 
          tree= tree_and(param, 
2238
 
                         tree, 
 
2171
          tree= tree_and(param,
 
2172
                         tree,
2239
2173
                         get_mm_parts(param, cond_func, field,
2240
2174
                                                       Item_func::LE_FUNC,
2241
2175
                                                       cond_func->arguments()[2],
2244
2178
      }
2245
2179
    }
2246
2180
    else
2247
 
      tree= get_mm_parts(param, 
2248
 
                         cond_func, 
 
2181
      tree= get_mm_parts(param,
 
2182
                         cond_func,
2249
2183
                         field,
2250
2184
                         (inv ?
2251
2185
                          (value == (Item*)1 ? Item_func::GT_FUNC :
2252
2186
                                               Item_func::LT_FUNC):
2253
2187
                          (value == (Item*)1 ? Item_func::LE_FUNC :
2254
2188
                                               Item_func::GE_FUNC)),
2255
 
                         cond_func->arguments()[0], 
 
2189
                         cond_func->arguments()[0],
2256
2190
                         cmp_type);
2257
2191
    break;
2258
2192
  }
2321
2255
        do
2322
2256
        {
2323
2257
          func->array->value_to_item(i, value_item);
2324
 
          tree= get_mm_parts(param, 
2325
 
                             cond_func, 
 
2258
          tree= get_mm_parts(param,
 
2259
                             cond_func,
2326
2260
                             field, Item_func::LT_FUNC,
2327
 
                             value_item, 
 
2261
                             value_item,
2328
2262
                             cmp_type);
2329
2263
          if (! tree)
2330
2264
            break;
2535
2469
  Item_equal *item_equal= field_item->item_equal;
2536
2470
  if (item_equal)
2537
2471
  {
2538
 
    Item_equal_iterator it(*item_equal);
 
2472
    Item_equal_iterator it(item_equal->begin());
2539
2473
    Item_field *item;
2540
2474
    while ((item= it++))
2541
2475
    {
2566
2500
 
2567
2501
  if (cond->type() == Item::COND_ITEM)
2568
2502
  {
2569
 
    List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
2503
    List<Item>::iterator li(((Item_cond*) cond)->argument_list()->begin());
2570
2504
 
2571
2505
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
2572
2506
    {
2573
2507
      tree=0;
2574
 
      Item *item;
2575
 
      while ((item=li++))
 
2508
      while (Item* item=li++)
2576
2509
      {
2577
2510
        optimizer::SEL_TREE *new_tree= get_mm_tree(param,item);
2578
2511
        if (param->session->is_fatal_error ||
2588
2521
      tree= get_mm_tree(param,li++);
2589
2522
      if (tree)
2590
2523
      {
2591
 
        Item *item;
2592
 
        while ((item=li++))
 
2524
        while (Item* item= li++)
2593
2525
        {
2594
2526
          optimizer::SEL_TREE *new_tree= get_mm_tree(param,item);
2595
2527
          if (!new_tree)
2690
2622
    Item_equal *item_equal= (Item_equal *) cond;
2691
2623
    if (!(value= item_equal->get_const()))
2692
2624
      return 0;
2693
 
    Item_equal_iterator it(*item_equal);
 
2625
    Item_equal_iterator it(item_equal->begin());
2694
2626
    ref_tables= value->used_tables();
2695
2627
    while ((field_item= it++))
2696
2628
    {
2751
2683
    if (field->eq(key_part->field))
2752
2684
    {
2753
2685
      optimizer::SEL_ARG *sel_arg=0;
2754
 
      if (!tree && !(tree=new optimizer::SEL_TREE()))
2755
 
        return 0;                               // OOM
 
2686
      if (!tree)
 
2687
        tree= new optimizer::SEL_TREE;
2756
2688
      if (!value || !(value->used_tables() & ~param->read_tables))
2757
2689
      {
2758
 
        sel_arg= get_mm_leaf(param,cond_func,
2759
 
            key_part->field,key_part,type,value);
 
2690
        sel_arg= get_mm_leaf(param,cond_func, key_part->field,key_part,type,value);
2760
2691
        if (! sel_arg)
2761
2692
          continue;
2762
2693
        if (sel_arg->type == optimizer::SEL_ARG::IMPOSSIBLE)
2768
2699
      else
2769
2700
      {
2770
2701
        // This key may be used later
2771
 
        if (! (sel_arg= new optimizer::SEL_ARG(optimizer::SEL_ARG::MAYBE_KEY)))
2772
 
          return 0;                     // OOM
 
2702
        sel_arg= new optimizer::SEL_ARG(optimizer::SEL_ARG::MAYBE_KEY);
2773
2703
      }
2774
2704
      sel_arg->part=(unsigned char) key_part->part;
2775
2705
      tree->keys[key_part->key]=sel_add(tree->keys[key_part->key],sel_arg);
2815
2745
        tree= &optimizer::null_element;
2816
2746
      goto end;
2817
2747
    }
2818
 
    if (!(tree= new (alloc) optimizer::SEL_ARG(field,is_null_string,is_null_string)))
2819
 
      goto end;                                 // out of memory
 
2748
    tree= new (*alloc) optimizer::SEL_ARG(field,is_null_string,is_null_string);
2820
2749
    if (type == Item_func::ISNOTNULL_FUNC)
2821
2750
    {
2822
2751
      tree->min_flag=NEAR_MIN;              /* IS NOT NULL ->  X > NULL */
2844
2773
    goto end;
2845
2774
 
2846
2775
  if (param->using_real_indexes)
2847
 
    optimize_range= field->optimize_range(param->real_keynr[key_part->key],
2848
 
                                          key_part->part);
 
2776
    optimize_range= field->optimize_range(param->real_keynr[key_part->key], key_part->part);
2849
2777
  else
2850
2778
    optimize_range= true;
2851
2779
 
2902
2830
        field_length= length;
2903
2831
    }
2904
2832
    length+=offset;
2905
 
    if (!(min_str= (unsigned char*) alloc->alloc_root(length*2)))
2906
 
    {
2907
 
      goto end;
2908
 
    }
2909
 
 
 
2833
    min_str= alloc->alloc(length*2);
2910
2834
    max_str=min_str+length;
2911
2835
    if (maybe_null)
2912
2836
      max_str[0]= min_str[0]=0;
2978
2902
   * it is, then we must convert to the highest Timestamp value (or lowest,
2979
2903
   * depending on whether the datetime is before or after the epoch.
2980
2904
   */
2981
 
  if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
 
2905
  if (field->is_timestamp())
2982
2906
  {
2983
2907
    /*
2984
2908
     * The left-side of the range comparison is a timestamp field.  Therefore,
3117
3041
               (value->val_int() < 0))
3118
3042
        type = Item_func::GE_FUNC;
3119
3043
    }
 
3044
    else if (err == 1)
 
3045
    {
 
3046
      tree= new (alloc) optimizer::SEL_ARG(field, 0, 0);
 
3047
      tree->type= optimizer::SEL_ARG::IMPOSSIBLE;
 
3048
      goto end;
 
3049
    }
3120
3050
  }
3121
3051
  else if (err < 0)
3122
3052
  {
3129
3059
    Any predicate except "<=>"(null-safe equality operator) involving NULL as a
3130
3060
    constant is always FALSE
3131
3061
    Put IMPOSSIBLE Tree(null_element) here.
3132
 
  */  
 
3062
  */
3133
3063
  if (type != Item_func::EQUAL_FUNC && field->is_real_null())
3134
3064
  {
3135
3065
    tree= &optimizer::null_element;
3136
3066
    goto end;
3137
3067
  }
3138
3068
 
3139
 
  str= (unsigned char*) alloc->alloc_root(key_part->store_length+1);
3140
 
  if (!str)
3141
 
    goto end;
 
3069
  str= alloc->alloc(key_part->store_length+1);
3142
3070
  if (maybe_null)
3143
 
    *str= (unsigned char) field->is_real_null();        // Set to 1 if null
 
3071
    *str= field->is_real_null();        // Set to 1 if null
3144
3072
  field->get_key_image(str+maybe_null, key_part->length);
3145
 
  if (! (tree= new (alloc) optimizer::SEL_ARG(field, str, str)))
3146
 
    goto end; // out of memory
 
3073
  tree= new (alloc) optimizer::SEL_ARG(field, str, str);
3147
3074
 
3148
3075
  /*
3149
3076
    Check if we are comparing an UNSIGNED integer with a negative constant.
3315
3242
  /* dispose index_merge if there is a "range" option */
3316
3243
  if (result_keys.any())
3317
3244
  {
3318
 
    tree1->merges.empty();
 
3245
    tree1->merges.clear();
3319
3246
    return(tree1);
3320
3247
  }
3321
3248
 
3337
3264
  optimizer::SEL_ARG *next= NULL;
3338
3265
  ulong use_count=key1->use_count;
3339
3266
 
3340
 
  if (key1->elements != 1)
 
3267
  if (key1->size() != 1)
3341
3268
  {
3342
 
    key2->use_count+=key1->elements-1; //psergey: why we don't count that key1 has n-k-p?
3343
 
    key2->increment_use_count((int) key1->elements-1);
 
3269
    key2->use_count+=key1->size()-1; //psergey: why we don't count that key1 has n-k-p?
 
3270
    key2->increment_use_count((int) key1->size()-1);
3344
3271
  }
3345
3272
  if (key1->type == optimizer::SEL_ARG::MAYBE_KEY)
3346
3273
  {
3480
3407
    if (! next || next->type != optimizer::SEL_ARG::IMPOSSIBLE)
3481
3408
    {
3482
3409
      optimizer::SEL_ARG *new_arg= e1->clone_and(e2);
3483
 
      if (! new_arg)
3484
 
        return &optimizer::null_element;                        // End of memory
3485
3410
      new_arg->next_key_part=next;
3486
3411
      if (! new_tree)
3487
3412
      {
3860
3785
      !(pk_is_clustered && keynr == param->table->getShare()->getPrimaryKey()))
3861
3786
     *mrr_flags |= HA_MRR_INDEX_ONLY;
3862
3787
 
3863
 
  if (session->lex->sql_command != SQLCOM_SELECT)
 
3788
  if (session->lex().sql_command != SQLCOM_SELECT)
3864
3789
    *mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
3865
3790
 
3866
3791
  *bufsize= param->session->variables.read_rnd_buff_size;
4007
3932
    {
4008
3933
      quick->mrr_flags= mrr_flags;
4009
3934
      quick->mrr_buf_size= mrr_buf_size;
4010
 
      if (parent_alloc)
4011
 
      {
4012
 
        quick->key_parts=(KEY_PART*)
4013
 
          parent_alloc->memdup_root( (char*) param->key[idx], sizeof(KEY_PART)* param->table->key_info[param->real_keynr[idx]].key_parts);
4014
 
      }
4015
 
      else
4016
 
      {
4017
 
        quick->key_parts=(KEY_PART*)
4018
 
          quick->alloc.memdup_root((char*) param->key[idx], sizeof(KEY_PART)* param->table->key_info[param->real_keynr[idx]].key_parts);
4019
 
      }
 
3935
      quick->key_parts= parent_alloc
 
3936
        ? (KEY_PART*)parent_alloc->memdup(param->key[idx], sizeof(KEY_PART)* param->table->key_info[param->real_keynr[idx]].key_parts)
 
3937
        : (KEY_PART*)quick->alloc.memdup(param->key[idx], sizeof(KEY_PART)* param->table->key_info[param->real_keynr[idx]].key_parts);
4020
3938
    }
4021
3939
  }
4022
3940
  return quick;
4151
4069
  }
4152
4070
 
4153
4071
  /* Get range for retrieving rows in QUICK_SELECT::get_next */
4154
 
  if (! (range= new optimizer::QuickRange(param->min_key,
 
4072
  range= new optimizer::QuickRange(param->min_key,
4155
4073
                                                             (uint32_t) (tmp_min_key - param->min_key),
4156
4074
                                           min_part >=0 ? make_keypart_map(min_part) : 0,
4157
4075
                                                             param->max_key,
4158
4076
                                                             (uint32_t) (tmp_max_key - param->max_key),
4159
4077
                                           max_part >=0 ? make_keypart_map(max_part) : 0,
4160
 
                                                             flag)))
4161
 
  {
4162
 
    return 1;                   // out of memory
4163
 
  }
 
4078
                                                             flag);
4164
4079
 
4165
4080
  set_if_bigger(quick->max_used_key_length, (uint32_t)range->min_length);
4166
4081
  set_if_bigger(quick->max_used_key_length, (uint32_t)range->max_length);
4167
4082
  set_if_bigger(quick->used_key_parts, (uint32_t) key_tree->part+1);
4168
 
  if (insert_dynamic(&quick->ranges, (unsigned char*) &range))
4169
 
  {
4170
 
    return 1;
4171
 
  }
 
4083
  quick->ranges.push_back(&range);
4172
4084
 
4173
4085
 end:
4174
4086
  if (key_tree->right != &optimizer::null_element)
4267
4179
    goto err;
4268
4180
  quick->records= records;
4269
4181
 
4270
 
  if ((cp_buffer_from_ref(session, ref) && session->is_fatal_error) ||
4271
 
      !(range= new(alloc) optimizer::QuickRange()))
 
4182
  if (cp_buffer_from_ref(session, ref) && session->is_fatal_error)
4272
4183
    goto err;                                   // out of memory
 
4184
  range= new (*alloc) optimizer::QuickRange;
4273
4185
 
4274
4186
  range->min_key= range->max_key= ref->key_buff;
4275
4187
  range->min_length= range->max_length= ref->key_length;
4276
4188
  range->min_keypart_map= range->max_keypart_map=
4277
4189
    make_prev_keypart_map(ref->key_parts);
4278
 
  range->flag= ((ref->key_length == key_info->key_length &&
4279
 
                 (key_info->flags & HA_END_SPACE_KEY) == 0) ? EQ_RANGE : 0);
4280
 
 
4281
 
 
4282
 
  if (!(quick->key_parts=key_part=(KEY_PART *)
4283
 
        quick->alloc.alloc_root(sizeof(KEY_PART)*ref->key_parts)))
4284
 
    goto err;
 
4190
  range->flag= (ref->key_length == key_info->key_length && (key_info->flags & HA_END_SPACE_KEY) == 0) ? EQ_RANGE : 0;
 
4191
 
 
4192
  quick->key_parts=key_part= new (quick->alloc) KEY_PART[ref->key_parts];
4285
4193
 
4286
4194
  for (part=0 ; part < ref->key_parts ;part++,key_part++)
4287
4195
  {
4292
4200
    key_part->null_bit=     key_info->key_part[part].null_bit;
4293
4201
    key_part->flag=         (uint8_t) key_info->key_part[part].key_part_flag;
4294
4202
  }
4295
 
  if (insert_dynamic(&quick->ranges,(unsigned char*)&range))
4296
 
    goto err;
 
4203
  quick->ranges.push_back(&range);
4297
4204
 
4298
4205
  /*
4299
4206
     Add a NULL range if REF_OR_NULL optimization is used.
4306
4213
    optimizer::QuickRange *null_range= NULL;
4307
4214
 
4308
4215
    *ref->null_ref_key= 1;              // Set null byte then create a range
4309
 
    if (!(null_range= new (alloc)
 
4216
    null_range= new (alloc)
4310
4217
          optimizer::QuickRange(ref->key_buff, ref->key_length,
4311
4218
                                 make_prev_keypart_map(ref->key_parts),
4312
4219
                                 ref->key_buff, ref->key_length,
4313
 
                                 make_prev_keypart_map(ref->key_parts), EQ_RANGE)))
4314
 
      goto err;
 
4220
                                 make_prev_keypart_map(ref->key_parts), EQ_RANGE);
4315
4221
    *ref->null_ref_key= 0;              // Clear null byte
4316
 
    if (insert_dynamic(&quick->ranges,(unsigned char*)&null_range))
4317
 
      goto err;
 
4222
    quick->ranges.push_back(&null_range);
4318
4223
  }
4319
4224
 
4320
4225
  /* Call multi_range_read_info() to get the MRR flags and buffer size */
4321
4226
  quick->mrr_flags= HA_MRR_NO_ASSOCIATION |
4322
4227
                    (table->key_read ? HA_MRR_INDEX_ONLY : 0);
4323
 
  if (session->lex->sql_command != SQLCOM_SELECT)
 
4228
  if (session->lex().sql_command != SQLCOM_SELECT)
4324
4229
    quick->mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
4325
4230
 
4326
4231
  quick->mrr_buf_size= session->variables.read_rnd_buff_size;
4327
 
  if (table->cursor->multi_range_read_info(quick->index, 1, (uint32_t)records,
4328
 
                                           &quick->mrr_buf_size,
4329
 
                                           &quick->mrr_flags, &cost))
 
4232
  if (table->cursor->multi_range_read_info(quick->index, 1, (uint32_t)records, &quick->mrr_buf_size, &quick->mrr_flags, &cost))
4330
4233
    goto err;
4331
4234
 
4332
4235
  return quick;
4355
4258
  quick->qr_traversal_ctx.first=  (optimizer::QuickRange**)quick->ranges.buffer;
4356
4259
  quick->qr_traversal_ctx.cur=    (optimizer::QuickRange**)quick->ranges.buffer;
4357
4260
  quick->qr_traversal_ctx.last=   quick->qr_traversal_ctx.cur +
4358
 
                                  quick->ranges.elements;
 
4261
                                  quick->ranges.size();
4359
4262
  return &quick->qr_traversal_ctx;
4360
4263
}
4361
4264
 
4568
4471
get_best_group_min_max(optimizer::Parameter *param, optimizer::SEL_TREE *tree)
4569
4472
{
4570
4473
  Session *session= param->session;
4571
 
  Join *join= session->lex->current_select->join;
 
4474
  Join *join= session->lex().current_select->join;
4572
4475
  Table *table= param->table;
4573
4476
  bool have_min= false;              /* true if there is a MIN function. */
4574
4477
  bool have_max= false;              /* true if there is a MAX function. */
4600
4503
    return NULL;
4601
4504
 
4602
4505
  /* Analyze the query in more detail. */
4603
 
  List_iterator<Item> select_items_it(join->fields_list);
 
4506
  List<Item>::iterator select_items_it(join->fields_list.begin());
4604
4507
 
4605
4508
  /* Check (SA1,SA4) and store the only MIN/MAX argument - the C attribute.*/
4606
4509
  if (join->make_sum_func_list(join->all_fields, join->fields_list, 1))
4756
4659
    */
4757
4660
    else if (join->select_distinct)
4758
4661
    {
4759
 
      select_items_it.rewind();
 
4662
      select_items_it= join->fields_list.begin();
4760
4663
      used_key_parts_map.reset();
4761
4664
      uint32_t max_key_part= 0;
4762
4665
      while ((item= select_items_it++))
4770
4673
        */
4771
4674
        if (used_key_parts_map.test(key_part_nr))
4772
4675
          continue;
4773
 
        if (key_part_nr < 1 || key_part_nr > join->fields_list.elements)
 
4676
        if (key_part_nr < 1 || key_part_nr > join->fields_list.size())
4774
4677
          goto next_index;
4775
4678
        cur_part= cur_index_info->key_part + key_part_nr - 1;
4776
4679
        cur_group_prefix_len+= cur_part->store_length;
4980
4883
    return NULL;
4981
4884
 
4982
4885
  /* The query passes all tests, so construct a new TRP object. */
4983
 
  read_plan=
4984
 
    new(param->mem_root) optimizer::GroupMinMaxReadPlan(have_min,
 
4886
  read_plan= new (*param->mem_root) optimizer::GroupMinMaxReadPlan(have_min,
4985
4887
                                                        have_max,
4986
4888
                                                        min_max_arg_part,
4987
4889
                                                        group_prefix_len,
4995
4897
                                                        best_index_tree,
4996
4898
                                                        best_param_idx,
4997
4899
                                                        best_quick_prefix_records);
4998
 
  if (read_plan)
4999
 
  {
5000
 
    if (tree && read_plan->quick_prefix_records == 0)
5001
 
      return NULL;
5002
 
 
5003
 
    read_plan->read_cost= best_read_cost;
5004
 
    read_plan->records= best_records;
5005
 
  }
5006
 
 
 
4900
  if (tree && read_plan->quick_prefix_records == 0)
 
4901
    return NULL;
 
4902
  read_plan->read_cost= best_read_cost;
 
4903
  read_plan->records= best_records;
5007
4904
  return read_plan;
5008
4905
}
5009
4906
 
5037
4934
  Item::Type cond_type= cond->type();
5038
4935
  if (cond_type == Item::COND_ITEM) /* 'AND' or 'OR' */
5039
4936
  {
5040
 
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
 
4937
    List<Item>::iterator li(((Item_cond*) cond)->argument_list()->begin());
5041
4938
    Item *and_or_arg= NULL;
5042
4939
    while ((and_or_arg= li++))
5043
4940
    {
5469
5366
optimizer::QuickSelectInterface *
5470
5367
optimizer::GroupMinMaxReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
5471
5368
{
5472
 
  optimizer::QuickGroupMinMaxSelect *quick= NULL;
5473
 
 
5474
 
  quick= new optimizer::QuickGroupMinMaxSelect(param->table,
5475
 
                                               param->session->lex->current_select->join,
 
5369
  optimizer::QuickGroupMinMaxSelect *quick= new optimizer::QuickGroupMinMaxSelect(param->table,
 
5370
                                               param->session->lex().current_select->join,
5476
5371
                                               have_min,
5477
5372
                                               have_max,
5478
5373
                                               min_max_arg_part,
5486
5381
                                               key_infix_len,
5487
5382
                                               key_infix,
5488
5383
                                               parent_alloc);
5489
 
  if (! quick)
5490
 
  {
5491
 
    return NULL;
5492
 
  }
5493
 
 
5494
5384
  if (quick->init())
5495
5385
  {
5496
5386
    delete quick;
5557
5447
 
5558
5448
optimizer::QuickSelectInterface *optimizer::RangeReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
5559
5449
{
5560
 
  optimizer::QuickRangeSelect *quick= NULL;
5561
 
  if ((quick= optimizer::get_quick_select(param,
5562
 
                                          key_idx,
5563
 
                                          key,
5564
 
                                          mrr_flags,
5565
 
                                          mrr_buf_size,
5566
 
                                          parent_alloc)))
 
5450
  optimizer::QuickRangeSelect *quick= optimizer::get_quick_select(param, key_idx, key, mrr_flags, mrr_buf_size, parent_alloc);
 
5451
  if (quick)
5567
5452
  {
5568
5453
    quick->records= records;
5569
5454
    quick->read_time= read_cost;
5577
5462
  boost::dynamic_bitset<> map= bitsToBitset();
5578
5463
  for (boost::dynamic_bitset<>::size_type i= 0; i < map.size(); i++)
5579
5464
  {
5580
 
    if (! map.test(i))
5581
 
    {
 
5465
    if (not map.test(i))
5582
5466
      return i;
5583
 
    }
5584
5467
  }
5585
5468
  return map.size();
5586
5469
}
5616
5499
  }
5617
5500
  string final(covered_fields_size - res.length(), '0');
5618
5501
  final.append(res);
5619
 
  return (boost::dynamic_bitset<>(final));
 
5502
  return boost::dynamic_bitset<>(final);
5620
5503
}
5621
5504
 
5622
5505