diff options
author | unknown <gluh@eagle.(none)> | 2007-02-02 10:25:45 +0400 |
---|---|---|
committer | unknown <gluh@eagle.(none)> | 2007-02-02 10:25:45 +0400 |
commit | ed0e4a968a4dfba3788bc270c73620f3e498dca5 (patch) | |
tree | a499a38ce070d521a711fde73af6cb95e3713dc3 /sql | |
parent | 4ebef0520629873253ed5007aba1a01c91d7f8fd (diff) | |
parent | a30830460794651c0e9fc5ec4779cf77680514ee (diff) | |
download | mariadb-git-ed0e4a968a4dfba3788bc270c73620f3e498dca5.tar.gz |
Merge mysql.com:/home/gluh/MySQL/Merge/5.0-opt
into mysql.com:/home/gluh/MySQL/Merge/5.1-opt
mysql-test/r/distinct.result:
Auto merged
mysql-test/r/join_nested.result:
Auto merged
mysql-test/r/null_key.result:
Auto merged
mysql-test/r/select.result:
Auto merged
mysql-test/r/subselect.result:
Auto merged
mysql-test/r/subselect3.result:
Auto merged
mysql-test/r/trigger.result:
Auto merged
mysql-test/t/select.test:
Auto merged
mysql-test/t/subselect.test:
Auto merged
mysql-test/t/trigger.test:
Auto merged
sql/filesort.cc:
Auto merged
sql/item.cc:
Auto merged
sql/item.h:
Auto merged
sql/item_cmpfunc.cc:
Auto merged
sql/item_cmpfunc.h:
Auto merged
sql/item_func.cc:
Auto merged
sql/item_subselect.cc:
Auto merged
sql/item_timefunc.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/opt_sum.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
sql/table.cc:
Auto merged
mysql-test/r/func_time.result:
manual merge
mysql-test/r/information_schema.result:
manual merge
mysql-test/t/func_time.test:
manual merge
mysql-test/t/information_schema.test:
manual merge
sql/opt_range.cc:
manual merge
sql/sql_delete.cc:
manual merge
sql/sql_lex.h:
manual merge
Diffstat (limited to 'sql')
-rw-r--r-- | sql/filesort.cc | 6 | ||||
-rw-r--r-- | sql/item.cc | 5 | ||||
-rw-r--r-- | sql/item_subselect.cc | 4 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 9 | ||||
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/opt_range.cc | 14 | ||||
-rw-r--r-- | sql/opt_sum.cc | 10 | ||||
-rw-r--r-- | sql/sql_base.cc | 51 | ||||
-rw-r--r-- | sql/sql_delete.cc | 10 | ||||
-rw-r--r-- | sql/sql_lex.h | 15 | ||||
-rw-r--r-- | sql/sql_parse.cc | 13 | ||||
-rw-r--r-- | sql/sql_select.cc | 60 | ||||
-rw-r--r-- | sql/sql_show.cc | 1 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 16 | ||||
-rw-r--r-- | sql/table.cc | 1 |
15 files changed, 159 insertions, 59 deletions
diff --git a/sql/filesort.cc b/sql/filesort.cc index 46ef9c9a553..58ca4837858 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -434,7 +434,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, byte *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH]; my_off_t record; TABLE *sort_form; - volatile THD::killed_state *killed= ¤t_thd->killed; + THD *thd= current_thd; + volatile THD::killed_state *killed= &thd->killed; handler *file; MY_BITMAP *save_read_set, *save_write_set; DBUG_ENTER("find_all_keys"); @@ -547,6 +548,9 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, } else file->unlock_row(); + /* It does not make sense to read more keys in case of a fatal error */ + if (thd->net.report_error) + DBUG_RETURN(HA_POS_ERROR); } if (quick_select) { diff --git a/sql/item.cc b/sql/item.cc index 0f28572163e..b88d0e92854 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1270,7 +1270,10 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, if (type() == SUM_FUNC_ITEM && skip_registered && ((Item_sum *) this)->ref_by) return; - if (type() != SUM_FUNC_ITEM && with_sum_func) + if ((type() != SUM_FUNC_ITEM && with_sum_func) || + (type() == FUNC_ITEM && + (((Item_func *) this)->functype() == Item_func::ISNOTNULLTEST_FUNC || + ((Item_func *) this)->functype() == Item_func::TRIG_COND_FUNC))) { /* Will split complicated items and ignore simple ones */ split_sum_func(thd, ref_pointer_array, fields); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index e131072d9bf..58aa7de073f 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -238,6 +238,10 @@ bool Item_subselect::exec() { int res; + if (thd->net.report_error) + /* Do not execute subselect in case of a fatal error */ + return 1; + res= engine->exec(); if (engine_changed) diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index faeef7fd5db..369ab842d65 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1007,7 +1007,8 @@ longlong Item_func_quarter::val_int() { DBUG_ASSERT(fixed == 1); TIME ltime; - (void) get_arg0_date(<ime, TIME_FUZZY_DATE); + if (get_arg0_date(<ime, TIME_FUZZY_DATE)) + return 0; return (longlong) ((ltime.month+2)/3); } @@ -1647,6 +1648,7 @@ String *Item_func_sec_to_time::val_str(String *str) { DBUG_ASSERT(fixed == 1); TIME ltime; + longlong arg_val= args[0]->val_int(); if ((null_value=args[0]->null_value) || str->alloc(19)) { @@ -1654,7 +1656,7 @@ String *Item_func_sec_to_time::val_str(String *str) return (String*) 0; } - sec_to_time(args[0]->val_int(), args[0]->unsigned_flag, <ime); + sec_to_time(arg_val, args[0]->unsigned_flag, <ime); make_time((DATE_TIME_FORMAT *) 0, <ime, str); return str; @@ -1665,11 +1667,12 @@ longlong Item_func_sec_to_time::val_int() { DBUG_ASSERT(fixed == 1); TIME ltime; + longlong arg_val= args[0]->val_int(); if ((null_value=args[0]->null_value)) return 0; - sec_to_time(args[0]->val_int(), args[0]->unsigned_flag, <ime); + sec_to_time(arg_val, args[0]->unsigned_flag, <ime); return (ltime.neg ? -1 : 1) * ((ltime.hour)*10000 + ltime.minute*100 + ltime.second); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 742efc71e63..1515fef4387 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1151,7 +1151,8 @@ bool push_new_name_resolution_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op); void add_join_on(TABLE_LIST *b,Item *expr); -void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields); +void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields, + SELECT_LEX *lex); bool add_proc_to_list(THD *thd, Item *item); TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find); void update_non_unique_table_error(TABLE_LIST *update, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 628b07631c1..1e18b2d48bd 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -219,6 +219,8 @@ public: } inline void merge_flags(SEL_ARG *arg) { maybe_flag|=arg->maybe_flag; } inline void maybe_smaller() { maybe_flag=1; } + /* Return true iff it's a single-point null interval */ + inline bool is_null_interval() { return maybe_null && max_value[0] == 1; } inline int cmp_min_to_min(SEL_ARG* arg) { return sel_cmp(field,min_value, arg->min_value, min_flag, arg->min_flag); @@ -560,7 +562,8 @@ public: bool is_ror_scan; /* Number of ranges in the last checked tree->key */ uint n_ranges; -}; + uint8 first_null_comp; /* first null component if any, 0 - otherwise */ +} PARAM; class TABLE_READ_PLAN; class TRP_RANGE; @@ -7016,6 +7019,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree, bool update_tbl_stats) DBUG_ENTER("check_quick_select"); param->is_ror_scan= FALSE; + param->first_null_comp= 0; if (!tree) DBUG_RETURN(HA_POS_ERROR); // Can't use it @@ -7116,6 +7120,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, ha_rows records=0, tmp; uint tmp_min_flag, tmp_max_flag, keynr, min_key_length, max_key_length; char *tmp_min_key, *tmp_max_key; + uint8 save_first_null_comp= param->first_null_comp; param->max_key_part=max(param->max_key_part,key_tree->part); if (key_tree->left != &null_element) @@ -7153,6 +7158,9 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, param->is_ror_scan= FALSE; } + if (!param->first_null_comp && key_tree->is_null_interval()) + param->first_null_comp= key_tree->part+1; + if (key_tree->next_key_part && key_tree->next_key_part->part == key_tree->part+1 && key_tree->next_key_part->type == SEL_ARG::KEY_RANGE) @@ -7196,7 +7204,8 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, (param->table->key_info[keynr].flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME && min_key_length == max_key_length && - !memcmp(param->min_key,param->max_key,min_key_length)) + !memcmp(param->min_key,param->max_key,min_key_length) && + !param->first_null_comp) { tmp=1; // Max one record param->n_ranges++; @@ -7271,6 +7280,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, return tmp; records+=tmp; } + param->first_null_comp= save_first_null_comp; return records; } diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 90a3ff66a22..5bd5ec4b42d 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -97,9 +97,9 @@ static ulonglong get_exact_record_count(TABLE_LIST *tables) GROUP BY part. RETURN VALUES - 0 No errors - 1 if all items were resolved - -1 on impossible conditions + 0 no errors + 1 if all items were resolved + HA_ERR_KEY_NOT_FOUND on impossible conditions OR an error number from my_base.h HA_ERR_... if a deadlock or a lock wait timeout happens, for example */ @@ -267,7 +267,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) if (error) { if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE) - return -1; // No rows matching WHERE + return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE /* HA_ERR_LOCK_DEADLOCK or some other error */ table->file->print_error(error, MYF(0)); return(error); @@ -354,7 +354,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) if (error) { if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE) - return -1; // No rows matching WHERE + return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE /* HA_ERR_LOCK_DEADLOCK or some other error */ table->file->print_error(error, MYF(0)); return(error); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index bb84e89a2ef..fd2e8445132 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3764,7 +3764,7 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, { List_iterator_fast<Natural_join_column> field_it(*(table_ref->join_columns)); - Natural_join_column *nj_col; + Natural_join_column *nj_col, *curr_nj_col; Field *found_field; Query_arena *arena, backup; DBUG_ENTER("find_field_in_natural_join"); @@ -3776,14 +3776,21 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, LINT_INIT(arena); LINT_INIT(found_field); - for (;;) + for (nj_col= NULL, curr_nj_col= field_it++; curr_nj_col; + curr_nj_col= field_it++) { - if (!(nj_col= field_it++)) - DBUG_RETURN(NULL); - - if (!my_strcasecmp(system_charset_info, nj_col->name(), name)) - break; + if (!my_strcasecmp(system_charset_info, curr_nj_col->name(), name)) + { + if (nj_col) + { + my_error(ER_NON_UNIQ_ERROR, MYF(0), name, thd->where); + DBUG_RETURN(NULL); + } + nj_col= curr_nj_col; + } } + if (!nj_col) + DBUG_RETURN(NULL); if (nj_col->view_field) { @@ -4684,9 +4691,16 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, { bool found= FALSE; const char *field_name_1; + /* true if field_name_1 is a member of using_fields */ + bool is_using_column_1; if (!(nj_col_1= it_1.get_or_create_column_ref(leaf_1))) goto err; field_name_1= nj_col_1->name(); + is_using_column_1= using_fields && + test_if_string_in_list(field_name_1, using_fields); + DBUG_PRINT ("info", ("field_name_1=%s.%s", + nj_col_1->table_name() ? nj_col_1->table_name() : "", + field_name_1)); /* Find a field with the same name in table_ref_2. @@ -4703,6 +4717,10 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, if (!(cur_nj_col_2= it_2.get_or_create_column_ref(leaf_2))) goto err; cur_field_name_2= cur_nj_col_2->name(); + DBUG_PRINT ("info", ("cur_field_name_2=%s.%s", + cur_nj_col_2->table_name() ? + cur_nj_col_2->table_name() : "", + cur_field_name_2)); /* Compare the two columns and check for duplicate common fields. @@ -4710,10 +4728,16 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, table_ref_2 (then found == TRUE), or if a field in table_ref_2 was already matched by some previous field in table_ref_1 (then cur_nj_col_2->is_common == TRUE). + Note that it is too early to check the columns outside of the + USING list for ambiguity because they are not actually "referenced" + here. These columns must be checked only on unqualified reference + by name (e.g. in SELECT list). */ if (!my_strcasecmp(system_charset_info, field_name_1, cur_field_name_2)) { - if (found || cur_nj_col_2->is_common) + DBUG_PRINT ("info", ("match c1.is_common=%d", nj_col_1->is_common)); + if (cur_nj_col_2->is_common || + (found && (!using_fields || is_using_column_1))) { my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, thd->where); goto err; @@ -4739,9 +4763,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, clause (if present), mark them as common fields, and add a new equi-join condition to the ON clause. */ - if (nj_col_2 && - (!using_fields || - test_if_string_in_list(field_name_1, using_fields))) + if (nj_col_2 && (!using_fields ||is_using_column_1)) { Item *item_1= nj_col_1->create_item(thd); Item *item_2= nj_col_2->create_item(thd); @@ -4796,6 +4818,13 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, eq_cond); nj_col_1->is_common= nj_col_2->is_common= TRUE; + DBUG_PRINT ("info", ("%s.%s and %s.%s are common", + nj_col_1->table_name() ? + nj_col_1->table_name() : "", + nj_col_1->name(), + nj_col_2->table_name() ? + nj_col_2->table_name() : "", + nj_col_2->name())); if (field_1) { diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index e3405d9c9d9..7daf3be1578 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -69,14 +69,14 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, Test if the user wants to delete all rows and deletion doesn't have any side-effects (because of triggers), so we can use optimized handler::delete_all_rows() method. - - If row-based replication is used, we also delete the table row by - row. + We implement fast TRUNCATE for InnoDB even if triggers are present. + TRUNCATE ignores triggers. */ if (!using_limit && const_cond && (!conds || conds->val_int()) && !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) && - !(table->triggers && table->triggers->has_delete_triggers()) && - !thd->current_stmt_binlog_row_based) + (thd->lex->sql_command == SQLCOM_TRUNCATE || + !(table->triggers && table->triggers->has_delete_triggers())) + ) { /* Update the table->file->stats.records number */ table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 8632ab0f675..cc52be37036 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -620,6 +620,21 @@ public: /* index in the select list of the expression currently being fixed */ int cur_pos_in_select_list; + List<udf_func> udf_list; /* udf function calls stack */ + /* + This is a copy of the original JOIN USING list that comes from + the parser. The parser : + 1. Sets the natural_join of the second TABLE_LIST in the join + and the st_select_lex::prev_join_using. + 2. Makes a parent TABLE_LIST and sets its is_natural_join/ + join_using_fields members. + 3. Uses the wrapper TABLE_LIST as a table in the upper level. + We cannot assign directly to join_using_fields in the parser because + at stage (1.) the parent TABLE_LIST is not constructed yet and + the assignment will override the JOIN USING fields of the lower level + joins on the right. + */ + List<String> *prev_join_using; void init_query(); void init_select(); st_select_lex_unit* master_unit(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 701a68f31b5..6d5d7328835 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6666,11 +6666,8 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd) If this is a JOIN ... USING, move the list of joined fields to the table reference that describes the join. */ - if (table->join_using_fields) - { - ptr->join_using_fields= table->join_using_fields; - table->join_using_fields= NULL; - } + if (prev_join_using) + ptr->join_using_fields= prev_join_using; } } join_list->push_front(ptr); @@ -6926,6 +6923,7 @@ void add_join_on(TABLE_LIST *b, Item *expr) a Left join argument b Right join argument using_fields Field names from USING clause + lex The current st_select_lex IMPLEMENTATION This function marks that table b should be joined with a either via @@ -6954,10 +6952,11 @@ void add_join_on(TABLE_LIST *b, Item *expr) None */ -void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields) +void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields, + SELECT_LEX *lex) { b->natural_join= a; - b->join_using_fields= using_fields; + lex->prev_join_using= using_fields; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index bd2a7a87c53..4966efbd366 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -717,11 +717,20 @@ JOIN::optimize() { int res; /* - opt_sum_query() returns -1 if no rows match to the WHERE conditions, - or 1 if all items were resolved, or 0, or an error number HA_ERR_... + opt_sum_query() returns HA_ERR_KEY_NOT_FOUND if no rows match + to the WHERE conditions, + or 1 if all items were resolved, + or 0, or an error number HA_ERR_... */ if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds))) { + if (res == HA_ERR_KEY_NOT_FOUND) + { + DBUG_PRINT("info",("No matching min/max row")); + zero_result_cause= "No matching min/max row"; + error=0; + DBUG_RETURN(0); + } if (res > 1) { thd->fatal_error(); @@ -729,13 +738,6 @@ JOIN::optimize() DBUG_PRINT("error",("Error from opt_sum_query")); DBUG_RETURN(1); } - if (res < 0) - { - DBUG_PRINT("info",("No matching min/max row")); - zero_result_cause= "No matching min/max row"; - error=0; - DBUG_RETURN(0); - } DBUG_PRINT("info",("Select tables optimized away")); zero_result_cause= "Select tables optimized away"; tables_list= 0; // All tables resolved @@ -865,6 +867,13 @@ JOIN::optimize() { ORDER *org_order= order; order=remove_const(this, order,conds,1, &simple_order); + if (thd->net.report_error) + { + error= 1; + DBUG_PRINT("error",("Error from remove_const")); + DBUG_RETURN(1); + } + /* If we are using ORDER BY NULL or ORDER BY const_expression, return result in any order (even if we are using a GROUP BY) @@ -874,10 +883,11 @@ JOIN::optimize() } /* Check if we can optimize away GROUP BY/DISTINCT. - We can do that if there are no aggregate functions and the + We can do that if there are no aggregate functions, the fields in DISTINCT clause (if present) and/or columns in GROUP BY (if present) contain direct references to all key parts of - an unique index (in whatever order). + an unique index (in whatever order) and if the key parts of the + unique index cannot contain NULLs. Note that the unique keys for DISTINCT and GROUP BY should not be the same (as long as they are unique). @@ -972,6 +982,12 @@ JOIN::optimize() group_list= remove_const(this, (old_group_list= group_list), conds, rollup.state == ROLLUP::STATE_NONE, &simple_group); + if (thd->net.report_error) + { + error= 1; + DBUG_PRINT("error",("Error from remove_const")); + DBUG_RETURN(1); + } if (old_group_list && !group_list) select_distinct= 0; } @@ -988,6 +1004,12 @@ JOIN::optimize() { group_list= procedure->group= remove_const(this, procedure->group, conds, 1, &simple_group); + if (thd->net.report_error) + { + error= 1; + DBUG_PRINT("error",("Error from remove_const")); + DBUG_RETURN(1); + } calc_group_buffer(this, group_list); } @@ -6578,6 +6600,8 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, *simple_order=0; // Must do a temp table to sort else if (!(order_tables & not_const_tables)) { + if (order->item[0]->with_subselect) + order->item[0]->val_str(&order->item[0]->str_value); DBUG_PRINT("info",("removing: %s", order->item[0]->full_name())); continue; // skip const item } @@ -12107,7 +12131,7 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts, /* - Check if GROUP BY/DISTINCT can be optimized away because the set is + Check if GROUP BY/DISTINCT can be optimized away because the set is already known to be distinct. SYNOPSIS @@ -12115,7 +12139,7 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts, table The table to operate on. find_func function to iterate over the list and search for a field - + DESCRIPTION Used in removing the GROUP BY/DISTINCT of the following types of statements: @@ -12126,12 +12150,13 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts, then <any combination of a,b,c>,{whatever} is also distinct This function checks if all the key parts of any of the unique keys - of the table are referenced by a list : either the select list + of the table are referenced by a list : either the select list through find_field_in_item_list or GROUP BY list through find_field_in_order_list. - If the above holds then we can safely remove the GROUP BY/DISTINCT, + If the above holds and the key parts cannot contain NULLs then we + can safely remove the GROUP BY/DISTINCT, as no result set can be more distinct than an unique key. - + RETURN VALUE 1 found 0 not found. @@ -12154,7 +12179,8 @@ list_contains_unique_index(TABLE *table, key_part < key_part_end; key_part++) { - if (!find_func(key_part->field, data)) + if (key_part->field->maybe_null() || + !find_func(key_part->field, data)) break; } if (key_part == key_part_end) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index a895bf14ce0..48471fa56d2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4985,6 +4985,7 @@ bool get_schema_tables_result(JOIN *join) if (is_subselect) // is subselect { + table_list->table->file->extra(HA_EXTRA_NO_CACHE); table_list->table->file->extra(HA_EXTRA_RESET_STATE); table_list->table->file->delete_all_rows(); free_io_cache(table_list->table); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index eb8641f011f..caca310180d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7116,11 +7116,11 @@ join_table: YYERROR_UNLESS($1 && $3); } '(' using_list ')' - { add_join_natural($1,$3,$7); $$=$3; } + { add_join_natural($1,$3,$7,Select); $$=$3; } | table_ref NATURAL JOIN_SYM table_factor { YYERROR_UNLESS($1 && ($$=$4)); - add_join_natural($1,$4,NULL); + add_join_natural($1,$4,NULL,Select); } /* LEFT JOIN variants */ @@ -7147,11 +7147,15 @@ join_table: YYERROR_UNLESS($1 && $5); } USING '(' using_list ')' - { add_join_natural($1,$5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } + { + add_join_natural($1,$5,$9,Select); + $5->outer_join|=JOIN_TYPE_LEFT; + $$=$5; + } | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor { YYERROR_UNLESS($1 && $6); - add_join_natural($1,$6,NULL); + add_join_natural($1,$6,NULL,Select); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; } @@ -7185,12 +7189,12 @@ join_table: LEX *lex= Lex; if (!($$= lex->current_select->convert_right_join())) YYABORT; - add_join_natural($$,$5,$9); + add_join_natural($$,$5,$9,Select); } | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor { YYERROR_UNLESS($1 && $6); - add_join_natural($6,$1,NULL); + add_join_natural($6,$1,NULL,Select); LEX *lex= Lex; if (!($$= lex->current_select->convert_right_join())) YYABORT; diff --git a/sql/table.cc b/sql/table.cc index cf2eb1705a5..e911d39b225 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3430,6 +3430,7 @@ Field *Natural_join_column::field() const char *Natural_join_column::table_name() { + DBUG_ASSERT(table_ref); return table_ref->alias; } |