diff options
author | Sergei Golubchik <sergii@pisem.net> | 2014-02-01 00:54:03 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2014-02-01 00:54:03 +0100 |
commit | 59d9d08e2b6f6f35e781d24c47d33d26fb4ba2a5 (patch) | |
tree | 3e4a302ccf3912d4d8a40aa271414003bfe7c9b6 /sql | |
parent | ce02738d7f2f2688eeec7004dd6a30293d36044f (diff) | |
parent | 6b6d40fa6ca1fe36f2a51c2723c58dfb3fc025bb (diff) | |
download | mariadb-git-59d9d08e2b6f6f35e781d24c47d33d26fb4ba2a5.tar.gz |
5.5 merge
Diffstat (limited to 'sql')
45 files changed, 619 insertions, 375 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 780473e3683..67406627e20 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1349,7 +1349,8 @@ bool ha_partition::is_crashed() const int ha_partition::prepare_new_partition(TABLE *tbl, HA_CREATE_INFO *create_info, handler *file, const char *part_name, - partition_element *p_elem) + partition_element *p_elem, + uint disable_non_uniq_indexes) { int error; DBUG_ENTER("prepare_new_partition"); @@ -1375,6 +1376,7 @@ int ha_partition::prepare_new_partition(TABLE *tbl, if ((error= file->ha_open(tbl, part_name, m_mode, m_open_test_lock))) goto error_open; DBUG_PRINT("info", ("partition %s opened", part_name)); + /* Note: if you plan to add another call that may return failure, better to do it before external_lock() as cleanup_new_partition() @@ -1385,6 +1387,9 @@ int ha_partition::prepare_new_partition(TABLE *tbl, goto error_external_lock; DBUG_PRINT("info", ("partition %s external locked", part_name)); + if (disable_non_uniq_indexes) + file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + DBUG_RETURN(0); error_external_lock: (void) file->ha_close(); @@ -1662,6 +1667,14 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, on them to prepare them for copy phase and also for later close calls */ + + /* + Before creating new partitions check whether indexes are disabled + in the partitions. + */ + + uint disable_non_uniq_indexes = indexes_are_disabled(); + i= 0; part_count= 0; part_it.rewind(); @@ -1696,11 +1709,13 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, if ((error= prepare_new_partition(table, create_info, new_file_array[part], (const char *)part_name_buff, - sub_elem))) + sub_elem, + disable_non_uniq_indexes))) { cleanup_new_partition(part_count); DBUG_RETURN(error); } + m_added_file[part_count++]= new_file_array[part]; } while (++j < num_subparts); } @@ -1713,11 +1728,13 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, if ((error= prepare_new_partition(table, create_info, new_file_array[i], (const char *)part_name_buff, - part_elem))) + part_elem, + disable_non_uniq_indexes))) { cleanup_new_partition(part_count); DBUG_RETURN(error); } + m_added_file[part_count++]= new_file_array[i]; } } @@ -7177,7 +7194,7 @@ void ha_partition::print_error(int error, myf errflag) { if (!(thd->lex->alter_info.flags & ALTER_TRUNCATE_PARTITION)) { - m_part_info->print_no_partition_found(table); + m_part_info->print_no_partition_found(table, errflag); DBUG_VOID_RETURN; } } diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 56993ae5f32..0108fb7994f 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -268,7 +268,8 @@ private: void cleanup_new_partition(uint part_count); int prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info, handler *file, const char *part_name, - partition_element *p_elem); + partition_element *p_elem, + uint disable_non_uniq_indexes); /* delete_table, rename_table and create uses very similar logic which is packed into this routine. diff --git a/sql/handler.cc b/sql/handler.cc index 1c5d643ed96..7a90ac310ea 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -44,6 +44,7 @@ #include "probes_mysql.h" #include "debug_sync.h" // DEBUG_SYNC #include "sql_audit.h" +#include <my_handler_errors.h> #ifdef WITH_PARTITION_STORAGE_ENGINE #include "ha_partition.h" @@ -3260,7 +3261,7 @@ void handler::print_error(int error, myf errflag) } } else - my_error(ER_GET_ERRNO, errflag, error, table_type()); + my_error(ER_GET_ERRNO, errflag, error, table_type()); DBUG_VOID_RETURN; } } @@ -5181,8 +5182,10 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat) "", 0, "DISABLED", 8) ? 1 : 0; } else + { result= db_type->show_status && db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0; + } } /* diff --git a/sql/item.cc b/sql/item.cc index e665e391042..9d2d4a6dbfd 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4705,6 +4705,12 @@ bool is_outer_table(TABLE_LIST *table, SELECT_LEX *select) /** Resolve the name of an outer select column reference. + @param[in] thd current thread + @param[in,out] from_field found field reference or (Field*)not_found_field + @param[in,out] reference view column if this item was resolved to a + view column + + @description The method resolves the column reference represented by 'this' as a column present in outer selects that contain current select. @@ -4714,10 +4720,16 @@ bool is_outer_table(TABLE_LIST *table, SELECT_LEX *select) current select as dependent. The found reference of field should be provided in 'from_field'. - @param[in] thd current thread - @param[in,out] from_field found field reference or (Field*)not_found_field - @param[in,out] reference view column if this item was resolved to a - view column + The cache is critical for prepared statements of type: + + SELECT a FROM (SELECT a FROM test.t1) AS s1 NATURAL JOIN t2 AS s2; + + This is internally converted to a join similar to + + SELECT a FROM t1 AS s1,t2 AS s2 WHERE t2.a=t1.a; + + Without the cache, we would on re-prepare not know if 'a' did match + s1.a or s2.a. @note This is the inner loop of Item_field::fix_fields: @@ -4747,7 +4759,12 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) enum_parsing_place place= NO_MATTER; bool field_found= (*from_field != not_found_field); bool upward_lookup= FALSE; + TABLE_LIST *table_list; + /* Calulate the TABLE_LIST for the table */ + table_list= (cached_table ? cached_table : + field_found && (*from_field) != view_ref_found ? + (*from_field)->table->pos_in_table_list : 0); /* If there are outer contexts (outer selects, but current select is not derived table or view) try to resolve this reference in the @@ -4766,6 +4783,15 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) if (current_sel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) outer_context= context->outer_context; + + /* + This assert is to ensure we have an outer contex when *from_field + is set. + If this would not be the case, we would assert in mark_as_dependent + as last_checked_countex == context + */ + DBUG_ASSERT(outer_context || !*from_field || + *from_field == not_found_field); for (; outer_context; outer_context= outer_context->outer_context) @@ -4782,7 +4808,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) to find_field_in_tables(). Only need to find appropriate context. */ if (field_found && outer_context->select_lex != - cached_table->select_lex) + table_list->select_lex) continue; /* In case of a view, find_field_in_tables() writes the pointer to @@ -4981,9 +5007,9 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) if (last_checked_context->select_lex->having_fix_field) { Item_ref *rf; - rf= new Item_ref(context, - (cached_table->db[0] ? cached_table->db : 0), - (char*) cached_table->alias, (char*) field_name); + rf= new Item_ref(context, (*from_field)->table->s->db.str, + (*from_field)->table->alias.c_ptr(), + (char*) field_name); if (!rf) return -1; thd->change_item_tree(reference, rf); @@ -5054,6 +5080,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference) if (!field) // If field is not checked { + TABLE_LIST *table_list; /* In case of view, find_field_in_tables() write pointer to view field expression to 'reference', i.e. it substitute that expression instead @@ -5139,11 +5166,14 @@ bool Item_field::fix_fields(THD *thd, Item **reference) else if (!from_field) goto error; - if (!outer_fixed && cached_table && cached_table->select_lex && + table_list= (cached_table ? cached_table : + from_field != view_ref_found ? + from_field->table->pos_in_table_list : 0); + if (!outer_fixed && table_list && table_list->select_lex && context->select_lex && - cached_table->select_lex != context->select_lex && - !context->select_lex->is_merged_child_of(cached_table->select_lex) && - is_outer_table(cached_table, context->select_lex)) + table_list->select_lex != context->select_lex && + !context->select_lex->is_merged_child_of(table_list->select_lex) && + is_outer_table(table_list, context->select_lex)) { int ret; if ((ret= fix_outer_field(thd, &from_field, reference)) < 0) diff --git a/sql/item.h b/sql/item.h index 113e8bdcb9c..2617e96989e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -332,6 +332,8 @@ struct Name_resolution_context: Sql_alloc */ TABLE_LIST *last_name_resolution_table; + /* Cache first_name_resolution_table in setup_natural_join_row_types */ + TABLE_LIST *natural_join_first_table; /* SELECT_LEX item belong to, in case of merged VIEW it can differ from SELECT_LEX where item was created, so we can't use table_list/field_list diff --git a/sql/item_func.cc b/sql/item_func.cc index 5d9abbb0d8c..2c6e195075a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2947,11 +2947,6 @@ bool Item_func_min_max::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) } unpack_time(min_max, ltime); - if (!(fuzzy_date & TIME_TIME_ONLY) && - ((null_value= check_date_with_warn(ltime, fuzzy_date, - MYSQL_TIMESTAMP_ERROR)))) - return true; - if (compare_as_dates->field_type() == MYSQL_TYPE_DATE) { ltime->time_type= MYSQL_TIMESTAMP_DATE; @@ -2962,8 +2957,15 @@ bool Item_func_min_max::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) ltime->time_type= MYSQL_TIMESTAMP_TIME; ltime->hour+= (ltime->month * 32 + ltime->day) * 24; ltime->month= ltime->day= 0; + if (adjust_time_range_with_warn(ltime, + min(decimals, TIME_SECOND_PART_DIGITS))) + return (null_value= true); } + if (!(fuzzy_date & TIME_TIME_ONLY) && + ((null_value= check_date_with_warn(ltime, fuzzy_date, + MYSQL_TIMESTAMP_ERROR)))) + return true; return (null_value= 0); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index b1b4ce7f826..7dcd6f26deb 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2000, 2013, Oracle and/or its affiliates. Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify @@ -64,11 +64,6 @@ C_MODE_END size_t username_char_length= 80; -/** - @todo Remove this. It is not safe to use a shared String object. - */ -String my_empty_string("",default_charset_info); - /* For the Items which have only val_str_ascii() method and don't have their own "native" val_str(), @@ -106,7 +101,6 @@ String *Item_str_func::val_str_from_val_str_ascii(String *str, String *str2) } - /* Convert an array of bytes to a hexadecimal representation. @@ -2757,7 +2751,7 @@ String *Item_func_make_set::val_str(String *str) ulonglong bits; bool first_found=0; Item **ptr=args+1; - String *result=&my_empty_string; + String *result= make_empty_result(); bits=args[0]->val_int(); if ((null_value=args[0]->null_value)) @@ -3204,7 +3198,9 @@ String *Item_func_conv::val_str(String *str) int to_base= (int) args[2]->val_int(); int err; + // Note that abs(INT_MIN) is undefined. if (args[0]->null_value || args[1]->null_value || args[2]->null_value || + from_base == INT_MIN || to_base == INT_MIN || abs(to_base) > 36 || abs(to_base) < 2 || abs(from_base) > 36 || abs(from_base) < 2 || !(res->length())) { diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 8d9bda4902e..edc4ce5e151 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -1166,7 +1166,5 @@ public: String *val_str(String *); }; -extern String my_empty_string; - #endif /* ITEM_STRFUNC_INCLUDED */ diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 9f2c3f074b6..e539d0b76b4 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1595,8 +1595,12 @@ void Item_sum_count::clear() bool Item_sum_count::add() { - if (!args[0]->maybe_null || !args[0]->is_null()) - count++; + for (uint i=0; i<arg_count; i++) + { + if (args[i]->maybe_null && args[i]->is_null()) + return 0; + } + count++; return 0; } diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index a3652ebf16e..63ad633cd2e 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2574,7 +2574,7 @@ bool Item_func_add_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) bool is_time= 0; long days, microseconds; longlong seconds; - int l_sign= sign, was_cut= 0; + int l_sign= sign; if (is_date) // TIMESTAMP function { @@ -2625,16 +2625,7 @@ bool Item_func_add_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) } ltime->hour+= days*24; - - MYSQL_TIME copy= *ltime; - ErrConvTime str(©); - - check_time_range(ltime, decimals, &was_cut); - if (was_cut) - make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - &str, MYSQL_TIMESTAMP_TIME, NullS); - - return (null_value= 0); + return (null_value= adjust_time_range_with_warn(ltime, decimals)); } @@ -2672,7 +2663,7 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) DBUG_ASSERT(fixed == 1); longlong seconds; long microseconds; - int l_sign= 1, was_cut= 0; + int l_sign= 1; MYSQL_TIME l_time1,l_time2,l_time3; ErrConvTime str(&l_time3); @@ -2716,12 +2707,8 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) return (null_value= 1); *ltime= l_time3; - check_time_range(ltime, decimals, &was_cut); + return (null_value= adjust_time_range_with_warn(ltime, decimals)); - if (was_cut) - make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - &str, MYSQL_TIMESTAMP_TIME, NullS); - return (null_value= 0); } /** diff --git a/sql/log_event.cc b/sql/log_event.cc index d205a08e708..66f3ff899d1 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6892,9 +6892,7 @@ int Intvar_log_event::do_apply_event(rpl_group_info *rgi) switch (type) { case LAST_INSERT_ID_EVENT: - thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1; - thd->first_successful_insert_id_in_prev_stmt_for_binlog= - thd->first_successful_insert_id_in_prev_stmt= val; + thd->first_successful_insert_id_in_prev_stmt= val; DBUG_PRINT("info",("last_insert_id_event: %ld", (long) val)); break; case INSERT_ID_EVENT: diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4e6646feead..923b8db779e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3270,7 +3270,6 @@ void my_message_sql(uint error, const char *str, myf MyFlags) DBUG_ASSERT(str != NULL); DBUG_ASSERT(error != 0); - mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_ERROR, error, str); if (MyFlags & ME_JUST_INFO) { level= MYSQL_ERROR::WARN_LEVEL_NOTE; @@ -3293,6 +3292,8 @@ void my_message_sql(uint error, const char *str, myf MyFlags) thd->is_fatal_error= 1; (void) thd->raise_condition(error, NULL, level, str); } + else + mysql_audit_general(0, MYSQL_AUDIT_GENERAL_ERROR, error, str); /* When simulating OOM, skip writing to error log to avoid mtr errors */ DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_VOID_RETURN;); diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 26bf4e42cf5..64a6cd7826c 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. Copyright (c) 2012, Monty Program Ab This program is free software; you can redistribute it and/or modify diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 371d3958e7b..d10a512cad6 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -10752,15 +10752,16 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, { KEY *table_key=quick->head->key_info+quick->index; flag=EQ_RANGE; - if ((table_key->flags & HA_NOSAME) && key->part == table_key->key_parts-1) + if ((table_key->flags & HA_NOSAME) && + key_tree->part == table_key->key_parts-1) { - if (!(table_key->flags & HA_NULL_PART_KEY) || - !null_part_in_key(key, - param->min_key, - (uint) (tmp_min_key - param->min_key))) - flag|= UNIQUE_RANGE; - else - flag|= NULL_RANGE; + if ((table_key->flags & HA_NULL_PART_KEY) && + null_part_in_key(key, + param->min_key, + (uint) (tmp_min_key - param->min_key))) + flag|= NULL_RANGE; + else + flag|= UNIQUE_RANGE; } } } @@ -10790,7 +10791,7 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, } /* - Return 1 if there is only one range and this uses the whole primary key + Return 1 if there is only one range and this uses the whole unique key */ bool QUICK_RANGE_SELECT::unique_key_range() diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 32e54d10856..48f58bc0e96 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1529,7 +1529,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) for (tl= (TABLE_LIST*)(parent_lex->table_list.first); tl->next_local; tl= tl->next_local) {} - tl->next_local= subq_lex->leaf_tables.head(); + tl->next_local= subq_lex->join->tables_list; /* A theory: no need to re-connect the next_global chain */ diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 3d33cd7b131..f94e5af119e 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -1330,7 +1330,7 @@ end: RETURN VALUES */ -void partition_info::print_no_partition_found(TABLE *table_arg) +void partition_info::print_no_partition_found(TABLE *table_arg, myf errflag) { char buf[100]; char *buf_ptr= (char*)&buf; @@ -1344,7 +1344,7 @@ void partition_info::print_no_partition_found(TABLE *table_arg) SELECT_ACL, &table_list, TRUE)) { my_message(ER_NO_PARTITION_FOR_GIVEN_VALUE, - ER(ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT), MYF(0)); + ER(ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT), errflag); } else { @@ -1360,7 +1360,7 @@ void partition_info::print_no_partition_found(TABLE *table_arg) part_expr->unsigned_flag ? 10 : -10); dbug_tmp_restore_column_map(table_arg->read_set, old_map); } - my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), buf_ptr); + my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, errflag, buf_ptr); } } diff --git a/sql/partition_info.h b/sql/partition_info.h index 17c9cb383ee..a590f8a0b2c 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -288,7 +288,7 @@ public: bool check_partition_info(THD *thd, handlerton **eng_type, handler *file, HA_CREATE_INFO *info, bool check_partition_function); - void print_no_partition_found(TABLE *table); + void print_no_partition_found(TABLE *table, myf errflag); void print_debug(const char *str, uint*); Item* get_column_item(Item *item, Field *field); int fix_partition_values(THD *thd, diff --git a/sql/records.cc b/sql/records.cc index e534c04935a..1b230c41156 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -189,7 +189,8 @@ bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table, info->table=table; info->forms= &info->table; /* Only one table */ - if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE && + if ((table->s->tmp_table == INTERNAL_TMP_TABLE || + table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE) && !table->sort.addon_field) (void) table->file->extra(HA_EXTRA_MMAP); diff --git a/sql/set_var.cc b/sql/set_var.cc index fc5c549b9de..fb691a9c095 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -216,7 +216,6 @@ uchar *sys_var::global_value_ptr(THD *thd, LEX_STRING *base) bool sys_var::check(THD *thd, set_var *var) { - do_deprecated_warning(thd); if ((var->value && do_check(thd, var)) || (on_check && on_check(this, thd, var))) { @@ -550,10 +549,10 @@ int mysql_del_sys_var_chain(sys_var *first) { int result= 0; - /* A write lock should be held on LOCK_system_variables_hash */ - + mysql_rwlock_wrlock(&LOCK_system_variables_hash); for (sys_var *var= first; var; var= var->next) result|= my_hash_delete(&system_variable_hash, (uchar*) var); + mysql_rwlock_unlock(&LOCK_system_variables_hash); return result; } @@ -700,6 +699,7 @@ err: int set_var::check(THD *thd) { + var->do_deprecated_warning(thd); if (var->is_readonly()) { my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name.str, "read only"); diff --git a/sql/set_var.h b/sql/set_var.h index 11501c4212a..229bbb3ff70 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -145,6 +145,7 @@ public: return (option.id != -1) && ((flags & PARSE_EARLY) == parse_flags) && insert_dynamic(array, (uchar*)&option); } + void do_deprecated_warning(THD *thd); private: virtual bool do_check(THD *thd, set_var *var) = 0; @@ -158,7 +159,7 @@ private: virtual void global_save_default(THD *thd, set_var *var) = 0; virtual bool session_update(THD *thd, set_var *var) = 0; virtual bool global_update(THD *thd, set_var *var) = 0; - void do_deprecated_warning(THD *thd); + protected: /** A pointer to a value of the variable for SHOW. diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index b74ffecf82e..0c9c84d4964 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -1777,31 +1777,8 @@ ER_WRONG_AUTO_KEY 42000 S1009 spa "Puede ser solamente un campo automatico y este debe ser definido como una clave" swe "Det får finnas endast ett AUTO_INCREMENT-fält och detta måste vara en nyckel" ukr "Невірне визначення таблиці; Може бути лише один автоматичний стовбець, що повинен бути визначений як ключ" -ER_READY - cze "%s: p-Břipraven na spojení\nVersion: '%s' socket: '%s' port: %d"" - dan "%s: klar til tilslutninger\nVersion: '%s' socket: '%s' port: %d"" - nla "%s: klaar voor verbindingen\nVersion: '%s' socket: '%s' port: %d"" - eng "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d" - jps "%s: 準備完了¥nVersion: '%s' socket: '%s' port: %d"", - est "%s: ootab ühendusi\nVersion: '%s' socket: '%s' port: %d"" - fre "%s: Prêt pour des connexions\nVersion: '%s' socket: '%s' port: %d"" - ger "%s: Bereit für Verbindungen.\nVersion: '%s' Socket: '%s' Port: %d" - greek "%s: σε αναμονή συνδέσεων\nVersion: '%s' socket: '%s' port: %d"" - hun "%s: kapcsolatra kesz\nVersion: '%s' socket: '%s' port: %d"" - ita "%s: Pronto per le connessioni\nVersion: '%s' socket: '%s' port: %d"" - jpn "%s: 準備完了\nVersion: '%s' socket: '%s' port: %d"" - kor "%s: 연결 준비중입니다\nVersion: '%s' socket: '%s' port: %d"" - nor "%s: klar for tilkoblinger\nVersion: '%s' socket: '%s' port: %d"" - norwegian-ny "%s: klar for tilkoblingar\nVersion: '%s' socket: '%s' port: %d"" - pol "%s: gotowe do poł?czenia\nVersion: '%s' socket: '%s' port: %d"" - por "%s: Pronto para conexões\nVersion: '%s' socket: '%s' port: %d"" - rum "%s: sint gata pentru conectii\nVersion: '%s' socket: '%s' port: %d"" - rus "%s: Готов принимать соединения.\nВерсия: '%s' сокет: '%s' порт: %d" - serbian "%s: Spreman za konekcije\nVersion: '%s' socket: '%s' port: %d"" - slo "%s: pripravený na spojenie\nVersion: '%s' socket: '%s' port: %d"" - spa "%s: preparado para conexiones\nVersion: '%s' socket: '%s' port: %d"" - swe "%s: klar att ta emot klienter\nVersion: '%s' socket: '%s' port: %d"" - ukr "%s: Готовий для з'єднань!\nVersion: '%s' socket: '%s' port: %d"" +ER_UNUSED_2 + eng "You should never see it" ER_NORMAL_SHUTDOWN cze "%s: norm-Bální ukončení\n" dan "%s: Normal nedlukning\n" @@ -4989,17 +4966,17 @@ ER_UNSUPPORTED_PS eng "This command is not supported in the prepared statement protocol yet" ger "Dieser Befehl wird im Protokoll für vorbereitete Anweisungen noch nicht unterstützt" ER_GET_ERRMSG - dan "Modtog fejl %d '%-.100s' fra %s" - eng "Got error %d '%-.100s' from %s" - ger "Fehler %d '%-.100s' von %s" - nor "Mottok feil %d '%-.100s' fa %s" - norwegian-ny "Mottok feil %d '%-.100s' fra %s" + dan "Modtog fejl %d '%-.200s' fra %s" + eng "Got error %d '%-.200s' from %s" + ger "Fehler %d '%-.200s' von %s" + nor "Mottok feil %d '%-.200s' fa %s" + norwegian-ny "Mottok feil %d '%-.200s' fra %s" ER_GET_TEMPORARY_ERRMSG - dan "Modtog temporary fejl %d '%-.100s' fra %s" - eng "Got temporary error %d '%-.100s' from %s" - ger "Temporärer Fehler %d '%-.100s' von %s" - nor "Mottok temporary feil %d '%-.100s' fra %s" - norwegian-ny "Mottok temporary feil %d '%-.100s' fra %s" + dan "Modtog temporary fejl %d '%-.200s' fra %s" + eng "Got temporary error %d '%-.200s' from %s" + ger "Temporärer Fehler %d '%-.200s' von %s" + nor "Mottok temporary feil %d '%-.200s' fra %s" + norwegian-ny "Mottok temporary feil %d '%-.200s' fra %s" ER_UNKNOWN_TIME_ZONE eng "Unknown or incorrect time zone: '%-.64s'" ger "Unbekannte oder falsche Zeitzone: '%-.64s'" diff --git a/sql/slave.cc b/sql/slave.cc index dab978be591..a887ad9d924 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1791,10 +1791,14 @@ when it try to get the value of TIME_ZONE global variable from master."; if (mysql_errno(mysql) == ER_UNKNOWN_SYSTEM_VARIABLE) { - // this is tolerable as OM -> NS is supported - mi->report(WARNING_LEVEL, mysql_errno(mysql), - "Notifying master by %s failed with " - "error: %s", query, mysql_error(mysql)); + /* Ignore this expected error if not a high error level */ + if (global_system_variables.log_warnings > 1) + { + // this is tolerable as OM -> NS is supported + mi->report(WARNING_LEVEL, mysql_errno(mysql), + "Notifying master by %s failed with " + "error: %s", query, mysql_error(mysql)); + } } else { diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 852661d5915..48ac853310d 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -157,10 +157,11 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, - Run a normal repair using the new index file and the old data file */ - if (table->s->frm_version != FRM_VER_TRUE_VARCHAR) + if (table->s->frm_version != FRM_VER_TRUE_VARCHAR && + table->s->varchar_fields) { error= send_check_errmsg(thd, table_list, "repair", - "Failed repairing incompatible .frm file"); + "Failed repairing a very old .frm file as the data file format has changed between versions. Please dump the table in your old system with mysqldump and read it into this system with mysql or mysqlimport"); goto end; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6e0a852601c..948b2ee7285 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -255,6 +255,7 @@ static void check_unused(THD *thd) uint count= 0, open_files= 0, idx= 0; TABLE *cur_link, *start_link, *entry; TABLE_SHARE *share; + DBUG_ENTER("check_unused"); if ((start_link=cur_link=unused_tables)) { @@ -263,7 +264,7 @@ static void check_unused(THD *thd) if (cur_link != cur_link->next->prev || cur_link != cur_link->prev->next) { DBUG_PRINT("error",("Unused_links aren't linked properly")); /* purecov: inspected */ - return; /* purecov: inspected */ + DBUG_VOID_RETURN; /* purecov: inspected */ } } while (count++ < table_cache_count && (cur_link=cur_link->next) != start_link); @@ -311,6 +312,7 @@ static void check_unused(THD *thd) DBUG_PRINT("error",("Unused_links doesn't match open_cache: diff: %d", /* purecov: inspected */ count)); /* purecov: inspected */ } + DBUG_VOID_RETURN; } #else #define check_unused(A) @@ -3038,6 +3040,7 @@ retry_share: MDL_deadlock_handler mdl_deadlock_handler(ot_ctx); bool wait_result; + DBUG_PRINT("info", ("old version of table share found")); release_table_share(share); mysql_mutex_unlock(&LOCK_open); @@ -3062,6 +3065,7 @@ retry_share: and try to reopen them. Note: refresh_version is currently changed only during FLUSH TABLES. */ + DBUG_PRINT("info", ("share version differs between tables")); release_table_share(share); mysql_mutex_unlock(&LOCK_open); (void)ot_ctx->request_backoff_action(Open_table_context::OT_REOPEN_TABLES, @@ -3075,6 +3079,7 @@ retry_share: table= share->free_tables.front(); table_def_use_table(thd, table); /* Release the share as we hold an extra reference to it */ + DBUG_PRINT("info", ("release temporarily acquired table share")); release_table_share(share); } else @@ -3153,6 +3158,7 @@ err_lock: release_table_share(share); mysql_mutex_unlock(&LOCK_open); + DBUG_PRINT("exit", ("failed")); DBUG_RETURN(TRUE); } @@ -6907,7 +6913,7 @@ find_field_in_tables(THD *thd, Item_ident *item, */ if (db) return cur_field; - + if (found) { if (report_error == REPORT_ALL_ERRORS || @@ -6922,7 +6928,7 @@ find_field_in_tables(THD *thd, Item_ident *item, if (found) return found; - + /* If the field was qualified and there were no tables to search, issue an error that an unknown table was given. The situation is detected @@ -7849,10 +7855,16 @@ err: order, thus when we iterate over it, we are moving from the right to the left in the FROM clause. + NOTES + We can't run this many times as the first_name_resolution_table would + be different for subsequent runs when sub queries has been optimized + away. + RETURN TRUE Error FALSE OK */ + static bool setup_natural_join_row_types(THD *thd, List<TABLE_LIST> *from_clause, Name_resolution_context *context) @@ -7862,6 +7874,19 @@ static bool setup_natural_join_row_types(THD *thd, if (from_clause->elements == 0) DBUG_RETURN(false); /* We come here in the case of UNIONs. */ + /* + Do not redo work if already done: + 1) for stored procedures, + 2) for multitable update after lock failure and table reopening. + */ + if (!context->select_lex->first_natural_join_processing) + { + context->first_name_resolution_table= context->natural_join_first_table; + DBUG_PRINT("info", ("using cached setup_natural_join_row_types")); + DBUG_RETURN(false); + } + context->select_lex->first_natural_join_processing= false; + List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause); TABLE_LIST *table_ref; /* Current table reference. */ /* Table reference to the left of the current. */ @@ -7878,22 +7903,15 @@ static bool setup_natural_join_row_types(THD *thd, left_neighbor= table_ref_it++; } while (left_neighbor && left_neighbor->sj_subq_pred); - /* - Do not redo work if already done: - 1) for stored procedures, - 2) for multitable update after lock failure and table reopening. - */ - if (context->select_lex->first_natural_join_processing) + + if (store_top_level_join_columns(thd, table_ref, + left_neighbor, right_neighbor)) + DBUG_RETURN(true); + if (left_neighbor) { - if (store_top_level_join_columns(thd, table_ref, - left_neighbor, right_neighbor)) - DBUG_RETURN(true); - if (left_neighbor) - { - TABLE_LIST *first_leaf_on_the_right; - first_leaf_on_the_right= table_ref->first_leaf_for_name_resolution(); - left_neighbor->next_name_resolution_table= first_leaf_on_the_right; - } + TABLE_LIST *first_leaf_on_the_right; + first_leaf_on_the_right= table_ref->first_leaf_for_name_resolution(); + left_neighbor->next_name_resolution_table= first_leaf_on_the_right; } right_neighbor= table_ref; } @@ -7907,8 +7925,11 @@ static bool setup_natural_join_row_types(THD *thd, DBUG_ASSERT(right_neighbor); context->first_name_resolution_table= right_neighbor->first_leaf_for_name_resolution(); - context->select_lex->first_natural_join_processing= false; - + /* + This is only to ensure that first_name_resolution_table doesn't + change on re-execution + */ + context->natural_join_first_table= context->first_name_resolution_table; DBUG_RETURN (false); } @@ -8254,12 +8275,9 @@ bool setup_tables(THD *thd, Name_resolution_context *context, if (table_list->merge_underlying_list) { DBUG_ASSERT(table_list->is_merged_derived()); - Query_arena *arena= thd->stmt_arena, backup; + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); bool res; - if (arena->is_conventional()) - arena= 0; // For easier test - else - thd->set_n_backup_active_arena(arena, &backup); res= table_list->setup_underlying(thd); if (arena) thd->restore_active_arena(arena, &backup); @@ -8510,7 +8528,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, if (!(item= field_iterator.create_item(thd))) DBUG_RETURN(TRUE); -// DBUG_ASSERT(item->fixed); + /* cache the table for the Item_fields inserted by expanding stars */ if (item->type() == Item::FIELD_ITEM && tables->cacheable_table) ((Item_field *)item)->cached_table= tables; @@ -8638,11 +8656,8 @@ void wrap_ident(THD *thd, Item **conds) { Item_direct_ref_to_ident *wrapper; DBUG_ASSERT((*conds)->type() == Item::FIELD_ITEM || (*conds)->type() == Item::REF_ITEM); - Query_arena *arena= thd->stmt_arena, backup; - if (arena->is_conventional()) - arena= 0; - else - thd->set_n_backup_active_arena(arena, &backup); + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); if ((wrapper= new Item_direct_ref_to_ident((Item_ident *)(*conds)))) (*conds)= (Item*) wrapper; if (arena) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8abdd53469f..c446d901055 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1142,6 +1142,7 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno, got_warning= 1; break; case MYSQL_ERROR::WARN_LEVEL_ERROR: + mysql_audit_general(this, MYSQL_AUDIT_GENERAL_ERROR, sql_errno, msg); break; default: DBUG_ASSERT(FALSE); @@ -2295,6 +2296,7 @@ bool select_result::check_simple_select() const static String default_line_term("\n",default_charset_info); static String default_escaped("\\",default_charset_info); static String default_field_term("\t",default_charset_info); +static String default_enclosed_and_line_start("", default_charset_info); static String default_xml_row_term("<row>", default_charset_info); sql_exchange::sql_exchange(char *name, bool flag, @@ -2303,7 +2305,7 @@ sql_exchange::sql_exchange(char *name, bool flag, { filetype= filetype_arg; field_term= &default_field_term; - enclosed= line_start= &my_empty_string; + enclosed= line_start= &default_enclosed_and_line_start; line_term= filetype == FILETYPE_CSV ? &default_line_term : &default_xml_row_term; escaped= &default_escaped; diff --git a/sql/sql_class.h b/sql/sql_class.h index a3fc3a7866f..a7e3290c543 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -109,6 +109,10 @@ enum enum_filetype { FILETYPE_CSV, FILETYPE_XML }; #define MODE_NO_ENGINE_SUBSTITUTION (1ULL << 30) #define MODE_PAD_CHAR_TO_FULL_LENGTH (1ULL << 31) +/* Bits for different old style modes */ +#define OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE 1 +#define OLD_MODE_NO_PROGRESS_INFO 2 + extern char internal_table_name[2]; extern char empty_c_string[1]; extern MYSQL_PLUGIN_IMPORT const char **errmesg; @@ -478,6 +482,7 @@ typedef struct system_variables ulonglong long_query_time; ulonglong optimizer_switch; ulonglong sql_mode; ///< which non-standard SQL behaviour should be enabled + ulonglong old_behavior; ///< which old SQL behaviour should be enabled ulonglong option_bits; ///< OPTION_xxx constants, e.g. OPTION_PROFILING ulonglong join_buff_space_limit; ulonglong log_slow_filter; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index b584ed6de93..f09c585fa79 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -358,6 +358,14 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) if (derived->merged) return FALSE; + if (dt_select->uncacheable & UNCACHEABLE_RAND) + { + /* There is random function => fall back to materialization. */ + derived->change_refs_to_fields(); + derived->set_materialized_derived(); + return FALSE; + } + if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI || thd->lex->sql_command == SQLCOM_DELETE_MULTI) thd->save_prep_leaf_list= TRUE; @@ -604,11 +612,8 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) thd->lex->sql_command == SQLCOM_DELETE_MULTI)))) DBUG_RETURN(FALSE); - Query_arena *arena= thd->stmt_arena, backup; - if (arena->is_conventional()) - arena= 0; // For easier test - else - thd->set_n_backup_active_arena(arena, &backup); + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); SELECT_LEX *first_select= unit->first_select(); @@ -708,7 +713,7 @@ exit: { TABLE *table= derived->table; table->derived_select_number= first_select->select_number; - table->s->tmp_table= NON_TRANSACTIONAL_TMP_TABLE; + table->s->tmp_table= INTERNAL_TMP_TABLE; #ifndef NO_EMBEDDED_ACCESS_CHECKS if (derived->referencing_view) table->grant= derived->grant; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 008c6e573c6..a20596f017b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1746,7 +1746,9 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) if (info->ignore && !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) { - table->file->print_error(error, MYF(ME_JUST_WARNING)); + if (!(thd->variables.old_behavior & + OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) + table->file->print_error(error, MYF(ME_JUST_WARNING)); goto ok_or_after_trg_err; } goto err; @@ -1874,7 +1876,9 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) if (!info->ignore || table->file->is_fatal_error(error, HA_CHECK_DUP)) goto err; - table->file->print_error(error, MYF(ME_JUST_WARNING)); + if (!(thd->variables.old_behavior & + OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) + table->file->print_error(error, MYF(ME_JUST_WARNING)); table->file->restore_auto_increment(prev_insert_id); goto ok_or_after_trg_err; } @@ -2423,6 +2427,10 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) goto error; dfield_ptr= copy->default_field; } + + /* Ensure we don't use the table list of the original table */ + copy->pos_in_table_list= 0; + /* Make a copy of all fields. The copied fields need to point into the copied record. This is done diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a89056eaf79..850dbc813bb 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -497,6 +497,7 @@ void lex_start(THD *thd) lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc; lex->select_lex.group_list.empty(); lex->select_lex.order_list.empty(); + lex->select_lex.gorder_list.empty(); lex->duplicates= DUP_ERROR; lex->ignore= 0; lex->spname= NULL; @@ -2145,14 +2146,15 @@ void st_select_lex_unit::exclude_tree() this to 'last' as dependent SYNOPSIS - last - pointer to last st_select_lex struct, before wich all + last - pointer to last st_select_lex struct, before which all st_select_lex have to be marked as dependent NOTE 'last' should be reachable from this st_select_lex_node */ -bool st_select_lex::mark_as_dependent(THD *thd, st_select_lex *last, Item *dependency) +bool st_select_lex::mark_as_dependent(THD *thd, st_select_lex *last, + Item *dependency) { DBUG_ASSERT(this != last); @@ -2344,7 +2346,10 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) If we need a bigger array, we must allocate a new one. */ if (ref_pointer_array_size >= n_elems) + { + DBUG_PRINT("info", ("reusing old ref_array")); return false; + } } ref_pointer_array= static_cast<Item**>(arena->alloc(sizeof(Item*) * n_elems)); if (ref_pointer_array != NULL) @@ -2610,7 +2615,9 @@ bool LEX::can_be_merged() // TODO: do not forget implement case when select_lex.table_list.elements==0 /* find non VIEW subqueries/unions */ - bool selects_allow_merge= select_lex.next_select() == 0; + bool selects_allow_merge= (select_lex.next_select() == 0 && + !(select_lex.uncacheable & + UNCACHEABLE_RAND)); if (selects_allow_merge) { for (SELECT_LEX_UNIT *tmp_unit= select_lex.first_inner_unit(); @@ -3346,6 +3353,7 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl) void st_select_lex::fix_prepare_information(THD *thd, Item **conds, Item **having_conds) { + DBUG_ENTER("st_select_lex::fix_prepare_information"); if (!thd->stmt_arena->is_conventional() && first_execution) { first_execution= 0; @@ -3374,6 +3382,7 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds, } fix_prepare_info_in_table_list(thd, table_list.first); } + DBUG_VOID_RETURN; } @@ -4111,11 +4120,8 @@ void SELECT_LEX::mark_const_derived(bool empty) bool st_select_lex::save_leaf_tables(THD *thd) { - Query_arena *arena= thd->stmt_arena, backup; - if (arena->is_conventional()) - arena= 0; - else - thd->set_n_backup_active_arena(arena, &backup); + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); List_iterator_fast<TABLE_LIST> li(leaf_tables); TABLE_LIST *table; @@ -4143,10 +4149,7 @@ bool st_select_lex::save_prep_leaf_tables(THD *thd) return 0; Query_arena *arena= thd->stmt_arena, backup; - if (arena->is_conventional()) - arena= 0; - else - thd->set_n_backup_active_arena(arena, &backup); + arena= thd->activate_stmt_arena_if_needed(&backup); List_iterator_fast<TABLE_LIST> li(leaf_tables); TABLE_LIST *table; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 4ce9c3828d7..944435d0acf 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2792,6 +2792,7 @@ struct LEX: public Query_tables_list sl->uncacheable|= cause; un->uncacheable|= cause; } + select_lex.uncacheable|= cause; } void set_trg_event_type_for_tables(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7366e4fc10f..02723647717 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2013,6 +2013,7 @@ mysql_execute_command(THD *thd) Rpl_filter *rpl_filter= thd->rpl_filter; #endif DBUG_ENTER("mysql_execute_command"); + #ifdef WITH_PARTITION_STORAGE_ENGINE thd->work_part_info= 0; #endif @@ -4811,6 +4812,7 @@ finish: DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() || thd->in_multi_stmt_transaction_mode()); + lex->unit.cleanup(); if (! thd->in_sub_stmt) { @@ -4842,7 +4844,6 @@ finish: ha_maria::implicit_commit(thd, FALSE); #endif } - lex->unit.cleanup(); /* Free tables */ thd_proc_info(thd, "closing tables"); @@ -6434,7 +6435,11 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->schema_table= schema_table; } ptr->select_lex= lex->current_select; - ptr->cacheable_table= 1; + /* + We can't cache internal temporary tables between prepares as the + table may be deleted before next exection. + */ + ptr->cacheable_table= !table->is_derived_table(); ptr->index_hints= index_hints_arg; ptr->option= option ? option->str : 0; /* check that used name is unique */ diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 454ff7c443c..752ad99908c 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -5105,6 +5105,8 @@ that are reorganised. } else if (alter_info->flags & ALTER_REBUILD_PARTITION) { + set_engine_all_partitions(tab_part_info, + tab_part_info->default_engine_type); if (set_part_state(alter_info, tab_part_info, PART_CHANGED)) { my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "REBUILD"); diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index d311d84d9de..f25c424e29a 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -191,6 +191,7 @@ mysql_mutex_t LOCK_plugin; static DYNAMIC_ARRAY plugin_dl_array; static DYNAMIC_ARRAY plugin_array; static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; +static MEM_ROOT plugin_mem_root; static bool reap_needed= false; static int plugin_array_version=0; @@ -202,7 +203,7 @@ ulong dlopen_count; write-lock on LOCK_system_variables_hash is required before modifying the following variables/structures */ -static MEM_ROOT plugin_mem_root; +static MEM_ROOT plugin_vars_mem_root; static uint global_variables_dynamic_size= 0; static HASH bookmark_hash; @@ -298,8 +299,8 @@ public: /* prototypes */ -static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv); -static bool plugin_load_list(MEM_ROOT *, int *, char **, const char *); +static void plugin_load(MEM_ROOT *tmp_root); +static bool plugin_load_list(MEM_ROOT *, const char *); static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *, int *, char **); static bool register_builtin(struct st_maria_plugin *, struct st_plugin_int *, @@ -1022,8 +1023,7 @@ static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin) Requires that a write-lock is held on LOCK_system_variables_hash */ static bool plugin_add(MEM_ROOT *tmp_root, - const LEX_STRING *name, LEX_STRING *dl, - int *argc, char **argv, int report) + const LEX_STRING *name, LEX_STRING *dl, int report) { struct st_plugin_int tmp; struct st_maria_plugin *plugin; @@ -1088,15 +1088,9 @@ static bool plugin_add(MEM_ROOT *tmp_root, tmp.ref_count= 0; tmp.state= PLUGIN_IS_UNINITIALIZED; tmp.load_option= PLUGIN_ON; - if (test_plugin_options(tmp_root, &tmp, argc, argv)) - tmp.state= PLUGIN_IS_DISABLED; if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) - { - mysql_del_sys_var_chain(tmp.system_vars); - restore_pluginvar_names(tmp.system_vars); goto err; - } plugin_array_version++; if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr)) tmp_plugin_ptr->state= PLUGIN_IS_FREED; @@ -1181,6 +1175,8 @@ static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check) if (ref_check && plugin->ref_count) sql_print_error("Plugin '%s' has ref_count=%d after deinitialization.", plugin->name.str, plugin->ref_count); + + restore_pluginvar_names(plugin->system_vars); } static void plugin_del(struct st_plugin_int *plugin) @@ -1188,10 +1184,6 @@ static void plugin_del(struct st_plugin_int *plugin) DBUG_ENTER("plugin_del"); mysql_mutex_assert_owner(&LOCK_plugin); /* Free allocated strings before deleting the plugin. */ - mysql_rwlock_wrlock(&LOCK_system_variables_hash); - mysql_del_sys_var_chain(plugin->system_vars); - mysql_rwlock_unlock(&LOCK_system_variables_hash); - restore_pluginvar_names(plugin->system_vars); plugin_vars_free_values(plugin->system_vars); my_hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin); plugin_dl_del(plugin->plugin_dl); @@ -1326,7 +1318,8 @@ void plugin_unlock_list(THD *thd, plugin_ref *list, uint count) } -static int plugin_initialize(struct st_plugin_int *plugin) +static int plugin_initialize(MEM_ROOT *tmp_root, struct st_plugin_int *plugin, + int *argc, char **argv, bool options_only) { int ret= 1; DBUG_ENTER("plugin_initialize"); @@ -1336,6 +1329,18 @@ static int plugin_initialize(struct st_plugin_int *plugin) DBUG_ASSERT(state == PLUGIN_IS_UNINITIALIZED); mysql_mutex_unlock(&LOCK_plugin); + + mysql_rwlock_wrlock(&LOCK_system_variables_hash); + if (test_plugin_options(tmp_root, plugin, argc, argv)) + state= PLUGIN_IS_DISABLED; + mysql_rwlock_unlock(&LOCK_system_variables_hash); + + if (options_only || state == PLUGIN_IS_DISABLED) + { + ret= 0; + goto err; + } + if (plugin_type_initialize[plugin->plugin->type]) { if ((*plugin_type_initialize[plugin->plugin->type])(plugin)) @@ -1395,6 +1400,9 @@ static int plugin_initialize(struct st_plugin_int *plugin) ret= 0; err: + if (ret) + restore_pluginvar_names(plugin->system_vars); + mysql_mutex_lock(&LOCK_plugin); plugin->state= state; @@ -1492,6 +1500,7 @@ int plugin_init(int *argc, char **argv, int flags) #endif init_alloc_root(&plugin_mem_root, 4096, 4096, MYF(0)); + init_alloc_root(&plugin_vars_mem_root, 4096, 4096, MYF(0)); init_alloc_root(&tmp_root, 4096, 4096, MYF(0)); if (my_hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0, @@ -1559,10 +1568,7 @@ int plugin_init(int *argc, char **argv, int flags) } free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE)); - if (test_plugin_options(&tmp_root, &tmp, argc, argv)) - tmp.state= PLUGIN_IS_DISABLED; - else - tmp.state= PLUGIN_IS_UNINITIALIZED; + tmp.state= PLUGIN_IS_UNINITIALIZED; if (register_builtin(plugin, &tmp, &plugin_ptr)) goto err_unlock; @@ -1577,15 +1583,12 @@ int plugin_init(int *argc, char **argv, int flags) mysqld --help for all other users, we will only initialize MyISAM here. */ - if (!(flags & PLUGIN_INIT_SKIP_INITIALIZATION) || is_myisam) + if (plugin_initialize(&tmp_root, plugin_ptr, argc, argv, !is_myisam && + (flags & PLUGIN_INIT_SKIP_INITIALIZATION))) { - if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED && - plugin_initialize(plugin_ptr)) - { - if (mandatory) - goto err_unlock; - plugin_ptr->state= PLUGIN_IS_DISABLED; - } + if (mandatory) + goto err_unlock; + plugin_ptr->state= PLUGIN_IS_DISABLED; } /* @@ -1611,14 +1614,11 @@ int plugin_init(int *argc, char **argv, int flags) if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING)) { if (opt_plugin_load) - plugin_load_list(&tmp_root, argc, argv, opt_plugin_load); + plugin_load_list(&tmp_root, opt_plugin_load); if (!(flags & PLUGIN_INIT_SKIP_PLUGIN_TABLE)) - plugin_load(&tmp_root, argc, argv); + plugin_load(&tmp_root); } - if (flags & PLUGIN_INIT_SKIP_INITIALIZATION) - goto end; - /* Now we initialize all remaining plugins */ @@ -1630,9 +1630,10 @@ int plugin_init(int *argc, char **argv, int flags) for (i= 0; i < plugin_array.elements; i++) { plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **); - if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED) + if (plugin_ptr->plugin_dl && plugin_ptr->state == PLUGIN_IS_UNINITIALIZED) { - if (plugin_initialize(plugin_ptr)) + if (plugin_initialize(&tmp_root, plugin_ptr, argc, argv, + (flags & PLUGIN_INIT_SKIP_INITIALIZATION))) { plugin_ptr->state= PLUGIN_IS_DYING; *(reap++)= plugin_ptr; @@ -1659,7 +1660,6 @@ int plugin_init(int *argc, char **argv, int flags) if (reaped_mandatory_plugin) goto err; -end: free_root(&tmp_root, MYF(0)); DBUG_RETURN(0); @@ -1698,7 +1698,7 @@ static bool register_builtin(struct st_maria_plugin *plugin, /* called only by plugin_init() */ -static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) +static void plugin_load(MEM_ROOT *tmp_root) { TABLE_LIST tables; TABLE *table; @@ -1757,7 +1757,7 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) the mutex here to satisfy the assert */ mysql_mutex_lock(&LOCK_plugin); - if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) + if (plugin_add(tmp_root, &name, &dl, REPORT_TO_LOG)) sql_print_warning("Couldn't load plugin named '%s' with soname '%s'.", str_name.c_ptr(), str_dl.c_ptr()); free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); @@ -1779,8 +1779,7 @@ end: /* called only by plugin_init() */ -static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, - const char *list) +static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) { char buffer[FN_REFLEN]; LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name; @@ -1815,14 +1814,14 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, mysql_mutex_lock(&LOCK_plugin); free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); name.str= 0; // load everything - if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) + if (plugin_add(tmp_root, &name, &dl, REPORT_TO_LOG)) goto error; } else { free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); mysql_mutex_lock(&LOCK_plugin); - if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) + if (plugin_add(tmp_root, &name, &dl, REPORT_TO_LOG)) goto error; } mysql_mutex_unlock(&LOCK_plugin); @@ -1980,6 +1979,7 @@ void plugin_shutdown(void) my_hash_free(&bookmark_hash); free_root(&plugin_mem_root, MYF(0)); + free_root(&plugin_vars_mem_root, MYF(0)); global_variables_dynamic_size= 0; @@ -1991,28 +1991,22 @@ void plugin_shutdown(void) That is, initialize it, and update mysql.plugin table */ -static bool finalize_install(THD *thd, TABLE *table, const LEX_STRING *name) +static bool finalize_install(THD *thd, TABLE *table, const LEX_STRING *name, + int *argc, char **argv) { struct st_plugin_int *tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN); int error; DBUG_ASSERT(tmp); mysql_mutex_assert_owner(&LOCK_plugin); // because of tmp->state - if (tmp->state == PLUGIN_IS_DISABLED) - { - if (global_system_variables.log_warnings) - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF), - name->str, "Plugin is disabled"); - } - else if (tmp->state != PLUGIN_IS_UNINITIALIZED) + if (tmp->state != PLUGIN_IS_UNINITIALIZED) { /* already installed */ return 0; } else { - if (plugin_initialize(tmp)) + if (plugin_initialize(thd->mem_root, tmp, argc, argv, false)) { report_error(REPORT_TO_USER, ER_CANT_INITIALIZE_UDF, name->str, "Plugin initialization function failed."); @@ -2020,6 +2014,13 @@ static bool finalize_install(THD *thd, TABLE *table, const LEX_STRING *name) return 1; } } + if (tmp->state == PLUGIN_IS_DISABLED) + { + if (global_system_variables.log_warnings) + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF), + name->str, "Plugin is disabled"); + } /* We do not replicate the INSTALL PLUGIN statement. Disable binlogging @@ -2069,6 +2070,12 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, MYSQL_LOCK_IGNORE_TIMEOUT))) DBUG_RETURN(TRUE); + if (my_load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv, NULL)) + { + report_error(REPORT_TO_USER, ER_PLUGIN_IS_NOT_LOADED, name->str); + DBUG_RETURN(TRUE); + } + /* Pre-acquire audit plugins for events that may potentially occur during [UN]INSTALL PLUGIN. @@ -2095,23 +2102,12 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, mysql_audit_acquire_plugins(thd, event_class_mask); mysql_mutex_lock(&LOCK_plugin); - mysql_rwlock_wrlock(&LOCK_system_variables_hash); - - if (my_load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv, NULL)) - { - report_error(REPORT_TO_USER, ER_PLUGIN_IS_NOT_LOADED, name->str); - goto err; - } - error= plugin_add(thd->mem_root, name, &dl, &argc, argv, REPORT_TO_USER); - if (argv) - free_defaults(argv); - mysql_rwlock_unlock(&LOCK_system_variables_hash); - + error= plugin_add(thd->mem_root, name, &dl, REPORT_TO_USER); if (error) goto err; if (name->str) - error= finalize_install(thd, table, name); + error= finalize_install(thd, table, name, &argc, argv); else { st_plugin_dl *plugin_dl= plugin_dl_find(&dl); @@ -2119,22 +2115,20 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, for (plugin= plugin_dl->plugins; plugin->info; plugin++) { LEX_STRING str= { const_cast<char*>(plugin->name), strlen(plugin->name) }; - error|= finalize_install(thd, table, &str); + error|= finalize_install(thd, table, &str, &argc, argv); } } if (error) - goto deinit; - - mysql_mutex_unlock(&LOCK_plugin); - DBUG_RETURN(FALSE); - -deinit: - reap_needed= true; - reap_plugins(); + { + reap_needed= true; + reap_plugins(); + } err: mysql_mutex_unlock(&LOCK_plugin); - DBUG_RETURN(TRUE); + if (argv) + free_defaults(argv); + DBUG_RETURN(error); } @@ -2857,7 +2851,7 @@ static st_bookmark *register_var(const char *plugin, const char *name, if (!(result= find_bookmark(NULL, varname + 1, flags))) { - result= (st_bookmark*) alloc_root(&plugin_mem_root, + result= (st_bookmark*) alloc_root(&plugin_vars_mem_root, sizeof(struct st_bookmark) + length-1); varname[0]= plugin_var_bookmark_key(flags); memcpy(result->key, varname, length); @@ -2916,6 +2910,7 @@ static st_bookmark *register_var(const char *plugin, const char *name, static void restore_pluginvar_names(sys_var *first) { + mysql_del_sys_var_chain(first); for (sys_var *var= first; var; var= var->next) { sys_var_pluginvar *pv= var->cast_pluginvar(); @@ -3835,7 +3830,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, enum_plugin_load_option plugin_load_option= tmp->load_option; MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ? - &tmp->mem_root : &plugin_mem_root; + &tmp->mem_root : &plugin_vars_mem_root; st_mysql_sys_var **opt; my_option *opts= NULL; LEX_STRING plugin_name; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 9c37c5d28fb..12b74b40815 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -880,7 +880,7 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, if (param->state == Item_param::NO_VALUE) DBUG_RETURN(1); - if (param->limit_clause_param) + if (param->limit_clause_param && param->state != Item_param::INT_VALUE) { param->set_int(param->val_int(), MY_INT64_NUM_DECIMAL_DIGITS); param->item_type= Item::INT_ITEM; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 54f9881fe45..fb258b1d5aa 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1083,8 +1083,10 @@ JOIN::optimize_inner() if (select_lex->handle_derived(thd->lex, DT_MERGE)) DBUG_RETURN(TRUE); table_count= select_lex->leaf_tables.elements; - select_lex->update_used_tables(); } + // Update used tables after all handling derived table procedures + select_lex->update_used_tables(); + /* In fact we transform underlying subqueries after their 'prepare' phase and before 'optimize' from upper query 'optimize' to allow semijoin @@ -1163,11 +1165,8 @@ TODO: make view to decide if it is possible to write to WHERE directly or make S MEMROOT for prepared statements and stored procedures. */ - Query_arena *arena= thd->stmt_arena, backup; - if (arena->is_conventional()) - arena= 0; // For easier test - else - thd->set_n_backup_active_arena(arena, &backup); + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); sel->first_cond_optimization= 0; @@ -2434,6 +2433,7 @@ void JOIN::exec_inner() In this case JOIN::exec must check for JOIN::having_value, in the same way it checks for JOIN::cond_value. */ + DBUG_ASSERT(error == 0); if (cond_value != Item::COND_FALSE && having_value != Item::COND_FALSE && (!conds || conds->val_int()) && @@ -2444,16 +2444,15 @@ void JOIN::exec_inner() procedure->end_of_records()) : result->send_data(fields_list)> 0)) error= 1; else - { - error= (int) result->send_eof(); send_records= ((select_options & OPTION_FOUND_ROWS) ? 1 : thd->sent_row_count); - } } else - { - error=(int) result->send_eof(); send_records= 0; + if (!error) + { + join_free(); // Unlock all cursors + error= (int) result->send_eof(); } } /* Single select (without union) always returns 0 or 1 row */ @@ -3395,7 +3394,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)* (MAX_TABLES + table_count + 1)); stat_vector= stat_ref + MAX_TABLES; - table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2)); + table_vector=(TABLE**) join->thd->calloc(sizeof(TABLE*)*(table_count*2)); join->positions= new (join->thd->mem_root) POSITION[(table_count+1)]; /* best_positions is ok to allocate with alloc() as we copy things to it with @@ -11449,6 +11448,16 @@ void JOIN::cleanup(bool full) { tab->cleanup(); } + + if (tabs_kind == WALK_OPTIMIZATION_TABS && + first_breadth_first_tab(this, WALK_OPTIMIZATION_TABS) != + first_breadth_first_tab(this, WALK_EXECUTION_TABS)) + { + JOIN_TAB *jt= first_breadth_first_tab(this, WALK_EXECUTION_TABS); + /* We've walked optimization tabs. do execution ones too */ + if (jt) + jt->cleanup(); + } } cleaned= true; @@ -11669,6 +11678,8 @@ static void update_depend_map_for_order(JOIN *join, ORDER *order) Remove all constants and check if ORDER only contains simple expressions. + We also remove all duplicate expressions, keeping only the first one. + simple_order is set to 1 if sort_order only uses fields from head table and the head table is not a LEFT JOIN table. @@ -11676,9 +11687,10 @@ static void update_depend_map_for_order(JOIN *join, ORDER *order) @param first_order List of SORT or GROUP order @param cond WHERE statement @param change_list Set to 1 if we should remove things from list. - If this is not set, then only simple_order is - calculated. - @param simple_order Set to 1 if we are only using simple expressions + If this is not set, then only simple_order is + calculated. + @param simple_order Set to 1 if we are only using simple + expressions. @return Returns new sort order @@ -11691,7 +11703,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, if (join->table_count == join->const_tables) return change_list ? 0 : first_order; // No need to sort - ORDER *order,**prev_ptr; + ORDER *order,**prev_ptr, *tmp_order; table_map first_table; table_map not_const_tables= ~join->const_table_map; table_map ref; @@ -11705,7 +11717,6 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, first_is_base_table= TRUE; } - /* Cleanup to avoid interference of calls of this function for ORDER BY and GROUP BY @@ -11774,6 +11785,17 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, } } } + /* Remove ORDER BY entries that we have seen before */ + for (tmp_order= first_order; + tmp_order != order; + tmp_order= tmp_order->next) + { + if (tmp_order->item[0]->eq(order->item[0],1)) + break; + } + if (tmp_order != order) + continue; // Duplicate order by. Remove + if (change_list) *prev_ptr= order; // use this entry prev_ptr= &order->next; @@ -15413,7 +15435,8 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, save_sum_fields|= param->precomputed_group_by; DBUG_ENTER("create_tmp_table"); DBUG_PRINT("enter", - ("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d", + ("table_alias: '%s' distinct: %d save_sum_fields: %d " + "rows_limit: %lu group: %d", table_alias, (int) distinct, (int) save_sum_fields, (ulong) rows_limit,test(group))); @@ -15856,23 +15879,8 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, if (!(field->flags & NOT_NULL_FLAG)) { - if (field->flags & GROUP_FLAG && !using_unique_constraint) - { - /* - We have to reserve one byte here for NULL bits, - as this is updated by 'end_update()' - */ - *pos++=0; // Null is stored here - recinfo->length=1; - recinfo->type=FIELD_NORMAL; - recinfo++; - bzero((uchar*) recinfo,sizeof(*recinfo)); - } - else - { - recinfo->null_bit= (uint8)1 << (null_count & 7); - recinfo->null_pos= null_count/8; - } + recinfo->null_bit= (uint8)1 << (null_count & 7); + recinfo->null_pos= null_count/8; field->move_field(pos,null_flags+null_count/8, (uint8)1 << (null_count & 7)); null_count++; @@ -16875,7 +16883,8 @@ free_tmp_table(THD *thd, TABLE *entry) MEM_ROOT own_root= entry->mem_root; const char *save_proc_info; DBUG_ENTER("free_tmp_table"); - DBUG_PRINT("enter",("table: %s",entry->alias.c_ptr())); + DBUG_PRINT("enter",("table: %s alias: %s",entry->s->table_name.str, + entry->alias.c_ptr())); save_proc_info=thd->proc_info; thd_proc_info(thd, "removing tmp table"); @@ -18841,19 +18850,6 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), goto end; } - /* - Copy null bits from group key to table - We can't copy all data as the key may have different format - as the row data (for example as with VARCHAR keys) - */ - KEY_PART_INFO *key_part; - for (group=table->group,key_part=table->key_info[0].key_part; - group ; - group=group->next,key_part++) - { - if (key_part->null_bit) - memcpy(table->record[0]+key_part->offset, group->buff, 1); - } init_tmptable_sum_functions(join->sum_funcs); if (copy_funcs(join->tmp_table_param.items_to_copy, join->thd)) DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ @@ -19507,7 +19503,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, key as a suffix to the secondary keys. If it has continue to check the primary key as a suffix. */ - if (!on_pk_suffix && + if (!on_pk_suffix && (table->key_info[idx].ext_key_part_map & 1) && (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && table->s->primary_key != MAX_KEY && table->s->primary_key != idx) @@ -19531,20 +19527,22 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, (((key_part_map) 1) << pk_part_idx))) break; } + /* Adjust const_key_parts */ const_key_parts&= (((key_part_map) 1) << pk_part_idx) -1; - for (; const_key_parts & 1 ; const_key_parts>>= 1) - key_part++; + for (; const_key_parts & 1 ; const_key_parts>>= 1) + key_part++; /* Test if the primary key parts were all const (i.e. there's one row). The sorting doesn't matter. */ - if (key_part == start+table->key_info[table->s->primary_key].key_parts && + if (key_part == + start+table->key_info[table->s->primary_key].key_parts && reverse == 0) { key_parts= 0; - reverse= 1; + reverse= 1; // Key is ok to use goto ok; } } @@ -20129,7 +20127,7 @@ check_reverse_order: table->disable_keyread(); } } - else if (tab->type != JT_ALL) + else if (tab->type != JT_ALL || tab->select->quick) { /* We're about to use a quick access to the table. diff --git a/sql/sql_show.cc b/sql/sql_show.cc index bb788175603..aac5932c593 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2209,7 +2209,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) field->maybe_null=1; field_list.push_back(field=new Item_empty_string("Info",max_query_length)); field->maybe_null=1; - if (!thd->variables.old_mode) + if (!thd->variables.old_mode && + !(thd->variables.old_behavior & OLD_MODE_NO_PROGRESS_INFO)) { field_list.push_back(field= new Item_float("Progress", 0.0, 3, 7)); field->maybe_null= 0; @@ -2281,6 +2282,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) (double) tmp->progress.max_counter) / (double) max_stage)) * 100.0); + set_if_smaller(thd_info->progress, 100); } else thd_info->progress= 0.0; @@ -2315,7 +2317,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) protocol->store(thd_info->state_info, system_charset_info); protocol->store(thd_info->query_string.str(), thd_info->query_string.charset()); - if (!thd->variables.old_mode) + if (!thd->variables.old_mode && + !(thd->variables.old_behavior & OLD_MODE_NO_PROGRESS_INFO)) protocol->store(thd_info->progress, 3, &store_buffer); if (protocol->write()) break; /* purecov: inspected */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e3e777f06fe..d63ce1c8707 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7136,14 +7136,35 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, /* Only report error if handler has not already reported an error */ if (!thd->is_error()) { - /* - Exchange the key_info for the error message. If we exchange - key number by key name in the message later, we need correct info. - */ - KEY *save_key_info= table->key_info; - table->key_info= key_info; - table->file->print_error(error, MYF(0)); - table->key_info= save_key_info; + /* + HACK HACK HACK + Prepare the list of keys for an error message. + It must match what the engine does internally in ::add_index(). + Here we emulate what innobase_create_key_def() does. + Luckily, in 10.0 this will go away. + */ + KEY *save_key_info= table->key_info; + uint add_cnt= index_add_count, old_cnt= table->s->keys; + KEY *merged= (KEY*)thd->alloc((old_cnt + add_cnt) * sizeof(KEY)); +#define is_PK(K) (!my_strcasecmp(system_charset_info, (K)->name, "PRIMARY")) + + if (is_PK(key_info)) + { + merged[0]= key_info[0]; + if (is_PK(table->key_info)) + { + old_cnt--; + table->key_info++; + } + memcpy(merged + 1, table->key_info, old_cnt * sizeof(KEY)); + memcpy(merged + old_cnt + 1, key_info + 1, (add_cnt - 1) * sizeof(KEY)); + } + else + merged= key_info; + + table->key_info= merged; + table->file->print_error(error, MYF(0)); + table->key_info= save_key_info; } goto err_new_table_cleanup; } diff --git a/sql/sql_time.cc b/sql/sql_time.cc index cf3cdd61000..507e77e7b2d 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -230,6 +230,20 @@ check_date_with_warn(const MYSQL_TIME *ltime, ulonglong fuzzy_date, } +bool +adjust_time_range_with_warn(MYSQL_TIME *ltime, uint dec) +{ + MYSQL_TIME copy= *ltime; + ErrConvTime str(©); + int warnings= 0; + if (check_time_range(ltime, dec, &warnings)) + return true; + if (warnings) + make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + &str, MYSQL_TIMESTAMP_TIME, NullS); + return false; +} + /* Convert a string to 8-bit representation, for use in str_to_time/str_to_date/str_to_date. diff --git a/sql/sql_time.h b/sql/sql_time.h index ab8f0e0b962..f9092769749 100644 --- a/sql/sql_time.h +++ b/sql/sql_time.h @@ -124,5 +124,6 @@ check_date(const MYSQL_TIME *ltime, ulonglong flags, int *was_cut) } bool check_date_with_warn(const MYSQL_TIME *ltime, ulonglong fuzzy_date, timestamp_type ts_type); - +bool adjust_time_range_with_warn(MYSQL_TIME *ltime, uint dec); + #endif /* SQL_TIME_INCLUDED */ diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 76857b58234..448e3c88d17 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -653,7 +653,10 @@ bool st_select_lex_unit::exec() { ha_rows records_at_start= 0; thd->lex->current_select= sl; - fake_select_lex->uncacheable|= sl->uncacheable; + if (sl != &thd->lex->select_lex) + fake_select_lex->uncacheable|= sl->uncacheable; + else + fake_select_lex->uncacheable= 0; { set_limit(sl); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 25986428089..2554909aea9 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1083,11 +1083,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, will be TRUE as far as we make new table cache). */ old_lex= thd->lex; - arena= thd->stmt_arena; - if (arena->is_conventional()) - arena= 0; - else - thd->set_n_backup_active_arena(arena, &backup); + arena= thd->activate_stmt_arena_if_needed(&backup); /* init timestamp */ if (!table->timestamp.str) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 19d8d1854a1..8e9b2cc8115 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9562,7 +9562,7 @@ variable_aux: if ($$ == NULL) MYSQL_YYABORT; LEX *lex= Lex; - lex->uncacheable(UNCACHEABLE_RAND); + lex->uncacheable(UNCACHEABLE_SIDEEFFECT); lex->set_var_list.push_back(item); } | ident_or_text @@ -9571,7 +9571,7 @@ variable_aux: if ($$ == NULL) MYSQL_YYABORT; LEX *lex= Lex; - lex->uncacheable(UNCACHEABLE_RAND); + lex->uncacheable(UNCACHEABLE_SIDEEFFECT); } | '@' opt_var_ident_type ident_or_text opt_component { diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 08b4953b2e4..7b0b64f9961 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2002, 2012, Oracle and/or its affiliates. - Copyright (c) 2012, Monty Program Ab +/* Copyright (c) 2002, 2013, Oracle and/or its affiliates. + Copyright (c) 2012, 2014, SkySQL Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1800,7 +1800,7 @@ static Sys_var_ulong Sys_net_retry_count( ON_UPDATE(fix_net_retry_count)); static Sys_var_mybool Sys_old_mode( - "old", "Use compatible behavior", + "old", "Use compatible behavior from previous MariaDB version. See also --old-mode", SESSION_VAR(old_mode), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); static Sys_var_mybool Sys_old_alter_table( @@ -2210,9 +2210,13 @@ static Sys_var_charptr Sys_socket( static Sys_var_ulong Sys_thread_concurrency( "thread_concurrency", "Permits the application to give the threads system a hint for " - "the desired number of threads that should be run at the same time", + "the desired number of threads that should be run at the same time." + "This variable has no effect, and is deprecated. " + "It will be removed in a future release.", READ_ONLY GLOBAL_VAR(concurrency), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(1, 512), DEFAULT(DEFAULT_CONCURRENCY), BLOCK_SIZE(1)); + VALID_RANGE(1, 512), DEFAULT(DEFAULT_CONCURRENCY), BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0), + DEPRECATED("")); static Sys_var_ulonglong Sys_thread_stack( "thread_stack", "The stack size for each thread", @@ -2629,6 +2633,30 @@ static Sys_var_set Sys_sql_mode( sql_mode_names, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_sql_mode), ON_UPDATE(fix_sql_mode)); +static const char *old_mode_names[]= +{ + "NO_DUP_KEY_WARNINGS_WITH_IGNORE", "NO_PROGRESS_INFO", + 0 +}; + +export bool old_mode_string_representation(THD *thd, ulonglong sql_mode, + LEX_STRING *ls) +{ + set_to_string(thd, ls, sql_mode, old_mode_names); + return ls->str == 0; +} +/* + sql_mode should *not* be IN_BINLOG as the slave can't remember this + anyway on restart. +*/ +static Sys_var_set Sys_old_behavior( + "old_mode", + "Used to emulate old behavior from earlier MariaDB or MySQL versions. " + "Syntax: old_mode=mode[,mode[,mode...]]. " + "See the manual for the complete list of valid old modes", + SESSION_VAR(old_behavior), CMD_LINE(REQUIRED_ARG), + old_mode_names, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG); + #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) #define SSL_OPT(X) CMD_LINE(REQUIRED_ARG,X) #else diff --git a/sql/table.cc b/sql/table.cc index f6bea7221ce..b9f2731e46e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -807,7 +807,6 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, keyinfo->ext_key_part_map= 0; if (share->use_ext_keys && i) { - keyinfo->ext_key_part_map= 0; for (j= 0; j < first_key_parts && keyinfo->ext_key_parts < MAX_REF_PARTS; j++) @@ -4084,8 +4083,9 @@ bool TABLE_LIST::create_field_translation(THD *thd) SELECT_LEX *select= get_single_select(); List_iterator_fast<Item> it(select->item_list); uint field_count= 0; - Query_arena *arena= thd->stmt_arena, backup; + Query_arena *arena, backup; bool res= FALSE; + DBUG_ENTER("TABLE_LIST::create_field_translation"); if (thd->stmt_arena->is_conventional() || thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) @@ -4106,7 +4106,7 @@ bool TABLE_LIST::create_field_translation(THD *thd) if (field_translation) { /* - Update items in the field translation aftet view have been prepared. + Update items in the field translation after view have been prepared. It's needed because some items in the select list, like IN subselects, might be substituted for optimized ones. */ @@ -4119,13 +4119,10 @@ bool TABLE_LIST::create_field_translation(THD *thd) field_translation_updated= TRUE; } - return FALSE; + DBUG_RETURN(FALSE); } - if (arena->is_conventional()) - arena= 0; // For easier test - else - thd->set_n_backup_active_arena(arena, &backup); + arena= thd->activate_stmt_arena_if_needed(&backup); /* Create view fields translation table */ @@ -4145,12 +4142,14 @@ bool TABLE_LIST::create_field_translation(THD *thd) } field_translation= transl; field_translation_end= transl + field_count; + /* It's safe to cache this table for prepared statements */ + cacheable_table= 1; exit: if (arena) thd->restore_active_arena(arena, &backup); - return res; + DBUG_RETURN(res); } diff --git a/sql/tztime.cc b/sql/tztime.cc index 0a574fb7688..3e79f1bc39e 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -41,6 +41,8 @@ #include <my_time.h> #include "tztime.h" #include <my_sys.h> +#include <mysql_version.h> +#include <my_getopt.h> #endif #include "tzfile.h" @@ -63,6 +65,8 @@ #endif /* !defined(DBUG_OFF) */ #endif /* defined(TZINFO2SQL) || defined(TESTTIME) */ +#define PROGRAM_VERSION "1.1" + /* Structure describing local time type (e.g. Moscow summer time (MSD)) */ typedef struct ttinfo { @@ -2386,7 +2390,6 @@ void Time_zone::adjust_leap_second(MYSQL_TIME *t) tables. */ - /* Print info about time zone described by TIME_ZONE_INFO struct as SQL statements populating mysql.time_zone* tables. @@ -2471,6 +2474,15 @@ MEM_ROOT tz_storage; char fullname[FN_REFLEN + 1]; char *root_name_end; +/* + known file types that exist in the zoneinfo directory that are safe to + silently skip +*/ +const char *known_extensions[]= { + ".tab", + NullS +}; + /* Recursively scan zoneinfo directory and print all found time zone @@ -2479,6 +2491,8 @@ char *root_name_end; SYNOPSIS scan_tz_dir() name_end - pointer to end of path to directory to be searched. + symlink_recursion_level How many symlink directory levels are used + verbose >0 if we should print warnings DESCRIPTION This auxiliary recursive function also uses several global @@ -2494,7 +2508,7 @@ char *root_name_end; */ my_bool -scan_tz_dir(char * name_end, uint symlink_recursion_level) +scan_tz_dir(char * name_end, uint symlink_recursion_level, uint verbose) { MY_DIR *cur_dir; char *name_end_tmp; @@ -2535,12 +2549,21 @@ scan_tz_dir(char * name_end, uint symlink_recursion_level) following such symlinks infinitely: /usr/share/zoneinfo/posix/posix/posix/.../posix/ */ - fflush(stdout); - fprintf(stderr, "Warning: Skipping directory '%s': " - "to avoid infinite symlink recursion.\n", fullname); + + /* + This is a normal case and not critical. only print warning if + verbose mode is choosen. + */ + if (verbose > 0) + { + fflush(stdout); + fprintf(stderr, "Warning: Skipping directory '%s': " + "to avoid infinite symlink recursion.\n", fullname); + } continue; } - if (scan_tz_dir(name_end_tmp, symlink_recursion_level + is_symlink)) + if (scan_tz_dir(name_end_tmp, symlink_recursion_level + is_symlink, + verbose)) { my_dirend(cur_dir); return 1; @@ -2553,10 +2576,28 @@ scan_tz_dir(char * name_end, uint symlink_recursion_level) print_tz_as_sql(root_name_end + 1, &tz_info); else { - fflush(stdout); - fprintf(stderr, - "Warning: Unable to load '%s' as time zone. Skipping it.\n", - fullname); + /* + Some systems (like debian, opensuse etc) have description + files (.tab). We skip these silently if verbose is > 0 + */ + const char *current_ext= fn_ext(fullname); + my_bool known_ext= 0; + + for (const char **ext= known_extensions ; *ext ; ext++) + { + if (!strcmp(*ext, current_ext)) + { + known_ext= 1; + break; + } + } + if (verbose > 0 || !known_ext) + { + fflush(stdout); + fprintf(stderr, + "Warning: Unable to load '%s' as time zone. Skipping it.\n", + fullname); + } } free_root(&tz_storage, MYF(0)); } @@ -2575,34 +2616,114 @@ scan_tz_dir(char * name_end, uint symlink_recursion_level) } +my_bool opt_leap, opt_verbose; + +static const char *load_default_groups[]= +{ "mysql_tzinfo_to_sql", 0}; + +static struct my_option my_long_options[] = +{ + {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, + 0, 0, 0, 0, 0, 0}, +#ifdef DBUG_OFF + {"debug", '#', "This is a non-debug version. Catch this and exit", + 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, +#else + {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", + 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, +#endif + {"leap", 'l', "Print the leap second information from the given time zone file. By convention, when --leap is used the next argument is the timezonefile", + &opt_leap, &opt_leap, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"verbose", 'v', "Write non critical warnings", + &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"version", 'V', "Output version information and exit.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; + + +C_MODE_START +static my_bool get_one_option(int optid, const struct my_option *, + char *argument); +C_MODE_END + +static void print_version(void) +{ + printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname, PROGRAM_VERSION, + MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} + +static void print_usage(void) +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s [options] timezonedir\n", my_progname); + fprintf(stderr, " %s [options] timezonefile timezonename\n", my_progname); + print_defaults("my",load_default_groups); + puts(""); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} + + +static my_bool +get_one_option(int optid, const struct my_option *opt, char *argument) +{ + switch(optid) { + case '#': +#ifndef DBUG_OFF + DBUG_PUSH(argument ? argument : "d:t:S:i:O,/tmp/mysq_tzinfo_to_sql.trace"); +#endif + break; + case '?': + print_version(); + puts(""); + print_usage(); + exit(0); + case 'V': + print_version(); + exit(0); + } + return 0; +} + + int main(int argc, char **argv) { + char **default_argv; MY_INIT(argv[0]); - if (argc != 2 && argc != 3) + if (load_defaults("my",load_default_groups,&argc,&argv)) + exit(1); + + default_argv= argv; + + if ((handle_options(&argc, &argv, my_long_options, get_one_option))) + exit(1); + + if ((argc != 1 && argc != 2) || (opt_leap && argc != 1)) { - fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s timezonedir\n", argv[0]); - fprintf(stderr, " %s timezonefile timezonename\n", argv[0]); - fprintf(stderr, " %s --leap timezonefile\n", argv[0]); + print_usage(); + free_defaults(default_argv); return 1; } - - if (argc == 2) + if (argc == 1 && !opt_leap) { - root_name_end= strmake_buf(fullname, argv[1]); + /* Argument is timezonedir */ + + root_name_end= strmake_buf(fullname, argv[0]); printf("TRUNCATE TABLE time_zone;\n"); printf("TRUNCATE TABLE time_zone_name;\n"); printf("TRUNCATE TABLE time_zone_transition;\n"); printf("TRUNCATE TABLE time_zone_transition_type;\n"); - if (scan_tz_dir(root_name_end, 0)) + if (scan_tz_dir(root_name_end, 0, opt_verbose)) { fflush(stdout); - fprintf(stderr, "There were fatal errors during processing " - "of zoneinfo directory\n"); + fprintf(stderr, + "There were fatal errors during processing " + "of zoneinfo directory '%s'\n", fullname); return 1; } @@ -2613,32 +2734,27 @@ main(int argc, char **argv) } else { + /* + First argument is timezonefile. + The second is timezonename if opt_leap is not given + */ init_alloc_root(&tz_storage, 32768, 0, MYF(0)); - if (strcmp(argv[1], "--leap") == 0) + if (tz_load(argv[0], &tz_info, &tz_storage)) { - if (tz_load(argv[2], &tz_info, &tz_storage)) - { - fflush(stdout); - fprintf(stderr, "Problems with zoneinfo file '%s'\n", argv[2]); - return 1; - } - print_tz_leaps_as_sql(&tz_info); + fflush(stdout); + fprintf(stderr, "Problems with zoneinfo file '%s'\n", argv[0]); + return 1; } + if (opt_leap) + print_tz_leaps_as_sql(&tz_info); else - { - if (tz_load(argv[1], &tz_info, &tz_storage)) - { - fflush(stdout); - fprintf(stderr, "Problems with zoneinfo file '%s'\n", argv[2]); - return 1; - } - print_tz_as_sql(argv[2], &tz_info); - } + print_tz_as_sql(argv[1], &tz_info); free_root(&tz_storage, MYF(0)); } + free_defaults(default_argv); my_end(0); return 0; } |