diff options
author | Sergei Golubchik <serg@mariadb.org> | 2016-04-26 23:05:26 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2016-04-26 23:05:26 +0200 |
commit | 872649c7baab3a9f7efdda78e49c4bc7dd481d91 (patch) | |
tree | 4fffb1a99ca36ccea65e64bcaa81293c40e7539f /sql | |
parent | 4995bcffaded6a02106632fb8f259cd3d9048dc4 (diff) | |
parent | 4f1ad43992d75676687f29da96dd7c4147247a8f (diff) | |
download | mariadb-git-872649c7baab3a9f7efdda78e49c4bc7dd481d91.tar.gz |
Merge branch '5.5' into 10.0
Diffstat (limited to 'sql')
-rw-r--r-- | sql/gen_lex_hash.cc | 2 | ||||
-rw-r--r-- | sql/handler.cc | 4 | ||||
-rw-r--r-- | sql/handler.h | 13 | ||||
-rw-r--r-- | sql/item.cc | 11 | ||||
-rw-r--r-- | sql/item.h | 2 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 77 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 2 | ||||
-rw-r--r-- | sql/item_func.cc | 24 | ||||
-rw-r--r-- | sql/item_func.h | 21 | ||||
-rw-r--r-- | sql/item_geofunc.h | 6 | ||||
-rw-r--r-- | sql/mysqld.cc | 3 | ||||
-rw-r--r-- | sql/mysqld.h | 12 | ||||
-rw-r--r-- | sql/sql_acl.cc | 47 | ||||
-rw-r--r-- | sql/sql_class.h | 14 | ||||
-rw-r--r-- | sql/sql_connect.cc | 3 | ||||
-rw-r--r-- | sql/sql_insert.cc | 13 | ||||
-rw-r--r-- | sql/sql_load.cc | 5 | ||||
-rw-r--r-- | sql/sql_locale.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 30 | ||||
-rw-r--r-- | sql/sql_parse.h | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 67 | ||||
-rw-r--r-- | sql/sql_table.cc | 22 | ||||
-rw-r--r-- | sql/sql_update.cc | 14 |
23 files changed, 239 insertions, 158 deletions
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 61d2b37c90f..136bc422a4f 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 diff --git a/sql/handler.h b/sql/handler.h index 6ec9769036c..e2176f04933 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 @@ -419,7 +419,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 { @@ -2822,7 +2824,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; } @@ -4153,4 +4158,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 d9d1409572c..065204dc9c3 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 @@ -1306,8 +1306,8 @@ Item *Item_param::safe_charset_converter(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. @@ -3835,7 +3835,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('?'); } @@ -6734,7 +6734,8 @@ Item *Item_field::update_value_transformer(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 b45faaf45ce..e402112b725 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2363,7 +2363,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 b2c580db507..e0dbf2c5a73 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -161,10 +161,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]->cmp_type()); /* When aggregating types of two row expressions we have to check @@ -176,6 +177,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; } @@ -2621,10 +2628,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)); } @@ -3081,24 +3085,6 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref) } -void Item_func_case::agg_str_lengths(Item* arg) -{ - fix_char_length(MY_MAX(max_char_length(), arg->max_char_length())); - set_if_bigger(decimals, arg->decimals); - unsigned_flag= unsigned_flag && arg->unsigned_flag; -} - - -void Item_func_case::agg_num_lengths(Item *arg) -{ - uint len= my_decimal_length_to_precision(arg->max_length, arg->decimals, - arg->unsigned_flag) - arg->decimals; - set_if_bigger(max_length, len); - set_if_bigger(decimals, arg->decimals); - unsigned_flag= unsigned_flag && arg->unsigned_flag; -} - - /** Check if (*place) and new_value points to different Items and call THD::change_item_tree() if needed. @@ -3164,17 +3150,7 @@ void Item_func_case::fix_length_and_dec() } else { - collation.set_numeric(); - max_length=0; - decimals=0; - unsigned_flag= TRUE; - for (uint i= 0; i < ncases; i+= 2) - agg_num_lengths(args[i + 1]); - if (else_expr_num != -1) - agg_num_lengths(args[else_expr_num]); - max_length= my_decimal_precision_to_length_no_truncation(max_length + - decimals, decimals, - unsigned_flag); + fix_attributes(agg, nagg); } /* @@ -3374,16 +3350,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); } @@ -3406,19 +3378,32 @@ void Item_func_coalesce::fix_length_and_dec() { cached_field_type= agg_field_type(args, arg_count); agg_result_type(&cached_result_type, args, arg_count); + fix_attributes(args, arg_count); +} + + +#if MYSQL_VERSION_ID > 100100 +#error Rename this to Item_hybrid_func::fix_attributes() when mering to 10.1 +#endif +void Item_func_hybrid_result_type::fix_attributes(Item **items, uint nitems) +{ switch (cached_result_type) { case STRING_RESULT: - if (count_string_result_length(cached_field_type, args, arg_count)) + if (count_string_result_length(field_type(), + items, nitems)) return; break; case DECIMAL_RESULT: - count_decimal_length(); + collation.set_numeric(); + count_decimal_length(items, nitems); break; case REAL_RESULT: - count_real_length(); + collation.set_numeric(); + count_real_length(items, nitems); break; case INT_RESULT: - count_only_length(args, arg_count); + collation.set_numeric(); + count_only_length(items, nitems); decimals= 0; break; case ROW_RESULT: diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index d109e412f0c..dbd96a89a24 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1274,8 +1274,6 @@ public: Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } void cleanup(); - void agg_str_lengths(Item *arg); - void agg_num_lengths(Item *arg); }; /* diff --git a/sql/item_func.cc b/sql/item_func.cc index 6c205b6afa7..a4a2782c8c4 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -639,16 +639,16 @@ void Item_func::count_datetime_length(Item **item, uint nitems) result length/precision depends on argument ones. */ -void Item_func::count_decimal_length() +void Item_func::count_decimal_length(Item **item, uint nitems) { int max_int_part= 0; decimals= 0; unsigned_flag= 1; - for (uint i=0 ; i < arg_count ; i++) + for (uint i=0 ; i < nitems ; i++) { - set_if_bigger(decimals, args[i]->decimals); - set_if_bigger(max_int_part, args[i]->decimal_int_part()); - set_if_smaller(unsigned_flag, args[i]->unsigned_flag); + set_if_bigger(decimals, item[i]->decimals); + set_if_bigger(max_int_part, item[i]->decimal_int_part()); + set_if_smaller(unsigned_flag, item[i]->unsigned_flag); } int precision= MY_MIN(max_int_part + decimals, DECIMAL_MAX_PRECISION); fix_char_length(my_decimal_precision_to_length_no_truncation(precision, @@ -679,19 +679,19 @@ void Item_func::count_only_length(Item **item, uint nitems) result length/precision depends on argument ones. */ -void Item_func::count_real_length() +void Item_func::count_real_length(Item **item, uint nitems) { uint32 length= 0; decimals= 0; max_length= 0; - for (uint i=0 ; i < arg_count ; i++) + for (uint i=0 ; i < nitems ; i++) { if (decimals != NOT_FIXED_DEC) { - set_if_bigger(decimals, args[i]->decimals); - set_if_bigger(length, (args[i]->max_length - args[i]->decimals)); + set_if_bigger(decimals, item[i]->decimals); + set_if_bigger(length, (item[i]->max_length - item[i]->decimals)); } - set_if_bigger(max_length, args[i]->max_length); + set_if_bigger(max_length, item[i]->max_length); } if (decimals != NOT_FIXED_DEC) { @@ -809,7 +809,7 @@ void Item_num_op::fix_length_and_dec(void) if (r0 == REAL_RESULT || r1 == REAL_RESULT || r0 == STRING_RESULT || r1 ==STRING_RESULT) { - count_real_length(); + count_real_length(args, arg_count); max_length= float_length(decimals); cached_result_type= REAL_RESULT; } @@ -6305,6 +6305,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 0b3454fa4b0..3d0cdca4472 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 @@ -40,6 +40,13 @@ protected: */ uint allowed_arg_cols; String *val_str_from_val_str_ascii(String *str, String *str2); + + void count_only_length(Item **item, uint nitems); + void count_real_length(Item **item, uint nitems); + void count_decimal_length(Item **item, uint nitems); + void count_datetime_length(Item **item, uint nitems); + bool count_string_result_length(enum_field_types field_type, + Item **item, uint nitems); public: uint arg_count; /* @@ -154,16 +161,10 @@ public: virtual void print(String *str, enum_query_type query_type); void print_op(String *str, enum_query_type query_type); void print_args(String *str, uint from, enum_query_type query_type); - void count_only_length(Item **item, uint nitems); - void count_real_length(); - void count_decimal_length(); inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { return (null_value=args[0]->get_date_with_conversion(ltime, fuzzy_date)); } - void count_datetime_length(Item **item, uint nitems); - bool count_string_result_length(enum_field_types field_type, - Item **item, uint nitems); inline bool get_arg0_time(MYSQL_TIME *ltime) { null_value= args[0]->get_time(ltime); @@ -253,7 +254,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() @@ -444,7 +445,7 @@ class Item_func_hybrid_result_type: public Item_func } protected: Item_result cached_result_type; - + void fix_attributes(Item **item, uint nitems); public: Item_func_hybrid_result_type() :Item_func(), cached_result_type(REAL_RESULT) { collation.set_numeric(); } diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 94be38e26ee..62d2198e221 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 @@ -191,7 +191,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/mysqld.cc b/sql/mysqld.cc index 5789e4b3cfe..177018dd171 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -281,7 +281,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= { @@ -8660,6 +8660,7 @@ mysqld_get_one_option(int optid, 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 673ef71cb7a..dbc65cd2a43 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 @@ -623,7 +623,13 @@ enum enum_query_type /// Without character set introducers. QT_WITHOUT_INTRODUCERS= (1 << 1), /// view internal representation (like QT_ORDINARY except ORDER BY clause) - QT_VIEW_INTERNAL= (1 << 2) + QT_VIEW_INTERNAL= (1 << 2), + /** + 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), }; /* query_id */ diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 502e9ff83f2..8cc9469cd09 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 @@ -742,9 +742,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, bool); static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); static inline void get_grantor(THD *thd, char* grantor); @@ -1035,7 +1034,6 @@ static my_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 (tables[0].table) // "host" table may not exist (e.g. in MySQL 5.6.7+) { if (init_read_record(&read_record_info, thd, table= tables[0].table, @@ -1097,11 +1095,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) NULL, 1, 1, FALSE)) goto end; table->use_all_columns(); - (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); - username_char_length= MY_MIN(table->field[1]->char_length(), USERNAME_CHAR_LENGTH); password_length= table->field[2]->field_length / @@ -1361,7 +1354,6 @@ static my_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; @@ -1423,8 +1415,6 @@ static my_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 (tables[3].table) { if (init_read_record(&read_record_info, thd, table= tables[3].table, @@ -1461,10 +1451,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) 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))) @@ -1503,6 +1490,7 @@ static my_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); } @@ -1519,12 +1507,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; } @@ -1605,6 +1593,15 @@ my_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); @@ -2611,6 +2608,7 @@ bool change_password(THD *thd, const char *host, const char *user, enum_binlog_format save_binlog_format; uint new_password_len= (uint) strlen(new_password); bool result= 1; + bool use_salt= 0; DBUG_ENTER("change_password"); DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", host,user,new_password)); @@ -2668,6 +2666,7 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->auth_string.length= new_password_len; set_user_salt(acl_user, new_password, new_password_len); set_user_plugin(acl_user, new_password_len); + use_salt= 1; } else push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, @@ -2676,7 +2675,7 @@ bool change_password(THD *thd, const char *host, const char *user, if (update_user_table(thd, table, safe_str(acl_user->host.hostname), safe_str(acl_user->user.str), - new_password, new_password_len)) + new_password, new_password_len, use_salt)) { mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */ goto end; @@ -2972,7 +2971,8 @@ bool hostname_requires_resolving(const char *hostname) static bool update_user_table(THD *thd, TABLE *table, const char *host, const char *user, - const char *new_password, uint new_password_len) + const char *new_password, uint new_password_len, + bool reset_plugin) { char user_key[MAX_KEY_LENGTH]; int error; @@ -2995,6 +2995,11 @@ static bool update_user_table(THD *thd, TABLE *table, } store_record(table,record[1]); table->field[2]->store(new_password, new_password_len, system_charset_info); + if (reset_plugin && table->s->fields >= 41) + { + table->field[40]->reset(); + table->field[41]->reset(); + } if ((error=table->file->ha_update_row(table->record[1],table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) { diff --git a/sql/sql_class.h b/sql/sql_class.h index e9f1d0a7a16..46eeeceb112 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 @@ -2100,6 +2100,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 4d2c48c83cc..c5a0d1464e7 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1196,7 +1196,8 @@ void end_connection(THD *thd) } if (!thd->killed && (net->error && net->vio != 0)) - thd->print_aborted_warning(1, ER(ER_UNKNOWN_ERROR)); + thd->print_aborted_warning(1, + thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->message() : ER(ER_UNKNOWN_ERROR)); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index def5560a011..d89f5cc44ea 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 @@ -1588,9 +1588,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) { /* @@ -1718,7 +1719,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)) @@ -1848,7 +1849,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)) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 08687b20b00..5d631027900 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 @@ -255,6 +255,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 d918d5c9cf4..8dc71452fa4 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 b91455888b8..fdaf3323366 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6029,6 +6029,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. @@ -6037,7 +6038,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); @@ -6077,10 +6079,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) @@ -8200,7 +8220,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 40ae5427133..7a55d8ac4a4 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 28f59047b43..f58738a4539 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 @@ -15437,6 +15437,14 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, Field *new_field; LINT_INIT(new_field); + /* + 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, 1); + else switch (item->result_type()) { case REAL_RESULT: new_field= new Field_double(item->max_length, maybe_null, @@ -15459,18 +15467,11 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, 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, 1); /* Make sure that the blob fits into a Field_varstring which has 2-byte lenght. */ - else if (item->max_length/item->collation.collation->mbmaxlen > 255 && + if (item->max_length/item->collation.collation->mbmaxlen > 255 && convert_blob_length <= Field_varstring::MAX_SIZE && convert_blob_length) new_field= new Field_varstring(convert_blob_length, maybe_null, @@ -24182,33 +24183,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; } @@ -24228,7 +24249,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) @@ -24241,7 +24262,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; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8ac914bdc40..7bf008870b9 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 @@ -5421,6 +5421,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()) { /* @@ -5491,6 +5494,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); @@ -8434,7 +8452,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 a59e635afaa..2507c3fec53 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 @@ -823,7 +823,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 @@ -831,7 +831,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); @@ -2131,7 +2131,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 @@ -2139,7 +2139,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); @@ -2414,7 +2414,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; |