1226
Check if given expression uses only table fields covered by the given index
1229
uses_index_fields_only()
1230
item Expression to check
1231
tbl The table having the index
1232
keyno The index number
1233
other_tbls_ok true <=> Fields of other non-const tables are allowed
1236
Check if given expression only uses fields covered by index #keyno in the
1237
table tbl. The expression can use any fields in any other tables.
1239
The expression is guaranteed not to be AND or OR - those constructs are
1240
handled outside of this function.
1246
static bool uses_index_fields_only(Item *item, Table *tbl, uint32_t keyno, bool other_tbls_ok)
1248
if (item->const_item())
1252
Don't push down the triggered conditions. Nested outer joins execution
1253
code may need to evaluate a condition several times (both triggered and
1254
untriggered), and there is no way to put thi
1255
TODO: Consider cloning the triggered condition and using the copies for:
1256
1. push the first copy down, to have most restrictive index condition
1258
2. Put the second copy into tab->select_cond.
1260
if (item->type() == Item::FUNC_ITEM &&
1261
((Item_func*)item)->functype() == Item_func::TRIG_COND_FUNC)
1264
if (!(item->used_tables() & tbl->map))
1265
return other_tbls_ok;
1267
Item::Type item_type= item->type();
1268
switch (item_type) {
1269
case Item::FUNC_ITEM:
1271
/* This is a function, apply condition recursively to arguments */
1272
Item_func *item_func= (Item_func*)item;
1274
Item **item_end= (item_func->arguments()) + item_func->argument_count();
1275
for (child= item_func->arguments(); child != item_end; child++)
1277
if (!uses_index_fields_only(*child, tbl, keyno, other_tbls_ok))
1282
case Item::COND_ITEM:
1284
/* This is a function, apply condition recursively to arguments */
1285
List_iterator<Item> li(*((Item_cond*)item)->argument_list());
1287
while ((list_item=li++))
1289
if (!uses_index_fields_only(item, tbl, keyno, other_tbls_ok))
1294
case Item::FIELD_ITEM:
1296
Item_field *item_field= (Item_field*)item;
1297
if (item_field->field->table != tbl)
1299
return item_field->field->part_of_key.test(keyno);
1301
case Item::REF_ITEM:
1302
return uses_index_fields_only(item->real_item(), tbl, keyno,
1305
return false; /* Play it safe, don't push unknown non-const items */
1211
1309
#define ICP_COND_USES_INDEX_ONLY 10
1312
Get a part of the condition that can be checked using only index fields
1315
make_cond_for_index()
1316
cond The source condition
1317
table The table that is partially available
1318
keyno The index in the above table. Only fields covered by the index
1320
other_tbls_ok true <=> Fields of other non-const tables are allowed
1323
Get a part of the condition that can be checked when for the given table
1324
we have values only of fields covered by some index. The condition may
1325
refer to other tables, it is assumed that we have values of all of their
1329
make_cond_for_index(
1330
"cond(t1.field) AND cond(t2.key1) AND cond(t2.non_key) AND cond(t2.key2)",
1333
"cond(t1.field) AND cond(t2.key2)"
1336
Index condition, or NULL if no condition could be inferred.
1338
static Item *make_cond_for_index(Item *cond, Table *table, uint32_t keyno, bool other_tbls_ok)
1342
if (cond->type() == Item::COND_ITEM)
1344
uint32_t n_marked= 0;
1345
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
1347
Item_cond_and *new_cond=new Item_cond_and;
1350
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1354
Item *fix= make_cond_for_index(item, table, keyno, other_tbls_ok);
1356
new_cond->argument_list()->push_back(fix);
1357
n_marked += test(item->marker == ICP_COND_USES_INDEX_ONLY);
1359
if (n_marked ==((Item_cond*)cond)->argument_list()->elements)
1360
cond->marker= ICP_COND_USES_INDEX_ONLY;
1361
switch (new_cond->argument_list()->elements) {
1365
return new_cond->argument_list()->head();
1367
new_cond->quick_fix_field();
1373
Item_cond_or *new_cond=new Item_cond_or;
1376
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1380
Item *fix= make_cond_for_index(item, table, keyno, other_tbls_ok);
1383
new_cond->argument_list()->push_back(fix);
1384
n_marked += test(item->marker == ICP_COND_USES_INDEX_ONLY);
1386
if (n_marked ==((Item_cond*)cond)->argument_list()->elements)
1387
cond->marker= ICP_COND_USES_INDEX_ONLY;
1388
new_cond->quick_fix_field();
1389
new_cond->top_level_item();
1394
if (!uses_index_fields_only(cond, table, keyno, other_tbls_ok))
1396
cond->marker= ICP_COND_USES_INDEX_ONLY;
1401
static Item *make_cond_remainder(Item *cond, bool exclude_index)
1403
if (exclude_index && cond->marker == ICP_COND_USES_INDEX_ONLY)
1404
return 0; /* Already checked */
1406
if (cond->type() == Item::COND_ITEM)
1408
table_map tbl_map= 0;
1409
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
1411
/* Create new top level AND item */
1412
Item_cond_and *new_cond=new Item_cond_and;
1415
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1419
Item *fix= make_cond_remainder(item, exclude_index);
1422
new_cond->argument_list()->push_back(fix);
1423
tbl_map |= fix->used_tables();
1426
switch (new_cond->argument_list()->elements) {
1430
return new_cond->argument_list()->head();
1432
new_cond->quick_fix_field();
1433
((Item_cond*)new_cond)->used_tables_cache= tbl_map;
1439
Item_cond_or *new_cond=new Item_cond_or;
1442
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1446
Item *fix= make_cond_remainder(item, false);
1449
new_cond->argument_list()->push_back(fix);
1450
tbl_map |= fix->used_tables();
1452
new_cond->quick_fix_field();
1453
((Item_cond*)new_cond)->used_tables_cache= tbl_map;
1454
new_cond->top_level_item();
1215
1462
cleanup JoinTable.
6554
Send a description about what how the select will be done to stdout.
6556
void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
6557
bool distinct,const char *message)
6559
List<Item> field_list;
6560
List<Item> item_list;
6561
Session *session=join->session;
6562
select_result *result=join->result;
6563
Item *item_null= new Item_null();
6564
const CHARSET_INFO * const cs= system_charset_info;
6566
/* Don't log this into the slow query log */
6567
session->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
6568
join->unit->offset_limit_cnt= 0;
6571
NOTE: the number/types of items pushed into item_list must be in sync with
6572
EXPLAIN column types as they're "defined" in Session::send_explain_fields()
6576
item_list.push_back(new Item_int((int32_t)
6577
join->select_lex->select_number));
6578
item_list.push_back(new Item_string(join->select_lex->type,
6579
strlen(join->select_lex->type), cs));
6580
for (uint32_t i=0 ; i < 7; i++)
6581
item_list.push_back(item_null);
6582
if (join->session->lex->describe & DESCRIBE_EXTENDED)
6583
item_list.push_back(item_null);
6585
item_list.push_back(new Item_string(message,strlen(message),cs));
6586
if (result->send_data(item_list))
6589
else if (join->select_lex == join->unit->fake_select_lex)
6592
here we assume that the query will return at least two rows, so we
6593
show "filesort" in EXPLAIN. Of course, sometimes we'll be wrong
6594
and no filesort will be actually done, but executing all selects in
6595
the UNION to provide precise EXPLAIN information will hardly be
6598
char table_name_buffer[NAME_LEN];
6601
item_list.push_back(new Item_null);
6603
item_list.push_back(new Item_string(join->select_lex->type,
6604
strlen(join->select_lex->type),
6608
Select_Lex *sl= join->unit->first_select();
6609
uint32_t len= 6, lastop= 0;
6610
memcpy(table_name_buffer, STRING_WITH_LEN("<union"));
6611
for (; sl && len + lastop + 5 < NAME_LEN; sl= sl->next_select())
6614
lastop= snprintf(table_name_buffer + len, NAME_LEN - len,
6615
"%u,", sl->select_number);
6617
if (sl || len + lastop >= NAME_LEN)
6619
memcpy(table_name_buffer + len, STRING_WITH_LEN("...>") + 1);
6625
table_name_buffer[len - 1]= '>'; // change ',' to '>'
6627
item_list.push_back(new Item_string(table_name_buffer, len, cs));
6630
item_list.push_back(new Item_string(access_method_str[AM_ALL].c_str(),
6631
access_method_str[AM_ALL].length(),
6634
item_list.push_back(item_null);
6636
item_list.push_back(item_null);
6638
item_list.push_back(item_null);
6640
item_list.push_back(item_null);
6642
if (join->session->lex->describe & DESCRIBE_EXTENDED)
6643
item_list.push_back(item_null);
6645
item_list.push_back(item_null);
6647
if (join->unit->global_parameters->order_list.first)
6648
item_list.push_back(new Item_string("Using filesort",
6651
item_list.push_back(new Item_string("", 0, cs));
6653
if (result->send_data(item_list))
6658
table_map used_tables=0;
6659
for (uint32_t i=0 ; i < join->tables ; i++)
6661
JoinTable *tab=join->join_tab+i;
6662
Table *table=tab->table;
6663
TableList *table_list= tab->table->pos_in_table_list;
6665
char buff1[512], buff2[512], buff3[512];
6666
char keylen_str_buf[64];
6667
String extra(buff, sizeof(buff),cs);
6668
char table_name_buffer[NAME_LEN];
6669
String tmp1(buff1,sizeof(buff1),cs);
6670
String tmp2(buff2,sizeof(buff2),cs);
6671
String tmp3(buff3,sizeof(buff3),cs);
6680
item_list.push_back(new Item_uint((uint32_t)
6681
join->select_lex->select_number));
6683
item_list.push_back(new Item_string(join->select_lex->type,
6684
strlen(join->select_lex->type),
6686
if (tab->type == AM_ALL && tab->select && tab->select->quick)
6688
quick_type= tab->select->quick->get_type();
6689
if ((quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) ||
6690
(quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) ||
6691
(quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION))
6692
tab->type = AM_INDEX_MERGE;
6694
tab->type = AM_RANGE;
6697
if (table->derived_select_number)
6699
/* Derived table name generation */
6700
int len= snprintf(table_name_buffer, sizeof(table_name_buffer)-1,
6702
table->derived_select_number);
6703
item_list.push_back(new Item_string(table_name_buffer, len, cs));
6707
TableList *real_table= table->pos_in_table_list;
6708
item_list.push_back(new Item_string(real_table->alias,
6709
strlen(real_table->alias),
6713
item_list.push_back(new Item_string(access_method_str[tab->type].c_str(),
6714
access_method_str[tab->type].length(),
6716
/* Build "possible_keys" value and add it to item_list */
6717
if (tab->keys.any())
6720
for (j=0 ; j < table->s->keys ; j++)
6722
if (tab->keys.test(j))
6726
tmp1.append(table->key_info[j].name,
6727
strlen(table->key_info[j].name),
6728
system_charset_info);
6733
item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),cs));
6735
item_list.push_back(item_null);
6737
/* Build "key", "key_len", and "ref" values and add them to item_list */
6738
if (tab->ref.key_parts)
6740
KEY *key_info=table->key_info+ tab->ref.key;
6741
register uint32_t length;
6742
item_list.push_back(new Item_string(key_info->name,
6743
strlen(key_info->name),
6744
system_charset_info));
6745
length= int64_t2str(tab->ref.key_length, keylen_str_buf, 10) -
6747
item_list.push_back(new Item_string(keylen_str_buf, length,
6748
system_charset_info));
6749
for (StoredKey **ref=tab->ref.key_copy ; *ref ; ref++)
6753
tmp2.append((*ref)->name(), strlen((*ref)->name()),
6754
system_charset_info);
6756
item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
6758
else if (tab->type == AM_NEXT)
6760
KEY *key_info=table->key_info+ tab->index;
6761
register uint32_t length;
6762
item_list.push_back(new Item_string(key_info->name,
6763
strlen(key_info->name),cs));
6764
length= int64_t2str(key_info->key_length, keylen_str_buf, 10) -
6766
item_list.push_back(new Item_string(keylen_str_buf,
6768
system_charset_info));
6769
item_list.push_back(item_null);
6771
else if (tab->select && tab->select->quick)
6773
tab->select->quick->add_keys_and_lengths(&tmp2, &tmp3);
6774
item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
6775
item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
6776
item_list.push_back(item_null);
6780
if (table_list->schema_table &&
6781
table_list->schema_table->getRequestedObject() & OPTIMIZE_I_S_TABLE)
6783
if (table_list->has_db_lookup_value)
6785
int f_idx= table_list->schema_table->getFirstColumnIndex();
6786
const string &tmp_buff= table_list->schema_table->getColumnName(f_idx);
6787
tmp2.append(tmp_buff.c_str(), tmp_buff.length(), cs);
6789
if (table_list->has_table_lookup_value)
6791
if (table_list->has_db_lookup_value)
6793
int f_idx= table_list->schema_table->getSecondColumnIndex();
6794
const string &tmp_buff= table_list->schema_table->getColumnName(f_idx);
6795
tmp2.append(tmp_buff.c_str(), tmp_buff.length(), cs);
6798
item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
6800
item_list.push_back(item_null);
6803
item_list.push_back(item_null);
6804
item_list.push_back(item_null);
6805
item_list.push_back(item_null);
6808
/* Add "rows" field to item_list. */
6809
if (table_list->schema_table)
6812
if (join->session->lex->describe & DESCRIBE_EXTENDED)
6813
item_list.push_back(item_null);
6815
item_list.push_back(item_null);
6819
double examined_rows;
6820
if (tab->select && tab->select->quick)
6821
examined_rows= rows2double(tab->select->quick->records);
6822
else if (tab->type == AM_NEXT || tab->type == AM_ALL)
6823
examined_rows= rows2double(tab->limit ? tab->limit :
6824
tab->table->cursor->records());
6827
optimizer::Position cur_pos= join->getPosFromOptimalPlan(i);
6828
examined_rows= cur_pos.getFanout();
6831
item_list.push_back(new Item_int((int64_t) (uint64_t) examined_rows,
6832
MY_INT64_NUM_DECIMAL_DIGITS));
6834
/* Add "filtered" field to item_list. */
6835
if (join->session->lex->describe & DESCRIBE_EXTENDED)
6840
optimizer::Position cur_pos= join->getPosFromOptimalPlan(i);
6841
f= (float) (100.0 * cur_pos.getFanout() /
6844
item_list.push_back(new Item_float(f, 2));
6848
/* Build "Extra" field and add it to item_list. */
6849
bool key_read=table->key_read;
6850
if ((tab->type == AM_NEXT || tab->type == AM_CONST) &&
6851
table->covering_keys.test(tab->index))
6853
if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
6854
!((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row)
6858
item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs));
6859
else if (tab->packed_info & TAB_INFO_HAVE_VALUE)
6861
if (tab->packed_info & TAB_INFO_USING_INDEX)
6862
extra.append(STRING_WITH_LEN("; Using index"));
6863
if (tab->packed_info & TAB_INFO_USING_WHERE)
6864
extra.append(STRING_WITH_LEN("; Using where"));
6865
if (tab->packed_info & TAB_INFO_FULL_SCAN_ON_NULL)
6866
extra.append(STRING_WITH_LEN("; Full scan on NULL key"));
6867
/* Skip initial "; "*/
6868
const char *str= extra.ptr();
6869
uint32_t len= extra.length();
6875
item_list.push_back(new Item_string(str, len, cs));
6879
uint32_t keyno= MAX_KEY;
6880
if (tab->ref.key_parts)
6881
keyno= tab->ref.key;
6882
else if (tab->select && tab->select->quick)
6883
keyno = tab->select->quick->index;
6885
if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
6886
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
6887
quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
6889
extra.append(STRING_WITH_LEN("; Using "));
6890
tab->select->quick->add_info_string(&extra);
6894
if (tab->use_quick == 2)
6897
* To print out the bitset in tab->keys, we go through
6898
* it 32 bits at a time. We need to do this to ensure
6899
* that the to_ulong() method will not throw an
6900
* out_of_range exception at runtime which would happen
6901
* if the bitset we were working with was larger than 64
6902
* bits on a 64-bit platform (for example).
6908
for (uint32_t pos= 0; pos < tab->keys.size(); pos+= 32)
6910
bitset<32> tmp(str, pos, 32);
6912
s << uppercase << hex << tmp.to_ulong();
6914
extra.append(STRING_WITH_LEN("; Range checked for each "
6915
"record (index map: 0x"));
6916
extra.append(s.str().c_str());
6919
else if (tab->select->cond)
6921
extra.append(STRING_WITH_LEN("; Using where"));
6926
if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
6927
extra.append(STRING_WITH_LEN("; Using index for group-by"));
6929
extra.append(STRING_WITH_LEN("; Using index"));
6931
if (table->reginfo.not_exists_optimize)
6932
extra.append(STRING_WITH_LEN("; Not exists"));
6934
if (table_list->schema_table &&
6935
table_list->schema_table->getRequestedObject() & OPTIMIZE_I_S_TABLE)
6937
if (!table_list->table_open_method)
6938
extra.append(STRING_WITH_LEN("; Skip_open_table"));
6939
else if (table_list->table_open_method == OPEN_FRM_ONLY)
6940
extra.append(STRING_WITH_LEN("; Open_frm_only"));
6942
extra.append(STRING_WITH_LEN("; Open_full_table"));
6943
if (table_list->has_db_lookup_value &&
6944
table_list->has_table_lookup_value)
6945
extra.append(STRING_WITH_LEN("; Scanned 0 databases"));
6946
else if (table_list->has_db_lookup_value ||
6947
table_list->has_table_lookup_value)
6948
extra.append(STRING_WITH_LEN("; Scanned 1 database"));
6950
extra.append(STRING_WITH_LEN("; Scanned all databases"));
6955
extra.append(STRING_WITH_LEN("; Using temporary"));
6960
extra.append(STRING_WITH_LEN("; Using filesort"));
6962
if (distinct & test_all_bits(used_tables,session->used_tables))
6963
extra.append(STRING_WITH_LEN("; Distinct"));
6965
if (tab->insideout_match_tab)
6967
extra.append(STRING_WITH_LEN("; LooseScan"));
6970
for (uint32_t part= 0; part < tab->ref.key_parts; part++)
6972
if (tab->ref.cond_guards[part])
6974
extra.append(STRING_WITH_LEN("; Full scan on NULL key"));
6979
if (i > 0 && tab[-1].next_select == sub_select_cache)
6980
extra.append(STRING_WITH_LEN("; Using join buffer"));
6982
/* Skip initial "; "*/
6983
const char *str= extra.ptr();
6984
uint32_t len= extra.length();
6990
item_list.push_back(new Item_string(str, len, cs));
6992
// For next iteration
6993
used_tables|=table->map;
6994
if (result->send_data(item_list))
6998
for (Select_Lex_Unit *unit= join->select_lex->first_inner_unit();
7000
unit= unit->next_unit())
7002
if (mysql_explain_union(session, unit, result))
7008
bool mysql_explain_union(Session *session, Select_Lex_Unit *unit, select_result *result)
7011
Select_Lex *first= unit->first_select();
7013
for (Select_Lex *sl= first;
7015
sl= sl->next_select())
7017
// drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
7018
uint8_t uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN);
7019
sl->type= (((&session->lex->select_lex)==sl)?
7020
(sl->first_inner_unit() || sl->next_select() ?
7021
"PRIMARY" : "SIMPLE"):
7023
((sl->linkage == DERIVED_TABLE_TYPE) ?
7025
((uncacheable & UNCACHEABLE_DEPENDENT) ?
7026
"DEPENDENT SUBQUERY":
7027
(uncacheable?"UNCACHEABLE SUBQUERY":
7029
((uncacheable & UNCACHEABLE_DEPENDENT) ?
7031
uncacheable?"UNCACHEABLE UNION":
7033
sl->options|= SELECT_DESCRIBE;
7035
if (unit->is_union())
7037
unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization
7038
unit->fake_select_lex->type= "UNION RESULT";
7039
unit->fake_select_lex->options|= SELECT_DESCRIBE;
7040
if (!(res= unit->prepare(session, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
7042
res|= unit->cleanup();
7046
session->lex->current_select= first;
7047
unit->set_limit(unit->global_parameters);
7048
res= mysql_select(session, &first->ref_pointer_array,
7049
(TableList*) first->table_list.first,
7050
first->with_wild, first->item_list,
7052
first->order_list.elements +
7053
first->group_list.elements,
7054
(order_st*) first->order_list.first,
7055
(order_st*) first->group_list.first,
7057
first->options | session->options | SELECT_DESCRIBE,
7058
result, unit, first);
7060
return(res || session->is_error());
6320
7063
static void print_table_array(Session *session, String *str, TableList **table,
6321
7064
TableList **end)