Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä 2021-04-21 07:58:42 +03:00
commit a0588d54a2
33 changed files with 675 additions and 127 deletions

View file

@ -683,6 +683,31 @@ bool Item_subselect::is_expensive()
}
static
int walk_items_for_table_list(Item_processor processor,
bool walk_subquery, void *argument,
List<TABLE_LIST>& join_list)
{
List_iterator<TABLE_LIST> li(join_list);
int res;
while (TABLE_LIST *table= li++)
{
if (table->on_expr)
{
if ((res= table->on_expr->walk(processor, walk_subquery, argument)))
return res;
}
if (table->nested_join)
{
if ((res= walk_items_for_table_list(processor, walk_subquery, argument,
table->nested_join->join_list)))
return res;
}
}
return 0;
}
bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
void *argument)
{
@ -714,7 +739,10 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
if (lex->having && (lex->having)->walk(processor, walk_subquery,
argument))
return 1;
/* TODO: why does this walk WHERE/HAVING but not ON expressions of outer joins? */
if (walk_items_for_table_list(processor, walk_subquery, argument,
*lex->join_list))
return 1;
while ((item=li++))
{

View file

@ -26,7 +26,7 @@
Used instead of FILE when reading or writing whole files.
This will make mf_rec_cache obsolete.
One can change info->pos_in_file to a higher value to skip bytes in file if
also info->rc_pos is set to info->rc_end.
also info->read_pos is set to info->read_end.
If called through open_cached_file(), then the temporary file will
only be created if a write exeeds the file buffer or if one calls
flush_io_cache().

View file

@ -32,7 +32,7 @@
#endif
#ifdef __APPLE__
#if defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/sysctl.h>
#endif
@ -57,7 +57,7 @@ extern const char *optimizer_switch_names[];
static inline void output_core_info()
{
/* proc is optional on some BSDs so it can't hurt to look */
#if defined(HAVE_READLINK) && !defined(__APPLE__)
#if defined(HAVE_READLINK) && !defined(__APPLE__) && !defined(__FreeBSD__)
char buff[PATH_MAX];
ssize_t len;
int fd;
@ -83,7 +83,7 @@ static inline void output_core_info()
my_close(fd, MYF(0));
}
#endif
#elif defined(__APPLE__)
#elif defined(__APPLE__) || defined(__FreeBSD__)
char buff[PATH_MAX];
size_t len = sizeof(buff);
if (sysctlbyname("kern.corefile", buff, &len, NULL, 0) == 0)

View file

@ -1,6 +1,6 @@
/*
Copyright (c) 2002, 2011, Oracle and/or its affiliates.
Copyright (c) 2010, 2020, MariaDB
Copyright (c) 2010, 2021, 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
@ -596,6 +596,32 @@ bool mysql_derived_init(THD *thd, LEX *lex, TABLE_LIST *derived)
}
/**
@brief
Prevent name resolution out of context of ON expressions in derived tables
@param
join_list list of tables used in from list of a derived
@details
The function sets the Name_resolution_context::outer_context to NULL
for all ON expressions contexts in the given join list. It does this
recursively for all nested joins the list contains.
*/
static void nullify_outer_context_for_on_clauses(List<TABLE_LIST>& join_list)
{
List_iterator<TABLE_LIST> li(join_list);
while (TABLE_LIST *table= li++)
{
if (table->on_context)
table->on_context->outer_context= NULL;
if (table->nested_join)
nullify_outer_context_for_on_clauses(table->nested_join->join_list);
}
}
/*
Create temporary table structure (but do not fill it)
@ -760,7 +786,12 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
/* prevent name resolving out of derived table */
for (SELECT_LEX *sl= first_select; sl; sl= sl->next_select())
{
// Prevent it for the WHERE clause
sl->context.outer_context= 0;
// And for ON clauses, if there are any
nullify_outer_context_for_on_clauses(*sl->join_list);
if (!derived->is_with_table_recursive_reference() ||
(!derived->with->with_anchor &&
!derived->with->is_with_prepared_anchor()))

View file

@ -9392,7 +9392,7 @@ SELECT_LEX *LEX::parsed_subselect(SELECT_LEX_UNIT *unit)
(curr_sel == NULL && current_select == &builtin_select));
if (curr_sel)
{
curr_sel->register_unit(unit, &curr_sel->context);
curr_sel->register_unit(unit, context_stack.head());
curr_sel->add_statistics(unit);
}

View file

@ -7607,6 +7607,7 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
bool new_select= select_lex == NULL;
int old_nest_level= lex->current_select->nest_level;
DBUG_ENTER("mysql_new_select");
Name_resolution_context *curr_context;
if (new_select)
{
@ -7614,6 +7615,7 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
DBUG_RETURN(1);
select_lex->select_number= ++thd->lex->stmt_lex->current_select_number;
select_lex->parent_lex= lex; /* Used in init_query. */
curr_context= lex->context_stack.head();
select_lex->init_query();
select_lex->init_select();
}
@ -7635,7 +7637,8 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
By default we assume that it is usual subselect and we have outer name
resolution context, if no we will assign it to 0 later
*/
select_lex->context.outer_context= &select_lex->outer_select()->context;
select_lex->context.outer_context= curr_context;
}
else
{

View file

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
Copyright (c) 2010, 2020, MariaDB
Copyright (c) 2010, 2021, 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
@ -8318,7 +8318,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
def->real_field_type() == MYSQL_TYPE_NEWDATE ||
def->real_field_type() == MYSQL_TYPE_DATETIME ||
def->real_field_type() == MYSQL_TYPE_DATETIME2) &&
!alter_ctx->datetime_field &&
!alter_ctx->datetime_field && !def->field &&
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
thd->variables.sql_mode & MODE_NO_ZERO_DATE)
{
@ -8527,7 +8527,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
key_parts.push_back(new (thd->mem_root) Key_part_spec(&cfield->field_name,
key_part_length, true),
thd->mem_root);
if (cfield->invisible < INVISIBLE_SYSTEM)
if (!(cfield->invisible == INVISIBLE_SYSTEM && cfield->vers_sys_field()))
user_keyparts= true;
}
if (table->s->tmp_table == NO_TMP_TABLE)
@ -8539,6 +8539,14 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
(void) delete_statistics_for_index(thd, table, key_info, TRUE);
}
if (!user_keyparts && key_parts.elements)
{
/*
If we dropped all user key-parts we also drop implicit system fields.
*/
key_parts.empty();
}
if (key_parts.elements)
{
KEY_CREATE_INFO key_create_info;
@ -8574,7 +8582,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
key_type= Key::PRIMARY;
else
key_type= Key::UNIQUE;
if (dropped_key_part && user_keyparts)
if (dropped_key_part)
{
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), dropped_key_part);
if (long_hash_key)