Commit dd1c1c1b authored by Otto Kekäläinen's avatar Otto Kekäläinen
Browse files

Merge tag 'upstream/5.5.57' into ubuntu-14.04

Upstream version 5.5.57

# gpg: Signature made su 23. heinäkuuta 2017 23.35.34 EEST
# gpg:                using RSA key BED8449FCEE8DA88
# gpg: Good signature from "Otto Kekäläinen <otto@seravo.fi>" [full]
# gpg:                 aka "Otto Kekäläinen <otto@kekalainen.net>" [full]
# gpg:                 aka "Otto Kekäläinen <otto@fsfe.org>" [full]
# gpg:                 aka "Otto Kekäläinen <otto@linux.com>" [full]
# gpg:                 aka "Otto Kekäläinen <otto.kekalainen@seravo.fi>" [full]
# gpg:                 aka "Otto Kekäläinen <otto@mariadb.org>" [undefined]
# gpg:                 aka "Otto Kekäläinen <otto@debian.org>" [undefined]
# gpg:                 aka "Otto Kekäläinen <otto@sange.fi>" [full]
parents fb3d7b9e 69b6b895
#!/usr/bin/perl
#!@PERL_PATH@
# -*- cperl -*-
#
# Copyright (c) 2007, 2013, Oracle and/or its affiliates.
# Copyright (c) 2007, 2017, Oracle and/or its affiliates.
#
# 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
......
#!/usr/bin/perl
#!@PERL_PATH@
# -*- cperl -*-
#
# Copyright (c) 2007, 2012, Oracle and/or its affiliates.
# Copyright (c) 2007, 2017, Oracle and/or its affiliates.
#
# 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
......@@ -388,6 +388,3 @@ Thanks for using MySQL!
HERE
#!/usr/bin/perl
#!@PERL_PATH@
## Emacs, this is -*- perl -*- mode? :-)
# Copyright (c) 2000, 2007 MySQL AB, 2009 Sun Microsystems, Inc.
# Use is subject to license terms.
# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
......
#!/usr/bin/perl
# Copyright (c) 2000-2002, 2004, 2006 MySQL AB, 2009 Sun Microsystems, Inc.
# Use is subject to license terms.
#!@PERL_PATH@
# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# 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
......
#!/usr/bin/perl
#!@PERL_PATH@
# Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
......@@ -477,15 +477,22 @@ MySQLaccess::Report::Print_Header();
# *****************************
# Read configuration-file
MySQLaccess::Debug::Print(1, "Reading configuration file...");
if (-f "./$script_conf") {
require "./$script_conf";
}
elsif (-f "@sysconfdir@/$script_conf") {
if (-f "@sysconfdir@/$script_conf") {
print "Configuration file '$script_conf' is found in '@sysconfdir@/'\n";
require "@sysconfdir@/$script_conf";
}
elsif (-f "/etc/$script_conf") {
print "Configuration file '$script_conf' is found in '/etc/'\n";
require "/etc/$script_conf";
}
elsif (-f "./$script_conf") {
print "\nERROR! Configuration file '$script_conf' is found in the current ";
print "directory.\nThe permissible locations for this file are either ";
print "@sysconfdir@/ or /etc/\n";
print "Please move it to one of these locations and retry.\n\n";
exit 0;
}
# ****************************
# Read in all parameters
......
#!/usr/bin/perl
# Copyright (c) 2000, 2010, Oracle and/or its affiliates.
# Copyright (c) 2000-2011 Monty Program Ab, Jani Tolonen
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; version 2
# of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
# MA 02110-1301, USA
#!@PERL_PATH@
# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2000, 2017, Oracle and/or its affiliates.
# Copyright (c) 2010, 2017, MariaDB Corporation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
......
#!/usr/bin/perl
#!@PERL_PATH@
# Copyright (c) 2000-2002, 2005-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
# Use is subject to license terms.
# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
......
#!/usr/bin/perl
#!@PERL_PATH@
# Copyright (c) 2000, 2010, Oracle and/or its affiliates
# Copyright (c) 2000, 2017, Oracle and/or its affiliates.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
......
......@@ -634,7 +634,7 @@ int ha_partition::create(const char *name, TABLE *table_arg,
int ha_partition::drop_partitions(const char *path)
{
List_iterator<partition_element> part_it(m_part_info->partitions);
char part_name_buff[FN_REFLEN];
char part_name_buff[FN_REFLEN + 1];
uint num_parts= m_part_info->partitions.elements;
uint num_subparts= m_part_info->num_subparts;
uint i= 0;
......@@ -667,9 +667,11 @@ int ha_partition::drop_partitions(const char *path)
{
partition_element *sub_elem= sub_it++;
part= i * num_subparts + j;
create_subpartition_name(part_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name, name_variant);
if ((ret_error= create_subpartition_name(part_name_buff,
sizeof(part_name_buff), path,
part_elem->partition_name,
sub_elem->partition_name, name_variant)))
error= ret_error;
file= m_file[part];
DBUG_PRINT("info", ("Drop subpartition %s", part_name_buff));
if ((ret_error= file->ha_delete_table(part_name_buff)))
......@@ -680,15 +682,19 @@ int ha_partition::drop_partitions(const char *path)
}
else
{
create_partition_name(part_name_buff, path,
part_elem->partition_name, name_variant,
TRUE);
file= m_file[i];
DBUG_PRINT("info", ("Drop partition %s", part_name_buff));
if ((ret_error= file->ha_delete_table(part_name_buff)))
if ((ret_error= create_partition_name(part_name_buff,
sizeof(part_name_buff), path,
part_elem->partition_name, name_variant, TRUE)))
error= ret_error;
if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
error= 1;
else
{
file= m_file[i];
DBUG_PRINT("info", ("Drop partition %s", part_name_buff));
if ((ret_error= file->ha_delete_table(part_name_buff)))
error= ret_error;
if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
error= 1;
}
}
if (part_elem->part_state == PART_IS_CHANGED)
part_elem->part_state= PART_NORMAL;
......@@ -724,8 +730,8 @@ int ha_partition::rename_partitions(const char *path)
{
List_iterator<partition_element> part_it(m_part_info->partitions);
List_iterator<partition_element> temp_it(m_part_info->temp_partitions);
char part_name_buff[FN_REFLEN];
char norm_name_buff[FN_REFLEN];
char part_name_buff[FN_REFLEN + 1];
char norm_name_buff[FN_REFLEN + 1];
uint num_parts= m_part_info->partitions.elements;
uint part_count= 0;
uint num_subparts= m_part_info->num_subparts;
......@@ -767,10 +773,11 @@ int ha_partition::rename_partitions(const char *path)
{
sub_elem= sub_it++;
file= m_reorged_file[part_count++];
create_subpartition_name(norm_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name,
NORMAL_PART_NAME);
if ((ret_error= create_subpartition_name(norm_name_buff,
sizeof(norm_name_buff), path,
part_elem->partition_name,
sub_elem->partition_name, NORMAL_PART_NAME)))
error= ret_error;
DBUG_PRINT("info", ("Delete subpartition %s", norm_name_buff));
if ((ret_error= file->ha_delete_table(norm_name_buff)))
error= ret_error;
......@@ -783,16 +790,20 @@ int ha_partition::rename_partitions(const char *path)
else
{
file= m_reorged_file[part_count++];
create_partition_name(norm_name_buff, path,
part_elem->partition_name, NORMAL_PART_NAME,
TRUE);
DBUG_PRINT("info", ("Delete partition %s", norm_name_buff));
if ((ret_error= file->ha_delete_table(norm_name_buff)))
if ((ret_error= create_partition_name(norm_name_buff,
sizeof(norm_name_buff), path,
part_elem->partition_name, NORMAL_PART_NAME, TRUE)))
error= ret_error;
else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
error= 1;
else
part_elem->log_entry= NULL; /* Indicate success */
{
DBUG_PRINT("info", ("Delete partition %s", norm_name_buff));
if ((ret_error= file->ha_delete_table(norm_name_buff)))
error= ret_error;
else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
error= 1;
else
part_elem->log_entry= NULL; /* Indicate success */
}
}
} while (++i < temp_partitions);
(void) sync_ddl_log();
......@@ -835,10 +846,11 @@ int ha_partition::rename_partitions(const char *path)
{
sub_elem= sub_it++;
part= i * num_subparts + j;
create_subpartition_name(norm_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name,
NORMAL_PART_NAME);
if ((ret_error= create_subpartition_name(norm_name_buff,
sizeof(norm_name_buff), path,
part_elem->partition_name,
sub_elem->partition_name, NORMAL_PART_NAME)))
error= ret_error;
if (part_elem->part_state == PART_IS_CHANGED)
{
file= m_reorged_file[part_count++];
......@@ -850,10 +862,11 @@ int ha_partition::rename_partitions(const char *path)
(void) sync_ddl_log();
}
file= m_new_file[part];
create_subpartition_name(part_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name,
TEMP_PART_NAME);
if ((ret_error= create_subpartition_name(part_name_buff,
sizeof(part_name_buff), path,
part_elem->partition_name,
sub_elem->partition_name, TEMP_PART_NAME)))
error= ret_error;
DBUG_PRINT("info", ("Rename subpartition from %s to %s",
part_name_buff, norm_name_buff));
if ((ret_error= file->ha_rename_table(part_name_buff,
......@@ -867,32 +880,36 @@ int ha_partition::rename_partitions(const char *path)
}
else
{
create_partition_name(norm_name_buff, path,
part_elem->partition_name, NORMAL_PART_NAME,
TRUE);
if (part_elem->part_state == PART_IS_CHANGED)
if ((ret_error= create_partition_name(norm_name_buff,
sizeof(norm_name_buff), path,
part_elem->partition_name, NORMAL_PART_NAME, TRUE)) ||
(ret_error= create_partition_name(part_name_buff,
sizeof(part_name_buff), path,
part_elem->partition_name, TEMP_PART_NAME, TRUE)))
error= ret_error;
else
{
file= m_reorged_file[part_count++];
DBUG_PRINT("info", ("Delete partition %s", norm_name_buff));
if ((ret_error= file->ha_delete_table(norm_name_buff)))
if (part_elem->part_state == PART_IS_CHANGED)
{
file= m_reorged_file[part_count++];
DBUG_PRINT("info", ("Delete partition %s", norm_name_buff));
if ((ret_error= file->ha_delete_table(norm_name_buff)))
error= ret_error;
else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
error= 1;
(void) sync_ddl_log();
}
file= m_new_file[i];
DBUG_PRINT("info", ("Rename partition from %s to %s",
part_name_buff, norm_name_buff));
if ((ret_error= file->ha_rename_table(part_name_buff,
norm_name_buff)))
error= ret_error;
else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
error= 1;
(void) sync_ddl_log();
else
part_elem->log_entry= NULL;
}
file= m_new_file[i];
create_partition_name(part_name_buff, path,
part_elem->partition_name, TEMP_PART_NAME,
TRUE);
DBUG_PRINT("info", ("Rename partition from %s to %s",
part_name_buff, norm_name_buff));
if ((ret_error= file->ha_rename_table(part_name_buff,
norm_name_buff)))
error= ret_error;
else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
error= 1;
else
part_elem->log_entry= NULL;
}
}
} while (++i < num_parts);
......@@ -1488,7 +1505,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
{
List_iterator<partition_element> part_it(m_part_info->partitions);
List_iterator <partition_element> t_it(m_part_info->temp_partitions);
char part_name_buff[FN_REFLEN];
char part_name_buff[FN_REFLEN + 1];
uint num_parts= m_part_info->partitions.elements;
uint num_subparts= m_part_info->num_subparts;
uint i= 0;
......@@ -1698,10 +1715,14 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
do
{
partition_element *sub_elem= sub_it++;
create_subpartition_name(part_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name,
name_variant);
if ((error= create_subpartition_name(part_name_buff,
sizeof(part_name_buff), path,
part_elem->partition_name, sub_elem->partition_name,
name_variant)))
{
cleanup_new_partition(part_count);
DBUG_RETURN(error);
}
part= i * num_subparts + j;
DBUG_PRINT("info", ("Add subpartition %s", part_name_buff));
if ((error= prepare_new_partition(table, create_info,
......@@ -1719,9 +1740,14 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
}
else
{
create_partition_name(part_name_buff, path,
part_elem->partition_name, name_variant,
TRUE);
if ((error= create_partition_name(part_name_buff,
sizeof(part_name_buff), path, part_elem->partition_name,
name_variant, TRUE)))
{
cleanup_new_partition(part_count);
DBUG_RETURN(error);
}
DBUG_PRINT("info", ("Add partition %s", part_name_buff));
if ((error= prepare_new_partition(table, create_info,
new_file_array[i],
......@@ -1980,8 +2006,8 @@ int ha_partition::del_ren_cre_table(const char *from,
{
int save_error= 0;
int error= HA_ERR_INTERNAL_ERROR;
char from_buff[FN_REFLEN], to_buff[FN_REFLEN], from_lc_buff[FN_REFLEN],
to_lc_buff[FN_REFLEN], buff[FN_REFLEN];
char from_buff[FN_REFLEN + 1], to_buff[FN_REFLEN + 1],
from_lc_buff[FN_REFLEN], to_lc_buff[FN_REFLEN], buff[FN_REFLEN];
char *name_buffer_ptr;
const char *from_path;
const char *to_path= NULL;
......@@ -2028,13 +2054,15 @@ int ha_partition::del_ren_cre_table(const char *from,
i= 0;
do
{
create_partition_name(from_buff, from_path, name_buffer_ptr,
NORMAL_PART_NAME, FALSE);
if ((error= create_partition_name(from_buff, sizeof(from_buff), from_path,
name_buffer_ptr, NORMAL_PART_NAME, FALSE)))
goto rename_error;
if (to != NULL)
{ // Rename branch
create_partition_name(to_buff, to_path, name_buffer_ptr,
NORMAL_PART_NAME, FALSE);
if ((error= create_partition_name(to_buff, sizeof(to_buff), to_path,
name_buffer_ptr, NORMAL_PART_NAME, FALSE)))
goto rename_error;
error= (*file)->ha_rename_table(from_buff, to_buff);
if (error)
goto rename_error;
......@@ -2081,9 +2109,9 @@ int ha_partition::del_ren_cre_table(const char *from,
name_buffer_ptr= m_name_buffer_ptr;
for (abort_file= file, file= m_file; file < abort_file; file++)
{
create_partition_name(from_buff, from_path, name_buffer_ptr, NORMAL_PART_NAME,
FALSE);
(void) (*file)->ha_delete_table((const char*) from_buff);
if (!create_partition_name(from_buff, sizeof(from_buff), from_path,
name_buffer_ptr, NORMAL_PART_NAME, FALSE))
(void) (*file)->ha_delete_table(from_buff);
name_buffer_ptr= strend(name_buffer_ptr) + 1;
}
DBUG_RETURN(error);
......@@ -2092,12 +2120,11 @@ int ha_partition::del_ren_cre_table(const char *from,
for (abort_file= file, file= m_file; file < abort_file; file++)
{
/* Revert the rename, back from 'to' to the original 'from' */
create_partition_name(from_buff, from_path, name_buffer_ptr,
NORMAL_PART_NAME, FALSE);
create_partition_name(to_buff, to_path, name_buffer_ptr,
NORMAL_PART_NAME, FALSE);
/* Ignore error here */
(void) (*file)->ha_rename_table(to_buff, from_buff);
if (!create_partition_name(from_buff, sizeof(from_buff), from_path,
name_buffer_ptr, NORMAL_PART_NAME, FALSE) &&
!create_partition_name(to_buff, sizeof(to_buff), to_path, name_buffer_ptr,
NORMAL_PART_NAME, FALSE))
(void) (*file)->ha_rename_table(to_buff, from_buff);
name_buffer_ptr= strend(name_buffer_ptr) + 1;
}
DBUG_RETURN(error);
......@@ -2895,7 +2922,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
char *name_buffer_ptr;
int error= HA_ERR_INITIALIZATION;
handler **file;
char name_buff[FN_REFLEN];
char name_buff[FN_REFLEN + 1];
bool is_not_tmp_table= (table_share->tmp_table == NO_TMP_TABLE);
ulonglong check_table_flags;
DBUG_ENTER("ha_partition::open");
......@@ -2965,8 +2992,9 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
file= m_is_clone_of->m_file;
for (i= 0; i < m_tot_parts; i++)
{
create_partition_name(name_buff, name, name_buffer_ptr, NORMAL_PART_NAME,
FALSE);
if ((error= create_partition_name(name_buff, sizeof(name_buff), name,
name_buffer_ptr, NORMAL_PART_NAME, FALSE)))
goto err_handler;
if (!(m_file[i]= file[i]->clone(name_buff, m_clone_mem_root)))
{
error= HA_ERR_INITIALIZATION;
......@@ -2981,8 +3009,9 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
file= m_file;
do
{
create_partition_name(name_buff, name, name_buffer_ptr, NORMAL_PART_NAME,
FALSE);
if ((error= create_partition_name(name_buff, sizeof(name_buff), name,
name_buffer_ptr, NORMAL_PART_NAME, FALSE)))
goto err_handler;
table->s->connect_string = m_connect_string[(uint)(file-m_file)];
if ((error= (*file)->ha_open(table, name_buff, mode, test_if_locked)))
goto err_handler;
......
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
Copyright (c) 2010, 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
......@@ -817,6 +817,7 @@ Item_ident::Item_ident(Name_resolution_context *context_arg,
cached_table(0), depended_from(0), can_be_depended(TRUE)
{
name = (char*) field_name_arg;
name_length= name ? strlen(name) : 0;
}
......@@ -829,6 +830,7 @@ Item_ident::Item_ident(TABLE_LIST *view_arg, const char *field_name_arg)
cached_table(NULL), depended_from(NULL), can_be_depended(TRUE)
{
name = (char*) field_name_arg;
name_length= name ? strlen(name) : 0;
}
......@@ -4622,7 +4624,7 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
int cur_match_degree= 0;
/* SELECT list element with explicit alias */
if ((*(cur_group->item))->name &&
if ((*(cur_group->item))->name && !table_name &&
!(*(cur_group->item))->is_autogenerated_name &&
!my_strcasecmp(system_charset_info,
(*(cur_group->item))->name, field_name))
......@@ -5045,6 +5047,12 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ?
(Item_ident*) (*reference) :
0));
if (thd->lex->in_sum_func &&
thd->lex->in_sum_func->nest_level >= select->nest_level)
{
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
select->nest_level);
}
/*
A reference to a view field had been found and we
substituted it instead of this Item (find_field_in_tables
......
......@@ -1165,7 +1165,11 @@ class Item_func_coercibility :public Item_int_func
longlong val_int();
const char *func_name() const { return "coercibility"; }
void fix_length_and_dec() { max_length=10; maybe_null= 0; }
table_map not_null_tables() const { return 0; }
bool eval_not_null_tables(uchar *opt_arg)
{
not_null_tables_cache= 0;
return 0;
}
};
class Item_func_locate :public Item_int_func
......@@ -1433,7 +1437,11 @@ class Item_udf_func :public Item_func
}
void cleanup();
Item_result result_type () const { return udf.result_type(); }
table_map not_null_tables() const { return 0; }
bool eval_not_null_tables(uchar *opt_arg)
{
not_null_tables_cache= 0;
return 0;
}
bool is_expensive() { return 1; }
virtual void print(String *str, enum_query_type query_type);
};
......@@ -1889,7 +1897,11 @@ class Item_func_match :public Item_real_func
bool is_expensive_processor(uchar *arg) { return TRUE; }
enum Functype functype() const { return FT_FUNC; }
const char *func_name() const { return "match"; }
table_map not_null_tables() const { return 0; }
bool eval_not_null_tables(uchar *opt_arg)
{
not_null_tables_cache= 0;
return 0;
}
bool fix_fields(THD *thd, Item **ref);
bool eq(const Item *, bool binary_cmp) const;
/* The following should be safe, even if we compare doubles */
......@@ -2091,6 +2103,11 @@ class Item_func_sp :public Item_func
{
return TRUE;
}
bool eval_not_null_tables(uchar *opt_arg)
{
not_null_tables_cache= 0;
return 0;
}
};
......@@ -2138,7 +2155,11 @@ class Item_func_last_value :public Item_func
void fix_length_and_dec();
enum Item_result result_type () const { return last_value->result_type(); }
const char *func_name() const { return "last_value"; }
table_map not_null_tables() const { return 0; }
bool eval_not_null_tables(uchar *opt_arg)
{
not_null_tables_cache= 0;
return 0;
}
enum_field_types field_type() const { return last_value->field_type(); }
bool const_item() const { return 0; }
void evaluate_sideeffects();
......
......@@ -316,7 +316,8 @@ bool Item_subselect::enumerate_field_refs_processor(uchar *arg)
while ((upper= it++))
{
if (upper->item->walk(&Item::enumerate_field_refs_processor, FALSE, arg))
if (upper->item &&
upper->item->walk(&Item::enumerate_field_refs_processor, FALSE, arg))
return TRUE;
}
return FALSE;
......@@ -1366,7 +1367,7 @@ Item_in_subselect::Item_in_subselect(Item * left_exp,
Item_exists_subselect(),
left_expr_cache(0), first_execution(TRUE), in_strategy(SUBS_NOT_TRANSFORMED),
optimizer(0), pushed_cond_guards(NULL), emb_on_expr_nest(NULL),
is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE),
do_not_convert_to_sj(FALSE), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE),
is_flattenable_semijoin(FALSE),
is_registered_semijoin(FALSE),
upper_item(0)
......@@ -2493,6 +2494,27 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg)
DBUG_ENTER("Item_in_subselect::inject_in_to_exists_cond");
DBUG_ASSERT(thd == join_arg->thd);
if (select_lex->min_max_opt_list.elements)
{
/*
MIN/MAX optimizations have been applied to Item_sum objects
of the subquery this subquery predicate in opt_sum_query().
Injection of new condition invalidates this optimizations.
Thus those optimizations must be rolled back.
*/
List_iterator_fast<Item_sum> it(select_lex->min_max_opt_list);
Item_sum *item;
while ((item= it++))
{
item->clear();
item->reset_forced_const();
}
if (where_item)
where_item->update_used_tables();
if (having_item)
having_item->update_used_tables();
}
if (where_item)
{
List<Item> *and_args= NULL;
......@@ -2850,7 +2872,8 @@ bool Item_in_subselect::init_cond_guards()
{
DBUG_ASSERT(thd);
uint cols_num= left_expr->cols();
if (!abort_on_null && left_expr->maybe_null && !pushed_cond_guards)
if (!abort_on_null && !pushed_cond_guards &&
(left_expr->maybe_null || cols_num > 1))
{
if (!(pushed_cond_guards= (bool*)thd->alloc(sizeof(bool) * cols_num)))
return TRUE;
......
......@@ -466,6 +466,8 @@ class Item_in_subselect :public Item_exists_subselect
NULL - for all other locations
*/
TABLE_LIST *emb_on_expr_nest;
/* May be TRUE only for the candidates to semi-join conversion */
bool do_not_convert_to_sj;
/*
Types of left_expr and subquery's select list allow to perform subquery
materialization. Currently, we set this to FALSE when it as well could
......@@ -554,9 +556,9 @@ class Item_in_subselect :public Item_exists_subselect
Item_in_subselect()
:Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE),
abort_on_null(0), in_strategy(SUBS_NOT_TRANSFORMED), optimizer(0),
pushed_cond_guards(NULL), func(NULL), emb_on_expr_nest(NULL),
is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE),
upper_item(0)
pushed_cond_guards(NULL), func(NULL), emb_on_expr_nest(NULL),
do_not_convert_to_sj(FALSE), is_jtbm_merged(FALSE),
is_jtbm_const_tab(FALSE), upper_item(0)
{}
void cleanup();
subs_type substype() { return IN_SUBS; }
......@@ -617,6 +619,8 @@ class Item_in_subselect :public Item_exists_subselect
emb_on_expr_nest= embedding;
}
void block_conversion_to_sj () { do_not_convert_to_sj= TRUE; }
bool test_strategy(uchar strategy)
{ return test(in_strategy & strategy); }
......
......@@ -454,6 +454,7 @@ class Item_sum :public Item_result_field
used_tables_cache= 0;
forced_const= TRUE;
}
void reset_forced_const() { forced_const= FALSE; }
virtual bool const_item() const { return forced_const; }
virtual bool const_during_execution() const { return false; }
virtual void print(String *str, enum_query_type query_type);
......
......@@ -3041,7 +3041,7 @@ get_date_time_result_type(const char *format, uint length)
const char *val= format;
const char *end= format + length;
for (; val != end && val != end; val++)
for (; val != end; val++)
{
if (*val == '%' && val+1 != end)
{
......
......@@ -4887,13 +4887,20 @@ int THD::binlog_write_table_map(TABLE *table, bool is_transactional,
IO_CACHE *file=
cache_mngr->get_binlog_cache_log(use_trans_cache(this, is_transactional));
binlog_cache_data *cache_data=
cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional));
if (with_annotate && *with_annotate)
{
Annotate_rows_log_event anno(current_thd, is_transactional, false);
/* Annotate event should be written not more than once */
*with_annotate= 0;
if ((error= anno.write(file)))
{
if (my_errno == EFBIG)
cache_data->set_incident();
DBUG_RETURN(error);
}
}
if ((error= the_event.write(file)))
DBUG_RETURN(error);
......
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2012, 2016, MariaDB
Copyright (c) 2012, 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
......
......@@ -678,6 +678,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!((join->select_options | // 10
select_lex->outer_select()->join->select_options) // 10
& SELECT_STRAIGHT_JOIN)) // 10
{
DBUG_PRINT("info", ("Subquery is semi-join conversion candidate"));
......@@ -1000,6 +1001,25 @@ bool check_for_outer_joins(List<TABLE_LIST> *join_list)
}
void find_and_block_conversion_to_sj(Item *to_find,
List_iterator_fast<Item_in_subselect> &li)
{
if (to_find->type() != Item::SUBSELECT_ITEM ||
((Item_subselect *) to_find)->substype() != Item_subselect::IN_SUBS)
return;
Item_in_subselect *in_subq;
li.rewind();
while ((in_subq= li++))
{
if (in_subq == to_find)
{
in_subq->block_conversion_to_sj();
return;
}
}
}
/*
Convert semi-join subquery predicates into semi-join join nests
......@@ -1052,7 +1072,6 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
Query_arena *arena, backup;
Item_in_subselect *in_subq;
THD *thd= join->thd;
List_iterator<TABLE_LIST> ti(join->select_lex->leaf_tables);
DBUG_ENTER("convert_join_subqueries_to_semijoins");
if (join->select_lex->sj_subselects.is_empty())
......@@ -1070,6 +1089,89 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
subq_sel->update_used_tables();
}
/*
Check all candidates to semi-join conversion that occur
in ON expressions of outer join. Set the flag blocking
this conversion for them.
*/
TABLE_LIST *tbl;
List_iterator<TABLE_LIST> ti(join->select_lex->leaf_tables);
while ((tbl= ti++))
{
TABLE_LIST *embedded;
TABLE_LIST *embedding= tbl;
do
{
embedded= embedding;
bool block_conversion_to_sj= false;
if (embedded->on_expr)
{
/*
Conversion of an IN subquery predicate into semi-join
is blocked now if the predicate occurs:
- in the ON expression of an outer join
- in the ON expression of an inner join embedded directly
or indirectly in the inner nest of an outer join
*/
for (TABLE_LIST *tl= embedded; tl; tl= tl->embedding)
{
if (tl->outer_join)
{
block_conversion_to_sj= true;
break;
}
}
}
if (block_conversion_to_sj)
{
Item *cond= embedded->on_expr;
if (!cond)
;
else if (cond->type() != Item::COND_ITEM)
find_and_block_conversion_to_sj(cond, li);
else if (((Item_cond*) cond)->functype() ==
Item_func::COND_AND_FUNC)
{
Item *item;
List_iterator<Item> it(*(((Item_cond*) cond)->argument_list()));
while ((item= it++))
{
find_and_block_conversion_to_sj(item, li);
}
}
}
embedding= embedded->embedding;
}
while (embedding &&
embedding->nested_join->join_list.head() == embedded);
}
/*
Block conversion to semi-joins for those candidates that
are encountered in the WHERE condition of the multi-table view
with CHECK OPTION if this view is used in UPDATE/DELETE.
(This limitation can be, probably, easily lifted.)
*/
li.rewind();
while ((in_subq= li++))
{
if (in_subq->emb_on_expr_nest != NO_JOIN_NEST &&
in_subq->emb_on_expr_nest->effective_with_check)
{
in_subq->block_conversion_to_sj();
}
}
if (join->select_options & SELECT_STRAIGHT_JOIN)
{
/* Block conversion to semijoins for all candidates */
li.rewind();
while ((in_subq= li++))
{
in_subq->block_conversion_to_sj();
}
}
li.rewind();
/* First, convert child join's subqueries. We proceed bottom-up here */
while ((in_subq= li++))
......@@ -1088,8 +1190,10 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
if (convert_join_subqueries_to_semijoins(child_join))
DBUG_RETURN(TRUE);
in_subq->sj_convert_priority=
test(in_subq->emb_on_expr_nest != NO_JOIN_NEST) * MAX_TABLES * 2 +
test(in_subq->do_not_convert_to_sj) * MAX_TABLES * 2 +
in_subq->is_correlated * MAX_TABLES + child_join->outer_tables;
}
......@@ -1122,7 +1226,7 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
bool remove_item= TRUE;
/* Stop processing if we've reached a subquery that's attached to the ON clause */
if (in_subq->emb_on_expr_nest != NO_JOIN_NEST)
if (in_subq->do_not_convert_to_sj)
break;
if (in_subq->is_flattenable_semijoin)
......@@ -3325,6 +3429,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
table_map remaining_tables= 0;
table_map handled_tabs= 0;
join->sjm_lookup_tables= 0;
join->sjm_scan_tables= 0;
for (tablenr= table_count - 1 ; tablenr != join->const_tables - 1; tablenr--)
{
POSITION *pos= join->best_positions + tablenr;
......@@ -3383,6 +3488,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
for (i= tablenr; i != (first + sjm->tables - 1); i--)
rem_tables |= join->best_positions[i].table->table->map;
for (i= first; i < first+ sjm->tables; i++)
join->sjm_scan_tables |= join->best_positions[i].table->table->map;
POSITION dummy;
join->cur_sj_inner_tables= 0;
for (i= first + sjm->tables; i <= tablenr; i++)
......
......@@ -253,6 +253,8 @@ int opt_sum_query(THD *thd,
int error= 0;
DBUG_ENTER("opt_sum_query");
thd->lex->current_select->min_max_opt_list.empty();
if (conds)
where_tables= conds->used_tables();
......@@ -444,7 +446,14 @@ int opt_sum_query(THD *thd,
item_sum->aggregator_clear();
}
else
{
item_sum->reset_and_add();
/*
Save a reference to the item for possible rollback
of the min/max optimizations for this select
*/
thd->lex->current_select->min_max_opt_list.push_back(item_sum);
}
item_sum->make_const();
recalc_const_item= 1;
break;
......
/*
Copyright (c) 2000, 2010, Oracle and/or its affiliates.
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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment