summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/handler.cc19
-rw-r--r--sql/item.cc7
-rw-r--r--sql/item.h48
-rw-r--r--sql/item_cmpfunc.cc93
-rw-r--r--sql/item_cmpfunc.h2
-rw-r--r--sql/item_subselect.cc9
-rw-r--r--sql/mysqld.cc4
-rw-r--r--sql/privilege.h2
-rw-r--r--sql/sql_acl.cc14
-rw-r--r--sql/sql_class.cc16
-rw-r--r--sql/sql_class.h8
-rw-r--r--sql/sql_explain.cc15
-rw-r--r--sql/sql_insert.cc35
-rw-r--r--sql/sql_lex.cc6
-rw-r--r--sql/sql_parse.cc7
-rw-r--r--sql/sql_prepare.cc10
-rw-r--r--sql/sql_select.cc92
-rw-r--r--sql/sql_select.h6
-rw-r--r--sql/sql_show.cc22
-rw-r--r--sql/sql_time.cc45
-rw-r--r--sql/sql_tvc.cc13
-rw-r--r--sql/sql_view.cc24
-rw-r--r--sql/sql_view.h2
-rw-r--r--sql/sql_yacc.yy5
-rw-r--r--sql/table.cc12
25 files changed, 371 insertions, 145 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index f1a6bb3746b..577d6ef9e26 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -4932,32 +4932,17 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
- const ulong v= table->s->mysql_version;
-
- if ((v >= MYSQL_VERSION_ID) &&
+ if ((table->s->mysql_version >= MYSQL_VERSION_ID) &&
(check_opt->sql_flags & TT_FOR_UPGRADE))
return 0;
- if (v < MYSQL_VERSION_ID)
+ if (table->s->mysql_version < MYSQL_VERSION_ID)
{
if (unlikely((error= check_old_types())))
return error;
error= ha_check_for_upgrade(check_opt);
if (unlikely(error && (error != HA_ADMIN_NEEDS_CHECK)))
return error;
- if (table->s->table_category == TABLE_CATEGORY_USER &&
- (v < 100142 ||
- (v >= 100200 && v < 100228) ||
- (v >= 100300 && v < 100319) ||
- (v >= 100400 && v < 100409)))
- {
- for (const KEY *key= table->key_info,
- *end= table->key_info + table->s->keys; key < end; key++)
- {
- if (key->flags & HA_BINARY_PACK_KEY && key->flags & HA_VAR_LENGTH_KEY)
- return HA_ADMIN_NEEDS_UPGRADE;
- }
- }
if (unlikely(!error && (check_opt->sql_flags & TT_FOR_UPGRADE)))
return 0;
}
diff --git a/sql/item.cc b/sql/item.cc
index 991825663c2..385016d51b0 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -3597,11 +3597,6 @@ void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref,
/* just pull to the upper context */
ctx->outer_context= context->outer_context->outer_context;
}
- else
- {
- /* No upper context (merging Derived/VIEW where context chain ends) */
- ctx->outer_context= NULL;
- }
ctx->table_list= context->first_name_resolution_table;
ctx->select_lex= new_parent;
if (context->select_lex == NULL)
@@ -9898,6 +9893,8 @@ bool Item_trigger_field::set_value(THD *thd, sp_rcontext * /*ctx*/, Item **it)
Item *item= thd->sp_fix_func_item_for_assignment(field, it);
if (!item)
return true;
+ if (field->vers_sys_field())
+ return false;
// NOTE: field->table->copy_blobs should be false here, but let's
// remember the value at runtime to avoid subtle bugs.
diff --git a/sql/item.h b/sql/item.h
index b3fc475fcdc..5122d361dbb 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -214,7 +214,7 @@ struct Name_resolution_context: Sql_alloc
The name resolution context to search in when an Item cannot be
resolved in this context (the context of an outer select)
*/
- Name_resolution_context *outer_context;
+ Name_resolution_context *outer_context= nullptr;
/*
List of tables used to resolve the items of this context. Usually these
@@ -224,7 +224,7 @@ struct Name_resolution_context: Sql_alloc
statements we have to change this member dynamically to ensure correct
name resolution of different parts of the statement.
*/
- TABLE_LIST *table_list;
+ TABLE_LIST *table_list= nullptr;
/*
In most cases the two table references below replace 'table_list' above
for the purpose of name resolution. The first and last name resolution
@@ -232,62 +232,65 @@ struct Name_resolution_context: Sql_alloc
join tree in a FROM clause. This is needed for NATURAL JOIN, JOIN ... USING
and JOIN ... ON.
*/
- TABLE_LIST *first_name_resolution_table;
+ TABLE_LIST *first_name_resolution_table= nullptr;
/*
Last table to search in the list of leaf table references that begins
with first_name_resolution_table.
*/
- TABLE_LIST *last_name_resolution_table;
+ TABLE_LIST *last_name_resolution_table= nullptr;
/* Cache first_name_resolution_table in setup_natural_join_row_types */
- TABLE_LIST *natural_join_first_table;
+ TABLE_LIST *natural_join_first_table= nullptr;
/*
SELECT_LEX item belong to, in case of merged VIEW it can differ from
SELECT_LEX where item was created, so we can't use table_list/field_list
from there
*/
- st_select_lex *select_lex;
+ st_select_lex *select_lex= nullptr;
/*
Processor of errors caused during Item name resolving, now used only to
hide underlying tables in errors about views (i.e. it substitute some
errors for views)
*/
- void (*error_processor)(THD *, void *);
- void *error_processor_data;
+ void (*error_processor)(THD *, void *)= &dummy_error_processor;
+ void *error_processor_data= nullptr;
/*
When TRUE items are resolved in this context both against the
SELECT list and this->table_list. If FALSE, items are resolved
only against this->table_list.
*/
- bool resolve_in_select_list;
+ bool resolve_in_select_list= false;
/*
Bitmap of tables that should be ignored when doing name resolution.
Normally it is {0}. Non-zero values are used by table functions.
*/
- ignored_tables_list_t ignored_tables;
+ ignored_tables_list_t ignored_tables= nullptr;
/*
Security context of this name resolution context. It's used for views
and is non-zero only if the view is defined with SQL SECURITY DEFINER.
*/
- Security_context *security_ctx;
+ Security_context *security_ctx= nullptr;
- Name_resolution_context()
- :outer_context(0), table_list(0), select_lex(0),
- error_processor_data(0),
- ignored_tables(NULL),
- security_ctx(0)
- {}
+ Name_resolution_context() = default;
+
+ /**
+ Name resolution context with resolution in only one table
+ */
+ Name_resolution_context(TABLE_LIST *table) :
+ first_name_resolution_table(table), last_name_resolution_table(table)
+ {}
void init()
{
resolve_in_select_list= FALSE;
error_processor= &dummy_error_processor;
- first_name_resolution_table= NULL;
- last_name_resolution_table= NULL;
+ ignored_tables= nullptr;
+ first_name_resolution_table= nullptr;
+ last_name_resolution_table= nullptr;
}
void resolve_in_table_list_only(TABLE_LIST *tables)
@@ -2119,6 +2122,11 @@ public:
}
virtual Item* transform(THD *thd, Item_transformer transformer, uchar *arg);
+ virtual Item* top_level_transform(THD *thd, Item_transformer transformer,
+ uchar *arg)
+ {
+ return transform(thd, transformer, arg);
+ }
/*
This function performs a generic "compilation" of the Item tree.
@@ -2488,6 +2496,8 @@ public:
{ return this; }
virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg)
{ return this; }
+ virtual Item *in_predicate_to_equality_transformer(THD *thd, uchar *arg)
+ { return this; }
virtual Item *field_transformer_for_having_pushdown(THD *thd, uchar *arg)
{ return this; }
virtual Item *multiple_equality_transformer(THD *thd, uchar *arg)
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index c202a32c3be..8b31362a9d9 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -35,6 +35,7 @@
#define PCRE2_STATIC 1 /* Important on Windows */
#include "pcre2.h" /* pcre2 header file */
+#include "my_json_writer.h"
/*
Compare row signature of two expressions
@@ -417,9 +418,18 @@ bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp)
if (args[0]->cmp_type() == STRING_RESULT &&
args[1]->cmp_type() == STRING_RESULT)
{
+ Query_arena *arena, backup;
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+
DTCollation tmp;
- if (agg_arg_charsets_for_comparison(tmp, args, 2))
- return true;
+ bool ret= agg_arg_charsets_for_comparison(tmp, args, 2);
+
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+
+ if (ret)
+ return ret;
+
cmp->m_compare_collation= tmp.collation;
}
// Convert constants when compared to int/year field
@@ -4345,6 +4355,56 @@ Item_func_in::fix_fields(THD *thd, Item **ref)
}
+Item *Item_func_in::in_predicate_to_equality_transformer(THD *thd, uchar *arg)
+{
+ if (!array || have_null || !all_items_are_consts(args + 1, arg_count - 1))
+ return this; /* Transformation is not applicable */
+
+ /*
+ If all elements in the array of constant values are equal and there are
+ no NULLs in the list then clause
+ - "a IN (e1,..,en)" can be converted to "a = e1"
+ - "a NOT IN (e1,..,en)" can be converted to "a != e1".
+ This means an object of Item_func_in can be replaced with an object of
+ Item_func_eq for IN (e1,..,en) clause or Item_func_ne for
+ NOT IN (e1,...,en).
+ */
+
+ /*
+ Since the array is sorted it's enough to compare the first and the last
+ elements to tell whether all elements are equal
+ */
+ if (array->compare_elems(0, array->used_count - 1))
+ {
+ /* Not all elements are equal, transformation is not possible */
+ return this;
+ }
+
+ Json_writer_object trace_wrapper(thd);
+ trace_wrapper.add("transformation", "in_predicate_to_equality")
+ .add("before", this);
+
+ Item *new_item= nullptr;
+ if (negated)
+ new_item= new (thd->mem_root) Item_func_ne(thd, args[0], args[1]);
+ else
+ new_item= new (thd->mem_root) Item_func_eq(thd, args[0], args[1]);
+ if (new_item)
+ {
+ new_item->set_name(thd, name);
+ if (new_item->fix_fields(thd, &new_item))
+ {
+ /*
+ If there are any problems during fixing fields, there is no need to
+ return an error, just discard the transformation
+ */
+ new_item= this;
+ }
+ }
+ trace_wrapper.add("after", new_item);
+ return new_item;
+}
+
bool
Item_func_in::eval_not_null_tables(void *opt_arg)
{
@@ -5167,6 +5227,35 @@ Item *Item_cond::transform(THD *thd, Item_transformer transformer, uchar *arg)
/**
+ Transform an Item_cond object with a transformer callback function.
+
+ This is like transform() but doesn't use change_item_tree(),
+ because top-level expression is stored in prep_where/prep_on anyway and
+ is restored from there, there is no need to use change_item_tree().
+
+ Furthermore, it can be actually harmful to use it, if build_equal_items()
+ had replaced Item_eq with Item_equal and deleted list_node with a pointer
+ to Item_eq. In this case rollback_item_tree_changes() would modify the
+ deleted list_node.
+*/
+Item *Item_cond::top_level_transform(THD *thd, Item_transformer transformer, uchar *arg)
+{
+ DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare());
+
+ List_iterator<Item> li(list);
+ Item *item;
+ while ((item= li++))
+ {
+ Item *new_item= item->top_level_transform(thd, transformer, arg);
+ if (!new_item)
+ return 0;
+ *li.ref()= new_item;
+ }
+ return Item_func::transform(thd, transformer, arg);
+}
+
+
+/**
Compile Item_cond object with a processor and a transformer
callback functions.
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index fe55f524f89..2d4b73cc6d8 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -2620,6 +2620,7 @@ public:
bool to_be_transformed_into_in_subq(THD *thd);
bool create_value_list_for_tvc(THD *thd, List< List<Item> > *values);
Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg) override;
+ Item *in_predicate_to_equality_transformer(THD *thd, uchar *arg) override;
uint32 max_length_of_left_expr();
};
@@ -3179,6 +3180,7 @@ public:
void copy_andor_arguments(THD *thd, Item_cond *item);
bool walk(Item_processor processor, bool walk_subquery, void *arg) override;
Item *transform(THD *thd, Item_transformer transformer, uchar *arg) override;
+ Item *top_level_transform(THD *thd, Item_transformer transformer, uchar *arg) override;
void traverse_cond(Cond_traverser, void *arg, traverse_order order) override;
void neg_arguments(THD *thd);
Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *) override;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index ae57462df8e..f509e00b8f6 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2016, Oracle and/or its affiliates.
- Copyright (c) 2010, 2021, MariaDB
+ Copyright (c) 2010, 2022, 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
@@ -5288,12 +5288,9 @@ bool subselect_hash_sj_engine::make_semi_join_conds()
tmp_table_ref->init_one_table(&empty_clex_str, &table_name, NULL, TL_READ);
tmp_table_ref->table= tmp_table;
- context= new Name_resolution_context;
- context->init();
- context->first_name_resolution_table=
- context->last_name_resolution_table= tmp_table_ref;
+ context= new Name_resolution_context(tmp_table_ref);
semi_join_conds_context= context;
-
+
for (uint i= 0; i < item_in->left_expr->cols(); i++)
{
/* New equi-join condition for the current column. */
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 31aac7301d2..5d3c4facd81 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -6271,7 +6271,7 @@ void handle_connections_sockets()
}
#endif // HAVE_POLL
- for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
+ for (uint retry=0; retry < MAX_ACCEPT_RETRY && !abort_loop; retry++)
{
size_socket length= sizeof(struct sockaddr_storage);
MYSQL_SOCKET new_sock;
@@ -8017,7 +8017,7 @@ mysqld_get_one_option(const struct my_option *opt, const char *argument,
global_system_variables.log_warnings= atoi(argument);
break;
case 'T':
- test_flags= argument ? (uint) atoi(argument) : 0;
+ test_flags= argument ? ((uint) atoi(argument) & ~TEST_BLOCKING) : 0;
opt_endinfo=1;
break;
case OPT_THREAD_CONCURRENCY:
diff --git a/sql/privilege.h b/sql/privilege.h
index c1233102522..82173912e2a 100644
--- a/sql/privilege.h
+++ b/sql/privilege.h
@@ -293,7 +293,7 @@ constexpr privilege_t SHOW_CREATE_TABLE_ACLS=
existing temporary tables (CREATE_ACL is necessary for ALTER ... RENAME).
*/
constexpr privilege_t TMP_TABLE_ACLS=
- COL_DML_ACLS | ALL_TABLE_DDL_ACLS;
+ COL_DML_ACLS | ALL_TABLE_DDL_ACLS | REFERENCES_ACL;
constexpr privilege_t PRIV_LOCK_TABLES= SELECT_ACL | LOCK_TABLES_ACL;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 95ca8b233ce..90776566458 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -4102,7 +4102,7 @@ bool change_password(THD *thd, LEX_USER *user)
if (update_user_table_password(thd, tables.user_table(), *acl_user))
goto end;
- acl_cache->clear(1); // Clear locked hostname cache
+ hostname_cache_refresh(); // Clear locked hostname cache
mysql_mutex_unlock(&acl_cache->lock);
result= acl_cache_is_locked= 0;
if (mysql_bin_log.is_open())
@@ -4259,7 +4259,6 @@ int acl_set_default_role(THD *thd, const char *host, const char *user,
goto end;
}
- acl_cache->clear(1);
mysql_mutex_unlock(&acl_cache->lock);
result= 0;
if (mysql_bin_log.is_open())
@@ -7742,7 +7741,10 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
a role
*/
if (role_as_user)
+ {
propagate_role_grants(role_as_user, PRIVS_TO_MERGE::ALL);
+ acl_cache->clear(1);
+ }
}
mysql_mutex_unlock(&acl_cache->lock);
@@ -14147,11 +14149,11 @@ static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user)
if (global_system_variables.log_warnings)
sql_print_information("X509 issuer mismatch: should be '%s' "
"but is '%s'", acl_user->x509_issuer, ptr);
- free(ptr);
+ OPENSSL_free(ptr);
X509_free(cert);
return 1;
}
- free(ptr);
+ OPENSSL_free(ptr);
}
/* X509 subject is specified, we check it .. */
if (acl_user->x509_subject[0])
@@ -14164,11 +14166,11 @@ static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user)
if (global_system_variables.log_warnings)
sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
acl_user->x509_subject, ptr);
- free(ptr);
+ OPENSSL_free(ptr);
X509_free(cert);
return 1;
}
- free(ptr);
+ OPENSSL_free(ptr);
}
X509_free(cert);
return 0;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ee79115e65b..0913b3834f8 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -5111,12 +5111,22 @@ void reset_thd(MYSQL_THD thd)
before writing response to client, to provide durability
guarantees, in other words, server can't send OK packet
before modified data is durable in redo log.
-*/
-extern "C" void thd_increment_pending_ops(MYSQL_THD thd)
+
+ NOTE: system THD (those that are not associated with client
+ connection) do not allows async operations yet.
+
+ @param thd a THD
+ @return thd
+ @retval nullptr if this is system THD */
+extern "C" MYSQL_THD thd_increment_pending_ops(MYSQL_THD thd)
{
+ if (!thd || thd->system_thread != NON_SYSTEM_THREAD)
+ return nullptr;
thd->async_state.inc_pending_ops();
+ return thd;
}
+
/**
This function can be used by plugin/engine to indicate
end of async operation (such as end of group commit
@@ -5127,6 +5137,8 @@ extern "C" void thd_increment_pending_ops(MYSQL_THD thd)
extern "C" void thd_decrement_pending_ops(MYSQL_THD thd)
{
DBUG_ASSERT(thd);
+ DBUG_ASSERT(thd->system_thread == NON_SYSTEM_THREAD);
+
thd_async_state::enum_async_state state;
if (thd->async_state.dec_pending_ops(&state) == 0)
{
diff --git a/sql/sql_class.h b/sql/sql_class.h
index bd8c1faf412..2daa5705bfc 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -2590,9 +2590,6 @@ struct thd_async_state
}
};
-extern "C" void thd_increment_pending_ops(MYSQL_THD);
-extern "C" void thd_decrement_pending_ops(MYSQL_THD);
-
/**
@class THD
@@ -6116,7 +6113,7 @@ class select_insert :public select_result_interceptor {
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
virtual int prepare2(JOIN *join);
virtual int send_data(List<Item> &items);
- virtual void store_values(List<Item> &values);
+ virtual bool store_values(List<Item> &values, bool ignore_errors);
virtual bool can_rollback_data() { return 0; }
bool prepare_eof();
bool send_ok_packet();
@@ -6161,7 +6158,8 @@ public:
}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
- void store_values(List<Item> &values);
+ int binlog_show_create_table(TABLE **tables, uint count);
+ bool store_values(List<Item> &values, bool ignore_errors);
bool send_eof();
virtual void abort_result_set();
virtual bool can_rollback_data() { return 1; }
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc
index 3cee9bbb2c5..87095917f71 100644
--- a/sql/sql_explain.cc
+++ b/sql/sql_explain.cc
@@ -664,7 +664,11 @@ int Explain_node::print_explain_for_children(Explain_query *query,
for (int i= 0; i < (int) children.elements(); i++)
{
Explain_node *node= query->get_node(children.at(i));
- if (node->print_explain(query, output, explain_flags, is_analyze))
+ /*
+ Note: node may not be present because for certain kinds of subqueries,
+ the optimizer is not able to see that they were eliminated.
+ */
+ if (node && node->print_explain(query, output, explain_flags, is_analyze))
return 1;
}
return 0;
@@ -708,8 +712,15 @@ void Explain_node::print_explain_json_for_children(Explain_query *query,
for (int i= 0; i < (int) children.elements(); i++)
{
Explain_node *node= query->get_node(children.at(i));
- /* Derived tables are printed inside Explain_table_access objects */
+ /*
+ Note: node may not be present because for certain kinds of subqueries,
+ the optimizer is not able to see that they were eliminated.
+ */
+ if (!node)
+ continue;
+
+ /* Derived tables are printed inside Explain_table_access objects */
if (!is_connection_printable_in_json(node->connection_type))
continue;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 0d4eabd2d06..7d05e2bae79 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -95,8 +95,8 @@ pthread_handler_t handle_delayed_insert(void *arg);
static void unlink_blobs(TABLE *table);
#endif
static bool check_view_insertability(THD *thd, TABLE_LIST *view);
-static int binlog_show_create_table(THD *thd, TABLE *table,
- Table_specification_st *create_info);
+static int binlog_show_create_table_(THD *thd, TABLE *table,
+ Table_specification_st *create_info);
/*
Check that insert/update fields are from the same single table of a view.
@@ -4147,9 +4147,7 @@ int select_insert::send_data(List<Item> &values)
bool error=0;
thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields
- store_values(values);
- if (table->default_field &&
- unlikely(table->update_default_fields(info.ignore)))
+ if (store_values(values, info.ignore))
DBUG_RETURN(1);
thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
if (unlikely(thd->is_error()))
@@ -4207,18 +4205,19 @@ int select_insert::send_data(List<Item> &values)
}
-void select_insert::store_values(List<Item> &values)
+bool select_insert::store_values(List<Item> &values, bool ignore_errors)
{
DBUG_ENTER("select_insert::store_values");
+ bool error;
if (fields->elements)
- fill_record_n_invoke_before_triggers(thd, table, *fields, values, 1,
- TRG_EVENT_INSERT);
+ error= fill_record_n_invoke_before_triggers(thd, table, *fields, values,
+ ignore_errors, TRG_EVENT_INSERT);
else
- fill_record_n_invoke_before_triggers(thd, table, table->field_to_fill(),
- values, 1, TRG_EVENT_INSERT);
+ error= fill_record_n_invoke_before_triggers(thd, table, table->field_to_fill(),
+ values, ignore_errors, TRG_EVENT_INSERT);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(error);
}
bool select_insert::prepare_eof()
@@ -4753,7 +4752,7 @@ select_create::prepare(List<Item> &_values, SELECT_LEX_UNIT *u)
TABLE const *const table = *tables;
if (thd->is_current_stmt_binlog_format_row() &&
!table->s->tmp_table)
- return binlog_show_create_table(thd, *tables, ptr->create_info);
+ return binlog_show_create_table_(thd, *tables, ptr->create_info);
return 0;
}
select_create *ptr;
@@ -4874,8 +4873,8 @@ select_create::prepare(List<Item> &_values, SELECT_LEX_UNIT *u)
}
-static int binlog_show_create_table(THD *thd, TABLE *table,
- Table_specification_st *create_info)
+static int binlog_show_create_table_(THD *thd, TABLE *table,
+ Table_specification_st *create_info)
{
/*
Note 1: In RBR mode, we generate a CREATE TABLE statement for the
@@ -4968,7 +4967,7 @@ bool binlog_create_table(THD *thd, TABLE *table, bool replace)
HA_CREATE_USED_DEFAULT_CHARSET);
/* Ensure we write all engine options to binary log */
create_info.used_fields|= HA_CREATE_PRINT_ALL_OPTIONS;
- result= binlog_show_create_table(thd, table, &create_info) != 0;
+ result= binlog_show_create_table_(thd, table, &create_info) != 0;
thd->variables.option_bits= save_option_bits;
return result;
}
@@ -5010,10 +5009,10 @@ bool binlog_drop_table(THD *thd, TABLE *table)
}
-void select_create::store_values(List<Item> &values)
+bool select_create::store_values(List<Item> &values, bool ignore_errors)
{
- fill_record_n_invoke_before_triggers(thd, table, field, values, 1,
- TRG_EVENT_INSERT);
+ return fill_record_n_invoke_before_triggers(thd, table, field, values,
+ ignore_errors, TRG_EVENT_INSERT);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index b98d4a62c55..57f7cfac595 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2951,6 +2951,7 @@ void st_select_lex::init_query()
min_max_opt_list.empty();
limit_params.clear();
join= 0;
+ cur_pos_in_select_list= UNDEF_POS;
having= prep_having= where= prep_where= 0;
cond_pushed_into_where= cond_pushed_into_having= 0;
attach_to_conds.empty();
@@ -10872,9 +10873,8 @@ st_select_lex::build_pushable_cond_for_having_pushdown(THD *thd, Item *cond)
*/
if (cond->get_extraction_flag() == MARKER_FULL_EXTRACTION)
{
- Item *result= cond->transform(thd,
- &Item::multiple_equality_transformer,
- (uchar *)this);
+ Item *result= cond->top_level_transform(thd,
+ &Item::multiple_equality_transformer, (uchar *)this);
if (!result)
return true;
if (result->type() == Item::COND_ITEM &&
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 784194e1dd7..3d0809f8785 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -7041,13 +7041,13 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
@brief Check if the requested privileges exists in either User-, Host- or
Db-tables.
@param thd Thread context
- @param want_access Privileges requested
+ @param requirements Privileges requested
@param tables List of tables to be compared against
- @param no_errors Don't report error to the client (using my_error() call).
@param any_combination_of_privileges_will_do TRUE if any privileges on any
column combination is enough.
@param number Only the first 'number' tables in the linked list are
relevant.
+ @param no_errors Don't report error to the client (using my_error() call).
The suppled table list contains cached privileges. This functions calls the
help functions check_access and check_grant to verify the first three steps
@@ -7074,7 +7074,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
bool
check_table_access(THD *thd, privilege_t requirements, TABLE_LIST *tables,
- bool any_combination_of_privileges_will_do,
+ bool any_combination_of_privileges_will_do,
uint number, bool no_errors)
{
TABLE_LIST *org_tables= tables;
@@ -9022,7 +9022,6 @@ push_new_name_resolution_context(THD *thd,
Name_resolution_context *on_context;
if (!(on_context= new (thd->mem_root) Name_resolution_context))
return TRUE;
- on_context->init();
on_context->first_name_resolution_table=
left_op->first_leaf_for_name_resolution();
on_context->last_name_resolution_table=
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index c82744ae48e..65d515d312f 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -5630,6 +5630,7 @@ public:
MEM_ROOT *alloc;
THD *new_thd;
Security_context empty_ctx;
+ ulonglong client_capabilities;
my_bool do_log_bin;
@@ -6257,6 +6258,7 @@ loc_advanced_command(MYSQL *mysql, enum enum_server_command command,
{
Ed_connection con(p->thd);
Security_context *ctx_orig= p->thd->security_ctx;
+ ulonglong cap_orig= p->thd->client_capabilities;
MYSQL_LEX_STRING sql_text;
my_bool log_bin_orig;
p->set_binlog_vars(&log_bin_orig);
@@ -6265,7 +6267,9 @@ loc_advanced_command(MYSQL *mysql, enum enum_server_command command,
sql_text.str= (char *) arg;
sql_text.length= arg_length;
p->thd->security_ctx= &p->empty_ctx;
+ p->thd->client_capabilities= p->client_capabilities;
result= con.execute_direct(p, sql_text);
+ p->thd->client_capabilities= cap_orig;
p->thd->security_ctx= ctx_orig;
p->restore_binlog_vars(log_bin_orig);
}
@@ -6391,6 +6395,7 @@ extern "C" MYSQL *mysql_real_connect_local(MYSQL *mysql)
THD *thd_orig= current_thd;
THD *new_thd;
Protocol_local *p;
+ ulonglong client_flag;
DBUG_ENTER("mysql_real_connect_local");
/* Test whether we're already connected */
@@ -6402,6 +6407,9 @@ extern "C" MYSQL *mysql_real_connect_local(MYSQL *mysql)
mysql->methods= &local_methods;
mysql->user= NULL;
+ client_flag= mysql->options.client_flag;
+ client_flag|= CLIENT_MULTI_RESULTS;;
+ client_flag&= ~(CLIENT_COMPRESS | CLIENT_PLUGIN_AUTH);
mysql->info_buffer= (char *) my_malloc(PSI_INSTRUMENT_ME,
MYSQL_ERRMSG_SIZE, MYF(0));
@@ -6425,6 +6433,7 @@ extern "C" MYSQL *mysql_real_connect_local(MYSQL *mysql)
new_thd->variables.wsrep_on= 0;
new_thd->variables.sql_log_bin= 0;
new_thd->set_binlog_bit();
+ new_thd->client_capabilities= client_flag;
/*
TOSO: decide if we should turn the auditing off
@@ -6446,6 +6455,7 @@ extern "C" MYSQL *mysql_real_connect_local(MYSQL *mysql)
{
p->empty_ctx.init();
p->empty_ctx.skip_grants();
+ p->client_capabilities= client_flag;
}
mysql->thd= p;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 9bd6aa4d5d3..794bcca00da 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2216,6 +2216,9 @@ JOIN::optimize_inner()
ignore_on_expr= true;
break;
}
+
+ transform_in_predicates_into_equalities(thd);
+
conds= optimize_cond(this, conds, join_list, ignore_on_expr,
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
@@ -30463,6 +30466,95 @@ static bool process_direct_rownum_comparison(THD *thd, SELECT_LEX_UNIT *unit,
DBUG_RETURN(false);
}
+/**
+ @brief
+ Transform IN predicates having equal constant elements to equalities
+
+ @param thd The context of the statement
+
+ @details
+ If all elements in an IN predicate are constant and equal to each other
+ then clause
+ - "a IN (e1,..,en)" can be transformed to "a = e1"
+ - "a NOT IN (e1,..,en)" can be transformed to "a != e1".
+ This means an object of Item_func_in can be replaced with an object of
+ Item_func_eq for IN (e1,..,en) clause or Item_func_ne for
+ NOT IN (e1,...,en).
+ Such a replacement allows the optimizer to choose a better execution plan.
+
+ This methods applies such transformation for each IN predicate of the WHERE
+ condition and ON expressions of this join where possible
+
+ @retval
+ false success
+ true failure
+*/
+bool JOIN::transform_in_predicates_into_equalities(THD *thd)
+{
+ DBUG_ENTER("JOIN::transform_in_predicates_into_equalities");
+ DBUG_RETURN(transform_all_conds_and_on_exprs(
+ thd, &Item::in_predicate_to_equality_transformer));
+}
+
+
+/**
+ @brief
+ Transform all items in WHERE and ON expressions using a given transformer
+
+ @param thd The context of the statement
+ transformer Pointer to the transformation function
+
+ @details
+ For each item of the WHERE condition and ON expressions of the SELECT
+ for this join the method performs the intransformation using the given
+ transformation function
+
+ @retval
+ false success
+ true failure
+*/
+bool JOIN::transform_all_conds_and_on_exprs(THD *thd,
+ Item_transformer transformer)
+{
+ if (conds)
+ {
+ conds= conds->top_level_transform(thd, transformer, (uchar *) 0);
+ if (!conds)
+ return true;
+ }
+ if (join_list)
+ {
+ if (transform_all_conds_and_on_exprs_in_join_list(thd, join_list,
+ transformer))
+ return true;
+ }
+ return false;
+}
+
+
+bool JOIN::transform_all_conds_and_on_exprs_in_join_list(
+ THD *thd, List<TABLE_LIST> *join_list, Item_transformer transformer)
+{
+ TABLE_LIST *table;
+ List_iterator<TABLE_LIST> li(*join_list);
+
+ while ((table= li++))
+ {
+ if (table->nested_join)
+ {
+ if (transform_all_conds_and_on_exprs_in_join_list(
+ thd, &table->nested_join->join_list, transformer))
+ return true;
+ }
+ if (table->on_expr)
+ {
+ table->on_expr= table->on_expr->top_level_transform(thd, transformer, 0);
+ if (!table->on_expr)
+ return true;
+ }
+ }
+ return false;
+}
/**
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 3a28c431df5..5aa775f4a2d 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1792,6 +1792,12 @@ private:
bool make_aggr_tables_info();
bool add_fields_for_current_rowid(JOIN_TAB *cur, List<Item> *fields);
void init_join_cache_and_keyread();
+ bool transform_in_predicates_into_equalities(THD *thd);
+ bool transform_all_conds_and_on_exprs(THD *thd,
+ Item_transformer transformer);
+ bool transform_all_conds_and_on_exprs_in_join_list(THD *thd,
+ List<TABLE_LIST> *join_list,
+ Item_transformer transformer);
};
enum enum_with_bush_roots { WITH_BUSH_ROOTS, WITHOUT_BUSH_ROOTS};
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 173cac3a3b7..a2a1c76411c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -6057,6 +6057,15 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
show_table->use_all_columns(); // Required for default
restore_record(show_table, s->default_values);
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ check_access(thd, SELECT_ACL, db_name->str,
+ &tables->grant.privilege, 0, 0, MY_TEST(tables->schema_table));
+ if (is_temporary_table(tables))
+ {
+ tables->grant.privilege|= TMP_TABLE_ACLS;
+ }
+#endif
+
for (; (field= *ptr) ; ptr++)
{
if(field->invisible > INVISIBLE_USER)
@@ -6076,14 +6085,13 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
restore_record(table, s->default_values);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- ulonglong col_access;
- check_access(thd,SELECT_ACL, db_name->str,
- &tables->grant.privilege, 0, 0, MY_TEST(tables->schema_table));
- col_access= get_column_grant(thd, &tables->grant,
- db_name->str, table_name->str,
- field->field_name.str) & COL_ACLS;
- if (!tables->schema_table && !col_access)
+ ulonglong col_access=
+ get_column_grant(thd, &tables->grant, db_name->str, table_name->str,
+ field->field_name.str) & COL_ACLS;
+
+ if (!col_access && !tables->schema_table)
continue;
+
char *end= tmp;
for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
{
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index 8bb96dfa776..12e4460ed25 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -68,62 +68,71 @@ int append_interval(String *str, interval_type int_type, const INTERVAL &interva
size_t len;
switch (int_type) {
case INTERVAL_YEAR:
- len= my_snprintf(buf,sizeof(buf),"%u", interval.year);
+ len= my_snprintf(buf,sizeof(buf),"%lu", interval.year);
break;
case INTERVAL_QUARTER:
case INTERVAL_MONTH:
- len= my_snprintf(buf,sizeof(buf),"%u", interval.month);
+ len= my_snprintf(buf,sizeof(buf),"%lu", interval.month);
int_type=INTERVAL_MONTH;
break;
case INTERVAL_WEEK:
case INTERVAL_DAY:
- len= my_snprintf(buf,sizeof(buf),"%u", interval.day);
+ len= my_snprintf(buf,sizeof(buf),"%lu", interval.day);
int_type=INTERVAL_DAY;
break;
case INTERVAL_HOUR:
- len= my_snprintf(buf,sizeof(buf),"%u", interval.hour);
+ len= my_snprintf(buf,sizeof(buf),"%lu", interval.hour);
break;
case INTERVAL_MINUTE:
- len= my_snprintf(buf,sizeof(buf),"%u", interval.minute);
+ len= my_snprintf(buf,sizeof(buf),"%llu", interval.minute);
break;
case INTERVAL_SECOND:
- len= my_snprintf(buf,sizeof(buf),"%u", interval.second);
+ len= my_snprintf(buf,sizeof(buf),"%llu", interval.second);
break;
case INTERVAL_MICROSECOND:
- len= my_snprintf(buf,sizeof(buf),"%u", interval.second_part);
+ len= my_snprintf(buf,sizeof(buf),"%llu", interval.second_part);
break;
case INTERVAL_YEAR_MONTH:
- len= my_snprintf(buf,sizeof(buf),"%u-%02u", interval.day, interval.month);
+ len= my_snprintf(buf,sizeof(buf),"'%lu-%02lu'",
+ interval.year, interval.month);
break;
case INTERVAL_DAY_HOUR:
- len= my_snprintf(buf,sizeof(buf),"%u %u", interval.day, interval.hour);
+ len= my_snprintf(buf,sizeof(buf),"'%lu %lu'", interval.day, interval.hour);
break;
case INTERVAL_DAY_MINUTE:
- len= my_snprintf(buf,sizeof(buf),"%u %u:%02u", interval.day, interval.hour, interval.minute);
+ len= my_snprintf(buf,sizeof(buf),"'%lu %lu:%02llu'",
+ interval.day, interval.hour, interval.minute);
break;
case INTERVAL_DAY_SECOND:
- len= my_snprintf(buf,sizeof(buf),"%u %u:%02u:%02u", interval.day, interval.hour, interval.minute, interval.second);
+ len= my_snprintf(buf,sizeof(buf),"'%lu %lu:%02llu:%02llu'",
+ interval.day, interval.hour, interval.minute, interval.second);
break;
case INTERVAL_HOUR_MINUTE:
- len= my_snprintf(buf,sizeof(buf),"%u:%02u", interval.hour, interval.minute);
+ len= my_snprintf(buf,sizeof(buf),"'%lu:%02llu'", interval.hour, interval.minute);
break;
case INTERVAL_HOUR_SECOND:
- len= my_snprintf(buf,sizeof(buf),"%u:%02u:%02u", interval.hour, interval.minute, interval.second);
+ len= my_snprintf(buf,sizeof(buf),"'%lu:%02llu:%02llu'",
+ interval.hour, interval.minute, interval.second);
break;
case INTERVAL_MINUTE_SECOND:
- len= my_snprintf(buf,sizeof(buf),"%u:%02u", interval.minute, interval.second);
+ len= my_snprintf(buf,sizeof(buf),"'%llu:%02llu'", interval.minute, interval.second);
break;
case INTERVAL_DAY_MICROSECOND:
- len= my_snprintf(buf,sizeof(buf),"%u %u:%02u:%02u.%06u", interval.day, interval.hour, interval.minute, interval.second, interval.second_part);
+ len= my_snprintf(buf,sizeof(buf),"'%lu %lu:%02llu:%02llu.%06llu'",
+ interval.day, interval.hour, interval.minute,
+ interval.second, interval.second_part);
break;
case INTERVAL_HOUR_MICROSECOND:
- len= my_snprintf(buf,sizeof(buf),"%u:%02u:%02u.%06u", interval.hour, interval.minute, interval.second, interval.second_part);
+ len= my_snprintf(buf,sizeof(buf),"'%lu:%02llu:%02llu.%06llu'",
+ interval.hour, interval.minute, interval.second,
+ interval.second_part);
break;
case INTERVAL_MINUTE_MICROSECOND:
- len= my_snprintf(buf,sizeof(buf),"%u:%02u.%06u", interval.minute, interval.second, interval.second_part);
+ len= my_snprintf(buf,sizeof(buf),"'%llu:%02llu.%06llu'",
+ interval.minute, interval.second, interval.second_part);
break;
case INTERVAL_SECOND_MICROSECOND:
- len= my_snprintf(buf,sizeof(buf),"%u.%06u", interval.second, interval.second_part);
+ len= my_snprintf(buf,sizeof(buf),"%llu.%06llu", interval.second, interval.second_part);
break;
default:
DBUG_ASSERT(0);
diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc
index a045d0e3908..6e6d446ce16 100644
--- a/sql/sql_tvc.cc
+++ b/sql/sql_tvc.cc
@@ -1173,12 +1173,10 @@ bool JOIN::transform_in_predicates_into_in_subq(THD *thd)
{
select_lex->parsing_place= IN_WHERE;
conds=
- conds->transform(thd,
- &Item::in_predicate_to_in_subs_transformer,
- (uchar*) 0);
+ conds->top_level_transform(thd,
+ &Item::in_predicate_to_in_subs_transformer, 0);
if (!conds)
DBUG_RETURN(true);
- select_lex->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
select_lex->where= conds;
}
@@ -1193,13 +1191,10 @@ bool JOIN::transform_in_predicates_into_in_subq(THD *thd)
if (table->on_expr)
{
table->on_expr=
- table->on_expr->transform(thd,
- &Item::in_predicate_to_in_subs_transformer,
- (uchar*) 0);
+ table->on_expr->top_level_transform(thd,
+ &Item::in_predicate_to_in_subs_transformer, 0);
if (!table->on_expr)
DBUG_RETURN(true);
- table->prep_on_expr= table->on_expr ?
- table->on_expr->copy_andor_structure(thd) : 0;
}
}
}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 7a52b822b9d..a2b744fc8be 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1245,19 +1245,26 @@ err:
bool mariadb_view_version_get(TABLE_SHARE *share)
{
DBUG_ASSERT(share->is_view);
+ DBUG_ASSERT(share->tabledef_version.length == 0);
if (!(share->tabledef_version.str=
(uchar*) alloc_root(&share->mem_root,
MICROSECOND_TIMESTAMP_BUFFER_SIZE)))
return TRUE;
- share->tabledef_version.length= 0; // safety if the drfinition file is brocken
DBUG_ASSERT(share->view_def != NULL);
if (share->view_def->parse((uchar *) &share->tabledef_version, NULL,
view_timestamp_parameters, 1,
&file_parser_dummy_hook))
+ {
+ // safety if the definition file is brocken
+ share->tabledef_version.length= 0;
+ my_error(ER_TABLE_CORRUPT, MYF(0),
+ share->db.str, share->table_name.str);
return TRUE;
+ }
DBUG_ASSERT(share->tabledef_version.length == MICROSECOND_TIMESTAMP_BUFFER_SIZE-1);
+
return FALSE;
}
@@ -1322,10 +1329,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
mysql_handle_single_derived(thd->lex, table, DT_REINIT);
DEBUG_SYNC(thd, "after_cached_view_opened");
- if (!share->tabledef_version.length)
- {
- mariadb_view_version_get(share);
- }
+ DBUG_ASSERT(share->tabledef_version.length);
DBUG_RETURN(0);
}
@@ -1379,15 +1383,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
required_view_parameters,
&file_parser_dummy_hook)))
goto end;
- if (!share->tabledef_version.length)
- {
- share->tabledef_version.str= (const uchar *)
- memdup_root(&share->mem_root,
- (const void *)
- table->hr_timestamp.str,
- (share->tabledef_version.length=
- table->hr_timestamp.length));
- }
+ DBUG_ASSERT(share->tabledef_version.length);
if (!table->tabledef_version.length)
{
table->set_view_def_version(&table->hr_timestamp);
diff --git a/sql/sql_view.h b/sql/sql_view.h
index 536b5f1b784..1b880e43eb1 100644
--- a/sql/sql_view.h
+++ b/sql/sql_view.h
@@ -66,4 +66,6 @@ extern const LEX_CSTRING view_type;
void make_valid_column_names(List<Item> &item_list);
+bool mariadb_view_version_get(TABLE_SHARE *share);
+
#endif /* SQL_VIEW_INCLUDED */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 0f651865a89..1c13fc1a1e1 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -5116,11 +5116,12 @@ server_part_option:
opt_versioning_rotation:
/* empty */ {}
- | INTERVAL_SYM expr interval opt_versioning_interval_start
+ | { Lex->clause_that_disallows_subselect= "INTERVAL"; }
+ INTERVAL_SYM expr interval opt_versioning_interval_start
{
partition_info *part_info= Lex->part_info;
const char *table_name= Lex->create_last_non_select_table->table_name.str;
- if (unlikely(part_info->vers_set_interval(thd, $2, $3, $4, table_name)))
+ if (unlikely(part_info->vers_set_interval(thd, $3, $4, $5, table_name)))
MYSQL_YYABORT;
}
| LIMIT ulonglong_num
diff --git a/sql/table.cc b/sql/table.cc
index b25779c3de8..6c20a1f8bbd 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -673,7 +673,11 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
if (!share->view_def)
share->error= OPEN_FRM_ERROR_ALREADY_ISSUED;
else
+ {
share->error= OPEN_FRM_OK;
+ if (mariadb_view_version_get(share))
+ share->error= OPEN_FRM_ERROR_ALREADY_ISSUED;
+ }
}
else
share->error= OPEN_FRM_NOT_A_TABLE;
@@ -8891,7 +8895,7 @@ int TABLE::update_virtual_field(Field *vf, bool ignore_warnings)
Counting_error_handler count_errors;
Suppress_warnings_error_handler warning_handler;
in_use->push_internal_handler(&count_errors);
- bool abort_on_warning;
+ bool abort_on_warning= ignore_warnings;
if (ignore_warnings)
{
abort_on_warning= in_use->abort_on_warning;
@@ -9716,7 +9720,8 @@ bool TABLE_LIST::change_refs_to_fields()
Item **materialized_items=
(Item **)thd->calloc(sizeof(void *) * table->s->fields);
- if (!materialized_items)
+ Name_resolution_context *ctx= new Name_resolution_context(this);
+ if (!materialized_items || !ctx)
return TRUE;
while ((ref= (Item_direct_ref*)li++))
@@ -9732,7 +9737,8 @@ bool TABLE_LIST::change_refs_to_fields()
DBUG_ASSERT(!field_it.end_of_fields());
if (!materialized_items[idx])
{
- materialized_items[idx]= new (thd->mem_root) Item_field(thd, table->field[idx]);
+ materialized_items[idx]=
+ new (thd->mem_root) Item_field(thd, ctx, table->field[idx]);
if (!materialized_items[idx])
return TRUE;
}