~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/range.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-12-11 17:49:56 UTC
  • mto: (1241.2.6 build)
  • mto: This revision was merged to the branch mainline in revision 1243.
  • Revision ID: osullivan.padraig@gmail.com-20091211174956-dgwh0c8zjhy6c1j9
Extracted a number of small classes into the table_read_plan.h header file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
123
123
#include "drizzled/optimizer/quick_index_merge_select.h"
124
124
#include "drizzled/optimizer/quick_ror_intersect_select.h"
125
125
#include "drizzled/optimizer/quick_ror_union_select.h"
 
126
#include "drizzled/optimizer/table_read_plan.h"
126
127
#include "drizzled/optimizer/sel_arg.h"
127
128
#include "drizzled/optimizer/range_param.h"
128
129
#include "drizzled/records.h"
277
278
  /* Note that #records for each key scan is stored in table->quick_rows */
278
279
};
279
280
 
280
 
class TABLE_READ_PLAN;
281
 
class TRP_RANGE;
282
 
class TRP_ROR_INTERSECT;
283
 
class TRP_ROR_UNION;
284
 
class TRP_ROR_INDEX_MERGE;
285
 
class TRP_GROUP_MIN_MAX;
286
 
 
287
281
struct st_ror_scan_info;
288
282
 
289
283
static SEL_TREE * get_mm_parts(optimizer::RangeParameter *param,
313
307
                                  uint32_t *bufsize,
314
308
                                  COST_VECT *cost);
315
309
 
316
 
static TRP_RANGE *get_key_scans_params(optimizer::Parameter *param,
317
 
                                       SEL_TREE *tree,
318
 
                                       bool index_read_must_be_used,
319
 
                                       bool update_tbl_stats,
320
 
                                       double read_time);
321
 
 
322
 
static
323
 
TRP_ROR_INTERSECT *get_best_ror_intersect(const optimizer::Parameter *param,
324
 
                                          SEL_TREE *tree,
325
 
                                          double read_time,
326
 
                                          bool *are_all_covering);
327
 
 
328
 
static
329
 
TRP_ROR_INTERSECT *get_best_covering_ror_intersect(optimizer::Parameter *param,
330
 
                                                   SEL_TREE *tree,
331
 
                                                   double read_time);
332
 
 
333
 
static
334
 
TABLE_READ_PLAN *get_best_disjunct_quick(optimizer::Parameter *param,
335
 
                                         SEL_IMERGE *imerge,
336
 
                                         double read_time);
337
 
 
338
 
static
339
 
TRP_GROUP_MIN_MAX *get_best_group_min_max(optimizer::Parameter *param, SEL_TREE *tree);
 
310
static optimizer::TRP_RANGE *get_key_scans_params(optimizer::Parameter *param,
 
311
                                                  SEL_TREE *tree,
 
312
                                                  bool index_read_must_be_used,
 
313
                                                  bool update_tbl_stats,
 
314
                                                  double read_time);
 
315
 
 
316
static
 
317
optimizer::TRP_ROR_INTERSECT *get_best_ror_intersect(const optimizer::Parameter *param,
 
318
                                                     SEL_TREE *tree,
 
319
                                                     double read_time,
 
320
                                                     bool *are_all_covering);
 
321
 
 
322
static
 
323
optimizer::TRP_ROR_INTERSECT *get_best_covering_ror_intersect(optimizer::Parameter *param,
 
324
                                                              SEL_TREE *tree,
 
325
                                                              double read_time);
 
326
 
 
327
static
 
328
optimizer::TABLE_READ_PLAN *get_best_disjunct_quick(optimizer::Parameter *param,
 
329
                                                    SEL_IMERGE *imerge,
 
330
                                                    double read_time);
 
331
 
 
332
static
 
333
optimizer::TRP_GROUP_MIN_MAX *get_best_group_min_max(optimizer::Parameter *param, SEL_TREE *tree);
340
334
 
341
335
static void print_sel_tree(optimizer::Parameter *param,
342
336
                           SEL_TREE *tree,
782
776
}
783
777
 
784
778
 
785
 
/*
786
 
  Table rows retrieval plan. Range optimizer creates QuickSelectInterface-derived
787
 
  objects from table read plans.
788
 
*/
789
 
