From d75f8a174218fd0ada64222d2a538f7aace897bc Mon Sep 17 00:00:00 2001 From: Venkatesh Duggirala Date: Wed, 23 Aug 2017 09:16:12 +0530 Subject: Bug#24763131 LOCAL-INFILE DEFAULT SHOULD BE DISABLED Problem & Analysis: Slave's Receiver thread, Applier thread and worker threads are created with LOCAL-INFILE option enabled. As the document says https://dev.mysql.com/doc/refman/5.7/en/load-data-local.html, there are some issues if a thread enables local infile. This flag should be enabled with care. But for the above mentioned internal threads, server is enabling it at the time of creation. Fix: Further analysis on the code shows that none of threads really need this flag to be enabled at any time as Slave never executes "LOAD DATA LOCAL INFILE" after reading it from Relay log. Applier thread removes "LOCAL" before start executing the query. --- sql/slave.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'sql') diff --git a/sql/slave.cc b/sql/slave.cc index 1e641ac6d7e..e533bc09b3d 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2109,7 +2109,6 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) thd->slave_thread = 1; thd->enable_slow_log= opt_log_slow_slave_statements; set_slave_thread_options(thd); - thd->client_capabilities = CLIENT_LOCAL_FILES; mysql_mutex_lock(&LOCK_thread_count); thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; mysql_mutex_unlock(&LOCK_thread_count); -- cgit v1.2.1 From ebd96c314953f5c0073ff5846484fd5e438fe0ad Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Tue, 15 Aug 2017 13:15:19 +0200 Subject: Bug#19875294 ASSERTION `SRC' FAILED IN MY_STRNXFRM_UNICODE (SIG 6 -STRINGS/CTYPE-UTF8.C:5151) Backport from 5.7 to 5.5 Field_set::val_str() should return String("", 0, cs) rather than String(NULL, 0, cs) --- sql/field.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 15571afefb8..e98c17fabae 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, 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 General Public License as published by @@ -8257,13 +8257,13 @@ String *Field_set::val_str(String *val_buffer, ulonglong tmp=(ulonglong) Field_enum::val_int(); uint bitnr=0; + /* + Some callers expect *val_buffer to contain the result, + so we assign to it, rather than doing 'return &empty_set_string. + */ + *val_buffer= empty_set_string; if (tmp == 0) { - /* - Some callers expect *val_buffer to contain the result, - so we assign to it, rather than doing 'return &empty_set_string. - */ - *val_buffer= empty_set_string; return val_buffer; } -- cgit v1.2.1 From be901b60ae59c93848c829d1b0b2cb523ab8692e Mon Sep 17 00:00:00 2001 From: Nisha Gopalakrishnan Date: Wed, 16 Aug 2017 13:58:25 +0530 Subject: Bug#26390632: CREATE TABLE CAN CAUSE MYSQL TO EXIT. Analysis ======== CREATE TABLE of InnoDB table with a partition name which exceeds the path limit can cause the server to exit. During the preparation of the partition name, there was no check to identify whether the complete path name for partition exceeds the max supported path length, causing the server to exit during subsequent processing. Fix === During the preparation of partition name, check and report an error if the partition path name exceeds the maximum path name limit. This is a 5.5 patch. --- sql/ha_partition.cc | 150 ++++++++++++++++++++++++++----------------- sql/sql_partition.cc | 177 ++++++++++++++++++++++++++++++++------------------- sql/sql_partition.h | 6 +- 3 files changed, 204 insertions(+), 129 deletions(-) (limited to 'sql') diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index aadac36e2ee..414f9d52536 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2005, 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 @@ -624,7 +624,7 @@ int ha_partition::create(const char *name, TABLE *table_arg, int ha_partition::drop_partitions(const char *path) { List_iterator 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; @@ -657,9 +657,12 @@ 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, 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))) @@ -670,9 +673,11 @@ int ha_partition::drop_partitions(const char *path) } else { - create_partition_name(part_name_buff, path, - part_elem->partition_name, name_variant, - TRUE); + if ((ret_error= create_partition_name(part_name_buff, path, + part_elem->partition_name, + name_variant, TRUE))) + error= ret_error; + file= m_file[i]; DBUG_PRINT("info", ("Drop partition %s", part_name_buff)); if ((ret_error= file->ha_delete_table(part_name_buff))) @@ -714,8 +719,8 @@ int ha_partition::rename_partitions(const char *path) { List_iterator part_it(m_part_info->partitions); List_iterator 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; @@ -757,10 +762,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, 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; @@ -773,9 +779,11 @@ 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); + if ((ret_error= create_partition_name(norm_name_buff, path, + part_elem->partition_name, + NORMAL_PART_NAME, TRUE))) + error= ret_error; + DBUG_PRINT("info", ("Delete partition %s", norm_name_buff)); if ((ret_error= file->ha_delete_table(norm_name_buff))) error= ret_error; @@ -825,10 +833,12 @@ 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, 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++]; @@ -840,10 +850,12 @@ 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, 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, @@ -857,9 +869,11 @@ 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 ((ret_error= create_partition_name(norm_name_buff, path, + part_elem->partition_name, + NORMAL_PART_NAME, TRUE))) + error= ret_error; + if (part_elem->part_state == PART_IS_CHANGED) { file= m_reorged_file[part_count++]; @@ -871,9 +885,11 @@ int ha_partition::rename_partitions(const char *path) (void) sync_ddl_log(); } file= m_new_file[i]; - create_partition_name(part_name_buff, path, - part_elem->partition_name, TEMP_PART_NAME, - TRUE); + if ((ret_error= create_partition_name(part_name_buff, path, + part_elem->partition_name, + TEMP_PART_NAME, TRUE))) + error= ret_error; + 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, @@ -1477,7 +1493,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, { List_iterator part_it(m_part_info->partitions); List_iterator 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; @@ -1687,10 +1703,15 @@ 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, 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, @@ -1708,9 +1729,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, 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], @@ -1967,8 +1993,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 + 1], + to_lc_buff[FN_REFLEN + 1], buff[FN_REFLEN + 1]; char *name_buffer_ptr; const char *from_path; const char *to_path= NULL; @@ -2015,13 +2041,16 @@ 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, from_path, name_buffer_ptr, + NORMAL_PART_NAME, FALSE))) + DBUG_RETURN(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, to_path, name_buffer_ptr, + NORMAL_PART_NAME, FALSE))) + DBUG_RETURN(error); + error= (*file)->ha_rename_table(from_buff, to_buff); if (error) goto rename_error; @@ -2066,9 +2095,9 @@ create_error: 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, from_path, name_buffer_ptr, NORMAL_PART_NAME, + FALSE)) + (void) (*file)->ha_delete_table((const char*) from_buff); name_buffer_ptr= strend(name_buffer_ptr) + 1; } DBUG_RETURN(error); @@ -2077,12 +2106,12 @@ rename_error: 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, from_path, name_buffer_ptr, + NORMAL_PART_NAME, FALSE)) + if (!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); name_buffer_ptr= strend(name_buffer_ptr) + 1; } DBUG_RETURN(error); @@ -2707,7 +2736,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"); @@ -2777,8 +2806,10 @@ 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, 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; @@ -2793,8 +2824,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, name, name_buffer_ptr, + NORMAL_PART_NAME, FALSE))) + goto err_handler; if ((error= (*file)->ha_open(table, name_buff, mode, test_if_locked))) goto err_handler; m_num_locks+= (*file)->lock_count(); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 5358535e9f9..65d4da0f2f6 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 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 @@ -5958,8 +5958,8 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, DDL_LOG_ENTRY ddl_log_entry; partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; - char tmp_path[FN_REFLEN]; - char normal_path[FN_REFLEN]; + char tmp_path[FN_REFLEN + 1]; + char normal_path[FN_REFLEN + 1]; List_iterator part_it(part_info->partitions); uint temp_partitions= part_info->temp_partitions.elements; uint num_elements= part_info->partitions.elements; @@ -5983,14 +5983,18 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(sub_elem->engine_type); - create_subpartition_name(tmp_path, path, - part_elem->partition_name, - sub_elem->partition_name, - TEMP_PART_NAME); - create_subpartition_name(normal_path, path, - part_elem->partition_name, - sub_elem->partition_name, - NORMAL_PART_NAME); + if (create_subpartition_name(tmp_path, path, + part_elem->partition_name, + sub_elem->partition_name, + TEMP_PART_NAME)) + DBUG_RETURN(TRUE); + + if (create_subpartition_name(normal_path, path, + part_elem->partition_name, + sub_elem->partition_name, + NORMAL_PART_NAME)) + DBUG_RETURN(TRUE); + ddl_log_entry.name= normal_path; ddl_log_entry.from_name= tmp_path; if (part_elem->part_state == PART_IS_CHANGED) @@ -6011,12 +6015,13 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(part_elem->engine_type); - create_partition_name(tmp_path, path, - part_elem->partition_name, - TEMP_PART_NAME, TRUE); - create_partition_name(normal_path, path, - part_elem->partition_name, - NORMAL_PART_NAME, TRUE); + if ((create_partition_name(tmp_path, path, part_elem->partition_name, + TEMP_PART_NAME, TRUE)) || + (create_partition_name(normal_path, path, + part_elem->partition_name, + NORMAL_PART_NAME, TRUE))) + DBUG_RETURN(TRUE); + ddl_log_entry.name= normal_path; ddl_log_entry.from_name= tmp_path; if (part_elem->part_state == PART_IS_CHANGED) @@ -6055,7 +6060,7 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, DDL_LOG_ENTRY ddl_log_entry; partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; - char tmp_path[FN_LEN]; + char tmp_path[FN_REFLEN + 1]; List_iterator part_it(part_info->partitions); List_iterator temp_it(part_info->temp_partitions); uint num_temp_partitions= part_info->temp_partitions.elements; @@ -6094,10 +6099,12 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(sub_elem->engine_type); - create_subpartition_name(tmp_path, path, - part_elem->partition_name, - sub_elem->partition_name, - name_variant); + if (create_subpartition_name(tmp_path, path, + part_elem->partition_name, + sub_elem->partition_name, + name_variant)) + DBUG_RETURN(TRUE); + ddl_log_entry.name= tmp_path; if (write_ddl_log_entry(&ddl_log_entry, &log_entry)) { @@ -6113,9 +6120,10 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(part_elem->engine_type); - create_partition_name(tmp_path, path, - part_elem->partition_name, - name_variant, TRUE); + if ((create_partition_name(tmp_path, path, part_elem->partition_name, + name_variant, TRUE))) + DBUG_RETURN(TRUE); + ddl_log_entry.name= tmp_path; if (write_ddl_log_entry(&ddl_log_entry, &log_entry)) { @@ -8194,29 +8202,28 @@ static uint32 get_next_subpartition_via_walking(PARTITION_ITERATOR *part_iter) } -/* - Create partition names - - SYNOPSIS - create_partition_name() - out:out Created partition name string - in1 First part - in2 Second part - name_variant Normal, temporary or renamed partition name - - RETURN VALUE - NONE - - DESCRIPTION - This method is used to calculate the partition name, service routine to - the del_ren_cre_table method. +/** + Create partition names. This method is used to calculate the + partition name, service routine to the del_ren_cre_table method. + The output buffer size should be FN_REFLEN + 1(terminating '\0'). + + @param [out] out Created partition name string + @param in1 First part + @param in2 Second part + @param in3 Third part + @param name_variant Normal, temporary or renamed partition name + @param translate Flag to determine whether to convert a table name + to it its corresponding filename. + + @retval true Error. + @retval false Success. */ -void create_partition_name(char *out, const char *in1, +bool create_partition_name(char *out, const char *in1, const char *in2, uint name_variant, bool translate) { - char transl_part_name[FN_REFLEN]; + char transl_part_name[FN_REFLEN + 1]; const char *transl_part; if (translate) @@ -8226,35 +8233,50 @@ void create_partition_name(char *out, const char *in1, } else transl_part= in2; + + // Check if the path name for partition exceeds maximum path length. if (name_variant == NORMAL_PART_NAME) - strxmov(out, in1, "#P#", transl_part, NullS); + { + if ((strlen(in1) + strlen(transl_part) + 3) > FN_REFLEN) + { + my_error(ER_PATH_LENGTH, MYF(0), in2); + return true; + } + } + else + if ((strlen(in1) + strlen(transl_part) + 8) > FN_REFLEN) + { + my_error(ER_PATH_LENGTH, MYF(0), in2); + return true; + } + + if (name_variant == NORMAL_PART_NAME) + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part, NullS); else if (name_variant == TEMP_PART_NAME) - strxmov(out, in1, "#P#", transl_part, "#TMP#", NullS); + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part, "#TMP#", NullS); else if (name_variant == RENAMED_PART_NAME) - strxmov(out, in1, "#P#", transl_part, "#REN#", NullS); -} + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part, "#REN#", NullS); + return false; +} -/* - Create subpartition name - - SYNOPSIS - create_subpartition_name() - out:out Created partition name string - in1 First part - in2 Second part - in3 Third part - name_variant Normal, temporary or renamed partition name - - RETURN VALUE - NONE - DESCRIPTION - This method is used to calculate the subpartition name, service routine to - the del_ren_cre_table method. +/** + Create subpartition name. This method is used to calculate the + subpartition name, service routine to the del_ren_cre_table method. + The output buffer size should be FN_REFLEN + 1(terminating '\0'). + + @param [out] out Created partition name string + @param in1 First part + @param in2 Second part + @param in3 Third part + @param name_variant Normal, temporary or renamed partition name + + @retval true Error. + @retval false Success. */ -void create_subpartition_name(char *out, const char *in1, +bool create_subpartition_name(char *out, const char *in1, const char *in2, const char *in3, uint name_variant) { @@ -8262,15 +8284,36 @@ void create_subpartition_name(char *out, const char *in1, tablename_to_filename(in2, transl_part_name, FN_REFLEN); tablename_to_filename(in3, transl_subpart_name, FN_REFLEN); + + // Check if the path name for subpartition exceeds maximum path length. + if (name_variant == NORMAL_PART_NAME) + { + if ((strlen(in1) + strlen(transl_part_name) + + strlen(transl_subpart_name) + 7) > FN_REFLEN) + { + my_error(ER_PATH_LENGTH, MYF(0), in3); + return true; + } + } + else + if ((strlen(in1) + strlen(transl_part_name) + + strlen(transl_subpart_name) + 12) > FN_REFLEN) + { + my_error(ER_PATH_LENGTH, MYF(0), in3); + return true; + } + if (name_variant == NORMAL_PART_NAME) - strxmov(out, in1, "#P#", transl_part_name, + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part_name, "#SP#", transl_subpart_name, NullS); else if (name_variant == TEMP_PART_NAME) - strxmov(out, in1, "#P#", transl_part_name, + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part_name, "#SP#", transl_subpart_name, "#TMP#", NullS); else if (name_variant == RENAMED_PART_NAME) - strxmov(out, in1, "#P#", transl_part_name, + strxnmov(out, FN_REFLEN, in1, "#P#", transl_part_name, "#SP#", transl_subpart_name, "#REN#", NullS); + + return false; } uint get_partition_field_store_length(Field *field) diff --git a/sql/sql_partition.h b/sql/sql_partition.h index f232eaa0629..cfaab903f04 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -1,7 +1,7 @@ #ifndef SQL_PARTITION_INCLUDED #define SQL_PARTITION_INCLUDED -/* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 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 @@ -272,10 +272,10 @@ char *generate_partition_syntax(partition_info *part_info, const char *current_comment_start); #endif -void create_partition_name(char *out, const char *in1, +bool create_partition_name(char *out, const char *in1, const char *in2, uint name_variant, bool translate); -void create_subpartition_name(char *out, const char *in1, +bool create_subpartition_name(char *out, const char *in1, const char *in2, const char *in3, uint name_variant); -- cgit v1.2.1 From f7316aa0c9a3909fc7498e7b95d5d3af044a7e21 Mon Sep 17 00:00:00 2001 From: Ajo Robert Date: Thu, 24 Aug 2017 17:03:21 +0530 Subject: Bug#26361149 MYSQL SERVER CRASHES AT: COL IN(IFNULL(CONST, COL), NAME_CONST('NAME', NULL)) Backport of Bug#19143243 fix. NAME_CONST item can return NULL_ITEM type in case of incorrect arguments. NULL_ITEM has special processing in Item_func_in function. In Item_func_in::fix_length_and_dec an array of possible comparators is created. Since NAME_CONST function has NULL_ITEM type, corresponding array element is empty. Then NAME_CONST is wrapped to ITEM_CACHE. ITEM_CACHE can not return proper type(NULL_ITEM) in Item_func_in::val_int(), so the NULL_ITEM is attempted compared with an empty comparator. The fix is to disable the caching of Item_name_const item. --- sql/item.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item.h b/sql/item.h index 8caa2bc5f9f..9f4e1d24424 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1,7 +1,7 @@ #ifndef ITEM_INCLUDED #define ITEM_INCLUDED -/* Copyright (c) 2000, 2016, 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 General Public License as published by @@ -1552,6 +1552,12 @@ public: return TRUE; } + virtual bool cache_const_expr_analyzer(uchar **arg) + { + // Item_name_const always wraps a literal, so there is no need to cache it. + return false; + } + int save_in_field(Field *field, bool no_conversions) { return value_item->save_in_field(field, no_conversions); -- cgit v1.2.1 From e30b6a983fe135dd1af0c79c81dbdb5b14b881c8 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 6 Oct 2017 18:23:40 +0400 Subject: MDEV-11819 NO_ZERO_IN_DATE: Incorrect generated column value --- sql/item_timefunc.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 0062d500835..5be9c5cacbd 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -500,8 +500,16 @@ public: { return val_decimal_from_date(decimal_value); } Field *tmp_table_field(TABLE *table) { return tmp_table_field_from_field_type(table, 0); } +#if MARIADB_VERSION_ID > 100300 +#error This code should be removed in 10.3, to use the derived save_in_field() +#else int save_in_field(Field *field, bool no_conversions) - { return save_date_in_field(field); } + { + return field_type() == MYSQL_TYPE_TIME ? + save_time_in_field(field) : + save_date_in_field(field); + } +#endif void fix_length_and_dec(); }; -- cgit v1.2.1 From c2509a1588ee1dc7351b67b2f9149003540015c4 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 10 Oct 2017 10:35:12 +0400 Subject: MDEV-13972 crash in Item_func_sec_to_time::get_date --- sql/item_timefunc.cc | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 0ed1506bbee..eeb373a75ee 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1733,9 +1733,18 @@ overflow: ltime->hour= TIME_MAX_HOUR+1; check_time_range(ltime, decimals, &unused); - make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - err->ptr(), err->length(), - MYSQL_TIMESTAMP_TIME, NullS); + if (!err) + { + ErrConvInteger err2(sec, unsigned_flag); + make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + &err2, MYSQL_TIMESTAMP_TIME, NullS); + } + else + { + ErrConvString err2(err); + make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + &err2, MYSQL_TIMESTAMP_TIME, NullS); + } return 0; } -- cgit v1.2.1 From 93aadda513d8b5c2b49001514e235c4fdd73e08a Mon Sep 17 00:00:00 2001 From: Vesa Pentti Date: Sun, 8 Oct 2017 22:15:00 +0300 Subject: MDEV-13149 -- show function status now works with PAD_CHAR_TO_FULL_LENGTH --- sql/sql_show.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sql') diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d8ea232caea..6e045648591 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -5716,6 +5716,10 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) DBUG_RETURN(1); } + /* Disable padding temporarily so it doesn't break the query */ + ulonglong sql_mode_was = thd->variables.sql_mode; + thd->variables.sql_mode &= ~MODE_PAD_CHAR_TO_FULL_LENGTH; + if (proc_table->file->ha_index_init(0, 1)) { res= 1; @@ -5751,6 +5755,7 @@ err: (void) proc_table->file->ha_index_end(); close_system_tables(thd, &open_tables_state_backup); + thd->variables.sql_mode = sql_mode_was; DBUG_RETURN(res); } -- cgit v1.2.1 From 991b9ee73597ba7287267207b3918e157e346899 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 13 Oct 2017 07:06:09 +0400 Subject: MDEV-13530 VARBINARY doesn't convert to to BLOB for sizes 65533, 65534 and 65535 --- sql/sql_const.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_const.h b/sql/sql_const.h index abe2a496045..e8385b537a8 100644 --- a/sql/sql_const.h +++ b/sql/sql_const.h @@ -41,7 +41,18 @@ #define MAX_MBWIDTH 3 /* Max multibyte sequence */ #define MAX_FIELD_CHARLENGTH 255 -#define MAX_FIELD_VARCHARLENGTH 65535 +/* + In MAX_FIELD_VARCHARLENGTH we reserve extra bytes for the overhead: + - 2 bytes for the length + - 1 byte for NULL bits + to avoid the "Row size too large" error for these three corner definitions: + CREATE TABLE t1 (c VARBINARY(65533)); + CREATE TABLE t1 (c VARBINARY(65534)); + CREATE TABLE t1 (c VARBINARY(65535)); + Like VARCHAR(65536), they will be converted to BLOB automatically + in non-sctict mode. +*/ +#define MAX_FIELD_VARCHARLENGTH (65535-2-1) #define MAX_FIELD_BLOBLENGTH UINT_MAX32 /* cf field_blob::get_length() */ #define CONVERT_IF_BIGGER_TO_BLOB 512 /* Threshold *in characters* */ -- cgit v1.2.1 From a4868c3509772da1666eb3d492515e7d39f8834d Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 19 Dec 2016 22:03:28 +0100 Subject: MDEV-9208: Function->Function->View = Mysqld segfault (Server crashes in Dependency_marker::visit_field on 2nd execution with merged subquery) Prevent crossing name resolution border in finding item tables. --- sql/item.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index fdfbba31404..3100a4e3408 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6876,7 +6876,11 @@ public: // Find which select the field is in. This is achieved by walking up // the select tree and looking for the table of interest. st_select_lex *sel; - for (sel= current_select; sel; sel= sel->outer_select()) + for (sel= current_select; + sel ; + sel= (sel->context.outer_context ? + sel->context.outer_context->select_lex: + NULL)) { List_iterator li(sel->leaf_tables); TABLE_LIST *tbl; -- cgit v1.2.1 From 8be76a6a907ab858b4fdb5d525548aedfdb4ddf3 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 12 Oct 2017 13:30:02 +0400 Subject: MDEV-10892 - rpl.rpl_semi_sync_uninstall_plugin fails with Assertion `0' failure in buildbot Removed plugin_array_version: it is being checked without mutex protection and thus is prone to data race and race conditions. In effect plugins are not protected from concurrent destruction. Removed state_mask inversion: doesn't seem to make any sense. When collecting local plugins list, only add plugins that match state_mask. Use plugin ref counting to protect against concurrent plugin destruction. --- sql/sql_plugin.cc | 57 ++++++++++++++++++++++--------------------------------- sql/sql_show.cc | 5 +++-- 2 files changed, 26 insertions(+), 36 deletions(-) (limited to 'sql') diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 75aca02990d..9eecd6a1345 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -194,7 +194,6 @@ static DYNAMIC_ARRAY plugin_array; static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; static MEM_ROOT plugin_mem_root; static bool reap_needed= false; -static int plugin_array_version=0; static bool initialized= 0; @@ -312,7 +311,6 @@ static void plugin_vars_free_values(sys_var *vars); static void restore_pluginvar_names(sys_var *first); static void plugin_opt_set_limits(struct my_option *, const struct st_mysql_sys_var *); -static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin); static void intern_plugin_unlock(LEX *lex, plugin_ref plugin); static void reap_plugins(void); @@ -924,14 +922,16 @@ SHOW_COMP_OPTION plugin_status(const char *name, size_t len, int type) } -static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc) +static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc, + uint state_mask= PLUGIN_IS_READY | + PLUGIN_IS_UNINITIALIZED) { st_plugin_int *pi= plugin_ref_to_int(rc); DBUG_ENTER("intern_plugin_lock"); mysql_mutex_assert_owner(&LOCK_plugin); - if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED)) + if (pi->state & state_mask) { plugin_ref plugin; #ifdef DBUG_OFF @@ -1111,7 +1111,6 @@ static bool plugin_add(MEM_ROOT *tmp_root, if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) goto err; - plugin_array_version++; if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr)) tmp_plugin_ptr->state= PLUGIN_IS_FREED; init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096); @@ -1210,7 +1209,6 @@ static void plugin_del(struct st_plugin_int *plugin) if (plugin->plugin_dl) plugin_dl_del(&plugin->plugin_dl->dl); plugin->state= PLUGIN_IS_FREED; - plugin_array_version++; free_root(&plugin->mem_root, MYF(0)); DBUG_VOID_RETURN; } @@ -2297,64 +2295,55 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name, bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, int type, uint state_mask, void *arg) { - uint idx, total; - struct st_plugin_int *plugin, **plugins; - int version=plugin_array_version; + uint idx, total= 0; + struct st_plugin_int *plugin; + plugin_ref *plugins; + my_bool res= FALSE; DBUG_ENTER("plugin_foreach_with_mask"); if (!initialized) DBUG_RETURN(FALSE); - state_mask= ~state_mask; // do it only once - mysql_mutex_lock(&LOCK_plugin); - total= type == MYSQL_ANY_PLUGIN ? plugin_array.elements - : plugin_hash[type].records; /* Do the alloca out here in case we do have a working alloca: - leaving the nested stack frame invalidates alloca allocation. + leaving the nested stack frame invalidates alloca allocation. */ - plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin)); if (type == MYSQL_ANY_PLUGIN) { - for (idx= 0; idx < total; idx++) + plugins= (plugin_ref*) my_alloca(plugin_array.elements * sizeof(plugin_ref)); + for (idx= 0; idx < plugin_array.elements; idx++) { plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); - plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; + if ((plugins[total]= intern_plugin_lock(0, plugin_int_to_ref(plugin), + state_mask))) + total++; } } else { HASH *hash= plugin_hash + type; - for (idx= 0; idx < total; idx++) + plugins= (plugin_ref*) my_alloca(hash->records * sizeof(plugin_ref)); + for (idx= 0; idx < hash->records; idx++) { plugin= (struct st_plugin_int *) my_hash_element(hash, idx); - plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; + if ((plugins[total]= intern_plugin_lock(0, plugin_int_to_ref(plugin), + state_mask))) + total++; } } mysql_mutex_unlock(&LOCK_plugin); for (idx= 0; idx < total; idx++) { - if (unlikely(version != plugin_array_version)) - { - mysql_mutex_lock(&LOCK_plugin); - for (uint i=idx; i < total; i++) - if (plugins[i] && plugins[i]->state & state_mask) - plugins[i]=0; - mysql_mutex_unlock(&LOCK_plugin); - } - plugin= plugins[idx]; /* It will stop iterating on first engine error when "func" returns TRUE */ - if (plugin && func(thd, plugin_int_to_ref(plugin), arg)) - goto err; + if ((res= func(thd, plugins[idx], arg))) + break; } + plugin_unlock_list(0, plugins, total); my_afree(plugins); - DBUG_RETURN(FALSE); -err: - my_afree(plugins); - DBUG_RETURN(TRUE); + DBUG_RETURN(res); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 6e045648591..512548b1d51 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -262,7 +262,7 @@ int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond) TABLE *table= tables->table; if (plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN, - ~PLUGIN_IS_FREED, table)) + ~(PLUGIN_IS_FREED | PLUGIN_IS_DYING), table)) DBUG_RETURN(1); DBUG_RETURN(0); @@ -5294,7 +5294,8 @@ int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond) DBUG_ENTER("fill_schema_engines"); if (plugin_foreach_with_mask(thd, iter_schema_engines, MYSQL_STORAGE_ENGINE_PLUGIN, - ~PLUGIN_IS_FREED, tables->table)) + ~(PLUGIN_IS_FREED | PLUGIN_IS_DYING), + tables->table)) DBUG_RETURN(1); DBUG_RETURN(0); } -- cgit v1.2.1 From 2bab29ebba7a641d43a98737fd1c160971357cd4 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 13 Oct 2017 07:24:35 -0700 Subject: Fixed the bug mdev-13135. For each SELECT the list sj_nests is built by the function simplify_joins() when scanning different join nests. This function may be called several times for the same join nest. That's why before adding a new member to sj_nests it is necessary to check if it's already in the list. The code of simplify_joins() lacked this check and as a result it could cause memory overwright for some queries. --- sql/sql_select.cc | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 720c0a22681..6e67bb11015 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13349,10 +13349,23 @@ simplify_joins(JOIN *join, List *join_list, COND *conds, bool top, nested_join= table->nested_join; if (table->sj_on_expr && !in_sj) { - /* - If this is a semi-join that is not contained within another semi-join, - leave it intact (otherwise it is flattened) - */ + /* + If this is a semi-join that is not contained within another semi-join + leave it intact (otherwise it is flattened) + */ + /* + Make sure that any semi-join appear in + the join->select_lex->sj_nests list only once + */ + List_iterator_fast sj_it(join->select_lex->sj_nests); + TABLE_LIST *sj_nest; + while ((sj_nest= sj_it++)) + { + if (table == sj_nest) + break; + } + if (sj_nest) + continue; join->select_lex->sj_nests.push_back(table); /* -- cgit v1.2.1 From 235b68299bc112f9cb7be97af8d01bf904919a6b Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Sat, 18 Feb 2017 17:47:31 +0100 Subject: MDEV-9619: Assertion `null_ref_table' failed in virtual table_map Item_direct_view_ref::used_tables() const on 2nd execution of PS Refer left expression indirectly in case it changes from execution to execution. --- sql/item_row.cc | 30 +++++++++++++++++++++++++++- sql/item_row.h | 1 + sql/item_subselect.cc | 6 ++++++ sql/opt_subselect.cc | 55 +++++++++++++++++++++++++++++++++++++++++++-------- sql/sql_base.cc | 7 ++++++- sql/sql_base.h | 5 +++-- sql/sql_do.cc | 2 +- sql/sql_insert.cc | 14 ++++++------- sql/sql_lex.h | 1 + sql/sql_load.cc | 10 +++++----- sql/sql_prepare.cc | 9 +++++---- sql/sql_select.cc | 2 +- sql/sql_update.cc | 4 ++-- sql/table.h | 3 ++- 14 files changed, 116 insertions(+), 33 deletions(-) (limited to 'sql') diff --git a/sql/item_row.cc b/sql/item_row.cc index ee1d17213ee..9e81c053b69 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -44,7 +44,14 @@ Item_row::Item_row(List &arg): //TODO: think placing 2-3 component items in item (as it done for function) if ((arg_count= arg.elements)) + { items= (Item**) sql_alloc(sizeof(Item*)*arg_count); + if (!items) + { + arg_count= 0; + return; + } + } else items= 0; List_iterator li(arg); @@ -53,7 +60,28 @@ Item_row::Item_row(List &arg): while ((item= li++)) { items[i]= item; - i++; + i++; + } +} + + +Item_row::Item_row(Item *item): + Item(), + used_tables_cache(0), + not_null_tables_cache(0), + arg_count(item->cols()), + const_item_cache(1), + with_null(0) +{ + items= (Item**) sql_alloc(sizeof(Item*) * arg_count); + if (!items) + { + arg_count= 0; + return; + } + for (uint i= 0; i < arg_count; i++) + { + items[i]= item->element_index(i); } } diff --git a/sql/item_row.h b/sql/item_row.h index aa56068f8ba..4d5c20711b5 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -35,6 +35,7 @@ public: const_item_cache(item->const_item_cache), with_null(0) {} + Item_row(Item *item); enum Type type() const { return ROW_ITEM; }; void illegal_method_call(const char *); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index ef90dd59be3..90f2bd5b9eb 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1374,6 +1374,9 @@ Item_in_subselect::Item_in_subselect(Item * left_exp, { DBUG_ENTER("Item_in_subselect::Item_in_subselect"); left_expr_orig= left_expr= left_exp; + /* prepare to possible disassembling the item in convert_subq_to_sj() */ + if (left_exp->type() == Item::ROW_ITEM) + left_expr_orig= new Item_row(left_exp); func= &eq_creator; init(select_lex, new select_exists_subselect(this)); max_columns= UINT_MAX; @@ -1398,6 +1401,9 @@ Item_allany_subselect::Item_allany_subselect(Item * left_exp, { DBUG_ENTER("Item_allany_subselect::Item_allany_subselect"); left_expr_orig= left_expr= left_exp; + /* prepare to possible disassembling the item in convert_subq_to_sj() */ + if (left_exp->type() == Item::ROW_ITEM) + left_expr_orig= new Item_row(left_exp); func= func_creator(all_arg); init(select_lex, new select_exists_subselect(this)); max_columns= 1; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index af1abb2001e..69a5367cdf1 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1609,6 +1609,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) sj-nest. */ st_select_lex *subq_lex= subq_pred->unit->first_select(); + DBUG_ASSERT(subq_lex->next_select() == NULL); nested_join->join_list.empty(); List_iterator_fast li(subq_lex->top_join_list); TABLE_LIST *tl; @@ -1706,7 +1707,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) if (subq_pred->left_expr->cols() == 1) { - nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr); + /* add left = select_list_element */ + nested_join->sj_outer_expr_list.push_back(&subq_pred->left_expr); /* Create Item_func_eq. Note that 1. this is done on the statement, not execution, arena @@ -1718,24 +1720,61 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) */ Item_func_eq *item_eq= new Item_func_eq(subq_pred->left_expr_orig, subq_lex->ref_pointer_array[0]); + if (!item_eq) + DBUG_RETURN(TRUE); if (subq_pred->left_expr_orig != subq_pred->left_expr) thd->change_item_tree(item_eq->arguments(), subq_pred->left_expr); item_eq->in_equality_no= 0; sj_nest->sj_on_expr= and_items(sj_nest->sj_on_expr, item_eq); } - else + else if (subq_pred->left_expr->type() == Item::ROW_ITEM) { + /* + disassemple left expression and add + left1 = select_list_element1 and left2 = select_list_element2 ... + */ for (uint i= 0; i < subq_pred->left_expr->cols(); i++) { nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr-> - element_index(i)); - Item_func_eq *item_eq= - new Item_func_eq(subq_pred->left_expr->element_index(i), + addr(i)); + Item_func_eq *item_eq= + new Item_func_eq(subq_pred->left_expr_orig->element_index(i), subq_lex->ref_pointer_array[i]); + if (!item_eq) + DBUG_RETURN(TRUE); + DBUG_ASSERT(subq_pred->left_expr->element_index(i)->fixed); + if (subq_pred->left_expr_orig->element_index(i) != + subq_pred->left_expr->element_index(i)) + thd->change_item_tree(item_eq->arguments(), + subq_pred->left_expr->element_index(i)); item_eq->in_equality_no= i; sj_nest->sj_on_expr= and_items(sj_nest->sj_on_expr, item_eq); } } + else + { + /* + add row operation + left = (select_list_element1, select_list_element2, ...) + */ + Item_row *row= new Item_row(subq_lex->pre_fix); + /* fix fields on subquery was call so they should be the same */ + DBUG_ASSERT(subq_pred->left_expr->cols() == row->cols()); + if (!row) + DBUG_RETURN(TRUE); + nested_join->sj_outer_expr_list.push_back(&subq_pred->left_expr); + Item_func_eq *item_eq= + new Item_func_eq(subq_pred->left_expr_orig, row); + if (!item_eq) + DBUG_RETURN(TRUE); + for (uint i= 0; i < row->cols(); i++) + { + if (row->element_index(i) != subq_lex->ref_pointer_array[i]) + thd->change_item_tree(row->addr(i), subq_lex->ref_pointer_array[i]); + } + item_eq->in_equality_no= 0; + sj_nest->sj_on_expr= and_items(sj_nest->sj_on_expr, item_eq); + } /* Fix the created equality and AND @@ -3285,8 +3324,8 @@ void restore_prev_sj_state(const table_map remaining_tables, ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest, table_map remaining_tables) { - List_iterator li(sj_nest->nested_join->sj_outer_expr_list); - Item *item; + List_iterator li(sj_nest->nested_join->sj_outer_expr_list); + Item **item; uint i= 0; ulonglong res= 0; while ((item= li++)) @@ -3297,7 +3336,7 @@ ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest, class and see if there is an element that is bound? (this is an optional feature) */ - if (!(item->used_tables() & remaining_tables)) + if (!(item[0]->used_tables() & remaining_tables)) { res |= 1ULL << i; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7f84f35c825..c06c4fcff29 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8128,13 +8128,15 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, bool setup_fields(THD *thd, Item **ref_pointer_array, List &fields, enum_mark_columns mark_used_columns, - List *sum_func_list, bool allow_sum_func) + List *sum_func_list, List *pre_fix, + bool allow_sum_func) { reg2 Item *item; enum_mark_columns save_mark_used_columns= thd->mark_used_columns; nesting_map save_allow_sum_func= thd->lex->allow_sum_func; List_iterator it(fields); bool save_is_item_list_lookup; + bool make_pre_fix= (pre_fix && (pre_fix->elements == 0)); DBUG_ENTER("setup_fields"); DBUG_PRINT("enter", ("ref_pointer_array: %p", ref_pointer_array)); @@ -8181,6 +8183,9 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, thd->lex->current_select->cur_pos_in_select_list= 0; while ((item= it++)) { + if (make_pre_fix) + pre_fix->push_back(item, thd->stmt_arena->mem_root); + if ((!item->fixed && item->fix_fields(thd, it.ref())) || (item= *(it.ref()))->check_cols(1)) { diff --git a/sql/sql_base.h b/sql/sql_base.h index d49554d5473..0cde933afb8 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -216,7 +216,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, List *sum_func_list, uint wild_num); bool setup_fields(THD *thd, Item** ref_pointer_array, List &item, enum_mark_columns mark_used_columns, - List *sum_func_list, bool allow_sum_func); + List *sum_func_list, List *pre_fix, + bool allow_sum_func); void unfix_fields(List &items); bool fill_record(THD *thd, Field **field, List &values, bool ignore_errors, bool use_value); @@ -407,7 +408,7 @@ inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array, bool res; thd->lex->select_lex.no_wrap_view_item= TRUE; res= setup_fields(thd, ref_pointer_array, item, mark_used_columns, - sum_func_list, allow_sum_func); + sum_func_list, NULL, allow_sum_func); thd->lex->select_lex.no_wrap_view_item= FALSE; return res; } diff --git a/sql/sql_do.cc b/sql/sql_do.cc index 4ba887b5ab2..46bdb421b3a 100644 --- a/sql/sql_do.cc +++ b/sql/sql_do.cc @@ -28,7 +28,7 @@ bool mysql_do(THD *thd, List &values) List_iterator li(values); Item *value; DBUG_ENTER("mysql_do"); - if (setup_fields(thd, 0, values, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, 0, values, MARK_COLUMNS_NONE, 0, NULL, 0)) DBUG_RETURN(TRUE); while ((value = li++)) value->val_int(); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 70a12faafb5..267a9a6f94e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -262,7 +262,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, if (table_list->is_view()) unfix_fields(fields); - res= setup_fields(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0); + res= setup_fields(thd, 0, fields, MARK_COLUMNS_WRITE, 0, NULL, 0); /* Restore the current context. */ ctx_state.restore_state(context, table_list); @@ -373,7 +373,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, } /* Check the fields we are going to modify */ - if (setup_fields(thd, 0, update_fields, MARK_COLUMNS_WRITE, 0, 0)) + if (setup_fields(thd, 0, update_fields, MARK_COLUMNS_WRITE, 0, NULL, 0)) return -1; if (insert_table_list->is_view() && @@ -810,7 +810,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); goto abort; } - if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, NULL, 0)) goto abort; } its.rewind (); @@ -1452,7 +1452,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, table_list->next_local= 0; context->resolve_in_table_list_only(table_list); - res= (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0) || + res= (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, NULL, 0) || check_insert_fields(thd, context->table_list, fields, *values, !insert_into_view, 0, &map)); @@ -1468,7 +1468,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, } if (!res) - res= setup_fields(thd, 0, update_values, MARK_COLUMNS_READ, 0, 0); + res= setup_fields(thd, 0, update_values, MARK_COLUMNS_READ, 0, NULL, 0); if (!res && duplic == DUP_UPDATE) { @@ -3369,7 +3369,7 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) */ lex->current_select= &lex->select_lex; - res= (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0) || + res= (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, NULL, 0) || check_insert_fields(thd, table_list, *fields, values, !insert_into_view, 1, &map)); @@ -3425,7 +3425,7 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) ctx_state.get_first_name_resolution_table(); res= res || setup_fields(thd, 0, *info.update_values, - MARK_COLUMNS_READ, 0, 0); + MARK_COLUMNS_READ, 0, NULL, 0); if (!res) { /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index d283085886e..3dcf8769c14 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -758,6 +758,7 @@ public: Group_list_ptrs *group_list_ptrs; List item_list; /* list of fields & expressions */ + List pre_fix; /* above list before fix_fields */ List interval_list; bool is_item_list_lookup; /* diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 23865ab8983..5029efa7d68 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -293,15 +293,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, Let us also prepare SET clause, altough it is probably empty in this case. */ - if (setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) || - setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) || + setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, NULL, 0)) DBUG_RETURN(TRUE); } else { // Part field list /* TODO: use this conds for 'WITH CHECK OPTIONS' */ - if (setup_fields(thd, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) || - setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) || + if (setup_fields(thd, 0, fields_vars, MARK_COLUMNS_WRITE, 0, NULL, 0) || + setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) || check_that_all_fields_are_given_values(thd, table, table_list)) DBUG_RETURN(TRUE); /* @@ -320,7 +320,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, } } /* Fix the expressions in SET clause */ - if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, NULL, 0)) DBUG_RETURN(TRUE); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 094677e150d..851e4f7b8ab 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1307,7 +1307,7 @@ static bool mysql_test_insert(Prepared_statement *stmt, my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); goto error; } - if (setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, NULL, 0)) goto error; } } @@ -1397,7 +1397,7 @@ static int mysql_test_update(Prepared_statement *stmt, table_list->register_want_access(want_privilege); #endif thd->lex->select_lex.no_wrap_view_item= TRUE; - res= setup_fields(thd, 0, select->item_list, MARK_COLUMNS_READ, 0, 0); + res= setup_fields(thd, 0, select->item_list, MARK_COLUMNS_READ, 0, NULL, 0); thd->lex->select_lex.no_wrap_view_item= FALSE; if (res) goto error; @@ -1408,7 +1408,8 @@ static int mysql_test_update(Prepared_statement *stmt, (SELECT_ACL & ~table_list->table->grant.privilege); table_list->register_want_access(SELECT_ACL); #endif - if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0) || + if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, NULL, + 0) || check_unique_table(thd, table_list)) goto error; /* TODO: here we should send types of placeholders to the client. */ @@ -1575,7 +1576,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt, if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL, DT_PREPARE | DT_CREATE)) DBUG_RETURN(TRUE); - DBUG_RETURN(setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0)); + DBUG_RETURN(setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, NULL, 0)); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6e67bb11015..c7f547edbc0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -724,7 +724,7 @@ JOIN::prepare(Item ***rref_pointer_array, wild_num)) || select_lex->setup_ref_array(thd, real_og_num) || setup_fields(thd, (*rref_pointer_array), fields_list, MARK_COLUMNS_READ, - &all_fields, 1) || + &all_fields, &select_lex->pre_fix, 1) || setup_without_group(thd, (*rref_pointer_array), tables_list, select_lex->leaf_tables, fields_list, all_fields, &conds, order, group_list, diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 060952a589d..ede38468513 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -361,7 +361,7 @@ int mysql_update(THD *thd, table_list->grant.want_privilege= table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); #endif - if (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, NULL, 0)) { free_underlaid_joins(thd, select_lex); DBUG_RETURN(1); /* purecov: inspected */ @@ -1521,7 +1521,7 @@ int multi_update::prepare(List ¬_used_values, reference tables */ - int error= setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0); + int error= setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, NULL, 0); ti.rewind(); while ((table_ref= ti++)) diff --git a/sql/table.h b/sql/table.h index dde01a85d77..c981243f28c 100644 --- a/sql/table.h +++ b/sql/table.h @@ -33,6 +33,7 @@ /* Structs that defines the TABLE */ class Item; /* Needed by ORDER */ +typedef Item (*Item_ptr); class Item_subselect; class Item_field; class GRANT_TABLE; @@ -2348,7 +2349,7 @@ typedef struct st_nested_join table_map sj_depends_on; /* Outer non-trivially correlated tables */ table_map sj_corr_tables; - List sj_outer_expr_list; + List sj_outer_expr_list; /** True if this join nest node is completely covered by the query execution plan. This means two things. -- cgit v1.2.1 From 3b7aa3017b65dcf11d33617e954e1cb471703582 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 13 Oct 2017 18:41:38 +0200 Subject: Cleanup usage of DBUG_ASSERTS. --- sql/item.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 3100a4e3408..a8913e97fe9 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -8075,7 +8075,6 @@ bool Item_direct_view_ref::send(Protocol *protocol, String *buffer) bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) { - DBUG_ASSERT(1); /* view fild reference must be defined */ DBUG_ASSERT(*ref); /* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */ @@ -9959,7 +9958,7 @@ void Item_direct_view_ref::update_used_tables() table_map Item_direct_view_ref::used_tables() const { - DBUG_ASSERT(null_ref_table); + DBUG_ASSERT(fixed); if (get_depended_from()) return OUTER_REF_TABLE_BIT; -- cgit v1.2.1 From d76f5774fe70c51577cfbfdddcbfb3309d51f06e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 16 Sep 2017 14:52:42 +0200 Subject: MDEV-13459 Warnings, when compiling with gcc-7.x mostly caused by -Wimplicit-fallthrough --- sql/events.cc | 8 +++--- sql/field.cc | 2 +- sql/ha_partition.cc | 1 + sql/item.cc | 2 +- sql/item_func.cc | 2 ++ sql/item_strfunc.cc | 4 +-- sql/log.cc | 5 ++++ sql/log_event.cc | 15 ----------- sql/opt_sum.cc | 1 + sql/partition_info.cc | 2 -- sql/sp_head.cc | 2 +- sql/sql_admin.cc | 1 - sql/sql_lex.cc | 4 ++- sql/sql_parse.cc | 6 +++-- sql/sql_partition.cc | 2 +- sql/sql_plugin.cc | 74 +++++++++++++++++++++++++-------------------------- sql/sql_prepare.cc | 1 + sql/sql_repl.cc | 1 + sql/sql_show.cc | 1 + sql/sql_table.cc | 2 +- sql/sql_yacc.yy | 10 +++---- 21 files changed, 71 insertions(+), 75 deletions(-) (limited to 'sql') diff --git a/sql/events.cc b/sql/events.cc index 763c75e77b0..008b6223702 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -185,8 +185,8 @@ common_1_lev_code: expr= tmp_expr - (tmp_expr/60)*60; /* the code after the switch will finish */ - } break; + } case INTERVAL_HOUR_SECOND: { ulonglong tmp_expr= expr; @@ -202,8 +202,8 @@ common_1_lev_code: expr= tmp_expr - (tmp_expr/60)*60; /* the code after the switch will finish */ - } break; + } case INTERVAL_DAY_SECOND: { ulonglong tmp_expr= expr; @@ -225,8 +225,8 @@ common_1_lev_code: expr= tmp_expr - (tmp_expr/60)*60; /* the code after the switch will finish */ - } break; + } case INTERVAL_DAY_MICROSECOND: case INTERVAL_HOUR_MICROSECOND: case INTERVAL_MINUTE_MICROSECOND: @@ -240,6 +240,8 @@ common_1_lev_code: break; case INTERVAL_WEEK: expr/= 7; + close_quote= FALSE; + break; default: close_quote= FALSE; break; diff --git a/sql/field.cc b/sql/field.cc index 716d522a196..a2e0caaa50d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -9218,7 +9218,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, case MYSQL_TYPE_DATE: /* We don't support creation of MYSQL_TYPE_DATE anymore */ sql_type= MYSQL_TYPE_NEWDATE; - /* fall trough */ + /* fall through */ case MYSQL_TYPE_NEWDATE: length= MAX_DATE_WIDTH; break; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index e048dbad5e6..b2c2140d4dc 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -7331,6 +7331,7 @@ void ha_partition::print_error(int error, myf errflag) m_err_rec= NULL; DBUG_VOID_RETURN; } + /* fall through */ default: { if (!(thd->lex->alter_info.flags & ALTER_TRUNCATE_PARTITION)) diff --git a/sql/item.cc b/sql/item.cc index a8913e97fe9..3c633ddc9ca 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6004,7 +6004,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) collation.collation); break; } - /* Fall through to make_string_field() */ + /* fall through */ case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: case MYSQL_TYPE_VAR_STRING: diff --git a/sql/item_func.cc b/sql/item_func.cc index cfccd66ea8a..00006a25a8d 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -863,6 +863,7 @@ void Item_func_num1::fix_length_and_dec() break; case TIME_RESULT: cached_result_type= DECIMAL_RESULT; + /* fall through */ case DECIMAL_RESULT: decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC max_length= args[0]->max_length; @@ -2038,6 +2039,7 @@ my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value) return decimal_value; case E_DEC_DIV_ZERO: signal_divide_by_null(); + /* fall through */ default: null_value= 1; return 0; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 756ab5152ca..939e518e386 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -4430,7 +4430,7 @@ bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) goto null; case DYN_COL_INT: signed_value= 1; // For error message - /* fall_trough */ + /* fall through */ case DYN_COL_UINT: if (signed_value || val.x.ulong_value <= LONGLONG_MAX) { @@ -4443,7 +4443,7 @@ bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) } /* let double_to_datetime_with_warn() issue the warning message */ val.x.double_value= static_cast(ULONGLONG_MAX); - /* fall_trough */ + /* fall through */ case DYN_COL_DOUBLE: if (double_to_datetime_with_warn(val.x.double_value, ltime, fuzzy_date, 0 /* TODO */)) diff --git a/sql/log.cc b/sql/log.cc index f8c256e645f..5b4ba87ef52 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -7261,8 +7261,10 @@ void TC_LOG_MMAP::close() mysql_cond_destroy(&COND_pool); mysql_cond_destroy(&COND_active); mysql_cond_destroy(&COND_queue_busy); + /* fall through */ case 5: data[0]='A'; // garble the first (signature) byte, in case mysql_file_delete fails + /* fall through */ case 4: for (i=0; i < npages; i++) { @@ -7271,10 +7273,13 @@ void TC_LOG_MMAP::close() mysql_mutex_destroy(&pages[i].lock); mysql_cond_destroy(&pages[i].cond); } + /* fall through */ case 3: my_free(pages); + /* fall through */ case 2: my_munmap((char*)data, (size_t)file_length); + /* fall through */ case 1: mysql_file_close(fd, MYF(0)); } diff --git a/sql/log_event.cc b/sql/log_event.cc index d5b5b5a4870..18e4cfbf187 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6437,21 +6437,6 @@ User_var_log_event(const char* buf, uint event_len, we keep the flags set to UNDEF_F. */ uint bytes_read= ((val + val_len) - start); -#ifndef DBUG_OFF - bool old_pre_checksum_fd= description_event->is_version_before_checksum( - &description_event->server_version_split); -#endif - DBUG_ASSERT((bytes_read == data_written - - (old_pre_checksum_fd || - (description_event->checksum_alg == - BINLOG_CHECKSUM_ALG_OFF)) ? - 0 : BINLOG_CHECKSUM_LEN) - || - (bytes_read == data_written -1 - - (old_pre_checksum_fd || - (description_event->checksum_alg == - BINLOG_CHECKSUM_ALG_OFF)) ? - 0 : BINLOG_CHECKSUM_LEN)); if ((data_written - bytes_read) > 0) { flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 1a8c6be5f41..f717be5ba3f 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -1047,6 +1047,7 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond) case Item_func::LT_FUNC: case Item_func::LE_FUNC: less_fl= 1; + /* fall through */ case Item_func::GT_FUNC: case Item_func::GE_FUNC: { diff --git a/sql/partition_info.cc b/sql/partition_info.cc index d8b901701cb..512bf296135 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -34,8 +34,6 @@ partition_info *partition_info::get_clone() { - if (!this) - return 0; List_iterator part_it(partitions); partition_element *part; partition_info *clone= new partition_info(); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 69364eaa43f..14a57914560 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -139,7 +139,7 @@ sp_get_item_value(THD *thd, Item *item, String *str) case DECIMAL_RESULT: if (item->field_type() != MYSQL_TYPE_BIT) return item->val_str(str); - else {/* Bit type is handled as binary string */} + /* fall through */ case STRING_RESULT: { String *result= item->val_str(str); diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 55effcd7002..7cddf50a896 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -54,7 +54,6 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list) if (thd->stmt_da->is_ok()) thd->stmt_da->reset_diagnostics_area(); table_list->table= NULL; - result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK; DBUG_RETURN(result_code); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 6611fd43876..6f94f1fbe63 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1147,12 +1147,14 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) state= MY_LEX_HEX_NUMBER; break; } + /* fall through */ case MY_LEX_IDENT_OR_BIN: if (lip->yyPeek() == '\'') { // Found b'bin-number' state= MY_LEX_BIN_NUMBER; break; } + /* fall through */ case MY_LEX_IDENT: const char *start; #if defined(USE_MB) && defined(USE_MB_IDENT) @@ -1499,7 +1501,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) state= MY_LEX_USER_VARIABLE_DELIMITER; break; } - /* " used for strings */ + /* fall through */ /* " used for strings */ case MY_LEX_STRING: // Incomplete text string if (!(yylval->lex_str.str = get_text(lip, 1, 1))) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ba0520de4bb..d003a13ae09 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2481,7 +2481,7 @@ case SQLCOM_PREPARE: #ifdef WITH_PARTITION_STORAGE_ENGINE { partition_info *part_info= thd->lex->part_info; - if (part_info && !(part_info= thd->lex->part_info->get_clone())) + if (part_info && !(part_info= part_info->get_clone())) { res= -1; goto end_with_restore_list; @@ -2850,8 +2850,8 @@ end_with_restore_list: /* mysql_update return 2 if we need to switch to multi-update */ if (up_result != 2) break; - /* Fall through */ } + /* fall through */ case SQLCOM_UPDATE_MULTI: { DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -2961,6 +2961,7 @@ end_with_restore_list: DBUG_PRINT("debug", ("Just after generate_incident()")); } #endif + /* fall through */ case SQLCOM_INSERT: { DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -3698,6 +3699,7 @@ end_with_restore_list: initialize this variable because RESET shares the same code as FLUSH */ lex->no_write_to_binlog= 1; + /* fall through */ case SQLCOM_FLUSH: { int write_to_binlog; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 0d9f6e6a1f5..bf34d328dc5 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4640,7 +4640,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, thd->work_part_info= thd->lex->part_info; if (thd->work_part_info && - !(thd->work_part_info= thd->lex->part_info->get_clone())) + !(thd->work_part_info= thd->work_part_info->get_clone())) DBUG_RETURN(TRUE); /* ALTER_ADMIN_PARTITION is handled in mysql_admin_table */ diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 9eecd6a1345..d1e855e272e 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1078,42 +1078,42 @@ static bool plugin_add(MEM_ROOT *tmp_root, if (!name->str && plugin_find_internal(&tmp.name, MYSQL_ANY_PLUGIN)) continue; // already installed - struct st_plugin_int *tmp_plugin_ptr; - if (*(int*)plugin->info < - min_plugin_info_interface_version[plugin->type] || - ((*(int*)plugin->info) >> 8) > - (cur_plugin_info_interface_version[plugin->type] >> 8)) - { - char buf[256]; - strxnmov(buf, sizeof(buf) - 1, "API version for ", - plugin_type_names[plugin->type].str, - " plugin ", tmp.name.str, - " not supported by this version of the server", NullS); - report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, ENOEXEC, buf); - goto err; - } - if (plugin_maturity_map[plugin->maturity] < plugin_maturity) - { - char buf[256]; - strxnmov(buf, sizeof(buf) - 1, "Loading of ", - plugin_maturity_names[plugin->maturity], - " plugin ", tmp.name.str, - " is prohibited by --plugin-maturity=", - plugin_maturity_names[plugin_maturity], - NullS); - report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, EPERM, buf); - goto err; - } - tmp.plugin= plugin; - tmp.ref_count= 0; - tmp.state= PLUGIN_IS_UNINITIALIZED; - tmp.load_option= PLUGIN_ON; + struct st_plugin_int *tmp_plugin_ptr; + if (*(int*)plugin->info < + min_plugin_info_interface_version[plugin->type] || + ((*(int*)plugin->info) >> 8) > + (cur_plugin_info_interface_version[plugin->type] >> 8)) + { + char buf[256]; + strxnmov(buf, sizeof(buf) - 1, "API version for ", + plugin_type_names[plugin->type].str, + " plugin ", tmp.name.str, + " not supported by this version of the server", NullS); + report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, ENOEXEC, buf); + goto err; + } + if (plugin_maturity_map[plugin->maturity] < plugin_maturity) + { + char buf[256]; + strxnmov(buf, sizeof(buf) - 1, "Loading of ", + plugin_maturity_names[plugin->maturity], + " plugin ", tmp.name.str, + " is prohibited by --plugin-maturity=", + plugin_maturity_names[plugin_maturity], + NullS); + report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, EPERM, buf); + goto err; + } + tmp.plugin= plugin; + tmp.ref_count= 0; + tmp.state= PLUGIN_IS_UNINITIALIZED; + tmp.load_option= PLUGIN_ON; - if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) - goto err; - if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr)) - tmp_plugin_ptr->state= PLUGIN_IS_FREED; - init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096); + if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) + goto err; + if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr)) + tmp_plugin_ptr->state= PLUGIN_IS_FREED; + init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096); if (name->str) DBUG_RETURN(FALSE); // all done @@ -1822,10 +1822,10 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) case '\0': list= NULL; /* terminate the loop */ /* fall through */ + case ';': #ifndef __WIN__ case ':': /* can't use this as delimiter as it may be drive letter */ #endif - case ';': str->str[str->length]= '\0'; if (str == &name) // load all plugins in named module { @@ -1863,6 +1863,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) str->str= p; continue; } + /* fall through */ default: str->length++; continue; @@ -3947,4 +3948,3 @@ void add_plugin_options(DYNAMIC_ARRAY *options, MEM_ROOT *mem_root) insert_dynamic(options, (uchar*) opt); } } - diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 851e4f7b8ab..faaeaf51573 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2075,6 +2075,7 @@ static bool check_prepared_statement(Prepared_statement *stmt) if (res != 2) break; + /* fall through */ case SQLCOM_UPDATE_MULTI: res= mysql_test_multiupdate(stmt, tables, res == 2); break; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 871cb27f0d0..ca6e8d15e7a 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1139,6 +1139,7 @@ impossible position"; loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK); break; } + /* fall through */ default: errmsg = "could not find next log"; my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 512548b1d51..8789f0c9f24 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -931,6 +931,7 @@ public: is_handled= FALSE; break; } + /* fall through */ case ER_COLUMNACCESS_DENIED_ERROR: case ER_VIEW_NO_EXPLAIN: /* Error was anonymized, ignore all the same. */ case ER_PROCACCESS_DENIED_ERROR: diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6ab39d7f8c6..e6490876352 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5504,7 +5504,7 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, case LEAVE_AS_IS: if (!indexes_were_disabled) break; - /* fall-through: disabled indexes */ + /* fall-through */ case DISABLE: error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 35c7203ca0d..4805cd4c66a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4212,15 +4212,11 @@ size_number: switch (end_ptr[0]) { case 'g': - case 'G': - text_shift_number+=10; + case 'G': text_shift_number+=30; break; case 'm': - case 'M': - text_shift_number+=10; + case 'M': text_shift_number+=20; break; case 'k': - case 'K': - text_shift_number+=10; - break; + case 'K': text_shift_number+=10; break; default: { my_error(ER_WRONG_SIZE_NUMBER, MYF(0)); -- cgit v1.2.1 From 421716391b8bafe9af853b1ee3f83d521b69db6e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 14 Oct 2017 15:03:43 +0200 Subject: MDEV-13912 Can't refer the same column twice in one ALTER TABLE backport ce6c0e584e3 MDEV-8960: Can't refer the same column twice in one ALTER TABLE Problem was that if column was created in alter table when it was refered again it was not tried to find from list of current columns. mysql_prepare_alter_table: There is two cases (1) If alter table adds a new column and then later alter changes the field definition, there was no check from list of new columns, instead an incorrect error was given. (2) If alter table adds a new column and then later alter changes the default, there was no check from list of new columns, instead an incorrect error was given. --- sql/sql_table.cc | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e6490876352..19093d9b2ca 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5739,9 +5739,25 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, { if (def->change && ! def->field) { - my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, - table->s->table_name.str); - goto err; + /* + Check if there is modify for newly added field. + */ + Create_field *find; + find_it.rewind(); + while((find=find_it++)) + { + if (!my_strcasecmp(system_charset_info,find->field_name, def->field_name)) + break; + } + + if (find && !find->field) + find_it.remove(); + else + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, + table->s->table_name.str); + goto err; + } } /* Check that the DATE/DATETIME not null field we are going to add is @@ -5793,6 +5809,29 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, */ alter_info->change_level= ALTER_TABLE_DATA_CHANGED; } + /* + Check if there is alter for newly added field. + */ + alter_it.rewind(); + Alter_column *alter; + while ((alter=alter_it++)) + { + if (!my_strcasecmp(system_charset_info,def->field_name, alter->name)) + break; + } + if (alter) + { + if (def->sql_type == MYSQL_TYPE_BLOB) + { + my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change); + goto err; + } + if ((def->def=alter->def)) // Use new default + def->flags&= ~NO_DEFAULT_VALUE_FLAG; + else + def->flags|= NO_DEFAULT_VALUE_FLAG; + alter_it.remove(); + } } if (alter_info->alter_list.elements) { -- cgit v1.2.1 From 19a702a85c69d241e360d1d5a040378928a3fdca Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 14 Oct 2017 15:59:54 +0200 Subject: MDEV-14056 DROP TEMPORARY TABLE IF EXISTS causes error 1290 with read_only option if it's a DROP TABLE, we cannot detect whether a table is temporary by looking in thd->temporary_tables - because the table might simply not exist at all. --- sql/sql_parse.cc | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) (limited to 'sql') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d003a13ae09..9f8a625325f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -811,8 +811,7 @@ out: @retval FALSE The statement isn't updating any relevant tables. */ -static my_bool deny_updates_if_read_only_option(THD *thd, - TABLE_LIST *all_tables) +static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables) { DBUG_ENTER("deny_updates_if_read_only_option"); @@ -821,11 +820,7 @@ static my_bool deny_updates_if_read_only_option(THD *thd, LEX *lex= thd->lex; - const my_bool user_is_super= - ((ulong)(thd->security_ctx->master_access & SUPER_ACL) == - (ulong)SUPER_ACL); - - if (user_is_super) + if (thd->security_ctx->master_access & SUPER_ACL) DBUG_RETURN(FALSE); if (!(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA)) @@ -835,30 +830,26 @@ static my_bool deny_updates_if_read_only_option(THD *thd, if (lex->sql_command == SQLCOM_UPDATE_MULTI) DBUG_RETURN(FALSE); + if (lex->sql_command == SQLCOM_CREATE_DB || + lex->sql_command == SQLCOM_DROP_DB) + DBUG_RETURN(TRUE); + /* a table-to-be-created is not in the temp table list yet, so CREATE TABLE needs a special treatment */ - const bool update_real_tables= - lex->sql_command == SQLCOM_CREATE_TABLE - ? !(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) - : some_non_temp_table_to_be_updated(thd, all_tables); - - const bool create_or_drop_databases= - (lex->sql_command == SQLCOM_CREATE_DB) || - (lex->sql_command == SQLCOM_DROP_DB); - - if (update_real_tables || create_or_drop_databases) - { - /* - An attempt was made to modify one or more non-temporary tables. - */ - DBUG_RETURN(TRUE); - } + if (lex->sql_command == SQLCOM_CREATE_TABLE) + DBUG_RETURN(!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)); + /* + a table-to-be-dropped might not exist (DROP TEMPORARY TABLE IF EXISTS), + cannot use the temp table list either. + */ + if (lex->sql_command == SQLCOM_DROP_TABLE && lex->drop_temporary) + DBUG_RETURN(FALSE); - /* Assuming that only temporary tables are modified. */ - DBUG_RETURN(FALSE); + /* Now, check thd->temporary_tables list */ + DBUG_RETURN(some_non_temp_table_to_be_updated(thd, all_tables)); } /** -- cgit v1.2.1 From b036b6b59464524d7dd54a4c9a75b5ee8a14dbe0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 16 Oct 2017 12:34:17 +0200 Subject: MDEV-13937 Aria engine: Internal Error 160 after partition handling Partition wasn't setting HA_OPTION_PACK_RECORD on ALTER TABLE if the row format was PAGE. (so one bit in the null bitmap was reserved for a deleted bit - see make_empty_rec - and all actual null bits were one off) --- sql/sql_partition.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index bf34d328dc5..cb01f8e339f 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6672,7 +6672,8 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, lpt->alter_info= alter_info; lpt->create_info= create_info; lpt->db_options= create_info->table_options; - if (create_info->row_type == ROW_TYPE_DYNAMIC) + if (create_info->row_type != ROW_TYPE_FIXED && + create_info->row_type != ROW_TYPE_DEFAULT) lpt->db_options|= HA_OPTION_PACK_RECORD; lpt->table= fast_alter_table; lpt->old_table= table; -- cgit v1.2.1 From b000e169562697aa072600695d4f0c0412f94f4f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 17 Oct 2017 10:57:51 +0200 Subject: Bug#26361149 MYSQL SERVER CRASHES AT: COL IN(IFNULL(CONST, COL), NAME_CONST('NAME', NULL)) based on: commit f7316aa0c9a Author: Ajo Robert Date: Thu Aug 24 17:03:21 2017 +0530 Bug#26361149 MYSQL SERVER CRASHES AT: COL IN(IFNULL(CONST, COL), NAME_CONST('NAME', NULL)) Backport of Bug#19143243 fix. NAME_CONST item can return NULL_ITEM type in case of incorrect arguments. NULL_ITEM has special processing in Item_func_in function. In Item_func_in::fix_length_and_dec an array of possible comparators is created. Since NAME_CONST function has NULL_ITEM type, corresponding array element is empty. Then NAME_CONST is wrapped to ITEM_CACHE. ITEM_CACHE can not return proper type(NULL_ITEM) in Item_func_in::val_int(), so the NULL_ITEM is attempted compared with an empty comparator. The fix is to disable the caching of Item_name_const item. --- sql/item.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 3c633ddc9ca..fa2e52bfd4a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6726,6 +6726,7 @@ bool Item::cache_const_expr_analyzer(uchar **arg) */ if (const_item() && !(basic_const_item() || item->basic_const_item() || + item->type() == Item::NULL_ITEM || /* Item_name_const hack */ item->type() == Item::FIELD_ITEM || item->type() == SUBSELECT_ITEM || /* -- cgit v1.2.1