~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/join.cc

  • Committer: Stewart Smith
  • Date: 2009-08-20 17:15:54 UTC
  • mto: (1119.2.2 merge)
  • mto: This revision was merged to the branch mainline in revision 1124.
  • Revision ID: stewart@flamingspork.com-20090820171554-72eo1tqlc4n64rak
Valgrind 3.5 requires --alignment to be a power of 2 between 16 and 4096. The specifying --alignment is not important for us, so remove it.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 * @{
28
28
 */
29
29
 
30
 
#include "config.h"
31
 
 
32
 
#include <float.h>
33
 
#include <math.h>
34
 
 
 
30
#include "drizzled/server_includes.h"
 
31
#include "drizzled/table_map_iterator.h"
35
32
#include "drizzled/item/cache.h"
36
33
#include "drizzled/item/cmpfunc.h"
37
34
#include "drizzled/item/copy_string.h"
45
42
#include "drizzled/join_cache.h"
46
43
#include "drizzled/show.h"
47
44
#include "drizzled/field/blob.h"
48
 
#include "drizzled/optimizer/position.h"
49
 
#include "drizzled/optimizer/sargable_param.h"
50
 
#include "drizzled/optimizer/key_use.h"
51
 
#include "drizzled/optimizer/range.h"
52
 
#include "drizzled/optimizer/sum.h"
53
 
#include "drizzled/optimizer/explain_plan.h"
54
 
#include "drizzled/records.h"
55
 
#include "drizzled/probes.h"
56
 
#include "drizzled/internal/my_bit.h"
57
 
#include "drizzled/internal/my_sys.h"
58
 
#include "drizzled/internal/iocache.h"
 
45
#include "mysys/my_bit.h"
59
46
 
60
47
#include <algorithm>
61
48
 
62
49
using namespace std;
63
50
 
64
 
namespace drizzled
65
 
{
66
 
 
67
 
extern plugin::StorageEngine *heap_engine;
68
 
extern std::bitset<12> test_flags;
69
 
 
70
51
/** Declarations of static functions used in this source file. */
71
52
static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
72
53
static void calc_group_buffer(JOIN *join,order_st *group);
73
54
static bool alloc_group_fields(JOIN *join,order_st *group);
 
55
/*
 
56
  TODO: 'find_best' is here only temporarily until 'greedy_search' is
 
57
  tested and approved.
 
58
*/
 
59
static bool find_best(JOIN *join,table_map rest_tables,uint32_t index, double record_count,double read_time);
74
60
static uint32_t cache_record_length(JOIN *join, uint32_t index);
75
61
static double prev_record_reads(JOIN *join, uint32_t idx, table_map found_ref);
76
62
static bool get_best_combination(JOIN *join);
77
 
static void set_position(JOIN *join,
78
 
                         uint32_t index,
79
 
                         JoinTable *table,
80
 
                         optimizer::KeyUse *key);
 
63
static void set_position(JOIN *join,uint32_t index,JoinTable *table,KeyUse *key);
81
64
static bool choose_plan(JOIN *join,table_map join_tables);
82
65
static void best_access_path(JOIN *join, JoinTable *s,
83
66
                             Session *session,
97
80
static uint32_t determine_search_depth(JOIN* join);
98
81
static bool make_simple_join(JOIN *join,Table *tmp_table);
99
82
static void make_outerjoin_info(JOIN *join);
100
 
static bool make_join_select(JOIN *join, optimizer::SqlSelect *select,COND *item);
 
83
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
101
84
static bool make_join_readinfo(JOIN *join, uint64_t options, uint32_t no_jbuf_after);
102
85
static void update_depend_map(JOIN *join);
103
86
static void update_depend_map(JOIN *join, order_st *order);
199
182
        select_lex->leaf_tables, fields_list,
200
183
        all_fields, &conds, order, group_list,
201
184
        &hidden_group_fields))
202
 
    return(-1);
 
185
    return(-1);       /* purecov: inspected */
203
186
 
204
187
  ref_pointer_array= *rref_pointer_array;
205
188
 
214
197
        having->check_cols(1)));
215
198
    select_lex->having_fix_field= 0;
216
199
    if (having_fix_rc || session->is_error())
217
 
      return(-1);
 
200
      return(-1);       /* purecov: inspected */
218
201
    session->lex->allow_sum_func= save_allow_sum_func;
219
202
  }
220
203
 
231
214
        in_subs= (Item_in_subselect*)subselect;
232
215
 
233
216
      {
234
 
        bool do_materialize= true;
 
217
        bool do_materialize= !test(session->variables.optimizer_switch &
 
218
                                   OPTIMIZER_SWITCH_NO_MATERIALIZATION);
235
219
        /*
236
220
          Check if the subquery predicate can be executed via materialization.
237
221
          The required conditions are:
249
233
             (Subquery is non-correlated ||
250
234
              Subquery is correlated to any query outer to IN predicate ||
251
235
              (Subquery is correlated to the immediate outer query &&
252
 
               Subquery !contains {GROUP BY, ORDER BY [LIMIT],
 
236
               Subquery !contains {GROUP BY, order_st BY [LIMIT],
253
237
               aggregate functions) && subquery predicate is not under "NOT IN"))
254
238
          6. No execution method was already chosen (by a prepared statement).
255
239
 
335
319
  }
336
320
 
337
321
  if (error)
338
 
    goto err;
 
322
    goto err;         /* purecov: inspected */
339
323
 
340
 
  /* 
341
 
   * The below will create the new table for
342
 
   * CREATE TABLE ... SELECT
343
 
   *
344
 
   * @see create_table_from_items() in drizzled/sql_insert.cc
345
 
   */
346
324
  if (result && result->prepare(fields_list, unit_arg))
347
 
    goto err;
 
325
    goto err;         /* purecov: inspected */
348
326
 
349
327
  /* Init join struct */
350
328
  count_field_types(select_lex, &tmp_table_param, all_fields, 0);
367
345
  return(0); // All OK
368
346
 
369
347
err:
370
 
  return(-1);
 
348
  return(-1);       /* purecov: inspected */
371
349
}
372
350
 
373
351
/*
428
406
{
429
407
  // to prevent double initialization on EXPLAIN
430
408
  if (optimized)
431
 
    return 0;
 
409
    return(0);
432
410
  optimized= 1;
433
411
 
434
412
  session->set_proc_info("optimizing");
504
482
  {
505
483
    int res;
506
484
    /*
507
 
      optimizer::sum_query() returns HA_ERR_KEY_NOT_FOUND if no rows match
 
485
      opt_sum_query() returns HA_ERR_KEY_NOT_FOUND if no rows match
508
486
      to the WHERE conditions,
509
487
      or 1 if all items were resolved,
510
488
      or 0, or an error number HA_ERR_...
511
489
    */
512
 
    if ((res= optimizer::sum_query(select_lex->leaf_tables, all_fields, conds)))
 
490
    if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