class TABLE_READ_PLAN
790
 
{
791
 
public:
792
 
  /*
793
 
    Plan read cost, with or without cost of full row retrieval, depending
794
 
    on plan creation parameters.
795
 
  */
796
 
  double read_cost;
797
 
  ha_rows records; /* estimate of #rows to be examined */
798
 
 
799
 
  /*
800
 
    If true, the scan returns rows in rowid order. This is used only for
801
 
    scans that can be both ROR and non-ROR.
802
 
  */
803
 
  bool is_ror;
804
 
 
805
 
  /*
806
 
    Create quick select for this plan.
807
 
    SYNOPSIS
808
 
     make_quick()
809
 
       param               Parameter from test_quick_select
810
 
       retrieve_full_rows  If true, created quick select will do full record
811
 
                           retrieval.
812
 
       parent_alloc        Memory pool to use, if any.
813
 
 
814
 
    NOTES
815
 
      retrieve_full_rows is ignored by some implementations.
816
 
 
817
 
    RETURN
818
 
      created quick select
819
 
      NULL on any error.
820
 
  */
821
 
  virtual optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
822
 
                                                      bool retrieve_full_rows,
823
 
                                                      MEM_ROOT *parent_alloc=NULL) = 0;
824
 
 
825
 
  /* Table read plans are allocated on MEM_ROOT and are never deleted */
826
 
  static void *operator new(size_t size, MEM_ROOT *mem_root)
827
 
  { return (void*) alloc_root(mem_root, (uint32_t) size); }
828
 
  static void operator delete(void *, size_t)
829
 
    { TRASH(ptr, size); }
830
 
  static void operator delete(void *, MEM_ROOT *)
831
 
    { /* Never called */ }
832
 
  virtual ~TABLE_READ_PLAN() {}               /* Remove gcc warning */
833
 
 
834
 
};
835
 
 
836
 
class TRP_ROR_INTERSECT;
837
 
class TRP_ROR_UNION;
838
 
class TRP_INDEX_MERGE;
839
 
 
840
 
 
841
 
/*
842
 
  Plan for a QuickRangeSelect scan.
843
 
  TRP_RANGE::make_quick ignores retrieve_full_rows parameter because
844
 
  QuickRangeSelect doesn't distinguish between 'index only' scans and full
845
 
  record retrieval scans.
846
 
*/
847
 
 
848
 
class TRP_RANGE : public TABLE_READ_PLAN
849
 
{
850
 
public:
851
 
  optimizer::SEL_ARG *key; /* set of intervals to be used in "range" method retrieval */
852
 
  uint32_t     key_idx; /* key number in Parameter::key */
853
 
  uint32_t     mrr_flags;
854
 
  uint32_t     mrr_buf_size;
855
 
 
856
 
  TRP_RANGE(optimizer::SEL_ARG *key_arg, uint32_t idx_arg, uint32_t mrr_flags_arg)
857
 
    :
858
 
      key(key_arg),
859
 
      key_idx(idx_arg),
860
 
      mrr_flags(mrr_flags_arg)
861
 
  {}
862
 
  virtual ~TRP_RANGE() {}                     /* Remove gcc warning */
863
 
 
864
 
  optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param, bool, MEM_ROOT *parent_alloc)
865
 
  {
866
 
    optimizer::QuickRangeSelect *quick= NULL;
867
 
    if ((quick= optimizer::get_quick_select(param,
868
 
                                            key_idx,
869
 
                                            key,
870
 
                                            mrr_flags,
871
 
                                            mrr_buf_size,
872
 
                                            parent_alloc)))
873
 
    {
874
 
      quick->records= records;
875
 
      quick->read_time= read_cost;
876
 
    }
877
 
    return quick;
878
 
  }
879
 
};
880
 
 
881
 
 
882
 
/* Plan for QuickRorIntersectSelect scan. */
883
 
 
884
 
class TRP_ROR_INTERSECT : public TABLE_READ_PLAN
885
 
{
886
 
public:
887
 
  TRP_ROR_INTERSECT() {}                      /* Remove gcc warning */
888
 
  virtual ~TRP_ROR_INTERSECT() {}             /* Remove gcc warning */
889
 
  optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
890
 
                                              bool retrieve_full_rows,
891
 
                                              MEM_ROOT *parent_alloc);
