~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_select.cc

Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
  @defgroup Query_Optimizer  Query Optimizer
23
23
  @{
24
24
*/
25
 
#include "drizzled/server_includes.h"
 
25
#include "config.h"
 
26
 
 
27
#include <string>
 
28
#include <iostream>
 
29
#include <algorithm>
 
30
#include <vector>
 
31
 
26
32
#include "drizzled/sql_select.h" /* include join.h */
27
 
#include "drizzled/table_map_iterator.h"
28
33
 
29
34
#include "drizzled/error.h"
30
35
#include "drizzled/gettext.h"
33
38
#include "drizzled/nested_join.h"
34
39
#include "drizzled/probes.h"
35
40
#include "drizzled/show.h"
36
 
#include "drizzled/info_schema.h"
37
41
#include "drizzled/item/cache.h"
38
42
#include "drizzled/item/cmpfunc.h"
39
43
#include "drizzled/item/copy_string.h"
45
49
#include "drizzled/lock.h"
46
50
#include "drizzled/item/outer_ref.h"
47
51
#include "drizzled/index_hint.h"
48
 
 
49
 
#include <drizzled/sql_union.h>
50
 
#include <drizzled/optimizer/key_field.h>
51
 
#include <drizzled/optimizer/position.h>
52
 
#include <drizzled/optimizer/sargable_param.h>
53
 
 
54
 
#include <string>
55
 
#include <iostream>
56
 
#include <algorithm>
57
 
#include <vector>
 
52
#include "drizzled/memory/multi_malloc.h"
 
53
#include "drizzled/records.h"
 
54
#include "drizzled/internal/iocache.h"
 
55
 
 
56
#include "drizzled/sql_union.h"
 
57
#include "drizzled/optimizer/key_field.h"
 
58
#include "drizzled/optimizer/position.h"
 
59
#include "drizzled/optimizer/sargable_param.h"
 
60
#include "drizzled/optimizer/key_use.h"
 
61
#include "drizzled/optimizer/range.h"
 
62
#include "drizzled/optimizer/quick_range_select.h"
 
63
#include "drizzled/optimizer/quick_ror_intersect_select.h"
58
64
 
59
65
using namespace std;
60
 
using namespace drizzled;
61
66
 
62
 
static const string access_method_str[]=
 
67
namespace drizzled
63
68
{
64
 
  "UNKNOWN",
65
 
  "system",
66
 
  "const",
67
 
  "eq_ref",
68
 
  "ref",
69
 
  "MAYBE_REF",
70
 
  "ALL",
71
 
  "range",
72
 
  "index",
73
 
  "ref_or_null",
74
 
  "unique_subquery",
75
 
  "index_subquery",
76
 
  "index_merge"
77
 
};
78
69
 
79
 
static int sort_keyuse(KeyUse *a,KeyUse *b);
 
70
static int sort_keyuse(optimizer::KeyUse *a, optimizer::KeyUse *b);
80
71
static COND *build_equal_items(Session *session, COND *cond,
81
72
                               COND_EQUAL *inherited,
82
73
                               List<TableList> *join_list,
124
115
{
125
116
  bool res;
126
117
  register Select_Lex *select_lex= &lex->select_lex;
127
 
  DRIZZLE_SELECT_START();
 
118
  DRIZZLE_SELECT_START(session->query.c_str());
128
119
 
129
120
  if (select_lex->master_unit()->is_union() ||
130
121
      select_lex->master_unit()->fake_select_lex)
157
148
  if (unlikely(res))
158
149
    result->abort();
159
150
 
160
 
  DRIZZLE_SELECT_END();
161
 
  return(res);
 
151
  DRIZZLE_SELECT_DONE(res, session->limit_found_rows);
 
152
  return res;
162
153
}
163
154
 
164
155
/*
314
305
/**
315
306
  An entry point to single-unit select (a select without UNION).
316
307
 
317
 
  @param session                  thread handler
 
308
  @param session                  thread Cursor
318
309
  @param rref_pointer_array   a reference to ref_pointer_array of
319
310
                              the top-level select_lex for this query
320
311
  @param tables               list of all tables used in this query.
330
321
                              for a, b and c in this list.
331
322
  @param conds                top level item of an expression representing
332
323
                              WHERE clause of the top level select
333
 
  @param og_num               total number of order_st BY and GROUP BY clauses
 
324
  @param og_num               total number of ORDER BY and GROUP BY clauses
334
325
                              arguments
335
 
  @param order                linked list of order_st BY agruments
 
326
  @param order                linked list of ORDER BY agruments
336
327
  @param group                linked list of GROUP BY arguments
337
328
  @param having               top level item of HAVING expression
338
329
  @param select_options       select options (BIG_RESULT, etc)
355
346
*/
356
347
bool mysql_select(Session *session,
357
348
                  Item ***rref_pointer_array,
358
 
                        TableList *tables, 
 
349
                  TableList *tables, 
359
350
                  uint32_t wild_num, 
360
351
                  List<Item> &fields,
361
 
                        COND *conds, 
 
352
                  COND *conds, 
362
353
                  uint32_t og_num,  
363
354
                  order_st *order, 
364
355
                  order_st *group,
365
 
                        Item *having, 
 
356
                  Item *having, 
366
357
                  uint64_t select_options,
367
 
                        select_result *result, 
 
358
                  select_result *result, 
368
359
                  Select_Lex_Unit *unit,
369
 
                        Select_Lex *select_lex)
 
360
                  Select_Lex *select_lex)
370
361
{
371
362
  bool err;
372
363
  bool free_join= 1;
417
408
    }
418
409
  }
419
410
 
420
 
  if ((err= join->optimize()))
 
411
  err= join->optimize();
 
412
  if (err)
421
413
  {
422
 
    goto err;                                   // 1
 
414
    goto err; // 1
423
415
  }
424
416
 
425
417
  if (session->lex->describe & DESCRIBE_EXTENDED)
471
463
  Create JoinTableS, make a guess about the table types,
472
464
  Approximate how many records will be used in each table
473
465
*****************************************************************************/
474
 
ha_rows get_quick_record_count(Session *session, SQL_SELECT *select, Table *table, const key_map *keys,ha_rows limit)
 
466
ha_rows get_quick_record_count(Session *session, optimizer::SqlSelect *select, Table *table, const key_map *keys,ha_rows limit)
475
467
{
476
468
  int error;
477
469
  if (check_stack_overrun(session, STACK_MIN_SIZE, NULL))
513
505
  return found;
514
506
}
515
507
 
516
 
static int sort_keyuse(KeyUse *a,KeyUse *b)
 
508
static int sort_keyuse(optimizer::KeyUse *a, optimizer::KeyUse *b)
517
509
{
518
510
  int res;
519
 
  if (a->table->tablenr != b->table->tablenr)
520
 
    return (int) (a->table->tablenr - b->table->tablenr);
521
 
  if (a->key != b->key)
522
 
    return (int) (a->key - b->key);
523
 
  if (a->keypart != b->keypart)
524
 
    return (int) (a->keypart - b->keypart);
 
511
  if (a->getTable()->tablenr != b->getTable()->tablenr)
 
512
    return static_cast<int>((a->getTable()->tablenr - b->getTable()->tablenr));
 
513
  if (a->getKey() != b->getKey())
 
514
    return static_cast<int>((a->getKey() - b->getKey()));
 
515
  if (a->getKeypart() != b->getKeypart())
 
516
    return static_cast<int>((a->getKeypart() - b->getKeypart()));
525
517
  // Place const values before other ones
526
 
  if ((res= test((a->used_tables & ~OUTER_REF_TABLE_BIT)) -
527
 
       test((b->used_tables & ~OUTER_REF_TABLE_BIT))))
 
518
  if ((res= test((a->getUsedTables() & ~OUTER_REF_TABLE_BIT)) -
 
519
       test((b->getUsedTables() & ~OUTER_REF_TABLE_BIT))))
528
520
    return res;
529
521
  /* Place rows that are not 'OPTIMIZE_REF_OR_NULL' first */
530
 
  return (int) ((a->optimize & KEY_OPTIMIZE_REF_OR_NULL) -
531
 
                (b->optimize & KEY_OPTIMIZE_REF_OR_NULL));
 
522
  return static_cast<int>(((a->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL) -
 
523
                          (b->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL)));
532
524
}
533
525
 
534
526
 
588
580
      (((session->lex->current_select->cond_count+1) +
589
581
        session->lex->current_select->between_count)*m+1);
590
582
  if (! (key_fields= (optimizer::KeyField*) session->alloc(sz)))
591
 
    return true; /* purecov: inspected */
 
583
    return true;
592
584
  and_level= 0;
593
585
  field= end= key_fields;
594
586
 
595
 
  if (my_init_dynamic_array(keyuse,sizeof(KeyUse),20,64))
 
587
  if (my_init_dynamic_array(keyuse, sizeof(optimizer::KeyUse), 20, 64))
596
588
    return true;
597
589
  if (cond)
598
590
  {
599
591
    add_key_fields(join_tab->join, &end, &and_level, cond, normal_tables,
600
592
                   sargables);
601
 
    for (; field != end ; field++)
 
593
    for (; field != end; field++)
602
594
    {
603
 
      add_key_part(keyuse,field);
 
595
      add_key_part(keyuse, field);
604
596
      /* Mark that we can optimize LEFT JOIN */
605
 
      if (field->val->type() == Item::NULL_ITEM &&
606
 
          !field->field->real_maybe_null())
607
 
        field->field->table->reginfo.not_exists_optimize=1;
 
597
      if (field->getValue()->type() == Item::NULL_ITEM &&
 
598
          ! field->getField()->real_maybe_null())
 
599
      {
 
600
        field->getField()->table->reginfo.not_exists_optimize= 1;
 
601
      }
608
602
    }
609
603
  }
610
 
  for (i=0 ; i < tables ; i++)
 
604
  for (i= 0; i < tables; i++)
