1227
Check if given expression uses only table fields covered by the given index
1230
uses_index_fields_only()
1231
item Expression to check
1232
tbl The table having the index
1233
keyno The index number
1234
other_tbls_ok true <=> Fields of other non-const tables are allowed
1237
Check if given expression only uses fields covered by index #keyno in the
1238
table tbl. The expression can use any fields in any other tables.
1240
The expression is guaranteed not to be AND or OR - those constructs are
1241
handled outside of this function.
1247
static bool uses_index_fields_only(Item *item, Table *tbl, uint32_t keyno, bool other_tbls_ok)
1249
if (item->const_item())
1253
Don't push down the triggered conditions. Nested outer joins execution
1254
code may need to evaluate a condition several times (both triggered and
1255
untriggered), and there is no way to put thi
1256
TODO: Consider cloning the triggered condition and using the copies for:
1257
1. push the first copy down, to have most restrictive index condition
1259
2. Put the second copy into tab->select_cond.
1261
if (item->type() == Item::FUNC_ITEM &&
1262
((Item_func*)item)->functype() == Item_func::TRIG_COND_FUNC)
1265
if (!(item->used_tables() & tbl->map))
1266
return other_tbls_ok;
1268
Item::Type item_type= item->type();
1269
switch (item_type) {
1270
case Item::FUNC_ITEM:
1272
/* This is a function, apply condition recursively to arguments */
1273
Item_func *item_func= (Item_func*)item;
1275
Item **item_end= (item_func->arguments()) + item_func->argument_count();
1276
for (child= item_func->arguments(); child != item_end; child++)
1278
if (!uses_index_fields_only(*child, tbl, keyno, other_tbls_ok))
1283
case Item::COND_ITEM:
1285
/* This is a function, apply condition recursively to arguments */
1286
List_iterator<Item> li(*((Item_cond*)item)->argument_list());
1288
while ((list_item=li++))
1290
if (!uses_index_fields_only(item, tbl, keyno, other_tbls_ok))
1295
case Item::FIELD_ITEM:
1297
Item_field *item_field= (Item_field*)item;
1298
if (item_field->field->table != tbl)
1300
return item_field->field->part_of_key.test(keyno);
1302
case Item::REF_ITEM:
1303
return uses_index_fields_only(item->real_item(), tbl, keyno,
1306
return false; /* Play it safe, don't push unknown non-const items */
1212
1310
#define ICP_COND_USES_INDEX_ONLY 10
1313
Get a part of the condition that can be checked using only index fields
1316
make_cond_for_index()
1317
cond The source condition
1318
table The table that is partially available
1319
keyno The index in the above table. Only fields covered by the index
1321
other_tbls_ok true <=> Fields of other non-const tables are allowed
1324
Get a part of the condition that can be checked when for the given table
1325
we have values only of fields covered by some index. The condition may
1326
refer to other tables, it is assumed that we have values of all of their
1330
make_cond_for_index(
1331
"cond(t1.field) AND cond(t2.key1) AND cond(t2.non_key) AND cond(t2.key2)",
1334
"cond(t1.field) AND cond(t2.key2)"
1337
Index condition, or NULL if no condition could be inferred.
1339
static Item *make_cond_for_index(Item *cond, Table *table, uint32_t keyno, bool other_tbls_ok)
1343
if (cond->type() == Item::COND_ITEM)
1345
uint32_t n_marked= 0;
1346
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
1348
Item_cond_and *new_cond=new Item_cond_and;
1351
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1355
Item *fix= make_cond_for_index(item, table, keyno, other_tbls_ok);
1357
new_cond->argument_list()->push_back(fix);
1358
n_marked += test(item->marker == ICP_COND_USES_INDEX_ONLY);
1360
if (n_marked ==((Item_cond*)cond)->argument_list()->elements)
1361
cond->marker= ICP_COND_USES_INDEX_ONLY;
1362
switch (new_cond->argument_list()->elements) {
1366
return new_cond->argument_list()->head();
1368
new_cond->quick_fix_field();
1374
Item_cond_or *new_cond=new Item_cond_or;
1377
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1381
Item *fix= make_cond_for_index(item, table, keyno, other_tbls_ok);
1384
new_cond->argument_list()->push_back(fix);
1385
n_marked += test(item->marker == ICP_COND_USES_INDEX_ONLY);
1387
if (n_marked ==((Item_cond*)cond)->argument_list()->elements)
1388
cond->marker= ICP_COND_USES_INDEX_ONLY;
1389
new_cond->quick_fix_field();
1390
new_cond->top_level_item();
1395
if (!uses_index_fields_only(cond, table, keyno, other_tbls_ok))
1397
cond->marker= ICP_COND_USES_INDEX_ONLY;
1402
static Item *make_cond_remainder(Item *cond, bool exclude_index)
1404
if (exclude_index && cond->marker == ICP_COND_USES_INDEX_ONLY)
1405
return 0; /* Already checked */
1407
if (cond->type() == Item::COND_ITEM)
1409
table_map tbl_map= 0;
1410
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
1412
/* Create new top level AND item */
1413
Item_cond_and *new_cond=new Item_cond_and;
1416
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1420
Item *fix= make_cond_remainder(item, exclude_index);
1423
new_cond->argument_list()->push_back(fix);
1424
tbl_map |= fix->used_tables();
1427
switch (new_cond->argument_list()->elements) {
1431
return new_cond->argument_list()->head();
1433
new_cond->quick_fix_field();
1434
((Item_cond*)new_cond)->used_tables_cache= tbl_map;
1440
Item_cond_or *new_cond=new Item_cond_or;
1443
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1447
Item *fix= make_cond_remainder(item, false);
1450
new_cond->argument_list()->push_back(fix);
1451
tbl_map |= fix->used_tables();
1453
new_cond->quick_fix_field();
1454
((Item_cond*)new_cond)->used_tables_cache= tbl_map;
1455
new_cond->top_level_item();
1216
1463
cleanup JoinTable.
6555
Send a description about what how the select will be done to stdout.
6557
void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
6558
bool distinct,const char *message)
6560
List<Item> field_list;
6561
List<Item> item_list;
6562
Session *session=join->session;
6563
select_result *result=join->result;
6564
Item *item_null= new Item_null();
6565
const CHARSET_INFO * const cs= system_charset_info;
6567
/* Don't log this into the slow query log */
6568
session->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
6569
join->unit->offset_limit_cnt= 0;
6572
NOTE: the number/types of items pushed into item_list must be in sync with
6573
EXPLAIN column types as they're "defined" in Session::send_explain_fields()
6577
item_list.push_back(new Item_int((int32_t)
6578
join->select_lex->select_number));
6579
item_list.push_back(new Item_string(join->select_lex->type,
6580
strlen(join->select_lex->type), cs));
6581
for (uint32_t i=0 ; i < 7; i++)
6582
item_list.push_back(item_null);
6583
if (join->session->lex->describe & DESCRIBE_EXTENDED)
6584
item_list.push_back(item_null);
6586
item_list.push_back(new Item_string(message,strlen(message),cs));
6587
if (result->send_data(item_list))
6590
else if (join->select_lex == join->unit->fake_select_lex)
6593
here we assume that the query will return at least two rows, so we
6594
show "filesort" in EXPLAIN. Of course, sometimes we'll be wrong
6595
and no filesort will be actually done, but executing all selects in
6596
the UNION to provide precise EXPLAIN information will hardly be
6599
char table_name_buffer[NAME_LEN];
6602
item_list.push_back(new Item_null);
6604
item_list.push_back(new Item_string(join->select_lex->type,
6605
strlen(join->select_lex->type),
6609
Select_Lex *sl= join->unit->first_select();
6610
uint32_t len= 6, lastop= 0;
6611
memcpy(table_name_buffer, STRING_WITH_LEN("<union"));
6612
for (; sl && len + lastop + 5 < NAME_LEN; sl= sl->next_select())
6615
lastop= snprintf(table_name_buffer + len, NAME_LEN - len,
6616
"%u,", sl->select_number);
6618
if (sl || len + lastop >= NAME_LEN)
6620
memcpy(table_name_buffer + len, STRING_WITH_LEN("...>") + 1);
6626
table_name_buffer[len - 1]= '>'; // change ',' to '>'
6628
item_list.push_back(new Item_string(table_name_buffer, len, cs));
6631
item_list.push_back(new Item_string(access_method_str[AM_ALL].c_str(),
6632
access_method_str[AM_ALL].length(),
6635
item_list.push_back(item_null);
6637
item_list.push_back(item_null);
6639
item_list.push_back(item_null);
6641
item_list.push_back(item_null);
6643
if (join->session->lex->describe & DESCRIBE_EXTENDED)
6644
item_list.push_back(item_null);
6646
item_list.push_back(item_null);
6648
if (join->unit->global_parameters->order_list.first)
6649
item_list.push_back(new Item_string("Using filesort",
6652
item_list.push_back(new Item_string("", 0, cs));
6654
if (result->send_data(item_list))
6659
table_map used_tables=0;
6660
for (uint32_t i=0 ; i < join->tables ; i++)
6662
JoinTable *tab=join->join_tab+i;
6663
Table *table=tab->table;
6664
TableList *table_list= tab->table->pos_in_table_list;
6666
char buff1[512], buff2[512], buff3[512];
6667
char keylen_str_buf[64];
6668
String extra(buff, sizeof(buff),cs);
6669
char table_name_buffer[NAME_LEN];
6670
String tmp1(buff1,sizeof(buff1),cs);
6671
String tmp2(buff2,sizeof(buff2),cs);
6672
String tmp3(buff3,sizeof(buff3),cs);
6681
item_list.push_back(new Item_uint((uint32_t)
6682
join->select_lex->select_number));
6684
item_list.push_back(new Item_string(join->select_lex->type,
6685
strlen(join->select_lex->type),
6687
if (tab->type == AM_ALL && tab->select && tab->select->quick)
6689
quick_type= tab->select->quick->get_type();
6690
if ((quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) ||
6691
(quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) ||
6692
(quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION))
6693
tab->type = AM_INDEX_MERGE;
6695
tab->type = AM_RANGE;
6698
if (table->derived_select_number)
6700
/* Derived table name generation */
6701
int len= snprintf(table_name_buffer, sizeof(table_name_buffer)-1,
6703
table->derived_select_number);
6704
item_list.push_back(new Item_string(table_name_buffer, len, cs));
6708
TableList *real_table= table->pos_in_table_list;
6709
item_list.push_back(new Item_string(real_table->alias,
6710
strlen(real_table->alias),
6714
item_list.push_back(new Item_string(access_method_str[tab->type].c_str(),
6715
access_method_str[tab->type].length(),
6717
/* Build "possible_keys" value and add it to item_list */
6718
if (tab->keys.any())
6721
for (j=0 ; j < table->s->keys ; j++)
6723
if (tab->keys.test(j))
6727
tmp1.append(table->key_info[j].name,
6728
strlen(table->key_info[j].name),
6729
system_charset_info);
6734
item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),cs));
6736
item_list.push_back(item_null);
6738
/* Build "key", "key_len", and "ref" values and add them to item_list */
6739
if (tab->ref.key_parts)
6741
KEY *key_info=table->key_info+ tab->ref.key;
6742
register uint32_t length;
6743
item_list.push_back(new Item_string(key_info->name,
6744
strlen(key_info->name),
6745
system_charset_info));
6746
length= int64_t2str(tab->ref.key_length, keylen_str_buf, 10) -
6748
item_list.push_back(new Item_string(keylen_str_buf, length,
6749
system_charset_info));
6750
for (StoredKey **ref=tab->ref.key_copy ; *ref ; ref++)
6754
tmp2.append((*ref)->name(), strlen((*ref)->name()),
6755
system_charset_info);
6757
item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
6759
else if (tab->type == AM_NEXT)
6761
KEY *key_info=table->key_info+ tab->index;
6762
register uint32_t length;
6763
item_list.push_back(new Item_string(key_info->name,
6764
strlen(key_info->name),cs));
6765
length= int64_t2str(key_info->key_length, keylen_str_buf, 10) -
6767
item_list.push_back(new Item_string(keylen_str_buf,
6769
system_charset_info));
6770
item_list.push_back(item_null);
6772
else if (tab->select && tab->select->quick)
6774
tab->select->quick->add_keys_and_lengths(&tmp2, &tmp3);
6775
item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
6776
item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
6777
item_list.push_back(item_null);
6781
if (table_list->schema_table &&
6782
table_list->schema_table->getRequestedObject() & OPTIMIZE_I_S_TABLE)
6784
if (table_list->has_db_lookup_value)
6786
int f_idx= table_list->schema_table->getFirstColumnIndex();
6787
const string &tmp_buff= table_list->schema_table->getColumnName(f_idx);
6788
tmp2.append(tmp_buff.c_str(), tmp_buff.length(), cs);
6790
if (table_list->has_table_lookup_value)
6792
if (table_list->has_db_lookup_value)
6794
int f_idx= table_list->schema_table->getSecondColumnIndex();
6795
const string &tmp_buff= table_list->schema_table->getColumnName(f_idx);
6796
tmp2.append(tmp_buff.c_str(), tmp_buff.length(), cs);
6799
item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
6801
item_list.push_back(item_null);
6804
item_list.push_back(item_null);
6805
item_list.push_back(item_null);
6806
item_list.push_back(item_null);
6809
/* Add "rows" field to item_list. */
6810
if (table_list->schema_table)
6813
if (join->session->lex->describe & DESCRIBE_EXTENDED)
6814
item_list.push_back(item_null);
6816
item_list.push_back(item_null);
6820
double examined_rows;
6821
if (tab->select && tab->select->quick)
6822
examined_rows= rows2double(tab->select->quick->records);
6823
else if (tab->type == AM_NEXT || tab->type == AM_ALL)
6824
examined_rows= rows2double(tab->limit ? tab->limit :
6825
tab->table->file->records());
6828
optimizer::Position cur_pos= join->getPosFromOptimalPlan(i);
6829
examined_rows= cur_pos.getFanout();
6832
item_list.push_back(new Item_int((int64_t) (uint64_t) examined_rows,
6833
MY_INT64_NUM_DECIMAL_DIGITS));
6835
/* Add "filtered" field to item_list. */
6836
if (join->session->lex->describe & DESCRIBE_EXTENDED)
6841
optimizer::Position cur_pos= join->getPosFromOptimalPlan(i);
6842
f= (float) (100.0 * cur_pos.getFanout() /
6845
item_list.push_back(new Item_float(f, 2));
6849
/* Build "Extra" field and add it to item_list. */
6850
bool key_read=table->key_read;
6851
if ((tab->type == AM_NEXT || tab->type == AM_CONST) &&
6852
table->covering_keys.test(tab->index))
6854
if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
6855
!((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row)
6859
item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs));
6860
else if (tab->packed_info & TAB_INFO_HAVE_VALUE)
6862
if (tab->packed_info & TAB_INFO_USING_INDEX)
6863
extra.append(STRING_WITH_LEN("; Using index"));
6864
if (tab->packed_info & TAB_INFO_USING_WHERE)
6865
extra.append(STRING_WITH_LEN("; Using where"));
6866
if (tab->packed_info & TAB_INFO_FULL_SCAN_ON_NULL)
6867
extra.append(STRING_WITH_LEN("; Full scan on NULL key"));
6868
/* Skip initial "; "*/
6869
const char *str= extra.ptr();
6870
uint32_t len= extra.length();
6876
item_list.push_back(new Item_string(str, len, cs));
6880
uint32_t keyno= MAX_KEY;
6881
if (tab->ref.key_parts)
6882
keyno= tab->ref.key;
6883
else if (tab->select && tab->select->quick)
6884
keyno = tab->select->quick->index;
6886
if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
6887
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
6888
quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
6890
extra.append(STRING_WITH_LEN("; Using "));
6891
tab->select->quick->add_info_string(&extra);
6895
if (tab->use_quick == 2)
6898
* To print out the bitset in tab->keys, we go through
6899
* it 32 bits at a time. We need to do this to ensure
6900
* that the to_ulong() method will not throw an
6901
* out_of_range exception at runtime which would happen
6902
* if the bitset we were working with was larger than 64
6903
* bits on a 64-bit platform (for example).
6909
for (uint32_t pos= 0; pos < tab->keys.size(); pos+= 32)
6911
bitset<32> tmp(str, pos, 32);
6913
s << uppercase << hex << tmp.to_ulong();
6915
extra.append(STRING_WITH_LEN("; Range checked for each "
6916
"record (index map: 0x"));
6917
extra.append(s.str().c_str());
6920
else if (tab->select->cond)
6922
extra.append(STRING_WITH_LEN("; Using where"));
6927
if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
6928
extra.append(STRING_WITH_LEN("; Using index for group-by"));
6930
extra.append(STRING_WITH_LEN("; Using index"));
6932
if (table->reginfo.not_exists_optimize)
6933
extra.append(STRING_WITH_LEN("; Not exists"));
6935
if (table_list->schema_table &&
6936
table_list->schema_table->getRequestedObject() & OPTIMIZE_I_S_TABLE)
6938
if (!table_list->table_open_method)
6939
extra.append(STRING_WITH_LEN("; Skip_open_table"));
6940
else if (table_list->table_open_method == OPEN_FRM_ONLY)
6941
extra.append(STRING_WITH_LEN("; Open_frm_only"));
6943
extra.append(STRING_WITH_LEN("; Open_full_table"));
6944
if (table_list->has_db_lookup_value &&
6945
table_list->has_table_lookup_value)
6946
extra.append(STRING_WITH_LEN("; Scanned 0 databases"));
6947
else if (table_list->has_db_lookup_value ||
6948
table_list->has_table_lookup_value)
6949
extra.append(STRING_WITH_LEN("; Scanned 1 database"));
6951
extra.append(STRING_WITH_LEN("; Scanned all databases"));
6956
extra.append(STRING_WITH_LEN("; Using temporary"));
6961
extra.append(STRING_WITH_LEN("; Using filesort"));
6963
if (distinct & test_all_bits(used_tables,session->used_tables))
6964
extra.append(STRING_WITH_LEN("; Distinct"));
6966
if (tab->insideout_match_tab)
6968
extra.append(STRING_WITH_LEN("; LooseScan"));
6971
for (uint32_t part= 0; part < tab->ref.key_parts; part++)
6973
if (tab->ref.cond_guards[part])
6975
extra.append(STRING_WITH_LEN("; Full scan on NULL key"));
6980
if (i > 0 && tab[-1].next_select == sub_select_cache)
6981
extra.append(STRING_WITH_LEN("; Using join buffer"));
6983
/* Skip initial "; "*/
6984
const char *str= extra.ptr();
6985
uint32_t len= extra.length();
6991
item_list.push_back(new Item_string(str, len, cs));
6993
// For next iteration
6994
used_tables|=table->map;
6995
if (result->send_data(item_list))
6999
for (Select_Lex_Unit *unit= join->select_lex->first_inner_unit();
7001
unit= unit->next_unit())
7003
if (mysql_explain_union(session, unit, result))
7009
bool mysql_explain_union(Session *session, Select_Lex_Unit *unit, select_result *result)
7012
Select_Lex *first= unit->first_select();
7014
for (Select_Lex *sl= first;
7016
sl= sl->next_select())
7018
// drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
7019
uint8_t uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN);
7020
sl->type= (((&session->lex->select_lex)==sl)?
7021
(sl->first_inner_unit() || sl->next_select() ?
7022
"PRIMARY" : "SIMPLE"):
7024
((sl->linkage == DERIVED_TABLE_TYPE) ?
7026
((uncacheable & UNCACHEABLE_DEPENDENT) ?
7027
"DEPENDENT SUBQUERY":
7028
(uncacheable?"UNCACHEABLE SUBQUERY":
7030
((uncacheable & UNCACHEABLE_DEPENDENT) ?
7032
uncacheable?"UNCACHEABLE UNION":
7034
sl->options|= SELECT_DESCRIBE;
7036
if (unit->is_union())
7038
unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization
7039
unit->fake_select_lex->type= "UNION RESULT";
7040
unit->fake_select_lex->options|= SELECT_DESCRIBE;
7041
if (!(res= unit->prepare(session, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
7043
res|= unit->cleanup();
7047
session->lex->current_select= first;
7048
unit->set_limit(unit->global_parameters);
7049
res= mysql_select(session, &first->ref_pointer_array,
7050
(TableList*) first->table_list.first,
7051
first->with_wild, first->item_list,
7053
first->order_list.elements +
7054
first->group_list.elements,
7055
(order_st*) first->order_list.first,
7056
(order_st*) first->group_list.first,
7058
first->options | session->options | SELECT_DESCRIBE,
7059
result, unit, first);
7061
return(res || session->is_error());
6256
7064
static void print_table_array(Session *session, String *str, TableList **table,
6257
7065
TableList **end)