892
 
 
893
 
  /* Array of pointers to ROR range scans used in this intersection */
894
 
  struct st_ror_scan_info **first_scan;
895
 
  struct st_ror_scan_info **last_scan; /* End of the above array */
896
 
  struct st_ror_scan_info *cpk_scan;  /* Clustered PK scan, if there is one */
897
 
  bool is_covering; /* true if no row retrieval phase is necessary */
898
 
  double index_scan_costs; /* SUM(cost(index_scan)) */
899
 
};
900
 
 
901
 
 
902
 
/*
903
 
  Plan for QuickRorUnionSelect scan.
904
 
  QuickRorUnionSelect always retrieves full rows, so retrieve_full_rows
905
 
  is ignored by make_quick.
906
 
*/
907
 
 
908
 
class TRP_ROR_UNION : public TABLE_READ_PLAN
909
 
{
910
 
public:
911
 
  TRP_ROR_UNION() {}                          /* Remove gcc warning */
912
 
  virtual ~TRP_ROR_UNION() {}                 /* Remove gcc warning */
913
 
  optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
914
 
                                              bool retrieve_full_rows,
915
 
                                              MEM_ROOT *parent_alloc);
916
 
  TABLE_READ_PLAN **first_ror; /* array of ptrs to plans for merged scans */
917
 
  TABLE_READ_PLAN **last_ror;  /* end of the above array */
918
 
};
919
 
 
920
 
 
921
 
/*
922
 
  Plan for QuickIndexMergeSelect scan.
923
 
  QuickRorIntersectSelect always retrieves full rows, so retrieve_full_rows
924
 
  is ignored by make_quick.
925
 
*/
926
 
 
927
 
class TRP_INDEX_MERGE : public TABLE_READ_PLAN
928
 
{
929
 
public:
930
 
  TRP_INDEX_MERGE() {}                        /* Remove gcc warning */
931
 
  virtual ~TRP_INDEX_MERGE() {}               /* Remove gcc warning */
932
 
  optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
933
 
                                              bool retrieve_full_rows,
934
 
                                              MEM_ROOT *parent_alloc);
935
 
  TRP_RANGE **range_scans; /* array of ptrs to plans of merged scans */
936
 
  TRP_RANGE **range_scans_end; /* end of the array */
937
 
};
938
 
 
939
 
 
940
 
/*
941
 
  Plan for a QuickGroupMinMaxSelect scan.
942
 
*/
943
 
 
944
 
class TRP_GROUP_MIN_MAX : public TABLE_READ_PLAN
945
 
{
946
 
private:
947
 
  bool have_min, have_max;
948
 
  KEY_PART_INFO *min_max_arg_part;
949
 
  uint32_t group_prefix_len;
950
 
  uint32_t used_key_parts;
951
 
  uint32_t group_key_parts;
952
 
  KEY *index_info;
953
 
  uint32_t index;
954
 
  uint32_t key_infix_len;
955
 
  unsigned char key_infix[MAX_KEY_LENGTH];
956
 
  SEL_TREE *range_tree; /* Represents all range predicates in the query. */
957
 
  optimizer::SEL_ARG  *index_tree; /* The SEL_ARG sub-tree corresponding to index_info. */
958
 
  uint32_t param_idx; /* Index of used key in param->key. */
959
 
  /* Number of records selected by the ranges in index_tree. */
960
 
public:
961
 
  ha_rows quick_prefix_records;
962
 
public:
963
 
  TRP_GROUP_MIN_MAX(bool have_min_arg, bool have_max_arg,
964
 
                    KEY_PART_INFO *min_max_arg_part_arg,
965
 
                    uint32_t group_prefix_len_arg, uint32_t used_key_parts_arg,
966
 
                    uint32_t group_key_parts_arg, KEY *index_info_arg,
967
 
                    uint32_t index_arg, uint32_t key_infix_len_arg,
968
 
                    unsigned char *key_infix_arg,
969
 
                    SEL_TREE *tree_arg, optimizer::SEL_ARG *index_tree_arg,
970
 
                    uint32_t param_idx_arg, ha_rows quick_prefix_records_arg)
971
 
    :
972
 
      have_min(have_min_arg),
973
 
      have_max(have_max_arg),
974
 
      min_max_arg_part(min_max_arg_part_arg),
975
 
      group_prefix_len(group_prefix_len_arg),
976
 
      used_key_parts(used_key_parts_arg),
977
 
      group_key_parts(group_key_parts_arg),
978
 
      index_info(index_info_arg),
979
 
      index(index_arg),
980
 
      key_infix_len(key_infix_len_arg),
981
 
      range_tree(tree_arg),
982
 
      index_tree(index_tree_arg),
983
 
      param_idx(param_idx_arg),
984
 
      quick_prefix_records(quick_prefix_records_arg)
985
 
    {
986
 
      if (key_infix_len)
987
 
        memcpy(this->key_infix, key_infix_arg, key_infix_len);
988
 
    }
989
 
  virtual ~TRP_GROUP_MIN_MAX() {}             /* Remove gcc warning */
990
 
 
991
 
  optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
992
 
                                              bool retrieve_full_rows,
993
 
                                              MEM_ROOT *parent_alloc);