611
605
  {
612
606
    /*
613
607
      Block the creation of keys for inner tables of outer joins.
651
645
  */
652
646
  if (keyuse->elements)
653
647
  {
654
 
    KeyUse key_end,*prev,*save_pos,*use;
 
648
    optimizer::KeyUse key_end,*prev,*save_pos,*use;
655
649
 
656
 
    my_qsort(keyuse->buffer,keyuse->elements,sizeof(KeyUse),
657
 
          (qsort_cmp) sort_keyuse);
 
650
    internal::my_qsort(keyuse->buffer,keyuse->elements,sizeof(optimizer::KeyUse),
 
651
                       (qsort_cmp) sort_keyuse);
658
652
 
659
653
    memset(&key_end, 0, sizeof(key_end)); /* Add for easy testing */
660
654
    insert_dynamic(keyuse,(unsigned char*) &key_end);
661
655
 
662
 
    use=save_pos=dynamic_element(keyuse,0,KeyUse*);
 
656
    use= save_pos= dynamic_element(keyuse, 0, optimizer::KeyUse*);
663
657
    prev= &key_end;
664
 
    found_eq_constant=0;
665
 
    for (i=0 ; i < keyuse->elements-1 ; i++,use++)
 
658
    found_eq_constant= 0;
 
659
    for (i= 0; i < keyuse->elements-1; i++, use++)
666
660
    {
667
 
      if (!use->used_tables && use->optimize != KEY_OPTIMIZE_REF_OR_NULL)
668
 
        use->table->const_key_parts[use->key]|= use->keypart_map;
669
 
      if (use->key == prev->key && use->table == prev->table)
 
661
      if (! use->getUsedTables() && use->getOptimizeFlags() != KEY_OPTIMIZE_REF_OR_NULL)
 
662
        use->getTable()->const_key_parts[use->getKey()]|= use->getKeypartMap();
 
663
      if (use->getKey() == prev->getKey() && use->getTable() == prev->getTable())
670
664
      {
671
 
        if (prev->keypart+1 < use->keypart || ((prev->keypart == use->keypart) && found_eq_constant))
 
665
        if (prev->getKeypart() + 1 < use->getKeypart() || 
 
666
            ((prev->getKeypart() == use->getKeypart()) && found_eq_constant))
672
667
          continue;                             /* remove */
673
668
      }
674
 
      else if (use->keypart != 0)               // First found must be 0
 
669
      else if (use->getKeypart() != 0)          // First found must be 0
675
670
        continue;
676
671
 
677
672
#ifdef HAVE_purify
680
675
#endif
681
676
        *save_pos= *use;
682
677
      prev=use;
683
 
      found_eq_constant= !use->used_tables;
 
678
      found_eq_constant= ! use->getUsedTables();
684
679
      /* Save ptr to first use */
685
 
      if (!use->table->reginfo.join_tab->keyuse)
686
 
        use->table->reginfo.join_tab->keyuse=save_pos;
687
 
      use->table->reginfo.join_tab->checked_keys.set(use->key);
 
680
      if (! use->getTable()->reginfo.join_tab->keyuse)
 
681
        use->getTable()->reginfo.join_tab->keyuse= save_pos;
 
682
      use->getTable()->reginfo.join_tab->checked_keys.set(use->getKey());
688
683
      save_pos++;
689
684
    }
690
 
    i=(uint32_t) (save_pos-(KeyUse*) keyuse->buffer);
691
 
    set_dynamic(keyuse,(unsigned char*) &key_end,i);
692
 
    keyuse->elements=i;
 
685
    i= (uint32_t) (save_pos - (optimizer::KeyUse*) keyuse->buffer);
 
686
    set_dynamic(keyuse, (unsigned char*) &key_end, i);
 
687
    keyuse->elements= i;
693
688
  }
694
689
  return false;
695
690
}
699
694
*/
700
695
void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
701
696
{
702
 
  KeyUse *end,*keyuse= dynamic_element(keyuse_array, 0, KeyUse*);
 
697
  optimizer::KeyUse *end,*keyuse= dynamic_element(keyuse_array, 
 
698
                                                  0, 
 
699
                                                  optimizer::KeyUse*);
703
700
 
704
701
  for (end= keyuse+ keyuse_array->elements ; keyuse < end ; keyuse++)
705
702
  {
712
709
      Constant tables are ignored.
713
710
      To avoid bad matches, we don't make ref_table_rows less than 100.
714
711
    */
715
 
    keyuse->ref_table_rows= ~(ha_rows) 0;       // If no ref
716
 
    if (keyuse->used_tables & (map= (keyuse->used_tables & ~join->const_table_map & ~OUTER_REF_TABLE_BIT)))
 
712
    keyuse->setTableRows(~(ha_rows) 0); // If no ref
 
713
    if (keyuse->getUsedTables() & (map= (keyuse->getUsedTables() & ~join->const_table_map & ~OUTER_REF_TABLE_BIT)))
717
714
    {
718
715
      uint32_t tablenr;
719
716
      for (tablenr=0 ; ! (map & 1) ; map>>=1, tablenr++) ;
720
717
      if (map == 1)                     // Only one table
721
718
      {
722
719
        Table *tmp_table=join->all_tables[tablenr];
723
 
        keyuse->ref_table_rows= max(tmp_table->file->stats.records, (ha_rows)100);
 
720
        keyuse->setTableRows(max(tmp_table->cursor->stats.records, (ha_rows)100));
724
721
      }
725
722
    }
726
723
    /*
727
724
      Outer reference (external field) is constant for single executing
728
725
      of subquery
729
726
    */
730
 
    if (keyuse->used_tables == OUTER_REF_TABLE_BIT)
731
 
      keyuse->ref_table_rows= 1;
 
727
    if (keyuse->getUsedTables() == OUTER_REF_TABLE_BIT)
 
728
      keyuse->setTableRows(1);
732
729
  }
733
730
}
734
731
 
874
871
    rec_length+=sizeof(bool);
875
872
  if (blobs)
876
873
  {
877
 
    uint32_t blob_length=(uint32_t) (join_tab->table->file->stats.mean_rec_length-
 
874
    uint32_t blob_length=(uint32_t) (join_tab->table->cursor->stats.mean_rec_length-
878
875
                                     (join_tab->table->getRecordLength()- rec_length));
879
876
    rec_length+= max((uint32_t)4,blob_length);
880
877
  }
884
881
}
885
882
 
886
883
StoredKey *get_store_key(Session *session,
887
 
                         KeyUse *keyuse,
 
884
                         optimizer::KeyUse *keyuse,
888
885
                         table_map used_tables,
889
 
                               KEY_PART_INFO *key_part,
 
886
                         KEY_PART_INFO *key_part,
890
887
                         unsigned char *key_buff,
891
888
                         uint32_t maybe_null)
892
889
{
893
 
  if (!((~used_tables) & keyuse->used_tables))          // if const item
 
890
  Item_ref *key_use_val= static_cast<Item_ref *>(keyuse->getVal());
 
891
  if (! ((~used_tables) & keyuse->getUsedTables())) // if const item
894
892
  {
895
893
    return new store_key_const_item(session,
896
894
                                    key_part->field,
897
895
                                    key_buff + maybe_null,
898
896
                                    maybe_null ? key_buff : 0,
899
897
                                    key_part->length,
900
 
                                    keyuse->val);
 
898
                                    key_use_val);
901
899
  }
902
 
  else if (keyuse->val->type() == Item::FIELD_ITEM ||
903
 
           (keyuse->val->type() == Item::REF_ITEM &&
904
 
            ((Item_ref*)keyuse->val)->ref_type() == Item_ref::OUTER_REF &&
905
 
            (*(Item_ref**)((Item_ref*)keyuse->val)->ref)->ref_type() ==
906
 
             Item_ref::DIRECT_REF &&
907
 
            keyuse->val->real_item()->type() == Item::FIELD_ITEM))
 
900
  else if (key_use_val->type() == Item::FIELD_ITEM ||
 
901
           (key_use_val->type() == Item::REF_ITEM &&
 
902
            key_use_val->ref_type() == Item_ref::OUTER_REF &&
 
903
            (*(Item_ref**)((Item_ref*)key_use_val)->ref)->ref_type() == Item_ref::DIRECT_REF &&
 
904
            key_use_val->real_item()->type() == Item::FIELD_ITEM))
 
905
  {
908
906
    return new store_key_field(session,
909
907
                               key_part->field,
910
908
                               key_buff + maybe_null,
911
909
                               maybe_null ? key_buff : 0,
912
910
                               key_part->length,
913
 
                               ((Item_field*) keyuse->val->real_item())->field,
914
 
                               keyuse->val->full_name());
 
911
                               ((Item_field*) key_use_val->real_item())->field,
 
912
                               key_use_val->full_name());
 
913
  }
915
914
  return new store_key_item(session,
916
915
                            key_part->field,
917
916
                            key_buff + maybe_null,
918
917
                            maybe_null ? key_buff : 0,
919
918
                            key_part->length,
920
 
                            keyuse->val);
 
919
                            key_use_val);
921
920
}
922
921
 
923
922
/**
960
959
    *e1= e2;
961
960
}
962
961
 
963
 
bool create_ref_for_key(JOIN *join, JoinTable *j, KeyUse *org_keyuse,
964
 
             table_map used_tables)
 
962
bool create_ref_for_key(JOIN *join, 
 
963
                        JoinTable *j, 
 
964
                        optimizer::KeyUse *org_keyuse,
 
965
                        table_map used_tables)
965
966
{
966
 
  KeyUse *keyuse=org_keyuse;
 
967
  optimizer::KeyUse *keyuse= org_keyuse;
967
968
  Session  *session= join->session;
968
 
  uint32_t keyparts,length,key;
969
 
  Table *table;
970
 
  KEY *keyinfo;
 
969
  uint32_t keyparts;
 
970
  uint32_t length;
 
971
  uint32_t key;
 
972
  Table *table= NULL;
 
973
  KEY *keyinfo= NULL;
971
974
 
972
975
  /*  Use best key from find_best */
973
 
  table=j->table;
974
 
  key=keyuse->key;
975
 
  keyinfo=table->key_info+key;
 
976
  table= j->table;
 
977
  key= keyuse->getKey();
 
978
  keyinfo= table->key_info + key;
976
979
 
977
980
  {
978
 
    keyparts=length=0;
 
981
    keyparts= length= 0;
979
982
    uint32_t found_part_ref_or_null= 0;
980
983
    /*
981
984
      Calculate length for the used key
984
987
    */
985
988
    do
986
989
    {
987
 
      if (!(~used_tables & keyuse->used_tables))
 
990
      if (! (~used_tables & keyuse->getUsedTables()))
988
991
      {
989
 
        if (keyparts == keyuse->keypart &&
990
 
            !(found_part_ref_or_null & keyuse->optimize))
 
992
        if (keyparts == keyuse->getKeypart() &&
 
993
            ! (found_part_ref_or_null & keyuse->getOptimizeFlags()))
991
994
        {
992
995
          keyparts++;
993
 
          length+= keyinfo->key_part[keyuse->keypart].store_length;
994
 
          found_part_ref_or_null|= keyuse->optimize;
 
996
          length+= keyinfo->key_part[keyuse->getKeypart()].store_length;
 
997
          found_part_ref_or_null|= keyuse->getOptimizeFlags();
995
998
        }
996
999
      }
997
1000
      keyuse++;
998
 
    } while (keyuse->table == table && keyuse->key == key);
 
1001
    } while (keyuse->getTable() == table && keyuse->getKey() == key);
999
1002
  }
1000
1003
 
1001
1004
  /* set up fieldref */
1018
1021
  keyuse=org_keyuse;
1019
1022
 
1020
1023
  StoredKey **ref_key= j->ref.key_copy;
1021
 
  unsigned char *key_buff=j->ref.key_buff, *null_ref_key= 0;
 
1024
  unsigned char *key_buff= j->ref.key_buff, *null_ref_key= 0;
1022
1025
  bool keyuse_uses_no_tables= true;
1023
1026
  {
1024
 
    uint32_t i;
1025
 
    for (i=0 ; i < keyparts ; keyuse++,i++)
 
1027
    for (uint32_t i= 0; i < keyparts; keyuse++, i++)
1026
1028
    {
1027
 
      while (keyuse->keypart != i ||
1028
 
       ((~used_tables) & keyuse->used_tables))
 
1029
      while (keyuse->getKeypart() != i ||
 
1030
             ((~used_tables) & keyuse->getUsedTables()))
1029
1031
        keyuse++;       /* Skip other parts */
1030
1032
 
1031
1033
      uint32_t maybe_null= test(keyinfo->key_part[i].null_bit);
1032
 
      j->ref.items[i]=keyuse->val;    // Save for cond removal
1033
 
      j->ref.cond_guards[i]= keyuse->cond_guard;
1034
 
      if (keyuse->null_rejecting)
 
1034
      j->ref.items[i]= keyuse->getVal();    // Save for cond removal
 
1035
      j->ref.cond_guards[i]= keyuse->getConditionalGuard();
 
1036
      if (keyuse->isNullRejected())
1035
1037
        j->ref.null_rejecting |= 1 << i;
1036
 
      keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables;
1037
 
      if (!keyuse->used_tables &&  !(join->select_options & SELECT_DESCRIBE))
 
1038
      keyuse_uses_no_tables= keyuse_uses_no_tables && ! keyuse->getUsedTables();
 
1039
      if (! keyuse->getUsedTables() &&  !(join->select_options & SELECT_DESCRIBE))
1038
1040
      {         // Compare against constant
1039
1041
        store_key_item tmp(session, keyinfo->key_part[i].field,
1040
1042
                           key_buff + maybe_null,
1041
1043
                           maybe_null ?  key_buff : 0,
1042
 
                           keyinfo->key_part[i].length, keyuse->val);
 
1044
                           keyinfo->key_part[i].length, keyuse->getVal());
1043
1045
        if (session->is_fatal_error)
1044
1046
          return(true);
1045
1047
        tmp.copy();
1054
1056
        But only if field _really_ can be null i.e. we force AM_REF
1055
1057
        instead of AM_REF_OR_NULL in case if field can't be null
1056
1058
      */
1057
 
      if ((keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null)
 
1059
      if ((keyuse->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null)
1058
1060
        null_ref_key= key_buff;
1059
1061
      key_buff+=keyinfo->key_part[i].store_length;
1060
1062
    }
1061
1063
  }
1062
 
  *ref_key=0;       // end_marker
 
1064
  *ref_key= 0;       // end_marker
1063
1065
  if (j->type == AM_CONST)
1064
1066
    j->table->const_table= 1;
1065
1067
  else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) != HA_NOSAME) ||
