diff options
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 166 |
1 files changed, 104 insertions, 62 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 436a2f6ce5d..ff93aa6d103 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1444,7 +1444,8 @@ TODO: make view to decide if it is possible to write to WHERE directly or make S Perform the optimization on fields evaluation mentioned above for all on expressions. */ - for (JOIN_TAB *tab= first_linear_tab(this, WITHOUT_CONST_TABLES); tab; + JOIN_TAB *tab; + for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) { if (*tab->on_expr_ref) @@ -1467,7 +1468,7 @@ TODO: make view to decide if it is possible to write to WHERE directly or make S Perform the optimization on fields evaliation mentioned above for all used ref items. */ - for (JOIN_TAB *tab= first_linear_tab(this, WITHOUT_CONST_TABLES); tab; + for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) { uint key_copy_index=0; @@ -2107,7 +2108,8 @@ bool JOIN::setup_subquery_caches() if (conds) conds= conds->transform(&Item::expr_cache_insert_transformer, (uchar*) thd); - for (JOIN_TAB *tab= first_linear_tab(this, WITHOUT_CONST_TABLES); + JOIN_TAB *tab; + for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) { if (tab->select_cond) @@ -2269,7 +2271,8 @@ JOIN::reinit() /* need to reset ref access state (see join_read_key) */ if (join_tab) { - for (JOIN_TAB *tab= first_linear_tab(this, WITH_CONST_TABLES); tab; + JOIN_TAB *tab; + for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITH_CONST_TABLES); tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) { tab->ref.key_err= TRUE; @@ -2531,7 +2534,7 @@ void JOIN::exec_inner() Item *cur_const_item; while ((cur_const_item= const_item_it++)) { - cur_const_item->val_str(&cur_const_item->str_value); + cur_const_item->val_str(); // This caches val_str() to Item::str_value if (thd->is_error()) { error= thd->is_error(); @@ -3137,8 +3140,9 @@ JOIN::destroy() { if (join_tab != tmp_join->join_tab) { - for (JOIN_TAB *tab= first_linear_tab(this, WITH_CONST_TABLES); tab; - tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) + JOIN_TAB *tab; + for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITH_CONST_TABLES); + tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) { tab->cleanup(); } @@ -8211,14 +8215,24 @@ JOIN_TAB *next_top_level_tab(JOIN *join, JOIN_TAB *tab) } -JOIN_TAB *first_linear_tab(JOIN *join, enum enum_with_const_tables const_tbls) +JOIN_TAB *first_linear_tab(JOIN *join, + enum enum_with_bush_roots include_bush_roots, + enum enum_with_const_tables const_tbls) { JOIN_TAB *first= join->join_tab; if (const_tbls == WITHOUT_CONST_TABLES) first+= join->const_tables; - if (first < join->join_tab + join->top_join_tab_count) - return first; - return NULL; /* All tables were const tables */ + + if (first >= join->join_tab + join->top_join_tab_count) + return NULL; /* All are const tables */ + + if (first->bush_children && include_bush_roots == WITHOUT_BUSH_ROOTS) + { + /* This JOIN_TAB is a SJM nest; Start from first table in nest */ + return first->bush_children->start; + } + + return first; } @@ -9084,9 +9098,10 @@ inline void add_cond_and_fix(THD *thd, Item **e1, Item *e2) static void add_not_null_conds(JOIN *join) { + JOIN_TAB *tab; DBUG_ENTER("add_not_null_conds"); - for (JOIN_TAB *tab= first_linear_tab(join, WITHOUT_CONST_TABLES); + for (tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS)) { @@ -9257,7 +9272,7 @@ make_outerjoin_info(JOIN *join) tab->table->pos_in_table_list being set. */ JOIN_TAB *tab; - for (tab= first_linear_tab(join, WITHOUT_CONST_TABLES); + for (tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS)) { @@ -9269,7 +9284,7 @@ make_outerjoin_info(JOIN *join) } } - for (JOIN_TAB *tab= first_linear_tab(join, WITHOUT_CONST_TABLES); tab; + for (JOIN_TAB *tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS)) { TABLE *table= tab->table; @@ -9901,6 +9916,25 @@ uint get_next_field_for_derived_key(uchar *arg) } +static +uint get_next_field_for_derived_key_simple(uchar *arg) +{ + KEYUSE *keyuse= *(KEYUSE **) arg; + if (!keyuse) + return (uint) (-1); + TABLE *table= keyuse->table; + uint key= keyuse->key; + uint fldno= keyuse->keypart; + for ( ; + keyuse->table == table && keyuse->key == key && keyuse->keypart == fldno; + keyuse++) + ; + if (keyuse->key != key) + keyuse= 0; + *((KEYUSE **) arg)= keyuse; + return fldno; +} + static bool generate_derived_keys_for_table(KEYUSE *keyuse, uint count, uint keys) { @@ -9931,12 +9965,28 @@ bool generate_derived_keys_for_table(KEYUSE *keyuse, uint count, uint keys) } else { - if (table->add_tmp_key(table->s->keys, parts, - get_next_field_for_derived_key, - (uchar *) &first_keyuse, - FALSE)) - return TRUE; - table->reginfo.join_tab->keys.set_bit(table->s->keys); + KEYUSE *save_first_keyuse= first_keyuse; + if (table->check_tmp_key(table->s->keys, parts, + get_next_field_for_derived_key_simple, + (uchar *) &first_keyuse)) + + { + first_keyuse= save_first_keyuse; + if (table->add_tmp_key(table->s->keys, parts, + get_next_field_for_derived_key, + (uchar *) &first_keyuse, + FALSE)) + return TRUE; + table->reginfo.join_tab->keys.set_bit(table->s->keys); + } + else + { + /* Mark keyuses for this key to be excluded */ + for (KEYUSE *curr=save_first_keyuse; curr < first_keyuse; curr++) + { + curr->key= MAX_KEY; + } + } first_keyuse= keyuse; key_count++; parts= 0; @@ -10023,7 +10073,7 @@ bool generate_derived_keys(DYNAMIC_ARRAY *keyuse_array) void JOIN::drop_unused_derived_keys() { JOIN_TAB *tab; - for (tab= first_linear_tab(this, WITHOUT_CONST_TABLES); + for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) { @@ -10711,7 +10761,7 @@ void check_join_cache_usage_for_tables(JOIN *join, ulonglong options, JOIN_TAB *tab; JOIN_TAB *prev_tab; - for (tab= first_linear_tab(join, WITHOUT_CONST_TABLES); + for (tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS)) { @@ -10719,7 +10769,7 @@ void check_join_cache_usage_for_tables(JOIN *join, ulonglong options, } uint idx= join->const_tables; - for (tab= first_linear_tab(join, WITHOUT_CONST_TABLES); + for (tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS)) { @@ -10893,7 +10943,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) tab->partial_join_cardinality= 1; JOIN_TAB *prev_tab= NULL; - for (tab= first_linear_tab(join, WITHOUT_CONST_TABLES), i= join->const_tables; + i= join->const_tables; + for (tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; prev_tab=tab, tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS)) { @@ -10918,7 +10969,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) check_join_cache_usage_for_tables(join, options, no_jbuf_after); JOIN_TAB *first_tab; - for (tab= first_tab= first_linear_tab(join, WITHOUT_CONST_TABLES); + for (tab= first_tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS)) { @@ -11612,7 +11663,8 @@ void JOIN::cleanup(bool full) } if (full) { - JOIN_TAB *sort_tab= first_linear_tab(this, WITHOUT_CONST_TABLES); + JOIN_TAB *sort_tab= first_linear_tab(this, WITH_BUSH_ROOTS, + WITHOUT_CONST_TABLES); if (pre_sort_join_tab) { if (sort_tab && sort_tab->select == pre_sort_join_tab->select) @@ -11659,7 +11711,7 @@ void JOIN::cleanup(bool full) } else { - for (tab= first_linear_tab(this, WITH_CONST_TABLES); tab; + for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITH_CONST_TABLES); tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) { if (tab->table) @@ -11821,7 +11873,9 @@ only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables) static void update_depend_map(JOIN *join) { - for (JOIN_TAB *join_tab= first_linear_tab(join, WITH_CONST_TABLES); join_tab; + JOIN_TAB *join_tab; + for (join_tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITH_CONST_TABLES); + join_tab; join_tab= next_linear_tab(join, join_tab, WITH_BUSH_ROOTS)) { TABLE_REF *ref= &join_tab->ref; @@ -21121,7 +21175,7 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) ref_pointer_array and all_fields are updated. - @param[in] thd Pointer to current thread structure + @param[in] thd Pointer to current thread structure @param[in,out] ref_pointer_array All select, group and order by fields @param[in] tables List of tables to search in (usually FROM clause) @@ -21163,11 +21217,11 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, order_item->full_name(), thd->where); return TRUE; } - order->item= ref_pointer_array + count - 1; + thd->change_item_tree((Item**)&order->item, (Item*)(ref_pointer_array + count - 1)); order->in_field_list= 1; order->counter= count; order->counter_used= 1; - return FALSE; + return FALSE; } /* Lookup the current GROUP/ORDER field in the SELECT clause. */ select_item= find_item_in_list(order_item, fields, &counter, @@ -21235,7 +21289,8 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, warning so the user knows that the field from the FROM clause overshadows the column reference from the SELECT list. */ - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR, + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR), ((Item_ident*) order_item)->field_name, current_thd->where); @@ -23005,13 +23060,11 @@ int print_explain_message_line(select_result_sink *result, ha_rows *rows, const char *message) { - const CHARSET_INFO *cs= system_charset_info; Item *item_null= new Item_null(); List<Item> item_list; item_list.push_back(new Item_int((int32) select_number)); - item_list.push_back(new Item_string(select_type, - strlen(select_type), cs)); + item_list.push_back(new Item_string_sys(select_type)); /* `table` */ item_list.push_back(item_null); @@ -23046,7 +23099,7 @@ int print_explain_message_line(select_result_sink *result, /* `Extra` */ if (message) - item_list.push_back(new Item_string(message,strlen(message),cs)); + item_list.push_back(new Item_string_sys(message)); else item_list.push_back(item_null); @@ -23107,45 +23160,39 @@ int print_explain_row(select_result_sink *result, double r_filtered, const char *extra) { - const CHARSET_INFO *cs= system_charset_info; Item *item_null= new Item_null(); List<Item> item_list; Item *item; item_list.push_back(new Item_int((int32) select_number)); - item_list.push_back(new Item_string(select_type, - strlen(select_type), cs)); - item_list.push_back(new Item_string(table_name, - strlen(table_name), cs)); + item_list.push_back(new Item_string_sys(select_type)); + item_list.push_back(new Item_string_sys(table_name)); if (options & DESCRIBE_PARTITIONS) { if (partitions) { - item_list.push_back(new Item_string(partitions, - strlen(partitions), cs)); + item_list.push_back(new Item_string_sys(partitions)); } else item_list.push_back(item_null); } const char *jtype_str= join_type_str[jtype]; - item_list.push_back(new Item_string(jtype_str, - strlen(jtype_str), cs)); + item_list.push_back(new Item_string_sys(jtype_str)); - item= possible_keys? new Item_string(possible_keys, strlen(possible_keys), - cs) : item_null; + item= possible_keys? new Item_string_sys(possible_keys) : item_null; item_list.push_back(item); /* 'index */ - item= index ? new Item_string(index, strlen(index), cs) : item_null; + item= index ? new Item_string_sys(index) : item_null; item_list.push_back(item); /* 'key_len */ - item= key_len ? new Item_string(key_len, strlen(key_len), cs) : item_null; + item= key_len ? new Item_string_sys(key_len) : item_null; item_list.push_back(item); /* 'ref' */ - item= ref ? new Item_string(ref, strlen(ref), cs) : item_null; + item= ref ? new Item_string_sys(ref) : item_null; item_list.push_back(item); /* 'rows' */ @@ -23180,7 +23227,7 @@ int print_explain_row(select_result_sink *result, /* 'Extra' */ if (extra) - item_list.push_back(new Item_string(extra, strlen(extra), cs)); + item_list.push_back(new Item_string_sys(extra)); else item_list.push_back(item_null); @@ -23193,7 +23240,6 @@ int print_explain_row(select_result_sink *result, int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, SELECT_LEX *select_lex, uint8 explain_flags) { - const CHARSET_INFO *cs= system_charset_info; Item *item_null= new Item_null(); List<Item> item_list; if (on_the_fly) @@ -23210,9 +23256,7 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, /* id */ item_list.push_back(new Item_null); /* select_type */ - item_list.push_back(new Item_string(select_lex->type, - strlen(select_lex->type), - cs)); + item_list.push_back(new Item_string_sys(select_lex->type)); /* table */ { SELECT_LEX *sl= select_lex->master_unit()->first_select(); @@ -23234,15 +23278,14 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, len+= lastop; table_name_buffer[len - 1]= '>'; // change ',' to '>' } - item_list.push_back(new Item_string(table_name_buffer, len, cs)); + item_list.push_back(new Item_string_sys(table_name_buffer, len)); } /* partitions */ if (explain_flags & DESCRIBE_PARTITIONS) item_list.push_back(item_null); /* type */ - item_list.push_back(new Item_string(join_type_str[JT_ALL], - strlen(join_type_str[JT_ALL]), - cs)); + item_list.push_back(new Item_string_sys(join_type_str[JT_ALL])); + /* possible_keys */ item_list.push_back(item_null); /* key*/ @@ -23258,10 +23301,9 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, item_list.push_back(item_null); /* extra */ if (select_lex->master_unit()->global_parameters->order_list.first) - item_list.push_back(new Item_string("Using filesort", - 14, cs)); + item_list.push_back(new Item_string_sys("Using filesort", 14)); else - item_list.push_back(new Item_string("", 0, cs)); + item_list.push_back(new Item_string_sys("", 0)); if (result->send_data(item_list)) return 1; |