994
 
};
995
 
 
996
779
 
997
780
/*
998
781
  Fill param->needed_fields with bitmap of fields used in the query.
1214
997
        read_time= key_read_time;
1215
998
    }
1216
999
 
1217
 
    TABLE_READ_PLAN *best_trp= NULL;
1218
 
    TRP_GROUP_MIN_MAX *group_trp;
 
1000
    optimizer::TABLE_READ_PLAN *best_trp= NULL;
 
1001
    optimizer::TRP_GROUP_MIN_MAX *group_trp= NULL;
1219
1002
    double best_read_time= read_time;
1220
1003
 
1221
1004
    if (cond)
1261
1044
      */
1262
1045
      if (tree->merges.is_empty())
1263
1046
      {
1264
 
        TRP_RANGE         *range_trp;
1265
 
        TRP_ROR_INTERSECT *rori_trp;
 
1047
        optimizer::TRP_RANGE *range_trp= NULL;
 
1048
        optimizer::TRP_ROR_INTERSECT *rori_trp= NULL;
1266
1049
        bool can_build_covering= false;
1267
1050
 
1268
1051
        /* Get best 'range' plan and prepare data for making other plans */
1304
1087
      {
1305
1088
        /* Try creating index_merge/ROR-union scan. */
1306
1089
        SEL_IMERGE *imerge;
1307
 
        TABLE_READ_PLAN *best_conj_trp= NULL, *new_conj_trp;
 
1090
        optimizer::TABLE_READ_PLAN *best_conj_trp= NULL;
 
1091
        optimizer::TABLE_READ_PLAN *new_conj_trp= NULL;
1308
1092
        List_iterator_fast<SEL_IMERGE> it(tree->merges);
1309
1093
        while ((imerge= it++))
1310
1094
        {
1413
1197
*/
1414
1198
 
1415
1199
static
1416
 
TABLE_READ_PLAN *get_best_disjunct_quick(optimizer::Parameter *param,
1417
 
                                         SEL_IMERGE *imerge,
1418
 
                                         double read_time)
 
1200
optimizer::TABLE_READ_PLAN *get_best_disjunct_quick(optimizer::Parameter *param,
 
1201
                                                    SEL_IMERGE *imerge,
 
1202
                                                    double read_time)
1419
1203
{
1420
1204
  SEL_TREE **ptree;
1421
 
  TRP_INDEX_MERGE *imerge_trp= NULL;
 
1205
  optimizer::TRP_INDEX_MERGE *imerge_trp= NULL;
1422
1206
  uint32_t n_child_scans= imerge->trees_next - imerge->trees;
1423
 
  TRP_RANGE **range_scans;
1424
 
  TRP_RANGE **cur_child;
1425
 
  TRP_RANGE **cpk_scan= NULL;
 
1207
  optimizer::TRP_RANGE **range_scans= NULL;
 
1208
  optimizer::TRP_RANGE **cur_child= NULL;
 
1209
  optimizer::TRP_RANGE **cpk_scan= NULL;
1426
1210
  bool imerge_too_expensive= false;
1427
1211
  double imerge_cost= 0.0;
1428
1212
  ha_rows cpk_scan_records= 0;
1431
1215
  bool all_scans_ror_able= true;
1432
1216
  bool all_scans_rors= true;
1433
1217
  uint32_t unique_calc_buff_size;
1434
 
  TABLE_READ_PLAN **roru_read_plans;
1435
 
  TABLE_READ_PLAN **cur_roru_plan;
 
1218
  optimizer::TABLE_READ_PLAN **roru_read_plans= NULL;
 
1219
  optimizer::TABLE_READ_PLAN **cur_roru_plan= NULL;
1436
1220
  double roru_index_costs;
1437
1221
  ha_rows roru_total_records;
1438
1222
  double roru_intersect_part= 1.0;
1439
1223
 
1440
 
  if (!(range_scans= (TRP_RANGE**)alloc_root(param->mem_root,
1441
 
                                             sizeof(TRP_RANGE*)*
1442
 
                                             n_child_scans)))
 
1224
  if (!(range_scans= (optimizer::TRP_RANGE**)alloc_root(param->mem_root,
 
1225
                                                        sizeof(optimizer::TRP_RANGE*)*
 
1226
                                                        n_child_scans)))
1443
1227
    return NULL;
1444
1228
  /*
1445
1229
    Collect best 'range' scan for each of disjuncts, and, while doing so,
1489
1273
  }
1490
1274
  if (all_scans_rors)
1491
1275
  {
1492
 
    roru_read_plans= (TABLE_READ_PLAN**)range_scans;
 
1276
    roru_read_plans= (optimizer::TABLE_READ_PLAN**)range_scans;
1493
1277
    goto skip_to_ror_scan;
1494
1278
  }
1495
1279
  if (cpk_scan)
1532
1316
                         param->session->variables.sortbuff_size);
1533
1317
  if (imerge_cost < read_time)
1534
1318
  {
1535
 
    if ((imerge_trp= new (param->mem_root)TRP_INDEX_MERGE))
 
1319
    if ((imerge_trp= new (param->mem_root) optimizer::TRP_INDEX_MERGE))
1536
1320
    {
1537
1321
      imerge_trp->read_cost= imerge_cost;
1538
1322
      imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
1551
1335
  /* Ok, it is possible to build a ROR-union, try it. */
1552
1336
  bool dummy;
1553
1337
  if (!(roru_read_plans=
1554
 
          (TABLE_READ_PLAN**)alloc_root(param->mem_root,
1555
 
                                        sizeof(TABLE_READ_PLAN*)*
1556
 
                                        n_child_scans)))
 
1338
          (optimizer::TABLE_READ_PLAN**)alloc_root(param->mem_root,
 
1339
                                                   sizeof(optimizer::TABLE_READ_PLAN*)*
 
1340
                                                   n_child_scans)))
1557
1341
    return(imerge_trp);
1558
1342
skip_to_ror_scan:
1559
1343
  roru_index_costs= 0.0;
1583
1367
    else
1584
1368
      cost= read_time;
1585
1369
 
1586
 
    TABLE_READ_PLAN *prev_plan= *cur_child;
 
1370
    optimizer::TABLE_READ_PLAN *prev_plan= *cur_child;
1587
1371
    if (!(*cur_roru_plan= get_best_ror_intersect(param, *ptree, cost,
1588
1372
                                                 &dummy)))
1589
1373
    {
1595
1379
    }
1596
1380
    else
1597
1381
      roru_index_costs +=
1598
 
        ((TRP_ROR_INTERSECT*)(*cur_roru_plan))->index_scan_costs;
 
1382
        ((optimizer::TRP_ROR_INTERSECT*)(*cur_roru_plan))->index_scan_costs;
1599
1383
    roru_total_records += (*cur_roru_plan)->records;
1600
1384
    roru_intersect_part *= (*cur_roru_plan)->records /
1601
1385
                           param->table->cursor->stats.records;
1630
1414
                     sweep_cost.total_cost();
1631
1415
  }
1632
1416
 
1633
 
  TRP_ROR_UNION* roru;
 
1417
  optimizer::TRP_ROR_UNION *roru= NULL;
1634
1418
  if (roru_total_cost < read_time)
1635
1419
  {
1636
 
    if ((roru= new (param->mem_root) TRP_ROR_UNION))
 
1420
    if ((roru= new (param->mem_root) optimizer::TRP_ROR_UNION))
1637
1421
    {
1638
1422
      roru->first_ror= roru_read_plans;
1639
1423
      roru->last_ror= roru_read_plans + n_child_scans;
1640
1424
      roru->read_cost= roru_total_cost;
1641
1425
      roru->records= roru_total_records;
1642
 
      return(roru);
 
1426
      return roru;
1643
1427
    }
1644
1428
  }
1645
1429
  return(imerge_trp);
2163
1947
*/
2164
1948
 
2165
1949
static
2166
 
TRP_ROR_INTERSECT *get_best_ror_intersect(const optimizer::Parameter *param,
2167
 
                                          SEL_TREE *tree,
2168
 
                                          double read_time,
2169
 
                                          bool *are_all_covering)
 
1950
optimizer::TRP_ROR_INTERSECT *get_best_ror_intersect(const optimizer::Parameter *param,
 
1951
                                                     SEL_TREE *tree,
 
1952
                                                     double read_time,
 
1953
                                                     bool *are_all_covering)
2170
1954
{
2171
1955
  uint32_t idx;
2172
1956
  double min_cost= DBL_MAX;
2289
2073
  }
2290
2074
 
2291
2075
  /* Ok, return ROR-intersect plan if we have found one */
2292
 
  TRP_ROR_INTERSECT *trp= NULL;
 
2076
  optimizer::TRP_ROR_INTERSECT *trp= NULL;
2293
2077
  if (min_cost < read_time && (cpk_scan_used || best_num > 1))
2294
2078
  {
2295
 
    if (!(trp= new (param->mem_root) TRP_ROR_INTERSECT))
2296
 
      return(trp);
2297
 
    if (!(trp->first_scan=
 
2079
    if (! (trp= new (param->mem_root) optimizer::TRP_ROR_INTERSECT))
 
2080
      return trp;
 
2081
 
 
2082
    if (! (trp->first_scan=
2298
2083
           (ROR_SCAN_INFO**)alloc_root(param->mem_root,
2299
2084
                                       sizeof(ROR_SCAN_INFO*)*best_num)))
2300
2085
      return NULL;
2349
2134
*/
2350
2135
 
2351
2136
static
2352
 
TRP_ROR_INTERSECT *get_best_covering_ror_intersect(optimizer::Parameter *param,
2353
 
                                                   SEL_TREE *tree,
2354
 
                                                   double read_time)
 
2137
optimizer::TRP_ROR_INTERSECT *get_best_covering_ror_intersect(optimizer::Parameter *param,
 
2138
                                                              SEL_TREE *tree,
 
2139
                                                              double read_time)
2355
2140
{
2356
2141
  ROR_SCAN_INFO **ror_scan_mark;
2357
2142
  ROR_SCAN_INFO **ror_scans_end= tree->ror_scans_end;
2441
2226
  if (total_cost > read_time)
2442
2227
    return NULL;
2443
2228
 
2444
 
  TRP_ROR_INTERSECT *trp;
2445
 
  if (!(trp= new (param->mem_root) TRP_ROR_INTERSECT))
2446
 
    return(trp);
 
2229
  optimizer::TRP_ROR_INTERSECT *trp= NULL;
 
2230
  if (! (trp= new (param->mem_root) optimizer::TRP_ROR_INTERSECT))
 
2231
  {
 
2232
    return trp;
 
2233
  }
 
2234
 
2447
2235
  uint32_t best_num= (ror_scan_mark - tree->ror_scans);
2448
2236
  if (!(trp->first_scan= (ROR_SCAN_INFO**)alloc_root(param->mem_root,
2449
2237
                                                     sizeof(ROR_SCAN_INFO*)*
2487
2275
    NULL if no plan found or error occurred
2488
2276
*/
2489
2277
 
2490
 
static TRP_RANGE *get_key_scans_params(optimizer::Parameter *param,
2491
 
                                       SEL_TREE *tree,
2492
 
                                       bool index_read_must_be_used,
2493
 
                                       bool update_tbl_stats,
2494
 
                                       double read_time)
 
2278
static optimizer::TRP_RANGE *get_key_scans_params(optimizer::Parameter *param,
 
2279
                                                  SEL_TREE *tree,
 
2280
                                                  bool index_read_must_be_used,
 
2281
                                                  bool update_tbl_stats,
 
2282
                                                  double read_time)
2495
2283
{
2496
2284
  uint32_t idx;
2497
 
  optimizer::SEL_ARG **key,**end, **key_to_read= NULL;
 
2285
  optimizer::SEL_ARG **key= NULL;
 
2286
  optimizer::SEL_ARG **end= NULL;
 
2287
  optimizer::SEL_ARG **key_to_read= NULL;
2498
2288
  ha_rows best_records= 0;
2499
 
  uint32_t    best_mrr_flags= 0, best_buf_size= 0;
2500
 
  TRP_RANGE* read_plan= NULL;
 
2289
  uint32_t best_mrr_flags= 0;
 
2290
  uint32_t best_buf_size= 0;
 
2291
  optimizer::TRP_RANGE *read_plan= NULL;
2501
2292
  /*
2502
2293
    Note that there may be trees that have type SEL_TREE::KEY but contain no
2503
2294
    key reads at all, e.g. tree for expression "key1 is not null" where key1
2546
2337
  if (key_to_read)
2547
2338
  {
2548
2339
    idx= key_to_read - tree->keys;
2549
 
    if ((read_plan= new (param->mem_root) TRP_RANGE(*key_to_read, idx,
2550
 
                                                    best_mrr_flags)))
 
2340
    if ((read_plan= new (param->mem_root) optimizer::TRP_RANGE(*key_to_read, idx,
 
2341
                                                               best_mrr_flags)))
2551
2342
    {
2552
2343
      read_plan->records= best_records;
2553
2344
      read_plan->is_ror= tree->ror_scans_map.test(idx);
2560
2351
}
2561
2352
 
2562
2353
 
2563
 
optimizer::QuickSelectInterface *TRP_INDEX_MERGE::make_quick(optimizer::Parameter *param, bool, MEM_ROOT *)
 
2354
optimizer::QuickSelectInterface *optimizer::TRP_INDEX_MERGE::make_quick(optimizer::Parameter *param, bool, MEM_ROOT *)
2564
2355
{
2565
2356
  optimizer::QuickIndexMergeSelect *quick_imerge;
2566
2357
  optimizer::QuickRangeSelect *quick= NULL;
2572
2363
 
2573
2364
  quick_imerge->records= records;
2574
2365
  quick_imerge->read_time= read_cost;
2575
 
  for (TRP_RANGE **range_scan= range_scans; range_scan != range_scans_end;
 
2366
  for (optimizer::TRP_RANGE **range_scan= range_scans; 
 
2367
       range_scan != range_scans_end;
2576
2368
       range_scan++)
2577
2369
  {
2578
2370
    if (! (quick= (optimizer::QuickRangeSelect*)
2587
2379
  return quick_imerge;
2588
2380
}
2589
2381
 
2590
 
optimizer::QuickSelectInterface *TRP_ROR_INTERSECT::make_quick(optimizer::Parameter *param,
2591
 
                                                         bool retrieve_full_rows,
2592
 
                                                         MEM_ROOT *parent_alloc)
 
2382
optimizer::QuickSelectInterface *optimizer::TRP_ROR_INTERSECT::make_quick(optimizer::Parameter *param,
 
2383
                                                                          bool retrieve_full_rows,
 
2384
                                                                          MEM_ROOT *parent_alloc)
2593
2385
{
2594
2386
  optimizer::QuickRorIntersectSelect *quick_intersect= NULL;
2595
2387
  optimizer::QuickRangeSelect *quick= NULL;
2642
2434
}
2643
2435
 
2644
2436
 
2645
 
optimizer::QuickSelectInterface *TRP_ROR_UNION::make_quick(optimizer::Parameter *param, bool, MEM_ROOT *)
 
2437
optimizer::QuickSelectInterface *optimizer::TRP_ROR_UNION::make_quick(optimizer::Parameter *param, bool, MEM_ROOT *)
2646
2438
{
2647
2439
  optimizer::QuickRorUnionSelect *quick_roru= NULL;
2648
 
  TABLE_READ_PLAN **scan= NULL;
 
2440
  optimizer::TABLE_READ_PLAN **scan= NULL;
2649
2441
  optimizer::QuickSelectInterface *quick= NULL;
2650
2442
  /*
2651
2443
    It is impossible to construct a ROR-union that will not retrieve full
5557
5349
    If mem_root == NULL
5558
5350
    - NULL
5559
5351
*/
5560
 
static TRP_GROUP_MIN_MAX *
 
5352
static optimizer::TRP_GROUP_MIN_MAX *
5561
5353
get_best_group_min_max(optimizer::Parameter *param, SEL_TREE *tree)
5562
5354
{
5563
5355
  Session *session= param->session;
5574
5366
  uint32_t used_key_parts= 0;   /* Number of index key parts used for access. */
5575
5367
  unsigned char key_infix[MAX_KEY_LENGTH]; /* Constants from equality predicates.*/
5576
5368
  uint32_t key_infix_len= 0;          /* Length of key_infix. */
5577
 
  TRP_GROUP_MIN_MAX *read_plan= NULL; /* The eventually constructed TRP. */
 
5369
  optimizer::TRP_GROUP_MIN_MAX *read_plan= NULL; /* The eventually constructed TRP. */
5578
5370
  uint32_t key_part_nr;
5579
5371
  order_st *tmp_group= NULL;
5580
5372
  Item *item= NULL;
5973
5765
 
5974
5766
  /* The query passes all tests, so construct a new TRP object. */
5975
5767
  read_plan=
5976
 
    new(param->mem_root) TRP_GROUP_MIN_MAX(have_min,
5977
 
                                           have_max,
5978
 
                                           min_max_arg_part,
5979
 
                                           group_prefix_len,
5980
 
                                           used_key_parts,
5981
 
                                           group_key_parts,
5982
 
                                           index_info,
5983
 
                                           index,
5984
 
                                           key_infix_len,
5985
 
                                           (key_infix_len > 0) ? key_infix : NULL,
5986
 
                                           tree,
5987
 
                                           best_index_tree,
5988
 
                                           best_param_idx,
5989
 
                                           best_quick_prefix_records);
 
5768
    new(param->mem_root) optimizer::TRP_GROUP_MIN_MAX(have_min,
 
5769
                                                      have_max,
 
5770
                                                      min_max_arg_part,
 
5771
                                                      group_prefix_len,
 
5772
                                                      used_key_parts,
 
5773
                                                      group_key_parts,
 
5774
                                                      index_info,
 
5775
                                                      index,
 
5776
                                                      key_infix_len,
 
5777
                                                      (key_infix_len > 0) ? key_infix : NULL,
 
5778
                                                      tree,
 
5779
                                                      best_index_tree,
 
5780
                                                      best_param_idx,
 
5781
                                                      best_quick_prefix_records);
5990
5782
  if (read_plan)
5991
5783
  {
5992
5784
    if (tree && read_plan->quick_prefix_records == 0)
6459
6251
    NULL otherwise.
6460
6252
*/
6461
6253
optimizer::QuickSelectInterface *
6462
 
TRP_GROUP_MIN_MAX::make_quick(optimizer::Parameter *param, bool, MEM_ROOT *parent_alloc)
 
6254
optimizer::TRP_GROUP_MIN_MAX::make_quick(optimizer::Parameter *param, bool, MEM_ROOT *parent_alloc)
6463
6255
{
6464
6256
  optimizer::QuickGroupMinMaxSelect *quick= NULL;
6465
6257
 
6547
6339
}
6548
6340
 
6549
6341
 
 
6342
optimizer::QuickSelectInterface *optimizer::TRP_RANGE::make_quick(optimizer::Parameter *param, bool, MEM_ROOT *parent_alloc)
 
6343
{
 
6344
  optimizer::QuickRangeSelect *quick= NULL;
 
6345
  if ((quick= optimizer::get_quick_select(param,
 
6346
                                          key_idx,
 
6347
                                          key,
 
6348
                                          mrr_flags,
 
6349
                                          mrr_buf_size,
 
6350
                                          parent_alloc)))
 
6351
  {
 
6352
    quick->records= records;
 
6353
    quick->read_time= read_cost;
 
6354
  }
 
6355
  return quick;
 
6356
}
 
6357
 
 
6358
 
6550
6359
static void print_sel_tree(optimizer::Parameter *param, SEL_TREE *tree, key_map *tree_map, const char *)
6551
6360
{
6552
6361
  optimizer::SEL_ARG **key= NULL;