513
491
    {
514
492
      if (res == HA_ERR_KEY_NOT_FOUND)
515
493
      {
532
510
      tables_list= 0;       // All tables resolved
533
511
      /*
534
512
        Extract all table-independent conditions and replace the WHERE
535
 
        clause with them. All other conditions were computed by optimizer::sum_query
 
513
        clause with them. All other conditions were computed by opt_sum_query
536
514
        and the MIN/MAX/COUNT function(s) have been replaced by constants,
537
515
        so there is no need to compute the whole WHERE clause again.
538
516
        Notice that make_cond_for_table() will always succeed to remove all
539
 
        computed conditions, because optimizer::sum_query() is applicable only to
 
517
        computed conditions, because opt_sum_query() is applicable only to
540
518
        conjunctions.
541
519
        Preserve conditions for EXPLAIN.
542
520
      */
583
561
  if (!(session->options & OPTION_BIG_SELECTS) &&
584
562
      best_read > (double) session->variables.max_join_size &&
585
563
      !(select_options & SELECT_DESCRIBE))
586
 
  {
 
564
  {           /* purecov: inspected */
587
565
    my_message(ER_TOO_BIG_SELECT, ER(ER_TOO_BIG_SELECT), MYF(0));
588
566
    error= -1;
589
567
    return 1;
595
573
    /* Handle the case where we have an OUTER JOIN without a WHERE */
596
574
    conds=new Item_int((int64_t) 1,1);  // Always true
597
575
  }
598
 
  select= optimizer::make_select(*table, const_table_map,
599
 
                                 const_table_map, conds, 1, &error);
 
576
  select= make_select(*table, const_table_map,
 
577
                      const_table_map, conds, 1, &error);
600
578
  if (error)
601
 
  {
602
 
    error= -1;
 
579
  {           /* purecov: inspected */
 
580
    error= -1;          /* purecov: inspected */
603
581
    return 1;
604
582
  }
605
583
 
639
617
  {
640
618
    conds=new Item_int((int64_t) 0,1);  // Always false
641
619
  }
642
 
 
643
620
  if (make_join_select(this, select, conds))
644
621
  {
645
622
    zero_result_cause=
660
637
    }
661
638
 
662
639
    /*
663
 
      If we are using ORDER BY NULL or ORDER BY const_expression,
 
640
      If we are using order_st BY NULL or order_st BY const_expression,
664
641
      return result in any order (even if we are using a GROUP BY)
665
642
    */
666
643
    if (!order && org_order)
679
656
     The FROM clause must contain a single non-constant table.
680
657
  */
681
658
  if (tables - const_tables == 1 && (group_list || select_distinct) &&
682
 
      ! tmp_table_param.sum_func_count &&
683
 
      (! join_tab[const_tables].select ||
684
 
       ! join_tab[const_tables].select->quick ||
 
659
      !tmp_table_param.sum_func_count &&
 
660
      (!join_tab[const_tables].select ||
 
661
       !join_tab[const_tables].select->quick ||
685
662
       join_tab[const_tables].select->quick->get_type() !=
686
 
       optimizer::QuickSelectInterface::QS_TYPE_GROUP_MIN_MAX))
 
663
       QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX))
687
664
  {
688
665
    if (group_list && list_contains_unique_index(join_tab[const_tables].table, find_field_in_order_list, (void *) group_list))
689
666
    {
691
668
        We have found that grouping can be removed since groups correspond to
692
669
        only one row anyway, but we still have to guarantee correct result
693
670
        order. The line below effectively rewrites the query from GROUP BY
694
 
        <fields> to ORDER BY <fields>. There are two exceptions:
 
671
        <fields> to order_st BY <fields>. There are two exceptions:
695
672
        - if skip_sort_order is set (see above), then we can simply skip
696
673
          GROUP BY;
697
 
        - we can only rewrite ORDER BY if the ORDER BY fields are 'compatible'
 
674
        - we can only rewrite order_st BY if the order_st BY fields are 'compatible'
698
675
          with the GROUP BY ones, i.e. either one is a prefix of another.
699
 
          We only check if the ORDER BY is a prefix of GROUP BY. In this case
 
676
          We only check if the order_st BY is a prefix of GROUP BY. In this case
700
677
          test_if_subpart() copies the ASC/DESC attributes from the original
701
 
          ORDER BY fields.
 
678
          order_st BY fields.
702
679
          If GROUP BY is a prefix of order_st BY, then it is safe to leave
703
680
          'order' as is.
704
681
       */
705
 
      if (! order || test_if_subpart(group_list, order))
 
682
      if (!order || test_if_subpart(group_list, order))
706
683
          order= skip_sort_order ? 0 : group_list;
707
684
      /*
708
685
        If we have an IGNORE INDEX FOR GROUP BY(fields) clause, this must be
737
714
      - We are scanning the whole table without LIMIT
738
715
        This can happen if:
739
716
        - We are using CALC_FOUND_ROWS
740
 
        - We are using an ORDER BY that can't be optimized away.
 
717
        - We are using an order_st BY that can't be optimized away.
741
718
 
742
719
      We don't want to use this optimization when we are using LIMIT
743
720
      because in this case we can just create a temporary table that
769
746
          {
770
747
            /*
771
748
              Force MySQL to read the table in sorted order to get result in
772
 
              ORDER BY order.
 
749
              order_st BY order.
773
750
            */
774
751
            tmp_table_param.quick_group=0;
775
752
          }
826
803
    This has to be done if all tables are not already read (const tables)
827
804
    and one of the following conditions holds:
828
805
    - We are using DISTINCT (simple distinct's are already optimized away)
829
 
    - We are using an ORDER BY or GROUP BY on fields not in the first table
830
 
    - We are using different ORDER BY and GROUP BY orders
 
806
    - We are using an order_st BY or GROUP BY on fields not in the first table
 
807
    - We are using different order_st BY and GROUP BY orders
831
808
    - The user wants us to buffer the result.
832
809
  */
833
810
  need_tmp= (const_tables != tables &&
847
824
  if (setup_subquery_materialization())
848
825
    return 1;
849
826
 
850
 
  /* Cache constant expressions in WHERE, HAVING, ON clauses. */
851
 
  cache_const_exprs();
852
 
 
853
827
  /*
854
828
    is this simple IN subquery?
855
829
  */
1006
980
                                                                     (order_st*) 0);
1007
981
    /*
1008
982
      Pushing LIMIT to the temporary table creation is not applicable
1009
 
      when there is ORDER BY or GROUP BY or there is no GROUP BY, but
 
983
      when there is order_st BY or GROUP BY or there is no GROUP BY, but
1010
984
      there are aggregate functions, because in all these cases we need
1011
985
      all result rows.
1012
986
    */
1108
1082
    */
1109
1083
    if (select_lex->uncacheable && !is_top_level_join() &&
1110
1084
        init_save_join_tab())
1111
 
      return(-1);
 
1085
      return(-1);                         /* purecov: inspected */
1112
1086
  }
1113
1087
 
1114
1088
  error= 0;
1133
1107
 
1134
1108
  if (exec_tmp_table1)
1135
1109
  {
1136
 
    exec_tmp_table1->cursor->extra(HA_EXTRA_RESET_STATE);
1137
 
    exec_tmp_table1->cursor->ha_delete_all_rows();
 
1110
    exec_tmp_table1->file->extra(HA_EXTRA_RESET_STATE);
 
1111
    exec_tmp_table1->file->ha_delete_all_rows();
1138
1112
    exec_tmp_table1->free_io_cache();
1139
1113
    exec_tmp_table1->filesort_free_buffers();
1140
1114
  }
1141
1115
  if (exec_tmp_table2)
1142
1116
  {
1143
 
    exec_tmp_table2->cursor->extra(HA_EXTRA_RESET_STATE);
1144
 
    exec_tmp_table2->cursor->ha_delete_all_rows();
 
1117
    exec_tmp_table2->file->extra(HA_EXTRA_RESET_STATE);
 
1118
    exec_tmp_table2->file->ha_delete_all_rows();
1145
1119
    exec_tmp_table2->free_io_cache();
1146
1120
    exec_tmp_table2->filesort_free_buffers();
1147
1121
  }
1178
1152
bool JOIN::init_save_join_tab()
1179
1153
{
1180
1154
  if (!(tmp_join= (JOIN*)session->alloc(sizeof(JOIN))))
1181
 
    return 1;
 
1155
    return 1;                                  /* purecov: inspected */
1182
1156
  error= 0;              // Ensure that tmp_join.error= 0
1183
1157
  restore_tmp();
1184
1158
  return 0;
1218
1192
  {                                           
1219
1193
    /* Only test of functions */
1220
1194
    if (select_options & SELECT_DESCRIBE)
1221
 
    {
1222
 
      optimizer::ExplainPlan planner(this, 
1223
 
                                     false,
1224
 
                                     false,
1225
 
                                     false,
1226
 
                                     (zero_result_cause ? zero_result_cause : "No tables used"));
1227
 
      planner.printPlan();
1228
 
    }
 
1195
      select_describe(this, false, false, false, (zero_result_cause?zero_result_cause:"No tables used"));
1229
1196
    else
1230
1197
    {
1231
1198
      result->send_fields(*columns_list);
1276
1243
    return;
1277
1244
  }
1278
1245
 
 
1246
  if ((this->select_lex->options & OPTION_SCHEMA_TABLE) && get_schema_tables_result(this, PROCESSED_BY_JOIN_EXEC))
 
1247
    return;
 
1248
 
1279
1249
  if (select_options & SELECT_DESCRIBE)
1280
1250
  {
1281
1251
    /*
1282
 
      Check if we managed to optimize ORDER BY away and don't use temporary
 
1252
      Check if we managed to optimize order_st BY away and don't use temporary
1283
1253
      table to resolve order_st BY: in that case, we only may need to do
1284
1254
      filesort for GROUP BY.
1285
1255
    */
1298
1268
      order= 0;
1299
1269
    }
1300
1270
    having= tmp_having;
1301
 
    optimizer::ExplainPlan planner(this,
1302
 
                                   need_tmp,
1303
 
                                   order != 0 && ! skip_sort_order,
1304
 
                                   select_distinct,
1305
 
                                   ! tables ? "No tables used" : NULL);
1306
 
    planner.printPlan();
 
1271
    select_describe(this, need_tmp, order != 0 && !skip_sort_order,  select_distinct, !tables ? "No tables used" : NULL);
1307
1272
    return;
1308
1273
  }
1309
1274
 
1342
1307
      error= tmp_error;
1343
1308
      return;
1344
1309
    }
1345
 
    curr_tmp_table->cursor->info(HA_STATUS_VARIABLE);
 
1310
    curr_tmp_table->file->info(HA_STATUS_VARIABLE);
1346
1311
 
1347
1312
    if (curr_join->having)
1348
1313
      curr_join->having= curr_join->tmp_having= 0; // Allready done
1585
1550
      if (sort_table_cond)
1586
1551
      {
1587
1552
        if (!curr_table->select)
1588
 
          if (!(curr_table->select= new optimizer::SqlSelect))
 
1553
          if (!(curr_table->select= new SQL_SELECT))
1589
1554
            return;
1590
1555
        if (!curr_table->select->cond)
1591
1556
          curr_table->select->cond= sort_table_cond;
1907
1872
      for (tab= join_tab, end= tab+tables; tab != end; tab++)
1908
1873
      {
1909
1874
        if (tab->table)
1910
 
          tab->table->cursor->ha_index_or_rnd_end();
 
1875
          tab->table->file->ha_index_or_rnd_end();
1911
1876
      }
1912
1877
    }
1913
1878
  }
2360
2325
          item->save_in_result_field(1);
2361
2326
      }
2362
2327
      copy_sum_funcs(sum_funcs_end[i+1], sum_funcs_end[i]);
2363
 
      if ((write_error= table_arg->cursor->ha_write_row(table_arg->record[0])))
 
2328
      if ((write_error= table_arg->file->ha_write_row(table_arg->record[0])))
2364
2329
      {
2365
2330
  if (create_myisam_from_heap(session, table_arg,
2366
2331
                                    tmp_table_param.start_recinfo,
2413
2378
}
2414
2379
 
2415
2380
/**
2416
 
  Cache constant expressions in WHERE, HAVING, ON conditions.
2417
 
*/
2418
 
 
2419
 
void JOIN::cache_const_exprs()
2420
 
{
2421
 
  bool cache_flag= false;
2422
 
  bool *analyzer_arg= &cache_flag;
2423
 
 
2424
 
  /* No need in cache if all tables are constant. */
2425
 
  if (const_tables == tables)
2426
 
    return;
2427
 
 
2428
 
  if (conds)
2429
 
    conds->compile(&Item::cache_const_expr_analyzer, (unsigned char **)&analyzer_arg,
2430
 
                  &Item::cache_const_expr_transformer, (unsigned char *)&cache_flag);
2431
 
  cache_flag= false;
2432
 
  if (having)
2433
 
    having->compile(&Item::cache_const_expr_analyzer, (unsigned char **)&analyzer_arg,
2434
 
                    &Item::cache_const_expr_transformer, (unsigned char *)&cache_flag);
2435
 
 
2436
 
  for (JoinTable *tab= join_tab + const_tables; tab < join_tab + tables ; tab++)
2437
 
  {
2438
 
    if (*tab->on_expr_ref)
2439
 
    {
2440
 
      cache_flag= false;
2441
 
      (*tab->on_expr_ref)->compile(&Item::cache_const_expr_analyzer,
2442
 
                                 (unsigned char **)&analyzer_arg,
2443
 
                                 &Item::cache_const_expr_transformer,
2444
 
                                 (unsigned char *)&cache_flag);
2445
 
    }
2446
 
  }
2447
 
}
2448
 
 
2449
 
/**
2450
2381
  @brief
2451
2382
  
2452
2383
  Process one record of the nested loop join.
2470
2401
  if (join->session->killed)                    // Aborted by user
2471
2402
  {
2472
2403
    join->session->send_kill_message();
2473
 
    return NESTED_LOOP_KILLED;
 
2404
    return NESTED_LOOP_KILLED;               /* purecov: inspected */
2474
2405
  }
2475
2406
  if (!select_cond || select_cond->val_int())
2476
2407
  {
2560
2491
        return NESTED_LOOP_NO_MORE_ROWS;
2561
2492
    }
2562
2493
    else
2563
 
      join_tab->read_record.cursor->unlock_row();
 
2494
      join_tab->read_record.file->unlock_row();
2564
2495
  }
2565
2496
  else
2566
2497
  {
2570
2501
    */
2571
2502
    join->examined_rows++;
2572
2503
    join->session->row_count++;
2573
 
    join_tab->read_record.cursor->unlock_row();
 
2504
    join_tab->read_record.file->unlock_row();
2574
2505
  }
2575
2506
  return NESTED_LOOP_OK;
2576
2507
}
2675
2606
    if (join->session->killed)
2676
2607
    {
2677
2608
      join->session->send_kill_message();
2678
 
      return NESTED_LOOP_KILLED;
 
2609
      return NESTED_LOOP_KILLED; // Aborted by user /* purecov: inspected */
2679
2610
    }
2680
 
    optimizer::SqlSelect *select= join_tab->select;
 
2611
    SQL_SELECT *select=join_tab->select;
2681
2612
    if (rc == NESTED_LOOP_OK &&
2682
2613
        (!join_tab->cache.select || !join_tab->cache.select->skip_record()))
2683
2614
    {
2708
2639
    join_tab->readCachedRecord();               // Restore current record
2709
2640
  reset_cache_write(&join_tab->cache);
2710
2641
  if (error > 0)                                // Fatal error
2711
 
    return NESTED_LOOP_ERROR;
 
2642
    return NESTED_LOOP_ERROR;                   /* purecov: inspected */
2712
2643
  for (JoinTable *tmp2=join->join_tab; tmp2 != join_tab ; tmp2++)
2713
2644
    tmp2->table->status=tmp2->status;
2714
2645
  return NESTED_LOOP_OK;
2749
2680
    if (join->do_send_rows)
2750
2681
      error=join->result->send_data(*join->fields);
2751
2682
    if (error)
2752
 
      return NESTED_LOOP_ERROR;
 
2683
      return NESTED_LOOP_ERROR; /* purecov: inspected */
2753
2684
    if (++join->send_records >= join->unit->select_limit_cnt && join->do_send_rows)
2754
2685
    {
2755
2686
      if (join->select_options & OPTION_FOUND_ROWS)
2758
2689
        if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group
2759
2690
            && !join->send_group_parts && !join->having && !jt->select_cond &&
2760
2691
            !(jt->select && jt->select->quick) &&
2761
 
            (jt->table->cursor->getEngine()->check_flag(HTON_BIT_STATS_RECORDS_IS_EXACT)) &&
 
2692
            (jt->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
2762
2693
                  (jt->ref.key < 0))
2763
2694
        {
2764
2695
          /* Join over all rows in table;  Return number of found rows */
2773
2704
          }
2774
2705
          else
2775
2706
          {
2776
 
            table->cursor->info(HA_STATUS_VARIABLE);
2777
 
            join->send_records= table->cursor->stats.records;
 
2707
            table->file->info(HA_STATUS_VARIABLE);
 
2708
            join->send_records= table->file->stats.records;
2778
2709
          }
2779
2710
        }
2780
2711
        else
2807
2738
  if (join->session->killed)                    // Aborted by user
2808
2739
  {
2809
2740
    join->session->send_kill_message();
2810
 
    return NESTED_LOOP_KILLED;
 
2741
    return NESTED_LOOP_KILLED;             /* purecov: inspected */
2811
2742
  }
2812
2743
  if (!end_of_records)
2813
2744
  {
2817
2748
    {
2818
2749
      int error;
2819
2750
      join->found_records++;
2820
 
      if ((error=table->cursor->ha_write_row(table->record[0])))
 
2751
      if ((error=table->file->ha_write_row(table->record[0])))
2821
2752
      {
2822
 
        if (!table->cursor->is_fatal_error(error, HA_CHECK_DUP))
 
2753
        if (!table->file->is_fatal_error(error, HA_CHECK_DUP))
2823
2754
          goto end;
2824
2755
        if (create_myisam_from_heap(join->session, table,
2825
2756
                                          join->tmp_table_param.start_recinfo,
2854
2785
  if (join->session->killed)                    // Aborted by user
2855
2786
  {
2856
2787
    join->session->send_kill_message();
2857
 
    return NESTED_LOOP_KILLED;
 
2788
    return NESTED_LOOP_KILLED;             /* purecov: inspected */
2858
2789
  }
2859
2790
 
2860
2791
  join->found_records++;
2868
2799
    if (item->maybe_null)
2869
2800
      group->buff[-1]= (char) group->field->is_null();
2870
2801
  }
2871
 
  if (!table->cursor->index_read_map(table->record[1],
 
2802
  if (!table->file->index_read_map(table->record[1],
2872
2803
                                   join->tmp_table_param.group_buff,
2873
2804
                                   HA_WHOLE_KEY,
2874
2805
                                   HA_READ_KEY_EXACT))
2875
2806
  {                                             /* Update old record */
2876
2807
    table->restoreRecord();
2877
2808
    update_tmptable_sum_func(join->sum_funcs,table);
2878
 
    if ((error= table->cursor->ha_update_row(table->record[1],
 
2809
    if ((error= table->file->ha_update_row(table->record[1],
2879
2810
                                          table->record[0])))
2880
2811
    {
2881
 
      table->print_error(error,MYF(0));
2882
 
      return NESTED_LOOP_ERROR;
 
2812
      table->file->print_error(error,MYF(0));   /* purecov: inspected */
 
2813
      return NESTED_LOOP_ERROR;            /* purecov: inspected */
2883
2814
    }
2884
2815
    return NESTED_LOOP_OK;
2885
2816
  }
2899
2830
  }
2900
2831
  init_tmptable_sum_functions(join->sum_funcs);
2901
2832
  copy_funcs(join->tmp_table_param.items_to_copy);
2902
 
  if ((error=table->cursor->ha_write_row(table->record[0])))
 
2833
  if ((error=table->file->ha_write_row(table->record[0])))
2903
2834
  {
2904
2835
    if (create_myisam_from_heap(join->session, table,
2905
2836
                                join->tmp_table_param.start_recinfo,
2907
2838
                                error, 0))
2908
2839
      return NESTED_LOOP_ERROR;            // Not a table_is_full error
2909
2840
    /* Change method to update rows */
2910
 
    table->cursor->ha_index_init(0, 0);
 
2841
    table->file->ha_index_init(0, 0);
2911
2842
    join->join_tab[join->tables-1].next_select= end_unique_update;
2912
2843
  }
2913
2844
  join->send_records++;
2925
2856
  if (join->session->killed)                    // Aborted by user
2926
2857
  {
2927
2858
    join->session->send_kill_message();
2928
 
    return NESTED_LOOP_KILLED;
 
2859
    return NESTED_LOOP_KILLED;             /* purecov: inspected */
2929
2860
  }
2930
2861
 
2931
2862
  init_tmptable_sum_functions(join->sum_funcs);
2932
2863
  copy_fields(&join->tmp_table_param);          // Groups are copied twice.
2933
2864
  copy_funcs(join->tmp_table_param.items_to_copy);
2934
2865
 
2935
 
  if (!(error= table->cursor->ha_write_row(table->record[0])))
 
2866
  if (!(error= table->file->ha_write_row(table->record[0])))
2936
2867
    join->send_records++;                       // New group
2937
2868
  else
2938
2869
  {
2939
 
    if ((int) table->get_dup_key(error) < 0)
 
2870
    if ((int) table->file->get_dup_key(error) < 0)
2940
2871
    {
2941
 
      table->print_error(error,MYF(0));
2942
 
      return NESTED_LOOP_ERROR;
 
2872
      table->file->print_error(error,MYF(0));   /* purecov: inspected */
 
2873
      return NESTED_LOOP_ERROR;            /* purecov: inspected */
2943
2874
    }
2944
 
    if (table->cursor->rnd_pos(table->record[1],table->cursor->dup_ref))
 
2875
    if (table->file->rnd_pos(table->record[1],table->file->dup_ref))
2945
2876
    {
2946
 
      table->print_error(error,MYF(0));
2947
 
      return NESTED_LOOP_ERROR;
 
2877
      table->file->print_error(error,MYF(0));   /* purecov: inspected */
 
2878
      return NESTED_LOOP_ERROR;            /* purecov: inspected */
2948
2879
    }
2949
2880
    table->restoreRecord();
2950
2881
    update_tmptable_sum_func(join->sum_funcs,table);
2951
 
    if ((error= table->cursor->ha_update_row(table->record[1],
 
2882
    if ((error= table->file->ha_update_row(table->record[1],
2952
2883
                                          table->record[0])))
2953
2884
    {
2954
 
      table->print_error(error,MYF(0));
2955
 
      return NESTED_LOOP_ERROR;
 
2885
      table->file->print_error(error,MYF(0));   /* purecov: inspected */
 
2886
      return NESTED_LOOP_ERROR;            /* purecov: inspected */
2956
2887
    }
2957
2888
  }
2958
2889
  return NESTED_LOOP_OK;
3074
3005
  {
3075
3006
    for (; group ; group=group->next)
3076
3007
    {
3077
 
      Cached_item *tmp= new_Cached_item(join->session, *group->item);
 
3008
      Cached_item *tmp=new_Cached_item(join->session, *group->item, false);
3078
3009
      if (!tmp || join->group_fields.push_front(tmp))
3079
3010
        return true;
3080
3011
    }
3083
3014
  return false;
3084
3015
}
3085
3016
 
 
3017
/**
 
3018
  @todo
 
3019
  - TODO: this function is here only temporarily until 'greedy_search' is
 
3020
  tested and accepted.
 
3021
 
 
3022
  RETURN VALUES
 
3023
    false       ok
 
3024
    true        Fatal error
 
3025
*/
 
3026
static bool find_best(JOIN *join,table_map rest_tables,uint32_t idx,double record_count, double read_time)
 
3027
{
 
3028
  Session *session= join->session;
 
3029
  Position partial_pos;
 
3030
  if (session->killed)
 
3031
  {
 
3032
    return true;
 
3033
  }
 
3034
 
 
3035
  if (! rest_tables)
 
3036
  {
 
3037
    read_time+= record_count/(double) TIME_FOR_COMPARE;
 
3038
    partial_pos= join->getPosFromPartialPlan(join->const_tables);
 
3039
    if (join->sort_by_table &&
 
3040
        join->sort_by_table !=
 
3041
        partial_pos.table->table)
 
3042
    {
 
3043
      read_time+= record_count;      // We have to make a temp table
 
3044
    }
 
3045
    if (read_time < join->best_read)
 
3046
    {
 
3047
      join->copyPartialPlanIntoOptimalPlan(idx);
 
3048
      join->best_read= read_time - 0.001;
 
3049
    }
 
3050
    return false;
 
3051
  }
 
3052
  if (read_time+record_count/(double) TIME_FOR_COMPARE >= join->best_read)
 
3053
  {
 
3054
    return false;          /* Found better before */
 
3055
  }
 
3056
 
 
3057
  JoinTable *s;
 
3058
  double best_record_count= DBL_MAX;
 
3059
  double best_read_time= DBL_MAX;
 
3060
  for (JoinTable **pos= join->best_ref+idx ; (s= *pos) ; pos++)
 
3061
  {
 
3062
    table_map real_table_bit= s->table->map;
 
3063
    if (idx)
 
3064
    {
 
3065
      partial_pos= join->getPosFromPartialPlan(idx - 1);
 
3066
    }
 
3067
    if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) &&
 
3068
        (! idx || ! check_interleaving_with_nj(partial_pos.table, s)))
 
3069
    {
 
3070
      double records, best;
 
3071
      best_access_path(join, s, session, rest_tables, idx, record_count,
 
3072
                       read_time);
 
3073
      partial_pos= join->getPosFromPartialPlan(idx);
 
3074
      records= partial_pos.records_read;
 
3075
      best= partial_pos.read_time;
 
3076
      /*
 
3077
         Go to the next level only if there hasn't been a better key on
 
3078
         this level! This will cut down the search for a lot simple cases!
 
3079
       */
 
3080
      double current_record_count= record_count * records;
 
3081
      double current_read_time= read_time + best;
 
3082
      if (best_record_count > current_record_count ||
 
3083
          best_read_time > current_read_time ||
 
3084
          (idx == join->const_tables && s->table == join->sort_by_table))
 
3085
      {
 
3086
        if (best_record_count >= current_record_count &&
 
3087
            best_read_time >= current_read_time &&
 
3088
            (! (s->key_dependent & rest_tables) || 
 
3089
             partial_pos.isConstTable()))
 
3090
        {
 
3091
          best_record_count= current_record_count;
 
3092
          best_read_time= current_read_time;
 
3093
        }
 
3094
        std::swap(join->best_ref[idx], *pos);
 
3095
        if (find_best(join,rest_tables & ~real_table_bit,idx+1,
 
3096
              current_record_count,current_read_time))
 
3097
        {
 
3098
          return true;
 
3099
        }
 
3100
        std::swap(join->best_ref[idx], *pos);
 
3101
      }
 
3102
      restore_prev_nj_state(s);
 
3103
      if (join->select_options & SELECT_STRAIGHT_JOIN)
 
3104
        break;        // Don't test all combinations
 
3105
    }
 
3106
  }
 
3107
  return false;
 
3108
}
 
3109
 
3086
3110
static uint32_t cache_record_length(JOIN *join,uint32_t idx)
3087
3111
{
3088
3112
  uint32_t length=0;
3154
3178
static double prev_record_reads(JOIN *join, uint32_t idx, table_map found_ref)
3155
3179
{
3156
3180
  double found=1.0;
3157
 
  optimizer::Position *pos_end= join->getSpecificPosInPartialPlan(-1);
3158
 
  for (optimizer::Position *pos= join->getSpecificPosInPartialPlan(idx - 1); 
 
3181
  Position *pos_end= join->getSpecificPosInPartialPlan(-1);
 
3182
  for (Position *pos= join->getSpecificPosInPartialPlan(idx - 1); 
3159
3183
       pos != pos_end; 
3160
3184
       pos--)
3161
3185
  {
3162
 
    if (pos->examinePosition(found_ref))
 
3186
    if (pos->table->table->map & found_ref)
3163
3187
    {
3164
 
      found_ref|= pos->getRefDependMap();
 
3188
      found_ref|= pos->ref_depend_map;
3165
3189
      /*
3166
3190
        For the case of "t1 LEFT JOIN t2 ON ..." where t2 is a const table
3167
3191
        with no matching row we will get position[t2].records_read==0.
3178
3202
          is an inprecise estimate and adding 1 (or, in the worst case,
3179
3203
          #max_nested_outer_joins=64-1) will not make it any more precise.
3180
3204
      */
3181
 
      if (pos->getFanout() > DBL_EPSILON)
3182
 
        found*= pos->getFanout();
 
3205
      if (pos->records_read > DBL_EPSILON)
 
3206
        found*= pos->records_read;
3183
3207
    }
3184
3208
  }
3185
3209
  return found;
3193
3217
  uint32_t i,tablenr;
3194
3218
  table_map used_tables;
3195
3219
  JoinTable *join_tab,*j;
3196
 
  optimizer::KeyUse *keyuse;
 
3220
  KeyUse *keyuse;
3197
3221
  uint32_t table_count;
3198
3222
  Session *session=join->session;
3199
 
  optimizer::Position cur_pos;
 
3223
  Position cur_pos;
3200
3224
 
3201
3225
  table_count=join->tables;
3202
3226
  if (!(join->join_tab=join_tab=
3210
3234
  {
3211
3235
    Table *form;
3212
3236
    cur_pos= join->getPosFromOptimalPlan(tablenr);
3213
 
    *j= *cur_pos.getJoinTable();
 
3237
    *j= *cur_pos.table;
3214
3238
    form=join->table[tablenr]=j->table;
3215
3239
    used_tables|= form->map;
3216
3240
    form->reginfo.join_tab=j;
3224
3248
 
3225
3249
    if (j->type == AM_SYSTEM)
3226
3250
      continue;
3227
 
    if (j->keys.none() || ! (keyuse= cur_pos.getKeyUse()))
 
3251
    if (j->keys.none() || !(keyuse= cur_pos.key))
3228
3252
    {
3229
3253
      j->type= AM_ALL;
3230
3254
      if (tablenr != join->const_tables)
3241
3265
}
3242
3266
 
3243
3267
/** Save const tables first as used tables. */
3244
 
static void set_position(JOIN *join,
3245
 
                         uint32_t idx,
3246
 
                         JoinTable *table,
3247
 
                         optimizer::KeyUse *key)
 
3268
static void set_position(JOIN *join,uint32_t idx,JoinTable *table,KeyUse *key)
3248
3269
{
3249
 
  optimizer::Position tmp_pos(1.0, /* This is a const table */
3250
 
                              0.0,
3251
 
                              table,
3252
 
                              key,
3253
 
                              0);
 
3270
  Position tmp_pos;
 
3271
  tmp_pos.table= table;
 
3272
  tmp_pos.key= key;
 
3273
  tmp_pos.records_read= 1.0;  /* This is a const table */
 
3274
  tmp_pos.ref_depend_map= 0;
3254
3275
  join->setPosInPartialPlan(idx, tmp_pos);
3255
3276
 
3256
3277
  /* Move the const table as down as possible in best_ref */
3278
3299
                      the query
3279
3300
  @param join_tables  set of the tables in the query
3280
3301
 
 
3302
  @todo
 
3303
    'MAX_TABLES+2' denotes the old implementation of find_best before
 
3304
    the greedy version. Will be removed when greedy_search is approved.
 
3305
 
3281
3306
  @retval
3282
3307
    false       ok
3283
3308
  @retval
3299
3324
      Apply heuristic: pre-sort all access plans with respect to the number of
3300
3325
      records accessed.
3301
3326
  */
3302
 
  internal::my_qsort(join->best_ref + join->const_tables,
3303
 
                     join->tables - join->const_tables, sizeof(JoinTable*),
3304
 
                     straight_join ? join_tab_cmp_straight : join_tab_cmp);
 
3327
  my_qsort(join->best_ref + join->const_tables,
 
3328
           join->tables - join->const_tables, sizeof(JoinTable*),
 
3329
           straight_join ? join_tab_cmp_straight : join_tab_cmp);
3305
3330
  if (straight_join)
3306
3331
  {
3307
3332
    optimize_straight_join(join, join_tables);
3308
3333
  }
3309
3334
  else
3310
3335
  {
3311
 
    if (search_depth == 0)
3312
 
      /* Automatically determine a reasonable value for 'search_depth' */
3313
 
      search_depth= determine_search_depth(join);
3314
 
    if (greedy_search(join, join_tables, search_depth, prune_level))
3315
 
      return true;
 
3336
    if (search_depth == MAX_TABLES+2)
 
3337
    { /*
 
3338
        TODO: 'MAX_TABLES+2' denotes the old implementation of find_best before
 
3339
        the greedy version. Will be removed when greedy_search is approved.
 
3340
      */
 
3341
      join->best_read= DBL_MAX;
 
3342
      if (find_best(join, join_tables, join->const_tables, 1.0, 0.0))
 
3343
        return(true);
 
3344
    }
 
3345
    else
 
3346
    {
 
3347
      if (search_depth == 0)
 
3348
        /* Automatically determine a reasonable value for 'search_depth' */
 
3349
        search_depth= determine_search_depth(join);
 
3350
      if (greedy_search(join, join_tables, search_depth, prune_level))
 
3351
        return(true);
 
3352
    }
3316
3353
  }
3317
3354
 
3318
3355
  /*
3358
3395
                             double record_count,
3359
3396
                             double)
3360
3397
{
3361
 
  optimizer::KeyUse *best_key= NULL;
3362
 
  uint32_t best_max_key_part= 0;
 
3398
  KeyUse *best_key=         0;
 
3399
  uint32_t best_max_key_part=   0;
3363
3400
  bool found_constraint= 0;
3364
 
  double best= DBL_MAX;
3365
 
  double best_time= DBL_MAX;
3366
 
  double records= DBL_MAX;
 
3401
  double best=              DBL_MAX;
 
3402
  double best_time=         DBL_MAX;
 
3403
  double records=           DBL_MAX;
3367
3404
  table_map best_ref_depends_map= 0;
3368
3405
  double tmp;
3369
3406
  ha_rows rec;
3371
3408
  if (s->keyuse)
3372
3409
  {                                            /* Use key if possible */
3373
3410
    Table *table= s->table;
3374
 
    optimizer::KeyUse *keyuse= NULL;
3375
 
    optimizer::KeyUse *start_key= NULL;
 
3411
    KeyUse *keyuse,*start_key=0;
3376
3412
    double best_records= DBL_MAX;
3377
3413
    uint32_t max_key_part=0;
3378
3414
 
3379
3415
    /* Test how we can use keys */
3380
3416
    rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE;  // Assumed records/key
3381
 
    for (keyuse= s->keyuse; keyuse->getTable() == table; )
 
3417
    for (keyuse=s->keyuse ; keyuse->table == table ;)
3382
3418
    {
3383
3419
      key_part_map found_part= 0;
3384
3420
      table_map found_ref= 0;
3385
 
      uint32_t key= keyuse->getKey();
3386
 
      KEY *keyinfo= table->key_info + key;
 
3421
      uint32_t key= keyuse->key;
 
3422
      KEY *keyinfo= table->key_info+key;
3387
3423
      /* Bitmap of keyparts where the ref access is over 'keypart=const': */
3388
3424
      key_part_map const_part= 0;
3389
3425
      /* The or-null keypart in ref-or-null access: */
3394
3430
 
3395
3431
      do /* For each keypart */
3396
3432
      {
3397
 
        uint32_t keypart= keyuse->getKeypart();
 
3433
        uint32_t keypart= keyuse->keypart;
3398
3434
        table_map best_part_found_ref= 0;
3399
3435
        double best_prev_record_reads= DBL_MAX;
3400
3436
 
3405
3441
            if 1. expression doesn't refer to forward tables
3406
3442
               2. we won't get two ref-or-null's
3407
3443
          */
3408
 
          if (! (remaining_tables & keyuse->getUsedTables()) &&
3409
 
              ! (ref_or_null_part && (keyuse->getOptimizeFlags() &
3410
 
                                      KEY_OPTIMIZE_REF_OR_NULL)))
 
3444
          if (!(remaining_tables & keyuse->used_tables) &&
 
3445
              !(ref_or_null_part && (keyuse->optimize &
 
3446
                                     KEY_OPTIMIZE_REF_OR_NULL)))
3411
3447
          {
3412
 
            found_part|= keyuse->getKeypartMap();
3413
 
            if (! (keyuse->getUsedTables() & ~join->const_table_map))
3414
 
              const_part|= keyuse->getKeypartMap();
 
3448
            found_part|= keyuse->keypart_map;
 
3449
            if (!(keyuse->used_tables & ~join->const_table_map))
 
3450
              const_part|= keyuse->keypart_map;
3415
3451
 
3416
3452
            double tmp2= prev_record_reads(join, idx, (found_ref |
3417
 
                                                       keyuse->getUsedTables()));
 
3453
                                                      keyuse->used_tables));
3418
3454
            if (tmp2 < best_prev_record_reads)
3419
3455
            {
3420
 
              best_part_found_ref= keyuse->getUsedTables() & ~join->const_table_map;
 
3456
              best_part_found_ref= keyuse->used_tables & ~join->const_table_map;
3421
3457
              best_prev_record_reads= tmp2;
3422
3458
            }
3423
 
            if (rec > keyuse->getTableRows())
3424
 
              rec= keyuse->getTableRows();
 
3459
            if (rec > keyuse->ref_table_rows)
 
3460
              rec= keyuse->ref_table_rows;
3425
3461
      /*
3426
3462
        If there is one 'key_column IS NULL' expression, we can
3427
3463
        use this ref_or_null optimisation of this field
3428
3464
      */
3429
 
            if (keyuse->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL)
3430
 
              ref_or_null_part|= keyuse->getKeypartMap();
 
3465
            if (keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL)
 
3466
              ref_or_null_part |= keyuse->keypart_map;
3431
3467
          }
3432
3468
 
3433
3469
          keyuse++;
3434
 
        } while (keyuse->getTable() == table && keyuse->getKey() == key &&
3435
 
                 keyuse->getKeypart() == keypart);
3436
 
        found_ref|= best_part_found_ref;
3437
 
      } while (keyuse->getTable() == table && keyuse->getKey() == key);
 
3470
        } while (keyuse->table == table && keyuse->key == key &&
 
3471
                 keyuse->keypart == keypart);
 
3472
  found_ref|= best_part_found_ref;
 
3473
      } while (keyuse->table == table && keyuse->key == key);
3438
3474
 
3439
3475
      /*
3440
3476
        Assume that that each key matches a proportional part of table.
3525
3561
            if (table->covering_keys.test(key))
3526
3562
            {
3527
3563
              /* we can use only index tree */
3528
 
              tmp= record_count * table->cursor->index_only_read_time(key, tmp);
 
3564
              tmp= record_count * table->file->index_only_read_time(key, tmp);
3529
3565
            }
3530
3566
            else
3531
3567
              tmp= record_count * min(tmp,s->worst_seeks);
3539
3575
            Set tmp to (previous record count) * (records / combination)
3540
3576
          */
3541
3577
          if ((found_part & 1) &&
3542
 
              (!(table->index_flags(key) & HA_ONLY_WHOLE_INDEX) ||
3543
 
               found_part == PREV_BITS(uint, keyinfo->key_parts)))
 
3578
              (!(table->file->index_flags(key, 0, 0) & HA_ONLY_WHOLE_INDEX) ||
 
3579
               found_part == PREV_BITS(uint,keyinfo->key_parts)))
3544
3580
          {
3545
3581
            max_key_part= max_part_bit(found_part);
3546
3582
            /*
3619
3655
              else
3620
3656
              {
3621
3657
                /*
3622
 
                  Assume that the first key part matches 1% of the cursor
 
3658
                  Assume that the first key part matches 1% of the file
3623
3659
                  and that the whole key matches 10 (duplicates) or 1
3624
3660
                  (unique) records.
3625
3661
                  Assume also that more key matches proportionally more
3690
3726
            if (table->covering_keys.test(key))
3691
3727
            {
3692
3728
              /* we can use only index tree */
3693
 
              tmp= record_count * table->cursor->index_only_read_time(key, tmp);
 
3729
              tmp= record_count * table->file->index_only_read_time(key, tmp);
3694
3730
            }
3695
3731
            else
3696
3732
              tmp= record_count * min(tmp,s->worst_seeks);
3742
3778
        scan.
3743
3779
  */
3744
3780
  if ((records >= s->found_records || best > s->read_time) &&            // (1)
3745
 
      ! (s->quick && best_key && s->quick->index == best_key->getKey() &&      // (2)
3746
 
        best_max_key_part >= s->table->quick_key_parts[best_key->getKey()]) &&// (2)
3747
 
      ! ((s->table->cursor->getEngine()->check_flag(HTON_BIT_TABLE_SCAN_ON_INDEX)) &&   // (3)
3748
 
        ! s->table->covering_keys.none() && best_key && !s->quick) && // (3)
3749
 
      ! (s->table->force_index && best_key && !s->quick))                 // (4)
 
3781
      !(s->quick && best_key && s->quick->index == best_key->key &&      // (2)
 
3782
        best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2)
 
3783
      !((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) &&   // (3)
 
3784
        ! s->table->covering_keys.none() && best_key && !s->quick) &&// (3)
 
3785
      !(s->table->force_index && best_key && !s->quick))                 // (4)
3750
3786
  {                                             // Check full join
3751
3787
    ha_rows rnd_records= s->found_records;
3752
3788
    /*
3791
3827
    else
3792
3828
    {
3793
3829
      /* Estimate cost of reading table. */
3794
 
      tmp= s->table->cursor->scan_time();
 
3830
      tmp= s->table->file->scan_time();
3795
3831
      if (s->table->map & join->outer_join)     // Can't use join cache
3796
3832
      {
3797
3833
        /*
3842
3878
  }
3843
3879
 
3844
3880
  /* Update the cost information for the current partial plan */
3845
 
  optimizer::Position tmp_pos(records,
3846
 
                              best,
3847
 
                              s,
3848
 
                              best_key,
3849
 
                              best_ref_depends_map);
 
3881
  Position tmp_pos;
 
3882
  tmp_pos.records_read= records;
 
3883
  tmp_pos.read_time=    best;
 
3884
  tmp_pos.key=          best_key;
 
3885
  tmp_pos.table=        s;
 
3886
  tmp_pos.ref_depend_map= best_ref_depends_map;
3850
3887
  join->setPosInPartialPlan(idx, tmp_pos);
3851
3888
 
3852
3889
  if (!best_key &&
3883
3920
static void optimize_straight_join(JOIN *join, table_map join_tables)
3884
3921
{
3885
3922
  JoinTable *s;
3886
 
  optimizer::Position partial_pos;
 
3923
  Position partial_pos;
3887
3924
  uint32_t idx= join->const_tables;
3888
3925
  double    record_count= 1.0;
3889
3926
  double    read_time=    0.0;
3895
3932
                     record_count, read_time);
3896
3933
    /* compute the cost of the new plan extended with 's' */
3897
3934
    partial_pos= join->getPosFromPartialPlan(idx);
3898
 
    record_count*= partial_pos.getFanout();
3899
 
    read_time+=    partial_pos.getCost();
 
3935
    record_count*= partial_pos.records_read;
 
3936
    read_time+=    partial_pos.read_time;
3900
3937
    join_tables&= ~(s->table->map);
3901
3938
    ++idx;
3902
3939
  }
3904
3941
  read_time+= record_count / (double) TIME_FOR_COMPARE;
3905
3942
  partial_pos= join->getPosFromPartialPlan(join->const_tables);
3906
3943
  if (join->sort_by_table &&
3907
 
      partial_pos.hasTableForSorting(join->sort_by_table))
 
3944
      join->sort_by_table != partial_pos.table->table)
3908
3945
    read_time+= record_count;  // We have to make a temp table
3909
3946
  join->copyPartialPlanIntoOptimalPlan(idx);
3910
3947
  join->best_read= read_time;
4000
4037
  uint32_t      idx= join->const_tables; // index into 'join->best_ref'
4001
4038
  uint32_t      best_idx;
4002
4039
  uint32_t      size_remain;    // cardinality of remaining_tables
4003
 
  optimizer::Position best_pos;
 
4040
  Position best_pos;
4004
4041
  JoinTable  *best_table; // the next plan node to be added to the curr QEP
4005
4042
 
4006
4043
  /* number of tables that remain to be optimized */
4007
 
  size_remain= internal::my_count_bits(remaining_tables);
 
4044
  size_remain= my_count_bits(remaining_tables);
4008
4045
 
4009
4046
  do {
4010
4047
    /* Find the extension of the current QEP with the lowest cost */
4024
4061
 
4025
4062
    /* select the first table in the optimal extension as most promising */
4026
4063
    best_pos= join->getPosFromOptimalPlan(idx);
4027
 
    best_table= best_pos.getJoinTable();
 
4064
    best_table= best_pos.table;
4028
4065
    /*
4029
4066
      Each subsequent loop of 'best_extension_by_limited_search' uses
4030
4067
      'join->positions' for cost estimates, therefore we have to update its
4042
4079
    std::swap(join->best_ref[idx], join->best_ref[best_idx]);
4043
4080
 
4044
4081
    /* compute the cost of the new plan extended with 'best_table' */
4045
 
    optimizer::Position partial_pos= join->getPosFromPartialPlan(idx);
4046
 
    record_count*= partial_pos.getFanout();
4047
 
    read_time+=    partial_pos.getCost();
 
4082
    Position partial_pos= join->getPosFromPartialPlan(idx);
 
4083
    record_count*= partial_pos.records_read;
 
4084
    read_time+=    partial_pos.read_time;
4048
4085
 
4049
4086
    remaining_tables&= ~(best_table->table->map);
4050
4087
    --size_remain;
4188
4225
  JoinTable *s;
4189
4226
  double best_record_count= DBL_MAX;
4190
4227
  double best_read_time=    DBL_MAX;
4191
 
  optimizer::Position partial_pos;
 
4228
  Position partial_pos;
4192
4229
 
4193
4230
  for (JoinTable **pos= join->best_ref + idx ; (s= *pos) ; pos++)
4194
4231
  {
4198
4235
      partial_pos= join->getPosFromPartialPlan(idx - 1);
4199
4236
    }
4200
4237
    if ((remaining_tables & real_table_bit) &&
4201
 
        ! (remaining_tables & s->dependent) &&
4202
 
        (! idx || ! check_interleaving_with_nj(partial_pos.getJoinTable(), s)))
 
4238
        !(remaining_tables & s->dependent) &&
 
4239
        (!idx || !check_interleaving_with_nj(partial_pos.table, s)))
4203
4240
    {
4204
4241
      double current_record_count, current_read_time;
4205
4242
 
4215
4252
                       record_count, read_time);
4216
4253
      /* Compute the cost of extending the plan with 's' */
4217
4254
      partial_pos= join->getPosFromPartialPlan(idx);
4218
 
      current_record_count= record_count * partial_pos.getFanout();
4219
 
      current_read_time=    read_time + partial_pos.getCost();
 
4255
      current_record_count= record_count * partial_pos.records_read;
 
4256
      current_read_time=    read_time + partial_pos.read_time;
4220
4257
 
4221
4258
      /* Expand only partial plans with lower cost than the best QEP so far */
4222
4259
      if ((current_read_time +
4274
4311
        partial_pos= join->getPosFromPartialPlan(join->const_tables);
4275
4312
        current_read_time+= current_record_count / (double) TIME_FOR_COMPARE;
4276
4313
        if (join->sort_by_table &&
4277
 
            partial_pos.hasTableForSorting(join->sort_by_table))
 
4314
            join->sort_by_table !=
 
4315
            partial_pos.table->table)
4278
4316
          /* We have to make a temp table */
4279
4317
          current_read_time+= current_record_count;
4280
4318
        if ((search_depth == 1) || (current_read_time < join->best_read))
4351
4389
  if (!join->table_reexec)
4352
4390
  {
4353
4391
    if (!(join->table_reexec= (Table**) join->session->alloc(sizeof(Table*))))
4354
 
      return(true);
 
4392
      return(true);                        /* purecov: inspected */
4355
4393
    if (join->tmp_join)
4356
4394
      join->tmp_join->table_reexec= join->table_reexec;
4357
4395
  }
4359
4397
  {
4360
4398
    if (!(join->join_tab_reexec=
4361
4399
          (JoinTable*) join->session->alloc(sizeof(JoinTable))))
4362
 
      return(true);
 
4400
      return(true);                        /* purecov: inspected */
4363
4401
    if (join->tmp_join)
4364
4402
      join->tmp_join->join_tab_reexec= join->join_tab_reexec;
4365
4403
  }
4494
4532
  return;
4495
4533
}
4496
4534
 
4497
 
static bool make_join_select(JOIN *join,
4498
 
                             optimizer::SqlSelect *select,
4499
 
                             COND *cond)
 
4535
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
4500
4536
{
4501
4537
  Session *session= join->session;
4502
 
  optimizer::Position cur_pos;
 
4538
  Position cur_pos;
4503
4539
  if (select)
4504
4540
  {
4505
4541
    add_not_null_conds(join);
4579
4615
        tab->ref.key= -1;
4580
4616
        tab->ref.key_parts= 0;          // Don't use ref key.
4581
4617
        cur_pos= join->getPosFromOptimalPlan(i);
4582
 
        cur_pos.setFanout(rows2double(tab->quick->records));
 
4618
        cur_pos.records_read= rows2double(tab->quick->records);
4583
4619
        /*
4584
4620
           We will use join cache here : prevent sorting of the first
4585
4621
           table only and sort at the end.
4617
4653
      if (tmp || !cond || tab->type == AM_REF || tab->type == AM_REF_OR_NULL ||
4618
4654
          tab->type == AM_EQ_REF)
4619
4655
      {
4620
 
        optimizer::SqlSelect *sel= tab->select= ((optimizer::SqlSelect*)
 
4656
        SQL_SELECT *sel= tab->select= ((SQL_SELECT*)
4621
4657
            session->memdup((unsigned char*) select,
4622
4658
              sizeof(*select)));
4623
4659
        if (! sel)
4681
4717
          cur_pos= join->getPosFromOptimalPlan(i);
4682
4718
          if ((cond && (! ((tab->keys & tab->const_keys) == tab->keys) && i > 0)) ||
4683
4719
              (! tab->const_keys.none() && (i == join->const_tables) &&
4684
 
              (join->unit->select_limit_cnt < cur_pos.getFanout()) && ((join->select_options & OPTION_FOUND_ROWS) == false)))
 
4720
              (join->unit->select_limit_cnt < cur_pos.records_read) && ((join->select_options & OPTION_FOUND_ROWS) == false)))
4685
4721
          {
4686
4722
            /* Join with outer join condition */
4687
4723
            COND *orig_cond= sel->cond;
4727
4763
            if (sel->quick)
4728
4764
            {
4729
4765
              cur_pos= join->getPosFromOptimalPlan(i);
4730
 
              cur_pos.setFanout(static_cast<double>(sel->quick->records));
 
4766
              cur_pos.records_read= (double)sel->quick->records;
4731
4767
            }
4732
4768
          }
4733
4769
          else
4755
4791
                                         current_map,
4756
4792
                                         current_map, 0)))
4757
4793
            {
4758
 
              tab->cache.select= (optimizer::SqlSelect*)
4759
 
                session->memdup((unsigned char*) sel, sizeof(optimizer::SqlSelect));
 
4794
              tab->cache.select= (SQL_SELECT*)
 
4795
                session->memdup((unsigned char*) sel, sizeof(SQL_SELECT));
4760
4796
              tab->cache.select->cond= tmp;
4761
4797
              tab->cache.select->read_tables= join->const_table_map;
4762
4798
            }
4884
4920
    Table *table=tab->table;
4885
4921
    bool using_join_cache;
4886
4922
    tab->read_record.table= table;
4887
 
    tab->read_record.cursor= table->cursor;
 
4923
    tab->read_record.file=table->file;
4888
4924
    tab->next_select=sub_select;                /* normal select */
4889
4925
    /*
4890
4926
      TODO: don't always instruct first table's ref/range access method to
4913
4949
          !table->no_keyread)
4914
4950
      {
4915
4951
        table->key_read=1;
4916
 
        table->cursor->extra(HA_EXTRA_KEYREAD);
 
4952
        table->file->extra(HA_EXTRA_KEYREAD);
4917
4953
      }
4918
4954
      break;
4919
4955
    case AM_EQ_REF:
4930
4966
      if (table->covering_keys.test(tab->ref.key) && !table->no_keyread)
4931
4967
      {
4932
4968
        table->key_read=1;
4933
 
        table->cursor->extra(HA_EXTRA_KEYREAD);
 
4969
        table->file->extra(HA_EXTRA_KEYREAD);
4934
4970
      }
4935
4971
      break;
4936
4972
    case AM_REF_OR_NULL:
4946
4982
      if (table->covering_keys.test(tab->ref.key) && !table->no_keyread)
4947
4983
      {
4948
4984
        table->key_read=1;
4949
 
        table->cursor->extra(HA_EXTRA_KEYREAD);
 
4985
        table->file->extra(HA_EXTRA_KEYREAD);
4950
4986
      }
4951
4987
      if (tab->type == AM_REF)
4952
4988
      {
5025
5061
              table->covering_keys.test(tab->select->quick->index))
5026
5062
          {
5027
5063
            table->key_read=1;
5028
 
            table->cursor->extra(HA_EXTRA_KEYREAD);
 
5064
            table->file->extra(HA_EXTRA_KEYREAD);
5029
5065
          }
5030
5066
          else if (!table->covering_keys.none() &&
5031
5067
            !(tab->select && tab->select->quick))
5037
5073
                      is always faster than using a secondary index".
5038
5074
                    */
5039
5075
                    if (table->s->primary_key != MAX_KEY &&
5040
 
                        table->cursor->primary_key_is_clustered())
 
5076
                        table->file->primary_key_is_clustered())
5041
5077
                      tab->index= table->s->primary_key;
5042
5078
                    else
5043
5079
                      tab->index= table->find_shortest_key(&table->covering_keys);
5049
5085
      }
5050
5086
      break;
5051
5087
    default:
5052
 
      break;
 
5088
      break;                                    /* purecov: deadcode */
5053
5089
    case AM_UNKNOWN:
5054
5090
    case AM_MAYBE_REF:
5055
 
      abort();
 
5091
      abort();                                  /* purecov: deadcode */
5056
5092
    }
5057
5093
  }
5058
5094
  join->join_tab[join->tables-1].next_select=0; /* Set by do_select */
5192
5228
{
5193
5229
  if (select_options & SELECT_DESCRIBE)
5194
5230
  {
5195
 
    optimizer::ExplainPlan planner(join,
5196
 
                                   false,
5197
 
                                   false,
5198
 
                                   false,
5199
 
                                   info);
5200
 
    planner.printPlan();
5201
 
    return 0;
 
5231
    select_describe(join, false, false, false, info);
 
5232
    return(0);
5202
5233
  }
5203
5234
 
5204
5235
  join->join_free();
5536
5567
  reclength= entry->s->reclength-offset;
5537
5568
 
5538
5569
  entry->free_io_cache();                               // Safety
5539
 
  entry->cursor->info(HA_STATUS_VARIABLE);
 
5570
  entry->file->info(HA_STATUS_VARIABLE);
5540
5571
  if (entry->s->db_type() == heap_engine ||
5541
5572
      (!entry->s->blob_fields &&
5542
 
       ((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->cursor->stats.records <
 
5573
       ((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->file->stats.records <
5543
5574
        session->variables.sortbuff_size)))
5544
5575
    error= remove_dup_with_hash_index(join->session, entry,
5545
5576
                                     field_count, first_field,
5594
5625
{
5595
5626
  int error;
5596
5627
  Table *table;
5597
 
  uint32_t i;
5598
 
  uint32_t table_count;
5599
 
  uint32_t const_count;
5600
 
  uint32_t key;
5601
 
  table_map found_const_table_map;
5602
 
  table_map all_table_map;
5603
 
  table_map found_ref;
5604
 
  table_map refs;
5605
 
  key_map const_ref;
5606
 
  key_map eq_part;
5607
 
  Table **table_vector= NULL;
5608
 
  JoinTable *stat= NULL;
5609
 
  JoinTable *stat_end= NULL;
5610
 
  JoinTable *s= NULL;
5611
 
  JoinTable **stat_ref= NULL;
5612
 
  optimizer::KeyUse *keyuse= NULL;
5613
 
  optimizer::KeyUse *start_keyuse= NULL;
5614
 
  table_map outer_join= 0;
5615
 
  vector<optimizer::SargableParam> sargables;
 
5628
  uint32_t i,table_count,const_count,key;
 
5629
  table_map found_const_table_map, all_table_map, found_ref, refs;
 
5630
  key_map const_ref, eq_part;
 
5631
  Table **table_vector;
 
5632
  JoinTable *stat,*stat_end,*s,**stat_ref;
 
5633
  KeyUse *keyuse,*start_keyuse;
 
5634
  table_map outer_join=0;
 
5635
  SARGABLE_PARAM *sargables= 0;
5616
5636
  JoinTable *stat_vector[MAX_TABLES+1];
5617
 
  optimizer::Position *partial_pos;
 
5637
  Position *partial_pos;
5618
5638
 
5619
 
  table_count= join->tables;
5620
 
  stat= (JoinTable*) join->session->calloc(sizeof(JoinTable)*table_count);
5621
 
  stat_ref= (JoinTable**) join->session->alloc(sizeof(JoinTable*)*MAX_TABLES);
5622
 
  table_vector= (Table**) join->session->alloc(sizeof(Table*)*(table_count*2));
 
5639
  table_count=join->tables;
 
5640
  stat=(JoinTable*) join->session->calloc(sizeof(JoinTable)*table_count);
 
5641
  stat_ref=(JoinTable**) join->session->alloc(sizeof(JoinTable*)*MAX_TABLES);
 
5642
  table_vector=(Table**) join->session->alloc(sizeof(Table*)*(table_count*2));
5623
5643
  if (! stat || ! stat_ref || ! table_vector)
5624
 
    return 1;
 
5644
    return 1;                           // Eom /* purecov: inspected */
5625
5645
 
5626
5646
  join->best_ref=stat_vector;
5627
5647
 
5641
5661
    s->needed_reg.reset();
5642
5662
    table_vector[i]=s->table=table=tables->table;
5643
5663
    table->pos_in_table_list= tables;
5644
 
    error= table->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
5664
    error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
5645
5665
    if (error)
5646
5666
    {
5647
 
        table->print_error(error, MYF(0));
 
5667
        table->file->print_error(error, MYF(0));
5648
5668
        return 1;
5649
5669
    }
5650
5670
    table->quick_keys.reset();
5658
5678
 
5659
5679
    s->dependent= tables->dep_tables;
5660
5680
    s->key_dependent= 0;
5661
 
    table->quick_condition_rows= table->cursor->stats.records;
 
5681
    if (tables->schema_table)
 
5682
      table->file->stats.records= 2;
 
5683
    table->quick_condition_rows= table->file->stats.records;
5662
5684
 
5663
5685
    s->on_expr_ref= &tables->on_expr;
5664
5686
    if (*s->on_expr_ref)
5665
5687
    {
5666
5688
      /* s is the only inner table of an outer join */
5667
 
      if (!table->cursor->stats.records && !embedding)
 
5689
      if (!table->file->stats.records && !embedding)
5668
5690
      {                                         // Empty table
5669
5691
        s->dependent= 0;                        // Ignore LEFT JOIN depend.
5670
 
        set_position(join, const_count++, s, (optimizer::KeyUse*) 0);
 
5692
        set_position(join,const_count++,s,(KeyUse*) 0);
5671
5693
        continue;
5672
5694
      }
5673
5695
      outer_join|= table->map;
5691
5713
      while (embedding);
5692
5714
      continue;
5693
5715
    }
5694
 
    if ((table->cursor->stats.records <= 1) && !s->dependent &&
5695
 
              (table->cursor->getEngine()->check_flag(HTON_BIT_STATS_RECORDS_IS_EXACT)) &&
 
5716
    if ((table->file->stats.records <= 1) && !s->dependent &&
 
5717
              (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) && 
5696
5718
        !join->no_const_tables)
5697
5719
    {
5698
 
      set_position(join, const_count++, s, (optimizer::KeyUse*) 0);
 
5720
      set_position(join,const_count++,s,(KeyUse*) 0);
5699
5721
    }
5700
5722
  }
5701
5723
  stat_vector[i]=0;
5738
5760
  if (conds || outer_join)
5739
5761
    if (update_ref_and_keys(join->session, keyuse_array, stat, join->tables,
5740
5762
                            conds, join->cond_equal,
5741
 
                            ~outer_join, join->select_lex, sargables))
 
5763
                            ~outer_join, join->select_lex, &sargables))
5742
5764
      return 1;
5743
5765
 
5744
5766
  /* Read tables with 0 or 1 rows (system tables) */
5745
5767
  join->const_table_map= 0;
5746
5768
 
5747
 
  optimizer::Position *p_pos= join->getFirstPosInPartialPlan();
5748
 
  optimizer::Position *p_end= join->getSpecificPosInPartialPlan(const_count);
 
5769
  Position *p_pos= join->getFirstPosInPartialPlan();
 
5770
  Position *p_end= join->getSpecificPosInPartialPlan(const_count);
5749
5771
  while (p_pos < p_end)
5750
5772
  {
5751
5773
    int tmp;
5752
 
    s= p_pos->getJoinTable();
 
5774
    s= p_pos->table;
5753
5775
    s->type= AM_SYSTEM;
5754
5776
    join->const_table_map|=s->table->map;
5755
5777
    if ((tmp= join_read_const_table(s, p_pos)))
5775
5797
      set_position() will move all const_tables first in stat_vector
5776
5798
    */
5777
5799
 
5778
 
    for (JoinTable **pos= stat_vector+const_count; (s= *pos); pos++)
 
5800
    for (JoinTable **pos=stat_vector+const_count ; (s= *pos) ; pos++)
5779
5801
    {
5780
 
      table= s->table;
 
5802
      table=s->table;
5781
5803
 
5782
5804
      /*
5783
5805
        If equi-join condition by a key is null rejecting and after a
5796
5818
          TODO. Apply single row substitution to null complemented inner tables
5797
5819
          for nested outer join operations.
5798
5820
        */
5799
 
        while (keyuse->getTable() == table)
 
5821
        while (keyuse->table == table)
5800
5822
        {
5801
 
          if (! (keyuse->getVal()->used_tables() & ~join->const_table_map) &&
5802
 
              keyuse->getVal()->is_null() && keyuse->isNullRejected())
 
5823
          if (!(keyuse->val->used_tables() & ~join->const_table_map) &&
 
5824
              keyuse->val->is_null() && keyuse->null_rejecting)
5803
5825
          {
5804
5826
            s->type= AM_CONST;
5805
5827
            table->mark_as_null_row();
5806
5828
            found_const_table_map|= table->map;
5807
5829
            join->const_table_map|= table->map;
5808
 
            set_position(join, const_count++, s, (optimizer::KeyUse*) 0);
 
5830
            set_position(join,const_count++,s,(KeyUse*) 0);
5809
5831
            goto more_const_tables_found;
5810
5832
           }
5811
5833
          keyuse++;
5817
5839
        // All dep. must be constants
5818
5840
        if (s->dependent & ~(found_const_table_map))
5819
5841
          continue;
5820
 
        if (table->cursor->stats.records <= 1L &&
5821
 
            (table->cursor->getEngine()->check_flag(HTON_BIT_STATS_RECORDS_IS_EXACT)) &&
 
5842
        if (table->file->stats.records <= 1L &&
 
5843
            (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
5822
5844
                  !table->pos_in_table_list->embedding)
5823
5845
        {                                       // system table
5824
5846
          int tmp= 0;
5825
5847
          s->type= AM_SYSTEM;
5826
5848
          join->const_table_map|=table->map;
5827
 
          set_position(join, const_count++, s, (optimizer::KeyUse*) 0);
 
5849
          set_position(join,const_count++,s,(KeyUse*) 0);
5828
5850
          partial_pos= join->getSpecificPosInPartialPlan(const_count - 1);
5829
5851
          if ((tmp= join_read_const_table(s, partial_pos)))
5830
5852
          {
5840
5862
      if ((keyuse=s->keyuse))
5841
5863
      {
5842
5864
        s->type= AM_REF;
5843
 
        while (keyuse->getTable() == table)
 
5865
        while (keyuse->table == table)
5844
5866
        {
5845
 
          start_keyuse= keyuse;
5846
 
          key= keyuse->getKey();
 
5867
          start_keyuse=keyuse;
 
5868
          key=keyuse->key;
5847
5869
          s->keys.set(key);               // QQ: remove this ?
5848
5870
 
5849
 
          refs= 0;
5850
 
          const_ref.reset();
 
5871
          refs=0;
 
5872
                const_ref.reset();
5851
5873
          eq_part.reset();
5852
5874
          do
5853
5875
          {
5854
 
            if (keyuse->getVal()->type() != Item::NULL_ITEM && 
5855
 
                ! keyuse->getOptimizeFlags())
 
5876
            if (keyuse->val->type() != Item::NULL_ITEM && !keyuse->optimize)
5856
5877
            {
5857
 
              if (! ((~found_const_table_map) & keyuse->getUsedTables()))
5858
 
                const_ref.set(keyuse->getKeypart());
 
5878
              if (!((~found_const_table_map) & keyuse->used_tables))
 
5879
                const_ref.set(keyuse->keypart);
5859
5880
              else
5860
 
                refs|= keyuse->getUsedTables();
5861
 
              eq_part.set(keyuse->getKeypart());
 
5881
                refs|=keyuse->used_tables;
 
5882
              eq_part.set(keyuse->keypart);
5862
5883
            }
5863
5884
            keyuse++;
5864
 
          } while (keyuse->getTable() == table && keyuse->getKey() == key);
 
5885
          } while (keyuse->table == table && keyuse->key == key);
5865
5886
 
5866
5887
          if (is_keymap_prefix(eq_part, table->key_info[key].key_parts) &&
5867
 
              ! table->pos_in_table_list->embedding)
 
5888
              !table->pos_in_table_list->embedding)
5868
5889
          {
5869
5890
            if ((table->key_info[key].flags & (HA_NOSAME)) == HA_NOSAME)
5870
5891
            {
5874
5895
                ref_changed = 1;
5875
5896
                s->type= AM_CONST;
5876
5897
                join->const_table_map|= table->map;
5877
 
                set_position(join, const_count++, s, start_keyuse);
 
5898
                set_position(join,const_count++,s,start_keyuse);
5878
5899
                if (create_ref_for_key(join, s, start_keyuse, found_const_table_map))
5879
5900
                  return 1;
5880
5901
                partial_pos= join->getSpecificPosInPartialPlan(const_count - 1);
5902
5923
    Update info on indexes that can be used for search lookups as
5903
5924
    reading const tables may has added new sargable predicates.
5904
5925
  */
5905
 
  if (const_count && ! sargables.empty())
 
5926
  if (const_count && sargables)
5906
5927
  {
5907
 
    vector<optimizer::SargableParam>::iterator iter= sargables.begin();
5908
 
    while (iter != sargables.end())
 
5928
    for( ; sargables->field ; sargables++)
5909
5929
    {
5910
 
      Field *field= (*iter).getField();
 
5930
      Field *field= sargables->field;
5911
5931
      JoinTable *join_tab= field->table->reginfo.join_tab;
5912
5932
      key_map possible_keys= field->key_start;
5913
5933
      possible_keys&= field->table->keys_in_use_for_query;
5914
 
      bool is_const= true;
5915
 
      for (uint32_t j= 0; j < (*iter).getNumValues(); j++)
5916
 
        is_const&= (*iter).isConstItem(j);
 
5934
      bool is_const= 1;
 
5935
      for (uint32_t j=0; j < sargables->num_values; j++)
 
5936
        is_const&= sargables->arg_value[j]->const_item();
5917
5937
      if (is_const)
5918
5938
        join_tab[0].const_keys|= possible_keys;
5919
 
      ++iter;
5920
5939
    }
5921
5940
  }
5922
5941
 
5931
5950
      continue;
5932
5951
    }
5933
5952
    /* Approximate found rows and time to read them */
5934
 
    s->found_records=s->records=s->table->cursor->stats.records;
5935
 
    s->read_time=(ha_rows) s->table->cursor->scan_time();
 
5953
    s->found_records=s->records=s->table->file->stats.records;
 
5954
    s->read_time=(ha_rows) s->table->file->scan_time();
5936
5955
 
5937
5956
    /*
5938
5957
      Set a max range of how many seeks we can expect when using keys
5954
5973
        !s->table->pos_in_table_list->embedding)
5955
5974
    {
5956
5975
      ha_rows records;
5957
 
      optimizer::SqlSelect *select= NULL;
5958
 
      select= optimizer::make_select(s->table, found_const_table_map, found_const_table_map, *s->on_expr_ref ? *s->on_expr_ref : conds, 1, &error);
 
5976
      SQL_SELECT *select;
 
5977
      select= make_select(s->table, found_const_table_map, found_const_table_map, *s->on_expr_ref ? *s->on_expr_ref : conds, 1, &error);
5959
5978
      if (! select)
5960
5979
        return 1;
5961
5980
      records= get_quick_record_count(join->session, select, s->table, &s->const_keys, join->row_limit);
5971
5990
          caller to abort with a zero row result.
5972
5991
        */
5973
5992
        join->const_table_map|= s->table->map;
5974
 
        set_position(join, const_count++, s, (optimizer::KeyUse*) 0);
 
5993
        set_position(join,const_count++,s,(KeyUse*) 0);
5975
5994
        s->type= AM_CONST;
5976
5995
        if (*s->on_expr_ref)
5977
5996
        {
6001
6020
  if (join->const_tables != join->tables)
6002
6021
  {
6003
6022
    optimize_keyuse(join, keyuse_array);
6004
 
    DRIZZLE_QUERY_OPT_CHOOSE_PLAN_START(join->session->query.c_str(), join->session->thread_id);
6005
 
    bool res= choose_plan(join, all_table_map & ~join->const_table_map);
6006
 
    DRIZZLE_QUERY_OPT_CHOOSE_PLAN_DONE(res ? 1 : 0);
6007
 
    if (res)
6008
 
      return true;
 
6023
    if (choose_plan(join, all_table_map & ~join->const_table_map))
 
6024
      return(true);
6009
6025
  }
6010
6026
  else
6011
6027
  {
6232
6248
    error=(int) cond->add(join_tab->select->cond);
6233
6249
    join_tab->select_cond=join_tab->select->cond=cond;
6234
6250
  }
6235
 
  else if ((join_tab->select= optimizer::make_select(join_tab->table, 0, 0, cond, 0,
6236
 
                                                     &error)))
 
6251
  else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0,
 
6252
                                          &error)))
6237
6253
    join_tab->select_cond=cond;
6238
6254
 
6239
6255
  return(error ? true : false);
6251
6267
/**
6252
6268
  @} (end of group Query_Optimizer)
6253
6269
*/
6254
 
 
6255
 
} /* namespace drizzled */