~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/range.cc

  • Committer: Monty Taylor
  • Date: 2011-02-13 17:24:18 UTC
  • mfrom: (2159.1.1 remove-lint)
  • mto: This revision was merged to the branch mainline in revision 2166.
  • Revision ID: mordred@inaugust.com-20110213172418-vd210j88hiwk8jih
Removed the lint stuff.

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
 
#include <drizzled/session.h>
140
 
 
141
 
#include <drizzled/unique.h>
142
 
 
143
 
#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
 
 
140
#include "drizzled/temporal.h" /* Needed in get_mm_leaf() for timestamp -> datetime comparisons */
144
141
 
145
142
using namespace std;
146
143
namespace drizzled
218
215
  else
219
216
  {
220
217
    double n_blocks=
221
 
      ceil(static_cast<double>(table->cursor->stats.data_file_length) / IO_SIZE);
 
218
      ceil(uint64_t2double(table->cursor->stats.data_file_length) / IO_SIZE);
222
219
    double busy_blocks=
223
 
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, static_cast<double>(nrows)));
 
220
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
224
221
    if (busy_blocks < 1.0)
225
222
      busy_blocks= 1.0;
226
223
 
742
739
    {
743
740
      int key_for_use= head->find_shortest_key(&head->covering_keys);
744
741
      double key_read_time=
745
 
        param.table->cursor->index_only_read_time(key_for_use, records) +
 
742
        param.table->cursor->index_only_read_time(key_for_use,
 
743
                                                rows2double(records)) +
746
744
        (double) records / TIME_FOR_COMPARE;
747
745
      if (key_read_time < read_time)
748
746
        read_time= key_read_time;
812
810
          objects are not allowed so don't use ROR-intersection for
813
811
          table deletes.
814
812
        */
815
 
        if ((session->getLex()->sql_command != SQLCOM_DELETE))
 
813
        if ((session->lex->sql_command != SQLCOM_DELETE))
816
814
        {
817
815
          /*
818
816
            Get best non-covering ROR-intersection plan and prepare data for
840
838
        optimizer::SEL_IMERGE *imerge= NULL;
841
839
        optimizer::TableReadPlan *best_conj_trp= NULL;
842
840
        optimizer::TableReadPlan *new_conj_trp= NULL;
843
 
        List<optimizer::SEL_IMERGE>::iterator it(tree->merges.begin());
 
841
        List_iterator_fast<optimizer::SEL_IMERGE> it(tree->merges);
844
842
        while ((imerge= it++))
845
843
        {
846
844
          new_conj_trp= get_best_disjunct_quick(session, &param, imerge, best_read_time);
1045
1043
  /* Calculate cost(rowid_to_row_scan) */
1046
1044
  {
1047
1045
    optimizer::CostVector sweep_cost;
1048
 
    Join *join= param->session->getLex()->select_lex.join;
 
1046
    Join *join= param->session->lex->select_lex.join;
1049
1047
    bool is_interrupted= test(join && join->tables == 1);
1050
1048
    get_sweep_read_cost(param->table, non_cpk_scan_records, is_interrupted,
1051
1049
                        &sweep_cost);
1088
1086
  }
1089
1087
 
1090
1088
build_ror_index_merge:
1091
 
  if (!all_scans_ror_able || param->session->getLex()->sql_command == SQLCOM_DELETE)
 
1089
  if (!all_scans_ror_able || param->session->lex->sql_command == SQLCOM_DELETE)
1092
1090
    return(imerge_trp);
1093
1091
 
1094
1092
  /* Ok, it is possible to build a ROR-union, try it. */
1121
1119
      cost= param->table->cursor->
1122
1120
              read_time(param->real_keynr[(*cur_child)->key_idx], 1,
1123
1121
                        (*cur_child)->records) +
1124
 
              static_cast<double>((*cur_child)->records) / TIME_FOR_COMPARE;
 
1122
              rows2double((*cur_child)->records) / TIME_FOR_COMPARE;
1125
1123
    }
1126
1124
    else
1127
1125
      cost= read_time;
1163
1161
  double roru_total_cost;
1164
1162
  {
1165
1163
    optimizer::CostVector sweep_cost;
1166
 
    Join *join= param->session->getLex()->select_lex.join;
 
1164
    Join *join= param->session->lex->select_lex.join;
1167
1165
    bool is_interrupted= test(join && join->tables == 1);
1168
1166
    get_sweep_read_cost(param->table, roru_total_records, is_interrupted,
1169
1167
                        &sweep_cost);
1170
1168
    roru_total_cost= roru_index_costs +
1171
 
                     static_cast<double>(roru_total_records)*log((double)n_child_scans) /
 
1169
                     rows2double(roru_total_records)*log((double)n_child_scans) /
1172
1170
                     (TIME_FOR_COMPARE_ROWID * M_LN2) +
1173
1171
                     sweep_cost.total_cost();
1174
1172
  }
1234
1232
    if (param->needed_fields.test(key_part->fieldnr-1))
1235
1233
      tmp_bitset.set(key_part->fieldnr-1);
1236
1234
  }
