diff options
author | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2018-01-24 12:29:31 +0200 |
---|---|---|
committer | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2018-01-24 12:29:31 +0200 |
commit | d833bb65d53b9a4375fa71cc485b4719fdb0ee53 (patch) | |
tree | d1271339e1c3a660e4788a5c9913bfe54e0271f1 /sql | |
parent | e431d90065d277e62fa4f81a1654790f58a84146 (diff) | |
parent | 76577e1e2602f3c30859a176808c433a263e1b0a (diff) | |
download | mariadb-git-d833bb65d53b9a4375fa71cc485b4719fdb0ee53.tar.gz |
Merge remote-tracking branch '5.5' into 10.0
Diffstat (limited to 'sql')
36 files changed, 231 insertions, 94 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 2e63dac6f02..8cd08d61e29 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (c) 2006, 2014, Oracle and/or its affiliates. -# Copyright (c) 2010, 2015, MariaDB +# Copyright (c) 2010, 2018, 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/field.cc b/sql/field.cc index f4aaaca69d6..c36fff06a07 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1873,7 +1873,7 @@ uint Field::fill_cache_field(CACHE_FIELD *copy) { uint store_length; copy->str= ptr; - copy->length= pack_length(); + copy->length= pack_length_in_rec(); copy->field= this; if (flags & BLOB_FLAG) { @@ -8711,7 +8711,7 @@ int Field_bit::key_cmp(const uchar *str, uint length) str++; length--; } - return memcmp(ptr, str, length); + return memcmp(ptr, str, bytes_in_rec); } diff --git a/sql/field.h b/sql/field.h index c99327bd068..5286dd49dde 100644 --- a/sql/field.h +++ b/sql/field.h @@ -301,7 +301,7 @@ public: { return alloc_root(mem_root, size); } static void *operator new(size_t size) throw () { return sql_alloc(size); } - static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); } + static void operator delete(void *ptr_arg, size_t size) { TRASH_FREE(ptr_arg, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { DBUG_ASSERT(0); } diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 5006266eaed..ec3e6c3aaaf 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -590,7 +590,7 @@ void Copy_field::set(uchar *to,Field *from) { from_ptr=from->ptr; to_ptr=to; - from_length=from->pack_length(); + from_length=from->pack_length_in_rec(); if (from->maybe_null()) { from_null_ptr=from->null_ptr; @@ -641,9 +641,9 @@ void Copy_field::set(Field *to,Field *from,bool save) from_field=from; to_field=to; from_ptr=from->ptr; - from_length=from->pack_length(); + from_length=from->pack_length_in_rec(); to_ptr= to->ptr; - to_length=to_field->pack_length(); + to_length=to_field->pack_length_in_rec(); // set up null handling from_null_ptr=to_null_ptr=0; diff --git a/sql/item.cc b/sql/item.cc index 3b8ca94642e..5f8cf6c80f7 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2010, 2017, MariaDB Corporation + Copyright (c) 2010, 2018, MariaDB Corporation 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 @@ -8480,7 +8480,7 @@ Item *Item_default_value::transform(Item_transformer transformer, uchar *args) bool Item_insert_value::eq(const Item *item, bool binary_cmp) const { return item->type() == INSERT_VALUE_ITEM && - ((Item_default_value *)item)->arg->eq(arg, binary_cmp); + ((Item_insert_value *)item)->arg->eq(arg, binary_cmp); } @@ -10004,7 +10004,7 @@ const char *dbug_print_item(Item *item) if (!item) return "(Item*)NULL"; item->print(&str ,QT_ORDINARY); - if (str.c_ptr() == buf) + if (str.c_ptr_safe() == buf) return buf; else return "Couldn't fit into buffer"; diff --git a/sql/item.h b/sql/item.h index 0470183faad..7856328a33b 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2,7 +2,7 @@ #define SQL_ITEM_INCLUDED /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB + Copyright (c) 2009, 2018, MariaDB Corporation 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 @@ -49,6 +49,12 @@ bool trace_unsupported_by_check_vcol_func_processor(const char *where) return trace_unsupported_func(where, "check_vcol_func_processor"); } +#ifdef DBUG_OFF +static inline const char *dbug_print_item(Item *item) { return NULL; } +#else +extern const char *dbug_print_item(Item *item); +#endif + class Protocol; struct TABLE_LIST; void item_init(void); /* Init item functions */ @@ -595,7 +601,7 @@ public: { return sql_alloc(size); } static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } - static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} enum Type {FIELD_ITEM= 0, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM, diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1df19e75d65..d1c62859d20 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1445,6 +1445,7 @@ bool Item_in_optimizer::is_top_level_item() void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) { + DBUG_ASSERT(fixed); /* This will re-calculate attributes of our Item_in_subselect: */ Item_bool_func::fix_after_pullout(new_parent, ref, merge); @@ -1468,6 +1469,33 @@ bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg) } +void Item_in_optimizer::print(String *str, enum_query_type query_type) +{ + restore_first_argument(); + Item_func::print(str, query_type); +} + + +/** + "Restore" first argument before fix_fields() call (after it is harmless). + + @Note: Main pointer to left part of IN/ALL/ANY subselect is subselect's + lest_expr (see Item_in_optimizer::fix_left) so changes made during + fix_fields will be rolled back there which can make + Item_in_optimizer::args[0] unusable on second execution before fix_left() + call. This call fix the pointer. +*/ + +void Item_in_optimizer::restore_first_argument() +{ + if (args[1]->type() == Item::SUBSELECT_ITEM && + ((Item_subselect *)args[1])->is_in_predicate()) + { + args[0]= ((Item_in_subselect *)args[1])->left_expr; + } +} + + bool Item_in_optimizer::fix_left(THD *thd) { DBUG_ENTER("Item_in_optimizer::fix_left"); @@ -1645,6 +1673,7 @@ Item *Item_in_optimizer::expr_cache_insert_transformer(uchar *thd_arg) { THD *thd= (THD*) thd_arg; DBUG_ENTER("Item_in_optimizer::expr_cache_insert_transformer"); + DBUG_ASSERT(fixed); if (invisible_mode()) DBUG_RETURN(this); @@ -1669,6 +1698,7 @@ Item *Item_in_optimizer::expr_cache_insert_transformer(uchar *thd_arg) void Item_in_optimizer::get_cache_parameters(List<Item> ¶meters) { + DBUG_ASSERT(fixed); /* Add left expression to the list of the parameters of the subquery */ if (!invisible_mode()) { @@ -1906,6 +1936,7 @@ Item *Item_in_optimizer::transform(Item_transformer transformer, { Item *new_item; + DBUG_ASSERT(fixed); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); DBUG_ASSERT(arg_count == 2); @@ -1957,6 +1988,7 @@ Item *Item_in_optimizer::transform(Item_transformer transformer, bool Item_in_optimizer::is_expensive_processor(uchar *arg) { + DBUG_ASSERT(fixed); return args[0]->is_expensive_processor(arg) || args[1]->is_expensive_processor(arg); } @@ -1964,6 +1996,7 @@ bool Item_in_optimizer::is_expensive_processor(uchar *arg) bool Item_in_optimizer::is_expensive() { + DBUG_ASSERT(fixed); return args[0]->is_expensive() || args[1]->is_expensive(); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index a541282b898..6d81c7acc40 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -275,6 +275,8 @@ public: void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge); bool invisible_mode(); void reset_cache() { cache= NULL; } + virtual void print(String *str, enum_query_type query_type); + void restore_first_argument(); }; class Comp_creator @@ -1388,9 +1390,9 @@ public: bool arg_is_datetime_notnull_field() { Item **args= arguments(); - if (args[0]->type() == Item::FIELD_ITEM) + if (args[0]->real_item()->type() == Item::FIELD_ITEM) { - Field *field=((Item_field*) args[0])->field; + Field *field=((Item_field*) args[0]->real_item())->field; if (((field->type() == MYSQL_TYPE_DATE) || (field->type() == MYSQL_TYPE_DATETIME)) && diff --git a/sql/item_func.cc b/sql/item_func.cc index 458db430222..002eef67667 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -594,6 +594,7 @@ my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value) } +#ifdef HAVE_DLOPEN void Item_udf_func::fix_num_length_and_dec() { uint fl_length= 0; @@ -610,6 +611,7 @@ void Item_udf_func::fix_num_length_and_dec() max_length= float_length(NOT_FIXED_DEC); } } +#endif /** diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 3ee8a0e4970..c0d60d7ef8b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB + Copyright (c) 2009, 2018, MariaDB Corporation 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 @@ -252,9 +252,9 @@ String *Item_func_sha2::val_str_ascii(String *str) size_t input_len; uint digest_length= 0; + input_string= args[0]->val_str(str); str->set_charset(&my_charset_bin); - input_string= args[0]->val_str(str); if (input_string == NULL) { null_value= TRUE; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index eb1e1a3d9b7..8e8748be87a 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -5388,7 +5388,7 @@ int subselect_hash_sj_engine::exec() if (has_covering_null_row) { - DBUG_ASSERT(count_partial_match_columns = field_count); + DBUG_ASSERT(count_partial_match_columns == field_count); count_pm_keys= 0; } else if (has_covering_null_columns) diff --git a/sql/key.cc b/sql/key.cc index aaaea9391c6..414c3392cff 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -65,7 +65,8 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, i < (int) key_count ; i++, key_info++) { - if (key_info->key_part[0].offset == fieldpos) + if (key_info->key_part[0].offset == fieldpos && + key_info->key_part[0].field->type() != MYSQL_TYPE_BIT) { /* Found key. Calc keylength */ *key_length= *keypart= 0; return i; /* Use this key */ @@ -84,7 +85,8 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, j < key_info->user_defined_key_parts ; j++, key_part++) { - if (key_part->offset == fieldpos) + if (key_part->offset == fieldpos && + key_part->field->type() != MYSQL_TYPE_BIT) { *keypart= j; return i; /* Use this key */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d9320fa3bcf..435fb07279f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3913,7 +3913,7 @@ static int init_common_variables() /* TODO: remove this when my_time_t is 64 bit compatible */ if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time)) { - sql_print_error("This MySQL server doesn't support dates later then 2038"); + sql_print_error("This MySQL server doesn't support dates later than 2038"); return 1; } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 7b29e8b2b7b..f1d84e5c623 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2671,7 +2671,7 @@ public: /* Table read plans are allocated on MEM_ROOT and are never deleted */ static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* Never called */ } virtual ~TABLE_READ_PLAN() {} /* Remove gcc warning */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e4dc10b97d3..964f82e7331 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -9095,7 +9095,17 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) DBUG_PRINT("info",("Performing FULLTEXT search")); while ((ifm=li++)) - ifm->init_search(no_order); +#if MYSQL_VERSION_ID < 100213 + if (unlikely(!ifm->fixed)) + /* + it mean that clause where was FT function was removed, so we have + to remove the function from the list. + */ + li.remove(); + else +#endif + ifm->init_search(no_order); + } return 0; } diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 109150ef0d5..8bfef270f4a 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1191,7 +1191,11 @@ void Query_cache::end_of_result(THD *thd) #endif if (try_lock(thd, Query_cache::WAIT)) + { + if (is_disabled()) + query_cache_tls->first_query_block= NULL; // do not try again with QC DBUG_VOID_RETURN; + } query_block= query_cache_tls->first_query_block; if (query_block) @@ -1563,6 +1567,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", unlock(); + DEBUG_SYNC(thd, "wait_in_query_cache_store_query"); + // init_n_lock make query block locked BLOCK_UNLOCK_WR(query_block); } @@ -2741,13 +2747,17 @@ void Query_cache::make_disabled() This function frees all resources allocated by the cache. You have to call init_cache() before using the cache again. This function - requires the structure_guard_mutex to be locked. + requires the cache to be locked (LOCKED_NO_WAIT, lock_and_suspend) or + disabling. */ void Query_cache::free_cache() { DBUG_ENTER("Query_cache::free_cache"); + DBUG_ASSERT(m_cache_lock_status == LOCKED_NO_WAIT || + m_cache_status == DISABLE_REQUEST); + /* Destroy locks */ Query_cache_block *block= queries_blocks; if (block) @@ -2755,6 +2765,13 @@ void Query_cache::free_cache() do { Query_cache_query *query= block->query(); + /* + There will not be new requests but some maybe not finished yet, + so wait for them by trying lock/unlock + */ + BLOCK_LOCK_WR(block); + BLOCK_UNLOCK_WR(block); + mysql_rwlock_destroy(&query->lock); block= block->next; } while (block != queries_blocks); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 1f5c465a37a..c20f9054c2b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2436,6 +2436,9 @@ void THD::check_and_register_item_tree_change(Item **place, Item **new_value, MEM_ROOT *runtime_memroot) { Item_change_record *change; + DBUG_ENTER("THD::check_and_register_item_tree_change"); + DBUG_PRINT("enter", ("Register: %p (%p) <- %p (%p)", + *place, place, *new_value, new_value)); I_List_iterator<Item_change_record> it(change_list); while ((change= it++)) { @@ -2445,6 +2448,7 @@ void THD::check_and_register_item_tree_change(Item **place, Item **new_value, if (change) nocheck_register_item_tree_change(place, change->old_value, runtime_memroot); + DBUG_VOID_RETURN; } @@ -2452,17 +2456,13 @@ void THD::rollback_item_tree_changes() { I_List_iterator<Item_change_record> it(change_list); Item_change_record *change; - DBUG_ENTER("rollback_item_tree_changes"); while ((change= it++)) { - DBUG_PRINT("info", ("revert %p -> %p", - change->old_value, (*change->place))); *change->place= change->old_value; } /* We can forget about changes memory: it's allocated in runtime memroot */ change_list.empty(); - DBUG_VOID_RETURN; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 3aeb8127030..518e88fcd1c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1096,6 +1096,30 @@ typedef struct st_xid_state { bool in_thd; /* Error reported by the Resource Manager (RM) to the Transaction Manager. */ uint rm_error; + + /** + Check that XA transaction has an uncommitted work. Report an error + to the user in case when there is an uncommitted work for XA transaction. + + @return result of check + @retval false XA transaction is NOT in state IDLE, PREPARED + or ROLLBACK_ONLY. + @retval true XA transaction is in state IDLE or PREPARED + or ROLLBACK_ONLY. + */ + + bool check_has_uncommitted_xa() const + { + if (xa_state == XA_IDLE || + xa_state == XA_PREPARED || + xa_state == XA_ROLLBACK_ONLY) + { + my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]); + return true; + } + return false; + } + } XID_STATE; extern mysql_mutex_t LOCK_xid_cache; @@ -3241,10 +3265,14 @@ public: void change_item_tree(Item **place, Item *new_value) { + DBUG_ENTER("THD::change_item_tree"); + DBUG_PRINT("enter", ("Register: %p (%p) <- %p", + *place, place, new_value)); /* TODO: check for OOM condition here */ if (!stmt_arena->is_conventional()) nocheck_register_item_tree_change(place, *place, mem_root); *place= new_value; + DBUG_VOID_RETURN; } /** Make change in item tree after checking whether it needs registering diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index d8684086e68..ff06d67fc29 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -210,7 +210,7 @@ void Server_side_cursor::operator delete(void *ptr, size_t size) MEM_ROOT own_root= *cursor->mem_root; DBUG_ENTER("Server_side_cursor::operator delete"); - TRASH(ptr, size); + TRASH_FREE(ptr, size); /* If this cursor has never been opened mem_root is empty. Otherwise mem_root points to the memory the cursor object was allocated in. diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index e9928572142..7ad0b4b4c69 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -367,7 +367,11 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) derived->get_unit())); if (derived->merged) + { + + DBUG_PRINT("info", ("Irreversibly merged: exit")); DBUG_RETURN(FALSE); + } if (dt_select->uncacheable & UNCACHEABLE_RAND) { @@ -678,6 +682,17 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) unit->derived= derived; + /* + Above cascade call of prepare is important for PS protocol, but after it + is called we can check if we really need prepare for this derived + */ + if (derived->merged) + { + DBUG_PRINT("info", ("Irreversibly merged: exit")); + DBUG_RETURN(FALSE); + } + + derived->fill_me= FALSE; if (!(derived->derived_result= new select_union)) @@ -807,6 +822,11 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", (derived->alias ? derived->alias : "<NULL>"), derived->get_unit())); + if (derived->merged) + { + DBUG_PRINT("info", ("Irreversibly merged: exit")); + DBUG_RETURN(FALSE); + } if (unit->optimized) DBUG_RETURN(FALSE); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index f4935fbc234..6036bbeb8b1 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2010, 2016, MariaDB + Copyright (c) 2010, 2018, MariaDB Corporation 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_join_cache.cc b/sql/sql_join_cache.cc index 7584b42c904..41f1c3e9e65 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -394,7 +394,7 @@ void JOIN_CACHE::create_flag_fields() TABLE *table= tab->table; /* Create a field for the null bitmap from table if needed */ - if (tab->used_null_fields || tab->used_uneven_bit_fields) + if (tab->used_null_fields || tab->used_uneven_bit_fields) length+= add_flag_field_to_join_cache(table->null_flags, table->s->null_bytes, ©); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 05819f1a973..6c7e57aa730 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB + Copyright (c) 2009, 2018, MariaDB Corporation 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_lex.h b/sql/sql_lex.h index c9ce84e51c0..3fed9808f57 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2016, MariaDB + Copyright (c) 2010, 2018, MariaDB Corporation 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 @@ -477,7 +477,7 @@ public: } static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} // Ensures that at least all members used during cleanup() are initialized. @@ -2959,7 +2959,7 @@ struct st_lex_local: public LEX return (void*) alloc_root(mem_root, (uint) size); } static void operator delete(void *ptr,size_t size) - { TRASH(ptr, size); } + { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* Never called */ } }; diff --git a/sql/sql_lifo_buffer.h b/sql/sql_lifo_buffer.h index feec4aeb4c2..f551cc48c23 100644 --- a/sql/sql_lifo_buffer.h +++ b/sql/sql_lifo_buffer.h @@ -84,7 +84,7 @@ public: start= start_arg; end= end_arg; if (end != start) - TRASH(start, end - start); + TRASH_ALLOC(start, end - start); reset(); } @@ -224,7 +224,7 @@ public: { DBUG_ASSERT(unused_end >= unused_start); DBUG_ASSERT(end == unused_start); - TRASH(unused_start, unused_end - unused_start); + TRASH_ALLOC(unused_start, unused_end - unused_start); end= unused_end; } /* Return pointer to start of the memory area that is occupied by the data */ diff --git a/sql/sql_list.h b/sql/sql_list.h index 7538f69766d..08667bed02a 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -41,12 +41,12 @@ public: { return alloc_root(mem_root, size); } static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } - static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr, size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* never called */ } static void operator delete[](void *ptr, MEM_ROOT *mem_root) { /* never called */ } - static void operator delete[](void *ptr, size_t size) { TRASH(ptr, size); } + static void operator delete[](void *ptr, size_t size) { TRASH_FREE(ptr, size); } #ifdef HAVE_valgrind bool dummy; inline Sql_alloc() :dummy(0) {} diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 778f2a46951..c1b49e64829 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -260,7 +260,7 @@ public: static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, size); } static void operator delete(void *ptr_arg,size_t size) - { TRASH(ptr_arg, size); } + { TRASH_FREE(ptr_arg, size); } sys_var_pluginvar(sys_var_chain *chain, const char *name_arg, struct st_mysql_sys_var *plugin_var_arg, @@ -467,6 +467,11 @@ static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl) sizeof(struct st_plugin_dl)); DBUG_RETURN(tmp); } +#else +static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *) +{ + return 0; +} #endif /* HAVE_DLOPEN */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3c2b62a6540..fd8ff6eb016 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016 Oracle and/or its affiliates. - Copyright (c) 2009, 2016 MariaDB + Copyright (c) 2009, 2018 MariaDB Corporation 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 @@ -280,6 +280,11 @@ enum enum_exec_or_opt {WALK_OPTIMIZATION_TABS , WALK_EXECUTION_TABS}; JOIN_TAB *first_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind); JOIN_TAB *next_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind, JOIN_TAB *tab); +static bool +find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, + ORDER *order, List<Item> &fields, List<Item> &all_fields, + bool is_group_field, bool add_to_all_fields); + static double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, table_map rem_tables); @@ -333,7 +338,6 @@ bool dbug_user_var_equals_int(THD *thd, const char *name, int value) } #endif - /** This handles SELECT with and without UNION. */ @@ -697,6 +701,9 @@ JOIN::prepare(Item ***rref_pointer_array, join_list= &select_lex->top_join_list; union_part= unit_arg->is_union(); + // simple check that we got usable conds + dbug_print_item(conds); + if (select_lex->handle_derived(thd->lex, DT_PREPARE)) DBUG_RETURN(1); @@ -759,12 +766,11 @@ JOIN::prepare(Item ***rref_pointer_array, } table_count= select_lex->leaf_tables.elements; - + TABLE_LIST *tbl; List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables); while ((tbl= li++)) { - //table_count++; /* Count the number of tables in the join. */ /* If the query uses implicit grouping where the select list contains both aggregate functions and non-aggregate fields, any non-aggregated field @@ -799,9 +805,15 @@ JOIN::prepare(Item ***rref_pointer_array, /* Resolve the ORDER BY that was skipped, then remove it. */ if (skip_order_by && select_lex != select_lex->master_unit()->global_parameters) { - if (setup_order(thd, (*rref_pointer_array), tables_list, fields_list, - all_fields, select_lex->order_list.first)) - DBUG_RETURN(-1); + thd->where= "order clause"; + for (ORDER *order= select_lex->order_list.first; order; order= order->next) + { + /* Don't add the order items to all fields. Just resolve them to ensure + the query is valid, we'll drop them immediately after. */ + if (find_order_in_list(thd, *rref_pointer_array, tables_list, order, + fields_list, all_fields, false, false)) + DBUG_RETURN(-1); + } select_lex->order_list.empty(); } @@ -2208,8 +2220,11 @@ bool JOIN::shrink_join_buffers(JOIN_TAB *jt, ulonglong curr_space, ulonglong needed_space) { + JOIN_TAB *tab; JOIN_CACHE *cache; - for (JOIN_TAB *tab= join_tab+const_tables; tab < jt; tab++) + for (tab= first_linear_tab(this, WITHOUT_BUSH_ROOTS, WITHOUT_CONST_TABLES); + tab != jt; + tab= next_linear_tab(this, tab, WITHOUT_BUSH_ROOTS)) { cache= tab->cache; if (cache) @@ -10239,7 +10254,7 @@ void JOIN::drop_unused_derived_keys() table->use_index(tab->ref.key); if (table->s->keys) { - if (tab->ref.key >= 0) + if (tab->ref.key >= 0 && tab->ref.key < MAX_KEY) tab->ref.key= 0; else table->s->keys= 0; @@ -12049,8 +12064,8 @@ static void update_depend_map(JOIN *join) uint i; for (i=0 ; i < ref->key_parts ; i++,item++) depend_map|=(*item)->used_tables(); - ref->depend_map=depend_map & ~OUTER_REF_TABLE_BIT; depend_map&= ~OUTER_REF_TABLE_BIT; + ref->depend_map= depend_map; for (JOIN_TAB **tab=join->map2table; depend_map ; tab++,depend_map>>=1 ) @@ -12355,7 +12370,7 @@ public: } static void operator delete(void *ptr __attribute__((unused)), size_t size __attribute__((unused))) - { TRASH(ptr, size); } + { TRASH_FREE(ptr, size); } Item *and_level; Item_bool_func2 *cmp_func; @@ -15189,14 +15204,14 @@ internal_remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) */ Item **args= ((Item_func_isnull*) cond)->arguments(); - Field *field=((Item_field*) args[0])->field; + Field *field=((Item_field*) (args[0]->real_item()))->field; Item *item0= new(thd->mem_root) Item_int((longlong)0, 1); Item *eq_cond= new(thd->mem_root) Item_func_eq(args[0], item0); if (!eq_cond) return cond; - if (field->table->pos_in_table_list->is_inner_table_of_outer_join()) + if (field->table->pos_in_table_list->is_inner_table_of_outer_join()) { // outer join: transform "col IS NULL" to "col IS NULL or col=0" Item *or_cond= new(thd->mem_root) Item_cond_or(eq_cond, cond); @@ -16430,7 +16445,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, else { field->set_notnull(); - memcpy(field->ptr, orig_field->ptr, field->pack_length()); + memcpy(field->ptr, orig_field->ptr, field->pack_length_in_rec()); } orig_field->move_field_offset(-diff); // Back to record[0] } @@ -21457,7 +21472,10 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) SELECT list) @param[in,out] all_fields All select, group and order by fields @param[in] is_group_field True if order is a GROUP field, false if - ORDER by field + ORDER by field + @param[in] add_to_all_fields If the item is to be added to all_fields and + ref_pointer_array, this flag can be set to + false to stop the automatic insertion. @retval FALSE if OK @@ -21468,7 +21486,7 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) static bool find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ORDER *order, List<Item> &fields, List<Item> &all_fields, - bool is_group_field) + bool is_group_field, bool add_to_all_fields) { Item *order_item= *order->item; /* The item from the GROUP/ORDER caluse. */ Item::Type order_item_type; @@ -21588,6 +21606,9 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, thd->is_error())) return TRUE; /* Wrong field. */ + if (!add_to_all_fields) + return FALSE; + uint el= all_fields.elements; DBUG_ASSERT(all_fields.elements <= thd->lex->current_select->ref_pointer_array_size); @@ -21617,13 +21638,13 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, */ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, - List<Item> &fields, List<Item> &all_fields, ORDER *order) + List<Item> &fields, List<Item> &all_fields, ORDER *order) { thd->where="order clause"; for (; order; order=order->next) { if (find_order_in_list(thd, ref_pointer_array, tables, order, fields, - all_fields, FALSE)) + all_fields, FALSE, true)) return 1; } return 0; @@ -21675,7 +21696,7 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, for (ord= order; ord; ord= ord->next) { if (find_order_in_list(thd, ref_pointer_array, tables, ord, fields, - all_fields, TRUE)) + all_fields, TRUE, true)) return 1; (*ord->item)->marker= UNDEF_POS; /* Mark found */ if ((*ord->item)->with_sum_func) @@ -21994,6 +22015,7 @@ get_sort_by_table(ORDER *a,ORDER *b, List<TABLE_LIST> &tables, if (!map || (map & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT))) DBUG_RETURN(0); + map&= ~const_tables; while ((table= ti++) && !(map & table->table->map)) ; if (map != table->table->map) DBUG_RETURN(0); // More than one table diff --git a/sql/sql_select.h b/sql/sql_select.h index 4f1b7bd7e05..f000ce3ba74 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1770,7 +1770,7 @@ int get_quick_record(SQL_SELECT *select); SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length, SORT_FIELD *sortorder); int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, - List<Item> &fields, List <Item> &all_fields, ORDER *order); + List<Item> &fields, List <Item> &all_fields, ORDER *order); int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, List<Item> &fields, List<Item> &all_fields, ORDER *order, bool *hidden_group_fields); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8e97428e27a..965bed80148 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2245,7 +2245,7 @@ public: } static void operator delete(void *ptr __attribute__((unused)), size_t size __attribute__((unused))) - { TRASH(ptr, size); } + { TRASH_FREE(ptr, size); } ulong thread_id; time_t start_time; diff --git a/sql/sql_string.h b/sql/sql_string.h index 557d14a79f8..d60280a75ed 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -112,7 +112,7 @@ public: { (void) ptr_arg; (void) size; - TRASH(ptr_arg, size); + TRASH_FREE(ptr_arg, size); } static void operator delete(void *, MEM_ROOT *) { /* never called */ } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 46705827e41..bb745f41d26 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1830,7 +1830,8 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) #endif /* Write shadow frm file */ lpt->create_info->table_options= lpt->db_options; - LEX_CUSTRING frm= build_frm_image(lpt->thd, lpt->table_name, + LEX_CUSTRING frm= build_frm_image(lpt->thd, + lpt->table_name, lpt->create_info, lpt->alter_info->create_list, lpt->key_count, lpt->key_info_buffer, diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 16de451211f..01de3098783 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -941,22 +941,6 @@ bool st_select_lex_unit::cleanup() void st_select_lex_unit::reinit_exec_mechanism() { prepared= optimized= executed= 0; -#ifndef DBUG_OFF - if (is_union()) - { - List_iterator_fast<Item> it(item_list); - Item *field; - while ((field= it++)) - { - /* - we can't cleanup here, because it broke link to temporary table field, - but have to drop fixed flag to allow next fix_field of this field - during re-executing - */ - field->fixed= 0; - } - } -#endif } diff --git a/sql/table.cc b/sql/table.cc index 2758b4c4c03..0dbacf93d63 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1313,9 +1313,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, extra_rec_buf_length= uint2korr(frm_image+59); rec_buff_length= ALIGN_SIZE(share->reclength + 1 + extra_rec_buf_length); share->rec_buff_length= rec_buff_length; - if (!(record= (uchar *) alloc_root(&share->mem_root, - rec_buff_length))) + if (!(record= (uchar *) alloc_root(&share->mem_root, rec_buff_length))) goto err; /* purecov: inspected */ + MEM_NOACCESS(record, rec_buff_length); + MEM_UNDEFINED(record, share->reclength); share->default_values= record; memcpy(record, frm_image + record_offset, share->reclength); @@ -2606,6 +2607,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, if (!(record= (uchar*) alloc_root(&outparam->mem_root, share->rec_buff_length * records))) goto err; /* purecov: inspected */ + MEM_NOACCESS(record, share->rec_buff_length * records); if (records == 0) { @@ -2620,6 +2622,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, else outparam->record[1]= outparam->record[0]; // Safety } + MEM_UNDEFINED(outparam->record[0], share->reclength); + MEM_UNDEFINED(outparam->record[1], share->reclength); if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root, (uint) ((share->fields+1)* @@ -4055,7 +4059,7 @@ void TABLE::init(THD *thd, TABLE_LIST *tl) DBUG_ASSERT(key_read == 0); /* mark the record[0] uninitialized */ - TRASH(record[0], s->reclength); + TRASH_ALLOC(record[0], s->reclength); /* Initialize the null marker bits, to ensure that if we are doing a read diff --git a/sql/transaction.cc b/sql/transaction.cc index a70c075e142..1d5ad9aa1b0 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -490,12 +490,8 @@ bool trans_savepoint(THD *thd, LEX_STRING name) !opt_using_transactions) DBUG_RETURN(FALSE); - enum xa_states xa_state= thd->transaction.xid_state.xa_state; - if (xa_state != XA_NOTR && xa_state != XA_ACTIVE) - { - my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]); + if (thd->transaction.xid_state.check_has_uncommitted_xa()) DBUG_RETURN(TRUE); - } sv= find_savepoint(thd, name); @@ -570,12 +566,8 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name) DBUG_RETURN(TRUE); } - enum xa_states xa_state= thd->transaction.xid_state.xa_state; - if (xa_state != XA_NOTR) - { - my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]); + if (thd->transaction.xid_state.check_has_uncommitted_xa()) DBUG_RETURN(TRUE); - } /** Checking whether it is safe to release metadata locks acquired after diff --git a/sql/unireg.cc b/sql/unireg.cc index 12d3c265a86..90e55fea30c 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab. + Copyright (c) 2009, 2018, MariaDB Corporation 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 @@ -83,7 +83,7 @@ static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type, return extra2_write(pos, type, reinterpret_cast<LEX_STRING *>(str)); } -/** +/* Create a frm (table definition) file @param thd Thread handler @@ -156,7 +156,8 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, DBUG_PRINT("info", ("Options length: %u", options_len)); if (validate_comment_length(thd, &create_info->comment, TABLE_COMMENT_MAXLEN, - ER_TOO_LONG_TABLE_COMMENT, table)) + ER_TOO_LONG_TABLE_COMMENT, + table)) DBUG_RETURN(frm); /* If table comment is longer than TABLE_COMMENT_INLINE_MAXLEN bytes, @@ -246,6 +247,14 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, DBUG_ASSERT(pos == frm_ptr + uint2korr(fileinfo+6)); key_info_length= pack_keys(pos, keys, key_info, data_offset); + if (key_info_length > UINT_MAX16) + { + my_printf_error(ER_CANT_CREATE_TABLE, + "Cannot create table %`s: index information is too long. " + "Decrease number of indexes or use shorter index names or shorter comments.", + MYF(0), table); + goto err; + } int2store(forminfo+2, frm.length - filepos); int4store(fileinfo+10, frm.length); |