1082
1084
  }
1083
1085
  else
1084
1086
    j->type= AM_EQ_REF;
1085
 
  return(0);
 
1087
  return 0;
1086
1088
}
1087
1089
 
1088
1090
/**
1137
1139
*/
1138
1140
void add_not_null_conds(JOIN *join)
1139
1141
{
1140
 
  for (uint32_t i=join->const_tables ; i < join->tables ; i++)
 
1142
  for (uint32_t i= join->const_tables; i < join->tables; i++)
1141
1143
  {
1142
1144
    JoinTable *tab=join->join_tab+i;
1143
1145
    if ((tab->type == AM_REF || tab->type == AM_EQ_REF ||
1463
1465
    if (table->key_read)
1464
1466
    {
1465
1467
      table->key_read= 0;
1466
 
      table->file->extra(HA_EXTRA_NO_KEYREAD);
 
1468
      table->cursor->extra(HA_EXTRA_NO_KEYREAD);
1467
1469
    }
1468
 
    table->file->ha_index_or_rnd_end();
 
1470
    table->cursor->ha_index_or_rnd_end();
1469
1471
    /*
1470
1472
      We need to reset this for next select
1471
1473
      (Tested in part_of_refkey)
1486
1488
}
1487
1489
 
1488
1490
/**
1489
 
  Remove the following expressions from order_st BY and GROUP BY:
 
1491
  Remove the following expressions from ORDER BY and GROUP BY:
1490
1492
  Constant expressions @n
1491
1493
  Expression that only uses tables that are of type EQ_REF and the reference
1492
1494
  is in the order_st list or if all refereed tables are of the above type.
1493
1495
 
1494
1496
  In the following, the X field can be removed:
1495
1497
  @code
1496
 
  SELECT * FROM t1,t2 WHERE t1.a=t2.a order_st BY t1.a,t2.X
1497
 
  SELECT * FROM t1,t2,t3 WHERE t1.a=t2.a AND t2.b=t3.b order_st BY t1.a,t3.X
 
1498
  SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t1.a,t2.X
 
1499
  SELECT * FROM t1,t2,t3 WHERE t1.a=t2.a AND t2.b=t3.b ORDER BY t1.a,t3.X
1498
1500
  @endcode
1499
1501
 
1500
1502
  These can't be optimized:
1501
1503
  @code
1502
 
  SELECT * FROM t1,t2 WHERE t1.a=t2.a order_st BY t2.X,t1.a
1503
 
  SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b order_st BY t1.a,t2.c
1504
 
  SELECT * FROM t1,t2 WHERE t1.a=t2.a order_st BY t2.b,t1.a
 
1504
  SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.X,t1.a
 
1505
  SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b ORDER BY t1.a,t2.c
 
1506
  SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.b,t1.a
1505
1507
  @endcode
1506
1508
*/
1507
1509
bool eq_ref_table(JOIN *join, order_st *start_order, JoinTable *tab)
1511
1513
  tab->cached_eq_ref_table=1;
1512
1514
  /* We can skip const tables only if not an outer table */
1513
1515
  if (tab->type == AM_CONST && !tab->first_inner)
1514
 
    return (tab->eq_ref_table=1);               /* purecov: inspected */
 
1516
    return (tab->eq_ref_table=1);
1515
1517
  if (tab->type != AM_EQ_REF || tab->table->maybe_null)
1516
1518
    return (tab->eq_ref_table=0);               // We must use this
1517
1519
  Item **ref_item=tab->ref.items;
2215
2217
    can get more freedom in performing join operations.
2216
2218
    Althogh we don't use this property now, it probably makes sense to use
2217
2219
    it in the future.
2218
 
  @param session                      Thread handler
 
2220
  @param session                      Thread Cursor
2219
2221
  @param cond                condition to build the multiple equalities for
2220
2222
  @param inherited           path to all inherited multiple equality items
2221
2223
  @param join_list           list of join tables to which the condition
2577
2579
        if (possible_keys.any())
2578
2580
        {
2579
2581
          Table *field_tab= field->table;
2580
 
          KeyUse *use;
2581
 
          for (use= stat->keyuse; use && use->table == field_tab; use++)
2582
 
            if (possible_keys.test(use->key) &&
2583
 
                field_tab->key_info[use->key].key_part[use->keypart].field ==
 
2582
          optimizer::KeyUse *use;
 
2583
          for (use= stat->keyuse; use && use->getTable() == field_tab; use++)
 
2584
            if (possible_keys.test(use->getKey()) &&
 
2585
                field_tab->key_info[use->getKey()].key_part[use->getKeypart()].field ==
2584
2586
                field)
2585
 
              field_tab->const_key_parts[use->key]|= use->keypart_map;
 
2587
              field_tab->const_key_parts[use->getKey()]|= use->getKeypartMap();
2586
2588
        }
2587
2589
      }
2588
2590
    }
2984
2986
          }
2985
2987
          break;
2986
2988
        case Item::COND_UNDEF:                  /* Impossible */
2987
 
          break; /* purecov: deadcode */
 
2989
          break;
2988
2990
      }
2989
2991
    }
2990
2992
 
3282
3284
 
3283
3285
  if (table)
3284
3286
  {
3285
 
    table->file->extra(HA_EXTRA_WRITE_CACHE);
 
3287
    table->cursor->extra(HA_EXTRA_WRITE_CACHE);
3286
3288
    table->emptyRecord();
3287
3289
    if (table->group && join->tmp_table_param.sum_func_count &&
3288
 
        table->s->keys && !table->file->inited)
3289
 
      table->file->ha_index_init(0, 0);
 
3290
        table->s->keys && !table->cursor->inited)
 
3291
      table->cursor->ha_index_init(0, 0);
3290
3292
  }
3291
3293
  /* Set up select_end */
3292
3294
  Next_select_func end_select= setup_end_select_func(join);
3358
3360
  if (table)
3359
3361
  {
3360
3362
    int tmp, new_errno= 0;
3361
 
    if ((tmp=table->file->extra(HA_EXTRA_NO_CACHE)))
 
3363
    if ((tmp=table->cursor->extra(HA_EXTRA_NO_CACHE)))
3362
3364
    {
3363
3365
      new_errno= tmp;
3364
3366
    }
3365
 
    if ((tmp=table->file->ha_index_or_rnd_end()))
 
3367
    if ((tmp=table->cursor->ha_index_or_rnd_end()))
3366
3368
    {
3367
3369
      new_errno= tmp;
3368
3370
    }
3369
3371
    if (new_errno)
3370
 
      table->file->print_error(new_errno,MYF(0));
 
3372
      table->print_error(new_errno,MYF(0));
3371
3373
  }
3372
3374
  return(join->session->is_error() ? -1 : rc);
3373
3375
}
3386
3388
  if (join->session->killed)            // If aborted by user
3387
3389
  {
3388
3390
    join->session->send_kill_message();
3389
 
    return NESTED_LOOP_KILLED;                   /* purecov: inspected */
 
3391
    return NESTED_LOOP_KILLED;
3390
3392
  }
3391
3393
  if (join_tab->use_quick != 2 || test_if_quick_select(join_tab) <= 0)
