diff options
author | Sergei Golubchik <serg@mariadb.org> | 2017-10-24 14:53:18 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2017-10-24 14:53:18 +0200 |
commit | e0a1c745ec3ed1ec6c0375a2a624697c29f480a6 (patch) | |
tree | 24ded2c6ebe3ea3413ce56af89ea0f2f63bb3a39 /sql | |
parent | 4ec88ea9c3ec52d996b39167d12a61ab95fdeacc (diff) | |
parent | 2aa51f528fd5d23cc54eca8fbd07e88e7b2993c7 (diff) | |
download | mariadb-git-e0a1c745ec3ed1ec6c0375a2a624697c29f480a6.tar.gz |
Merge branch '10.1' into 10.2
Diffstat (limited to 'sql')
38 files changed, 380 insertions, 217 deletions
diff --git a/sql/events.cc b/sql/events.cc index 1f2501646cb..07cfdf1028a 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -188,8 +188,8 @@ common_1_lev_code: expr= tmp_expr - (tmp_expr/60)*60; /* the code after the switch will finish */ - } break; + } case INTERVAL_HOUR_SECOND: { ulonglong tmp_expr= expr; @@ -205,8 +205,8 @@ common_1_lev_code: expr= tmp_expr - (tmp_expr/60)*60; /* the code after the switch will finish */ - } break; + } case INTERVAL_DAY_SECOND: { ulonglong tmp_expr= expr; @@ -228,8 +228,8 @@ common_1_lev_code: expr= tmp_expr - (tmp_expr/60)*60; /* the code after the switch will finish */ - } break; + } case INTERVAL_DAY_MICROSECOND: case INTERVAL_HOUR_MICROSECOND: case INTERVAL_MINUTE_MICROSECOND: @@ -243,7 +243,8 @@ common_1_lev_code: break; case INTERVAL_WEEK: expr/= 7; - /* fall through */ + close_quote= FALSE; + break; default: close_quote= FALSE; break; diff --git a/sql/field.cc b/sql/field.cc index 6b3f836048f..bff936b7052 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2008, 2013, Monty Program Ab. + Copyright (c) 2000, 2017, Oracle and/or its affiliates. + Copyright (c) 2008, 2017, 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 @@ -8913,13 +8913,13 @@ String *Field_set::val_str(String *val_buffer, ulonglong tmp=(ulonglong) Field_enum::val_int(); uint bitnr=0; + /* + Some callers expect *val_buffer to contain the result, + so we assign to it, rather than doing 'return &empty_set_string. + */ + *val_buffer= empty_set_string; if (tmp == 0) { - /* - Some callers expect *val_buffer to contain the result, - so we assign to it, rather than doing 'return &empty_set_string. - */ - *val_buffer= empty_set_string; return val_buffer; } diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index a0fbdffec90..cc5521114f4 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2005, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab & SkySQL Ab + Copyright (c) 2005, 2017, Oracle and/or its affiliates. + Copyright (c) 2009, 2017, 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 @@ -1933,7 +1933,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, cleanup_new_partition(part_count); DBUG_RETURN(error); } - + DBUG_PRINT("info", ("Add partition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, new_file_array[i], diff --git a/sql/handler.cc b/sql/handler.cc index 2e499238dba..1f3df447f24 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -404,7 +404,7 @@ static int ha_finish_errors(void) } static volatile int32 need_full_discover_for_existence= 0; -static volatile int32 engines_with_discover_table_names= 0; +static volatile int32 engines_with_discover_file_names= 0; static volatile int32 engines_with_discover= 0; static int full_discover_for_existence(handlerton *, const char *, const char *) @@ -429,8 +429,8 @@ static void update_discovery_counters(handlerton *hton, int val) if (hton->discover_table_existence == full_discover_for_existence) my_atomic_add32(&need_full_discover_for_existence, val); - if (hton->discover_table_names) - my_atomic_add32(&engines_with_discover_table_names, val); + if (hton->discover_table_names && hton->tablefile_extensions[0]) + my_atomic_add32(&engines_with_discover_file_names, val); if (hton->discover_table) my_atomic_add32(&engines_with_discover, val); @@ -5200,6 +5200,7 @@ void Discovered_table_list::remove_duplicates() { LEX_STRING **src= tables->front(); LEX_STRING **dst= src; + sort(); while (++dst <= tables->back()) { LEX_STRING *s= *src, *d= *dst; @@ -5267,10 +5268,12 @@ int ha_discover_table_names(THD *thd, LEX_STRING *db, MY_DIR *dirp, int error; DBUG_ENTER("ha_discover_table_names"); - if (engines_with_discover_table_names == 0 && !reusable) + if (engines_with_discover_file_names == 0 && !reusable) { - error= ext_table_discovery_simple(dirp, result); - result->sort(); + st_discover_names_args args= {db, NULL, result, 0}; + error= ext_table_discovery_simple(dirp, result) || + plugin_foreach(thd, discover_names, + MYSQL_STORAGE_ENGINE_PLUGIN, &args); } else { @@ -5283,8 +5286,6 @@ int ha_discover_table_names(THD *thd, LEX_STRING *db, MY_DIR *dirp, error= extension_based_table_discovery(dirp, reg_ext, result) || plugin_foreach(thd, discover_names, MYSQL_STORAGE_ENGINE_PLUGIN, &args); - result->sort(); - if (args.possible_duplicates > 0) result->remove_duplicates(); } diff --git a/sql/item.cc b/sql/item.cc index 910fdd06303..efd82d4f873 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2248,6 +2248,9 @@ bool Item_func_or_sum::agg_item_set_converter(const DTCollation &coll, Item **args, uint nargs, uint flags, int item_sep) { + THD *thd= current_thd; + if (thd->lex->is_ps_or_view_context_analysis()) + return false; Item **arg, *safe_args[2]= {NULL, NULL}; /* @@ -2263,7 +2266,6 @@ bool Item_func_or_sum::agg_item_set_converter(const DTCollation &coll, safe_args[1]= args[item_sep]; } - THD *thd= current_thd; bool res= FALSE; uint i; @@ -6188,7 +6190,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, Field_string(max_length, maybe_null, name, collation.collation); break; } - /* Fall through */ + /* fall through */ case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: case MYSQL_TYPE_VAR_STRING: @@ -7000,6 +7002,7 @@ bool Item::cache_const_expr_analyzer(uchar **arg) */ if (const_item() && !(basic_const_item() || item->basic_const_item() || + item->type() == Item::NULL_ITEM || /* Item_name_const hack */ item->type() == Item::FIELD_ITEM || item->type() == SUBSELECT_ITEM || item->type() == CACHE_ITEM || @@ -7355,7 +7358,11 @@ public: // Find which select the field is in. This is achieved by walking up // the select tree and looking for the table of interest. st_select_lex *sel; - for (sel= current_select; sel; sel= sel->outer_select()) + for (sel= current_select; + sel ; + sel= (sel->context.outer_context ? + sel->context.outer_context->select_lex: + NULL)) { List_iterator<TABLE_LIST> li(sel->leaf_tables); TABLE_LIST *tbl; @@ -8529,7 +8536,6 @@ bool Item_direct_view_ref::send(Protocol *protocol, String *buffer) bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) { - DBUG_ASSERT(1); /* view fild reference must be defined */ DBUG_ASSERT(*ref); /* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */ @@ -10597,7 +10603,7 @@ void Item_direct_view_ref::update_used_tables() table_map Item_direct_view_ref::used_tables() const { - DBUG_ASSERT(null_ref_table); + DBUG_ASSERT(fixed); if (get_depended_from()) return OUTER_REF_TABLE_BIT; diff --git a/sql/item.h b/sql/item.h index 76708fb3570..9b94a08c34e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1,8 +1,8 @@ #ifndef SQL_ITEM_INCLUDED #define SQL_ITEM_INCLUDED -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB Corporation. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. + Copyright (c) 2009, 2017, 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/item_row.cc b/sql/item_row.cc index fc484f560ee..6486bb66615 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -24,7 +24,6 @@ #include "sql_class.h" // THD, set_var.h: THD #include "set_var.h" - void Item_row::illegal_method_call(const char *method) { DBUG_ENTER("Item_row::illegal_method_call"); diff --git a/sql/item_row.h b/sql/item_row.h index cd58e15fe8b..d7326df04ce 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -47,13 +47,10 @@ public: Item_row(THD *thd, List<Item> &list): Item(thd), Item_args(thd, list), not_null_tables_cache(0), with_null(0) { } - Item_row(THD *thd, Item_row *item): - Item(thd), - Item_args(item), - Used_tables_and_const_cache(item), - not_null_tables_cache(0), - with_null(0) - {} + Item_row(THD *thd, Item_row *row): + Item(thd), Item_args(thd, static_cast<Item_args*>(row)), Used_tables_and_const_cache(), + not_null_tables_cache(0), with_null(0) + { } enum Type type() const { return ROW_ITEM; }; void illegal_method_call(const char *); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 29433be4af8..e6907747a8c 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1448,6 +1448,10 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp, DBUG_ENTER("Item_in_subselect::Item_in_subselect"); DBUG_PRINT("info", ("in_strategy: %u", (uint)in_strategy)); left_expr_orig= left_expr= left_exp; + /* prepare to possible disassembling the item in convert_subq_to_sj() */ + if (left_exp->type() == Item::ROW_ITEM) + left_expr_orig= new (thd->mem_root) + Item_row(thd, static_cast<Item_row*>(left_exp)); func= &eq_creator; init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this)); max_columns= UINT_MAX; @@ -1471,6 +1475,10 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp, { DBUG_ENTER("Item_allany_subselect::Item_allany_subselect"); left_expr_orig= left_expr= left_exp; + /* prepare to possible disassembling the item in convert_subq_to_sj() */ + if (left_exp->type() == Item::ROW_ITEM) + left_expr_orig= new (thd->mem_root) + Item_row(thd, static_cast<Item_row*>(left_exp)); func= func_creator(all_arg); init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this)); max_columns= 1; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 2724bb63eda..01b07c00816 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1852,9 +1852,18 @@ overflow: ltime->hour= TIME_MAX_HOUR+1; check_time_range(ltime, decimals, &unused); - make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, - err->ptr(), err->length(), - MYSQL_TIMESTAMP_TIME, NullS); + if (!err) + { + ErrConvInteger err2(sec, unsigned_flag); + make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, + &err2, MYSQL_TIMESTAMP_TIME, NullS); + } + else + { + ErrConvString err2(err); + make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, + &err2, MYSQL_TIMESTAMP_TIME, NullS); + } return 0; } diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index dccccc479ef..354a54a5c1a 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -546,8 +546,16 @@ public: { return val_decimal_from_date(decimal_value); } Field *create_field_for_create_select(TABLE *table) { return tmp_table_field_from_field_type(table, false, false); } +#if MARIADB_VERSION_ID > 100300 +#error This code should be removed in 10.3, to use the derived save_in_field() +#else int save_in_field(Field *field, bool no_conversions) - { return save_date_in_field(field); } + { + return field_type() == MYSQL_TYPE_TIME ? + save_time_in_field(field) : + save_date_in_field(field); + } +#endif void fix_length_and_dec(); }; diff --git a/sql/log_event.cc b/sql/log_event.cc index 8932d0f261d..8840861bfdc 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8673,22 +8673,7 @@ User_var_log_event(const char* buf, uint event_len, Old events will not have this extra byte, thence, we keep the flags set to UNDEF_F. */ - size_t bytes_read= ((val + val_len) - buf_start); -#ifndef DBUG_OFF - bool old_pre_checksum_fd= description_event->is_version_before_checksum( - &description_event->server_version_split); -#endif - DBUG_ASSERT((bytes_read == data_written - - (old_pre_checksum_fd || - (description_event->checksum_alg == - BINLOG_CHECKSUM_ALG_OFF)) ? - 0 : BINLOG_CHECKSUM_LEN) - || - (bytes_read == data_written -1 - - (old_pre_checksum_fd || - (description_event->checksum_alg == - BINLOG_CHECKSUM_ALG_OFF)) ? - 0 : BINLOG_CHECKSUM_LEN)); + uint bytes_read= ((val + val_len) - buf_start); if ((data_written - bytes_read) > 0) { flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3d9c1aef4b8..04d2059eb62 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -8536,6 +8536,34 @@ bool sel_trees_can_be_ored(RANGE_OPT_PARAM* param, } /* + Check whether the key parts inf_init..inf_end-1 of one index can compose + an infix for the key parts key_init..key_end-1 of another index +*/ + +static +bool is_key_infix(KEY_PART *key_init, KEY_PART *key_end, + KEY_PART *inf_init, KEY_PART *inf_end) +{ + KEY_PART *key_part, *inf_part; + for (key_part= key_init; key_part < key_end; key_part++) + { + if (key_part->field->eq(inf_init->field)) + break; + } + if (key_part == key_end) + return false; + for (key_part++, inf_part= inf_init + 1; + key_part < key_end && inf_part < inf_end; + key_part++, inf_part++) + { + if (!key_part->field->eq(inf_part->field)) + return false; + } + return inf_part == inf_end; +} + + +/* Check whether range parts of two trees must be ored for some indexes SYNOPSIS @@ -8591,14 +8619,9 @@ bool sel_trees_must_be_ored(RANGE_OPT_PARAM* param, KEY_PART *key2_init= param->key[idx2]+tree2->keys[idx2]->part; KEY_PART *key2_end= param->key[idx2]+tree2->keys[idx2]->max_part_no; - KEY_PART *part1, *part2; - for (part1= key1_init, part2= key2_init; - part1 < key1_end && part2 < key2_end; - part1++, part2++) - { - if (!part1->field->eq(part2->field)) - DBUG_RETURN(FALSE); - } + if (!is_key_infix(key1_init, key1_end, key2_init, key2_end) && + !is_key_infix(key2_init, key2_end, key1_init, key1_end)) + DBUG_RETURN(FALSE); } } diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index f37db88957a..b16fec1de3e 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1614,6 +1614,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) sj-nest. */ st_select_lex *subq_lex= subq_pred->unit->first_select(); + DBUG_ASSERT(subq_lex->next_select() == NULL); nested_join->join_list.empty(); List_iterator_fast<TABLE_LIST> li(subq_lex->top_join_list); TABLE_LIST *tl; @@ -1717,7 +1718,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) if (subq_pred->left_expr->cols() == 1) { - nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr, + /* add left = select_list_element */ + nested_join->sj_outer_expr_list.push_back(&subq_pred->left_expr, thd->mem_root); /* Create Item_func_eq. Note that @@ -1731,26 +1733,62 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) Item_func_eq *item_eq= new (thd->mem_root) Item_func_eq(thd, subq_pred->left_expr_orig, subq_lex->ref_pointer_array[0]); + if (!item_eq) + DBUG_RETURN(TRUE); if (subq_pred->left_expr_orig != subq_pred->left_expr) thd->change_item_tree(item_eq->arguments(), subq_pred->left_expr); item_eq->in_equality_no= 0; sj_nest->sj_on_expr= and_items(thd, sj_nest->sj_on_expr, item_eq); } - else + else if (subq_pred->left_expr->type() == Item::ROW_ITEM) { + /* + disassemple left expression and add + left1 = select_list_element1 and left2 = select_list_element2 ... + */ for (uint i= 0; i < subq_pred->left_expr->cols(); i++) { - nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr-> - element_index(i), + nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr->addr(i), thd->mem_root); - Item_func_eq *item_eq= + Item_func_eq *item_eq= new (thd->mem_root) - Item_func_eq(thd, subq_pred->left_expr->element_index(i), + Item_func_eq(thd, subq_pred->left_expr_orig->element_index(i), subq_lex->ref_pointer_array[i]); + if (!item_eq) + DBUG_RETURN(TRUE); + DBUG_ASSERT(subq_pred->left_expr->element_index(i)->fixed); + if (subq_pred->left_expr_orig->element_index(i) != + subq_pred->left_expr->element_index(i)) + thd->change_item_tree(item_eq->arguments(), + subq_pred->left_expr->element_index(i)); item_eq->in_equality_no= i; sj_nest->sj_on_expr= and_items(thd, sj_nest->sj_on_expr, item_eq); } } + else + { + /* + add row operation + left = (select_list_element1, select_list_element2, ...) + */ + Item_row *row= new (thd->mem_root) Item_row(thd, subq_lex->pre_fix); + /* fix fields on subquery was call so they should be the same */ + DBUG_ASSERT(subq_pred->left_expr->cols() == row->cols()); + if (!row) + DBUG_RETURN(TRUE); + nested_join->sj_outer_expr_list.push_back(&subq_pred->left_expr); + Item_func_eq *item_eq= + new (thd->mem_root) Item_func_eq(thd, subq_pred->left_expr_orig, row); + if (!item_eq) + DBUG_RETURN(TRUE); + for (uint i= 0; i < row->cols(); i++) + { + if (row->element_index(i) != subq_lex->ref_pointer_array[i]) + thd->change_item_tree(row->addr(i), subq_lex->ref_pointer_array[i]); + } + item_eq->in_equality_no= 0; + sj_nest->sj_on_expr= and_items(thd, sj_nest->sj_on_expr, item_eq); + } /* Fix the created equality and AND @@ -3299,8 +3337,8 @@ void restore_prev_sj_state(const table_map remaining_tables, ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest, table_map remaining_tables) { - List_iterator<Item> li(sj_nest->nested_join->sj_outer_expr_list); - Item *item; + List_iterator<Item_ptr> li(sj_nest->nested_join->sj_outer_expr_list); + Item **item; uint i= 0; ulonglong res= 0; while ((item= li++)) @@ -3311,7 +3349,7 @@ ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest, class and see if there is an element that is bound? (this is an optional feature) */ - if (!(item->used_tables() & remaining_tables)) + if (!(item[0]->used_tables() & remaining_tables)) { res |= 1ULL << i; } diff --git a/sql/slave.cc b/sql/slave.cc index 1b1a597fa2a..19905841a2c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3213,7 +3213,6 @@ static int init_slave_thread(THD* thd, Master_info *mi, thd->variables.sql_log_slow= opt_log_slow_slave_statements; thd->variables.log_slow_filter= global_system_variables.log_slow_filter; set_slave_thread_options(thd); - thd->client_capabilities = CLIENT_LOCAL_FILES; if (thd_type == SLAVE_THD_SQL) THD_STAGE_INFO(thd, stage_waiting_for_the_next_event_in_relay_log); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index b3edcdca474..20c02fce752 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -119,7 +119,6 @@ sp_get_item_value(THD *thd, Item *item, String *str) case DECIMAL_RESULT: if (item->field_type() != MYSQL_TYPE_BIT) return item->val_str(str); - else {/* Bit type is handled as binary string */} /* fall through */ case STRING_RESULT: { @@ -2545,10 +2544,18 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access) *full_access= ((!check_table_access(thd, SELECT_ACL, &tables, FALSE, 1, TRUE) && (tables.grant.privilege & SELECT_ACL) != 0) || + /* Check if user owns the routine. */ (!strcmp(sp->m_definer_user.str, thd->security_ctx->priv_user) && !strcmp(sp->m_definer_host.str, - thd->security_ctx->priv_host))); + thd->security_ctx->priv_host)) || + /* Check if current role or any of the sub-granted roles + own the routine. */ + (sp->m_definer_host.length == 0 && + (!strcmp(sp->m_definer_user.str, + thd->security_ctx->priv_role) || + check_role_is_granted(thd->security_ctx->priv_role, NULL, + sp->m_definer_user.str)))); if (!*full_access) return check_some_routine_access(thd, sp->m_db.str, sp->m_name.str, sp->m_type == TYPE_ENUM_PROCEDURE); @@ -4327,4 +4334,3 @@ sp_add_to_query_tables(THD *thd, LEX *lex, lex->add_to_query_tables(table); return table; } - diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index af49eefa2a5..555865804f9 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -9194,6 +9194,16 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc) mysql_mutex_unlock(&acl_cache->lock); } +static int check_role_is_granted_callback(ACL_USER_BASE *grantee, void *data) +{ + LEX_CSTRING *rolename= static_cast<LEX_CSTRING *>(data); + if (rolename->length == grantee->user.length && + !strcmp(rolename->str, grantee->user.str)) + return -1; // End search, we've found our role. + + /* Keep looking, we haven't found our role yet. */ + return 0; +} /* Modify a privilege table. @@ -11198,7 +11208,6 @@ bool check_grant(THD *, ulong, TABLE_LIST *, bool, uint, bool) } #endif /*NO_EMBEDDED_ACCESS_CHECKS */ - SHOW_VAR acl_statistics[] = { #ifndef NO_EMBEDDED_ACCESS_CHECKS {"column_grants", (char*)show_column_grants, SHOW_SIMPLE_FUNC}, @@ -11214,6 +11223,43 @@ SHOW_VAR acl_statistics[] = { {NullS, NullS, SHOW_LONG}, }; +/* Check if a role is granted to a user/role. We traverse the role graph + and return true if we find a match. + + hostname == NULL means we are looking for a role as a starting point, + otherwise a user. +*/ +bool check_role_is_granted(const char *username, + const char *hostname, + const char *rolename) +{ + DBUG_ENTER("check_role_is_granted"); + bool result= false; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + ACL_USER_BASE *root; + mysql_mutex_lock(&acl_cache->lock); + if (hostname) + root= find_user_exact(username, hostname); + else + root= find_acl_role(username); + + LEX_CSTRING role_lex; + role_lex.str= rolename; + role_lex.length= strlen(rolename); + + if (root && /* No grantee, nothing to search. */ + traverse_role_graph_down(root, &role_lex, check_role_is_granted_callback, + NULL) == -1) + { + /* We have found the role during our search. */ + result= true; + } + + /* We haven't found the role or we had no initial grantee to start from. */ + mysql_mutex_unlock(&acl_cache->lock); +#endif + DBUG_RETURN(result); +} int fill_schema_enabled_roles(THD *thd, TABLE_LIST *tables, COND *cond) { @@ -13599,4 +13645,3 @@ maria_declare_plugin(mysql_password) MariaDB_PLUGIN_MATURITY_STABLE /* Maturity */ } maria_declare_plugin_end; - diff --git a/sql/sql_acl.h b/sql/sql_acl.h index daa36f6c32a..8d233fd3d0a 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -409,6 +409,14 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, extern SHOW_VAR acl_statistics[]; +/* Check if a role is granted to a user/role. + + If hostname == NULL, search for a role as the starting grantee. +*/ +bool check_role_is_granted(const char *username, + const char *hostname, + const char *rolename); + #ifndef DBUG_OFF extern ulong role_global_merges, role_db_merges, role_table_merges, role_column_merges, role_routine_merges; diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index dd3c2694202..5222381270a 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -66,7 +66,6 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list) if (thd->get_stmt_da()->is_ok()) thd->get_stmt_da()->reset_diagnostics_area(); table_list->table= NULL; - result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK; DBUG_RETURN(result_code); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ea57e1d19c9..3f5af2985db 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6994,13 +6994,15 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, enum_mark_columns mark_used_columns, - List<Item> *sum_func_list, bool allow_sum_func) + List<Item> *sum_func_list, List<Item> *pre_fix, + bool allow_sum_func) { reg2 Item *item; enum_mark_columns save_mark_used_columns= thd->mark_used_columns; nesting_map save_allow_sum_func= thd->lex->allow_sum_func; List_iterator<Item> it(fields); bool save_is_item_list_lookup; + bool make_pre_fix= (pre_fix && (pre_fix->elements == 0)); DBUG_ENTER("setup_fields"); DBUG_PRINT("enter", ("ref_pointer_array: %p", ref_pointer_array.array())); @@ -7050,6 +7052,9 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, thd->lex->current_select->cur_pos_in_select_list= 0; while ((item= it++)) { + if (make_pre_fix) + pre_fix->push_back(item, thd->stmt_arena->mem_root); + if ((!item->fixed && item->fix_fields(thd, it.ref())) || (item= *(it.ref()))->check_cols(1)) { diff --git a/sql/sql_base.h b/sql/sql_base.h index 374ac56c3d8..9fb94e92d09 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -159,7 +159,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, List<Item> *sum_func_list, uint wild_num); bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &item, enum_mark_columns mark_used_columns, - List<Item> *sum_func_list, bool allow_sum_func); + List<Item> *sum_func_list, List<Item> *pre_fix, + bool allow_sum_func); void unfix_fields(List<Item> &items); bool fill_record(THD * thd, TABLE *table_arg, List<Item> &fields, List<Item> &values, bool ignore_errors, bool update); @@ -364,7 +365,7 @@ inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array, bool res; thd->lex->select_lex.no_wrap_view_item= TRUE; res= setup_fields(thd, ref_pointer_array, item, mark_used_columns, - sum_func_list, allow_sum_func); + sum_func_list, NULL, allow_sum_func); thd->lex->select_lex.no_wrap_view_item= FALSE; return res; } diff --git a/sql/sql_const.h b/sql/sql_const.h index 95960ac131a..c91992a9029 100644 --- a/sql/sql_const.h +++ b/sql/sql_const.h @@ -45,7 +45,18 @@ #define MAX_MBWIDTH 3 /* Max multibyte sequence */ #define MAX_FILENAME_MBWIDTH 5 #define MAX_FIELD_CHARLENGTH 255 -#define MAX_FIELD_VARCHARLENGTH 65535 +/* + In MAX_FIELD_VARCHARLENGTH we reserve extra bytes for the overhead: + - 2 bytes for the length + - 1 byte for NULL bits + to avoid the "Row size too large" error for these three corner definitions: + CREATE TABLE t1 (c VARBINARY(65533)); + CREATE TABLE t1 (c VARBINARY(65534)); + CREATE TABLE t1 (c VARBINARY(65535)); + Like VARCHAR(65536), they will be converted to BLOB automatically + in non-sctict mode. +*/ +#define MAX_FIELD_VARCHARLENGTH (65535-2-1) #define MAX_FIELD_BLOBLENGTH UINT_MAX32 /* cf field_blob::get_length() */ #define CONVERT_IF_BIGGER_TO_BLOB 512 /* Threshold *in characters* */ diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index a30f9ae2a32..7b7a7e3f804 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -762,7 +762,7 @@ l DBUG_RETURN(TRUE); if ((wild_num && setup_wild(thd, table_list, field_list, NULL, wild_num)) || setup_fields(thd, Ref_ptr_array(), - field_list, MARK_COLUMNS_READ, NULL, 0) || + field_list, MARK_COLUMNS_READ, NULL, NULL, 0) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_ftfuncs(select_lex)) DBUG_RETURN(TRUE); diff --git a/sql/sql_do.cc b/sql/sql_do.cc index 6d86ece6a9f..da7dfe0c137 100644 --- a/sql/sql_do.cc +++ b/sql/sql_do.cc @@ -29,7 +29,7 @@ bool mysql_do(THD *thd, List<Item> &values) List_iterator<Item> li(values); Item *value; DBUG_ENTER("mysql_do"); - if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_NONE, 0, NULL, 0)) DBUG_RETURN(TRUE); while ((value = li++)) (void) value->is_null(); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a226ea17eb3..a94349527bf 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -268,7 +268,8 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, if (table_list->is_view()) unfix_fields(fields); - res= setup_fields(thd, Ref_ptr_array(), fields, MARK_COLUMNS_WRITE, 0, 0); + res= setup_fields(thd, Ref_ptr_array(), + fields, MARK_COLUMNS_WRITE, 0, NULL, 0); /* Restore the current context. */ ctx_state.restore_state(context, table_list); @@ -378,7 +379,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, /* Check the fields we are going to modify */ if (setup_fields(thd, Ref_ptr_array(), - update_fields, MARK_COLUMNS_WRITE, 0, 0)) + update_fields, MARK_COLUMNS_WRITE, 0, NULL, 0)) return -1; if (insert_table_list->is_view() && @@ -804,7 +805,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); goto abort; } - if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), + *values, MARK_COLUMNS_READ, 0, NULL, 0)) goto abort; switch_to_nullable_trigger_fields(*values, table); } @@ -1529,13 +1531,13 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, context->resolve_in_table_list_only(table_list); res= (setup_fields(thd, Ref_ptr_array(), - *values, MARK_COLUMNS_READ, 0, 0) || + *values, MARK_COLUMNS_READ, 0, NULL, 0) || check_insert_fields(thd, context->table_list, fields, *values, !insert_into_view, 0, &map)); if (!res) res= setup_fields(thd, Ref_ptr_array(), - update_values, MARK_COLUMNS_READ, 0, 0); + update_values, MARK_COLUMNS_READ, 0, NULL, 0); if (!res && duplic == DUP_UPDATE) { @@ -3525,7 +3527,8 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) */ lex->current_select= &lex->select_lex; - res= (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0) || + res= (setup_fields(thd, Ref_ptr_array(), + values, MARK_COLUMNS_READ, 0, NULL, 0) || check_insert_fields(thd, table_list, *fields, values, !insert_into_view, 1, &map)); @@ -3578,7 +3581,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) ctx_state.get_first_name_resolution_table(); res= res || setup_fields(thd, Ref_ptr_array(), *info.update_values, - MARK_COLUMNS_READ, 0, 0); + MARK_COLUMNS_READ, 0, NULL, 0); if (!res) { /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 9ab09c9fe7e..9ec9b5cdf95 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -783,6 +783,7 @@ public: Group_list_ptrs *group_list_ptrs; List<Item> item_list; /* list of fields & expressions */ + List<Item> pre_fix; /* above list before fix_fields */ bool is_item_list_lookup; /* Usualy it is pointer to ftfunc_list_alloc, but in union used to create fake diff --git a/sql/sql_load.cc b/sql/sql_load.cc index ea05d42673f..fbdc00433a6 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -387,21 +387,23 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, in this case. */ if (setup_fields(thd, Ref_ptr_array(), - set_fields, MARK_COLUMNS_WRITE, 0, 0) || - setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0)) + set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) || + setup_fields(thd, Ref_ptr_array(), + set_values, MARK_COLUMNS_READ, 0, NULL, 0)) DBUG_RETURN(TRUE); } else { // Part field list /* TODO: use this conds for 'WITH CHECK OPTIONS' */ if (setup_fields(thd, Ref_ptr_array(), - fields_vars, MARK_COLUMNS_WRITE, 0, 0) || + fields_vars, MARK_COLUMNS_WRITE, 0, NULL, 0) || setup_fields(thd, Ref_ptr_array(), - set_fields, MARK_COLUMNS_WRITE, 0, 0) || + set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) || check_that_all_fields_are_given_values(thd, table, table_list)) DBUG_RETURN(TRUE); /* Fix the expressions in SET clause */ - if (setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), + set_values, MARK_COLUMNS_READ, 0, NULL, 0)) DBUG_RETURN(TRUE); } switch_to_nullable_trigger_fields(fields_vars, table); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7662cc404a7..bf5144bfda6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1414,8 +1414,7 @@ out: @retval FALSE The statement isn't updating any relevant tables. */ -static my_bool deny_updates_if_read_only_option(THD *thd, - TABLE_LIST *all_tables) +static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables) { DBUG_ENTER("deny_updates_if_read_only_option"); @@ -1424,11 +1423,7 @@ static my_bool deny_updates_if_read_only_option(THD *thd, LEX *lex= thd->lex; - const my_bool user_is_super= - ((ulong)(thd->security_ctx->master_access & SUPER_ACL) == - (ulong)SUPER_ACL); - - if (user_is_super) + if (thd->security_ctx->master_access & SUPER_ACL) DBUG_RETURN(FALSE); if (!(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA)) @@ -1438,28 +1433,26 @@ static my_bool deny_updates_if_read_only_option(THD *thd, if (lex->sql_command == SQLCOM_UPDATE_MULTI) DBUG_RETURN(FALSE); + if (lex->sql_command == SQLCOM_CREATE_DB || + lex->sql_command == SQLCOM_DROP_DB) + DBUG_RETURN(TRUE); + /* a table-to-be-created is not in the temp table list yet, so CREATE TABLE needs a special treatment */ - const bool update_real_tables= lex->sql_command == SQLCOM_CREATE_TABLE ? - !lex->tmp_table() : some_non_temp_table_to_be_updated(thd, all_tables); - - const bool create_or_drop_databases= - (lex->sql_command == SQLCOM_CREATE_DB) || - (lex->sql_command == SQLCOM_DROP_DB); - - if (update_real_tables || create_or_drop_databases) - { - /* - An attempt was made to modify one or more non-temporary tables. - */ - DBUG_RETURN(TRUE); - } + if (lex->sql_command == SQLCOM_CREATE_TABLE) + DBUG_RETURN(!lex->tmp_table()); + /* + a table-to-be-dropped might not exist (DROP TEMPORARY TABLE IF EXISTS), + cannot use the temp table list either. + */ + if (lex->sql_command == SQLCOM_DROP_TABLE && lex->tmp_table()) + DBUG_RETURN(FALSE); - /* Assuming that only temporary tables are modified. */ - DBUG_RETURN(FALSE); + /* Now, check thd->temporary_tables list */ + DBUG_RETURN(some_non_temp_table_to_be_updated(thd, all_tables)); } @@ -3794,7 +3787,7 @@ mysql_execute_command(THD *thd) #ifdef WITH_PARTITION_STORAGE_ENGINE { partition_info *part_info= thd->lex->part_info; - if (part_info && !(part_info= thd->lex->part_info->get_clone(thd))) + if (part_info && !(part_info= part_info->get_clone(thd))) { res= -1; goto end_with_restore_list; @@ -4271,7 +4264,7 @@ end_with_restore_list: if (up_result != 2) break; } - /* Fall through */ + /* fall through */ case SQLCOM_UPDATE_MULTI: { DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -4382,7 +4375,7 @@ end_with_restore_list: DBUG_PRINT("debug", ("Just after generate_incident()")); } #endif - /* fall through */ + /* fall through */ case SQLCOM_INSERT: { WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 6e4da0fbbf2..3f06c950472 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2005, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, SkySQL Ab. +/* Copyright (c) 2005, 2017, Oracle and/or its affiliates. + Copyright (c) 2009, 2017, 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 @@ -6561,7 +6561,8 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, lpt->alter_info= alter_info; lpt->create_info= create_info; lpt->db_options= create_info->table_options; - if (create_info->row_type == ROW_TYPE_DYNAMIC) + if (create_info->row_type != ROW_TYPE_FIXED && + create_info->row_type != ROW_TYPE_DEFAULT) lpt->db_options|= HA_OPTION_PACK_RECORD; lpt->table= table; lpt->key_info_buffer= 0; @@ -8073,6 +8074,7 @@ int create_partition_name(char *out, size_t outlen, const char *in1, } else transl_part= in2; + if (name_variant == NORMAL_PART_NAME) end= strxnmov(out, outlen-1, in1, "#P#", transl_part, NullS); else if (name_variant == TEMP_PART_NAME) @@ -8087,25 +8089,19 @@ int create_partition_name(char *out, size_t outlen, const char *in1, return 0; } - -/* - Create subpartition name - - SYNOPSIS - create_subpartition_name() - out:out The buffer for the created partition name string - must be *at least* of FN_REFLEN+1 bytes - in1 First part - in2 Second part - in3 Third part - name_variant Normal, temporary or renamed partition name - - RETURN VALUE - 0 if ok, error if name too long - - DESCRIPTION - This method is used to calculate the subpartition name, service routine to - the del_ren_cre_table method. +/** + Create subpartition name. This method is used to calculate the + subpartition name, service routine to the del_ren_cre_table method. + The output buffer size should be FN_REFLEN + 1(terminating '\0'). + + @param [out] out Created partition name string + @param in1 First part + @param in2 Second part + @param in3 Third part + @param name_variant Normal, temporary or renamed partition name + + @retval true Error. + @retval false Success. */ int create_subpartition_name(char *out, size_t outlen, @@ -8117,6 +8113,7 @@ int create_subpartition_name(char *out, size_t outlen, tablename_to_filename(in2, transl_part_name, FN_REFLEN); tablename_to_filename(in3, transl_subpart_name, FN_REFLEN); + if (name_variant == NORMAL_PART_NAME) end= strxnmov(out, outlen-1, in1, "#P#", transl_part_name, "#SP#", transl_subpart_name, NullS); diff --git a/sql/sql_partition.h b/sql/sql_partition.h index 2d0ec788332..acca6f61f01 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -1,7 +1,8 @@ #ifndef SQL_PARTITION_INCLUDED #define SQL_PARTITION_INCLUDED -/* Copyright (c) 2006, 2013, Oracle and/or its affiliates. +/* Copyright (c) 2006, 2017, Oracle and/or its affiliates. + Copyright (c) 2011, 2017, 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/sql_plugin.cc b/sql/sql_plugin.cc index 17b68750bc6..2f0a5eaf9c9 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -228,7 +228,6 @@ 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; static bool initialized= 0; ulong dlopen_count; @@ -323,7 +322,6 @@ static void unlock_variables(THD *thd, struct system_variables *vars); static void cleanup_variables(struct system_variables *vars); static void plugin_vars_free_values(sys_var *vars); static void restore_ptr_backup(uint n, st_ptr_backup *backup); -static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin); static void intern_plugin_unlock(LEX *lex, plugin_ref plugin); static void reap_plugins(void); @@ -944,15 +942,17 @@ SHOW_COMP_OPTION plugin_status(const char *name, size_t len, int type) } -static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc) +static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc, + uint state_mask= PLUGIN_IS_READY | + PLUGIN_IS_UNINITIALIZED | + PLUGIN_IS_DELETED) { st_plugin_int *pi= plugin_ref_to_int(rc); DBUG_ENTER("intern_plugin_lock"); mysql_mutex_assert_owner(&LOCK_plugin); - if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED | - PLUGIN_IS_DELETED)) + if (pi->state & state_mask) { plugin_ref plugin; #ifdef DBUG_OFF @@ -1147,7 +1147,6 @@ static bool plugin_add(MEM_ROOT *tmp_root, if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) goto err; - plugin_array_version++; if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr)) tmp_plugin_ptr->state= PLUGIN_IS_FREED; init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096, MYF(0)); @@ -1247,7 +1246,6 @@ static void plugin_del(struct st_plugin_int *plugin) my_hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin); plugin_dl_del(plugin->plugin_dl); plugin->state= PLUGIN_IS_FREED; - plugin_array_version++; free_root(&plugin->mem_root, MYF(0)); } else @@ -1865,11 +1863,11 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) switch ((*(p++)= *(list++))) { case '\0': list= NULL; /* terminate the loop */ -#ifndef __WIN__ /* fall through */ + case ';': +#ifndef __WIN__ case ':': /* can't use this as delimiter as it may be drive letter */ #endif - case ';': str->str[str->length]= '\0'; if (str == &name) // load all plugins in named module { @@ -2341,64 +2339,55 @@ error: bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, int type, uint state_mask, void *arg) { - uint idx, total; - struct st_plugin_int *plugin, **plugins; - int version=plugin_array_version; + uint idx, total= 0; + struct st_plugin_int *plugin; + plugin_ref *plugins; + my_bool res= FALSE; DBUG_ENTER("plugin_foreach_with_mask"); if (!initialized) DBUG_RETURN(FALSE); - state_mask= ~state_mask; // do it only once - mysql_mutex_lock(&LOCK_plugin); - total= type == MYSQL_ANY_PLUGIN ? plugin_array.elements - : plugin_hash[type].records; /* Do the alloca out here in case we do have a working alloca: - leaving the nested stack frame invalidates alloca allocation. + leaving the nested stack frame invalidates alloca allocation. */ - plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin)); if (type == MYSQL_ANY_PLUGIN) { - for (idx= 0; idx < total; idx++) + plugins= (plugin_ref*) my_alloca(plugin_array.elements * sizeof(plugin_ref)); + for (idx= 0; idx < plugin_array.elements; idx++) { plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); - plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; + if ((plugins[total]= intern_plugin_lock(0, plugin_int_to_ref(plugin), + state_mask))) + total++; } } else { HASH *hash= plugin_hash + type; - for (idx= 0; idx < total; idx++) + plugins= (plugin_ref*) my_alloca(hash->records * sizeof(plugin_ref)); + for (idx= 0; idx < hash->records; idx++) { plugin= (struct st_plugin_int *) my_hash_element(hash, idx); - plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; + if ((plugins[total]= intern_plugin_lock(0, plugin_int_to_ref(plugin), + state_mask))) + total++; } } mysql_mutex_unlock(&LOCK_plugin); for (idx= 0; idx < total; idx++) { - if (unlikely(version != plugin_array_version)) - { - mysql_mutex_lock(&LOCK_plugin); - for (uint i=idx; i < total; i++) - if (plugins[i] && plugins[i]->state & state_mask) - plugins[i]=0; - mysql_mutex_unlock(&LOCK_plugin); - } - plugin= plugins[idx]; /* It will stop iterating on first engine error when "func" returns TRUE */ - if (plugin && func(thd, plugin_int_to_ref(plugin), arg)) - goto err; + if ((res= func(thd, plugins[idx], arg))) + break; } + plugin_unlock_list(0, plugins, total); my_afree(plugins); - DBUG_RETURN(FALSE); -err: - my_afree(plugins); - DBUG_RETURN(TRUE); + DBUG_RETURN(res); } @@ -3525,7 +3514,6 @@ bool sys_var_pluginvar::global_update(THD *thd, set_var *var) options->max_value= getopt_double2ulonglong((opt)->max_val); \ options->block_size= (long) (opt)->blk_sz; - void plugin_opt_set_limits(struct my_option *options, const struct st_mysql_sys_var *opt) { diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 6724346a490..19c714cfc01 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1379,7 +1379,8 @@ static bool mysql_test_insert(Prepared_statement *stmt, my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); goto error; } - if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), + *values, MARK_COLUMNS_NONE, 0, NULL, 0)) goto error; } } @@ -1470,7 +1471,7 @@ static int mysql_test_update(Prepared_statement *stmt, #endif thd->lex->select_lex.no_wrap_view_item= TRUE; res= setup_fields(thd, Ref_ptr_array(), - select->item_list, MARK_COLUMNS_READ, 0, 0); + select->item_list, MARK_COLUMNS_READ, 0, NULL, 0); thd->lex->select_lex.no_wrap_view_item= FALSE; if (res) goto error; @@ -1482,7 +1483,7 @@ static int mysql_test_update(Prepared_statement *stmt, table_list->register_want_access(SELECT_ACL); #endif if (setup_fields(thd, Ref_ptr_array(), - stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0) || + stmt->lex->value_list, MARK_COLUMNS_NONE, 0, NULL, 0) || check_unique_table(thd, table_list)) goto error; /* TODO: here we should send types of placeholders to the client. */ @@ -1655,7 +1656,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt, DT_PREPARE | DT_CREATE)) DBUG_RETURN(TRUE); DBUG_RETURN(setup_fields(thd, Ref_ptr_array(), - *values, MARK_COLUMNS_NONE, 0, 0)); + *values, MARK_COLUMNS_NONE, 0, NULL, 0)); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f4f0e46afed..46e1a912250 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -804,7 +804,7 @@ JOIN::prepare(TABLE_LIST *tables_init, thd->lex->current_select->context_analysis_place; thd->lex->current_select->context_analysis_place= SELECT_LIST; if (setup_fields(thd, ref_ptrs, fields_list, MARK_COLUMNS_READ, - &all_fields, 1)) + &all_fields, &select_lex->pre_fix, 1)) DBUG_RETURN(-1); thd->lex->current_select->context_analysis_place= save_place; @@ -14708,10 +14708,23 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top, nested_join= table->nested_join; if (table->sj_on_expr && !in_sj) { - /* - If this is a semi-join that is not contained within another semi-join, - leave it intact (otherwise it is flattened) - */ + /* + If this is a semi-join that is not contained within another semi-join + leave it intact (otherwise it is flattened) + */ + /* + Make sure that any semi-join appear in + the join->select_lex->sj_nests list only once + */ + List_iterator_fast<TABLE_LIST> sj_it(join->select_lex->sj_nests); + TABLE_LIST *sj_nest; + while ((sj_nest= sj_it++)) + { + if (table == sj_nest) + break; + } + if (sj_nest) + continue; join->select_lex->sj_nests.push_back(table, join->thd->mem_root); /* diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 579cbcd878e..c7ba6705cb0 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -139,6 +139,12 @@ bool get_lookup_field_values(THD *, COND *, TABLE_LIST *, LOOKUP_FIELD_VALUES *) ** List all table types supported ***************************************************************************/ + +static bool is_show_command(THD *thd) +{ + return sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND; +} + static int make_version_string(char *buf, int buf_length, uint version) { return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff); @@ -278,7 +284,7 @@ int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond) TABLE *table= tables->table; if (plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN, - ~PLUGIN_IS_FREED, table)) + ~(PLUGIN_IS_FREED | PLUGIN_IS_DYING), table)) DBUG_RETURN(1); DBUG_RETURN(0); @@ -986,13 +992,20 @@ find_files(THD *thd, Dynamic_array<LEX_STRING*> *files, LEX_STRING *db, if (tl.add_file(file->name)) goto err; } - tl.sort(); } else { if (ha_discover_table_names(thd, db, dirp, &tl, false)) goto err; } +#if MYSQL_VERSION_ID < 100300 + /* incomplete optimization, but a less drastic change in GA version */ + if (!thd->lex->select_lex.order_list.elements && + !thd->lex->select_lex.group_list.elements) +#else + if (is_show_command(thd)) +#endif + tl.sort(); DBUG_PRINT("info",("found: %zu files", files->elements())); my_dirend(dirp); @@ -4137,7 +4150,7 @@ make_table_name_list(THD *thd, Dynamic_array<LEX_STRING*> *table_names, */ if (res == FIND_FILES_DIR) { - if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) + if (is_show_command(thd)) return 1; thd->clear_error(); return 2; @@ -5685,7 +5698,8 @@ int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond) DBUG_ENTER("fill_schema_engines"); if (plugin_foreach_with_mask(thd, iter_schema_engines, MYSQL_STORAGE_ENGINE_PLUGIN, - ~PLUGIN_IS_FREED, tables->table)) + ~(PLUGIN_IS_FREED | PLUGIN_IS_DYING), + tables->table)) DBUG_RETURN(1); DBUG_RETURN(0); } @@ -5957,13 +5971,13 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, val_int() == TYPE_ENUM_PROCEDURE)) return 0; - if ((lex->sql_command == SQLCOM_SHOW_STATUS_PROC && + if (!is_show_command(thd) || + (lex->sql_command == SQLCOM_SHOW_STATUS_PROC && proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int() == TYPE_ENUM_PROCEDURE) || (lex->sql_command == SQLCOM_SHOW_STATUS_FUNC && proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int() == - TYPE_ENUM_FUNCTION) || - (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0) + TYPE_ENUM_FUNCTION)) { restore_record(table, s->default_values); if (!wild || !wild[0] || !wild_case_compare(system_charset_info, @@ -6088,6 +6102,10 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) DBUG_RETURN(1); } + /* Disable padding temporarily so it doesn't break the query */ + ulonglong sql_mode_was = thd->variables.sql_mode; + thd->variables.sql_mode &= ~MODE_PAD_CHAR_TO_FULL_LENGTH; + if (proc_table->file->ha_index_init(0, 1)) { res= 1; @@ -6123,6 +6141,7 @@ err: (void) proc_table->file->ha_index_end(); close_system_tables(thd, &open_tables_state_backup); + thd->variables.sql_mode = sql_mode_was; DBUG_RETURN(res); } @@ -7706,7 +7725,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) tmp_table_param->field_count= field_count; tmp_table_param->schema_table= 1; SELECT_LEX *select_lex= thd->lex->current_select; - bool keep_row_order= sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND; + bool keep_row_order= is_show_command(thd); if (!(table= create_tmp_table(thd, tmp_table_param, field_list, (ORDER*) 0, 0, 0, (select_lex->options | thd->variables.option_bits | diff --git a/sql/sql_table.cc b/sql/sql_table.cc index db9340d7977..c112b01ba36 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4141,7 +4141,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (!sql_field->default_value && !sql_field->has_default_function() && (sql_field->flags & NOT_NULL_FLAG) && - !is_timestamp_type(sql_field->sql_type)) + (!is_timestamp_type(sql_field->sql_type) || + opt_explicit_defaults_for_timestamp)) { sql_field->flags|= NO_DEFAULT_VALUE_FLAG; sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT; @@ -4150,6 +4151,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (thd->variables.sql_mode & MODE_NO_ZERO_DATE && !sql_field->default_value && !sql_field->vcol_info && is_timestamp_type(sql_field->sql_type) && + !opt_explicit_defaults_for_timestamp && (sql_field->flags & NOT_NULL_FLAG) && (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD)) { @@ -7051,7 +7053,6 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, case Alter_info::LEAVE_AS_IS: if (!indexes_were_disabled) break; - /* disabled indexes */ /* fall through */ case Alter_info::DISABLE: error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index b1069efbbc8..a2cfcbabc95 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -359,7 +359,7 @@ int mysql_update(THD *thd, table_list->grant.want_privilege= table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); #endif - if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, NULL, 0)) { free_underlaid_joins(thd, select_lex); DBUG_RETURN(1); /* purecov: inspected */ @@ -1691,7 +1691,7 @@ int multi_update::prepare(List<Item> ¬_used_values, */ int error= setup_fields(thd, Ref_ptr_array(), - *values, MARK_COLUMNS_READ, 0, 0); + *values, MARK_COLUMNS_READ, 0, NULL, 0); ti.rewind(); while ((table_ref= ti++)) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ded0332bc53..434cd10d1b9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4772,17 +4772,11 @@ size_number: switch (end_ptr[0]) { case 'g': - case 'G': - text_shift_number+=10; - /* fall through */ + case 'G': text_shift_number+=30; break; case 'm': - case 'M': - text_shift_number+=10; - /* fall through */ + case 'M': text_shift_number+=20; break; case 'k': - case 'K': - text_shift_number+=10; - break; + case 'K': text_shift_number+=10; break; default: my_yyabort_error((ER_WRONG_SIZE_NUMBER, MYF(0))); } diff --git a/sql/table.h b/sql/table.h index 22846e05bde..7e3f94a60ff 100644 --- a/sql/table.h +++ b/sql/table.h @@ -36,6 +36,7 @@ /* Structs that defines the TABLE */ class Item; /* Needed by ORDER */ +typedef Item (*Item_ptr); class Item_subselect; class Item_field; class GRANT_TABLE; @@ -2560,7 +2561,7 @@ typedef struct st_nested_join table_map sj_depends_on; /* Outer non-trivially correlated tables */ table_map sj_corr_tables; - List<Item> sj_outer_expr_list; + List<Item_ptr> sj_outer_expr_list; /** True if this join nest node is completely covered by the query execution plan. This means two things. |