summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@mariadb.com>2018-01-19 19:22:00 +0200
committerJan Lindström <jan.lindstrom@mariadb.com>2018-01-19 19:22:00 +0200
commitff979674e689266590672268692d85275a323e18 (patch)
treeab7becd376adda341b65a1a43a96f78eec7a541c /sql
parent9007ca68738cb11b24854aa1bfa12dcd204a459d (diff)
parentfafdac3365f4943e73bcefd0e0d07d69997a9724 (diff)
downloadmariadb-git-ff979674e689266590672268692d85275a323e18.tar.gz
Merge tag 'mariadb-5.5.59' into 5.5-galera
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt2
-rw-r--r--sql/field.cc6
-rw-r--r--sql/field_conv.cc6
-rw-r--r--sql/filesort.cc7
-rw-r--r--sql/item.cc7
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_cmpfunc.cc13
-rw-r--r--sql/item_cmpfunc.h1
-rw-r--r--sql/item_strfunc.cc4
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/opt_subselect.cc64
-rw-r--r--sql/partition_info.cc20
-rw-r--r--sql/partition_info.h1
-rw-r--r--sql/share/errmsg-utf8.txt44
-rw-r--r--sql/sql_base.cc12
-rw-r--r--sql/sql_cache.cc21
-rw-r--r--sql/sql_class.cc9
-rw-r--r--sql/sql_class.h24
-rw-r--r--sql/sql_derived.cc48
-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.h2
-rw-r--r--sql/sql_partition.cc11
-rw-r--r--sql/sql_select.cc15
-rw-r--r--sql/sql_yacc.yy14
-rw-r--r--sql/table.cc11
-rw-r--r--sql/table.h6
-rw-r--r--sql/transaction.cc12
-rw-r--r--sql/unireg.cc42
31 files changed, 303 insertions, 111 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 7fcdf601d81..8a6f32797e7 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 08ba437fa30..5b111ab5e03 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1758,7 +1758,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)
{
@@ -8422,7 +8422,7 @@ int Field_bit::cmp_max(const uchar *a, const uchar *b, uint max_len)
if ((flag= (int) (bits_a - bits_b)))
return flag;
}
- return memcmp(a, b, field_length);
+ return memcmp(a, b, bytes_in_rec);
}
@@ -8437,7 +8437,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_conv.cc b/sql/field_conv.cc
index 5781f1da576..09792aa1660 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -589,7 +589,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;
@@ -640,9 +640,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/filesort.cc b/sql/filesort.cc
index 38404b01cf7..5674786d8b2 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -210,7 +210,9 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
{
ulonglong keys= memory_available / (param.rec_length + sizeof(char*));
table_sort.keys= (uint) min(num_rows, keys);
- sort_buff_sz= table_sort.keys*(param.rec_length+sizeof(char*));
+ /* Cast to size_t to avoid overflow when result is greater than uint. */
+ sort_buff_sz= ((size_t)table_sort.keys) *
+ (param.rec_length + sizeof(char*));
set_if_bigger(sort_buff_sz, param.rec_length * MERGEBUFF2);
DBUG_EXECUTE_IF("make_sort_keys_alloc_fail",
@@ -914,7 +916,8 @@ static void make_sortkey(register SORTPARAM *param,
if (maybe_null)
*to++=1;
char *tmp_buffer= param->tmp_buffer ? param->tmp_buffer : (char*)to;
- String tmp(tmp_buffer, param->sort_length, cs);
+ String tmp(tmp_buffer, param->tmp_buffer ? param->sort_length :
+ sort_field->length, cs);
String *res= item->str_result(&tmp);
if (!res)
{
diff --git a/sql/item.cc b/sql/item.cc
index fa2e52bfd4a..576dce78299 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
@@ -4771,7 +4771,8 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
select->having_fix_field &&
- select_ref != not_found_item && !group_by_ref)
+ select_ref != not_found_item && !group_by_ref &&
+ !ref->alias_name_used)
{
/*
Report the error if fields was found only in the SELECT item list and
@@ -8491,7 +8492,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);
}
diff --git a/sql/item.h b/sql/item.h
index 4d0860af547..e01cf5384b9 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
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index ebe088e5092..62e76922c0e 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2001,6 +2001,19 @@ bool Item_func_opt_neg::eq(const Item *item, bool binary_cmp) const
}
+bool Item_func_interval::fix_fields(THD *thd, Item **ref)
+{
+ if (Item_int_func::fix_fields(thd, ref))
+ return true;
+ for (uint i= 0 ; i < row->cols(); i++)
+ {
+ if (row->element_index(i)->check_cols(1))
+ return true;
+ }
+ return false;
+}
+
+
void Item_func_interval::fix_length_and_dec()
{
uint rows= row->cols();
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index a8befa47b95..7b7ca9223fd 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -728,6 +728,7 @@ public:
{
allowed_arg_cols= 0; // Fetch this value from first argument
}
+ bool fix_fields(THD *, Item **);
longlong val_int();
void fix_length_and_dec();
const char *func_name() const { return "interval"; }
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 939e518e386..a7ca21b79de 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
@@ -265,9 +265,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 90f2bd5b9eb..46d41fd61e3 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -4927,7 +4927,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/item_sum.cc b/sql/item_sum.cc
index 9a2e2e6cd4c..709c2b6f7b5 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -3656,7 +3656,7 @@ void Item_func_group_concat::print(String *str, enum_query_type query_type)
}
}
str->append(STRING_WITH_LEN(" separator \'"));
- str->append(*separator);
+ str->append_for_single_quote(separator->ptr(), separator->length());
str->append(STRING_WITH_LEN("\')"));
}
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 69a5367cdf1..028bf44bf79 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -2687,7 +2687,8 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
LooseScan detector in best_access_path)
*/
remaining_tables &= ~new_join_tab->table->map;
- table_map dups_producing_tables;
+ table_map dups_producing_tables, prev_dups_producing_tables,
+ prev_sjm_lookup_tables;
if (idx == join->const_tables)
dups_producing_tables= 0;
@@ -2698,7 +2699,7 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
if ((emb_sj_nest= new_join_tab->emb_sj_nest))
dups_producing_tables |= emb_sj_nest->sj_inner_tables;
- Semi_join_strategy_picker **strategy;
+ Semi_join_strategy_picker **strategy, **prev_strategy;
if (idx == join->const_tables)
{
/* First table, initialize pickers */
@@ -2750,23 +2751,54 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
3. We have no clue what to do about fanount of semi-join Y.
*/
if ((dups_producing_tables & handled_fanout) ||
- (read_time < *current_read_time &&
+ (read_time < *current_read_time &&
!(handled_fanout & pos->inner_tables_handled_with_other_sjs)))
{
- /* Mark strategy as used */
- (*strategy)->mark_used();
- pos->sj_strategy= sj_strategy;
- if (sj_strategy == SJ_OPT_MATERIALIZE)
- join->sjm_lookup_tables |= handled_fanout;
+ DBUG_ASSERT(pos->sj_strategy != sj_strategy);
+ /*
+ If the strategy choosen first time or
+ the strategy replace strategy which was used to exectly the same
+ tables
+ */
+ if (pos->sj_strategy == SJ_OPT_NONE ||
+ handled_fanout ==
+ (prev_dups_producing_tables ^ dups_producing_tables))
+ {
+ prev_strategy= strategy;
+ if (pos->sj_strategy == SJ_OPT_NONE)
+ {
+ prev_dups_producing_tables= dups_producing_tables;
+ prev_sjm_lookup_tables= join->sjm_lookup_tables;
+ }
+ /* Mark strategy as used */
+ (*strategy)->mark_used();
+ pos->sj_strategy= sj_strategy;
+ if (sj_strategy == SJ_OPT_MATERIALIZE)
+ join->sjm_lookup_tables |= handled_fanout;
+ else
+ join->sjm_lookup_tables &= ~handled_fanout;
+ *current_read_time= read_time;
+ *current_record_count= rec_count;
+ dups_producing_tables &= ~handled_fanout;
+ //TODO: update bitmap of semi-joins that were handled together with
+ // others.
+ if (is_multiple_semi_joins(join, join->positions, idx,
+ handled_fanout))
+ pos->inner_tables_handled_with_other_sjs |= handled_fanout;
+ }
else
- join->sjm_lookup_tables &= ~handled_fanout;
- *current_read_time= read_time;
- *current_record_count= rec_count;
- dups_producing_tables &= ~handled_fanout;
- //TODO: update bitmap of semi-joins that were handled together with
- // others.
- if (is_multiple_semi_joins(join, join->positions, idx, handled_fanout))
- pos->inner_tables_handled_with_other_sjs |= handled_fanout;
+ {
+ /* Conflict fall to most general variant */
+ (*prev_strategy)->set_empty();
+ dups_producing_tables= prev_dups_producing_tables;
+ join->sjm_lookup_tables= prev_sjm_lookup_tables;
+ // mark it 'none' to avpoid loops
+ pos->sj_strategy= SJ_OPT_NONE;
+ // next skip to last;
+ strategy= pickers +
+ (sizeof(pickers)/sizeof(Semi_join_strategy_picker*) - 3);
+ continue;
+ }
}
else
{
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 512bf296135..740e5087477 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -2132,6 +2132,24 @@ end:
DBUG_RETURN(result);
}
+
+bool partition_info::error_if_requires_values() const
+{
+ switch (part_type) {
+ case NOT_A_PARTITION:
+ case HASH_PARTITION:
+ break;
+ case RANGE_PARTITION:
+ my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "RANGE", "LESS THAN");
+ return true;
+ case LIST_PARTITION:
+ my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "LIST", "IN");
+ return true;
+ }
+ return false;
+}
+
+
/*
The parser generates generic data structures, we need to set them up
as the rest of the code expects to find them. This is in reality part
@@ -2221,6 +2239,8 @@ int partition_info::fix_parser_data(THD *thd)
part_elem= it++;
List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
num_elements= part_elem->list_val_list.elements;
+ if (!num_elements && error_if_requires_values())
+ DBUG_RETURN(true);
DBUG_ASSERT(part_type == RANGE_PARTITION ?
num_elements == 1U : TRUE);
for (j= 0; j < num_elements; j++)
diff --git a/sql/partition_info.h b/sql/partition_info.h
index cff941a858a..779948eddc9 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -313,6 +313,7 @@ public:
void set_show_version_string(String *packet);
void report_part_expr_error(bool use_subpart_expr);
bool has_same_partitioning(partition_info *new_part_info);
+ bool error_if_requires_values() const;
private:
static int list_part_cmp(const void* a, const void* b);
bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 51a9f6e3847..57ff5902178 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -1825,28 +1825,28 @@ ER_WRONG_AUTO_KEY 42000 S1009
ER_UNUSED_2
eng "You should never see it"
ER_NORMAL_SHUTDOWN
- cze "%s: norm-Bální ukončení\n"
- dan "%s: Normal nedlukning\n"
- nla "%s: Normaal afgesloten \n"
- eng "%s: Normal shutdown\n"
- est "%s: MariaDB lõpetas\n"
- fre "%s: Arrêt normal du serveur\n"
- ger "%s: Normal heruntergefahren\n"
- greek "%s: Φυσιολογική διαδικασία shutdown\n"
- hun "%s: Normal leallitas\n"
- ita "%s: Shutdown normale\n"
- kor "%s: 정상적인 shutdown\n"
- nor "%s: Normal avslutning\n"
- norwegian-ny "%s: Normal nedkopling\n"
- pol "%s: Standardowe zakończenie działania\n"
- por "%s: 'Shutdown' normal\n"
- rum "%s: Terminare normala\n"
- rus "%s: Корректная остановка\n"
- serbian "%s: Normalno gašenje\n"
- slo "%s: normálne ukončenie\n"
- spa "%s: Apagado normal\n"
- swe "%s: Normal avslutning\n"
- ukr "%s: Нормальне завершення\n"
+ cze "%s: norm-Bální ukončení"
+ dan "%s: Normal nedlukning"
+ nla "%s: Normaal afgesloten"
+ eng "%s: Normal shutdown"
+ est "%s: MariaDB lõpetas"
+ fre "%s: Arrêt normal du serveur"
+ ger "%s: Normal heruntergefahren"
+ greek "%s: Φυσιολογική διαδικασία shutdown"
+ hun "%s: Normal leallitas"
+ ita "%s: Shutdown normale"
+ kor "%s: 정상적인 shutdown"
+ nor "%s: Normal avslutning"
+ norwegian-ny "%s: Normal nedkopling"
+ pol "%s: Standardowe zakończenie działania"
+ por "%s: 'Shutdown' normal"
+ rum "%s: Terminare normala"
+ rus "%s: Корректная остановка"
+ serbian "%s: Normalno gašenje"
+ slo "%s: normálne ukončenie"
+ spa "%s: Apagado normal"
+ swe "%s: Normal avslutning"
+ ukr "%s: Нормальне завершення"
ER_GOT_SIGNAL
cze "%s: p-Břijat signal %d, končím\n"
dan "%s: Fangede signal %d. Afslutter!!\n"
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index bc89c2fbf2d..b1979de36e6 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -9610,7 +9610,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 8794cdb2a45..2a03b13aa75 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1184,7 +1184,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)
@@ -1556,6 +1560,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);
}
@@ -1757,7 +1763,7 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
sql++;
continue;
}
- /* fall trough */
+ /* fall through */
default:
break;
}
@@ -2699,13 +2705,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)
@@ -2713,6 +2723,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 fcba6661410..883f0c9cc88 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2441,6 +2441,8 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
MEM_ROOT *runtime_memroot)
{
Item_change_record *change;
+ DBUG_ENTER("THD::nocheck_register_item_tree_change");
+ DBUG_PRINT("enter", ("Register %p <- %p", old_value, (*place)));
/*
Now we use one node per change, which adds some memory overhead,
but still is rather fast as we use alloc_root for allocations.
@@ -2453,12 +2455,13 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
OOM, thd->fatal_error() is called by the error handler of the
memroot. Just return.
*/
- return;
+ DBUG_VOID_RETURN;
}
change= new (change_mem) Item_change_record;
change->place= place;
change->old_value= old_value;
change_list.append(change);
+ DBUG_VOID_RETURN;
}
/**
@@ -2499,7 +2502,11 @@ void THD::rollback_item_tree_changes()
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 70bf6f7783d..2bb2b12aebe 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1011,6 +1011,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;
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 6cd4547aaf9..2a6d82c161a 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -361,6 +361,9 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
SELECT_LEX *parent_lex= derived->select_lex;
Query_arena *arena, backup;
DBUG_ENTER("mysql_derived_merge");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (derived->alias ? derived->alias : "<NULL>"),
+ derived->get_unit()));
if (derived->merged)
DBUG_RETURN(FALSE);
@@ -508,6 +511,9 @@ unconditional_materialization:
bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
{
DBUG_ENTER("mysql_derived_merge_for_insert");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (derived->alias ? derived->alias : "<NULL>"),
+ derived->get_unit()));
if (derived->merged_for_insert)
DBUG_RETURN(FALSE);
if (derived->init_derived(thd, FALSE))
@@ -554,6 +560,9 @@ bool mysql_derived_init(THD *thd, LEX *lex, TABLE_LIST *derived)
{
SELECT_LEX_UNIT *unit= derived->get_unit();
DBUG_ENTER("mysql_derived_init");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (derived->alias ? derived->alias : "<NULL>"),
+ derived->get_unit()));
// Skip already prepared views/DT
if (!unit || unit->prepared)
@@ -624,7 +633,9 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
SELECT_LEX_UNIT *unit= derived->get_unit();
DBUG_ENTER("mysql_derived_prepare");
bool res= FALSE;
- DBUG_PRINT("enter", ("unit 0x%lx", (ulong) unit));
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (derived->alias ? derived->alias : "<NULL>"),
+ derived->get_unit()));
// Skip already prepared views/DT
if (!unit || unit->prepared ||
@@ -781,6 +792,9 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived)
bool res= FALSE;
DBUG_ENTER("mysql_derived_optimize");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (derived->alias ? derived->alias : "<NULL>"),
+ derived->get_unit()));
if (unit->optimized)
DBUG_RETURN(FALSE);
@@ -846,6 +860,9 @@ err:
bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived)
{
DBUG_ENTER("mysql_derived_create");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (derived->alias ? derived->alias : "<NULL>"),
+ derived->get_unit()));
TABLE *table= derived->table;
SELECT_LEX_UNIT *unit= derived->get_unit();
@@ -895,9 +912,13 @@ bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived)
bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived)
{
- DBUG_ENTER("mysql_derived_fill");
+ Field_iterator_table field_iterator;
SELECT_LEX_UNIT *unit= derived->get_unit();
bool res= FALSE;
+ DBUG_ENTER("mysql_derived_fill");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (derived->alias ? derived->alias : "<NULL>"),
+ derived->get_unit()));
if (unit->executed && !unit->uncacheable && !unit->describe)
DBUG_RETURN(FALSE);
@@ -937,7 +958,27 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived)
if (derived_result->flush())
res= TRUE;
unit->executed= TRUE;
+
+ if (derived->field_translation)
+ {
+ /* reset translation table to materialized table */
+ field_iterator.set_table(derived->table);
+ for (uint i= 0;
+ !field_iterator.end_of_fields();
+ field_iterator.next(), i= i + 1)
+ {
+ Item *item;
+
+ if (!(item= field_iterator.create_item(thd)))
+ {
+ res= TRUE;
+ break;
+ }
+ thd->change_item_tree(&derived->field_translation[i].item, item);
+ }
+ }
}
+
if (res || !lex->describe)
unit->cleanup();
lex->current_select= save_current_select;
@@ -966,6 +1007,9 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived)
bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
{
DBUG_ENTER("mysql_derived_reinit");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (derived->alias ? derived->alias : "<NULL>"),
+ derived->get_unit()));
st_select_lex_unit *unit= derived->get_unit();
if (derived->table)
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 074ea6e8f71..64c9497fb7d 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 820ac75c885..13f06024b22 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 2c4926cf498..beabae844f1 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, 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
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 3dcf8769c14..cf34c567626 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
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index ab31a8c1791..01dcc7cc2ac 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -4770,16 +4770,11 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
"LIST", "IN");
}
- else if (tab_part_info->part_type == RANGE_PARTITION)
- {
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
- }
else
{
- DBUG_ASSERT(tab_part_info->part_type == LIST_PARTITION);
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "LIST", "IN");
+ DBUG_ASSERT(tab_part_info->part_type == RANGE_PARTITION ||
+ tab_part_info->part_type == LIST_PARTITION);
+ (void) tab_part_info->error_if_requires_values();
}
goto err;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index c7f547edbc0..9f89a261540 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
@@ -11222,8 +11222,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 )
@@ -13980,9 +13980,9 @@ bool cond_is_datetime_is_null(Item *cond)
((Item_func*) cond)->functype() == Item_func::ISNULL_FUNC)
{
Item **args= ((Item_func_isnull*) cond)->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)) &&
@@ -14308,14 +14308,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);
@@ -15537,7 +15537,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]
}
@@ -21159,6 +21159,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_yacc.yy b/sql/sql_yacc.yy
index e0a6b155074..8dd38e286b2 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4679,18 +4679,8 @@ opt_part_values:
partition_info *part_info= lex->part_info;
if (! lex->is_partition_management())
{
- if (part_info->part_type == RANGE_PARTITION)
- {
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
- MYSQL_YYABORT;
- }
- if (part_info->part_type == LIST_PARTITION)
- {
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "LIST", "IN");
- MYSQL_YYABORT;
- }
+ if (part_info->error_if_requires_values())
+ MYSQL_YYABORT;
}
else
part_info->part_type= HASH_PARTITION;
diff --git a/sql/table.cc b/sql/table.cc
index 0c6e02b7a5c..5db14599adc 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -4117,6 +4117,9 @@ bool TABLE_LIST::create_field_translation(THD *thd)
Query_arena *arena, backup;
bool res= FALSE;
DBUG_ENTER("TABLE_LIST::create_field_translation");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (alias ? alias : "<NULL>"),
+ get_unit()));
if (thd->stmt_arena->is_conventional() ||
thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
@@ -5996,6 +5999,14 @@ void TABLE::create_key_part_by_field(KEY_PART_INFO *key_part_info,
might be reused.
*/
key_part_info->store_length= key_part_info->length;
+ /*
+ For BIT fields null_bit is not set to 0 even if the field is defined
+ as NOT NULL, look at Field_bit::Field_bit
+ */
+ if (!field->real_maybe_null())
+ {
+ key_part_info->null_bit= 0;
+ }
/*
The total store length of the key part is the raw length of the field +
diff --git a/sql/table.h b/sql/table.h
index c981243f28c..98f8c7ad73f 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -2107,6 +2107,9 @@ struct TABLE_LIST
inline void set_merged_derived()
{
DBUG_ENTER("set_merged_derived");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (alias ? alias : "<NULL>"),
+ get_unit()));
derived_type= ((derived_type & DTYPE_MASK) |
DTYPE_TABLE | DTYPE_MERGE);
set_check_merged();
@@ -2119,6 +2122,9 @@ struct TABLE_LIST
void set_materialized_derived()
{
DBUG_ENTER("set_materialized_derived");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (alias ? alias : "<NULL>"),
+ get_unit()));
derived_type= ((derived_type & (derived ? DTYPE_MASK : DTYPE_VIEW)) |
DTYPE_TABLE | DTYPE_MATERIALIZE);
set_check_materialized();
diff --git a/sql/transaction.cc b/sql/transaction.cc
index c293c651c04..56345748fd6 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -481,12 +481,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);
@@ -561,12 +557,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);
- }
if (ha_rollback_to_savepoint(thd, sv))
res= TRUE;
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 528c3025c57..936203a78ab 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -1,5 +1,6 @@
/*
Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+ 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
@@ -90,6 +91,28 @@ handle_condition(THD *,
}
/*
+ In ALTER TABLE, mysql_create_frm() gets the temporary table name,
+ like #sql-3696_2. It's used for error messages, when a table cannot
+ be created because of some OS error.
+ If there's a user error (like, too long comment), we want to show
+ the real table name, though.
+*/
+static const char *get_real_table_name(const char *table,
+ List<Create_field> &fields)
+{
+ const char *real_table_name= table;
+ List_iterator<Create_field> it(fields);
+ Create_field *field;
+ while ((field=it++))
+ {
+ if (field->field && field->field->table &&
+ (real_table_name= field->field->table->s->table_name.str))
+ break;
+ }
+ return real_table_name;
+}
+
+/*
Create a frm (table definition) file
SYNOPSIS
@@ -232,15 +255,7 @@ bool mysql_create_frm(THD *thd, const char *file_name,
if (tmp_len < create_info->comment.length)
{
- char *real_table_name= (char*) table;
- List_iterator<Create_field> it(create_fields);
- Create_field *field;
- while ((field=it++))
- {
- if (field->field && field->field->table &&
- (real_table_name= field->field->table->s->table_name.str))
- break;
- }
+ const char *real_table_name= get_real_table_name(table, create_fields);
if ((thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
{
@@ -285,6 +300,15 @@ bool mysql_create_frm(THD *thd, const char *file_name,
keybuff=(uchar*) my_malloc(key_buff_length, MYF(0));
key_info_length= pack_keys(keybuff, keys, key_info, data_offset);
+ if (key_info_length > UINT_MAX16)
+ {
+ my_printf_error(ER_CANT_CREATE_TABLE,
+ "Cannot create table %`s.%`s: index information is too long. "
+ "Decrease number of indexes or use shorter index names or shorter comments.",
+ MYF(0), db, get_real_table_name(table, create_fields));
+ goto err;
+ }
+
/*
Ensure that there are no forms in this newly created form file.
Even if the form file exists, create_frm must truncate it to