3392
3394
  {
3584
3586
{
3585
3587
  int error;
3586
3588
  Table *table= tab->table;
3587
 
  if ((error=table->file->index_read_map(table->record[0],
 
3589
  if ((error=table->cursor->index_read_map(table->record[0],
3588
3590
                                         tab->ref.key_buff,
3589
3591
                                         make_prev_keypart_map(tab->ref.key_parts),
3590
3592
                                         HA_READ_KEY_EXACT)))
3620
3622
        (int) table->reginfo.lock_type <= (int) TL_READ_WITH_SHARED_LOCKS)
3621
3623
    {
3622
3624
      table->key_read=1;
3623
 
      table->file->extra(HA_EXTRA_KEYREAD);
 
3625
      table->cursor->extra(HA_EXTRA_KEYREAD);
3624
3626
      tab->index= tab->ref.key;
3625
3627
    }
3626
3628
    error=join_read_const(tab);
3627
3629
    if (table->key_read)
3628
3630
    {
3629
3631
      table->key_read=0;
3630
 
      table->file->extra(HA_EXTRA_NO_KEYREAD);
 
3632
      table->cursor->extra(HA_EXTRA_NO_KEYREAD);
3631
3633
    }
3632
3634
    if (error)
3633
3635
    {
3676
3678
  int error;
3677
3679
  if (table->status & STATUS_GARBAGE)           // If first read
3678
3680
  {
3679
 
    if ((error=table->file->read_first_row(table->record[0],
 
3681
    if ((error=table->cursor->read_first_row(table->record[0],
3680
3682
                                           table->s->primary_key)))
3681
3683
    {
3682
3684
      if (error != HA_ERR_END_OF_FILE)
3716
3718
      error= HA_ERR_KEY_NOT_FOUND;
3717
3719
    else
3718
3720
    {
3719
 
      error=table->file->index_read_idx_map(table->record[0],tab->ref.key,
 
3721
      error=table->cursor->index_read_idx_map(table->record[0],tab->ref.key,
3720
3722
                                            (unsigned char*) tab->ref.key_buff,
3721
3723
                                            make_prev_keypart_map(tab->ref.key_parts),
3722
3724
                                            HA_READ_KEY_EXACT);
3762
3764
  int error;
3763
3765
  Table *table= tab->table;
3764
3766
 
3765
 
  if (!table->file->inited)
 
3767
  if (!table->cursor->inited)
3766
3768
  {
3767
 
    table->file->ha_index_init(tab->ref.key, tab->sorted);
 
3769
    table->cursor->ha_index_init(tab->ref.key, tab->sorted);
3768
3770
  }
3769
3771
 
3770
3772
  /* TODO: Why don't we do "Late NULLs Filtering" here? */
3776
3778
      table->status=STATUS_NOT_FOUND;
3777
3779
      return -1;
3778
3780
    }
3779
 
    error=table->file->index_read_map(table->record[0],
 
3781
    error=table->cursor->index_read_map(table->record[0],
3780
3782
                                      tab->ref.key_buff,
3781
3783
                                      make_prev_keypart_map(tab->ref.key_parts),
3782
3784
                                      HA_READ_KEY_EXACT);
3811
3813
  Table *table= tab->table;
3812
3814
 
3813
3815
  /* Initialize the index first */
3814
 
  if (!table->file->inited)
3815
 
    table->file->ha_index_init(tab->ref.key, tab->sorted);
 
3816
  if (!table->cursor->inited)
 
3817
    table->cursor->ha_index_init(tab->ref.key, tab->sorted);
3816
3818
 
3817
3819
  /* Perform "Late NULLs Filtering" (see internals manual for explanations) */
3818
3820
  for (uint32_t i= 0 ; i < tab->ref.key_parts ; i++)
3823
3825
 
3824
3826
  if (cp_buffer_from_ref(tab->join->session, &tab->ref))
3825
3827
    return -1;
3826
 
  if ((error=table->file->index_read_map(table->record[0],
 
3828
  if ((error=table->cursor->index_read_map(table->record[0],
3827
3829
                                         tab->ref.key_buff,
3828
3830
                                         make_prev_keypart_map(tab->ref.key_parts),
3829
3831
                                         HA_READ_KEY_EXACT)))
3830
3832
  {
3831
3833
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
3832
3834
      return table->report_error(error);
3833
 
    return -1; /* purecov: inspected */
 
3835
    return -1;
3834
3836
  }
3835
3837
 
3836
3838
  return 0;
3837
3839
}
3838
3840
 
3839
3841
/**
3840
 
  This function is used when optimizing away order_st BY in
3841
 
  SELECT * FROM t1 WHERE a=1 order_st BY a DESC,b DESC.
 
3842
  This function is used when optimizing away ORDER BY in
 
3843
  SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC.
3842
3844
*/
3843
3845
int join_read_last_key(JoinTable *tab)
3844
3846
{
3845
3847
  int error;
3846
3848
  Table *table= tab->table;
3847
3849
 
3848
 
  if (!table->file->inited)
3849
 
    table->file->ha_index_init(tab->ref.key, tab->sorted);
 
3850
  if (!table->cursor->inited)
 
3851
    table->cursor->ha_index_init(tab->ref.key, tab->sorted);
3850
3852
  if (cp_buffer_from_ref(tab->join->session, &tab->ref))
3851
3853
    return -1;
3852
 
  if ((error=table->file->index_read_last_map(table->record[0],
 
3854
  if ((error=table->cursor->index_read_last_map(table->record[0],
3853
3855
                                              tab->ref.key_buff,
3854
3856
                                              make_prev_keypart_map(tab->ref.key_parts))))
3855
3857
  {
3856
3858
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
3857
3859
      return table->report_error(error);
3858
 
    return -1; /* purecov: inspected */
 
3860
    return -1;
3859
3861
  }
3860
3862
  return 0;
3861
3863
}
3878
3880
      /* Save index tuple from record to the buffer */
3879
3881
      key_copy(tab->insideout_buf, info->record, key, 0);
3880
3882
 
3881
 
      if ((error=table->file->index_next_same(table->record[0],
 
3883
      if ((error=table->cursor->index_next_same(table->record[0],
3882
3884
                                              tab->ref.key_buff,
3883
3885
                                              tab->ref.key_length)))
3884
3886
      {
3902
3904
  Table *table= info->table;
3903
3905
  JoinTable *tab=table->reginfo.join_tab;
3904
3906
 
3905
 
  if ((error=table->file->index_next_same(table->record[0],
 
3907
  if ((error=table->cursor->index_next_same(table->record[0],
3906
3908
                                          tab->ref.key_buff,
3907
3909
                                          tab->ref.key_length)))
3908
3910
  {
3921
3923
  Table *table= info->table;
3922
3924
  JoinTable *tab=table->reginfo.join_tab;
3923
3925
 
3924
 
  if ((error=table->file->index_prev(table->record[0])))
 
3926
  if ((error=table->cursor->index_prev(table->record[0])))
3925
3927
    return table->report_error(error);
3926
3928
  if (key_cmp_if_same(table, tab->ref.key_buff, tab->ref.key,
3927
3929
                      tab->ref.key_length))
3943
3945
int init_read_record_seq(JoinTable *tab)
3944
3946
{
3945
3947
  tab->read_record.read_record= rr_sequential;
3946
 
  if (tab->read_record.file->ha_rnd_init(1))
 
3948
  if (tab->read_record.cursor->ha_rnd_init(1))
3947
3949
    return 1;
3948
3950
  return (*tab->read_record.read_record)(&tab->read_record);
3949
3951
}
3973
3975
      !table->no_keyread)
3974
3976
  {
3975
3977
    table->key_read=1;
3976
 
    table->file->extra(HA_EXTRA_KEYREAD);
 
3978
    table->cursor->extra(HA_EXTRA_KEYREAD);
3977
3979
  }
3978
3980
  tab->table->status=0;
3979
3981
  tab->read_record.table=table;
3980
 
  tab->read_record.file=table->file;
 
3982
  tab->read_record.cursor=table->cursor;
3981
3983
  tab->read_record.index=tab->index;
3982
3984
  tab->read_record.record=table->record[0];
3983
3985
  if (tab->insideout_match_tab)
3992
3994
    tab->read_record.do_insideout_scan= 0;
3993
3995
  }
3994
3996
 
3995
 
  if (!table->file->inited)
3996
 
    table->file->ha_index_init(tab->index, tab->sorted);
3997
 
  if ((error=tab->table->file->index_first(tab->table->record[0])))
 
3997
  if (!table->cursor->inited)
 
3998
    table->cursor->ha_index_init(tab->index, tab->sorted);
 
3999
  if ((error=tab->table->cursor->index_first(tab->table->record[0])))
3998
4000
  {
3999
4001
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
4000
4002
      table->report_error(error);
4016
4018
      /* Save index tuple from record to the buffer */
4017
4019
      key_copy(tab->insideout_buf, info->record, key, 0);
4018
4020
 
4019
 
      if ((error=info->file->index_next(info->record)))
 
4021
      if ((error=info->cursor->index_next(info->record)))
4020
4022
        return info->table->report_error(error);
4021
4023
    } while (!key_cmp(tab->table->key_info[tab->index].key_part,
4022
4024
                      tab->insideout_buf, key->key_length));
4030
4032
int join_read_next(READ_RECORD *info)
4031
4033
{
4032
4034
  int error;
4033
 
  if ((error=info->file->index_next(info->record)))
 
4035
  if ((error=info->cursor->index_next(info->record)))
4034
4036
    return info->table->report_error(error);
4035
4037
  return 0;
4036
4038
}
4043
4045
      !table->no_keyread)
4044
4046
  {
4045
4047
    table->key_read=1;
4046
 
    table->file->extra(HA_EXTRA_KEYREAD);
 
4048
    table->cursor->extra(HA_EXTRA_KEYREAD);
4047
4049
  }
4048
4050
  tab->table->status=0;
4049
4051
  tab->read_record.read_record=join_read_prev;
4050
4052
  tab->read_record.table=table;
4051
 
  tab->read_record.file=table->file;
 
4053
  tab->read_record.cursor=table->cursor;
4052
4054
  tab->read_record.index=tab->index;
4053
4055
  tab->read_record.record=table->record[0];
4054
 
  if (!table->file->inited)
4055
 
    table->file->ha_index_init(tab->index, 1);
4056
 
  if ((error= tab->table->file->index_last(tab->table->record[0])))
 
4056
  if (!table->cursor->inited)
 
4057
    table->cursor->ha_index_init(tab->index, 1);
 
4058
  if ((error= tab->table->cursor->index_last(tab->table->record[0])))
4057
4059
    return table->report_error(error);
4058
4060
 
4059
4061
  return 0;
4062
4064
int join_read_prev(READ_RECORD *info)
4063
4065
{
4064
4066
  int error;
4065
 
  if ((error= info->file->index_prev(info->record)))
 
4067
  if ((error= info->cursor->index_prev(info->record)))
4066
4068
    return info->table->report_error(error);
4067
4069
 
4068
4070
  return 0;
4139
4141
          }
4140
4142
        }
4141
4143
        if (error > 0)
4142
 
          return(NESTED_LOOP_ERROR);        /* purecov: inspected */
 
4144
          return(NESTED_LOOP_ERROR);
4143
4145
        if (end_of_records)
4144
4146
          return(NESTED_LOOP_OK);
4145
4147
        if (join->send_records >= join->unit->select_limit_cnt &&
4196
4198
  if (join->session->killed)
4197
4199
  {                                             // Aborted by user
4198
4200
    join->session->send_kill_message();
4199
 
    return NESTED_LOOP_KILLED;             /* purecov: inspected */
 
4201
    return NESTED_LOOP_KILLED;
4200
4202
  }
4201
4203
  if (!join->first_record || end_of_records ||
4202
4204
      (idx=test_if_item_cache_changed(join->group_fields)) >= 0)
4214
4216
        copy_sum_funcs(join->sum_funcs, join->sum_funcs_end[send_group_parts]);
4215
4217
        if (!join->having || join->having->val_int())
4216
4218
        {
4217
 
          int error= table->file->ha_write_row(table->record[0]);
 
4219
          int error= table->cursor->ha_write_row(table->record[0]);
4218
4220
          if (error && create_myisam_from_heap(join->session, table,
4219
4221
                                              join->tmp_table_param.start_recinfo,
4220
4222
                                                &join->tmp_table_param.recinfo,
4354
4356
      /* Create new top level AND item */
4355
4357
      Item_cond_and *new_cond=new Item_cond_and;
4356
4358
      if (!new_cond)
4357
 
        return (COND*) 0;                       // OOM /* purecov: inspected */
 
4359
        return (COND*) 0;
4358
4360
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
4359
4361
      Item *item;
4360
4362
      while ((item=li++))
4384
4386
    {                                           // Or list
4385
4387
      Item_cond_or *new_cond=new Item_cond_or;
4386
4388
      if (!new_cond)
4387
 
        return (COND*) 0;                       // OOM /* purecov: inspected */
 
4389
        return (COND*) 0;
4388
4390
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
4389
4391
      Item *item;
4390
4392
      while ((item=li++))
4492
4494
*/
4493
4495
static int test_if_order_by_key(order_st *order, Table *table, uint32_t idx, uint32_t *used_key_parts)
4494
4496
{
4495
 
  KEY_PART_INFO *key_part,*key_part_end;
4496
 
  key_part=table->key_info[idx].key_part;
4497
 
  key_part_end=key_part+table->key_info[idx].key_parts;
 
4497
  KEY_PART_INFO *key_part= NULL;
 
4498
  KEY_PART_INFO *key_part_end= NULL;
 
4499
  key_part= table->key_info[idx].key_part;
 
4500
  key_part_end= key_part + table->key_info[idx].key_parts;
4498
4501
  key_part_map const_key_parts=table->const_key_parts[idx];
4499
 
  int reverse=0;
 
4502
  int reverse= 0;
4500
4503
  bool on_primary_key= false;
4501
4504
 
4502
4505
  for (; order ; order=order->next, const_key_parts>>=1)
4506
4509
 
4507
4510
    /*
4508
4511
      Skip key parts that are constants in the WHERE clause.
4509
 
      These are already skipped in the order_st BY by const_expression_in_where()
 
4512
      These are already skipped in the ORDER BY by const_expression_in_where()
4510
4513
    */
4511
4514
    for (; const_key_parts & 1 ; const_key_parts>>= 1)
4512
4515
      key_part++;
4519
4522
        the primary key as a suffix.
4520
4523
      */
4521
4524
      if (!on_primary_key &&
4522
 
          (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
 
4525
          (table->cursor->getEngine()->check_flag(HTON_BIT_PRIMARY_KEY_IN_READ_INDEX)) &&
4523
4526
          table->s->primary_key != MAX_KEY)
4524
4527
      {
4525
4528
        on_primary_key= true;
4553
4556
  }
4554
4557
  *used_key_parts= on_primary_key ? table->key_info[idx].key_parts :
4555
4558
    (uint32_t) (key_part - table->key_info[idx].key_part);
4556
 
  if (reverse == -1 && !(table->file->index_flags(idx, *used_key_parts-1, 1) &
 
4559
  if (reverse == -1 && !(table->index_flags(idx) &
4557
4560
                         HA_READ_PREV))
4558
4561
    reverse= 0;                                 // Index can't be used
4559
4562
  return(reverse);
4576
4579
*/
4577
4580
inline bool is_subkey(KEY_PART_INFO *key_part,
4578
4581
                      KEY_PART_INFO *ref_key_part,
4579
 
                            KEY_PART_INFO *ref_key_part_end)
 
4582
                      KEY_PART_INFO *ref_key_part_end)
4580
4583
{
4581
4584
  for (; ref_key_part < ref_key_part_end; key_part++, ref_key_part++)
4582
 
    if (!key_part->field->eq(ref_key_part->field))
 
4585
    if (! key_part->field->eq(ref_key_part->field))
4583
4586
      return 0;
4584
4587
  return 1;
4585
4588
}
4599
4602
                               Table *table,
4600
4603
                               uint32_t ref,
4601
4604
                               uint32_t ref_key_parts,
4602
 
                                     const key_map *usable_keys)
 
4605
                               const key_map *usable_keys)
4603
4606
{
4604
4607
  uint32_t nr;
4605
4608
  uint32_t min_length= UINT32_MAX;
4663
4666
         (table->key_info[keynr].flags & HA_NOSAME))
4664
4667
    {
4665
4668
      KEY *keyinfo= table->key_info + keynr;
4666
 
      KEY_PART_INFO *key_part, *key_part_end;
 
4669
      KEY_PART_INFO *key_part= NULL;
 
4670
      KEY_PART_INFO *key_part_end= NULL;
4667
4671
 
4668
4672
      for (key_part=keyinfo->key_part,
4669
4673
           key_part_end=key_part+ keyinfo->key_parts;
4671
4675
           key_part++)
4672
4676
      {
4673
4677
        if (key_part->field->maybe_null() ||
4674
 
            !find_func(key_part->field, data))
 
4678
            ! find_func(key_part->field, data))
4675
4679
          break;
4676
4680
      }
4677
4681
      if (key_part == key_part_end)
4744
4748
}
4745
4749
 
4746
4750
/**
4747
 
  Test if we can skip the order_st BY by using an index.
 
4751
  Test if we can skip the ORDER BY by using an index.
4748
4752
 
4749
4753
  SYNOPSIS
4750
4754
    test_if_skip_sort_order()
4775
4779
  int order_direction;
4776
4780
  uint32_t used_key_parts;
4777
4781
  Table *table=tab->table;
4778
 
  SQL_SELECT *select=tab->select;
 
4782
  optimizer::SqlSelect *select= tab->select;
4779
4783
  key_map usable_keys;
4780
 
  QUICK_SELECT_I *save_quick= 0;
 
4784
  optimizer::QuickSelectInterface *save_quick= NULL;
4781
4785
 
4782
4786
  /*
4783
4787
    Keys disabled by ALTER Table ... DISABLE KEYS should have already
4807
4811
    if (tab->type == AM_REF_OR_NULL)
4808
4812
      return(0);
4809
4813
  }
4810
 
  else if (select && select->quick)             // Range found by opt_range
 
4814
  else if (select && select->quick)             // Range found by optimizer/range
4811
4815
  {
4812
4816
    int quick_type= select->quick->get_type();
4813
4817
    save_quick= select->quick;
4817
4821
      by clustered PK values.
4818
4822
    */
4819
4823
 
4820
 
    if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
4821
 
        quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
4822
 
        quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT)
 
4824
    if (quick_type == optimizer::QuickSelectInterface::QS_TYPE_INDEX_MERGE ||
 
4825
        quick_type == optimizer::QuickSelectInterface::QS_TYPE_ROR_UNION ||
 
4826
        quick_type == optimizer::QuickSelectInterface::QS_TYPE_ROR_INTERSECT)
4823
4827
      return(0);
4824
4828
    ref_key=       select->quick->index;
4825
4829
    ref_key_parts= select->quick->used_key_parts;
4858
4862
            "part1 = const1 AND part2=const2".
4859
4863
            So we build tab->ref from scratch here.
4860
4864
          */
4861
 
          KeyUse *keyuse= tab->keyuse;
4862
 
          while (keyuse->key != new_ref_key && keyuse->table == tab->table)
 
4865
          optimizer::KeyUse *keyuse= tab->keyuse;
 
4866
          while (keyuse->getKey() != new_ref_key && keyuse->getTable() == tab->table)
4863
4867
            keyuse++;
4864
4868
 
4865
4869
          if (create_ref_for_key(tab->join, tab, keyuse,
4869
4873
        else
4870
4874
        {
4871
4875
          /*
4872
 
            The range optimizer constructed QUICK_RANGE for ref_key, and
 
4876
            The range optimizer constructed QuickRange for ref_key, and
4873
4877
            we want to use instead new_ref_key as the index. We can't
4874
4878
            just change the index of the quick select, because this may
4875
4879
            result in an incosistent QUICK_SELECT object. Below we
4916
4920
    double fanout= 1;
4917
4921
    JOIN *join= tab->join;
4918
4922
    uint32_t tablenr= tab - join->join_tab;
4919
 
    ha_rows table_records= table->file->stats.records;
 
4923
    ha_rows table_records= table->cursor->stats.records;
4920
4924
    bool group= join->group && order == join->group_list;
4921
4925
    optimizer::Position cur_pos;
4922
4926
 
4933
4937
        */
4934
4938
      if (tab->type == AM_ALL && tab->join->tables > tab->join->const_tables + 1)
4935
4939
        return(0);
4936
 
      keys= *table->file->keys_to_use_for_scanning();
 
4940
      keys= *table->cursor->keys_to_use_for_scanning();
4937
4941
      keys|= table->covering_keys;
4938
4942
 
4939
4943
      /*
4963
4967
      if (keys.test(nr) &&
4964
4968
          (direction= test_if_order_by_key(order, table, nr, &used_key_parts)))
4965
4969
      {
4966
 
        bool is_covering= table->covering_keys.test(nr) || (nr == table->s->primary_key && table->file->primary_key_is_clustered());
 
4970
        bool is_covering= table->covering_keys.test(nr) || (nr == table->s->primary_key && table->cursor->primary_key_is_clustered());
4967
4971
 
4968
4972
        /*
4969
 
          Don't use an index scan with order_st BY without limit.
 
4973
          Don't use an index scan with ORDER BY without limit.
4970
4974
          For GROUP BY without limit always use index scan
4971
4975
          if there is a suitable index.
4972
4976
          Why we hold to this asymmetry hardly can be explained
5033
5037
            Rows in such a sequence are supposed to be ordered
5034
5038
            by rowid/primary key. When reading the data
5035
5039
            in a sequence we'll touch not more pages than the
5036
 
            table file contains.
 
5040
            table cursor contains.
5037
5041
            TODO. Use the formula for a disk sweep sequential access
5038
5042
            to calculate the cost of accessing data rows for one
5039
5043
            index entry.
5040
5044
          */
5041
5045
          index_scan_time= select_limit/rec_per_key *
5042
 
                           min(rec_per_key, table->file->scan_time());
 
5046
                           min(rec_per_key, table->cursor->scan_time());
5043
5047
          if (is_covering || (ref_key < 0 && (group || table->force_index)) ||
5044
5048
              index_scan_time < read_time)
5045
5049
          {
5094
5098
          if (table->covering_keys.test(best_key))
5095
5099
          {
5096
5100
            table->key_read=1;
5097
 
            table->file->extra(HA_EXTRA_KEYREAD);
 
5101
            table->cursor->extra(HA_EXTRA_KEYREAD);
5098
5102
          }
5099
 
          table->file->ha_index_or_rnd_end();
 
5103
          table->cursor->ha_index_or_rnd_end();
5100
5104
          if (join->select_options & SELECT_DESCRIBE)
5101
5105
          {
5102
5106
            tab->ref.key= -1;
5118
5122
          tab->ref.key= -1;
5119
5123
          tab->ref.key_parts=0;         // Don't use ref key.
5120
5124
          tab->read_first_record= join_init_read_record;
5121
 
          /*
5122
 
            TODO: update the number of records in join->best_positions[tablenr]
5123
 
          */
5124
5125
        }
5125
5126
      }
5126
5127
      used_key_parts= best_key_parts;
5131
5132
  }
5132
5133
 
5133
5134
check_reverse_order:
5134
 
  if (order_direction == -1)            // If order_st BY ... DESC
 
5135
  if (order_direction == -1)            // If ORDER BY ... DESC
5135
5136
  {
5136
5137
    if (select && select->quick)
5137
5138
    {
5139
5140
        Don't reverse the sort order, if it's already done.
5140
5141
        (In some cases test_if_order_by_key() can be called multiple times
5141
5142
      */
5142
 
      if (!select->quick->reverse_sorted())
 
5143
      if (! select->quick->reverse_sorted())
5143
5144
      {
5144
 
        QUICK_SELECT_DESC *tmp;
 
5145
        optimizer::QuickSelectDescending *tmp= NULL;
5145
5146
        bool error= false;
5146
5147
        int quick_type= select->quick->get_type();
5147
 
        if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
5148
 
            quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
5149
 
            quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
5150
 
            quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
 
5148
        if (quick_type == optimizer::QuickSelectInterface::QS_TYPE_INDEX_MERGE ||
 
5149
            quick_type == optimizer::QuickSelectInterface::QS_TYPE_ROR_INTERSECT ||
 
5150
            quick_type == optimizer::QuickSelectInterface::QS_TYPE_ROR_UNION ||
 
5151
            quick_type == optimizer::QuickSelectInterface::QS_TYPE_GROUP_MIN_MAX)
5151
5152
        {
5152
5153
          tab->limit= 0;
5153
5154
          select->quick= save_quick;
5154
 
          return(0);                   // Use filesort
 
5155
          return 0; // Use filesort
5155
5156
        }
5156
5157
 
5157
 
        /* order_st BY range_key DESC */
5158
 
        tmp= new QUICK_SELECT_DESC((QUICK_RANGE_SELECT*)(select->quick),
5159
 
                                          used_key_parts, &error);
5160
 
        if (!tmp || error)
 
5158
        /* ORDER BY range_key DESC */
 
5159
        tmp= new optimizer::QuickSelectDescending((optimizer::QuickRangeSelect*)(select->quick),
 
5160
                                                  used_key_parts, 
 
5161
                                                  &error);
 
5162
        if (! tmp || error)
5161
5163
        {
5162
5164
          delete tmp;
5163
 
                select->quick= save_quick;
5164
 
                tab->limit= 0;
5165
 
          return(0);            // Reverse sort not supported
 
5165
          select->quick= save_quick;
 
5166
          tab->limit= 0;
 
5167
          return 0; // Reverse sort not supported
5166
5168
        }
5167
5169
        select->quick=tmp;
5168
5170
      }
5171
5173
             tab->ref.key >= 0 && tab->ref.key_parts <= used_key_parts)
5172
5174
    {
5173
5175
      /*
5174
 
        SELECT * FROM t1 WHERE a=1 order_st BY a DESC,b DESC
 
5176
        SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
5175
5177
 
5176
5178
        Use a traversal function that starts by reading the last row
5177
5179
        with key part (A) and then traverse the index backwards.
5182
5184
  }
5183
5185
  else if (select && select->quick)
5184
5186
    select->quick->sorted= 1;
5185
 
  return(1);
 
5187
  return 1;
5186
5188
}
5187
5189
 
5188
5190
/*
5190
5192
 
5191
5193
  SYNOPSIS
5192
5194
   create_sort_index()
5193
 
     session            Thread handler
 
5195
     session            Thread Cursor
5194
5196
     tab                Table to sort (in join structure)
5195
5197
     order              How table should be sorted
5196
5198
     filesort_limit     Max number of rows that needs to be sorted
5203
5205
  IMPLEMENTATION
5204
5206
   - If there is an index that can be used, 'tab' is modified to use
5205
5207
     this index.
5206
 
   - If no index, create with filesort() an index file that can be used to
 
5208
   - If no index, create with filesort() an index cursor that can be used to
5207
5209
     retrieve rows in order (should be done with 'read_record').
5208
5210
     The sorted data is stored in tab->table and will be freed when calling
5209
5211
     tab->table->free_io_cache().
5218
5220
  uint32_t length= 0;
5219
5221
  ha_rows examined_rows;
5220
5222
  Table *table;
5221
 
  SQL_SELECT *select;
 
5223
  optimizer::SqlSelect *select= NULL;
5222
5224
  JoinTable *tab;
5223
5225
 
5224
5226
  if (join->tables == join->const_tables)
5235
5237
  */
5236
5238
  if ((order != join->group_list ||
5237
5239
       !(join->select_options & SELECT_BIG_RESULT) ||
5238
 
       (select && select->quick && (select->quick->get_type() == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX))) &&
 
5240
       (select && select->quick && (select->quick->get_type() == optimizer::QuickSelectInterface::QS_TYPE_GROUP_MIN_MAX))) &&
5239
5241
      test_if_skip_sort_order(tab,order,select_limit,0,
5240
5242
                              is_order_by ?  &table->keys_in_use_for_order_by :
5241
5243
                              &table->keys_in_use_for_group_by))
5244
5246
    length++;
5245
5247
  if (!(join->sortorder=
5246
5248
        make_unireg_sortorder(order, &length, join->sortorder)))
5247
 
    goto err;                           /* purecov: inspected */
 
5249
    goto err;
5248
5250
 
5249
 
  table->sort.io_cache= new IO_CACHE;
5250
 
  memset(table->sort.io_cache, 0, sizeof(IO_CACHE));
 
5251
  table->sort.io_cache= new internal::IO_CACHE;
 
5252
  memset(table->sort.io_cache, 0, sizeof(internal::IO_CACHE));
5251
5253
  table->status=0;                              // May be wrong if quick_select
5252
5254
 
5253
5255
  // If table has a range, move it to select
5264
5266
      if (table->key_read && ((uint32_t) tab->ref.key != select->quick->index))
5265
5267
      {
5266
5268
        table->key_read=0;
5267
 
        table->file->extra(HA_EXTRA_NO_KEYREAD);
 
5269
        table->cursor->extra(HA_EXTRA_NO_KEYREAD);
5268
5270
      }
5269
5271
    }
5270
5272
    else
5275
5277
        For impossible ranges (like when doing a lookup on NULL on a NOT NULL
5276
5278
        field, quick will contain an empty record set.
5277
5279
      */
5278
 
      if (!(select->quick= (get_quick_select_for_ref(session, table, &tab->ref,
5279
 
                                                     tab->found_records))))
 
5280
      if (! (select->quick= (optimizer::get_quick_select_for_ref(session, 
 
5281
                                                                 table, 
 
5282
                                                                 &tab->ref,
 
5283
                                                                 tab->found_records))))
 
5284
      {
5280
5285
        goto err;
 
5286
      }
5281
5287
    }
5282
5288
  }
5283
5289
 
5284
 
  /* Fill schema tables with data before filesort if it's necessary */
5285
 
  if ((join->select_lex->options & OPTION_SCHEMA_TABLE) &&
5286
 
      get_schema_tables_result(join, PROCESSED_BY_CREATE_SORT_INDEX))
5287
 
    goto err;
5288
 
 
5289
5290
  if (table->s->tmp_table)
5290
 
    table->file->info(HA_STATUS_VARIABLE);      // Get record count
 
5291
    table->cursor->info(HA_STATUS_VARIABLE);    // Get record count
5291
5292
  table->sort.found_records=filesort(session, table,join->sortorder, length,
5292
5293
                                     select, filesort_limit, 0,
5293
5294
                                     &examined_rows);
5306
5307
  if (table->key_read)                          // Restore if we used indexes
5307
5308
  {
5308
5309
    table->key_read=0;
5309
 
    table->file->extra(HA_EXTRA_NO_KEYREAD);
 
5310
    table->cursor->extra(HA_EXTRA_NO_KEYREAD);
5310
5311
  }
5311
5312
  return(table->sort.found_records == HA_POS_ERROR);
5312
5313
err:
5315
5316
 
5316
5317
int remove_dup_with_compare(Session *session, Table *table, Field **first_field, uint32_t offset, Item *having)
5317
5318
{
5318
 
  handler *file=table->file;
 
5319
  Cursor *cursor=table->cursor;
5319
5320
  char *org_record,*new_record;
5320
5321
  unsigned char *record;
5321
5322
  int error;
5324
5325
  org_record=(char*) (record=table->record[0])+offset;
5325
5326
  new_record=(char*) table->record[1]+offset;
5326
5327
 
5327
 
  file->ha_rnd_init(1);
5328
 
  error=file->rnd_next(record);
 
5328
  cursor->ha_rnd_init(1);
 
5329
  error=cursor->rnd_next(record);
5329
5330
  for (;;)
5330
5331
  {
5331
5332
    if (session->killed)
5344
5345
    }
5345
5346
    if (having && !having->val_int())
5346
5347
    {
5347
 
      if ((error=file->ha_delete_row(record)))
 
5348
      if ((error=cursor->ha_delete_row(record)))
5348
5349
        goto err;
5349
 
      error=file->rnd_next(record);
 
5350
      error=cursor->rnd_next(record);
5350
5351
      continue;
5351
5352
    }
5352
5353
    if (copy_blobs(first_field))
5357
5358
    }
5358
5359
    memcpy(new_record,org_record,reclength);
5359
5360
 
5360
 
    /* Read through rest of file and mark duplicated rows deleted */
 
5361
    /* Read through rest of cursor and mark duplicated rows deleted */
5361
5362
    bool found=0;
5362
5363
    for (;;)
5363
5364
    {
5364
 
      if ((error=file->rnd_next(record)))
 
5365
      if ((error=cursor->rnd_next(record)))
5365
5366
      {
5366
5367
        if (error == HA_ERR_RECORD_DELETED)
5367
5368
          continue;
5371
5372
      }
5372
5373
      if (table->compare_record(first_field) == 0)
5373
5374
      {
5374
 
        if ((error=file->ha_delete_row(record)))
 
5375
        if ((error=cursor->ha_delete_row(record)))
5375
5376
          goto err;
5376
5377
      }
5377
5378
      else if (!found)
5378
5379
      {
5379
5380
        found= 1;
5380
 
        file->position(record); // Remember position
 
5381
        cursor->position(record);       // Remember position
5381
5382
      }
5382
5383
    }
5383
5384
    if (!found)
5384
 
      break;                                    // End of file
 
5385
      break;                                    // End of cursor
5385
5386
    /* Restart search on next row */
5386
 
    error=file->restart_rnd_next(record,file->ref);
 
5387
    error=cursor->restart_rnd_next(record,cursor->ref);
5387
5388
  }
5388
5389
 
5389
 
  file->extra(HA_EXTRA_NO_CACHE);
 
5390
  cursor->extra(HA_EXTRA_NO_CACHE);
5390
5391
  return(0);
5391
5392
err:
5392
 
  file->extra(HA_EXTRA_NO_CACHE);
 
5393
  cursor->extra(HA_EXTRA_NO_CACHE);
5393
5394
  if (error)
5394
 
    file->print_error(error,MYF(0));
 
5395
    table->print_error(error,MYF(0));
5395
5396
  return(1);
5396
5397
}
5397
5398
 
5410
5411
{
5411
5412
  unsigned char *key_buffer, *key_pos, *record=table->record[0];
5412
5413
  int error;
5413
 
  handler *file= table->file;
 
5414
  Cursor *cursor= table->cursor;
5414
5415
  uint32_t extra_length= ALIGN_SIZE(key_length)-key_length;
5415
5416
  uint32_t *field_lengths,*field_length;
5416
5417
  HASH hash;
5417
5418
 
5418
 
  if (!my_multi_malloc(MYF(MY_WME),
 
5419
  if (! memory::multi_malloc(false,
5419
5420
                       &key_buffer,
5420
5421
                       (uint32_t) ((key_length + extra_length) *
5421
 
                               (long) file->stats.records),
 
5422
                               (long) cursor->stats.records),
5422
5423
                       &field_lengths,
5423
5424
                       (uint32_t) (field_count*sizeof(*field_lengths)),
5424
5425
                       NULL))
5438
5439
    extra_length= ALIGN_SIZE(key_length)-key_length;
5439
5440
  }
5440
5441
 
5441
 
  if (hash_init(&hash, &my_charset_bin, (uint32_t) file->stats.records, 0,
 
5442
  if (hash_init(&hash, &my_charset_bin, (uint32_t) cursor->stats.records, 0,
5442
5443
                key_length, (hash_get_key) 0, 0, 0))
5443
5444
  {
5444
5445
    free((char*) key_buffer);
5445
5446
    return(1);
5446
5447
  }
5447
5448
 
5448
 
  file->ha_rnd_init(1);
 
5449
  cursor->ha_rnd_init(1);
5449
5450
  key_pos=key_buffer;
5450
5451
  for (;;)
5451
5452
  {
5456
5457
      error=0;
5457
5458
      goto err;
5458
5459
    }
5459
 
    if ((error=file->rnd_next(record)))
 
5460
    if ((error=cursor->rnd_next(record)))
5460
5461
    {
5461
5462
      if (error == HA_ERR_RECORD_DELETED)
5462
5463
        continue;
5466
5467
    }
5467
5468
    if (having && !having->val_int())
5468
5469
    {
5469
 
      if ((error=file->ha_delete_row(record)))
 
5470
      if ((error=cursor->ha_delete_row(record)))
5470
5471
        goto err;
5471
5472
      continue;
5472
5473
    }
5483
5484
    if (hash_search(&hash, org_key_pos, key_length))
5484
5485
    {
5485
5486
      /* Duplicated found ; Remove the row */
5486
 
      if ((error=file->ha_delete_row(record)))
 
5487
      if ((error=cursor->ha_delete_row(record)))
5487
5488
        goto err;
5488
5489
    }
5489
5490
    else
5492
5493
  }
5493
5494
  free((char*) key_buffer);
5494
5495
  hash_free(&hash);
5495
 
  file->extra(HA_EXTRA_NO_CACHE);
5496
 
  (void) file->ha_rnd_end();
 
5496
  cursor->extra(HA_EXTRA_NO_CACHE);
 
5497
  (void) cursor->ha_rnd_end();
5497
5498
  return(0);
5498
5499
 
5499
5500
err:
5500
5501
  free((char*) key_buffer);
5501
5502
  hash_free(&hash);
5502
 
  file->extra(HA_EXTRA_NO_CACHE);
5503
 
  (void) file->ha_rnd_end();
 
5503
  cursor->extra(HA_EXTRA_NO_CACHE);
 
5504
  (void) cursor->ha_rnd_end();
5504
5505
  if (error)
5505
 
    file->print_error(error,MYF(0));
 
5506
    table->print_error(error,MYF(0));
5506
5507
  return(1);
5507
5508
}
5508
5509
 
5515
5516
  for (order_st *tmp = order; tmp; tmp=tmp->next)
5516
5517
    count++;
5517
5518
  if (!sortorder)
5518
 
    sortorder= (SORT_FIELD*) sql_alloc(sizeof(SORT_FIELD) *
 
5519
    sortorder= (SORT_FIELD*) memory::sql_alloc(sizeof(SORT_FIELD) *
5519
5520
                                       (max(count, *length) + 1));
5520
5521
  pos= sort= sortorder;
5521
5522
 
5603
5604
*****************************************************************************/
5604
5605
 
5605
5606
/**
5606
 
  Resolve an order_st BY or GROUP BY column reference.
 
5607
  Resolve an ORDER BY or GROUP BY column reference.
5607
5608
 
5608
5609
  Given a column reference (represented by 'order') from a GROUP BY or order_st
5609
5610
  BY clause, find the actual column it represents. If the column being
5610
5611
  resolved is from the GROUP BY clause, the procedure searches the SELECT
5611
5612
  list 'fields' and the columns in the FROM list 'tables'. If 'order' is from
5612
 
  the order_st BY clause, only the SELECT list is being searched.
 
5613
  the ORDER BY clause, only the SELECT list is being searched.
5613
5614
 
5614
5615
  If 'order' is resolved to an Item, then order->item is set to the found
5615
5616
  Item. If there is no item for the found column (that is, it was resolved
5791
5792
/**
5792
5793
  Intitialize the GROUP BY list.
5793
5794
 
5794
 
  @param session                        Thread handler
 
5795
  @param session                        Thread Cursor
5795
5796
  @param ref_pointer_array      We store references to all fields that was
5796
5797
                               not in 'fields' here.
5797
5798
  @param fields         All fields in the select part. Any item in
6150
6151
                another extra byte to not get warnings from purify in
6151
6152
                Field_varstring::val_int
6152
6153
              */
6153
 
        if (!(tmp= (unsigned char*) sql_alloc(field->pack_length()+2)))
 
6154
        if (!(tmp= (unsigned char*) memory::sql_alloc(field->pack_length()+2)))
6154
6155
          goto err;
6155
6156
        if (copy)
6156
6157
        {
6196
6197
    itr++;
6197
6198
  itr.sublist(res_selected_fields, elements);
6198
6199
  /*
6199
 
    Put elements from HAVING, order_st BY and GROUP BY last to ensure that any
 
6200
    Put elements from HAVING, ORDER BY and GROUP BY last to ensure that any
6200
6201
    reference used in these will resolve to a item that is already calculated
6201
6202
  */
6202
6203
  param->copy_funcs.concat(&extra_funcs);
6361
6362
/**
6362
6363
  Call ::setup for all sum functions.
6363
6364
 
6364
 
  @param session           thread handler
 
6365
  @param session           thread Cursor
6365
6366
  @param func_ptr      sum function list
6366
6367
 
6367
6368
  @retval
6536
6537
  return 0;
6537
6538
}
6538
6539
 
6539
 
/**
6540
 
  EXPLAIN handling.
6541
 
 
6542
 
  Send a description about what how the select will be done to stdout.
6543
 
*/
6544
 
void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
6545
 
                     bool distinct,const char *message)
6546
 
{
6547
 
  List<Item> field_list;
6548
 
  List<Item> item_list;
6549
 
  Session *session=join->session;
6550
 
  select_result *result=join->result;
6551
 
  Item *item_null= new Item_null();
6552
 
  const CHARSET_INFO * const cs= system_charset_info;
6553
 
  int quick_type;
6554
 
  /* Don't log this into the slow query log */
6555
 
  session->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
6556
 
  join->unit->offset_limit_cnt= 0;
6557
 
 
6558
 
  /*
6559
 
    NOTE: the number/types of items pushed into item_list must be in sync with
6560
 
    EXPLAIN column types as they're "defined" in Session::send_explain_fields()
6561
 
  */
6562
 
  if (message)
6563
 
  {
6564
 
    item_list.push_back(new Item_int((int32_t)
6565
 
                                     join->select_lex->select_number));
6566
 
    item_list.push_back(new Item_string(join->select_lex->type,
6567
 
                                        strlen(join->select_lex->type), cs));
6568
 
    for (uint32_t i=0 ; i < 7; i++)
6569
 
      item_list.push_back(item_null);
6570
 
    if (join->session->lex->describe & DESCRIBE_EXTENDED)
6571
 
      item_list.push_back(item_null);
6572
 
 
6573
 
    item_list.push_back(new Item_string(message,strlen(message),cs));
6574
 
    if (result->send_data(item_list))
6575
 
      join->error= 1;
6576
 
  }
6577
 
  else if (join->select_lex == join->unit->fake_select_lex)
6578
 
  {
6579
 
    /*
6580
 
      here we assume that the query will return at least two rows, so we
6581
 
      show "filesort" in EXPLAIN. Of course, sometimes we'll be wrong
6582
 
      and no filesort will be actually done, but executing all selects in
6583
 
      the UNION to provide precise EXPLAIN information will hardly be
6584
 
      appreciated :)
6585
 
    */
6586
 
    char table_name_buffer[NAME_LEN];
6587
 
    item_list.empty();
6588
 
    /* id */
6589
 
    item_list.push_back(new Item_null);
6590
 
    /* select_type */
6591
 
    item_list.push_back(new Item_string(join->select_lex->type,
6592
 
                                        strlen(join->select_lex->type),
6593
 
                                        cs));
6594
 
    /* table */
6595
 
    {
6596
 
      Select_Lex *sl= join->unit->first_select();
6597
 
      uint32_t len= 6, lastop= 0;
6598
 
      memcpy(table_name_buffer, STRING_WITH_LEN("<union"));
6599
 
      for (; sl && len + lastop + 5 < NAME_LEN; sl= sl->next_select())
6600
 
      {
6601
 
        len+= lastop;
6602
 
        lastop= snprintf(table_name_buffer + len, NAME_LEN - len,
6603
 
                         "%u,", sl->select_number);
6604
 
      }
6605
 
      if (sl || len + lastop >= NAME_LEN)
6606
 
      {
6607
 
        memcpy(table_name_buffer + len, STRING_WITH_LEN("...>") + 1);
6608
 
        len+= 4;
6609
 
      }
6610
 
      else
6611
 
      {
6612
 
        len+= lastop;
6613
 
        table_name_buffer[len - 1]= '>';  // change ',' to '>'
6614
 
      }
6615
 
      item_list.push_back(new Item_string(table_name_buffer, len, cs));
6616
 
    }
6617
 
    /* type */
6618
 
    item_list.push_back(new Item_string(access_method_str[AM_ALL].c_str(),
6619
 
                                        access_method_str[AM_ALL].length(),
6620
 
                                        cs));
6621
 
    /* possible_keys */
6622
 
    item_list.push_back(item_null);
6623
 
    /* key*/
6624
 
    item_list.push_back(item_null);
6625
 
    /* key_len */
6626
 
    item_list.push_back(item_null);
6627
 
    /* ref */
6628
 
    item_list.push_back(item_null);
6629
 
    /* in_rows */
6630
 
    if (join->session->lex->describe & DESCRIBE_EXTENDED)
6631
 
      item_list.push_back(item_null);
6632
 
    /* rows */
6633
 
    item_list.push_back(item_null);
6634
 
    /* extra */
6635
 
    if (join->unit->global_parameters->order_list.first)
6636
 
      item_list.push_back(new Item_string("Using filesort",
6637
 
                                          14, cs));
6638
 
    else
6639
 
      item_list.push_back(new Item_string("", 0, cs));
6640
 
 
6641
 
    if (result->send_data(item_list))
6642
 
      join->error= 1;
6643
 
  }
6644
 
  else
6645
 
  {
6646
 
    table_map used_tables=0;
6647
 
    for (uint32_t i=0 ; i < join->tables ; i++)
6648
 
    {
6649
 
      JoinTable *tab=join->join_tab+i;
6650
 
      Table *table=tab->table;
6651
 
      TableList *table_list= tab->table->pos_in_table_list;
6652
 
      char buff[512];
6653
 
      char buff1[512], buff2[512], buff3[512];
6654
 
      char keylen_str_buf[64];
6655
 
      String extra(buff, sizeof(buff),cs);
6656
 
      char table_name_buffer[NAME_LEN];
6657
 
      String tmp1(buff1,sizeof(buff1),cs);
6658
 
      String tmp2(buff2,sizeof(buff2),cs);
6659
 
      String tmp3(buff3,sizeof(buff3),cs);
6660
 
      extra.length(0);
6661
 
      tmp1.length(0);
6662
 
      tmp2.length(0);
6663
 
      tmp3.length(0);
6664
 
 
6665
 
      quick_type= -1;
6666
 
      item_list.empty();
6667
 
      /* id */
6668
 
      item_list.push_back(new Item_uint((uint32_t)
6669
 
                                       join->select_lex->select_number));
6670
 
      /* select_type */
6671
 
      item_list.push_back(new Item_string(join->select_lex->type,
6672
 
                                          strlen(join->select_lex->type),
6673
 
                                          cs));
6674
 
      if (tab->type == AM_ALL && tab->select && tab->select->quick)
6675
 
      {
6676
 
        quick_type= tab->select->quick->get_type();
6677
 
        if ((quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) ||
6678
 
            (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) ||
6679
 
            (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION))
6680
 
          tab->type = AM_INDEX_MERGE;
6681
 
        else
6682
 
          tab->type = AM_RANGE;
6683
 
      }
6684
 
      /* table */
6685
 
      if (table->derived_select_number)
6686
 
      {
6687
 
        /* Derived table name generation */
6688
 
        int len= snprintf(table_name_buffer, sizeof(table_name_buffer)-1,
6689
 
                          "<derived%u>",
6690
 
                          table->derived_select_number);
6691
 
        item_list.push_back(new Item_string(table_name_buffer, len, cs));
6692
 
      }
6693
 
      else
6694
 
      {
6695
 
        TableList *real_table= table->pos_in_table_list;
6696
 
        item_list.push_back(new Item_string(real_table->alias,
6697
 
                                            strlen(real_table->alias),
6698
 
                                            cs));
6699
 
      }
6700
 
      /* "type" column */
6701
 
      item_list.push_back(new Item_string(access_method_str[tab->type].c_str(),
6702
 
                                          access_method_str[tab->type].length(),
6703
 
                                          cs));
6704
 
      /* Build "possible_keys" value and add it to item_list */
6705
 
      if (tab->keys.any())
6706
 
      {
6707
 
        uint32_t j;
6708
 
        for (j=0 ; j < table->s->keys ; j++)
6709
 
        {
6710
 
          if (tab->keys.test(j))
6711
 
          {
6712
 
            if (tmp1.length())
6713
 
              tmp1.append(',');
6714
 
            tmp1.append(table->key_info[j].name,
6715
 
                        strlen(table->key_info[j].name),
6716
 
                        system_charset_info);
6717
 
          }
6718
 
        }
6719
 
      }
6720
 
      if (tmp1.length())
6721
 
        item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),cs));
6722
 
      else
6723
 
        item_list.push_back(item_null);
6724
 
 
6725
 
      /* Build "key", "key_len", and "ref" values and add them to item_list */
6726
 
      if (tab->ref.key_parts)
6727
 
      {
6728
 
        KEY *key_info=table->key_info+ tab->ref.key;
6729
 
        register uint32_t length;
6730
 
        item_list.push_back(new Item_string(key_info->name,
6731
 
                                            strlen(key_info->name),
6732
 
                                            system_charset_info));
6733
 
        length= int64_t2str(tab->ref.key_length, keylen_str_buf, 10) -
6734
 
                keylen_str_buf;
6735
 
        item_list.push_back(new Item_string(keylen_str_buf, length,
6736
 
                                            system_charset_info));
6737
 
        for (StoredKey **ref=tab->ref.key_copy ; *ref ; ref++)
6738
 
        {
6739
 
          if (tmp2.length())
6740
 
            tmp2.append(',');
6741
 
          tmp2.append((*ref)->name(), strlen((*ref)->name()),
6742
 
                      system_charset_info);
6743
 
        }
6744
 
        item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
6745
 
      }
6746
 
      else if (tab->type == AM_NEXT)
6747
 
      {
6748
 
        KEY *key_info=table->key_info+ tab->index;
6749
 
        register uint32_t length;
6750
 
        item_list.push_back(new Item_string(key_info->name,
6751
 
                                            strlen(key_info->name),cs));
6752
 
        length= int64_t2str(key_info->key_length, keylen_str_buf, 10) -
6753
 
                keylen_str_buf;
6754
 
        item_list.push_back(new Item_string(keylen_str_buf,
6755
 
                                            length,
6756
 
                                            system_charset_info));
6757
 
        item_list.push_back(item_null);
6758
 
      }
6759
 
      else if (tab->select && tab->select->quick)
6760
 
      {
6761
 
        tab->select->quick->add_keys_and_lengths(&tmp2, &tmp3);
6762
 
        item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
6763
 
        item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
6764
 
        item_list.push_back(item_null);
6765
 
      }
6766
 
      else
6767
 
      {
6768
 
        if (table_list->schema_table && 
6769
 
            table_list->schema_table->getRequestedObject() & OPTIMIZE_I_S_TABLE)
6770
 
        {
6771
 
          if (table_list->has_db_lookup_value)
6772
 
          {
6773
 
            int f_idx= table_list->schema_table->getFirstColumnIndex();
6774
 
            const string &tmp_buff= table_list->schema_table->getColumnName(f_idx);
6775
 
            tmp2.append(tmp_buff.c_str(), tmp_buff.length(), cs);
6776
 
          }
6777
 
          if (table_list->has_table_lookup_value)
6778
 
          {
6779
 
            if (table_list->has_db_lookup_value)
6780
 
              tmp2.append(',');
6781
 
            int f_idx= table_list->schema_table->getSecondColumnIndex();
6782
 
            const string &tmp_buff= table_list->schema_table->getColumnName(f_idx);
6783
 
            tmp2.append(tmp_buff.c_str(), tmp_buff.length(), cs);
6784
 
          }
6785
 
          if (tmp2.length())
6786
 
            item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
6787
 
          else
6788
 
            item_list.push_back(item_null);
6789
 
        }
6790
 
        else
6791
 
          item_list.push_back(item_null);
6792
 
        item_list.push_back(item_null);
6793
 
        item_list.push_back(item_null);
6794
 
      }
6795
 
 
6796
 
      /* Add "rows" field to item_list. */
6797
 
      if (table_list->schema_table)
6798
 
      {
6799
 
        /* in_rows */
6800
 
        if (join->session->lex->describe & DESCRIBE_EXTENDED)
6801
 
          item_list.push_back(item_null);
6802
 
        /* rows */
6803
 
        item_list.push_back(item_null);
6804
 
      }
6805
 
      else
6806
 
      {
6807
 
        double examined_rows;
6808
 
        if (tab->select && tab->select->quick)
6809
 
          examined_rows= rows2double(tab->select->quick->records);
6810
 
        else if (tab->type == AM_NEXT || tab->type == AM_ALL)
6811
 
          examined_rows= rows2double(tab->limit ? tab->limit :
6812
 
                                     tab->table->file->records());
6813
 
        else
6814
 
        {
6815
 
          optimizer::Position cur_pos= join->getPosFromOptimalPlan(i);
6816
 
          examined_rows= cur_pos.getFanout();
6817
 
        }
6818
 
 
6819
 
        item_list.push_back(new Item_int((int64_t) (uint64_t) examined_rows,
6820
 
                                         MY_INT64_NUM_DECIMAL_DIGITS));
6821
 
 
6822
 
        /* Add "filtered" field to item_list. */
6823
 
        if (join->session->lex->describe & DESCRIBE_EXTENDED)
6824
 
        {
6825
 
          float f= 0.0;
6826
 
          if (examined_rows)
6827
 
          {
6828
 
            optimizer::Position cur_pos= join->getPosFromOptimalPlan(i);
6829
 
            f= (float) (100.0 * cur_pos.getFanout() /
6830
 
                        examined_rows);
6831
 
          }
6832
 
          item_list.push_back(new Item_float(f, 2));
6833
 
        }
6834
 
      }
6835
 
 
6836
 
      /* Build "Extra" field and add it to item_list. */
6837
 
      bool key_read=table->key_read;
6838
 
      if ((tab->type == AM_NEXT || tab->type == AM_CONST) &&
6839
 
          table->covering_keys.test(tab->index))
6840
 
        key_read=1;
6841
 
      if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
6842
 
          !((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row)
6843
 
        key_read=1;
6844
 
 
6845
 
      if (tab->info)
6846
 
        item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs));
6847
 
      else if (tab->packed_info & TAB_INFO_HAVE_VALUE)
6848
 
      {
6849
 
        if (tab->packed_info & TAB_INFO_USING_INDEX)
6850
 
          extra.append(STRING_WITH_LEN("; Using index"));
6851
 
        if (tab->packed_info & TAB_INFO_USING_WHERE)
6852
 
          extra.append(STRING_WITH_LEN("; Using where"));
6853
 
        if (tab->packed_info & TAB_INFO_FULL_SCAN_ON_NULL)
6854
 
          extra.append(STRING_WITH_LEN("; Full scan on NULL key"));
6855
 
        /* Skip initial "; "*/
6856
 
        const char *str= extra.ptr();
6857
 
        uint32_t len= extra.length();
6858
 
        if (len)
6859
 
        {
6860
 
          str += 2;
6861
 
          len -= 2;
6862
 
        }
6863
 
        item_list.push_back(new Item_string(str, len, cs));
6864
 
      }
6865
 
      else
6866
 
      {
6867
 
        uint32_t keyno= MAX_KEY;
6868
 
        if (tab->ref.key_parts)
6869
 
          keyno= tab->ref.key;
6870
 
        else if (tab->select && tab->select->quick)
6871
 
          keyno = tab->select->quick->index;
6872
 
 
6873
 
        if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
6874
 
            quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
6875
 
            quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
6876
 
        {
6877
 
          extra.append(STRING_WITH_LEN("; Using "));
6878
 
          tab->select->quick->add_info_string(&extra);
6879
 
        }
6880
 
          if (tab->select)
6881
 
        {
6882
 
          if (tab->use_quick == 2)
6883
 
          {
6884
 
            /*
6885
 
             * To print out the bitset in tab->keys, we go through
6886
 
             * it 32 bits at a time. We need to do this to ensure
6887
 
             * that the to_ulong() method will not throw an
6888
 
             * out_of_range exception at runtime which would happen
6889
 
             * if the bitset we were working with was larger than 64
6890
 
             * bits on a 64-bit platform (for example).
6891
 
             */
6892
 
            stringstream s, w;
6893
 
            string str;
6894
 
            w << tab->keys;
6895
 
            w >> str;
6896
 
            for (uint32_t pos= 0; pos < tab->keys.size(); pos+= 32)
6897
 
            {
6898
 
              bitset<32> tmp(str, pos, 32);
6899
 
              if (tmp.any())
6900
 
                s << uppercase << hex << tmp.to_ulong();
6901
 
            }
6902
 
            extra.append(STRING_WITH_LEN("; Range checked for each "
6903
 
                                         "record (index map: 0x"));
6904
 
            extra.append(s.str().c_str());
6905
 
            extra.append(')');
6906
 
          }
6907
 
          else if (tab->select->cond)
6908
 
          {
6909
 
            extra.append(STRING_WITH_LEN("; Using where"));
6910
 
          }
6911
 
        }
6912
 
        if (key_read)
6913
 
        {
6914
 
          if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
6915
 
            extra.append(STRING_WITH_LEN("; Using index for group-by"));
6916
 
          else
6917
 
            extra.append(STRING_WITH_LEN("; Using index"));
6918
 
        }
6919
 
        if (table->reginfo.not_exists_optimize)
6920
 
          extra.append(STRING_WITH_LEN("; Not exists"));
6921
 
 
6922
 
        if (table_list->schema_table &&
6923
 
            table_list->schema_table->getRequestedObject() & OPTIMIZE_I_S_TABLE)
6924
 
        {
6925
 
          if (!table_list->table_open_method)
6926
 
            extra.append(STRING_WITH_LEN("; Skip_open_table"));
6927
 
          else if (table_list->table_open_method == OPEN_FRM_ONLY)
6928
 
            extra.append(STRING_WITH_LEN("; Open_frm_only"));
6929
 
          else
6930
 
            extra.append(STRING_WITH_LEN("; Open_full_table"));
6931
 
          if (table_list->has_db_lookup_value &&
6932
 
              table_list->has_table_lookup_value)
6933
 
            extra.append(STRING_WITH_LEN("; Scanned 0 databases"));
6934
 
          else if (table_list->has_db_lookup_value ||
6935
 
                   table_list->has_table_lookup_value)
6936
 
            extra.append(STRING_WITH_LEN("; Scanned 1 database"));
6937
 
          else
6938
 
            extra.append(STRING_WITH_LEN("; Scanned all databases"));
6939
 
        }
6940
 
        if (need_tmp_table)
6941
 
        {
6942
 
          need_tmp_table=0;
6943
 
          extra.append(STRING_WITH_LEN("; Using temporary"));
6944
 
        }
6945
 
        if (need_order)
6946
 
        {
6947
 
          need_order=0;
6948
 
          extra.append(STRING_WITH_LEN("; Using filesort"));
6949
 
        }
6950
 
        if (distinct & test_all_bits(used_tables,session->used_tables))
6951
 
          extra.append(STRING_WITH_LEN("; Distinct"));
6952
 
 
6953
 
        if (tab->insideout_match_tab)
6954
 
        {
6955
 
          extra.append(STRING_WITH_LEN("; LooseScan"));
6956
 
        }
6957
 
 
6958
 
        for (uint32_t part= 0; part < tab->ref.key_parts; part++)
6959
 
        {
6960
 
          if (tab->ref.cond_guards[part])
6961
 
          {
6962
 
            extra.append(STRING_WITH_LEN("; Full scan on NULL key"));
6963
 
            break;
6964
 
          }
6965
 
        }
6966
 
 
6967
 
        if (i > 0 && tab[-1].next_select == sub_select_cache)
6968
 
          extra.append(STRING_WITH_LEN("; Using join buffer"));
6969
 
 
6970
 
        /* Skip initial "; "*/
6971
 
        const char *str= extra.ptr();
6972
 
        uint32_t len= extra.length();
6973
 
        if (len)
6974
 
        {
6975
 
          str += 2;
6976
 
          len -= 2;
6977
 
        }
6978
 
        item_list.push_back(new Item_string(str, len, cs));
6979
 
      }
6980
 
      // For next iteration
6981
 
      used_tables|=table->map;
6982
 
      if (result->send_data(item_list))
6983
 
        join->error= 1;
6984
 
    }
6985
 
  }
6986
 
  for (Select_Lex_Unit *unit= join->select_lex->first_inner_unit();
6987
 
       unit;
6988
 
       unit= unit->next_unit())
6989
 
  {
6990
 
    if (mysql_explain_union(session, unit, result))
6991
 
      return;
6992
 
  }
6993
 
  return;
6994
 
}
6995
 
 
6996
 
bool mysql_explain_union(Session *session, Select_Lex_Unit *unit, select_result *result)
6997
 
{
6998
 
  bool res= false;
6999
 
  Select_Lex *first= unit->first_select();
7000
 
 
7001
 
  for (Select_Lex *sl= first;
7002
 
       sl;
7003
 
       sl= sl->next_select())
7004
 
  {
7005
 
    // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
7006
 
    uint8_t uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN);
7007
 
    sl->type= (((&session->lex->select_lex)==sl)?
7008
 
               (sl->first_inner_unit() || sl->next_select() ?
7009
 
                "PRIMARY" : "SIMPLE"):
7010
 
               ((sl == first)?
7011
 
                ((sl->linkage == DERIVED_TABLE_TYPE) ?
7012
 
                 "DERIVED":
7013
 
                 ((uncacheable & UNCACHEABLE_DEPENDENT) ?
7014
 
                  "DEPENDENT SUBQUERY":
7015
 
                  (uncacheable?"UNCACHEABLE SUBQUERY":
7016
 
                   "SUBQUERY"))):
7017
 
                ((uncacheable & UNCACHEABLE_DEPENDENT) ?
7018
 
                 "DEPENDENT UNION":
7019
 
                 uncacheable?"UNCACHEABLE UNION":
7020
 
                 "UNION")));
7021
 
    sl->options|= SELECT_DESCRIBE;
7022
 
  }
7023
 
  if (unit->is_union())
7024
 
  {
7025
 
    unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization
7026
 
    unit->fake_select_lex->type= "UNION RESULT";
7027
 
    unit->fake_select_lex->options|= SELECT_DESCRIBE;
7028
 
    if (!(res= unit->prepare(session, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
7029
 
      res= unit->exec();
7030
 
    res|= unit->cleanup();
7031
 
  }
7032
 
  else
7033
 
  {
7034
 
    session->lex->current_select= first;
7035
 
    unit->set_limit(unit->global_parameters);
7036
 
    res= mysql_select(session, &first->ref_pointer_array,
7037
 
                        (TableList*) first->table_list.first,
7038
 
                        first->with_wild, first->item_list,
7039
 
                        first->where,
7040
 
                        first->order_list.elements +
7041
 
                        first->group_list.elements,
7042
 
                        (order_st*) first->order_list.first,
7043
 
                        (order_st*) first->group_list.first,
7044
 
                        first->having,
7045
 
                        first->options | session->options | SELECT_DESCRIBE,
7046
 
                        result, unit, first);
7047
 
  }
7048
 
  return(res || session->is_error());
7049
 
}
7050
6540
 
7051
6541
static void print_table_array(Session *session, String *str, TableList **table,
7052
6542
                              TableList **end)
7077
6567
 
7078
6568
/**
7079
6569
  Print joins from the FROM clause.
7080
 
  @param session     thread handler
 
6570
  @param session     thread Cursor
7081
6571
  @param str     string where table should be printed
7082
6572
  @param tables  list of tables in join
7083
6573
  @query_type    type of the query is being generated
7212
6702
/**
7213
6703
  @} (end of group Query_Optimizer)
7214
6704
*/
 
6705
 
 
6706
} /* namespace drizzled */