1237
 
  double rows= param->table->quick_rows[ror_scan->keynr];
 
1235
  double rows= rows2double(param->table->quick_rows[ror_scan->keynr]);
1238
1236
  ror_scan->index_read_cost=
1239
1237
    param->table->cursor->index_only_read_time(ror_scan->keynr, rows);
1240
1238
  ror_scan->covered_fields= tmp_bitset.to_ulong();
1257
1255
 
1258
1256
static int cmp_ror_scan_info(optimizer::RorScanInfo** a, optimizer::RorScanInfo** b)
1259
1257
{
1260
 
  double val1= static_cast<double>((*a)->records) * (*a)->key_rec_length;
1261
 
  double val2= static_cast<double>((*b)->records) * (*b)->key_rec_length;
 
1258
  double val1= rows2double((*a)->records) * (*a)->key_rec_length;
 
1259
  double val2= rows2double((*b)->records) * (*b)->key_rec_length;
1262
1260
  return (val1 < val2)? -1: (val1 == val2)? 0 : 1;
1263
1261
}
1264
1262
 
1494
1492
      if (cur_covered)
1495
1493
      {
1496
1494
        /* uncovered -> covered */
1497
 
        selectivity_mult *= static_cast<double>(records) / prev_records;
 
1495
        double tmp= rows2double(records)/rows2double(prev_records);
 
1496
        selectivity_mult *= tmp;
1498
1497
        prev_records= HA_POS_ERROR;
1499
1498
      }
1500
1499
      else
1507
1506
  }
1508
1507
  if (!prev_covered)
1509
1508
  {
1510
 
    selectivity_mult *= static_cast<double>(info->param->table->quick_rows[scan->keynr]) / prev_records;
 
1509
    double tmp= rows2double(info->param->table->quick_rows[scan->keynr]) /
 
1510
                rows2double(prev_records);
 
1511
    selectivity_mult *= tmp;
1511
1512
  }
1512
 
  return selectivity_mult;
 
1513
  return(selectivity_mult);
1513
1514
}
1514
1515
 
1515
1516
 
1570
1571
      each record of every scan. Assuming 1/TIME_FOR_COMPARE_ROWID
1571
1572
      per check this gives us:
1572
1573
    */
1573
 
    info->index_scan_costs += static_cast<double>(info->index_records) /
 
1574
    info->index_scan_costs += rows2double(info->index_records) /
1574
1575
                              TIME_FOR_COMPARE_ROWID;
1575
1576
  }
1576
1577
  else
1589
1590
  if (! info->is_covering)
