46
46
#include "drizzled/item/outer_ref.h"
47
47
#include "drizzled/index_hint.h"
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>
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
#include "drizzled/optimizer/key_use.h"
55
56
#include <iostream>
79
static int sort_keyuse(KeyUse *a,KeyUse *b);
80
static int sort_keyuse(optimizer::KeyUse *a, optimizer::KeyUse *b);
80
81
static COND *build_equal_items(Session *session, COND *cond,
81
82
COND_EQUAL *inherited,
82
83
List<TableList> *join_list,
516
static int sort_keyuse(KeyUse *a,KeyUse *b)
517
static int sort_keyuse(optimizer::KeyUse *a, optimizer::KeyUse *b)
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);
520
if (a->getTable()->tablenr != b->getTable()->tablenr)
521
return static_cast<int>((a->getTable()->tablenr - b->getTable()->tablenr));
522
if (a->getKey() != b->getKey())
523
return static_cast<int>((a->getKey() - b->getKey()));
524
if (a->getKeypart() != b->getKeypart())
525
return static_cast<int>((a->getKeypart() - b->getKeypart()));
525
526
// 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))))
527
if ((res= test((a->getUsedTables() & ~OUTER_REF_TABLE_BIT)) -
528
test((b->getUsedTables() & ~OUTER_REF_TABLE_BIT))))
529
530
/* 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));
531
return static_cast<int>(((a->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL) -
532
(b->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL)));
593
594
field= end= key_fields;
595
if (my_init_dynamic_array(keyuse,sizeof(KeyUse),20,64))
596
if (my_init_dynamic_array(keyuse, sizeof(optimizer::KeyUse), 20, 64))
599
600
add_key_fields(join_tab->join, &end, &and_level, cond, normal_tables,
601
for (; field != end ; field++)
602
for (; field != end; field++)
603
add_key_part(keyuse,field);
604
add_key_part(keyuse, field);
604
605
/* 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;
606
if (field->getValue()->type() == Item::NULL_ITEM &&
607
! field->getField()->real_maybe_null())
609
field->getField()->table->reginfo.not_exists_optimize= 1;
610
for (i=0 ; i < tables ; i++)
613
for (i= 0; i < tables; i++)
613
616
Block the creation of keys for inner tables of outer joins.
652
655
if (keyuse->elements)
654
KeyUse key_end,*prev,*save_pos,*use;
657
optimizer::KeyUse key_end,*prev,*save_pos,*use;
656
my_qsort(keyuse->buffer,keyuse->elements,sizeof(KeyUse),
659
my_qsort(keyuse->buffer,keyuse->elements,sizeof(optimizer::KeyUse),
657
660
(qsort_cmp) sort_keyuse);
659
662
memset(&key_end, 0, sizeof(key_end)); /* Add for easy testing */
660
663
insert_dynamic(keyuse,(unsigned char*) &key_end);
662
use=save_pos=dynamic_element(keyuse,0,KeyUse*);
665
use= save_pos= dynamic_element(keyuse, 0, optimizer::KeyUse*);
665
for (i=0 ; i < keyuse->elements-1 ; i++,use++)
667
found_eq_constant= 0;
668
for (i= 0; i < keyuse->elements-1; i++, use++)
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)
670
if (! use->getUsedTables() && use->getOptimizeFlags() != KEY_OPTIMIZE_REF_OR_NULL)
671
use->getTable()->const_key_parts[use->getKey()]|= use->getKeypartMap();
672
if (use->getKey() == prev->getKey() && use->getTable() == prev->getTable())
671
if (prev->keypart+1 < use->keypart || ((prev->keypart == use->keypart) && found_eq_constant))
674
if (prev->getKeypart() + 1 < use->getKeypart() ||
675
((prev->getKeypart() == use->getKeypart()) && found_eq_constant))
672
676
continue; /* remove */
674
else if (use->keypart != 0) // First found must be 0
678
else if (use->getKeypart() != 0) // First found must be 0
677
681
#ifdef HAVE_purify
683
found_eq_constant= !use->used_tables;
687
found_eq_constant= ! use->getUsedTables();
684
688
/* 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);
689
if (! use->getTable()->reginfo.join_tab->keyuse)
690
use->getTable()->reginfo.join_tab->keyuse= save_pos;
691
use->getTable()->reginfo.join_tab->checked_keys.set(use->getKey());
690
i=(uint32_t) (save_pos-(KeyUse*) keyuse->buffer);
691
set_dynamic(keyuse,(unsigned char*) &key_end,i);
694
i= (uint32_t) (save_pos - (optimizer::KeyUse*) keyuse->buffer);
695
set_dynamic(keyuse, (unsigned char*) &key_end, i);
700
704
void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
702
KeyUse *end,*keyuse= dynamic_element(keyuse_array, 0, KeyUse*);
706
optimizer::KeyUse *end,*keyuse= dynamic_element(keyuse_array,
704
710
for (end= keyuse+ keyuse_array->elements ; keyuse < end ; keyuse++)
712
718
Constant tables are ignored.
713
719
To avoid bad matches, we don't make ref_table_rows less than 100.
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)))
721
keyuse->setTableRows(~(ha_rows) 0); // If no ref
722
if (keyuse->getUsedTables() & (map= (keyuse->getUsedTables() & ~join->const_table_map & ~OUTER_REF_TABLE_BIT)))
718
724
uint32_t tablenr;
719
725
for (tablenr=0 ; ! (map & 1) ; map>>=1, tablenr++) ;
720
726
if (map == 1) // Only one table
722
728
Table *tmp_table=join->all_tables[tablenr];
723
keyuse->ref_table_rows= max(tmp_table->file->stats.records, (ha_rows)100);
729
keyuse->setTableRows(max(tmp_table->file->stats.records, (ha_rows)100));
727
733
Outer reference (external field) is constant for single executing
730
if (keyuse->used_tables == OUTER_REF_TABLE_BIT)
731
keyuse->ref_table_rows= 1;
736
if (keyuse->getUsedTables() == OUTER_REF_TABLE_BIT)
737
keyuse->setTableRows(1);
886
892
StoredKey *get_store_key(Session *session,
893
optimizer::KeyUse *keyuse,
888
894
table_map used_tables,
889
KEY_PART_INFO *key_part,
895
KEY_PART_INFO *key_part,
890
896
unsigned char *key_buff,
891
897
uint32_t maybe_null)
893
if (!((~used_tables) & keyuse->used_tables)) // if const item
899
Item_ref *key_use_val= static_cast<Item_ref *>(keyuse->getVal());
900
Item_ref **dir_val= reinterpret_cast<Item_ref **>(key_use_val->ref);
901
if (! ((~used_tables) & keyuse->getUsedTables())) // if const item
895
903
return new store_key_const_item(session,
897
905
key_buff + maybe_null,
898
906
maybe_null ? key_buff : 0,
899
907
key_part->length,
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))
910
else if (key_use_val->type() == Item::FIELD_ITEM ||
911
(key_use_val->type() == Item::REF_ITEM &&
912
key_use_val->ref_type() == Item_ref::OUTER_REF &&
913
(*dir_val)->ref_type() == Item_ref::DIRECT_REF &&
914
key_use_val->real_item()->type() == Item::FIELD_ITEM))
908
916
return new store_key_field(session,
910
918
key_buff + maybe_null,
911
919
maybe_null ? key_buff : 0,
912
920
key_part->length,
913
((Item_field*) keyuse->val->real_item())->field,
914
keyuse->val->full_name());
921
((Item_field*) key_use_val->real_item())->field,
922
key_use_val->full_name());
915
924
return new store_key_item(session,
917
926
key_buff + maybe_null,
918
927
maybe_null ? key_buff : 0,
919
928
key_part->length,
963
bool create_ref_for_key(JOIN *join, JoinTable *j, KeyUse *org_keyuse,
964
table_map used_tables)
972
bool create_ref_for_key(JOIN *join,
974
optimizer::KeyUse *org_keyuse,
975
table_map used_tables)
966
KeyUse *keyuse=org_keyuse;
977
optimizer::KeyUse *keyuse= org_keyuse;
967
978
Session *session= join->session;
968
uint32_t keyparts,length,key;
972
985
/* Use best key from find_best */
975
keyinfo=table->key_info+key;
987
key= keyuse->getKey();
988
keyinfo= table->key_info + key;
979
992
uint32_t found_part_ref_or_null= 0;
981
994
Calculate length for the used key
987
if (!(~used_tables & keyuse->used_tables))
1000
if (! (~used_tables & keyuse->getUsedTables()))
989
if (keyparts == keyuse->keypart &&
990
!(found_part_ref_or_null & keyuse->optimize))
1002
if (keyparts == keyuse->getKeypart() &&
1003
! (found_part_ref_or_null & keyuse->getOptimizeFlags()))
993
length+= keyinfo->key_part[keyuse->keypart].store_length;
994
found_part_ref_or_null|= keyuse->optimize;
1006
length+= keyinfo->key_part[keyuse->getKeypart()].store_length;
1007
found_part_ref_or_null|= keyuse->getOptimizeFlags();
998
} while (keyuse->table == table && keyuse->key == key);
1011
} while (keyuse->getTable() == table && keyuse->getKey() == key);
1001
1014
/* set up fieldref */
1018
1031
keyuse=org_keyuse;
1020
1033
StoredKey **ref_key= j->ref.key_copy;
1021
unsigned char *key_buff=j->ref.key_buff, *null_ref_key= 0;
1034
unsigned char *key_buff= j->ref.key_buff, *null_ref_key= 0;
1022
1035
bool keyuse_uses_no_tables= true;
1025
for (i=0 ; i < keyparts ; keyuse++,i++)
1037
for (uint32_t i= 0; i < keyparts; keyuse++, i++)
1027
while (keyuse->keypart != i ||
1028
((~used_tables) & keyuse->used_tables))
1039
while (keyuse->getKeypart() != i ||
1040
((~used_tables) & keyuse->getUsedTables()))
1029
1041
keyuse++; /* Skip other parts */
1031
1043
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)
1044
j->ref.items[i]= keyuse->getVal(); // Save for cond removal
1045
j->ref.cond_guards[i]= keyuse->getConditionalGuard();
1046
if (keyuse->isNullRejected())
1035
1047
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))
1048
keyuse_uses_no_tables= keyuse_uses_no_tables && ! keyuse->getUsedTables();
1049
if (! keyuse->getUsedTables() && !(join->select_options & SELECT_DESCRIBE))
1038
1050
{ // Compare against constant
1039
1051
store_key_item tmp(session, keyinfo->key_part[i].field,
1040
1052
key_buff + maybe_null,
1041
1053
maybe_null ? key_buff : 0,
1042
keyinfo->key_part[i].length, keyuse->val);
1054
keyinfo->key_part[i].length, keyuse->getVal());
1043
1055
if (session->is_fatal_error)
1054
1066
But only if field _really_ can be null i.e. we force AM_REF
1055
1067
instead of AM_REF_OR_NULL in case if field can't be null
1057
if ((keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null)
1069
if ((keyuse->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null)
1058
1070
null_ref_key= key_buff;
1059
1071
key_buff+=keyinfo->key_part[i].store_length;
1062
*ref_key=0; // end_marker
1074
*ref_key= 0; // end_marker
1063
1075
if (j->type == AM_CONST)
1064
1076
j->table->const_table= 1;
1065
1077
else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) != HA_NOSAME) ||
1138
1150
void add_not_null_conds(JOIN *join)
1140
for (uint32_t i=join->const_tables ; i < join->tables ; i++)
1152
for (uint32_t i= join->const_tables; i < join->tables; i++)
1142
1154
JoinTable *tab=join->join_tab+i;
1143
1155
if ((tab->type == AM_REF || tab->type == AM_EQ_REF ||
2577
2589
if (possible_keys.any())
2579
2591
Table *field_tab= field->table;
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 ==
2592
optimizer::KeyUse *use;
2593
for (use= stat->keyuse; use && use->getTable() == field_tab; use++)
2594
if (possible_keys.test(use->getKey()) &&
2595
field_tab->key_info[use->getKey()].key_part[use->getKeypart()].field ==
2585
field_tab->const_key_parts[use->key]|= use->keypart_map;
2597
field_tab->const_key_parts[use->getKey()]|= use->getKeypartMap();
4493
4505
static int test_if_order_by_key(order_st *order, Table *table, uint32_t idx, uint32_t *used_key_parts)
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;
4507
KEY_PART_INFO *key_part= NULL;
4508
KEY_PART_INFO *key_part_end= NULL;
4509
key_part= table->key_info[idx].key_part;
4510
key_part_end= key_part + table->key_info[idx].key_parts;
4498
4511
key_part_map const_key_parts=table->const_key_parts[idx];
4500
4513
bool on_primary_key= false;
4502
4515
for (; order ; order=order->next, const_key_parts>>=1)
4577
4590
inline bool is_subkey(KEY_PART_INFO *key_part,
4578
4591
KEY_PART_INFO *ref_key_part,
4579
KEY_PART_INFO *ref_key_part_end)
4592
KEY_PART_INFO *ref_key_part_end)
4581
4594
for (; ref_key_part < ref_key_part_end; key_part++, ref_key_part++)
4582
if (!key_part->field->eq(ref_key_part->field))
4595
if (! key_part->field->eq(ref_key_part->field))
4663
4676
(table->key_info[keynr].flags & HA_NOSAME))
4665
4678
KEY *keyinfo= table->key_info + keynr;
4666
KEY_PART_INFO *key_part, *key_part_end;
4679
KEY_PART_INFO *key_part= NULL;
4680
KEY_PART_INFO *key_part_end= NULL;
4668
4682
for (key_part=keyinfo->key_part,
4669
4683
key_part_end=key_part+ keyinfo->key_parts;
4673
4687
if (key_part->field->maybe_null() ||
4674
!find_func(key_part->field, data))
4688
! find_func(key_part->field, data))
4677
4691
if (key_part == key_part_end)
4858
4872
"part1 = const1 AND part2=const2".
4859
4873
So we build tab->ref from scratch here.
4861
KeyUse *keyuse= tab->keyuse;
4862
while (keyuse->key != new_ref_key && keyuse->table == tab->table)
4875
optimizer::KeyUse *keyuse= tab->keyuse;
4876
while (keyuse->getKey() != new_ref_key && keyuse->getTable() == tab->table)
4865
4879
if (create_ref_for_key(tab->join, tab, keyuse,