summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorVicențiu Ciorbaru <vicentiu@mariadb.org>2018-01-24 12:29:31 +0200
committerVicențiu Ciorbaru <vicentiu@mariadb.org>2018-01-24 12:29:31 +0200
commitd833bb65d53b9a4375fa71cc485b4719fdb0ee53 (patch)
treed1271339e1c3a660e4788a5c9913bfe54e0271f1 /sql
parente431d90065d277e62fa4f81a1654790f58a84146 (diff)
parent76577e1e2602f3c30859a176808c433a263e1b0a (diff)
downloadmariadb-git-d833bb65d53b9a4375fa71cc485b4719fdb0ee53.tar.gz
Merge remote-tracking branch '5.5' into 10.0
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt2
-rw-r--r--sql/field.cc4
-rw-r--r--sql/field.h2
-rw-r--r--sql/field_conv.cc6
-rw-r--r--sql/item.cc6
-rw-r--r--sql/item.h10
-rw-r--r--sql/item_cmpfunc.cc33
-rw-r--r--sql/item_cmpfunc.h6
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_strfunc.cc4
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/key.cc6
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/sql_base.cc12
-rw-r--r--sql/sql_cache.cc19
-rw-r--r--sql/sql_class.cc8
-rw-r--r--sql/sql_class.h28
-rw-r--r--sql/sql_cursor.cc2
-rw-r--r--sql/sql_derived.cc20
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_join_cache.cc2
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h6
-rw-r--r--sql/sql_lifo_buffer.h4
-rw-r--r--sql/sql_list.h4
-rw-r--r--sql/sql_plugin.cc7
-rw-r--r--sql/sql_select.cc60
-rw-r--r--sql/sql_select.h2
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/sql_string.h2
-rw-r--r--sql/sql_table.cc3
-rw-r--r--sql/sql_union.cc16
-rw-r--r--sql/table.cc10
-rw-r--r--sql/transaction.cc12
-rw-r--r--sql/unireg.cc15
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> &parameters)
{
+ 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,
&copy);
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);