1590
1591
  {
1591
1592
    optimizer::CostVector sweep_cost;
1592
 
    Join *join= info->param->session->getLex()->select_lex.join;
 
1593
    Join *join= info->param->session->lex->select_lex.join;
1593
1594
    bool is_interrupted= test(join && join->tables == 1);
1594
1595
    get_sweep_read_cost(info->param->table, double2rows(info->out_rows),
1595
1596
                        is_interrupted, &sweep_cost);
1703
1704
    cost total_cost.
1704
1705
  */
1705
1706
  /* Add priority queue use cost. */
1706
 
  total_cost += static_cast<double>(records) *
 
1707
  total_cost += rows2double(records)*
1707
1708
                log((double)(ror_scan_mark - tree->ror_scans)) /
1708
1709
                (TIME_FOR_COMPARE_ROWID * M_LN2);
1709
1710
 
2565
2566
 
2566
2567
  if (cond->type() == Item::COND_ITEM)
2567
2568
  {
2568
 
    List<Item>::iterator li(((Item_cond*) cond)->argument_list()->begin());
 
2569
    List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
2569
2570
 
2570
2571
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
2571
2572
    {
2977
2978
   * it is, then we must convert to the highest Timestamp value (or lowest,
2978
2979
   * depending on whether the datetime is before or after the epoch.
2979
2980
   */
2980
 
  if (field->is_timestamp())
 
2981
  if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
2981
2982
  {
2982
2983
    /*
2983
2984
     * The left-side of the range comparison is a timestamp field.  Therefore,
3314
3315
  /* dispose index_merge if there is a "range" option */
3315
3316
  if (result_keys.any())
3316
3317
  {
3317
 
    tree1->merges.clear();
 
3318
    tree1->merges.empty();
3318
3319
    return(tree1);
3319
3320
  }
3320
3321
 
3859
3860
      !(pk_is_clustered && keynr == param->table->getShare()->getPrimaryKey()))
3860
3861
     *mrr_flags |= HA_MRR_INDEX_ONLY;
3861
3862
 
3862
 
  if (session->getLex()->sql_command != SQLCOM_SELECT)
 
3863
  if (session->lex->sql_command != SQLCOM_SELECT)
3863
3864
    *mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
3864
3865
 
3865
3866
  *bufsize= param->session->variables.read_rnd_buff_size;
4319
4320
  /* Call multi_range_read_info() to get the MRR flags and buffer size */
4320
4321
  quick->mrr_flags= HA_MRR_NO_ASSOCIATION |
4321
4322
                    (table->key_read ? HA_MRR_INDEX_ONLY : 0);
4322
 
  if (session->getLex()->sql_command != SQLCOM_SELECT)
 
4323
  if (session->lex->sql_command != SQLCOM_SELECT)
4323
4324
    quick->mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
4324
4325
 
4325
4326
  quick->mrr_buf_size= session->variables.read_rnd_buff_size;
4567
4568
get_best_group_min_max(optimizer::Parameter *param, optimizer::SEL_TREE *tree)
4568
4569
{
4569
4570
  Session *session= param->session;
4570
 
  Join *join= session->getLex()->current_select->join;
 
4571
  Join *join= session->lex->current_select->join;
4571
4572
  Table *table= param->table;
4572
4573
  bool have_min= false;              /* true if there is a MIN function. */
4573
4574
  bool have_max= false;              /* true if there is a MAX function. */
4599
4600
    return NULL;
4600
4601
 
4601
4602
  /* Analyze the query in more detail. */
4602
 
  List<Item>::iterator select_items_it(join->fields_list.begin());
 
4603
  List_iterator<Item> select_items_it(join->fields_list);
4603
4604
 
4604
4605
  /* Check (SA1,SA4) and store the only MIN/MAX argument - the C attribute.*/
4605
4606
  if (join->make_sum_func_list(join->all_fields, join->fields_list, 1))
4755
4756
    */
4756
4757
    else if (join->select_distinct)
4757
4758
    {
4758
 
      select_items_it= join->fields_list.begin();
 
4759
      select_items_it.rewind();
4759
4760
      used_key_parts_map.reset();
4760
4761
      uint32_t max_key_part= 0;
4761
4762
      while ((item= select_items_it++))
5036
5037
  Item::Type cond_type= cond->type();
5037
5038
  if (cond_type == Item::COND_ITEM) /* 'AND' or 'OR' */
5038
5039
  {
5039
 
    List<Item>::iterator li(((Item_cond*) cond)->argument_list()->begin());
 
5040
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
5040
5041
    Item *and_or_arg= NULL;
5041
5042
    while ((and_or_arg= li++))
5042
5043
    {
5471
5472
  optimizer::QuickGroupMinMaxSelect *quick= NULL;
5472
5473
 
5473
5474
  quick= new optimizer::QuickGroupMinMaxSelect(param->table,
5474
 
                                               param->session->getLex()->current_select->join,
 
5475
                                               param->session->lex->current_select->join,
5475
5476
                                               have_min,
5476
5477
                                               have_max,
5477
5478
                                               min_max_arg_part,