22 #include <drizzled/session.h>
23 #include <drizzled/item/uint.h>
24 #include <drizzled/item/float.h>
25 #include <drizzled/item/string.h>
26 #include <drizzled/optimizer/explain_plan.h>
27 #include <drizzled/optimizer/position.h>
28 #include <drizzled/optimizer/quick_ror_intersect_select.h>
29 #include <drizzled/optimizer/range.h>
30 #include <drizzled/sql_select.h>
32 #include <drizzled/internal/m_string.h>
33 #include <drizzled/select_result.h>
34 #include <drizzled/sql_lex.h>
46 static const string access_method_str[]=
63 static const string select_type_str[]=
69 "UNCACHEABLE SUBQUERY",
77 void optimizer::ExplainPlan::printPlan()
80 Session *session= join->session;
81 select_result *result= join->result;
82 Item *item_null=
new Item_null();
83 const charset_info_st *
const cs= system_charset_info;
86 session->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
87 join->unit->offset_limit_cnt= 0;
95 item_list.push_back(
new Item_int((int32_t)join->select_lex->select_number));
96 item_list.push_back(
new Item_string(select_type_str[join->select_lex->type], cs));
97 for (uint32_t i= 0; i < 7; i++)
98 item_list.push_back(item_null);
100 if (join->session->lex().describe & DESCRIBE_EXTENDED)
101 item_list.push_back(item_null);
103 item_list.push_back(
new Item_string(
str_ref(message), cs));
104 if (result->send_data(item_list))
107 else if (join->select_lex == join->unit->fake_select_lex)
116 char table_name_buffer[NAME_LEN];
119 item_list.push_back(
new Item_null);
121 item_list.push_back(
new Item_string(select_type_str[join->select_lex->type], cs));
124 Select_Lex *sl= join->unit->first_select();
125 uint32_t len= 6, lastop= 0;
126 memcpy(table_name_buffer, STRING_WITH_LEN(
"<union"));
127 for (; sl && len + lastop + 5 < NAME_LEN; sl= sl->next_select())
130 lastop= snprintf(table_name_buffer + len, NAME_LEN - len,
131 "%u,", sl->select_number);
133 if (sl || len + lastop >= NAME_LEN)
135 memcpy(table_name_buffer + len, STRING_WITH_LEN(
"...>") + 1);
141 table_name_buffer[len - 1]=
'>';
143 item_list.push_back(
new Item_string(table_name_buffer, len, cs));
146 item_list.push_back(
new Item_string(access_method_str[AM_ALL], cs));
148 item_list.push_back(item_null);
150 item_list.push_back(item_null);
152 item_list.push_back(item_null);
154 item_list.push_back(item_null);
156 if (join->session->lex().describe & DESCRIBE_EXTENDED)
157 item_list.push_back(item_null);
159 item_list.push_back(item_null);
161 if (join->unit->global_parameters->order_list.first)
162 item_list.push_back(
new Item_string(
str_ref(
"Using filesort"), cs));
164 item_list.push_back(
new Item_string(
str_ref(
""), cs));
166 if (result->send_data(item_list))
171 table_map used_tables= 0;
172 for (uint32_t i= 0; i < join->tables; i++)
174 JoinTable *tab= join->join_tab + i;
175 Table *table= tab->table;
176 char keylen_str_buf[64];
178 char table_name_buffer[NAME_LEN];
186 item_list.push_back(
new Item_uint((uint32_t)join->select_lex->select_number));
188 item_list.push_back(
new Item_string(select_type_str[join->select_lex->type], cs));
189 if (tab->type == AM_ALL && tab->select && tab->select->quick)
191 quick_type= tab->select->quick->get_type();
192 if ((quick_type == optimizer::QuickSelectInterface::QS_TYPE_INDEX_MERGE) ||
193 (quick_type == optimizer::QuickSelectInterface::QS_TYPE_ROR_INTERSECT) ||
194 (quick_type == optimizer::QuickSelectInterface::QS_TYPE_ROR_UNION))
195 tab->type = AM_INDEX_MERGE;
197 tab->type = AM_RANGE;
200 if (table->derived_select_number)
203 int len= snprintf(table_name_buffer,
204 sizeof(table_name_buffer)-1,
206 table->derived_select_number);
207 item_list.push_back(
new Item_string(table_name_buffer, len, cs));
211 TableList *real_table= table->pos_in_table_list;
212 item_list.push_back(
new Item_string(
str_ref(real_table->alias), cs));
215 item_list.push_back(
new Item_string(access_method_str[tab->type], cs));
219 for (uint32_t j= 0; j < table->getShare()->sizeKeys(); j++)
221 if (tab->keys.test(j))
225 tmp1.append(table->key_info[j].name,
226 strlen(table->key_info[j].name));
231 item_list.push_back(
new Item_string(tmp1, cs));
233 item_list.push_back(item_null);
236 if (tab->ref.key_parts)
238 KeyInfo *key_info= table->key_info+ tab->ref.key;
239 item_list.push_back(
new Item_string(
str_ref(key_info->name), system_charset_info));
240 uint32_t length= internal::int64_t2str(tab->ref.key_length, keylen_str_buf, 10) - keylen_str_buf;
241 item_list.push_back(
new Item_string(keylen_str_buf, length, system_charset_info));
242 for (StoredKey **ref= tab->ref.key_copy; *ref; ref++)
246 tmp2.append((*ref)->name(),
247 strlen((*ref)->name()));
249 item_list.push_back(
new Item_string(tmp2, cs));
251 else if (tab->type == AM_NEXT)
253 KeyInfo *key_info=table->key_info+ tab->index;
254 item_list.push_back(
new Item_string(
str_ref(key_info->name),cs));
255 uint32_t length= internal::int64_t2str(key_info->key_length, keylen_str_buf, 10) - keylen_str_buf;
256 item_list.push_back(
new Item_string(keylen_str_buf, length, system_charset_info));
257 item_list.push_back(item_null);
259 else if (tab->select && tab->select->quick)
261 tab->select->quick->add_keys_and_lengths(&tmp2, &tmp3);
262 item_list.push_back(
new Item_string(tmp2, cs));
263 item_list.push_back(
new Item_string(tmp3, cs));
264 item_list.push_back(item_null);
268 item_list.push_back(item_null);
269 item_list.push_back(item_null);
270 item_list.push_back(item_null);
274 double examined_rows;
275 if (tab->select && tab->select->quick)
277 examined_rows= tab->select->quick->records;
279 else if (tab->type == AM_NEXT || tab->type == AM_ALL)
281 examined_rows= tab->limit ? tab->limit : tab->table->cursor->records();
285 optimizer::Position cur_pos= join->getPosFromOptimalPlan(i);
286 examined_rows= cur_pos.getFanout();
289 item_list.push_back(
new Item_int((int64_t) (uint64_t) examined_rows,
290 MY_INT64_NUM_DECIMAL_DIGITS));
293 if (join->session->lex().describe & DESCRIBE_EXTENDED)
298 optimizer::Position cur_pos= join->getPosFromOptimalPlan(i);
299 f=
static_cast<float>(100.0 * cur_pos.getFanout() / examined_rows);
301 item_list.push_back(
new Item_float(f, 2));
305 bool key_read= table->key_read;
306 if ((tab->type == AM_NEXT || tab->type == AM_CONST) &&
307 table->covering_keys.test(tab->index))
309 if (quick_type == optimizer::QuickSelectInterface::QS_TYPE_ROR_INTERSECT &&
310 ! ((optimizer::QuickRorIntersectSelect *) tab->select->quick)->need_to_fetch_row)
314 item_list.push_back(
new Item_string(
str_ref(tab->info),cs));
315 else if (tab->packed_info & TAB_INFO_HAVE_VALUE)
317 if (tab->packed_info & TAB_INFO_USING_INDEX)
318 extra.append(
"; Using index");
319 if (tab->packed_info & TAB_INFO_USING_WHERE)
320 extra.append(
"; Using where");
321 if (tab->packed_info & TAB_INFO_FULL_SCAN_ON_NULL)
322 extra.append(
"; Full scan on NULL key");
325 item_list.push_back(
new Item_string(extra, cs));
329 if (quick_type == optimizer::QuickSelectInterface::QS_TYPE_ROR_UNION ||
330 quick_type == optimizer::QuickSelectInterface::QS_TYPE_ROR_INTERSECT ||
331 quick_type == optimizer::QuickSelectInterface::QS_TYPE_INDEX_MERGE)
333 extra.append(
"; Using ");
334 tab->select->quick->add_info_string(&extra);
338 if (tab->use_quick == 2)
352 for (uint32_t pos= 0; pos < tab->keys.size(); pos+= 32)
354 bitset<32> tmp(str, pos, 32);
356 s << uppercase << hex << tmp.to_ulong();
358 extra.append(
"; Range checked for each record (index map: 0x");
359 extra.append(s.str().c_str());
362 else if (tab->select->cond)
364 extra.append(
"; Using where");
369 if (quick_type == optimizer::QuickSelectInterface::QS_TYPE_GROUP_MIN_MAX)
370 extra.append(
"; Using index for group-by");
372 extra.append(
"; Using index");
374 if (table->reginfo.not_exists_optimize)
375 extra.append(
"; Not exists");
380 extra.append(
"; Using temporary");
385 extra.append(
"; Using filesort");
387 if (distinct & test_all_bits(used_tables,session->used_tables))
388 extra.append(
"; Distinct");
390 if (tab->insideout_match_tab)
392 extra.append(
"; LooseScan");
395 for (uint32_t part= 0; part < tab->ref.key_parts; part++)
397 if (tab->ref.cond_guards[part])
399 extra.append(
"; Full scan on NULL key");
404 if (i > 0 && tab[-1].next_select == sub_select_cache)
405 extra.append(
"; Using join buffer");
409 item_list.push_back(
new Item_string(extra, cs));
412 used_tables|=table->map;
413 if (result->send_data(item_list))
417 for (Select_Lex_Unit *unit= join->select_lex->first_inner_unit();
419 unit= unit->next_unit())
421 if (explainUnion(session, unit, result))
427 bool optimizer::ExplainPlan::explainUnion(Session *session,
428 Select_Lex_Unit *unit,
429 select_result *result)
432 Select_Lex *first= unit->first_select();
434 for (Select_Lex *sl= first;
436 sl= sl->next_select())
440 if (&session->lex().select_lex == sl)
442 if (sl->first_inner_unit() || sl->next_select())
444 sl->type= optimizer::ST_PRIMARY;
448 sl->type= optimizer::ST_SIMPLE;
455 if (sl->linkage == DERIVED_TABLE_TYPE)
457 sl->type= optimizer::ST_DERIVED;
461 if (sl->uncacheable.test(UNCACHEABLE_DEPENDENT))
463 sl->type= optimizer::ST_DEPENDENT_SUBQUERY;
467 if (sl->uncacheable.any())
469 sl->type= optimizer::ST_UNCACHEABLE_SUBQUERY;
473 sl->type= optimizer::ST_SUBQUERY;
480 if (sl->uncacheable.test(UNCACHEABLE_DEPENDENT))
482 sl->type= optimizer::ST_DEPENDENT_UNION;
486 if (sl->uncacheable.any())
488 sl->type= optimizer::ST_UNCACHEABLE_UNION;
492 sl->type= optimizer::ST_UNION;
497 sl->options|= SELECT_DESCRIBE;
500 if (unit->is_union())
502 unit->fake_select_lex->select_number= UINT_MAX;
503 unit->fake_select_lex->type= optimizer::ST_UNION_RESULT;
504 unit->fake_select_lex->options|= SELECT_DESCRIBE;
505 if (! (res= unit->prepare(session, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
509 res|= unit->cleanup();
513 session->lex().current_select= first;
514 unit->set_limit(unit->global_parameters);
516 &first->ref_pointer_array,
517 (TableList*) first->table_list.first,
521 first->order_list.elements + first->group_list.elements,
522 (Order*) first->order_list.first,
523 (Order*) first->group_list.first,
525 first->options | session->options | SELECT_DESCRIBE,
530 return (res || session->is_error());
TODO: Rename this file - func.h is stupid.
bool select_query(Session *session, Item ***rref_pointer_array, TableList *tables, uint32_t wild_num, List< Item > &fields, COND *conds, uint32_t og_num, Order *order, Order *group, Item *having, uint64_t select_options, select_result *result, Select_Lex_Unit *unit, Select_Lex *select_lex)
static const uint32_t UNCACHEABLE_EXPLAIN
forcing to save JOIN for explain