3311
3311
/* Test how we can use keys */
3312
3312
rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE; // Assumed records/key
3313
for (keyuse=s->keyuse ; keyuse->table == table ;)
3313
for (keyuse= s->keyuse; keyuse->getTable() == table ;)
3315
3315
key_part_map found_part= 0;
3316
3316
table_map found_ref= 0;
3317
uint32_t key= keyuse->key;
3318
KEY *keyinfo= table->key_info+key;
3317
uint32_t key= keyuse->getKey();
3318
KEY *keyinfo= table->key_info + key;
3319
3319
/* Bitmap of keyparts where the ref access is over 'keypart=const': */
3320
3320
key_part_map const_part= 0;
3321
3321
/* The or-null keypart in ref-or-null access: */
3327
3327
do /* For each keypart */
3329
uint32_t keypart= keyuse->keypart;
3329
uint32_t keypart= keyuse->getKeypart();
3330
3330
table_map best_part_found_ref= 0;
3331
3331
double best_prev_record_reads= DBL_MAX;
3337
3337
if 1. expression doesn't refer to forward tables
3338
3338
2. we won't get two ref-or-null's
3340
if (!(remaining_tables & keyuse->used_tables) &&
3341
!(ref_or_null_part && (keyuse->optimize &
3342
KEY_OPTIMIZE_REF_OR_NULL)))
3340
if (! (remaining_tables & keyuse->getUsedTables()) &&
3341
! (ref_or_null_part && (keyuse->getOptimizeFlags() &
3342
KEY_OPTIMIZE_REF_OR_NULL)))
3344
found_part|= keyuse->keypart_map;
3345
if (!(keyuse->used_tables & ~join->const_table_map))
3346
const_part|= keyuse->keypart_map;
3344
found_part|= keyuse->getKeypartMap();
3345
if (! (keyuse->getUsedTables() & ~join->const_table_map))
3346
const_part|= keyuse->getKeypartMap();
3348
3348
double tmp2= prev_record_reads(join, idx, (found_ref |
3349
keyuse->used_tables));
3349
keyuse->getUsedTables()));
3350
3350
if (tmp2 < best_prev_record_reads)
3352
best_part_found_ref= keyuse->used_tables & ~join->const_table_map;
3352
best_part_found_ref= keyuse->getUsedTables() & ~join->const_table_map;
3353
3353
best_prev_record_reads= tmp2;
3355
if (rec > keyuse->ref_table_rows)
3356
rec= keyuse->ref_table_rows;
3355
if (rec > keyuse->getTableRows())
3356
rec= keyuse->getTableRows();
3358
3358
If there is one 'key_column IS NULL' expression, we can
3359
3359
use this ref_or_null optimisation of this field
3361
if (keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL)
3362
ref_or_null_part |= keyuse->keypart_map;
3361
if (keyuse->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL)
3362
ref_or_null_part|= keyuse->getKeypartMap();
3366
} while (keyuse->table == table && keyuse->key == key &&
3367
keyuse->keypart == keypart);
3368
found_ref|= best_part_found_ref;
3369
} while (keyuse->table == table && keyuse->key == key);
3366
} while (keyuse->getTable() == table && keyuse->getKey() == key &&
3367
keyuse->getKeypart() == keypart);
3368
found_ref|= best_part_found_ref;
3369
} while (keyuse->getTable() == table && keyuse->getKey() == key);
3372
3372
Assume that that each key matches a proportional part of table.
3676
3676
if ((records >= s->found_records || best > s->read_time) && // (1)
3677
!(s->quick && best_key && s->quick->index == best_key->key && // (2)
3678
best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2)
3679
!((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) && // (3)
3680
! s->table->covering_keys.none() && best_key && !s->quick) &&// (3)
3681
!(s->table->force_index && best_key && !s->quick)) // (4)
3677
! (s->quick && best_key && s->quick->index == best_key->getKey() && // (2)
3678
best_max_key_part >= s->table->quick_key_parts[best_key->getKey()]) &&// (2)
3679
! ((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) && // (3)
3680
! s->table->covering_keys.none() && best_key && !s->quick) && // (3)
3681
! (s->table->force_index && best_key && !s->quick)) // (4)
3682
3682
{ // Check full join
3683
3683
ha_rows rnd_records= s->found_records;
5712
5712
TODO. Apply single row substitution to null complemented inner tables
5713
5713
for nested outer join operations.
5715
while (keyuse->table == table)
5715
while (keyuse->getTable() == table)
5717
if (!(keyuse->val->used_tables() & ~join->const_table_map) &&
5718
keyuse->val->is_null() && keyuse->null_rejecting)
5717
if (! (keyuse->getVal()->used_tables() & ~join->const_table_map) &&
5718
keyuse->getVal()->is_null() && keyuse->isNullRejected())
5720
5720
s->type= AM_CONST;
5721
5721
table->mark_as_null_row();
5756
5756
if ((keyuse=s->keyuse))
5758
5758
s->type= AM_REF;
5759
while (keyuse->table == table)
5759
while (keyuse->getTable() == table)
5761
start_keyuse=keyuse;
5761
start_keyuse= keyuse;
5762
key= keyuse->getKey();
5763
5763
s->keys.set(key); // QQ: remove this ?
5767
5767
eq_part.reset();
5770
if (keyuse->val->type() != Item::NULL_ITEM && !keyuse->optimize)
5770
if (keyuse->getVal()->type() != Item::NULL_ITEM &&
5771
! keyuse->getOptimizeFlags())
5772
if (!((~found_const_table_map) & keyuse->used_tables))
5773
const_ref.set(keyuse->keypart);
5773
if (! ((~found_const_table_map) & keyuse->getUsedTables()))
5774
const_ref.set(keyuse->getKeypart());
5775
refs|=keyuse->used_tables;
5776
eq_part.set(keyuse->keypart);
5776
refs|= keyuse->getUsedTables();
5777
eq_part.set(keyuse->getKeypart());
5779
} while (keyuse->table == table && keyuse->key == key);
5780
} while (keyuse->getTable() == table && keyuse->getKey() == key);
5781
5782
if (is_keymap_prefix(eq_part, table->key_info[key].key_parts) &&
5782
!table->pos_in_table_list->embedding)
5783
! table->pos_in_table_list->embedding)
5784
5785
if ((table->key_info[key].flags & (HA_NOSAME)) == HA_NOSAME)