diff options
author | Sergei Golubchik <serg@mariadb.org> | 2016-05-04 15:23:26 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2016-05-04 15:23:26 +0200 |
commit | 87e3e67f434628768b5125fbab7e8862fa60da1a (patch) | |
tree | df19b8bcac9988d83270ed1da05f765bfc4e8624 /sql | |
parent | 80da57cc4f0c717ee3e01ac5abccc859b88a2fbf (diff) | |
parent | cee9ab9d85a8d75290b0d60bc7af26c8cf179a1d (diff) | |
download | mariadb-git-87e3e67f434628768b5125fbab7e8862fa60da1a.tar.gz |
Merge branch '10.0' into 10.1
Diffstat (limited to 'sql')
-rw-r--r-- | sql/debug_sync.h | 1 | ||||
-rw-r--r-- | sql/gen_lex_hash.cc | 2 | ||||
-rw-r--r-- | sql/handler.cc | 5 | ||||
-rw-r--r-- | sql/handler.h | 18 | ||||
-rw-r--r-- | sql/item.cc | 11 | ||||
-rw-r--r-- | sql/item.h | 2 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 26 | ||||
-rw-r--r-- | sql/item_func.cc | 2 | ||||
-rw-r--r-- | sql/item_func.h | 7 | ||||
-rw-r--r-- | sql/item_geofunc.h | 6 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 10 | ||||
-rw-r--r-- | sql/mysqld.cc | 5 | ||||
-rw-r--r-- | sql/mysqld.h | 11 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 9 | ||||
-rw-r--r-- | sql/sql_acl.cc | 76 | ||||
-rw-r--r-- | sql/sql_class.cc | 61 | ||||
-rw-r--r-- | sql/sql_class.h | 14 | ||||
-rw-r--r-- | sql/sql_connect.cc | 3 | ||||
-rw-r--r-- | sql/sql_insert.cc | 48 | ||||
-rw-r--r-- | sql/sql_load.cc | 5 | ||||
-rw-r--r-- | sql/sql_locale.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 43 | ||||
-rw-r--r-- | sql/sql_parse.h | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 71 | ||||
-rw-r--r-- | sql/sql_table.cc | 22 | ||||
-rw-r--r-- | sql/sql_update.cc | 14 | ||||
-rw-r--r-- | sql/sys_vars.ic | 2 |
27 files changed, 302 insertions, 177 deletions
diff --git a/sql/debug_sync.h b/sql/debug_sync.h index bf1b3167dbc..25b379e5892 100644 --- a/sql/debug_sync.h +++ b/sql/debug_sync.h @@ -44,6 +44,7 @@ extern void debug_sync_end(void); extern void debug_sync_init_thread(THD *thd); extern void debug_sync_end_thread(THD *thd); extern bool debug_sync_set_action(THD *thd, const char *action_str, size_t len); +extern bool debug_sync_update(THD *thd, char *val_str); #endif /* defined(ENABLED_DEBUG_SYNC) */ diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index c37f4f145cf..3a3273d279b 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -310,6 +310,7 @@ void print_find_structs() add_structs_to_map(root_by_len,max_len); set_links(root_by_len,max_len); print_hash_map("sql_functions_map"); + free(hash_map); hash_map= 0; size_hash_map= 0; @@ -319,6 +320,7 @@ void print_find_structs() add_structs_to_map(root_by_len2,max_len2); set_links(root_by_len2,max_len2); print_hash_map("symbols_map"); + free(hash_map); } diff --git a/sql/handler.cc b/sql/handler.cc index fb2921f9ba3..1e6e16171e3 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. + Copyright (c) 2009, 2016, MariaDB 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 @@ -4200,6 +4200,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_info::ALTER_COLUMN_DEFAULT | Alter_inplace_info::ALTER_COLUMN_OPTION | Alter_inplace_info::CHANGE_CREATE_OPTION | + Alter_inplace_info::ALTER_PARTITIONED | Alter_inplace_info::ALTER_RENAME; /* Is there at least one operation that requires copy algorithm? */ diff --git a/sql/handler.h b/sql/handler.h index 34b7b147d58..4f30ec6d7ec 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1,8 +1,8 @@ #ifndef HANDLER_INCLUDED #define HANDLER_INCLUDED /* - Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, Monty Program Ab. + Copyright (c) 2000, 2016, Oracle and/or its affiliates. + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -406,7 +406,9 @@ static const uint MYSQL_START_TRANS_OPT_READ_WRITE = 4; /* Flags for method is_fatal_error */ #define HA_CHECK_DUP_KEY 1 #define HA_CHECK_DUP_UNIQUE 2 +#define HA_CHECK_FK_ERROR 4 #define HA_CHECK_DUP (HA_CHECK_DUP_KEY + HA_CHECK_DUP_UNIQUE) +#define HA_CHECK_ALL (~0U) enum legacy_db_type { @@ -1929,7 +1931,10 @@ public: // Virtual columns changed static const HA_ALTER_FLAGS ALTER_COLUMN_VCOL = 1L << 30; - // ALTER TABLE for a partitioned table + /** + ALTER TABLE for a partitioned table. The engine needs to commit + online alter of all partitions atomically (using group_commit_ctx) + */ static const HA_ALTER_FLAGS ALTER_PARTITIONED = 1L << 31; /** @@ -2934,7 +2939,10 @@ public: ((flags & HA_CHECK_DUP_KEY) && (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE)) || - error == HA_ERR_AUTOINC_ERANGE) + error == HA_ERR_AUTOINC_ERANGE || + ((flags & HA_CHECK_FK_ERROR) && + (error == HA_ERR_ROW_IS_REFERENCED || + error == HA_ERR_NO_REFERENCED_ROW))) return FALSE; return TRUE; } @@ -4269,4 +4277,4 @@ inline const char *table_case_name(HA_CREATE_INFO *info, const char *name) void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag); void print_keydup_error(TABLE *table, KEY *key, myf errflag); -#endif +#endif /* HANDLER_INCLUDED */ diff --git a/sql/item.cc b/sql/item.cc index f1362e7e5da..adf70312b37 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2014, Oracle and/or its affiliates. + Copyright (c) 2000, 2016, Oracle and/or its affiliates. Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify @@ -1219,8 +1219,8 @@ Item *Item_param::safe_charset_converter(THD *thd, CHARSET_INFO *tocs) to it's possible that the converter will not be needed at all: PREPARE stmt FROM 'SELECT * FROM t1 WHERE field = ?'; - SET @@arg= 1; - EXECUTE stms USING @arg; + SET @arg= 1; + EXECUTE stmt USING @arg; In the above example result_type is STRING_RESULT at prepare time, and INT_RESULT at execution time. @@ -3701,7 +3701,7 @@ Item_param::eq(const Item *item, bool binary_cmp) const void Item_param::print(String *str, enum_query_type query_type) { - if (state == NO_VALUE) + if (state == NO_VALUE || query_type & QT_NO_DATA_EXPANSION) { str->append('?'); } @@ -6649,7 +6649,8 @@ Item *Item_field::update_value_transformer(THD *thd, uchar *select_arg) void Item_field::print(String *str, enum_query_type query_type) { - if (field && field->table->const_table) + if (field && field->table->const_table && + !(query_type & QT_NO_DATA_EXPANSION)) { print_value(str); return; diff --git a/sql/item.h b/sql/item.h index 6e0a4aa82ce..bef57c4a967 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2546,7 +2546,7 @@ public: max_length= 0; name= name_par ? name_par : (char*) "NULL"; fixed= 1; - collation.set(cs, DERIVATION_IGNORABLE); + collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII); } enum Type type() const { return NULL_ITEM; } bool eq(const Item *item, bool binary_cmp) const { return null_eq(item); } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1ce8bad933b..d745dd8ff73 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -120,10 +120,11 @@ static int cmp_row_type(Item* item1, Item* item2) static int agg_cmp_type(Item_result *type, Item **items, uint nitems) { - uint i; + uint unsigned_count= items[0]->unsigned_flag; type[0]= items[0]->cmp_type(); - for (i= 1 ; i < nitems ; i++) + for (uint i= 1 ; i < nitems ; i++) { + unsigned_count+= items[i]->unsigned_flag; type[0]= item_cmp_type(type[0], items[i]); /* When aggregating types of two row expressions we have to check @@ -135,6 +136,12 @@ static int agg_cmp_type(Item_result *type, Item **items, uint nitems) if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i])) return 1; // error found: invalid usage of rows } + /** + If all arguments are of INT type but have different unsigned_flag values, + switch to DECIMAL_RESULT. + */ + if (type[0] == INT_RESULT && unsigned_count != nitems && unsigned_count != 0) + type[0]= DECIMAL_RESULT; return 0; } @@ -2334,10 +2341,7 @@ bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, uint fuzzydate) DBUG_ASSERT(fixed == 1); if (!args[0]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES)) return (null_value= false); - if (!args[1]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES)) - return (null_value= false); - bzero((char*) ltime,sizeof(*ltime)); - return null_value= !(fuzzydate & TIME_FUZZY_DATES); + return (null_value= args[1]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES)); } @@ -3367,16 +3371,12 @@ double Item_func_coalesce::real_op() bool Item_func_coalesce::date_op(MYSQL_TIME *ltime,uint fuzzydate) { DBUG_ASSERT(fixed == 1); - null_value= 0; for (uint i= 0; i < arg_count; i++) { - bool res= args[i]->get_date_with_conversion(ltime, - fuzzydate & ~TIME_FUZZY_DATES); - if (!args[i]->null_value) - return res; + if (!args[i]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES)) + return (null_value= false); } - bzero((char*) ltime,sizeof(*ltime)); - return null_value|= !(fuzzydate & TIME_FUZZY_DATES); + return (null_value= true); } diff --git a/sql/item_func.cc b/sql/item_func.cc index e5c1f4c75f6..6edb276ca20 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -6307,6 +6307,8 @@ bool Item_func_match::fix_index() for (i=1; i < arg_count; i++) { + if (args[i]->type() != FIELD_ITEM) + goto err; item=(Item_field*)args[i]; for (keynr=0 ; keynr < fts ; keynr++) { diff --git a/sql/item_func.h b/sql/item_func.h index a5f6bf26134..6a1494040c9 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1,7 +1,7 @@ #ifndef ITEM_FUNC_INCLUDED #define ITEM_FUNC_INCLUDED -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, MariaDB +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. + Copyright (c) 2009, 2016, MariaDB 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 @@ -210,7 +210,7 @@ public: char buf[256]; String str(buf, sizeof(buf), system_charset_info); str.length(0); - print(&str, QT_ORDINARY); + print(&str, QT_NO_DATA_EXPANSION); my_error(ER_DATA_OUT_OF_RANGE, MYF(0), type_name, str.c_ptr_safe()); } inline double raise_float_overflow() @@ -452,7 +452,6 @@ class Item_func_hybrid_field_type: public Item_hybrid_func } protected: Item_result cached_result_type; - public: Item_func_hybrid_field_type(THD *thd): Item_hybrid_func(thd) diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index b72661fe054..6b991a1b643 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -1,8 +1,8 @@ #ifndef ITEM_GEOFUNC_INCLUDED #define ITEM_GEOFUNC_INCLUDED -/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. - Copyright (C) 2011, 2015 MariaDB +/* Copyright (c) 2000, 2016 Oracle and/or its affiliates. + Copyright (C) 2011, 2016, MariaDB 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 @@ -259,7 +259,7 @@ public: if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY) { String str; - args[i]->print(&str, QT_ORDINARY); + args[i]->print(&str, QT_NO_DATA_EXPANSION); str.append('\0'); my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric", str.ptr()); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 8bf1521e971..38fc58d00d5 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -814,9 +814,10 @@ String *Item_func_des_encrypt::val_str(String *str) /* We make good 24-byte (168 bit) key from given plaintext key with MD5 */ bzero((char*) &ivec,sizeof(ivec)); - EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, + if (!EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, (uchar*) keystr->ptr(), (int) keystr->length(), - 1, (uchar*) &keyblock,ivec); + 1, (uchar*) &keyblock,ivec)) + goto error; DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1); DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2); DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3); @@ -909,9 +910,10 @@ String *Item_func_des_decrypt::val_str(String *str) goto error; bzero((char*) &ivec,sizeof(ivec)); - EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, + if (!EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, (uchar*) keystr->ptr(),(int) keystr->length(), - 1,(uchar*) &keyblock,ivec); + 1,(uchar*) &keyblock,ivec)) + goto error; // Here we set all 64-bit keys (56 effective) one by one DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1); DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a4c6184f313..ee40df945ed 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -290,7 +290,7 @@ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"}; static const char *tc_heuristic_recover_names[]= { - "COMMIT", "ROLLBACK", NullS + "OFF", "COMMIT", "ROLLBACK", NullS }; static TYPELIB tc_heuristic_recover_typelib= { @@ -7039,7 +7039,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */ create_new_thread(thd); connect_number++; - set_current_thd(thd); + set_current_thd(0); continue; errorconn: @@ -9180,6 +9180,7 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument) log_error_file_ptr= const_cast<char*>(""); break; case OPT_IGNORE_DB_DIRECTORY: + opt_ignore_db_dirs= NULL; // will be set in ignore_db_dirs_process_additions if (*argument == 0) ignore_db_dirs_reset(); else diff --git a/sql/mysqld.h b/sql/mysqld.h index 30120d66113..594afac521d 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -1,5 +1,5 @@ -/* Copyright (c) 2006, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB +/* Copyright (c) 2006, 2016, Oracle and/or its affiliates. + Copyright (c) 2010, 2016, MariaDB 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 @@ -683,7 +683,12 @@ enum enum_query_type /// Be more detailed than QT_EXPLAIN. /// Perhaps we should eventually include QT_ITEM_IDENT_SKIP_CURRENT_DATABASE /// here, as it would give better readable results - QT_EXPLAIN_EXTENDED= QT_TO_SYSTEM_CHARSET + QT_EXPLAIN_EXTENDED= QT_TO_SYSTEM_CHARSET, + + // If an expression is constant, print the expression, not the value + // it evaluates to. Should be used for error messages, so that they + // don't reveal values. + QT_NO_DATA_EXPANSION= (1 << 9), }; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index cb356fbdf41..537774aea2a 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -2251,7 +2251,8 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map) rows *= join->map2table[tableno]->table->quick_condition_rows; sjm->rows= MY_MIN(sjm->rows, rows); } - memcpy(sjm->positions, join->best_positions + join->const_tables, + memcpy((uchar*) sjm->positions, + (uchar*) (join->best_positions + join->const_tables), sizeof(POSITION) * n_tables); /* @@ -3354,7 +3355,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) SJ_MATERIALIZATION_INFO *sjm= s->emb_sj_nest->sj_mat_info; sjm->is_used= TRUE; sjm->is_sj_scan= FALSE; - memcpy(pos - sjm->tables + 1, sjm->positions, + memcpy((uchar*) (pos - sjm->tables + 1), (uchar*) sjm->positions, sizeof(POSITION) * sjm->tables); recalculate_prefix_record_count(join, tablenr - sjm->tables + 1, tablenr); @@ -3370,8 +3371,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) sjm->is_used= TRUE; sjm->is_sj_scan= TRUE; first= pos->sjmat_picker.sjm_scan_last_inner - sjm->tables + 1; - memcpy(join->best_positions + first, - sjm->positions, sizeof(POSITION) * sjm->tables); + memcpy((uchar*) (join->best_positions + first), + (uchar*) sjm->positions, sizeof(POSITION) * sjm->tables); recalculate_prefix_record_count(join, first, first + sjm->tables); join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE_SCAN; join->best_positions[first].n_sj_tables= sjm->tables; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f323c7871c9..d168529df37 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, SkySQL Ab. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. + Copyright (c) 2009, 2016, MariaDB 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 @@ -745,9 +745,8 @@ static ACL_USER *find_user_wild(const char *host, const char *user, const char * static ACL_ROLE *find_acl_role(const char *user); static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_STRING *u, const LEX_STRING *h, const LEX_STRING *r); static ACL_USER_BASE *find_acl_user_base(const char *user, const char *host); -static bool update_user_table(THD *thd, TABLE *table, const char *host, - const char *user, const char *new_password, - uint new_password_len); +static bool update_user_table(THD *, TABLE *, const char *, const char *, const + char *, uint); static bool acl_load(THD *thd, TABLE_LIST *tables); static bool grant_load(THD *thd, TABLE_LIST *tables); static inline void get_grantor(THD *thd, char* grantor); @@ -1206,7 +1205,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) grant_version++; /* Privileges updated */ init_sql_alloc(&acl_memroot, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); - (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST), 20, 50, MYF(0)); if ((table= tables[HOST_TABLE].table)) // "host" table may not exist (e.g. in MySQL 5.6.7+) { if (init_read_record(&read_record_info, thd, table, NULL, 1, 1, FALSE)) @@ -1263,12 +1261,11 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) } freeze_size(&acl_hosts); - (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER), 50, 100, MYF(0)); - (void) my_hash_init2(&acl_roles,50, &my_charset_utf8_bin, - 0, 0, 0, (my_hash_get_key) acl_role_get_key, 0, - (void (*)(void *))free_acl_role, 0); + if (init_read_record(&read_record_info, thd, table=tables[USER_TABLE].table, + NULL, 1, 1, FALSE)) + goto end; + table->use_all_columns(); - table= tables[USER_TABLE].table, username_char_length= MY_MIN(table->field[1]->char_length(), USERNAME_CHAR_LENGTH); password_length= table->field[2]->field_length / @@ -1280,10 +1277,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) goto end; } - if (init_read_record(&read_record_info, thd, table, NULL, 1, 1, FALSE)) - goto end; - table->use_all_columns(); - DBUG_PRINT("info",("user table fields: %d, password length: %d", table->s->fields, password_length)); @@ -1295,7 +1288,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) mysql_mutex_unlock(&LOCK_global_system_variables); sql_print_error("Fatal error: mysql.user table is in old format, " "but server started with --secure-auth option."); - end_read_record(&read_record_info); goto end; } mysql_user_table_is_in_short_password_format= true; @@ -1531,7 +1523,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) NULL, 1, 1, FALSE)) goto end; table->use_all_columns(); - (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB), 50, 100, MYF(0)); while (!(read_record_info.read_record(&read_record_info))) { ACL_DB db; @@ -1593,8 +1584,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) end_read_record(&read_record_info); freeze_size(&acl_dbs); - (void) my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER), - 50, 100, MYF(0)); if ((table= tables[PROXIES_PRIV_TABLE].table)) { if (init_read_record(&read_record_info, thd, table, @@ -1630,10 +1619,7 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) if (init_read_record(&read_record_info, thd, table, NULL, 1, 1, FALSE)) goto end; table->use_all_columns(); - /* account for every role mapping */ - (void) my_hash_init2(&acl_roles_mappings, 50, system_charset_info, 0, 0, 0, - (my_hash_get_key) acl_role_map_get_key, 0, 0, 0); MEM_ROOT temp_root; init_alloc_root(&temp_root, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); while (!(read_record_info.read_record(&read_record_info))) @@ -1672,6 +1658,7 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) return_val= FALSE; end: + end_read_record(&read_record_info); thd->variables.sql_mode= old_sql_mode; DBUG_RETURN(return_val); } @@ -1688,12 +1675,12 @@ void acl_free(bool end) delete_dynamic(&acl_proxy_users); my_hash_free(&acl_check_hosts); my_hash_free(&acl_roles_mappings); - plugin_unlock(0, native_password_plugin); - plugin_unlock(0, old_password_plugin); if (!end) acl_cache->clear(1); /* purecov: inspected */ else { + plugin_unlock(0, native_password_plugin); + plugin_unlock(0, old_password_plugin); delete acl_cache; acl_cache=0; } @@ -1755,6 +1742,15 @@ bool acl_reload(THD *thd) old_acl_roles_mappings= acl_roles_mappings; old_acl_proxy_users= acl_proxy_users; old_acl_dbs= acl_dbs; + my_init_dynamic_array(&acl_hosts, sizeof(ACL_HOST), 20, 50, MYF(0)); + my_init_dynamic_array(&acl_users, sizeof(ACL_USER), 50, 100, MYF(0)); + my_init_dynamic_array(&acl_dbs, sizeof(ACL_DB), 50, 100, MYF(0)); + my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER), 50, 100, MYF(0)); + my_hash_init2(&acl_roles,50, &my_charset_utf8_bin, + 0, 0, 0, (my_hash_get_key) acl_role_get_key, 0, + (void (*)(void *))free_acl_role, 0); + my_hash_init2(&acl_roles_mappings, 50, system_charset_info, 0, 0, 0, + (my_hash_get_key) acl_role_map_get_key, 0, 0, 0); old_mem= acl_memroot; delete_dynamic(&acl_wild_hosts); my_hash_free(&acl_check_hosts); @@ -7647,7 +7643,8 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant, if (!grant_column) priv|= (grant->privilege | grant_table_role->privs); else - priv|= (grant->privilege | grant_table->privs | grant_column->rights); + priv|= (grant->privilege | grant_table_role->privs | + grant_column->rights); } } mysql_rwlock_unlock(&LOCK_grant); @@ -7777,9 +7774,6 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user) DBUG_RETURN(TRUE); } - mysql_rwlock_rdlock(&LOCK_grant); - mysql_mutex_lock(&acl_cache->lock); - if (lex_user->user.str == current_user.str) { username= thd->security_ctx->priv_user; @@ -7797,23 +7791,28 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user) } else { - lex_user= get_current_user(thd, lex_user, false); + Security_context *sctx= thd->security_ctx; + bool do_check_access; + + lex_user= get_current_user(thd, lex_user); if (!lex_user) - { - mysql_mutex_unlock(&acl_cache->lock); - mysql_rwlock_unlock(&LOCK_grant); DBUG_RETURN(TRUE); - } if (lex_user->is_role()) { rolename= lex_user->user.str; + do_check_access= strcmp(rolename, sctx->priv_role); } else { username= lex_user->user.str; hostname= lex_user->host.str; + do_check_access= strcmp(username, sctx->priv_user) || + strcmp(hostname, sctx->priv_host); } + + if (do_check_access && check_access(thd, SELECT_ACL, "mysql", 0, 0, 1, 0)) + DBUG_RETURN(TRUE); } DBUG_ASSERT(rolename || username); @@ -7826,14 +7825,11 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user) mysql_show_grants_get_fields(thd, &field_list, buff); if (protocol->send_result_set_metadata(&field_list, - Protocol::SEND_NUM_ROWS | - Protocol::SEND_EOF)) - { - mysql_mutex_unlock(&acl_cache->lock); - mysql_rwlock_unlock(&LOCK_grant); - + Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - } + + mysql_rwlock_rdlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); if (username) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 236b68586d5..16773ab3018 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1973,46 +1973,63 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use, { THD *in_use= ctx_in_use->get_thd(); bool signalled= FALSE; + DBUG_ENTER("THD::notify_shared_lock"); + DBUG_PRINT("enter",("needs_thr_lock_abort: %d", needs_thr_lock_abort)); if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) && !in_use->killed) { - in_use->killed= KILL_CONNECTION; - mysql_mutex_lock(&in_use->mysys_var->mutex); - if (in_use->mysys_var->current_cond) - mysql_cond_broadcast(in_use->mysys_var->current_cond); - mysql_mutex_unlock(&in_use->mysys_var->mutex); + /* This code is similar to kill_delayed_threads() */ + DBUG_PRINT("info", ("kill delayed thread")); + mysql_mutex_lock(&in_use->LOCK_thd_data); + if (in_use->killed < KILL_CONNECTION) + in_use->killed= KILL_CONNECTION; + if (in_use->mysys_var) + { + mysql_mutex_lock(&in_use->mysys_var->mutex); + if (in_use->mysys_var->current_cond) + mysql_cond_broadcast(in_use->mysys_var->current_cond); + + /* Abort if about to wait in thr_upgrade_write_delay_lock */ + in_use->mysys_var->abort= 1; + mysql_mutex_unlock(&in_use->mysys_var->mutex); + } + mysql_mutex_unlock(&in_use->LOCK_thd_data); signalled= TRUE; } if (needs_thr_lock_abort) { mysql_mutex_lock(&in_use->LOCK_thd_data); - for (TABLE *thd_table= in_use->open_tables; - thd_table ; - thd_table= thd_table->next) + /* If not already dying */ + if (in_use->killed != KILL_CONNECTION_HARD) { - /* - Check for TABLE::needs_reopen() is needed since in some places we call - handler::close() for table instance (and set TABLE::db_stat to 0) - and do not remove such instances from the THD::open_tables - for some time, during which other thread can see those instances - (e.g. see partitioning code). - */ - if (!thd_table->needs_reopen()) + for (TABLE *thd_table= in_use->open_tables; + thd_table ; + thd_table= thd_table->next) { - signalled|= mysql_lock_abort_for_thread(this, thd_table); - if (this && WSREP(this) && wsrep_thd_is_BF(this, FALSE)) + /* + Check for TABLE::needs_reopen() is needed since in some + places we call handler::close() for table instance (and set + TABLE::db_stat to 0) and do not remove such instances from + the THD::open_tables for some time, during which other + thread can see those instances (e.g. see partitioning code). + */ + if (!thd_table->needs_reopen()) { - WSREP_DEBUG("remove_table_from_cache: %llu", - (unsigned long long) this->real_id); - wsrep_abort_thd((void *)this, (void *)in_use, FALSE); + signalled|= mysql_lock_abort_for_thread(this, thd_table); + if (this && WSREP(this) && wsrep_thd_is_BF(this, FALSE)) + { + WSREP_DEBUG("remove_table_from_cache: %llu", + (unsigned long long) this->real_id); + wsrep_abort_thd((void *)this, (void *)in_use, FALSE); + } } } } mysql_mutex_unlock(&in_use->LOCK_thd_data); } - return signalled; + DBUG_RETURN(signalled); } diff --git a/sql/sql_class.h b/sql/sql_class.h index e1127f77c09..8bfc243977f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2000, 2016, Oracle and/or its affiliates. Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify @@ -2193,6 +2193,18 @@ public: current_stmt_binlog_format == BINLOG_FORMAT_ROW); return current_stmt_binlog_format == BINLOG_FORMAT_ROW; } + /** + Determine if binlogging is disabled for this session + @retval 0 if the current statement binlogging is disabled + (could be because of binlog closed/binlog option + is set to false). + @retval 1 if the current statement will be binlogged + */ + inline bool is_current_stmt_binlog_disabled() const + { + return (!(variables.option_bits & OPTION_BIN_LOG) || + !mysql_bin_log.is_open()); + } enum binlog_filter_state { diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 7821b96b9bb..80ac420937a 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1165,7 +1165,8 @@ void end_connection(THD *thd) } if (!thd->killed && (net->error && net->vio != 0)) - thd->print_aborted_warning(1, ER_THD(thd, ER_UNKNOWN_ERROR)); + thd->print_aborted_warning(1, thd->get_stmt_da()->is_error() + ? thd->get_stmt_da()->message() : ER_THD(thd, ER_UNKNOWN_ERROR)); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 9b4238b513d..fcf8c143ec4 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2000, 2016, Oracle and/or its affiliates. + Copyright (c) 2010, 2016, MariaDB 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 @@ -1623,9 +1623,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) else table->file->insert_id_for_cur_row= insert_id_for_cur_row; bool is_duplicate_key_error; - if (table->file->is_fatal_error(error, HA_CHECK_DUP)) + if (table->file->is_fatal_error(error, HA_CHECK_ALL)) goto err; - is_duplicate_key_error= table->file->is_fatal_error(error, 0); + is_duplicate_key_error= + table->file->is_fatal_error(error, HA_CHECK_ALL & ~HA_CHECK_DUP); if (!is_duplicate_key_error) { /* @@ -1752,7 +1753,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) error != HA_ERR_RECORD_IS_THE_SAME) { if (info->ignore && - !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + !table->file->is_fatal_error(error, HA_CHECK_ALL)) { if (!(thd->variables.old_behavior & OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) @@ -1882,7 +1883,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) { DEBUG_SYNC(thd, "write_row_noreplace"); if (!info->ignore || - table->file->is_fatal_error(error, HA_CHECK_DUP)) + table->file->is_fatal_error(error, HA_CHECK_ALL)) goto err; if (!(thd->variables.old_behavior & OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) @@ -2012,7 +2013,7 @@ public: TABLE *table; mysql_mutex_t mutex; mysql_cond_t cond, cond_client; - volatile uint tables_in_use,stacked_inserts; + uint tables_in_use, stacked_inserts; volatile bool status; bool retry; /** @@ -2663,14 +2664,16 @@ static void end_delayed_insert(THD *thd) void kill_delayed_threads(void) { + DBUG_ENTER("kill_delayed_threads"); mysql_mutex_lock(&LOCK_delayed_insert); // For unlink from list I_List_iterator<Delayed_insert> it(delayed_threads); Delayed_insert *di; while ((di= it++)) { - di->thd.killed= KILL_CONNECTION; mysql_mutex_lock(&di->thd.LOCK_thd_data); + if (di->thd.killed < KILL_CONNECTION) + di->thd.killed= KILL_CONNECTION; if (di->thd.mysys_var) { mysql_mutex_lock(&di->thd.mysys_var->mutex); @@ -2691,6 +2694,7 @@ void kill_delayed_threads(void) mysql_mutex_unlock(&di->thd.LOCK_thd_data); } mysql_mutex_unlock(&LOCK_delayed_insert); // For unlink from list + DBUG_VOID_RETURN; } @@ -2895,6 +2899,12 @@ pthread_handler_t handle_delayed_insert(void *arg) /* Tell client that the thread is initialized */ mysql_cond_signal(&di->cond_client); + /* + Inform mdl that it needs to call mysql_lock_abort to abort locks + for delayed insert. + */ + thd->mdl_context.set_needs_thr_lock_abort(TRUE); + di->table->mark_columns_needed_for_insert(); /* Now wait until we get an insert or lock to handle */ @@ -2905,6 +2915,7 @@ pthread_handler_t handle_delayed_insert(void *arg) if (thd->killed) { uint lock_count; + DBUG_PRINT("delayed", ("Insert delayed killed")); /* Remove this from delay insert list so that no one can request a table from this @@ -2915,11 +2926,15 @@ pthread_handler_t handle_delayed_insert(void *arg) lock_count=di->lock_count(); mysql_mutex_unlock(&LOCK_delayed_insert); mysql_mutex_lock(&di->mutex); - if (!lock_count && !di->tables_in_use && !di->stacked_inserts) + if (!lock_count && !di->tables_in_use && !di->stacked_inserts && + !thd->lock) break; // Time to die } /* Shouldn't wait if killed or an insert is waiting. */ + DBUG_PRINT("delayed", + ("thd->killed: %d di->status: %d di->stacked_inserts: %d", + thd->killed, di->status, di->stacked_inserts)); if (!thd->killed && !di->status && !di->stacked_inserts) { struct timespec abstime; @@ -2959,6 +2974,9 @@ pthread_handler_t handle_delayed_insert(void *arg) mysql_mutex_unlock(&di->thd.mysys_var->mutex); mysql_mutex_lock(&di->mutex); } + DBUG_PRINT("delayed", + ("thd->killed: %d di->tables_in_use: %d thd->lock: %d", + thd->killed, di->tables_in_use, thd->lock != 0)); if (di->tables_in_use && ! thd->lock && !thd->killed) { @@ -3019,9 +3037,19 @@ pthread_handler_t handle_delayed_insert(void *arg) { DBUG_ENTER("handle_delayed_insert-cleanup"); di->table=0; - thd->killed= KILL_CONNECTION; // If error mysql_mutex_unlock(&di->mutex); + /* + Protect against mdl_locks trying to access open tables + We use KILL_CONNECTION_HARD here to ensure that + THD::notify_shared_lock() dosn't try to access open tables after + this. + */ + mysql_mutex_lock(&thd->LOCK_thd_data); + thd->killed= KILL_CONNECTION_HARD; // If error + thd->mdl_context.set_needs_thr_lock_abort(0); + mysql_mutex_unlock(&thd->LOCK_thd_data); + close_thread_tables(thd); // Free the table thd->mdl_context.release_transactional_locks(); mysql_cond_broadcast(&di->cond_client); // Safety diff --git a/sql/sql_load.cc b/sql/sql_load.cc index e102066c0bc..4e6d91b9c1f 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2000, 2016, Oracle and/or its affiliates. + Copyright (c) 2010, 2016, MariaDB 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 @@ -240,6 +240,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { DBUG_RETURN(TRUE); } + thd_proc_info(thd, "executing"); /* Let us emit an error if we are loading data to table which is used in subselect in SET clause like we do it for INSERT. diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc index 5ac069de98b..58443a9a977 100644 --- a/sql/sql_locale.cc +++ b/sql/sql_locale.cc @@ -427,7 +427,7 @@ MY_LOCALE my_locale_da_DK /***** LOCALE BEGIN de_AT: German - Austria *****/ static const char *my_locale_month_names_de_AT[13] = - {"Jänner","Feber","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS }; + {"Jänner","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS }; static const char *my_locale_ab_month_names_de_AT[13] = {"Jän","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez", NullS }; static const char *my_locale_day_names_de_AT[8] = diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4c8bb05cc39..3c0bf523c2c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4939,21 +4939,10 @@ end_with_restore_list: case SQLCOM_SHOW_GRANTS: { LEX_USER *grant_user= lex->grant_user; - Security_context *sctx= thd->security_ctx; if (!grant_user) goto error; - if (grant_user->user.str && !strcmp(sctx->priv_user, grant_user->user.str) && - grant_user->host.str && !strcmp(sctx->priv_host, grant_user->host.str)) - grant_user->user= current_user; - - if (grant_user->user.str == current_user.str || - grant_user->user.str == current_role.str || - grant_user->user.str == current_user_and_current_role.str || - !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0)) - { - res = mysql_show_grants(thd, grant_user); - } + res = mysql_show_grants(thd, grant_user); break; } #endif @@ -6653,6 +6642,7 @@ bool check_global_access(THD *thd, ulong want_access, bool no_errors) temporary table flag) @param alter_info [in] Initial list of columns and indexes for the table to be created + @param create_db [in] Database of the created table @retval false ok. @@ -6661,7 +6651,8 @@ bool check_global_access(THD *thd, ulong want_access, bool no_errors) */ bool check_fk_parent_table_access(THD *thd, HA_CREATE_INFO *create_info, - Alter_info *alter_info) + Alter_info *alter_info, + const char* create_db) { Key *key; List_iterator<Key> key_iterator(alter_info->key_list); @@ -6701,10 +6692,28 @@ bool check_fk_parent_table_access(THD *thd, return true; } } - else if (thd->lex->copy_db_to(&db_name.str, &db_name.length)) - return true; else - is_qualified_table_name= false; + { + if (!thd->db) + { + db_name.str= (char *) thd->memdup(create_db, strlen(create_db)+1); + db_name.length= strlen(create_db); + is_qualified_table_name= true; + + if(create_db && check_db_name(&db_name)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str); + return true; + } + } + else + { + if (thd->lex->copy_db_to(&db_name.str, &db_name.length)) + return true; + else + is_qualified_table_name= false; + } + } // if lower_case_table_names is set then convert tablename to lower case. if (lower_case_table_names) @@ -8855,7 +8864,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, goto err; } - if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info)) + if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info, create_table->db)) goto err; /* diff --git a/sql/sql_parse.h b/sql/sql_parse.h index c3c47567cf5..7a67df55ac3 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -48,7 +48,8 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *create_table); bool check_fk_parent_table_access(THD *thd, HA_CREATE_INFO *create_info, - Alter_info *alter_info); + Alter_info *alter_info, + const char* create_db); bool parse_sql(THD *thd, Parser_state *parser_state, Object_creation_ctx *creation_ctx, bool do_pfs_digest=false); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e83f63d1070..9de597eb0e3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2015 Oracle and/or its affiliates. +/* Copyright (c) 2000, 2016 Oracle and/or its affiliates. Copyright (c) 2009, 2016 MariaDB This program is free software; you can redistribute it and/or modify @@ -15821,6 +15821,14 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, Field *UNINIT_VAR(new_field); MEM_ROOT *mem_root= thd->mem_root; + /* + To preserve type or DATE/TIME and GEOMETRY fields, + they need to be handled separately. + */ + if (item->cmp_type() == TIME_RESULT || + item->field_type() == MYSQL_TYPE_GEOMETRY) + new_field= item->tmp_table_field_from_field_type(table, true, false); + else switch (item->result_type()) { case REAL_RESULT: new_field= new (mem_root) @@ -15845,16 +15853,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, break; case STRING_RESULT: DBUG_ASSERT(item->collation.collation); - - /* - DATE/TIME and GEOMETRY fields have STRING_RESULT result type. - To preserve type they needed to be handled separately. - */ - if (item->cmp_type() == TIME_RESULT || - item->field_type() == MYSQL_TYPE_GEOMETRY) - new_field= item->tmp_table_field_from_field_type(table, true, false); - else - new_field= item->make_string_field(table); + new_field= item->make_string_field(table); new_field->set_derivation(item->collation.derivation); break; case DECIMAL_RESULT: @@ -24658,33 +24657,53 @@ static void print_join(THD *thd, /* List is reversed => we should reverse it before using */ List_iterator_fast<TABLE_LIST> ti(*tables); TABLE_LIST **table; - uint non_const_tables= 0; DBUG_ENTER("print_join"); + /* + If the QT_NO_DATA_EXPANSION flag is specified, we print the + original table list, including constant tables that have been + optimized away, as the constant tables may be referenced in the + expression printed by Item_field::print() when this flag is given. + Otherwise, only non-const tables are printed. + + Example: + + Original SQL: + select * from (select 1) t + + Printed without QT_NO_DATA_EXPANSION: + select '1' AS `1` from dual + + Printed with QT_NO_DATA_EXPANSION: + select `t`.`1` from (select 1 AS `1`) `t` + */ + const bool print_const_tables= (query_type & QT_NO_DATA_EXPANSION); + size_t tables_to_print= 0; + for (TABLE_LIST *t= ti++; t ; t= ti++) { - /* - See comment in print_table_array() about the second part of the - condition - */ - if (!t->optimized_away && !is_eliminated_table(eliminated_tables, t)) - non_const_tables++; + /* See comment in print_table_array() about the second condition */ + if (print_const_tables || !t->optimized_away) + if (!is_eliminated_table(eliminated_tables, t)) + tables_to_print++; } - if (!non_const_tables) + if (tables_to_print == 0) { str->append(STRING_WITH_LEN("dual")); DBUG_VOID_RETURN; // all tables were optimized away } ti.rewind(); - if (!(table= (TABLE_LIST **)thd->alloc(sizeof(TABLE_LIST*) * - non_const_tables))) + if (!(table= static_cast<TABLE_LIST **>(thd->alloc(sizeof(TABLE_LIST*) * + tables_to_print)))) DBUG_VOID_RETURN; // out of memory - TABLE_LIST *tmp, **t= table + (non_const_tables - 1); + TABLE_LIST *tmp, **t= table + (tables_to_print - 1); while ((tmp= ti++)) { - if (tmp->optimized_away || is_eliminated_table(eliminated_tables, tmp)) + if (tmp->optimized_away && !print_const_tables) + continue; + if (is_eliminated_table(eliminated_tables, tmp)) continue; *t--= tmp; } @@ -24704,7 +24723,7 @@ static void print_join(THD *thd, */ if ((*table)->sj_inner_tables) { - TABLE_LIST **end= table + non_const_tables; + TABLE_LIST **end= table + tables_to_print; for (TABLE_LIST **t2= table; t2!=end; t2++) { if (!(*t2)->sj_inner_tables) @@ -24717,7 +24736,7 @@ static void print_join(THD *thd, } } print_table_array(thd, eliminated_tables, str, table, - table + non_const_tables, query_type); + table + tables_to_print, query_type); DBUG_VOID_RETURN; } @@ -25132,7 +25151,7 @@ void JOIN::save_query_plan(Join_plan_state *save_to) } memcpy((uchar*) save_to->best_positions, (uchar*) best_positions, sizeof(POSITION) * (table_count + 1)); - memset(best_positions, 0, sizeof(POSITION) * (table_count + 1)); + memset((uchar*) best_positions, 0, sizeof(POSITION) * (table_count + 1)); /* Save SJM nests */ List_iterator<TABLE_LIST> it(select_lex->sj_nests); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index dfce503e314..337fb06d4e4 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2000, 2016, Oracle and/or its affiliates. Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify @@ -5422,6 +5422,9 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, /* We have to write the query before we unlock the tables. */ + if (thd->is_current_stmt_binlog_disabled()) + goto err; + if (thd->is_current_stmt_binlog_format_row()) { /* @@ -5492,6 +5495,21 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, */ if (!table->view) { + /* + After opening a MERGE table add the children to the query list of + tables, so that children tables info can be used on "CREATE TABLE" + statement generation by the binary log. + Note that placeholders don't have the handler open. + */ + if (table->table->file->extra(HA_EXTRA_ADD_CHILDREN_LIST)) + goto err; + + /* + As the reference table is temporary and may not exist on slave, we must + force the ENGINE to be present into CREATE TABLE. + */ + create_info->used_fields|= HA_CREATE_USED_ENGINE; + int result __attribute__((unused))= show_create_table(thd, table, &query, create_info, WITH_DB_NAME); @@ -8479,7 +8497,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, till this point for the alter operation. */ if ((alter_info->flags & Alter_info::ADD_FOREIGN_KEY) && - check_fk_parent_table_access(thd, create_info, alter_info)) + check_fk_parent_table_access(thd, create_info, alter_info, new_db)) DBUG_RETURN(true); /* diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 43038ba9321..3c0827bb164 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2011, 2015, MariaDB +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. + Copyright (c) 2011, 2016, MariaDB 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 @@ -838,7 +838,7 @@ int mysql_update(THD *thd, error= 0; } else if (!ignore || - table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + table->file->is_fatal_error(error, HA_CHECK_ALL)) { /* If (ignore && error is ignorable) we don't have to @@ -846,7 +846,7 @@ int mysql_update(THD *thd, */ myf flags= 0; - if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + if (table->file->is_fatal_error(error, HA_CHECK_ALL)) flags|= ME_FATALERROR; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); @@ -2167,7 +2167,7 @@ int multi_update::send_data(List<Item> ¬_used_values) { updated--; if (!ignore || - table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + table->file->is_fatal_error(error, HA_CHECK_ALL)) { /* If (ignore && error == is ignorable) we don't have to @@ -2175,7 +2175,7 @@ int multi_update::send_data(List<Item> ¬_used_values) */ myf flags= 0; - if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + if (table->file->is_fatal_error(error, HA_CHECK_ALL)) flags|= ME_FATALERROR; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); @@ -2452,7 +2452,7 @@ int multi_update::do_updates() local_error != HA_ERR_RECORD_IS_THE_SAME) { if (!ignore || - table->file->is_fatal_error(local_error, HA_CHECK_DUP_KEY)) + table->file->is_fatal_error(local_error, HA_CHECK_ALL)) { err_table= table; goto err; diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic index 373f5834838..7c62516d52b 100644 --- a/sql/sys_vars.ic +++ b/sql/sys_vars.ic @@ -30,6 +30,7 @@ #include "strfunc.h" #include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone #include "rpl_mi.h" // For Multi-Source Replication +#include "debug_sync.h" /* a set of mostly trivial (as in f(X)=X) defines below to make system variable @@ -1469,7 +1470,6 @@ public: } bool session_update(THD *thd, set_var *var) { - extern bool debug_sync_update(THD *thd, char *val_str); return debug_sync_update(thd, var->save_result.string_value.str); } bool global_update(THD *thd, set_var *var) |