diff options
author | Sachin Setiya <sachin.setiya@mariadb.com> | 2017-04-18 12:01:56 +0530 |
---|---|---|
committer | Sachin Setiya <sachin.setiya@mariadb.com> | 2017-04-18 12:01:56 +0530 |
commit | 5ca8121292df337849811458b6c6671f7e9b2080 (patch) | |
tree | f8b4cd35955681c5b2deea916f2e0dab33ce7c59 /sql | |
parent | fce9a0c46ab9a8a95345a8d661d2b047e64ad7d6 (diff) | |
parent | 663068c6eea736a38eff9ac183326d6c7e4e239b (diff) | |
download | mariadb-git-5ca8121292df337849811458b6c6671f7e9b2080.tar.gz |
Merge tag 'mariadb-5.5.55' into bb-5.5-sachin-merge
Signed-off-by: Sachin Setiya <sachin.setiya@mariadb.com>
Diffstat (limited to 'sql')
38 files changed, 283 insertions, 251 deletions
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index 4cff1c09ba7..82203505f50 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -1520,6 +1520,8 @@ static void debug_sync(THD *thd, const char *sync_point_name, size_t name_len) { if (!thd) thd= current_thd; + if (!thd) + return; st_debug_sync_control *ds_control= thd->debug_sync_control; st_debug_sync_action *action; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b7580293fe3..19e1ce67b84 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -6673,6 +6673,7 @@ int ha_partition::reset(void) DBUG_ENTER("ha_partition::reset"); if (m_part_info) bitmap_set_all(&m_part_info->used_partitions); + m_extra_prepare_for_update= FALSE; file= m_file; do { diff --git a/sql/handler.cc b/sql/handler.cc index 8813f7072b1..ddbc3bcf0fc 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2979,6 +2979,7 @@ void handler::print_error(int error, myf errflag) textno=ER_FILE_USED; break; case ENOENT: + case ENOTDIR: textno=ER_FILE_NOT_FOUND; break; case ENOSPC: @@ -3448,12 +3449,10 @@ int handler::delete_table(const char *name) int saved_error= 0; int error= 0; int enoent_or_zero= ENOENT; // Error if no file was deleted - char buff[FN_REFLEN]; for (const char **ext=bas_ext(); *ext ; ext++) { - fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT); - if (mysql_file_delete_with_symlink(key_file_misc, buff, MYF(0))) + if (my_handler_delete_with_symlink(key_file_misc, name, *ext, 0)) { if (my_errno != ENOENT) { diff --git a/sql/item.h b/sql/item.h index 89155ac00db..9db5c7e9ac0 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3694,6 +3694,11 @@ public: virtual double val_real() = 0; virtual longlong val_int() = 0; virtual int save_in_field(Field *field, bool no_conversions) = 0; + bool walk(Item_processor processor, bool walk_subquery, uchar *args) + { + return (item->walk(processor, walk_subquery, args)) || + (this->*processor)(args); + } }; /** diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 3bd0b5b3fa2..ebe088e5092 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -777,7 +777,7 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, Item **a1, Item **a2, Item_result type) { - thd= current_thd; + THD *thd= current_thd; owner= owner_arg; set_null= set_null && owner_arg; a= a1; @@ -846,7 +846,6 @@ Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value, void Arg_comparator::set_datetime_cmp_func(Item_result_field *owner_arg, Item **a1, Item **b1) { - thd= current_thd; owner= owner_arg; a= a1; b= b1; @@ -919,12 +918,10 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, if (cache_arg && item->const_item() && !(item->type() == Item::CACHE_ITEM && item->cmp_type() == TIME_RESULT)) { - Query_arena backup; - Query_arena *save_arena= thd->switch_to_arena_for_cached_items(&backup); - Item_cache_temporal *cache= new Item_cache_temporal(f_type); - if (save_arena) - thd->set_query_arena(save_arena); + if (!thd) + thd= current_thd; + Item_cache_temporal *cache= new Item_cache_temporal(f_type); cache->store_packed(value, item); *cache_arg= cache; *item_arg= cache_arg; @@ -959,12 +956,12 @@ int Arg_comparator::compare_datetime() owner->null_value= 1; /* Get DATE/DATETIME/TIME value of the 'a' item. */ - a_value= get_datetime_value(thd, &a, &a_cache, *b, &a_is_null); + a_value= get_datetime_value(0, &a, &a_cache, *b, &a_is_null); if (a_is_null) return -1; /* Get DATE/DATETIME/TIME value of the 'b' item. */ - b_value= get_datetime_value(thd, &b, &b_cache, *a, &b_is_null); + b_value= get_datetime_value(0, &b, &b_cache, *a, &b_is_null); if (b_is_null) return -1; @@ -982,10 +979,10 @@ int Arg_comparator::compare_e_datetime() longlong a_value, b_value; /* Get DATE/DATETIME/TIME value of the 'a' item. */ - a_value= get_datetime_value(thd, &a, &a_cache, *b, &a_is_null); + a_value= get_datetime_value(0, &a, &a_cache, *b, &a_is_null); /* Get DATE/DATETIME/TIME value of the 'b' item. */ - b_value= get_datetime_value(thd, &b, &b_cache, *a, &b_is_null); + b_value= get_datetime_value(0, &b, &b_cache, *a, &b_is_null); return a_is_null || b_is_null ? a_is_null == b_is_null : a_value == b_value; } @@ -3600,7 +3597,7 @@ void in_datetime::set(uint pos,Item *item) bool is_null; struct packed_longlong *buff= &((packed_longlong*) base)[pos]; - buff->val= get_datetime_value(thd, &tmp_item, 0, warn_item, &is_null); + buff->val= get_datetime_value(0, &tmp_item, 0, warn_item, &is_null); buff->unsigned_flag= 1L; } @@ -3608,7 +3605,7 @@ uchar *in_datetime::get_value(Item *item) { bool is_null; Item **tmp_item= lval_cache ? &lval_cache : &item; - tmp.val= get_datetime_value(thd, &tmp_item, &lval_cache, warn_item, &is_null); + tmp.val= get_datetime_value(0, &tmp_item, &lval_cache, warn_item, &is_null); if (item->null_value) return 0; tmp.unsigned_flag= 1L; @@ -3852,7 +3849,7 @@ void cmp_item_datetime::store_value(Item *item) { bool is_null; Item **tmp_item= lval_cache ? &lval_cache : &item; - value= get_datetime_value(thd, &tmp_item, &lval_cache, warn_item, &is_null); + value= get_datetime_value(0, &tmp_item, &lval_cache, warn_item, &is_null); } @@ -3861,7 +3858,7 @@ int cmp_item_datetime::cmp(Item *arg) bool is_null; Item **tmp_item= &arg; return value != - get_datetime_value(thd, &tmp_item, 0, warn_item, &is_null); + get_datetime_value(0, &tmp_item, 0, warn_item, &is_null); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 0194f9cd0e0..a8befa47b95 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -44,7 +44,6 @@ class Arg_comparator: public Sql_alloc Arg_comparator *comparators; // used only for compare_row() double precision; /* Fields used in DATE/DATETIME comparison. */ - THD *thd; Item *a_cache, *b_cache; // Cached values of a and b items // when one of arguments is NULL. public: @@ -52,10 +51,10 @@ public: /* Allow owner function to use string buffers. */ String value1, value2; - Arg_comparator(): set_null(TRUE), comparators(0), thd(0), + Arg_comparator(): set_null(TRUE), comparators(0), a_cache(0), b_cache(0) {}; Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), set_null(TRUE), - comparators(0), thd(0), a_cache(0), b_cache(0) {}; + comparators(0), a_cache(0), b_cache(0) {}; int set_compare_func(Item_result_field *owner, Item_result type); inline int set_compare_func(Item_result_field *owner_arg) @@ -944,15 +943,13 @@ public: class in_datetime :public in_longlong { public: - THD *thd; /* An item used to issue warnings. */ Item *warn_item; /* Cache for the left item. */ Item *lval_cache; in_datetime(Item *warn_item_arg, uint elements) - :in_longlong(elements), thd(current_thd), warn_item(warn_item_arg), - lval_cache(0) {}; + :in_longlong(elements), warn_item(warn_item_arg), lval_cache(0) {}; void set(uint pos,Item *item); uchar *get_value(Item *item); Item* create_item() @@ -1112,14 +1109,13 @@ class cmp_item_datetime :public cmp_item { longlong value; public: - THD *thd; /* Item used for issuing warnings. */ Item *warn_item; /* Cache for the left item. */ Item *lval_cache; cmp_item_datetime(Item *warn_item_arg) - :thd(current_thd), warn_item(warn_item_arg), lval_cache(0) {} + : warn_item(warn_item_arg), lval_cache(0) {} void store_value(Item *item); int cmp(Item *arg); int compare(cmp_item *ci); diff --git a/sql/item_func.cc b/sql/item_func.cc index 463fafc6a30..b822509e534 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2868,7 +2868,6 @@ void Item_func_min_max::fix_length_and_dec() decimals=0; max_length=0; maybe_null=0; - thd= current_thd; cmp_type=args[0]->result_type(); for (uint i=0 ; i < arg_count ; i++) @@ -2941,13 +2940,11 @@ bool Item_func_min_max::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { Item **arg= args + i; bool is_null; - longlong res= get_datetime_value(thd, &arg, 0, compare_as_dates, &is_null); + longlong res= get_datetime_value(0, &arg, 0, compare_as_dates, &is_null); /* Check if we need to stop (because of error or KILL) and stop the loop */ - if (thd->is_error() || args[i]->null_value) - { + if (args[i]->null_value) return (null_value= 1); - } if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0) min_max= res; diff --git a/sql/item_func.h b/sql/item_func.h index 0da38e22c7f..d60801745fe 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1068,7 +1068,6 @@ class Item_func_min_max :public Item_func int cmp_sign; /* An item used for issuing warnings while string to DATETIME conversion. */ Item *compare_as_dates; - THD *thd; protected: enum_field_types cached_field_type; public: diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index ec9580bfabd..756ab5152ca 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab. + Copyright (c) 2000, 2017, Oracle and/or its affiliates. + Copyright (c) 2009, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3449,6 +3449,7 @@ String *Item_func_quote::val_str(String *str) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + ulong max_allowed_packet= current_thd->variables.max_allowed_packet; char *from, *to, *end, *start; String *arg= args[0]->val_str(str); uint arg_length, new_length; @@ -3467,11 +3468,14 @@ String *Item_func_quote::val_str(String *str) new_length= arg_length + 2; /* for beginning and ending ' signs */ for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++) new_length+= get_esc_bit(escmask, (uchar) *from); + if (new_length > max_allowed_packet) + goto toolong; } else { new_length= (arg_length * 2) + /* For string characters */ (2 * collation.collation->mbmaxlen); /* For quotes */ + set_if_smaller(new_length, max_allowed_packet); } if (tmp_value.alloc(new_length)) @@ -3487,7 +3491,7 @@ String *Item_func_quote::val_str(String *str) /* Put leading quote */ if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0) - goto null; + goto toolong; to+= mblen; for (start= (char*) arg->ptr(), end= start + arg_length; start < end; ) @@ -3507,17 +3511,17 @@ String *Item_func_quote::val_str(String *str) if (escape) { if ((mblen= cs->cset->wc_mb(cs, '\\', (uchar*) to, to_end)) <= 0) - goto null; + goto toolong; to+= mblen; } if ((mblen= cs->cset->wc_mb(cs, wc, (uchar*) to, to_end)) <= 0) - goto null; + goto toolong; to+= mblen; } /* Put trailing quote */ if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0) - goto null; + goto toolong; to+= mblen; new_length= to - tmp_value.ptr(); goto ret; @@ -3561,6 +3565,11 @@ ret: null_value= 0; return &tmp_value; +toolong: + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_ALLOWED_PACKET_OVERFLOWED, + ER_THD(current_thd, ER_WARN_ALLOWED_PACKET_OVERFLOWED), + func_name(), max_allowed_packet); null: null_value= 1; return 0; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 5750de713e6..78dcfc4215c 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -878,7 +878,7 @@ void Item_subselect::update_used_tables() if (!forced_const) { recalc_used_tables(parent_select, FALSE); - if (!engine->uncacheable()) + if (!(engine->uncacheable() & ~UNCACHEABLE_EXPLAIN)) { // did all used tables become static? if (!(used_tables_cache & ~engine->upper_select_const_tables())) @@ -2035,6 +2035,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, We can encounter "NULL IN (SELECT ...)". Wrap the added condition within a trig_cond. */ + disable_cond_guard_for_const_null_left_expr(0); item= new Item_func_trig_cond(item, get_cond_guard(0)); } @@ -2059,6 +2060,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, having= new Item_is_not_null_test(this, having); if (left_expr->maybe_null) { + disable_cond_guard_for_const_null_left_expr(0); if (!(having= new Item_func_trig_cond(having, get_cond_guard(0)))) DBUG_RETURN(true); @@ -2077,6 +2079,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, */ if (!abort_on_null && left_expr->maybe_null) { + disable_cond_guard_for_const_null_left_expr(0); if (!(item= new Item_func_trig_cond(item, get_cond_guard(0)))) DBUG_RETURN(true); } @@ -2103,6 +2106,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, (char *)"<result>")); if (!abort_on_null && left_expr->maybe_null) { + disable_cond_guard_for_const_null_left_expr(0); if (!(new_having= new Item_func_trig_cond(new_having, get_cond_guard(0)))) DBUG_RETURN(true); @@ -2299,6 +2303,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, Item *col_item= new Item_cond_or(item_eq, item_isnull); if (!abort_on_null && left_expr->element_index(i)->maybe_null) { + disable_cond_guard_for_const_null_left_expr(i); if (!(col_item= new Item_func_trig_cond(col_item, get_cond_guard(i)))) DBUG_RETURN(true); } @@ -2313,6 +2318,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, (char *)"<list ref>")); if (!abort_on_null && left_expr->element_index(i)->maybe_null) { + disable_cond_guard_for_const_null_left_expr(i); if (!(item_nnull_test= new Item_func_trig_cond(item_nnull_test, get_cond_guard(i)))) DBUG_RETURN(true); @@ -2373,6 +2379,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, */ if (left_expr->element_index(i)->maybe_null) { + disable_cond_guard_for_const_null_left_expr(i); if (!(item= new Item_func_trig_cond(item, get_cond_guard(i)))) DBUG_RETURN(true); if (!(having_col_item= diff --git a/sql/item_subselect.h b/sql/item_subselect.h index a44503b4471..2f166c83e8f 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -596,6 +596,14 @@ public: void set_first_execution() { if (first_execution) first_execution= FALSE; } bool expr_cache_is_needed(THD *thd); inline bool left_expr_has_null(); + void disable_cond_guard_for_const_null_left_expr(int i) + { + if (left_expr->const_item() && !left_expr->is_expensive()) + { + if (left_expr->element_index(i)->is_null()) + set_cond_guard_var(i,FALSE); + } + } int optimize(double *out_rows, double *cost); /* diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 064038a06fe..a49b5749f88 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -1,4 +1,5 @@ -/* Copyright (c) 2005, 2013, Oracle and/or its affiliates. +/* Copyright (c) 2005, 2016, Oracle and/or its affiliates. + Copyright (c) 2009, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2706,9 +2707,9 @@ int xml_enter(MY_XML_PARSER *st,const char *attr, size_t len) node.parent= data->parent; // Set parent for the new node to old parent data->parent= numnodes; // Remember current node as new parent - DBUG_ASSERT(data->level <= MAX_LEVEL); + DBUG_ASSERT(data->level < MAX_LEVEL); data->pos[data->level]= numnodes; - if (data->level < MAX_LEVEL) + if (data->level < MAX_LEVEL - 1) node.level= data->level++; else return MY_XML_ERROR; diff --git a/sql/log_slow.h b/sql/log_slow.h index 92a2d1bf4f6..541ef55f9e1 100644 --- a/sql/log_slow.h +++ b/sql/log_slow.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Monty Program Ab +/* Copyright (C) 2009, 2017, 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 @@ -16,20 +16,19 @@ /* Defining what to log to slow log */ #define LOG_SLOW_VERBOSITY_INIT 0 -#define LOG_SLOW_VERBOSITY_INNODB 1 << 0 -#define LOG_SLOW_VERBOSITY_QUERY_PLAN 1 << 1 +#define LOG_SLOW_VERBOSITY_INNODB (1U << 0) +#define LOG_SLOW_VERBOSITY_QUERY_PLAN (1U << 1) #define QPLAN_INIT QPLAN_QC_NO -#define QPLAN_ADMIN 1 << 0 -#define QPLAN_FILESORT 1 << 1 -#define QPLAN_FILESORT_DISK 1 << 2 -#define QPLAN_FULL_JOIN 1 << 3 -#define QPLAN_FULL_SCAN 1 << 4 -#define QPLAN_QC 1 << 5 -#define QPLAN_QC_NO 1 << 6 -#define QPLAN_TMP_DISK 1 << 7 -#define QPLAN_TMP_TABLE 1 << 8 +#define QPLAN_ADMIN (1U << 0) +#define QPLAN_FILESORT (1U << 1) +#define QPLAN_FILESORT_DISK (1U << 2) +#define QPLAN_FULL_JOIN (1U << 3) +#define QPLAN_FULL_SCAN (1U << 4) +#define QPLAN_QC (1U << 5) +#define QPLAN_QC_NO (1U << 6) +#define QPLAN_TMP_DISK (1U << 7) +#define QPLAN_TMP_TABLE (1U << 8) /* ... */ -#define QPLAN_MAX ((ulong) 1) << 31 /* reserved as placeholder */ - +#define QPLAN_MAX (1U << 31) /* reserved as placeholder */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 363a8cea6ff..9198f616d15 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -8075,7 +8075,7 @@ static int mysql_init_variables(void) mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0; #if defined(HAVE_REALPATH) && !defined(HAVE_valgrind) && !defined(HAVE_BROKEN_REALPATH) /* We can only test for sub paths if my_symlink.c is using realpath */ - myisam_test_invalid_symlink= test_if_data_home_dir; + mysys_test_invalid_symlink= path_starts_from_data_home_dir; #endif opt_log= opt_slow_log= 0; opt_bin_log= opt_bin_log_used= 0; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index a40363ff9ab..25a9e729a8b 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7500,8 +7500,15 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond) if (cond_func->functype() == Item_func::BETWEEN || cond_func->functype() == Item_func::IN_FUNC) inv= ((Item_func_opt_neg *) cond_func)->negated; - else if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE) - DBUG_RETURN(0); + else + { + MEM_ROOT *tmp_root= param->mem_root; + param->thd->mem_root= param->old_root; + Item_func::optimize_type opt_res= cond_func->select_optimize(); + param->thd->mem_root= tmp_root; + if (opt_res == Item_func::OPTIMIZE_NONE) + DBUG_RETURN(0); + } param->cond= cond; @@ -9335,6 +9342,13 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) if (!tmp->next_key_part) { + if (key2->use_count) + { + SEL_ARG *key2_cpy= new SEL_ARG(*key2); + if (key2_cpy) + return 0; + key2= key2_cpy; + } /* tmp->next_key_part is empty: cut the range that is covered by tmp from key2. @@ -9366,13 +9380,6 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) key2: [---] tmp: [---------] */ - if (key2->use_count) - { - SEL_ARG *key2_cpy= new SEL_ARG(*key2); - if (key2_cpy) - return 0; - key2= key2_cpy; - } key2->copy_max_to_min(tmp); continue; } diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 6fcb460e6c6..51a9f6e3847 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -4883,7 +4883,7 @@ WARN_DATA_TRUNCATED 01000 spa "Datos truncados para columna '%s' en la línea %lu" ER_WARN_USING_OTHER_HANDLER eng "Using storage engine %s for table '%s'" - ger "Für Tabelle '%s' wird Speicher-Engine %s benutzt" + ger "Speicher-Engine %s wird für Tabelle '%s' benutzt" por "Usando engine de armazenamento %s para tabela '%s'" spa "Usando motor de almacenamiento %s para tabla '%s'" swe "Använder handler %s för tabell '%s'" diff --git a/sql/sp.cc b/sql/sp.cc index 9ae0c84b36c..932e801a01d 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2002, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2002, 2016, Oracle and/or its affiliates. + Copyright (c) 2009, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -375,7 +375,7 @@ void Proc_table_intact::report_error(uint code, const char *fmt, ...) my_vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - if (code) + if (code == ER_COL_COUNT_DOESNT_MATCH_CORRUPTED) my_message(code, buf, MYF(0)); else my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "proc"); @@ -1767,7 +1767,8 @@ sp_find_routine(THD *thd, stored_procedure_type type, sp_name *name, @param thd Thread handler @param routines List of needles in the hay stack - @param any Any of the needles are good enough + @param is_proc Indicates whether routines in the list are procedures + or functions. @return @retval FALSE Found. @@ -1775,7 +1776,7 @@ sp_find_routine(THD *thd, stored_procedure_type type, sp_name *name, */ bool -sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any) +sp_exist_routines(THD *thd, TABLE_LIST *routines, bool is_proc) { TABLE_LIST *routine; bool sp_object_found; @@ -1791,17 +1792,14 @@ sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any) lex_name.str= thd->strmake(routine->table_name, lex_name.length); name= new sp_name(lex_db, lex_name, true); name->init_qname(thd); - sp_object_found= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name, - &thd->sp_proc_cache, FALSE) != NULL || - sp_find_routine(thd, TYPE_ENUM_FUNCTION, name, - &thd->sp_func_cache, FALSE) != NULL; + sp_object_found= is_proc ? sp_find_routine(thd, TYPE_ENUM_PROCEDURE, + name, &thd->sp_proc_cache, + FALSE) != NULL : + sp_find_routine(thd, TYPE_ENUM_FUNCTION, + name, &thd->sp_func_cache, + FALSE) != NULL; thd->warning_info->clear_warning_info(thd->query_id); - if (sp_object_found) - { - if (any) - break; - } - else if (!any) + if (! sp_object_found) { my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION or PROCEDURE", routine->table_name); @@ -121,7 +121,7 @@ sp_cache_routine(THD *thd, stored_procedure_type type, sp_name *name, bool lookup_only, sp_head **sp); bool -sp_exist_routines(THD *thd, TABLE_LIST *procs, bool any); +sp_exist_routines(THD *thd, TABLE_LIST *procs, bool is_proc); bool sp_show_create_routine(THD *thd, stored_procedure_type type, sp_name *name); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ea5b4c51e16..11351f28a07 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -6321,12 +6321,12 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, switch ( struct_no ) { case USER_ACL: acl_user->user= strdup_root(&mem, user_to->user.str); - acl_user->host.hostname= strdup_root(&mem, user_to->host.str); + update_hostname(&acl_user->host, strdup_root(&mem, user_to->host.str)); break; case DB_ACL: acl_db->user= strdup_root(&mem, user_to->user.str); - acl_db->host.hostname= strdup_root(&mem, user_to->host.str); + update_hostname(&acl_db->host, strdup_root(&mem, user_to->host.str)); break; case COLUMN_PRIVILEGES_HASH: diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 31858682543..345c7acb508 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -9055,9 +9055,7 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values, /* Update virtual fields*/ thd->abort_on_warning= FALSE; if (vcol_table && vcol_table->vfield && - update_virtual_fields(thd, vcol_table, - vcol_table->triggers ? VCOL_UPDATE_ALL : - VCOL_UPDATE_FOR_WRITE)) + update_virtual_fields(thd, vcol_table, VCOL_UPDATE_FOR_WRITE)) goto err; thd->abort_on_warning= save_abort_on_warning; thd->no_errors= save_no_errors; @@ -9121,9 +9119,7 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields, if (item_field && item_field->field && (table= item_field->field->table) && table->vfield) - result= update_virtual_fields(thd, table, - table->triggers ? VCOL_UPDATE_ALL : - VCOL_UPDATE_FOR_WRITE); + result= update_virtual_fields(thd, table, VCOL_UPDATE_FOR_WRITE); } } return result; @@ -9208,9 +9204,7 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors, /* Update virtual fields*/ thd->abort_on_warning= FALSE; if (table->vfield && - update_virtual_fields(thd, table, - table->triggers ? VCOL_UPDATE_ALL : - VCOL_UPDATE_FOR_WRITE)) + update_virtual_fields(thd, table, VCOL_UPDATE_FOR_WRITE)) goto err; thd->abort_on_warning= abort_on_warning_saved; DBUG_RETURN(thd->is_error()); @@ -9263,9 +9257,7 @@ fill_record_n_invoke_before_triggers(THD *thd, Field **ptr, { TABLE *table= (*ptr)->table; if (table->vfield) - result= update_virtual_fields(thd, table, - table->triggers ? VCOL_UPDATE_ALL : - VCOL_UPDATE_FOR_WRITE); + result= update_virtual_fields(thd, table, VCOL_UPDATE_FOR_WRITE); } return result; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index fd2dec5a146..1d0b86ad2f5 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2016, MariaDB + Copyright (c) 2008, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1162,7 +1162,6 @@ THD::THD() m_internal_handler= NULL; m_binlog_invoker= FALSE; - arena_for_cached_items= 0; memset(&invoker_user, 0, sizeof(invoker_user)); memset(&invoker_host, 0, sizeof(invoker_host)); prepare_derived_at_open= FALSE; diff --git a/sql/sql_class.h b/sql/sql_class.h index 26123e48aa3..8a9c3d2429a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3164,26 +3164,7 @@ public: } } -private: - /* - This reference points to the table arena when the expression - for a virtual column is being evaluated - */ - Query_arena *arena_for_cached_items; - public: - void reset_arena_for_cached_items(Query_arena *new_arena) - { - arena_for_cached_items= new_arena; - } - Query_arena *switch_to_arena_for_cached_items(Query_arena *backup) - { - if (!arena_for_cached_items) - return 0; - set_n_backup_active_arena(arena_for_cached_items, backup); - return backup; - } - void clear_wakeup_ready() { wakeup_ready= false; } /* Sleep waiting for others to wake us up with signal_wakeup_ready(). diff --git a/sql/sql_const.h b/sql/sql_const.h index 3c127a03826..abe2a496045 100644 --- a/sql/sql_const.h +++ b/sql/sql_const.h @@ -65,6 +65,7 @@ #define RAND_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-1)) #define PSEUDO_TABLE_BITS (PARAM_TABLE_BIT | OUTER_REF_TABLE_BIT | \ RAND_TABLE_BIT) +#define CONNECT_STRING_MAXLEN 65535 /* stored in 2 bytes in .frm */ #define MAX_FIELDS 4096 /* Limit in the .frm file */ #define MAX_PARTITIONS 1024 diff --git a/sql/sql_db.cc b/sql/sql_db.cc index f72a8918f61..7bb4f0fa60e 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1083,9 +1083,9 @@ static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp, strxmov(filePath, path, "/", file->name, NullS); /* We ignore ENOENT error in order to skip files that was deleted - by concurrently running statement like REAPIR TABLE ... + by concurrently running statement like REPAIR TABLE ... */ - if (my_delete_with_symlink(filePath, MYF(0)) && + if (my_handler_delete_with_symlink(key_file_misc, filePath, "", MYF(0)) && my_errno != ENOENT) { my_error(EE_DELETE, MYF(0), filePath, my_errno); @@ -1206,7 +1206,7 @@ long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path) continue; } strxmov(filePath, org_path, "/", file->name, NullS); - if (mysql_file_delete_with_symlink(key_file_misc, filePath, MYF(MY_WME))) + if (my_handler_delete_with_symlink(key_file_misc, filePath, "", MYF(MY_WME))) { goto err; } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index dbfb44801b0..f40e7a67ee4 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -328,9 +328,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ! thd->is_error()) { if (table->vfield) - update_virtual_fields(thd, table, - table->triggers ? VCOL_UPDATE_ALL : - VCOL_UPDATE_FOR_READ); + update_virtual_fields(thd, table, VCOL_UPDATE_FOR_READ); thd->examined_row_count++; // thd->is_error() is tested to disallow delete row on error if (!select || select->skip_record(thd) > 0) @@ -1085,4 +1083,3 @@ bool multi_delete::send_eof() } return 0; } - diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 44395599961..20fca2de8cf 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -446,6 +446,9 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) { Item *expr= derived->on_expr; expr= and_conds(expr, dt_select->join ? dt_select->join->conds : 0); + if (expr) + expr->top_level_item(); + if (expr && (derived->prep_on_expr || expr != derived->on_expr)) { derived->on_expr= expr; diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 9411b3a92c8..820ac75c885 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -589,6 +589,11 @@ void JOIN_CACHE::create_remaining_fields() { MY_BITMAP *rem_field_set; TABLE *table= tab->table; +#if MYSQL_VERSION_ID < 100204 + empty_record(table); +#else +#error remove +#endif if (all_read_fields) rem_field_set= table->read_set; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 4723c2b643d..dcbd9f180d1 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -979,7 +979,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, { uint length; uchar *pos; - Item *real_item; + Item_field *real_item; if (read_info.read_field()) break; @@ -991,16 +991,26 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, pos=read_info.row_start; length=(uint) (read_info.row_end-pos); - real_item= item->real_item(); + real_item= item->filed_for_view_update(); if ((!read_info.enclosed && (enclosed_length && length == 4 && !memcmp(pos, STRING_WITH_LEN("NULL")))) || (length == 1 && read_info.found_null)) { - if (real_item->type() == Item::FIELD_ITEM) + if (item->type() == Item::STRING_ITEM) { - Field *field= ((Item_field *)real_item)->field; + ((Item_user_var_as_out_param *)item)->set_null_value( + read_info.read_charset); + } + else if (!real_item) + { + my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name); + DBUG_RETURN(1); + } + else + { + Field *field= real_item->field; if (field->reset()) { my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name, @@ -1017,39 +1027,29 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, ER_WARN_NULL_TO_NOTNULL, 1); } } - else if (item->type() == Item::STRING_ITEM) - { - ((Item_user_var_as_out_param *)item)->set_null_value( - read_info.read_charset); - } - else - { - my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name()); - DBUG_RETURN(1); - } continue; } - if (real_item->type() == Item::FIELD_ITEM) - { - Field *field= ((Item_field *)real_item)->field; - field->set_notnull(); - read_info.row_end[0]=0; // Safe to change end marker - if (field == table->next_number_field) - table->auto_increment_field_not_null= TRUE; - field->store((char*) pos, length, read_info.read_charset); - } - else if (item->type() == Item::STRING_ITEM) + if (item->type() == Item::STRING_ITEM) { ((Item_user_var_as_out_param *)item)->set_value((char*) pos, length, read_info.read_charset); } - else + else if (!real_item) { - my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name()); + my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name); DBUG_RETURN(1); } + else + { + Field *field= real_item->field; + field->set_notnull(); + read_info.row_end[0]=0; // Safe to change end marker + if (field == table->next_number_field) + table->auto_increment_field_not_null= TRUE; + field->store((char*) pos, length, read_info.read_charset); + } } if (thd->is_error()) @@ -1069,10 +1069,20 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, break; for (; item ; item= it++) { - Item *real_item= item->real_item(); - if (real_item->type() == Item::FIELD_ITEM) + Item_field *real_item= item->filed_for_view_update(); + if (item->type() == Item::STRING_ITEM) + { + ((Item_user_var_as_out_param *)item)->set_null_value( + read_info.read_charset); + } + else if (!real_item) { - Field *field= ((Item_field *)real_item)->field; + my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name); + DBUG_RETURN(1); + } + else + { + Field *field= real_item->field; if (field->reset()) { my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name, @@ -1093,16 +1103,6 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, ER(ER_WARN_TOO_FEW_RECORDS), thd->warning_info->current_row_for_warning()); } - else if (item->type() == Item::STRING_ITEM) - { - ((Item_user_var_as_out_param *)item)->set_null_value( - read_info.read_charset); - } - else - { - my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name()); - DBUG_RETURN(1); - } } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f74e5d6c3e9..28963e65218 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2015, MariaDB +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. + Copyright (c) 2008, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1844,12 +1844,12 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, #endif case SCH_COLUMNS: case SCH_STATISTICS: - { #ifdef DONT_ALLOW_SHOW_COMMANDS my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */ DBUG_RETURN(1); #else + { DBUG_ASSERT(table_ident); TABLE_LIST **query_tables_last= lex->query_tables_last; schema_select_lex= new SELECT_LEX(); @@ -6449,7 +6449,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, #endif /* WITH_WSREP */ /* - When you modify mysql_parse(), you may need to mofify + When you modify mysql_parse(), you may need to modify mysql_test_parse_for_slave() in this same file. */ @@ -8319,27 +8319,20 @@ bool check_ident_length(LEX_STRING *ident) Check if path does not contain mysql data home directory SYNOPSIS - test_if_data_home_dir() - dir directory + path_starts_from_data_home_dir() + dir directory, with all symlinks resolved RETURN VALUES 0 ok 1 error ; Given path contains data directory */ -C_MODE_START +extern "C" { -int test_if_data_home_dir(const char *dir) +int path_starts_from_data_home_dir(const char *path) { - char path[FN_REFLEN]; - int dir_len; - DBUG_ENTER("test_if_data_home_dir"); + int dir_len= strlen(path); + DBUG_ENTER("path_starts_from_data_home_dir"); - if (!dir) - DBUG_RETURN(0); - - (void) fn_format(path, dir, "", "", - (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); - dir_len= strlen(path); if (mysql_unpacked_real_data_home_len<= dir_len) { if (dir_len > mysql_unpacked_real_data_home_len && @@ -8367,7 +8360,31 @@ int test_if_data_home_dir(const char *dir) DBUG_RETURN(0); } -C_MODE_END +} + +/* + Check if path does not contain mysql data home directory + + SYNOPSIS + test_if_data_home_dir() + dir directory + + RETURN VALUES + 0 ok + 1 error ; Given path contains data directory +*/ + +int test_if_data_home_dir(const char *dir) +{ + char path[FN_REFLEN]; + DBUG_ENTER("test_if_data_home_dir"); + + if (!dir) + DBUG_RETURN(0); + + (void) fn_format(path, dir, "", "", MY_RETURN_REAL_PATH); + DBUG_RETURN(path_starts_from_data_home_dir(path)); +} /** diff --git a/sql/sql_parse.h b/sql/sql_parse.h index a08048dcb1e..58885594a5d 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -33,7 +33,8 @@ enum enum_mysql_completiontype { COMMIT_RELEASE=-1, COMMIT=0, COMMIT_AND_CHAIN=6 }; -extern "C" int test_if_data_home_dir(const char *dir); +extern "C" int path_starts_from_data_home_dir(const char *dir); +int test_if_data_home_dir(const char *dir); bool multi_update_precheck(THD *thd, TABLE_LIST *tables); bool multi_delete_precheck(THD *thd, TABLE_LIST *tables); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 9318dae2e31..1f95ac279fd 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1988,7 +1988,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt, THD *thd= stmt->thd; LEX *lex= stmt->lex; SQL_HANDLER *ha_table; - DBUG_ENTER("mysql_test_select"); + DBUG_ENTER("mysql_test_handler_read"); lex->select_lex.context.resolve_in_select_list= TRUE; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c406fab5a3a..d83e8e2bfce 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -714,10 +714,15 @@ JOIN::prepare(Item ***rref_pointer_array, if (mixed_implicit_grouping && tbl->table) tbl->table->maybe_null= 1; } + + uint real_og_num= og_num; + if (skip_order_by && + select_lex != select_lex->master_unit()->global_parameters) + real_og_num+= select_lex->order_list.elements; if ((wild_num && setup_wild(thd, tables_list, fields_list, &all_fields, wild_num)) || - select_lex->setup_ref_array(thd, og_num) || + select_lex->setup_ref_array(thd, real_og_num) || setup_fields(thd, (*rref_pointer_array), fields_list, MARK_COLUMNS_READ, &all_fields, 1) || setup_without_group(thd, (*rref_pointer_array), tables_list, @@ -7788,8 +7793,6 @@ get_best_combination(JOIN *join) form=join->table[tablenr]=j->table; used_tables|= form->map; form->reginfo.join_tab=j; - if (!*j->on_expr_ref) - form->reginfo.not_exists_optimize=0; // Only with LEFT JOIN DBUG_PRINT("info",("type: %d", j->type)); if (j->type == JT_CONST) goto loop_end; // Handled in make_join_stat.. @@ -8620,7 +8623,10 @@ make_outerjoin_info(JOIN *join) tab->cond_equal= tbl->cond_equal; if (embedding && !embedding->is_active_sjm()) tab->first_upper= embedding->nested_join->first_nested; - } + } + else if (!embedding) + tab->table->reginfo.not_exists_optimize= 0; + for ( ; embedding ; embedding= embedding->embedding) { if (embedding->is_active_sjm()) @@ -8630,7 +8636,10 @@ make_outerjoin_info(JOIN *join) } /* Ignore sj-nests: */ if (!(embedding->on_expr && embedding->outer_join)) + { + tab->table->reginfo.not_exists_optimize= 0; continue; + } NESTED_JOIN *nested_join= embedding->nested_join; if (!nested_join->counter) { @@ -8646,17 +8655,10 @@ make_outerjoin_info(JOIN *join) } if (!tab->first_inner) tab->first_inner= nested_join->first_nested; - if (tab->table->reginfo.not_exists_optimize) - tab->first_inner->table->reginfo.not_exists_optimize= 1; if (++nested_join->counter < nested_join->n_tables) break; /* Table tab is the last inner table for nested join. */ nested_join->first_nested->last_inner= tab; - if (tab->first_inner->table->reginfo.not_exists_optimize) - { - for (JOIN_TAB *join_tab= tab->first_inner; join_tab <= tab; join_tab++) - join_tab->table->reginfo.not_exists_optimize= 1; - } } } DBUG_RETURN(FALSE); @@ -8792,7 +8794,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5 */ if (tab == join->join_tab + join->top_join_tab_count - 1) - current_map|= OUTER_REF_TABLE_BIT | RAND_TABLE_BIT; + current_map|= RAND_TABLE_BIT; used_tables|=current_map; if (tab->type == JT_REF && tab->quick && @@ -9420,7 +9422,7 @@ void JOIN::drop_unused_derived_keys() continue; if (!table->pos_in_table_list->is_materialized_derived()) continue; - if (table->max_keys > 1) + if (table->max_keys > 1 && !tab->is_ref_for_hash_join()) table->use_index(tab->ref.key); if (table->s->keys) { @@ -14622,7 +14624,9 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, if (new_field) new_field->init(table); - if (copy_func && item->real_item()->is_result_field()) + if (copy_func && + (item->is_result_field() || + (item->real_item()->is_result_field()))) *((*copy_func)++) = item; // Save for copy_funcs if (modify_item) item->set_result_field(new_field); @@ -17092,32 +17096,41 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, first_unmatched->found= 1; for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++) { + /* + Check whether 'not exists' optimization can be used here. + If tab->table->reginfo.not_exists_optimize is set to true + then WHERE contains a conjunctive predicate IS NULL over + a non-nullable field of tab. When activated this predicate + will filter out all records with matches for the left part + of the outer join whose inner tables start from the + first_unmatched table and include table tab. To safely use + 'not exists' optimization we have to check that the + IS NULL predicate is really activated, i.e. all guards + that wrap it are in the 'open' state. + */ + bool not_exists_opt_is_applicable= + tab->table->reginfo.not_exists_optimize; + for (JOIN_TAB *first_upper= first_unmatched->first_upper; + not_exists_opt_is_applicable && first_upper; + first_upper= first_upper->first_upper) + { + if (!first_upper->found) + not_exists_opt_is_applicable= false; + } /* Check all predicates that has just been activated. */ /* Actually all predicates non-guarded by first_unmatched->found will be re-evaluated again. It could be fixed, but, probably, it's not worth doing now. */ - /* - not_exists_optimize has been created from a - select_cond containing 'is_null'. This 'is_null' - predicate is still present on any 'tab' with - 'not_exists_optimize'. Furthermore, the usual rules - for condition guards also applies for - 'not_exists_optimize' -> When 'is_null==false' we - know all cond. guards are open and we can apply - the 'not_exists_optimize'. - */ - DBUG_ASSERT(!(tab->table->reginfo.not_exists_optimize && - !tab->select_cond)); - if (tab->select_cond && !tab->select_cond->val_int()) { /* The condition attached to table tab is false */ - if (tab == join_tab) { found= 0; + if (not_exists_opt_is_applicable) + DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); } else { @@ -17126,21 +17139,10 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, not to the last table of the current nest level. */ join->return_tab= tab; - } - - if (tab->table->reginfo.not_exists_optimize) - { - /* - When not_exists_optimize is set: No need to further - explore more rows of 'tab' for this partial result. - Any found 'tab' matches are known to evaluate to 'false'. - Returning .._NO_MORE_ROWS will skip rem. 'tab' rows. - */ - DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); - } - else if (tab != join_tab) - { - DBUG_RETURN(NESTED_LOOP_OK); + if (not_exists_opt_is_applicable) + DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); + else + DBUG_RETURN(NESTED_LOOP_OK); } } } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ff080f79da9..0d946a2aa8b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2904,6 +2904,21 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, uint total_uneven_bit_length= 0; DBUG_ENTER("mysql_prepare_create_table"); + LEX_STRING* connect_string = &create_info->connect_string; + if (connect_string->length != 0 && + connect_string->length > CONNECT_STRING_MAXLEN && + (system_charset_info->cset->charpos(system_charset_info, + connect_string->str, + (connect_string->str + + connect_string->length), + CONNECT_STRING_MAXLEN) + < connect_string->length)) + { + my_error(ER_WRONG_STRING_LENGTH, MYF(0), + connect_string->str, "CONNECTION", CONNECT_STRING_MAXLEN); + DBUG_RETURN(TRUE); + } + select_field_pos= alter_info->create_list.elements - select_field_count; null_fields=blob_columns=0; create_info->varchar= 0; @@ -3826,7 +3841,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check); if (thd->variables.sql_mode & MODE_NO_ZERO_DATE && - !sql_field->def && + !sql_field->def && !sql_field->vcol_info && sql_field->sql_type == MYSQL_TYPE_TIMESTAMP && (sql_field->flags & NOT_NULL_FLAG) && (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD)) diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 2b64239c41b..c562ee9762c 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -2246,6 +2246,9 @@ void Table_triggers_list::mark_fields_used(trg_event_type event) bitmap_set_bit(trigger_table->read_set, trg_field->field_idx); if (trg_field->get_settable_routine_parameter()) bitmap_set_bit(trigger_table->write_set, trg_field->field_idx); + if (trigger_table->field[trg_field->field_idx]->vcol_info) + trigger_table->mark_virtual_col(trigger_table-> + field[trg_field->field_idx]); } } } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 7c2f313b4ae..49fcf16a045 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -569,9 +569,7 @@ int mysql_update(THD *thd, while (!(error=info.read_record(&info)) && !thd->killed) { if (table->vfield) - update_virtual_fields(thd, table, - table->triggers ? VCOL_UPDATE_ALL : - VCOL_UPDATE_FOR_READ); + update_virtual_fields(thd, table, VCOL_UPDATE_FOR_READ); thd->examined_row_count++; if (!select || (error= select->skip_record(thd)) > 0) { @@ -695,9 +693,7 @@ int mysql_update(THD *thd, while (!(error=info.read_record(&info)) && !thd->killed) { if (table->vfield) - update_virtual_fields(thd, table, - table->triggers ? VCOL_UPDATE_ALL : - VCOL_UPDATE_FOR_READ); + update_virtual_fields(thd, table, VCOL_UPDATE_FOR_READ); thd->examined_row_count++; if (!select || select->skip_record(thd) > 0) { @@ -2243,10 +2239,7 @@ int multi_update::do_updates() { int error; if (table->vfield && - update_virtual_fields(thd, table, - (table->triggers ? - VCOL_UPDATE_ALL : - VCOL_UPDATE_FOR_WRITE))) + update_virtual_fields(thd, table, VCOL_UPDATE_FOR_WRITE)) goto err2; if ((error= cur_table->view_check_option(thd, ignore)) != VIEW_CHECK_OK) diff --git a/sql/sys_vars.h b/sql/sys_vars.h index 3cbd24f1c89..dbe27ab107e 100644 --- a/sql/sys_vars.h +++ b/sql/sys_vars.h @@ -1141,7 +1141,7 @@ public: if (var->value->result_type() == STRING_RESULT) { - if (!(res=var->value->val_str(&str))) + if (!(res=var->value->val_str_ascii(&str))) return true; else { diff --git a/sql/table.cc b/sql/table.cc index b53518a1fa9..0c6e02b7a5c 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6566,11 +6566,9 @@ bool is_simple_order(ORDER *order) @details The function computes the values of the virtual columns of the table and stores them in the table record buffer. - If vcol_update_mode is set to VCOL_UPDATE_ALL then all virtual column are - computed. Otherwise, only fields from vcol_set are computed: all of them, - if vcol_update_mode is set to VCOL_UPDATE_FOR_WRITE, and, only those with - the stored_in_db flag set to false, if vcol_update_mode is equal to - VCOL_UPDATE_FOR_READ. + Only fields from vcol_set are computed: all of them, if vcol_update_mode is + set to VCOL_UPDATE_FOR_WRITE, and, only those with the stored_in_db flag + set to false, if vcol_update_mode is equal to VCOL_UPDATE_FOR_READ. @retval 0 Success @@ -6586,15 +6584,16 @@ int update_virtual_fields(THD *thd, TABLE *table, int error __attribute__ ((unused))= 0; DBUG_ASSERT(table && table->vfield); - thd->reset_arena_for_cached_items(table->expr_arena); + Query_arena backup_arena; + thd->set_n_backup_active_arena(table->expr_arena, &backup_arena); + /* Iterate over virtual fields in the table */ for (vfield_ptr= table->vfield; *vfield_ptr; vfield_ptr++) { vfield= (*vfield_ptr); DBUG_ASSERT(vfield->vcol_info && vfield->vcol_info->expr_item); - if ((bitmap_is_set(table->vcol_set, vfield->field_index) && - (vcol_update_mode == VCOL_UPDATE_FOR_WRITE || !vfield->stored_in_db)) || - vcol_update_mode == VCOL_UPDATE_ALL) + if (bitmap_is_set(table->vcol_set, vfield->field_index) && + (vcol_update_mode == VCOL_UPDATE_FOR_WRITE || !vfield->stored_in_db)) { /* Compute the actual value of the virtual fields */ error= vfield->vcol_info->expr_item->save_in_field(vfield, 0); @@ -6605,7 +6604,7 @@ int update_virtual_fields(THD *thd, TABLE *table, DBUG_PRINT("info", ("field '%s' - skipped", vfield->field_name)); } } - thd->reset_arena_for_cached_items(0); + thd->restore_active_arena(table->expr_arena, &backup_arena); DBUG_RETURN(0); } diff --git a/sql/table.h b/sql/table.h index 17fdd4aba15..dde01a85d77 100644 --- a/sql/table.h +++ b/sql/table.h @@ -302,8 +302,7 @@ enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP }; enum enum_vcol_update_mode { VCOL_UPDATE_FOR_READ= 0, - VCOL_UPDATE_FOR_WRITE, - VCOL_UPDATE_ALL + VCOL_UPDATE_FOR_WRITE }; typedef struct st_filesort_info |