diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-01-04 09:22:59 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-01-04 09:22:59 +0200 |
commit | 145ae15a33210e13d33d6f41b145b3f04cab2263 (patch) | |
tree | 02810e3c0d629f7d7def2dbc663154cbdb53242f /sql | |
parent | acd2862e65a6555fba6065b7b4ded8513e2ce37c (diff) | |
parent | 1a1bda2222e0c2ab41baed1510f6fbca80c20d31 (diff) | |
download | mariadb-git-145ae15a33210e13d33d6f41b145b3f04cab2263.tar.gz |
Merge bb-10.2-ext into 10.3
Diffstat (limited to 'sql')
45 files changed, 1709 insertions, 903 deletions
diff --git a/sql/events.cc b/sql/events.cc index 36f03e26125..3ad546217a7 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -421,7 +421,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data) DBUG_RETURN(ret); #ifdef WITH_WSREP error: - DBUG_RETURN(true); + DBUG_RETURN(TRUE); #endif /* WITH_WSREP */ } diff --git a/sql/filesort.cc b/sql/filesort.cc index b762773b11e..4cf2a00dbc4 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -710,6 +710,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, handler *file; MY_BITMAP *save_read_set, *save_write_set, *save_vcol_set; Item *sort_cond; + ha_rows retval; DBUG_ENTER("find_all_keys"); DBUG_PRINT("info",("using: %s", (select ? select->quick ? "ranges" : "where": @@ -767,7 +768,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, if (quick_select) { if (select->quick->reset()) - DBUG_RETURN(HA_POS_ERROR); + goto err; } DEBUG_SYNC(thd, "after_index_merge_phase1"); @@ -804,7 +805,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, (void) file->extra(HA_EXTRA_NO_CACHE); file->ha_rnd_end(); } - DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ + goto err; /* purecov: inspected */ } bool write_record= false; @@ -852,7 +853,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, if (idx == param->max_keys_per_buffer) { if (write_keys(param, fs_info, idx, buffpek_pointers, tempfile)) - DBUG_RETURN(HA_POS_ERROR); + goto err; idx= 0; indexpos++; } @@ -878,12 +879,12 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, file->ha_rnd_end(); } - if (thd->is_error()) - DBUG_RETURN(HA_POS_ERROR); - /* Signal we should use orignal column read and write maps */ sort_form->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set); + if (thd->is_error()) + DBUG_RETURN(HA_POS_ERROR); + DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos)); if (error != HA_ERR_END_OF_FILE) { @@ -893,11 +894,15 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, if (indexpos && idx && write_keys(param, fs_info, idx, buffpek_pointers, tempfile)) DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ - const ha_rows retval= - my_b_inited(tempfile) ? - (ha_rows) (my_b_tell(tempfile)/param->rec_length) : idx; + retval= (my_b_inited(tempfile) ? + (ha_rows) (my_b_tell(tempfile)/param->rec_length) : + idx); DBUG_PRINT("info", ("find_all_keys return %llu", (ulonglong) retval)); DBUG_RETURN(retval); + +err: + sort_form->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set); + DBUG_RETURN(HA_POS_ERROR); } /* find_all_keys */ @@ -995,7 +1000,8 @@ Type_handler_string_result::make_sort_key(uchar *to, Item *item, if (maybe_null) *to++= 1; char *tmp_buffer= param->tmp_buffer ? param->tmp_buffer : (char*) to; - String tmp(tmp_buffer, param->sort_length, cs); + String tmp(tmp_buffer, param->tmp_buffer ? param->sort_length : + sort_field->length, cs); String *res= item->str_result(&tmp); if (!res) { diff --git a/sql/filesort_utils.cc b/sql/filesort_utils.cc index 11be9229c1d..b39bb880c15 100644 --- a/sql/filesort_utils.cc +++ b/sql/filesort_utils.cc @@ -105,7 +105,7 @@ uchar **Filesort_buffer::alloc_sort_buffer(uint num_records, DBUG_EXECUTE_IF("alloc_sort_buffer_fail", DBUG_SET("+d,simulate_out_of_memory");); - buff_size= num_records * (record_length + sizeof(uchar*)); + buff_size= ((size_t)num_records) * (record_length + sizeof(uchar*)); set_if_bigger(buff_size, record_length * MERGEBUFF2); if (!m_idx_array.is_null()) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index e2d6bb1bdfe..44ae66c76c8 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2204,38 +2204,19 @@ void ha_partition::update_create_info(HA_CREATE_INFO *create_info) DBUG_ASSERT(sub_elem); part= i * num_subparts + j; DBUG_ASSERT(part < m_file_tot_parts && m_file[part]); - if (ha_legacy_type(m_file[part]->ht) == DB_TYPE_INNODB) - { - dummy_info.data_file_name= dummy_info.index_file_name= NULL; - m_file[part]->update_create_info(&dummy_info); - - if (dummy_info.data_file_name || sub_elem->data_file_name) - { - sub_elem->data_file_name= (char*) dummy_info.data_file_name; - } - if (dummy_info.index_file_name || sub_elem->index_file_name) - { - sub_elem->index_file_name= (char*) dummy_info.index_file_name; - } - } + dummy_info.data_file_name= dummy_info.index_file_name = NULL; + m_file[part]->update_create_info(&dummy_info); + sub_elem->data_file_name = (char*) dummy_info.data_file_name; + sub_elem->index_file_name = (char*) dummy_info.index_file_name; } } else { DBUG_ASSERT(m_file[i]); - if (ha_legacy_type(m_file[i]->ht) == DB_TYPE_INNODB) - { - dummy_info.data_file_name= dummy_info.index_file_name= NULL; - m_file[i]->update_create_info(&dummy_info); - if (dummy_info.data_file_name || part_elem->data_file_name) - { - part_elem->data_file_name= (char*) dummy_info.data_file_name; - } - if (dummy_info.index_file_name || part_elem->index_file_name) - { - part_elem->index_file_name= (char*) dummy_info.index_file_name; - } - } + dummy_info.data_file_name= dummy_info.index_file_name= NULL; + m_file[i]->update_create_info(&dummy_info); + part_elem->data_file_name = (char*) dummy_info.data_file_name; + part_elem->index_file_name = (char*) dummy_info.index_file_name; } } DBUG_VOID_RETURN; @@ -9681,20 +9662,36 @@ uint ha_partition::alter_table_flags(uint flags) bool ha_partition::check_if_incompatible_data(HA_CREATE_INFO *create_info, uint table_changes) { - handler **file; - bool ret= COMPATIBLE_DATA_YES; - /* The check for any partitioning related changes have already been done in mysql_alter_table (by fix_partition_func), so it is only up to the underlying handlers. */ - for (file= m_file; *file; file++) - if ((ret= (*file)->check_if_incompatible_data(create_info, - table_changes)) != - COMPATIBLE_DATA_YES) - break; - return ret; + List_iterator<partition_element> part_it(m_part_info->partitions); + HA_CREATE_INFO dummy_info= *create_info; + uint i=0; + while (partition_element *part_elem= part_it++) + { + if (m_is_sub_partitioned) + { + List_iterator<partition_element> subpart_it(part_elem->subpartitions); + while (partition_element *sub_elem= subpart_it++) + { + dummy_info.data_file_name= sub_elem->data_file_name; + dummy_info.index_file_name= sub_elem->index_file_name; + if (m_file[i++]->check_if_incompatible_data(&dummy_info, table_changes)) + return COMPATIBLE_DATA_NO; + } + } + else + { + dummy_info.data_file_name= part_elem->data_file_name; + dummy_info.index_file_name= part_elem->index_file_name; + if (m_file[i++]->check_if_incompatible_data(&dummy_info, table_changes)) + return COMPATIBLE_DATA_NO; + } + } + return COMPATIBLE_DATA_YES; } diff --git a/sql/item.cc b/sql/item.cc index 805ddb2918f..ddc0813933a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2185,8 +2185,10 @@ bool Item_name_const::fix_fields(THD *thd, Item **ref) String s(buf, sizeof(buf), &my_charset_bin); s.length(0); - if (value_item->fix_fields(thd, &value_item) || - name_item->fix_fields(thd, &name_item) || + if ((!value_item->fixed && + value_item->fix_fields(thd, &value_item)) || + (!name_item->fixed && + name_item->fix_fields(thd, &name_item)) || !value_item->const_item() || !name_item->const_item() || !(item_name= name_item->val_str(&s))) // Can't have a NULL name @@ -5569,7 +5571,8 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && select->having_fix_field && - select_ref != not_found_item && !group_by_ref) + select_ref != not_found_item && !group_by_ref && + !ref->alias_name_used) { /* Report the error if fields was found only in the SELECT item list and diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index dff5fb5df0f..00ee42ac487 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1839,6 +1839,19 @@ bool Item_func_opt_neg::eq(const Item *item, bool binary_cmp) const } +bool Item_func_interval::fix_fields(THD *thd, Item **ref) +{ + if (Item_long_func::fix_fields(thd, ref)) + return true; + for (uint i= 0 ; i < row->cols(); i++) + { + if (row->element_index(i)->check_cols(1)) + return true; + } + return false; +} + + void Item_func_interval::fix_length_and_dec() { uint rows= row->cols(); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 1561a78a12a..8b47f09497f 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -976,6 +976,7 @@ public: Item_func_interval(THD *thd, Item_row *a): Item_long_func(thd, a), row(a), intervals(0) { } + bool fix_fields(THD *, Item **); longlong val_int(); void fix_length_and_dec(); const char *func_name() const { return "interval"; } diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 7afb94ba332..4b2de7cf28b 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -781,10 +781,10 @@ String *Item_func_json_extract::read_json(String *str, { str->set_charset(js->charset()); str->length(0); - } - if (possible_multiple_values && str->append("[", 1)) - goto error; + if (possible_multiple_values && str->append("[", 1)) + goto error; + } json_get_path_start(&je, js->charset(),(const uchar *) js->ptr(), (const uchar *) js->ptr() + js->length(), &p); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index d4abdfc614f..945224c2623 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -4136,7 +4136,7 @@ void Item_func_group_concat::print(String *str, enum_query_type query_type) } } str->append(STRING_WITH_LEN(" separator \'")); - str->append(*separator); + str->append_for_single_quote(separator->ptr(), separator->length()); str->append(STRING_WITH_LEN("\')")); } diff --git a/sql/log.cc b/sql/log.cc index bdf0b6fdc59..6923a6241cd 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2470,7 +2470,7 @@ static int find_uniq_filename(char *name, ulong next_log_number) char buff[FN_REFLEN], ext_buf[FN_REFLEN]; struct st_my_dir *dir_info; reg1 struct fileinfo *file_info; - ulong max_found, next, number; + ulong max_found, next, UNINIT_VAR(number); size_t buf_length, length; char *start, *end; int error= 0; @@ -2993,7 +2993,6 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, mysql_mutex_lock(&LOCK_log); if (is_open()) { // Safety agains reopen - int tmp_errno= 0; char buff[80], *end; char query_time_buff[22+7], lock_time_buff[22+7]; size_t buff_len; @@ -3015,16 +3014,13 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, /* Note that my_b_write() assumes it knows the length for this */ if (my_b_write(&log_file, (uchar*) buff, buff_len)) - tmp_errno= errno; + goto err; } const uchar uh[]= "# User@Host: "; - if (my_b_write(&log_file, uh, sizeof(uh) - 1)) - tmp_errno= errno; - if (my_b_write(&log_file, (uchar*) user_host, user_host_len)) - tmp_errno= errno; - if (my_b_write(&log_file, (uchar*) "\n", 1)) - tmp_errno= errno; - } + if (my_b_write(&log_file, uh, sizeof(uh) - 1) || + my_b_write(&log_file, (uchar*) user_host, user_host_len) || + my_b_write(&log_file, (uchar*) "\n", 1)) + goto err; /* For slow query log */ sprintf(query_time_buff, "%.6f", ulonglong2double(query_utime)/1000000.0); @@ -3039,9 +3035,8 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, (ulong) thd->get_sent_row_count(), (ulong) thd->get_examined_row_count(), (ulong) thd->get_affected_rows(), - (ulong) (thd->status_var.bytes_sent - thd->bytes_sent_old)) - == (size_t) -1) - tmp_errno= errno; + (ulong) (thd->status_var.bytes_sent - thd->bytes_sent_old))) + goto err; if ((thd->variables.log_slow_verbosity & LOG_SLOW_VERBOSITY_QUERY_PLAN) && thd->tmp_tables_used && @@ -3050,13 +3045,13 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, "Tmp_table_sizes: %s\n", (ulong) thd->tmp_tables_used, (ulong) thd->tmp_tables_disk_used, - llstr(thd->tmp_tables_size, llbuff)) == (uint) -1) - tmp_errno= errno; + llstr(thd->tmp_tables_size, llbuff))) + goto err; - if (thd->spcont) - if (my_b_printf(&log_file, "# Stored_routine: %s\n", - ErrConvDQName(thd->spcont->m_sp).ptr()) == (uint) -1) - tmp_errno= errno; + if (thd->spcont && + my_b_printf(&log_file, "# Stored_routine: %s\n", + ErrConvDQName(thd->spcont->m_sp).ptr())) + goto err; if ((thd->variables.log_slow_verbosity & LOG_SLOW_VERBOSITY_QUERY_PLAN) && (thd->query_plan_flags & @@ -3078,21 +3073,22 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, thd->query_plan_fsort_passes, ((thd->query_plan_flags & QPLAN_FILESORT_PRIORITY_QUEUE) ? "Yes" : "No") - ) == (size_t) -1) - tmp_errno= errno; + )) + goto err; if (thd->variables.log_slow_verbosity & LOG_SLOW_VERBOSITY_EXPLAIN && thd->lex->explain) { StringBuffer<128> buf; DBUG_ASSERT(!thd->free_list); if (!print_explain_for_slow_log(thd->lex, thd, &buf)) - my_b_printf(&log_file, "%s", buf.c_ptr_safe()); + if (my_b_printf(&log_file, "%s", buf.c_ptr_safe())) + goto err; thd->free_items(); } if (thd->db && strcmp(thd->db, db)) { // Database changed - if (my_b_printf(&log_file,"use %s;\n",thd->db) == (size_t) -1) - tmp_errno= errno; + if (my_b_printf(&log_file,"use %s;\n",thd->db)) + goto err; strmov(db,thd->db); } if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt) @@ -3128,7 +3124,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, *end='\n'; if (my_b_write(&log_file, (uchar*) "SET ", 4) || my_b_write(&log_file, (uchar*) buff + 1, (uint) (end-buff))) - tmp_errno= errno; + goto err; } if (is_command) { @@ -3137,24 +3133,27 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, DBUG_EXECUTE_IF("simulate_slow_log_write_error", {DBUG_SET("+d,simulate_file_write_error");}); if(my_b_write(&log_file, (uchar*) buff, buff_len)) - tmp_errno= errno; + goto err; } if (my_b_write(&log_file, (uchar*) sql_text, sql_text_len) || my_b_write(&log_file, (uchar*) ";\n",2) || flush_io_cache(&log_file)) - tmp_errno= errno; - if (tmp_errno) - { - error= 1; - if (! write_error) - { - write_error= 1; - sql_print_error(ER_THD(thd, ER_ERROR_ON_WRITE), name, tmp_errno); - } + goto err; + } } +end: mysql_mutex_unlock(&LOCK_log); DBUG_RETURN(error); + +err: + error= 1; + if (! write_error) + { + write_error= 1; + sql_print_error(ER_THD(thd, ER_ERROR_ON_WRITE), name, errno); + } + goto end; } @@ -3650,6 +3649,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name, new_xid_list_entry->binlog_name= name_mem; new_xid_list_entry->binlog_name_len= len; new_xid_list_entry->xid_count= 0; + new_xid_list_entry->notify_count= 0; /* Find the name for the Initial binlog checkpoint. @@ -5006,7 +5006,55 @@ MYSQL_BIN_LOG::is_xidlist_idle_nolock() return true; } +#ifdef WITH_WSREP +inline bool +is_gtid_cached_internal(IO_CACHE *file) +{ + uchar data[EVENT_TYPE_OFFSET+1]; + bool result= false; + my_off_t write_pos= my_b_tell(file); + if (reinit_io_cache(file, READ_CACHE, 0, 0, 0)) + return false; + /* + In the cache we have gtid event if , below condition is true, + */ + my_b_read(file, data, sizeof(data)); + uint event_type= (uchar)data[EVENT_TYPE_OFFSET]; + if (event_type == GTID_LOG_EVENT) + result= true; + /* + Cleanup , Why because we have not read the full buffer + and this will cause next to next reinit_io_cache(called in write_cache) + to make cache empty. + */ + file->read_pos= file->read_end; + if (reinit_io_cache(file, WRITE_CACHE, write_pos, 0, 0)) + return false; + return result; +} +#endif +#ifdef WITH_WSREP +inline bool +MYSQL_BIN_LOG::is_gtid_cached(THD *thd) +{ + binlog_cache_mngr *mngr= (binlog_cache_mngr *) thd_get_ha_data( + thd, binlog_hton); + if (!mngr) + return false; + binlog_cache_data *cache_trans= mngr->get_binlog_cache_data( + use_trans_cache(thd, true)); + binlog_cache_data *cache_stmt= mngr->get_binlog_cache_data( + use_trans_cache(thd, false)); + if (cache_trans && !cache_trans->empty() && + is_gtid_cached_internal(&cache_trans->cache_log)) + return true; + if (cache_stmt && !cache_stmt->empty() && + is_gtid_cached_internal(&cache_stmt->cache_log)) + return true; + return false; +} +#endif /** Create a new log file name. @@ -5611,7 +5659,36 @@ THD::binlog_start_trans_and_stmt() cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF) { this->binlog_set_stmt_begin(); - if (in_multi_stmt_transaction_mode()) + bool mstmt_mode= in_multi_stmt_transaction_mode(); +#ifdef WITH_WSREP + /* Write Gtid + Get domain id only when gtid mode is set + If this event is replicate through a master then , + we will forward the same gtid another nodes + We have to do this only one time in mysql transaction. + Since this function is called multiple times , We will check for + ha_info->is_started() + */ + Ha_trx_info *ha_info; + ha_info= this->ha_data[binlog_hton->slot].ha_info + (mstmt_mode ? 1 : 0); + + if (!ha_info->is_started() && wsrep_gtid_mode + && this->variables.gtid_seq_no) + { + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton); + binlog_cache_data *cache_data= cache_mngr->get_binlog_cache_data(1); + IO_CACHE *file= &cache_data->cache_log; + Log_event_writer writer(file, cache_data); + Gtid_log_event gtid_event(this, this->variables.gtid_seq_no, + this->variables.gtid_domain_id, + true, LOG_EVENT_SUPPRESS_USE_F, + true, 0); + gtid_event.server_id= this->variables.server_id; + writer.write(>id_event); + } +#endif + if (mstmt_mode) trans_register_ha(this, TRUE, binlog_hton); trans_register_ha(this, FALSE, binlog_hton); /* @@ -5891,7 +5968,7 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone, DBUG_PRINT("enter", ("standalone: %d", standalone)); #ifdef WITH_WSREP - if (WSREP(thd) && thd->wsrep_trx_meta.gtid.seqno != -1 && wsrep_gtid_mode) + if (WSREP(thd) && thd->wsrep_trx_meta.gtid.seqno != -1 && wsrep_gtid_mode && !thd->variables.gtid_seq_no) { domain_id= wsrep_gtid_domain_id; } else { @@ -5945,6 +6022,12 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone, /* Write the event to the binary log. */ DBUG_ASSERT(this == &mysql_bin_log); + +#ifdef WITH_WSREP + if (wsrep_gtid_mode && is_gtid_cached(thd)) + DBUG_RETURN(false); +#endif + if (write_event(>id_event)) DBUG_RETURN(true); status_var_add(thd->status_var.binlog_bytes_written, gtid_event.data_written); @@ -9720,9 +9803,20 @@ void TC_LOG_BINLOG::commit_checkpoint_notify(void *cookie) { xid_count_per_binlog *entry= static_cast<xid_count_per_binlog *>(cookie); + bool found_entry= false; mysql_mutex_lock(&LOCK_binlog_background_thread); - entry->next_in_queue= binlog_background_thread_queue; - binlog_background_thread_queue= entry; + /* count the same notification kind from different engines */ + for (xid_count_per_binlog *link= binlog_background_thread_queue; + link && !found_entry; link= link->next_in_queue) + { + if ((found_entry= (entry == link))) + entry->notify_count++; + } + if (!found_entry) + { + entry->next_in_queue= binlog_background_thread_queue; + binlog_background_thread_queue= entry; + } mysql_cond_signal(&COND_binlog_background_thread); mysql_mutex_unlock(&LOCK_binlog_background_thread); } @@ -9817,13 +9911,16 @@ binlog_background_thread(void *arg __attribute__((unused))) ); while (queue) { + long count= queue->notify_count; THD_STAGE_INFO(thd, stage_binlog_processing_checkpoint_notify); DEBUG_SYNC(thd, "binlog_background_thread_before_mark_xid_done"); /* Set the thread start time */ thd->set_time(); /* Grab next pointer first, as mark_xid_done() may free the element. */ next= queue->next_in_queue; - mysql_bin_log.mark_xid_done(queue->binlog_id, true); + queue->notify_count= 0; + for (long i= 0; i <= count; i++) + mysql_bin_log.mark_xid_done(queue->binlog_id, true); queue= next; DBUG_EXECUTE_IF("binlog_background_checkpoint_processed", diff --git a/sql/log.h b/sql/log.h index 02ace7c7921..6305dd97355 100644 --- a/sql/log.h +++ b/sql/log.h @@ -571,7 +571,13 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG bool write_transaction_to_binlog_events(group_commit_entry *entry); void trx_group_commit_leader(group_commit_entry *leader); bool is_xidlist_idle_nolock(); - +#ifdef WITH_WSREP + /* + When this mariadb node is slave and galera enabled. So in this case + we write the gtid in wsrep_run_commit itself. + */ + inline bool is_gtid_cached(THD *thd); +#endif public: /* A list of struct xid_count_per_binlog is used to keep track of how many @@ -591,6 +597,7 @@ public: ulong binlog_id; /* Total prepared XIDs and pending checkpoint requests in this binlog. */ long xid_count; + long notify_count; /* For linking in requests to the binlog background thread. */ xid_count_per_binlog *next_in_queue; xid_count_per_binlog(); /* Give link error if constructor used. */ diff --git a/sql/log_event.cc b/sql/log_event.cc index 7fe00b2bf43..1bf28df876d 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -216,7 +216,7 @@ is_parallel_retry_error(rpl_group_info *rgi, int err) static void inline slave_rows_error_report(enum loglevel level, int ha_error, rpl_group_info *rgi, THD *thd, TABLE *table, const char * type, - const char *log_name, ulong pos) + const char *log_name, my_off_t pos) { const char *handler_error= (ha_error ? HA_ERR(ha_error) : NULL); char buff[MAX_SLAVE_ERRMSG], *slider; @@ -250,14 +250,14 @@ static void inline slave_rows_error_report(enum loglevel level, int ha_error, rli->report(level, errcode, rgi->gtid_info(), "Could not execute %s event on table %s.%s;" "%s handler error %s; " - "the event's master log %s, end_log_pos %lu", + "the event's master log %s, end_log_pos %llu", type, table->s->db.str, table->s->table_name.str, buff, handler_error == NULL ? "<unknown>" : handler_error, log_name, pos); else rli->report(level, errcode, rgi->gtid_info(), "Could not execute %s event on table %s.%s;" - "%s the event's master log %s, end_log_pos %lu", + "%s the event's master log %s, end_log_pos %llu", type, table->s->db.str, table->s->table_name.str, buff, log_name, pos); } @@ -290,10 +290,9 @@ public: flags Flags for the cache DESCRIPTION - - Class used to guarantee copy of cache to file before exiting the - current block. On successful copy of the cache, the cache will - be reinited as a WRITE_CACHE. + Cache common parameters and ensure common flush_data() code + on successful copy of the cache, the cache will be reinited as a + WRITE_CACHE. Currently, a pointer to the cache is provided in the constructor, but it would be possible to create a subclass @@ -305,28 +304,35 @@ public: reinit_io_cache(m_cache, WRITE_CACHE, 0L, FALSE, TRUE); } - ~Write_on_release_cache() + ~Write_on_release_cache() {} + + bool flush_data() { #ifdef MYSQL_CLIENT - if(m_ev == NULL) + if (m_ev == NULL) { - copy_event_cache_to_file_and_reinit(m_cache, m_file); - if (m_flags & FLUSH_F) - fflush(m_file); + if (copy_event_cache_to_file_and_reinit(m_cache, m_file)) + return 1; + if ((m_flags & FLUSH_F) && fflush(m_file)) + return 1; } else // if m_ev<>NULL, then storing the output in output_buf { LEX_STRING tmp_str; + bool res; if (copy_event_cache_to_string_and_reinit(m_cache, &tmp_str)) - exit(1); - m_ev->output_buf.append(&tmp_str); + return 1; + res= m_ev->output_buf.append(&tmp_str) != 0; my_free(tmp_str.str); + return res ? res : 0; } #else /* MySQL_SERVER */ - copy_event_cache_to_file_and_reinit(m_cache, m_file); - if (m_flags & FLUSH_F) - fflush(m_file); + if (copy_event_cache_to_file_and_reinit(m_cache, m_file)) + return 1; + if ((m_flags & FLUSH_F) && fflush(m_file)) + return 1; #endif + return 0; } /* @@ -364,27 +370,36 @@ private: */ #ifdef MYSQL_CLIENT -static void pretty_print_str(IO_CACHE* cache, const char* str, int len) +static bool pretty_print_str(IO_CACHE* cache, const char* str, int len) { const char* end = str + len; - my_b_write_byte(cache, '\''); + if (my_b_write_byte(cache, '\'')) + goto err; + while (str < end) { char c; + int error; + switch ((c=*str++)) { - case '\n': my_b_write(cache, (uchar*)"\\n", 2); break; - case '\r': my_b_write(cache, (uchar*)"\\r", 2); break; - case '\\': my_b_write(cache, (uchar*)"\\\\", 2); break; - case '\b': my_b_write(cache, (uchar*)"\\b", 2); break; - case '\t': my_b_write(cache, (uchar*)"\\t", 2); break; - case '\'': my_b_write(cache, (uchar*)"\\'", 2); break; - case 0 : my_b_write(cache, (uchar*)"\\0", 2); break; + case '\n': error= my_b_write(cache, (uchar*)"\\n", 2); break; + case '\r': error= my_b_write(cache, (uchar*)"\\r", 2); break; + case '\\': error= my_b_write(cache, (uchar*)"\\\\", 2); break; + case '\b': error= my_b_write(cache, (uchar*)"\\b", 2); break; + case '\t': error= my_b_write(cache, (uchar*)"\\t", 2); break; + case '\'': error= my_b_write(cache, (uchar*)"\\'", 2); break; + case 0 : error= my_b_write(cache, (uchar*)"\\0", 2); break; default: - my_b_write_byte(cache, c); + error= my_b_write_byte(cache, c); break; } + if (error) + goto err; } - my_b_write_byte(cache, '\''); + return my_b_write_byte(cache, '\''); + +err: + return 1; } #endif /* MYSQL_CLIENT */ @@ -1144,19 +1159,25 @@ int append_query_string(CHARSET_INFO *csinfo, String *to, #ifdef MYSQL_CLIENT -static void print_set_option(IO_CACHE* file, uint32 bits_changed, +static bool print_set_option(IO_CACHE* file, uint32 bits_changed, uint32 option, uint32 flags, const char* name, bool* need_comma) { if (bits_changed & option) { if (*need_comma) - my_b_write(file, (uchar*)", ", 2); - my_b_printf(file, "%s=%d", name, MY_TEST(flags & option)); + if (my_b_write(file, (uchar*)", ", 2)) + goto err; + if (my_b_printf(file, "%s=%d", name, MY_TEST(flags & option))) + goto err; *need_comma= 1; } + return 0; +err: + return 1; } #endif + /************************************************************************** Log_event methods (= the parent class of all events) **************************************************************************/ @@ -1327,7 +1348,7 @@ Log_event::Log_event(const char* buf, */ log_pos+= data_written; /* purecov: inspected */ } - DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos)); + DBUG_PRINT("info", ("log_pos: %llu", log_pos)); flags= uint2korr(buf + FLAGS_OFFSET); if (((uchar)buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT) || @@ -1456,7 +1477,7 @@ void Log_event::init_show_field_list(THD *thd, List<Item>* field_list) mem_root); field_list->push_back(new (mem_root) Item_return_int(thd, "Pos", - MY_INT32_NUM_DECIMAL_DIGITS, + MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG), mem_root); field_list->push_back(new (mem_root) @@ -1468,7 +1489,7 @@ void Log_event::init_show_field_list(THD *thd, List<Item>* field_list) mem_root); field_list->push_back(new (mem_root) Item_return_int(thd, "End_log_pos", - MY_INT32_NUM_DECIMAL_DIGITS, + MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG), mem_root); field_list->push_back(new (mem_root) Item_empty_string(thd, "Info", 20), @@ -2241,7 +2262,7 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, #ifdef MYSQL_CLIENT -static void hexdump_minimal_header_to_io_cache(IO_CACHE *file, +static bool hexdump_minimal_header_to_io_cache(IO_CACHE *file, my_off_t offset, uchar *ptr) { @@ -2254,15 +2275,18 @@ static void hexdump_minimal_header_to_io_cache(IO_CACHE *file, more headers (which must be printed by other methods, if desired). */ char emit_buf[120]; // Enough for storing one line - my_b_printf(file, - "# " - "|Timestamp " - "|Type " - "|Master ID " - "|Size " - "|Master Pos " - "|Flags\n"); - size_t const emit_buf_written= + size_t emit_buf_written; + + if (my_b_printf(file, + "# " + "|Timestamp " + "|Type " + "|Master ID " + "|Size " + "|Master Pos " + "|Flags\n")) + goto err; + emit_buf_written= my_snprintf(emit_buf, sizeof(emit_buf), "# %8llx " /* Position */ "|%02x %02x %02x %02x " /* Timestamp */ @@ -2280,8 +2304,13 @@ static void hexdump_minimal_header_to_io_cache(IO_CACHE *file, ptr[17], ptr[18]); /* Flags */ DBUG_ASSERT(static_cast<size_t>(emit_buf_written) < sizeof(emit_buf)); - my_b_write(file, reinterpret_cast<uchar*>(emit_buf), emit_buf_written); - my_b_write(file, (uchar*)"#\n", 2); + if (my_b_write(file, reinterpret_cast<uchar*>(emit_buf), emit_buf_written) || + my_b_write(file, (uchar*)"#\n", 2)) + goto err; + + return 0; +err: + return 1; } @@ -2306,7 +2335,7 @@ static void format_hex_line(char *emit_buff) HEXDUMP_BYTES_PER_LINE + 2]= '\0'; } -static void hexdump_data_to_io_cache(IO_CACHE *file, +static bool hexdump_data_to_io_cache(IO_CACHE *file, my_off_t offset, uchar *ptr, my_off_t size) @@ -2328,7 +2357,7 @@ static void hexdump_data_to_io_cache(IO_CACHE *file, my_off_t i; if (size == 0) - return; + return 0; // ok, nothing to do format_hex_line(emit_buffer); /* @@ -2358,8 +2387,9 @@ static void hexdump_data_to_io_cache(IO_CACHE *file, (ulonglong) starting_offset); /* remove \0 left after printing address */ emit_buffer[2 + emit_buf_written]= ' '; - my_b_write(file, reinterpret_cast<uchar*>(emit_buffer), - sizeof(emit_buffer) - 1); + if (my_b_write(file, reinterpret_cast<uchar*>(emit_buffer), + sizeof(emit_buffer) - 1)) + goto err; c= emit_buffer + 2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2; h= emit_buffer + 2 + 8 + 2; format_hex_line(emit_buffer); @@ -2394,17 +2424,23 @@ static void hexdump_data_to_io_cache(IO_CACHE *file, /* pad unprinted area */ memset(h, ' ', (HEXDUMP_BYTES_PER_LINE * 3 + 1) - (h - (emit_buffer + 2 + 8 + 2))); - my_b_write(file, reinterpret_cast<uchar*>(emit_buffer), - c - emit_buffer); + if (my_b_write(file, reinterpret_cast<uchar*>(emit_buffer), + c - emit_buffer)) + goto err; } - my_b_write(file, (uchar*)"#\n", 2); + if (my_b_write(file, (uchar*)"#\n", 2)) + goto err; + + return 0; +err: + return 1; } /* Log_event::print_header() */ -void Log_event::print_header(IO_CACHE* file, +bool Log_event::print_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info, bool is_more __attribute__((unused))) { @@ -2412,10 +2448,11 @@ void Log_event::print_header(IO_CACHE* file, my_off_t hexdump_from= print_event_info->hexdump_from; DBUG_ENTER("Log_event::print_header"); - my_b_write_byte(file, '#'); - print_timestamp(file); - my_b_printf(file, " server id %lu end_log_pos %s ", (ulong) server_id, - llstr(log_pos,llbuff)); + if (my_b_write_byte(file, '#') || + print_timestamp(file) || + my_b_printf(file, " server id %lu end_log_pos %s ", (ulong) server_id, + llstr(log_pos,llbuff))) + goto err; /* print the checksum */ @@ -2425,8 +2462,10 @@ void Log_event::print_header(IO_CACHE* file, char checksum_buf[BINLOG_CHECKSUM_LEN * 2 + 4]; // to fit to "%p " size_t const bytes_written= my_snprintf(checksum_buf, sizeof(checksum_buf), "0x%08x ", crc); - my_b_printf(file, "%s ", get_type(&binlog_checksum_typelib, checksum_alg)); - my_b_printf(file, checksum_buf, bytes_written); + if (my_b_printf(file, "%s ", get_type(&binlog_checksum_typelib, + checksum_alg)) || + my_b_printf(file, checksum_buf, bytes_written)) + goto err; } /* mysqlbinlog --hexdump */ @@ -2439,24 +2478,32 @@ void Log_event::print_header(IO_CACHE* file, size-= hdr_len; - my_b_printf(file, "# Position\n"); + if (my_b_printf(file, "# Position\n")) + goto err; /* Write the header, nicely formatted by field. */ - hexdump_minimal_header_to_io_cache(file, hexdump_from, ptr); + if (hexdump_minimal_header_to_io_cache(file, hexdump_from, ptr)) + goto err; ptr+= hdr_len; hexdump_from+= hdr_len; /* Print the rest of the data, mimicking "hexdump -C" output. */ - hexdump_data_to_io_cache(file, hexdump_from, ptr, size); + if (hexdump_data_to_io_cache(file, hexdump_from, ptr, size)) + goto err; /* Prefix the next line so that the output from print_helper() will appear as a comment. */ - my_b_write(file, (uchar*)"# Event: ", 9); + if (my_b_write(file, (uchar*)"# Event: ", 9)) + goto err; } - DBUG_VOID_RETURN; + + DBUG_RETURN(0); + +err: + DBUG_RETURN(1); } @@ -2464,7 +2511,7 @@ void Log_event::print_header(IO_CACHE* file, Prints a quoted string to io cache. Control characters are displayed as hex sequence, e.g. \x00 Single-quote and backslash characters are escaped with a \ - + @param[in] file IO cache @param[in] prt Pointer to string @param[in] length String length @@ -2551,12 +2598,14 @@ my_b_write_quoted_with_length(IO_CACHE *file, const uchar *ptr, uint length) @param[in] sl Signed number @param[in] ul Unsigned number */ -static void +static bool my_b_write_sint32_and_uint32(IO_CACHE *file, int32 si, uint32 ui) { - my_b_printf(file, "%d", si); + bool res= my_b_printf(file, "%d", si); if (si < 0) - my_b_printf(file, " (%u)", ui); + if (my_b_printf(file, " (%u)", ui)) + res= 1; + return res; } @@ -2575,8 +2624,8 @@ my_b_write_sint32_and_uint32(IO_CACHE *file, int32 si, uint32 ui) */ static size_t -log_event_print_value(IO_CACHE *file, const uchar *ptr, - uint type, uint meta, +log_event_print_value(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info, + const uchar *ptr, uint type, uint meta, char *typestr, size_t typestr_length) { uint32 length= 0; @@ -2959,19 +3008,15 @@ log_event_print_value(IO_CACHE *file, const uchar *ptr, return my_b_write_quoted_with_length(file, ptr, length); case MYSQL_TYPE_DECIMAL: - my_b_printf(file, - "!! Old DECIMAL (mysql-4.1 or earlier). " - "Not enough metadata to display the value. "); + print_event_info->flush_for_error(); + fprintf(stderr, "\nError: Found Old DECIMAL (mysql-4.1 or earlier). " + "Not enough metadata to display the value.\n"); break; - default: - { - char tmp[5]; - my_snprintf(tmp, sizeof(tmp), "%04x", meta); - my_b_printf(file, - "!! Don't know how to handle column type=%d meta=%d (%s)", - type, meta, tmp); - } + print_event_info->flush_for_error(); + fprintf(stderr, + "\nError: Don't know how to handle column type: %d meta: %d (%04x)\n", + type, meta, meta); break; } *typestr= 0; @@ -2992,7 +3037,8 @@ return_null: @param[in] value Pointer to packed row @param[in] prefix Row's SQL clause ("SET", "WHERE", etc) - @retval - number of bytes scanned. + @retval 0 error + # number of bytes scanned. */ @@ -3022,7 +3068,8 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, value+= (bitmap_bits_set(cols_bitmap) + 7) / 8; if (!no_fill_output) - my_b_printf(file, "%s", prefix); + if (my_b_printf(file, "%s", prefix)) + goto err; for (size_t i= 0; i < td->size(); i ++) { @@ -3034,7 +3081,8 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, continue; if (!no_fill_output) - my_b_printf(file, "### @%d=", static_cast<int>(i + 1)); + if (my_b_printf(file, "### @%d=", static_cast<int>(i + 1))) + goto err; if (!is_null) { @@ -3042,8 +3090,9 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, if (value + fsize > m_rows_end) { if (!no_fill_output) - my_b_printf(file, "***Corrupted replication event was detected." - " Not printing the value***\n"); + if (my_b_printf(file, "***Corrupted replication event was detected." + " Not printing the value***\n")) + goto err; value+= fsize; return 0; } @@ -3051,7 +3100,7 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, if (!no_fill_output) { - size= log_event_print_value(file,is_null? NULL: value, + size= log_event_print_value(file, print_event_info, is_null? NULL: value, td->type(i), td->field_metadata(i), typestr, sizeof(typestr)); #ifdef WHEN_FLASHBACK_REVIEW_READY @@ -3062,12 +3111,14 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, // Using a tmp IO_CACHE to get the value output open_cached_file(&tmp_cache, NULL, NULL, 0, MYF(MY_WME | MY_NABP)); - size= log_event_print_value(&tmp_cache, is_null? NULL: value, + size= log_event_print_value(&tmp_cache, print_event_info, + is_null ? NULL: value, td->type(i), td->field_metadata(i), typestr, sizeof(typestr)); - if (copy_event_cache_to_string_and_reinit(&tmp_cache, &review_str)) - exit(1); + error= copy_event_cache_to_string_and_reinit(&tmp_cache, &review_str); close_cached_file(&tmp_cache); + if (error) + return 0; switch (td->type(i)) // Converting a string to HEX format { @@ -3085,12 +3136,14 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, exit(1); } octet2hex((char*) hex_str.ptr(), tmp_str.ptr(), tmp_str.length()); - my_b_printf(review_sql, ", UNHEX('%s')", hex_str.ptr()); + if (my_b_printf(review_sql, ", UNHEX('%s')", hex_str.ptr())) + goto err; break; default: tmp_str.free(); - tmp_str.append(review_str.str, review_str.length); - my_b_printf(review_sql, ", %s", tmp_str.ptr()); + if (tmp_str.append(review_str.str, review_str.length) || + my_b_printf(review_sql, ", %s", tmp_str.ptr())) + goto err; break; } my_free(revieww_str.str); @@ -3101,36 +3154,40 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, { IO_CACHE tmp_cache; open_cached_file(&tmp_cache, NULL, NULL, 0, MYF(MY_WME | MY_NABP)); - size= log_event_print_value(&tmp_cache,is_null? NULL: value, + size= log_event_print_value(&tmp_cache, print_event_info, + is_null ? NULL: value, td->type(i), td->field_metadata(i), typestr, sizeof(typestr)); close_cached_file(&tmp_cache); } if (!size) - return 0; + goto err; if (!is_null) value+= size; if (print_event_info->verbose > 1 && !no_fill_output) { - my_b_write(file, (uchar*)" /* ", 4); - - my_b_printf(file, "%s ", typestr); - - my_b_printf(file, "meta=%d nullable=%d is_null=%d ", - td->field_metadata(i), - td->maybe_null(i), is_null); - my_b_write(file, (uchar*)"*/", 2); + if (my_b_write(file, (uchar*)" /* ", 4) || + my_b_printf(file, "%s ", typestr) || + my_b_printf(file, "meta=%d nullable=%d is_null=%d ", + td->field_metadata(i), + td->maybe_null(i), is_null) || + my_b_write(file, (uchar*)"*/", 2)) + goto err; } if (!no_fill_output) - my_b_write_byte(file, '\n'); + if (my_b_write_byte(file, '\n')) + goto err; null_bit_index++; } return value - value0; + +err: + return 0; } @@ -3169,10 +3226,10 @@ void Rows_log_event::change_to_flashback_event(PRINT_EVENT_INFO *print_event_inf if (!(length1= print_verbose_one_row(NULL, td, print_event_info, &m_cols, value, (const uchar*) "", TRUE))) - { - fprintf(stderr, "\nError row length: %zu\n", length1); - exit(1); - } + { + fprintf(stderr, "\nError row length: %zu\n", length1); + exit(1); + } value+= length1; swap_buff1= (uchar *) my_malloc(length1, MYF(0)); @@ -3251,18 +3308,230 @@ end: delete td; } +/** + Calc length of a packed value of the given SQL type + + @param[in] ptr Pointer to string + @param[in] type Column type + @param[in] meta Column meta information + + @retval - number of bytes scanned from ptr. + Except in case of NULL, in which case we return 1 to indicate ok +*/ + +static size_t calc_field_event_length(const uchar *ptr, uint type, uint meta) +{ + uint32 length= 0; + + if (type == MYSQL_TYPE_STRING) + { + if (meta >= 256) + { + uint byte0= meta >> 8; + uint byte1= meta & 0xFF; + + if ((byte0 & 0x30) != 0x30) + { + /* a long CHAR() field: see #37426 */ + length= byte1 | (((byte0 & 0x30) ^ 0x30) << 4); + type= byte0 | 0x30; + } + else + length = meta & 0xFF; + } + else + length= meta; + } + + switch (type) { + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_TIMESTAMP: + return 4; + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_YEAR: + return 1; + case MYSQL_TYPE_SHORT: + return 2; + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_NEWDATE: + case MYSQL_TYPE_DATE: + return 3; + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_DATETIME: + return 8; + case MYSQL_TYPE_NEWDECIMAL: + { + uint precision= meta >> 8; + uint decimals= meta & 0xFF; + uint bin_size= my_decimal_get_binary_size(precision, decimals); + return bin_size; + } + case MYSQL_TYPE_FLOAT: + return 4; + case MYSQL_TYPE_DOUBLE: + return 8; + case MYSQL_TYPE_BIT: + { + /* Meta-data: bit_len, bytes_in_rec, 2 bytes */ + uint nbits= ((meta >> 8) * 8) + (meta & 0xFF); + length= (nbits + 7) / 8; + return length; + } + case MYSQL_TYPE_TIMESTAMP2: + return my_timestamp_binary_length(meta); + case MYSQL_TYPE_DATETIME2: + return my_datetime_binary_length(meta); + case MYSQL_TYPE_TIME2: + return my_time_binary_length(meta); + case MYSQL_TYPE_ENUM: + switch (meta & 0xFF) { + case 1: + case 2: + return (meta & 0xFF); + default: + /* Unknown ENUM packlen=%d", meta & 0xFF */ + return 0; + } + break; + case MYSQL_TYPE_SET: + return meta & 0xFF; + case MYSQL_TYPE_BLOB: + return (meta <= 4 ? meta : 0); + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_VAR_STRING: + length= meta; + /* fall through */ + case MYSQL_TYPE_STRING: + if (length < 256) + return (uint) *ptr + 1; + return uint2korr(ptr) + 2; + case MYSQL_TYPE_DECIMAL: + break; + default: + break; + } + return 0; +} + + +size_t +Rows_log_event::calc_row_event_length(table_def *td, + PRINT_EVENT_INFO *print_event_info, + MY_BITMAP *cols_bitmap, + const uchar *value) +{ + const uchar *value0= value; + const uchar *null_bits= value; + uint null_bit_index= 0; + + /* + Skip metadata bytes which gives the information about nullabity of master + columns. Master writes one bit for each affected column. + */ + + value+= (bitmap_bits_set(cols_bitmap) + 7) / 8; + + for (size_t i= 0; i < td->size(); i ++) + { + int is_null; + is_null= (null_bits[null_bit_index / 8] >> (null_bit_index % 8)) & 0x01; + + if (bitmap_is_set(cols_bitmap, i) == 0) + continue; + + if (!is_null) + { + size_t size; + size_t fsize= td->calc_field_size((uint)i, (uchar*) value); + if (value + fsize > m_rows_end) + { + /* Corrupted replication event was detected, skipping entry */ + return 0; + } + if (!(size= calc_field_event_length(value, td->type(i), + td->field_metadata(i)))) + return 0; + value+= size; + } + null_bit_index++; + } + return value - value0; +} + + +/** + Calculate how many rows there are in the event + + @param[in] file IO cache + @param[in] print_event_into Print parameters +*/ + +void Rows_log_event::count_row_events(PRINT_EVENT_INFO *print_event_info) +{ + Table_map_log_event *map; + table_def *td; + uint row_events; + Log_event_type general_type_code= get_general_type_code(); + + switch (general_type_code) { + case WRITE_ROWS_EVENT: + case DELETE_ROWS_EVENT: + row_events= 1; + break; + case UPDATE_ROWS_EVENT: + row_events= 2; + break; + default: + DBUG_ASSERT(0); /* Not possible */ + return; + } + + if (!(map= print_event_info->m_table_map.get_table(m_table_id)) || + !(td= map->create_table_def())) + { + /* Row event for unknown table */ + return; + } + + for (const uchar *value= m_rows_buf; value < m_rows_end; ) + { + size_t length; + print_event_info->row_events++; + + /* Print the first image */ + if (!(length= calc_row_event_length(td, print_event_info, + &m_cols, value))) + break; + value+= length; + DBUG_ASSERT(value <= m_rows_end); + + /* Print the second image (for UPDATE only) */ + if (row_events == 2) + { + if (!(length= calc_row_event_length(td, print_event_info, + &m_cols_ai, value))) + break; + value+= length; + DBUG_ASSERT(value <= m_rows_end); + } + } + delete td; +} + /** Print a row event into IO cache in human readable form (in SQL format) - + @param[in] file IO cache @param[in] print_event_into Print parameters */ -void Rows_log_event::print_verbose(IO_CACHE *file, + +bool Rows_log_event::print_verbose(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info) { Table_map_log_event *map; - table_def *td; + table_def *td= 0; const char *sql_command, *sql_clause1, *sql_clause2; const char *sql_command_short __attribute__((unused)); Log_event_type general_type_code= get_general_type_code(); @@ -3276,9 +3545,10 @@ void Rows_log_event::print_verbose(IO_CACHE *file, uint8 extra_payload_len= extra_data_len - EXTRA_ROW_INFO_HDR_BYTES; assert(extra_data_len >= EXTRA_ROW_INFO_HDR_BYTES); - my_b_printf(file, "### Extra row data format: %u, len: %u :", - m_extra_row_data[EXTRA_ROW_INFO_FORMAT_OFFSET], - extra_payload_len); + if (my_b_printf(file, "### Extra row data format: %u, len: %u :", + m_extra_row_data[EXTRA_ROW_INFO_FORMAT_OFFSET], + extra_payload_len)) + goto err; if (extra_payload_len) { /* @@ -3289,9 +3559,11 @@ void Rows_log_event::print_verbose(IO_CACHE *file, char buff[buff_len]; str_to_hex(buff, (const char*) &m_extra_row_data[EXTRA_ROW_INFO_HDR_BYTES], extra_payload_len); - my_b_printf(file, "%s", buff); + if (my_b_printf(file, "%s", buff)) + goto err; } - my_b_printf(file, "\n"); + if (my_b_printf(file, "\n")) + goto err; } switch (general_type_code) { @@ -3318,41 +3590,45 @@ void Rows_log_event::print_verbose(IO_CACHE *file, sql_command_short= ""; DBUG_ASSERT(0); /* Not possible */ } - + if (!(map= print_event_info->m_table_map.get_table(m_table_id)) || !(td= map->create_table_def())) { - my_b_printf(file, "### Row event for unknown table #%lu", - (ulong) m_table_id); - return; + return (my_b_printf(file, "### Row event for unknown table #%lu", + (ulong) m_table_id)); } /* If the write rows event contained no values for the AI */ if (((general_type_code == WRITE_ROWS_EVENT) && (m_rows_buf==m_rows_end))) { - my_b_printf(file, "### INSERT INTO %`s.%`s VALUES ()\n", - map->get_db_name(), map->get_table_name()); + if (my_b_printf(file, "### INSERT INTO %`s.%`s VALUES ()\n", + map->get_db_name(), map->get_table_name())) + goto err; goto end; } for (const uchar *value= m_rows_buf; value < m_rows_end; ) { size_t length; - my_b_printf(file, "### %s %`s.%`s\n", - sql_command, - map->get_db_name(), map->get_table_name()); + print_event_info->row_events++; + if (my_b_printf(file, "### %s %`s.%`s\n", + sql_command, + map->get_db_name(), map->get_table_name())) + goto err; #ifdef WHEN_FLASHBACK_REVIEW_READY if (need_flashback_review) - my_b_printf(review_sql, "\nINSERT INTO `%s`.`%s` VALUES ('%s'", - map->get_review_dbname(), map->get_review_tablename(), sql_command_short); + if (my_b_printf(review_sql, "\nINSERT INTO `%s`.`%s` VALUES ('%s'", + map->get_review_dbname(), map->get_review_tablename(), + sql_command_short)) + goto err; #endif /* Print the first image */ if (!(length= print_verbose_one_row(file, td, print_event_info, &m_cols, value, (const uchar*) sql_clause1))) - goto end; + goto err; value+= length; /* Print the second image (for UPDATE only) */ @@ -3361,7 +3637,7 @@ void Rows_log_event::print_verbose(IO_CACHE *file, if (!(length= print_verbose_one_row(file, td, print_event_info, &m_cols_ai, value, (const uchar*) sql_clause2))) - goto end; + goto err; value+= length; } #ifdef WHEN_FLASHBACK_REVIEW_READY @@ -3369,16 +3645,22 @@ void Rows_log_event::print_verbose(IO_CACHE *file, { if (need_flashback_review) for (size_t i= 0; i < td->size(); i ++) - my_b_printf(review_sql, ", NULL"); + if (my_b_printf(review_sql, ", NULL")) + goto err; } if (need_flashback_review) - my_b_printf(review_sql, ")%s\n", print_event_info->delimiter); + if (my_b_printf(review_sql, ")%s\n", print_event_info->delimiter)) + goto err; #endif } end: delete td; + return 0; +err: + delete td; + return 1; } void free_table_map_log_event(Table_map_log_event *event) @@ -3386,7 +3668,7 @@ void free_table_map_log_event(Table_map_log_event *event) delete event; } -void Log_event::print_base64(IO_CACHE* file, +bool Log_event::print_base64(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info, bool more) { @@ -3394,14 +3676,6 @@ void Log_event::print_base64(IO_CACHE* file, uint32 size= uint4korr(ptr + EVENT_LEN_OFFSET); DBUG_ENTER("Log_event::print_base64"); - size_t const tmp_str_sz= my_base64_needed_encoded_length((int) size); - char *const tmp_str= (char *) my_malloc(tmp_str_sz, MYF(MY_WME)); - if (!tmp_str) { - fprintf(stderr, "\nError: Out of memory. " - "Could not print correct binlog event.\n"); - DBUG_VOID_RETURN; - } - if (is_flashback) { uint tmp_size= size; @@ -3447,27 +3721,41 @@ void Log_event::print_base64(IO_CACHE* file, delete ev; } - if (my_base64_encode(ptr, (size_t) size, tmp_str)) + if (print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER && + print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS && + ! print_event_info->short_form) { - DBUG_ASSERT(0); - } - - if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS) - { - if (my_b_tell(file) == 0) - my_b_write_string(file, "\nBINLOG '\n"); + size_t const tmp_str_sz= my_base64_needed_encoded_length((int) size); + bool error= 0; + char *tmp_str; + if (!(tmp_str= (char *) my_malloc(tmp_str_sz, MYF(MY_WME)))) + goto err; - my_b_printf(file, "%s\n", tmp_str); + if (my_base64_encode(ptr, (size_t) size, tmp_str)) + { + DBUG_ASSERT(0); + } - if (!more) - my_b_printf(file, "'%s\n", print_event_info->delimiter); + if (my_b_tell(file) == 0) + if (my_b_write_string(file, "\nBINLOG '\n")) + error= 1; + if (!error && my_b_printf(file, "%s\n", tmp_str)) + error= 1; + if (!more && !error) + if (my_b_printf(file, "'%s\n", print_event_info->delimiter)) + error= 1; + my_free(tmp_str); + if (error) + goto err; } #ifdef WHEN_FLASHBACK_REVIEW_READY - if (print_event_info->verbose || need_flashback_review) + if (print_event_info->verbose || print_event_info->print_row_count || + need_flashback_review) #else // Flashback need the table_map to parse the event - if (print_event_info->verbose || is_flashback) + if (print_event_info->verbose || print_event_info->print_row_count || + is_flashback) #endif { Rows_log_event *ev= NULL; @@ -3542,27 +3830,49 @@ void Log_event::print_base64(IO_CACHE* file, if (ev) { + bool error= 0; + #ifdef WHEN_FLASHBACK_REVIEW_READY ev->need_flashback_review= need_flashback_review; if (print_event_info->verbose) - ev->print_verbose(file, print_event_info); + { + if (ev->print_verbose(file, print_event_info)) + goto err; + } else { IO_CACHE tmp_cache; - open_cached_file(&tmp_cache, NULL, NULL, 0, MYF(MY_WME | MY_NABP)); - ev->print_verbose(&tmp_cache, print_event_info); + + if (open_cached_file(&tmp_cache, NULL, NULL, 0, + MYF(MY_WME | MY_NABP))) + { + delete ev; + goto err; + } + + error= ev->print_verbose(&tmp_cache, print_event_info); close_cached_file(&tmp_cache); + if (error) + { + delete ev; + goto err; + } } #else if (print_event_info->verbose) - ev->print_verbose(file, print_event_info); + error= ev->print_verbose(file, print_event_info); + else + ev->count_row_events(print_event_info); #endif delete ev; + if (error) + goto err; } } + DBUG_RETURN(0); - my_free(tmp_str); - DBUG_VOID_RETURN; +err: + DBUG_RETURN(1); } @@ -3570,7 +3880,7 @@ void Log_event::print_base64(IO_CACHE* file, Log_event::print_timestamp() */ -void Log_event::print_timestamp(IO_CACHE* file, time_t* ts) +bool Log_event::print_timestamp(IO_CACHE* file, time_t* ts) { struct tm *res; time_t my_when= when; @@ -3579,14 +3889,13 @@ void Log_event::print_timestamp(IO_CACHE* file, time_t* ts) ts = &my_when; res=localtime(ts); - my_b_printf(file,"%02d%02d%02d %2d:%02d:%02d", - res->tm_year % 100, - res->tm_mon+1, - res->tm_mday, - res->tm_hour, - res->tm_min, - res->tm_sec); - DBUG_VOID_RETURN; + DBUG_RETURN(my_b_printf(file,"%02d%02d%02d %2d:%02d:%02d", + res->tm_year % 100, + res->tm_mon+1, + res->tm_mday, + res->tm_hour, + res->tm_min, + res->tm_sec)); } #endif /* MYSQL_CLIENT */ @@ -4745,7 +5054,7 @@ Query_log_event::begin_event(String *packet, ulong ev_offset, @todo print the catalog ?? */ -void Query_log_event::print_query_header(IO_CACHE* file, +bool Query_log_event::print_query_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info) { // TODO: print the catalog ?? @@ -4755,10 +5064,12 @@ void Query_log_event::print_query_header(IO_CACHE* file, if (!print_event_info->short_form) { - print_header(file, print_event_info, FALSE); - my_b_printf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d\n", - get_type_str(), (ulong) thread_id, (ulong) exec_time, - error_code); + if (print_header(file, print_event_info, FALSE) || + my_b_printf(file, + "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d\n", + get_type_str(), (ulong) thread_id, (ulong) exec_time, + error_code)) + goto err; } if ((flags & LOG_EVENT_SUPPRESS_USE_F)) @@ -4772,7 +5083,8 @@ void Query_log_event::print_query_header(IO_CACHE* file, if (different_db) memcpy(print_event_info->db, db, db_len + 1); if (db[0] && different_db) - my_b_printf(file, "use %`s%s\n", db, print_event_info->delimiter); + if (my_b_printf(file, "use %`s%s\n", db, print_event_info->delimiter)) + goto err; } end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10); @@ -4783,15 +5095,17 @@ void Query_log_event::print_query_header(IO_CACHE* file, } end= strmov(end, print_event_info->delimiter); *end++='\n'; - my_b_write(file, (uchar*) buff, (uint) (end-buff)); + if (my_b_write(file, (uchar*) buff, (uint) (end-buff))) + goto err; if ((!print_event_info->thread_id_printed || ((flags & LOG_EVENT_THREAD_SPECIFIC_F) && thread_id != print_event_info->thread_id))) { // If --short-form, print deterministic value instead of pseudo_thread_id. - my_b_printf(file,"SET @@session.pseudo_thread_id=%lu%s\n", - short_form ? 999999999 : (ulong)thread_id, - print_event_info->delimiter); + if (my_b_printf(file,"SET @@session.pseudo_thread_id=%lu%s\n", + short_form ? 999999999 : (ulong)thread_id, + print_event_info->delimiter)) + goto err; print_event_info->thread_id= thread_id; print_event_info->thread_id_printed= 1; } @@ -4816,18 +5130,20 @@ void Query_log_event::print_query_header(IO_CACHE* file, if (unlikely(tmp)) /* some bits have changed */ { bool need_comma= 0; - my_b_write_string(file, "SET "); - print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2, - "@@session.foreign_key_checks", &need_comma); - print_set_option(file, tmp, OPTION_AUTO_IS_NULL, flags2, - "@@session.sql_auto_is_null", &need_comma); - print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2, - "@@session.unique_checks", &need_comma); - print_set_option(file, tmp, OPTION_NOT_AUTOCOMMIT, ~flags2, - "@@session.autocommit", &need_comma); - print_set_option(file, tmp, OPTION_NO_CHECK_CONSTRAINT_CHECKS, ~flags2, - "@@session.check_constraint_checks", &need_comma); - my_b_printf(file,"%s\n", print_event_info->delimiter); + if (my_b_write_string(file, "SET ") || + print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2, + "@@session.foreign_key_checks", &need_comma)|| + print_set_option(file, tmp, OPTION_AUTO_IS_NULL, flags2, + "@@session.sql_auto_is_null", &need_comma) || + print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2, + "@@session.unique_checks", &need_comma) || + print_set_option(file, tmp, OPTION_NOT_AUTOCOMMIT, ~flags2, + "@@session.autocommit", &need_comma) || + print_set_option(file, tmp, OPTION_NO_CHECK_CONSTRAINT_CHECKS, + ~flags2, + "@@session.check_constraint_checks", &need_comma) || + my_b_printf(file,"%s\n", print_event_info->delimiter)) + goto err; print_event_info->flags2= flags2; } } @@ -4850,17 +5166,19 @@ void Query_log_event::print_query_header(IO_CACHE* file, !print_event_info->sql_mode_inited))) { char llbuff[22]; - my_b_printf(file,"SET @@session.sql_mode=%s%s\n", - ullstr(sql_mode, llbuff), print_event_info->delimiter); + if (my_b_printf(file,"SET @@session.sql_mode=%s%s\n", + ullstr(sql_mode, llbuff), print_event_info->delimiter)) + goto err; print_event_info->sql_mode= sql_mode; print_event_info->sql_mode_inited= 1; } if (print_event_info->auto_increment_increment != auto_increment_increment || print_event_info->auto_increment_offset != auto_increment_offset) { - my_b_printf(file,"SET @@session.auto_increment_increment=%lu, @@session.auto_increment_offset=%lu%s\n", - auto_increment_increment,auto_increment_offset, - print_event_info->delimiter); + if (my_b_printf(file,"SET @@session.auto_increment_increment=%lu, @@session.auto_increment_offset=%lu%s\n", + auto_increment_increment,auto_increment_offset, + print_event_info->delimiter)) + goto err; print_event_info->auto_increment_increment= auto_increment_increment; print_event_info->auto_increment_offset= auto_increment_offset; } @@ -4875,18 +5193,20 @@ void Query_log_event::print_query_header(IO_CACHE* file, if (cs_info) { /* for mysql client */ - my_b_printf(file, "/*!\\C %s */%s\n", - cs_info->csname, print_event_info->delimiter); - } - my_b_printf(file,"SET " - "@@session.character_set_client=%d," - "@@session.collation_connection=%d," - "@@session.collation_server=%d" - "%s\n", - uint2korr(charset), - uint2korr(charset+2), - uint2korr(charset+4), - print_event_info->delimiter); + if (my_b_printf(file, "/*!\\C %s */%s\n", + cs_info->csname, print_event_info->delimiter)) + goto err; + } + if (my_b_printf(file,"SET " + "@@session.character_set_client=%d," + "@@session.collation_connection=%d," + "@@session.collation_server=%d" + "%s\n", + uint2korr(charset), + uint2korr(charset+2), + uint2korr(charset+4), + print_event_info->delimiter)) + goto err; memcpy(print_event_info->charset, charset, 6); print_event_info->charset_inited= 1; } @@ -4895,31 +5215,40 @@ void Query_log_event::print_query_header(IO_CACHE* file, if (memcmp(print_event_info->time_zone_str, time_zone_str, time_zone_len+1)) { - my_b_printf(file,"SET @@session.time_zone='%s'%s\n", - time_zone_str, print_event_info->delimiter); + if (my_b_printf(file,"SET @@session.time_zone='%s'%s\n", + time_zone_str, print_event_info->delimiter)) + goto err; memcpy(print_event_info->time_zone_str, time_zone_str, time_zone_len+1); } } if (lc_time_names_number != print_event_info->lc_time_names_number) { - my_b_printf(file, "SET @@session.lc_time_names=%d%s\n", - lc_time_names_number, print_event_info->delimiter); + if (my_b_printf(file, "SET @@session.lc_time_names=%d%s\n", + lc_time_names_number, print_event_info->delimiter)) + goto err; print_event_info->lc_time_names_number= lc_time_names_number; } if (charset_database_number != print_event_info->charset_database_number) { if (charset_database_number) - my_b_printf(file, "SET @@session.collation_database=%d%s\n", - charset_database_number, print_event_info->delimiter); - else - my_b_printf(file, "SET @@session.collation_database=DEFAULT%s\n", - print_event_info->delimiter); + { + if (my_b_printf(file, "SET @@session.collation_database=%d%s\n", + charset_database_number, print_event_info->delimiter)) + goto err; + } + else if (my_b_printf(file, "SET @@session.collation_database=DEFAULT%s\n", + print_event_info->delimiter)) + goto err; print_event_info->charset_database_number= charset_database_number; } + return 0; + +err: + return 1; } -void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) +bool Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { Write_on_release_cache cache(&print_event_info->head_cache, file, 0, this); @@ -4929,25 +5258,32 @@ void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) */ DBUG_EXECUTE_IF ("simulate_file_write_error", {(&cache)->write_pos= (&cache)->write_end- 500;}); - print_query_header(&cache, print_event_info); + if (print_query_header(&cache, print_event_info)) + goto err; if (!is_flashback) { - my_b_write(&cache, (uchar*) query, q_len); - my_b_printf(&cache, "\n%s\n", print_event_info->delimiter); + if (my_b_write(&cache, (uchar*) query, q_len) || + my_b_printf(&cache, "\n%s\n", print_event_info->delimiter)) + goto err; } else // is_flashback == 1 { if (strcmp("BEGIN", query) == 0) { - my_b_write(&cache, (uchar*) "COMMIT", 6); - my_b_printf(&cache, "\n%s\n", print_event_info->delimiter); + if (my_b_write(&cache, (uchar*) "COMMIT", 6) || + my_b_printf(&cache, "\n%s\n", print_event_info->delimiter)) + goto err; } else if (strcmp("COMMIT", query) == 0) { - my_b_write(&cache, (uchar*) "BEGIN", 5); - my_b_printf(&cache, "\n%s\n", print_event_info->delimiter); + if (my_b_write(&cache, (uchar*) "BEGIN", 5) || + my_b_printf(&cache, "\n%s\n", print_event_info->delimiter)) + goto err; } } + return cache.flush_data(); +err: + return 1; } #endif /* MYSQL_CLIENT */ @@ -5558,7 +5894,7 @@ void Start_log_event_v3::pack_info(Protocol *protocol) */ #ifdef MYSQL_CLIENT -void Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info) +bool Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { DBUG_ENTER("Start_log_event_v3::print"); @@ -5567,16 +5903,21 @@ void Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info) if (!print_event_info->short_form) { - print_header(&cache, print_event_info, FALSE); - my_b_printf(&cache, "\tStart: binlog v %d, server v %s created ", - binlog_version, server_version); - print_timestamp(&cache); + if (print_header(&cache, print_event_info, FALSE) || + my_b_printf(&cache, "\tStart: binlog v %d, server v %s created ", + binlog_version, server_version) || + print_timestamp(&cache)) + goto err; if (created) - my_b_printf(&cache," at startup"); - my_b_printf(&cache, "\n"); + if (my_b_printf(&cache," at startup")) + goto err; + if (my_b_printf(&cache, "\n")) + goto err; if (flags & LOG_EVENT_BINLOG_IN_USE_F) - my_b_printf(&cache, "# Warning: this binlog is either in use or was not " - "closed properly.\n"); + if (my_b_printf(&cache, + "# Warning: this binlog is either in use or was not " + "closed properly.\n")) + goto err; } if (!is_artificial_event() && created) { @@ -5587,9 +5928,12 @@ void Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info) and rollback unfinished transaction. Probably this can be done with RESET CONNECTION (syntax to be defined). */ - my_b_printf(&cache,"RESET CONNECTION%s\n", print_event_info->delimiter); + if (my_b_printf(&cache,"RESET CONNECTION%s\n", + print_event_info->delimiter)) + goto err; #else - my_b_printf(&cache,"ROLLBACK%s\n", print_event_info->delimiter); + if (my_b_printf(&cache,"ROLLBACK%s\n", print_event_info->delimiter)) + goto err; #endif } if (temp_buf && @@ -5597,11 +5941,15 @@ void Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info) !print_event_info->short_form) { if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS) - my_b_printf(&cache, "BINLOG '\n"); - print_base64(&cache, print_event_info, FALSE); + if (my_b_printf(&cache, "BINLOG '\n")) + goto err; + if (print_base64(&cache, print_event_info, FALSE)) + goto err; print_event_info->printed_fd_event= TRUE; } - DBUG_VOID_RETURN; + DBUG_RETURN(cache.flush_data()); +err: + DBUG_RETURN(1); } #endif /* MYSQL_CLIENT */ @@ -6284,7 +6632,7 @@ int Start_encryption_log_event::do_update_pos(rpl_group_info *rgi) #endif #ifndef MYSQL_SERVER -void Start_encryption_log_event::print(FILE* file, +bool Start_encryption_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { Write_on_release_cache cache(&print_event_info->head_cache, file); @@ -6296,7 +6644,9 @@ void Start_encryption_log_event::print(FILE* file, buf.append(STRING_WITH_LEN(", nonce: ")); buf.append_hex(nonce, BINLOG_NONCE_LENGTH); buf.append(STRING_WITH_LEN("\n# The rest of the binlog is encrypted!\n")); - my_b_write(&cache, (uchar*)buf.ptr(), buf.length()); + if (my_b_write(&cache, (uchar*)buf.ptr(), buf.length())) + return 1; + return (cache.flush_data()); } #endif /************************************************************************** @@ -6321,7 +6671,7 @@ void Start_encryption_log_event::print(FILE* file, */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -void Load_log_event::print_query(THD *thd, bool need_db, const char *cs, +bool Load_log_event::print_query(THD *thd, bool need_db, const char *cs, String *buf, my_off_t *fn_start, my_off_t *fn_end, const char *qualify_db) { @@ -6417,6 +6767,7 @@ void Load_log_event::print_query(THD *thd, bool need_db, const char *cs, } buf->append(STRING_WITH_LEN(")")); } + return 0; } @@ -6660,26 +7011,27 @@ err: */ #ifdef MYSQL_CLIENT -void Load_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) +bool Load_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { - print(file, print_event_info, 0); + return print(file, print_event_info, 0); } -void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info, +bool Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info, bool commented) { Write_on_release_cache cache(&print_event_info->head_cache, file_arg); - + bool different_db= 1; DBUG_ENTER("Load_log_event::print"); + if (!print_event_info->short_form) { - print_header(&cache, print_event_info, FALSE); - my_b_printf(&cache, "\tQuery\tthread_id=%ld\texec_time=%ld\n", - thread_id, exec_time); + if (print_header(&cache, print_event_info, FALSE) || + my_b_printf(&cache, "\tQuery\tthread_id=%ld\texec_time=%ld\n", + thread_id, exec_time)) + goto err; } - bool different_db= 1; if (db) { /* @@ -6692,69 +7044,86 @@ void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info, !commented) memcpy(print_event_info->db, db, db_len + 1); } - + if (db && db[0] && different_db) - my_b_printf(&cache, "%suse %`s%s\n", - commented ? "# " : "", - db, print_event_info->delimiter); + if (my_b_printf(&cache, "%suse %`s%s\n", + commented ? "# " : "", + db, print_event_info->delimiter)) + goto err; if (flags & LOG_EVENT_THREAD_SPECIFIC_F) - my_b_printf(&cache,"%sSET @@session.pseudo_thread_id=%lu%s\n", - commented ? "# " : "", (ulong)thread_id, - print_event_info->delimiter); - my_b_printf(&cache, "%sLOAD DATA ", - commented ? "# " : ""); + if (my_b_printf(&cache,"%sSET @@session.pseudo_thread_id=%lu%s\n", + commented ? "# " : "", (ulong)thread_id, + print_event_info->delimiter)) + goto err; + if (my_b_printf(&cache, "%sLOAD DATA ", + commented ? "# " : "")) + goto err; if (check_fname_outside_temp_buf()) - my_b_write_string(&cache, "LOCAL "); - my_b_printf(&cache, "INFILE '%-*s' ", fname_len, fname); + if (my_b_write_string(&cache, "LOCAL ")) + goto err; + if (my_b_printf(&cache, "INFILE '%-*s' ", fname_len, fname)) + goto err; if (sql_ex.opt_flags & REPLACE_FLAG) - my_b_write_string(&cache, "REPLACE "); + { + if (my_b_write_string(&cache, "REPLACE ")) + goto err; + } else if (sql_ex.opt_flags & IGNORE_FLAG) - my_b_write_string(&cache, "IGNORE "); - - my_b_printf(&cache, "INTO TABLE `%s`", table_name); - my_b_write_string(&cache, " FIELDS TERMINATED BY "); - pretty_print_str(&cache, sql_ex.field_term, sql_ex.field_term_len); + if (my_b_write_string(&cache, "IGNORE ")) + goto err; - if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG) - my_b_write_string(&cache, " OPTIONALLY "); - my_b_write_string(&cache, " ENCLOSED BY "); - pretty_print_str(&cache, sql_ex.enclosed, sql_ex.enclosed_len); - - my_b_write_string(&cache, " ESCAPED BY "); - pretty_print_str(&cache, sql_ex.escaped, sql_ex.escaped_len); - - my_b_write_string(&cache, " LINES TERMINATED BY "); - pretty_print_str(&cache, sql_ex.line_term, sql_ex.line_term_len); + if (my_b_printf(&cache, "INTO TABLE `%s`", table_name) || + my_b_write_string(&cache, " FIELDS TERMINATED BY ") || + pretty_print_str(&cache, sql_ex.field_term, sql_ex.field_term_len)) + goto err; + if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG) + if (my_b_write_string(&cache, " OPTIONALLY ")) + goto err; + if (my_b_write_string(&cache, " ENCLOSED BY ") || + pretty_print_str(&cache, sql_ex.enclosed, sql_ex.enclosed_len) || + my_b_write_string(&cache, " ESCAPED BY ") || + pretty_print_str(&cache, sql_ex.escaped, sql_ex.escaped_len) || + my_b_write_string(&cache, " LINES TERMINATED BY ") || + pretty_print_str(&cache, sql_ex.line_term, sql_ex.line_term_len)) + goto err; if (sql_ex.line_start) { - my_b_write_string(&cache," STARTING BY "); - pretty_print_str(&cache, sql_ex.line_start, sql_ex.line_start_len); + if (my_b_write_string(&cache," STARTING BY ") || + pretty_print_str(&cache, sql_ex.line_start, sql_ex.line_start_len)) + goto err; } if ((long) skip_lines > 0) - my_b_printf(&cache, " IGNORE %ld LINES", (long) skip_lines); + if (my_b_printf(&cache, " IGNORE %ld LINES", (long) skip_lines)) + goto err; if (num_fields) { uint i; const char* field = fields; - my_b_write_string(&cache, " ("); + if (my_b_write_string(&cache, " (")) + goto err; for (i = 0; i < num_fields; i++) { if (i) - my_b_write_byte(&cache, ','); - my_b_printf(&cache, "%`s", field); - + if (my_b_write_byte(&cache, ',')) + goto err; + if (my_b_printf(&cache, "%`s", field)) + goto err; field += field_lens[i] + 1; } - my_b_write_byte(&cache, ')'); + if (my_b_write_byte(&cache, ')')) + goto err; } - my_b_printf(&cache, "%s\n", print_event_info->delimiter); - DBUG_VOID_RETURN; + if (my_b_printf(&cache, "%s\n", print_event_info->delimiter)) + goto err; + DBUG_RETURN(cache.flush_data()); +err: + DBUG_RETURN(1); } #endif /* MYSQL_CLIENT */ @@ -7113,19 +7482,25 @@ void Rotate_log_event::pack_info(Protocol *protocol) */ #ifdef MYSQL_CLIENT -void Rotate_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) +bool Rotate_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { + if (print_event_info->short_form) + return 0; + char buf[22]; Write_on_release_cache cache(&print_event_info->head_cache, file, Write_on_release_cache::FLUSH_F); - - if (print_event_info->short_form) - return; - print_header(&cache, print_event_info, FALSE); - my_b_write_string(&cache, "\tRotate to "); + if (print_header(&cache, print_event_info, FALSE) || + my_b_write_string(&cache, "\tRotate to ")) + goto err; if (new_log_ident) - my_b_write(&cache, (uchar*) new_log_ident, (uint)ident_len); - my_b_printf(&cache, " pos: %s\n", llstr(pos, buf)); + if (my_b_write(&cache, (uchar*) new_log_ident, (uint)ident_len)) + goto err; + if (my_b_printf(&cache, " pos: %s\n", llstr(pos, buf))) + goto err; + return cache.flush_data(); +err: + return 1; } #endif /* MYSQL_CLIENT */ @@ -7330,18 +7705,21 @@ Binlog_checkpoint_log_event::do_shall_skip(rpl_group_info *rgi) #ifdef MYSQL_CLIENT -void Binlog_checkpoint_log_event::print(FILE *file, +bool Binlog_checkpoint_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) { + if (print_event_info->short_form) + return 0; + Write_on_release_cache cache(&print_event_info->head_cache, file, Write_on_release_cache::FLUSH_F); - if (print_event_info->short_form) - return; - print_header(&cache, print_event_info, FALSE); - my_b_write_string(&cache, "\tBinlog checkpoint "); - my_b_write(&cache, (uchar*)binlog_file_name, binlog_file_len); - my_b_write_byte(&cache, '\n'); + if (print_header(&cache, print_event_info, FALSE) || + my_b_write_string(&cache, "\tBinlog checkpoint ") || + my_b_write(&cache, (uchar*)binlog_file_name, binlog_file_len) || + my_b_write_byte(&cache, '\n')) + return 1; + return cache.flush_data(); } #endif /* MYSQL_CLIENT */ @@ -7659,7 +8037,7 @@ Gtid_log_event::do_shall_skip(rpl_group_info *rgi) #else /* !MYSQL_SERVER */ -void +bool Gtid_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) { Write_on_release_cache cache(&print_event_info->head_cache, file, @@ -7671,26 +8049,34 @@ Gtid_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) { print_header(&cache, print_event_info, FALSE); longlong10_to_str(seq_no, buf, 10); - my_b_printf(&cache, "\tGTID %u-%u-%s", domain_id, server_id, buf); + if (my_b_printf(&cache, "\tGTID %u-%u-%s", domain_id, server_id, buf)) + goto err; if (flags2 & FL_GROUP_COMMIT_ID) { longlong10_to_str(commit_id, buf2, 10); - my_b_printf(&cache, " cid=%s", buf2); + if (my_b_printf(&cache, " cid=%s", buf2)) + goto err; } if (flags2 & FL_DDL) - my_b_write_string(&cache, " ddl"); + if (my_b_write_string(&cache, " ddl")) + goto err; if (flags2 & FL_TRANSACTIONAL) - my_b_write_string(&cache, " trans"); + if (my_b_write_string(&cache, " trans")) + goto err; if (flags2 & FL_WAITED) - my_b_write_string(&cache, " waited"); - my_b_printf(&cache, "\n"); + if (my_b_write_string(&cache, " waited")) + goto err; + if (my_b_printf(&cache, "\n")) + goto err; if (!print_event_info->allow_parallel_printed || print_event_info->allow_parallel != !!(flags2 & FL_ALLOW_PARALLEL)) { - my_b_printf(&cache, + if (my_b_printf(&cache, "/*!100101 SET @@session.skip_parallel_replication=%u*/%s\n", - !(flags2 & FL_ALLOW_PARALLEL), print_event_info->delimiter); + !(flags2 & FL_ALLOW_PARALLEL), + print_event_info->delimiter)) + goto err; print_event_info->allow_parallel= !!(flags2 & FL_ALLOW_PARALLEL); print_event_info->allow_parallel_printed= true; } @@ -7698,8 +8084,10 @@ Gtid_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) if (!print_event_info->domain_id_printed || print_event_info->domain_id != domain_id) { - my_b_printf(&cache, "/*!100001 SET @@session.gtid_domain_id=%u*/%s\n", - domain_id, print_event_info->delimiter); + if (my_b_printf(&cache, + "/*!100001 SET @@session.gtid_domain_id=%u*/%s\n", + domain_id, print_event_info->delimiter)) + goto err; print_event_info->domain_id= domain_id; print_event_info->domain_id_printed= true; } @@ -7707,18 +8095,25 @@ Gtid_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) if (!print_event_info->server_id_printed || print_event_info->server_id != server_id) { - my_b_printf(&cache, "/*!100001 SET @@session.server_id=%u*/%s\n", - server_id, print_event_info->delimiter); + if (my_b_printf(&cache, "/*!100001 SET @@session.server_id=%u*/%s\n", + server_id, print_event_info->delimiter)) + goto err; print_event_info->server_id= server_id; print_event_info->server_id_printed= true; } if (!is_flashback) - my_b_printf(&cache, "/*!100001 SET @@session.gtid_seq_no=%s*/%s\n", - buf, print_event_info->delimiter); + if (my_b_printf(&cache, "/*!100001 SET @@session.gtid_seq_no=%s*/%s\n", + buf, print_event_info->delimiter)) + goto err; } if (!(flags2 & FL_STANDALONE)) - my_b_printf(&cache, is_flashback ? "COMMIT\n%s\n" : "BEGIN\n%s\n", print_event_info->delimiter); + if (my_b_printf(&cache, is_flashback ? "COMMIT\n%s\n" : "BEGIN\n%s\n", print_event_info->delimiter)) + goto err; + + return cache.flush_data(); +err: + return 1; } #endif /* MYSQL_SERVER */ @@ -7956,28 +8351,37 @@ Gtid_list_log_event::pack_info(Protocol *protocol) #else /* !MYSQL_SERVER */ -void +bool Gtid_list_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) { - if (!print_event_info->short_form) - { - Write_on_release_cache cache(&print_event_info->head_cache, file, - Write_on_release_cache::FLUSH_F); - char buf[21]; - uint32 i; + if (print_event_info->short_form) + return 0; - print_header(&cache, print_event_info, FALSE); - my_b_printf(&cache, "\tGtid list ["); - for (i= 0; i < count; ++i) - { - longlong10_to_str(list[i].seq_no, buf, 10); - my_b_printf(&cache, "%u-%u-%s", list[i].domain_id, - list[i].server_id, buf); - if (i < count-1) - my_b_printf(&cache, ",\n# "); - } - my_b_printf(&cache, "]\n"); + Write_on_release_cache cache(&print_event_info->head_cache, file, + Write_on_release_cache::FLUSH_F); + char buf[21]; + uint32 i; + + if (print_header(&cache, print_event_info, FALSE) || + my_b_printf(&cache, "\tGtid list [")) + goto err; + + for (i= 0; i < count; ++i) + { + longlong10_to_str(list[i].seq_no, buf, 10); + if (my_b_printf(&cache, "%u-%u-%s", list[i].domain_id, + list[i].server_id, buf)) + goto err; + if (i < count-1) + if (my_b_printf(&cache, ",\n# ")) + goto err; } + if (my_b_printf(&cache, "]\n")) + goto err; + + return cache.flush_data(); +err: + return 1; } #endif /* MYSQL_SERVER */ @@ -8109,7 +8513,7 @@ bool Intvar_log_event::write() */ #ifdef MYSQL_CLIENT -void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) +bool Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { char llbuff[22]; const char *UNINIT_VAR(msg); @@ -8118,11 +8522,13 @@ void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) if (!print_event_info->short_form) { - print_header(&cache, print_event_info, FALSE); - my_b_write_string(&cache, "\tIntvar\n"); + if (print_header(&cache, print_event_info, FALSE) || + my_b_write_string(&cache, "\tIntvar\n")) + goto err; } - my_b_printf(&cache, "SET "); + if (my_b_printf(&cache, "SET ")) + goto err; switch (type) { case LAST_INSERT_ID_EVENT: msg="LAST_INSERT_ID"; @@ -8135,8 +8541,13 @@ void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) msg="INVALID_INT"; break; } - my_b_printf(&cache, "%s=%s%s\n", - msg, llstr(val,llbuff), print_event_info->delimiter); + if (my_b_printf(&cache, "%s=%s%s\n", + msg, llstr(val,llbuff), print_event_info->delimiter)) + goto err; + + return cache.flush_data(); +err: + return 1; } #endif @@ -8235,7 +8646,7 @@ bool Rand_log_event::write() #ifdef MYSQL_CLIENT -void Rand_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) +bool Rand_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { Write_on_release_cache cache(&print_event_info->head_cache, file, Write_on_release_cache::FLUSH_F); @@ -8243,12 +8654,18 @@ void Rand_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) char llbuff[22],llbuff2[22]; if (!print_event_info->short_form) { - print_header(&cache, print_event_info, FALSE); - my_b_write_string(&cache, "\tRand\n"); + if (print_header(&cache, print_event_info, FALSE) || + my_b_write_string(&cache, "\tRand\n")) + goto err; } - my_b_printf(&cache, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s%s\n", - llstr(seed1, llbuff),llstr(seed2, llbuff2), - print_event_info->delimiter); + if (my_b_printf(&cache, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s%s\n", + llstr(seed1, llbuff),llstr(seed2, llbuff2), + print_event_info->delimiter)) + goto err; + + return cache.flush_data(); +err: + return 1; } #endif /* MYSQL_CLIENT */ @@ -8360,7 +8777,7 @@ bool Xid_log_event::write() #ifdef MYSQL_CLIENT -void Xid_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) +bool Xid_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { Write_on_release_cache cache(&print_event_info->head_cache, file, Write_on_release_cache::FLUSH_F, this); @@ -8370,10 +8787,17 @@ void Xid_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) char buf[64]; longlong10_to_str(xid, buf, 10); - print_header(&cache, print_event_info, FALSE); - my_b_printf(&cache, "\tXid = %s\n", buf); + if (print_header(&cache, print_event_info, FALSE) || + my_b_printf(&cache, "\tXid = %s\n", buf)) + goto err; } - my_b_printf(&cache, is_flashback ? "BEGIN%s\n" : "COMMIT%s\n", print_event_info->delimiter); + if (my_b_printf(&cache, is_flashback ? "BEGIN%s\n" : "COMMIT%s\n", + print_event_info->delimiter)) + goto err; + + return cache.flush_data(); +err: + return 1; } #endif /* MYSQL_CLIENT */ @@ -8762,23 +9186,26 @@ bool User_var_log_event::write() */ #ifdef MYSQL_CLIENT -void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) +bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { Write_on_release_cache cache(&print_event_info->head_cache, file, Write_on_release_cache::FLUSH_F); if (!print_event_info->short_form) { - print_header(&cache, print_event_info, FALSE); - my_b_write_string(&cache, "\tUser_var\n"); + if (print_header(&cache, print_event_info, FALSE) || + my_b_write_string(&cache, "\tUser_var\n")) + goto err; } - my_b_write_string(&cache, "SET @"); - my_b_write_backtick_quote(&cache, name, name_len); + if (my_b_write_string(&cache, "SET @") || + my_b_write_backtick_quote(&cache, name, name_len)) + goto err; if (is_null) { - my_b_printf(&cache, ":=NULL%s\n", print_event_info->delimiter); + if (my_b_printf(&cache, ":=NULL%s\n", print_event_info->delimiter)) + goto err; } else { @@ -8788,13 +9215,17 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) char real_buf[FMT_G_BUFSIZE(14)]; float8get(real_val, val); sprintf(real_buf, "%.14g", real_val); - my_b_printf(&cache, ":=%s%s\n", real_buf, print_event_info->delimiter); + if (my_b_printf(&cache, ":=%s%s\n", real_buf, + print_event_info->delimiter)) + goto err; break; case INT_RESULT: char int_buf[22]; longlong10_to_str(uint8korr(val), int_buf, ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10)); - my_b_printf(&cache, ":=%s%s\n", int_buf, print_event_info->delimiter); + if (my_b_printf(&cache, ":=%s%s\n", int_buf, + print_event_info->delimiter)) + goto err; break; case DECIMAL_RESULT: { @@ -8810,7 +9241,9 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) bin2decimal((uchar*) val+2, &dec, precision, scale); decimal2string(&dec, str_buf, &str_len, 0, 0, 0); str_buf[str_len]= 0; - my_b_printf(&cache, ":=%s%s\n", str_buf, print_event_info->delimiter); + if (my_b_printf(&cache, ":=%s%s\n", str_buf, + print_event_info->delimiter)) + goto err; break; } case STRING_RESULT: @@ -8831,11 +9264,12 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) */ char *hex_str; CHARSET_INFO *cs; + bool error; // 2 hex digits / byte hex_str= (char *) my_malloc(2 * val_len + 1 + 3, MYF(MY_WME)); if (!hex_str) - return; + goto err; str_to_hex(hex_str, val, val_len); /* For proper behaviour when mysqlbinlog|mysql, we need to explicitly @@ -8844,24 +9278,31 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) character set. But there's not much to do about this and it's unlikely. */ if (!(cs= get_charset(charset_number, MYF(0)))) - /* + { /* Generate an unusable command (=> syntax error) is probably the best thing we can do here. */ - my_b_printf(&cache, ":=???%s\n", print_event_info->delimiter); + error= my_b_printf(&cache, ":=???%s\n", print_event_info->delimiter); + } else - my_b_printf(&cache, ":=_%s %s COLLATE `%s`%s\n", - cs->csname, hex_str, cs->name, - print_event_info->delimiter); + error= my_b_printf(&cache, ":=_%s %s COLLATE `%s`%s\n", + cs->csname, hex_str, cs->name, + print_event_info->delimiter); my_free(hex_str); - } + if (error) + goto err; break; + } case ROW_RESULT: default: DBUG_ASSERT(0); - return; + break; } } + + return cache.flush_data(); +err: + return 1; } #endif @@ -8984,19 +9425,25 @@ User_var_log_event::do_shall_skip(rpl_group_info *rgi) #ifdef HAVE_REPLICATION #ifdef MYSQL_CLIENT -void Unknown_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info) +bool Unknown_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info) { + if (print_event_info->short_form) + return 0; + Write_on_release_cache cache(&print_event_info->head_cache, file_arg); - if (print_event_info->short_form) - return; if (what != ENCRYPTED) { - print_header(&cache, print_event_info, FALSE); - my_b_printf(&cache, "\n# Unknown event\n"); + if (print_header(&cache, print_event_info, FALSE) || + my_b_printf(&cache, "\n# Unknown event\n")) + goto err; } - else - my_b_printf(&cache, "# Encrypted event\n"); + else if (my_b_printf(&cache, "# Encrypted event\n")) + goto err; + + return cache.flush_data(); +err: + return 1; } #endif @@ -9009,16 +9456,18 @@ void Unknown_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info */ #ifdef MYSQL_CLIENT -void Stop_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) +bool Stop_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { + if (print_event_info->short_form) + return 0; + Write_on_release_cache cache(&print_event_info->head_cache, file, Write_on_release_cache::FLUSH_F, this); - if (print_event_info->short_form) - return; - - print_header(&cache, print_event_info, FALSE); - my_b_write_string(&cache, "\tStop\n"); + if (print_header(&cache, print_event_info, FALSE) || + my_b_write_string(&cache, "\tStop\n")) + return 1; + return cache.flush_data(); } #endif /* MYSQL_CLIENT */ @@ -9200,22 +9649,25 @@ Create_file_log_event::Create_file_log_event(const char* buf, uint len, */ #ifdef MYSQL_CLIENT -void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info, +bool Create_file_log_event::print(FILE* file, + PRINT_EVENT_INFO* print_event_info, bool enable_local) { - Write_on_release_cache cache(&print_event_info->head_cache, file); - if (print_event_info->short_form) { if (enable_local && check_fname_outside_temp_buf()) - Load_log_event::print(file, print_event_info); - return; + return Load_log_event::print(file, print_event_info); + return 0; } + Write_on_release_cache cache(&print_event_info->head_cache, file); + if (enable_local) { - Load_log_event::print(file, print_event_info, - !check_fname_outside_temp_buf()); + if (Load_log_event::print(file, print_event_info, + !check_fname_outside_temp_buf())) + goto err; + /** reduce the size of io cache so that the write function is called for every call to my_b_printf(). @@ -9227,16 +9679,24 @@ void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info That one is for "file_id: etc" below: in mysqlbinlog we want the #, in SHOW BINLOG EVENTS we don't. */ - my_b_write_byte(&cache, '#'); + if (my_b_write_byte(&cache, '#')) + goto err; } - my_b_printf(&cache, " file_id: %d block_len: %d\n", file_id, block_len); + if (my_b_printf(&cache, " file_id: %d block_len: %d\n", file_id, block_len)) + goto err; + + return cache.flush_data(); +err: + return 1; + } -void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) +bool Create_file_log_event::print(FILE* file, + PRINT_EVENT_INFO* print_event_info) { - print(file, print_event_info, 0); + return print(file, print_event_info, 0); } #endif /* MYSQL_CLIENT */ @@ -9302,7 +9762,7 @@ int Create_file_log_event::do_apply_event(rpl_group_info *rgi) fname_buf); goto err; } - + // a trick to avoid allocating another buffer fname= fname_buf; fname_len= (uint) (strmov(ext, ".data") - fname); @@ -9317,7 +9777,7 @@ int Create_file_log_event::do_apply_event(rpl_group_info *rgi) } end_io_cache(&file); mysql_file_close(fd, MYF(0)); - + // fname_buf now already has .data, not .info, because we did our trick /* old copy may exist already */ mysql_file_delete(key_file_log_event_data, fname_buf, MYF(0)); @@ -9415,16 +9875,22 @@ bool Append_block_log_event::write() */ #ifdef MYSQL_CLIENT -void Append_block_log_event::print(FILE* file, +bool Append_block_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { + if (print_event_info->short_form) + return 0; + Write_on_release_cache cache(&print_event_info->head_cache, file); - if (print_event_info->short_form) - return; - print_header(&cache, print_event_info, FALSE); - my_b_printf(&cache, "\n#%s: file_id: %d block_len: %d\n", - get_type_str(), file_id, block_len); + if (print_header(&cache, print_event_info, FALSE) || + my_b_printf(&cache, "\n#%s: file_id: %d block_len: %d\n", + get_type_str(), file_id, block_len)) + goto err; + + return cache.flush_data(); +err: + return 1; } #endif /* MYSQL_CLIENT */ @@ -9574,15 +10040,19 @@ bool Delete_file_log_event::write() */ #ifdef MYSQL_CLIENT -void Delete_file_log_event::print(FILE* file, +bool Delete_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { + if (print_event_info->short_form) + return 0; + Write_on_release_cache cache(&print_event_info->head_cache, file); - if (print_event_info->short_form) - return; - print_header(&cache, print_event_info, FALSE); - my_b_printf(&cache, "\n#Delete_file: file_id=%u\n", file_id); + if (print_header(&cache, print_event_info, FALSE) || + my_b_printf(&cache, "\n#Delete_file: file_id=%u\n", file_id)) + return 1; + + return cache.flush_data(); } #endif /* MYSQL_CLIENT */ @@ -9674,16 +10144,20 @@ bool Execute_load_log_event::write() */ #ifdef MYSQL_CLIENT -void Execute_load_log_event::print(FILE* file, +bool Execute_load_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { + if (print_event_info->short_form) + return 0; + Write_on_release_cache cache(&print_event_info->head_cache, file); - if (print_event_info->short_form) - return; - print_header(&cache, print_event_info, FALSE); - my_b_printf(&cache, "\n#Exec_load: file_id=%d\n", - file_id); + if (print_header(&cache, print_event_info, FALSE) || + my_b_printf(&cache, "\n#Exec_load: file_id=%d\n", + file_id)) + return 1; + + return cache.flush_data(); } #endif @@ -9905,22 +10379,24 @@ Execute_load_query_log_event::write_post_header_for_derived() #ifdef MYSQL_CLIENT -void Execute_load_query_log_event::print(FILE* file, +bool Execute_load_query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { - print(file, print_event_info, 0); + return print(file, print_event_info, 0); } /** Prints the query as LOAD DATA LOCAL and with rewritten filename. */ -void Execute_load_query_log_event::print(FILE* file, +bool Execute_load_query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info, const char *local_fname) { Write_on_release_cache cache(&print_event_info->head_cache, file); - print_query_header(&cache, print_event_info); + if (print_query_header(&cache, print_event_info)) + goto err; + /** reduce the size of io cache so that the write function is called for every call to my_b_printf(). @@ -9931,24 +10407,33 @@ void Execute_load_query_log_event::print(FILE* file, if (local_fname) { - my_b_write(&cache, (uchar*) query, fn_pos_start); - my_b_write_string(&cache, " LOCAL INFILE "); - pretty_print_str(&cache, local_fname, strlen(local_fname)); + if (my_b_write(&cache, (uchar*) query, fn_pos_start) || + my_b_write_string(&cache, " LOCAL INFILE ") || + pretty_print_str(&cache, local_fname, strlen(local_fname))) + goto err; if (dup_handling == LOAD_DUP_REPLACE) - my_b_write_string(&cache, " REPLACE"); - my_b_write_string(&cache, " INTO"); - my_b_write(&cache, (uchar*) query + fn_pos_end, q_len-fn_pos_end); - my_b_printf(&cache, "\n%s\n", print_event_info->delimiter); + if (my_b_write_string(&cache, " REPLACE")) + goto err; + + if (my_b_write_string(&cache, " INTO") || + my_b_write(&cache, (uchar*) query + fn_pos_end, q_len-fn_pos_end) || + my_b_printf(&cache, "\n%s\n", print_event_info->delimiter)) + goto err; } else { - my_b_write(&cache, (uchar*) query, q_len); - my_b_printf(&cache, "\n%s\n", print_event_info->delimiter); + if (my_b_write(&cache, (uchar*) query, q_len) || + my_b_printf(&cache, "\n%s\n", print_event_info->delimiter)) + goto err; } if (!print_event_info->short_form) my_b_printf(&cache, "# file_id: %d \n", file_id); + + return cache.flush_data(); +err: + return 1; } #endif @@ -10928,7 +11413,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) if (global_system_variables.log_warnings) slave_rows_error_report(WARNING_LEVEL, error, rgi, thd, table, get_type_str(), - RPL_LOG_NAME, (ulong) log_pos); + RPL_LOG_NAME, log_pos); thd->clear_error(1); error= 0; if (idempotent_error == 0) @@ -10980,7 +11465,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) if (global_system_variables.log_warnings) slave_rows_error_report(WARNING_LEVEL, error, rgi, thd, table, get_type_str(), - RPL_LOG_NAME, (ulong) log_pos); + RPL_LOG_NAME, log_pos); thd->clear_error(1); error= 0; } @@ -10991,7 +11476,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) { slave_rows_error_report(ERROR_LEVEL, error, rgi, thd, table, get_type_str(), - RPL_LOG_NAME, (ulong) log_pos); + RPL_LOG_NAME, log_pos); /* @todo We should probably not call reset_current_stmt_binlog_format_row() from here. @@ -11021,7 +11506,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) thd->is_error() ? 0 : error, rgi, thd, table, get_type_str(), - RPL_LOG_NAME, (ulong) log_pos); + RPL_LOG_NAME, log_pos); DBUG_RETURN(error); err: @@ -11261,7 +11746,7 @@ void Rows_log_event::pack_info(Protocol *protocol) #endif #ifdef MYSQL_CLIENT -void Rows_log_event::print_helper(FILE *file, +bool Rows_log_event::print_helper(FILE *file, PRINT_EVENT_INFO *print_event_info, char const *const name) { @@ -11270,33 +11755,51 @@ void Rows_log_event::print_helper(FILE *file, #ifdef WHEN_FLASHBACK_REVIEW_READY IO_CACHE *const sql= &print_event_info->review_sql_cache; #endif + bool const last_stmt_event= get_flags(STMT_END_F); if (!print_event_info->short_form) { - bool const last_stmt_event= get_flags(STMT_END_F); print_header(head, print_event_info, !last_stmt_event); - my_b_printf(head, "\t%s: table id %lu%s\n", - name, m_table_id, - last_stmt_event ? " flags: STMT_END_F" : ""); - print_base64(body, print_event_info, !last_stmt_event); + if (my_b_printf(head, "\t%s: table id %lu%s\n", + name, m_table_id, + last_stmt_event ? " flags: STMT_END_F" : "")) + goto err; } + if (!print_event_info->short_form || print_event_info->print_row_count) + if (print_base64(body, print_event_info, !last_stmt_event)) + goto err; - if (get_flags(STMT_END_F)) + if (last_stmt_event) { - LEX_STRING tmp_str; - - copy_event_cache_to_string_and_reinit(head, &tmp_str); - output_buf.append(&tmp_str); - my_free(tmp_str.str); - copy_event_cache_to_string_and_reinit(body, &tmp_str); - output_buf.append(&tmp_str); - my_free(tmp_str.str); + if (!is_flashback) + { + if (copy_event_cache_to_file_and_reinit(head, file) || + copy_event_cache_to_file_and_reinit(body, file)) + goto err; + } + else + { + LEX_STRING tmp_str; + if (copy_event_cache_to_string_and_reinit(head, &tmp_str)) + return 1; + output_buf.append(&tmp_str); + my_free(tmp_str.str); + if (copy_event_cache_to_string_and_reinit(body, &tmp_str)) + return 1; + output_buf.append(&tmp_str); + my_free(tmp_str.str); #ifdef WHEN_FLASHBACK_REVIEW_READY - copy_event_cache_to_string_and_reinit(sql, &tmp_str); - output_buf.append(&tmp_str); - my_free(tmp_str.str); + if (copy_event_cache_to_string_and_reinit(sql, &tmp_str)) + return 1; + output_buf.append(&tmp_str); + my_free(tmp_str.str); #endif + } } + + return 0; +err: + return 1; } #endif @@ -11384,25 +11887,28 @@ void Annotate_rows_log_event::pack_info(Protocol* protocol) #endif #ifdef MYSQL_CLIENT -void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo) +bool Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo) { - if (pinfo->short_form) - return; - - print_header(&pinfo->head_cache, pinfo, TRUE); - my_b_printf(&pinfo->head_cache, "\tAnnotate_rows:\n"); - char *pbeg; // beginning of the next line char *pend; // end of the next line uint cnt= 0; // characters counter + if (!pinfo->short_form) + { + if (print_header(&pinfo->head_cache, pinfo, TRUE) || + my_b_printf(&pinfo->head_cache, "\tAnnotate_rows:\n")) + goto err; + } + else if (my_b_printf(&pinfo->head_cache, "# Annotate_rows:\n")) + goto err; + for (pbeg= m_query_txt; ; pbeg= pend) { // skip all \r's and \n's at the beginning of the next line for (;; pbeg++) { if (++cnt > m_query_len) - return; + return 0; if (*pbeg != '\r' && *pbeg != '\n') break; @@ -11415,10 +11921,15 @@ void Annotate_rows_log_event::print(FILE *file, PRINT_EVENT_INFO *pinfo) ; // print next line - my_b_write(&pinfo->head_cache, (const uchar*) "#Q> ", 4); - my_b_write(&pinfo->head_cache, (const uchar*) pbeg, pend - pbeg); - my_b_write(&pinfo->head_cache, (const uchar*) "\n", 1); + if (my_b_write(&pinfo->head_cache, (const uchar*) "#Q> ", 4) || + my_b_write(&pinfo->head_cache, (const uchar*) pbeg, pend - pbeg) || + my_b_write(&pinfo->head_cache, (const uchar*) "\n", 1)) + goto err; } + + return 0; +err: + return 1; } #endif @@ -11715,7 +12226,7 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, ptr_after_colcnt= ptr_after_colcnt + m_colcnt; bytes_read= (uint) (ptr_after_colcnt - (uchar *)buf); - DBUG_PRINT("info", ("Bytes read: %d.\n", bytes_read)); + DBUG_PRINT("info", ("Bytes read: %d", bytes_read)); if (bytes_read < event_len) { m_field_metadata_size= net_field_length(&ptr_after_colcnt); @@ -12153,19 +12664,29 @@ void Table_map_log_event::pack_info(Protocol *protocol) #ifdef MYSQL_CLIENT -void Table_map_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) +bool Table_map_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) { if (!print_event_info->short_form) { print_header(&print_event_info->head_cache, print_event_info, TRUE); - my_b_printf(&print_event_info->head_cache, - "\tTable_map: %`s.%`s mapped to number %lu%s\n", - m_dbnam, m_tblnam, m_table_id, - ((m_flags & TM_BIT_HAS_TRIGGERS_F) ? - " (has triggers)" : "")); - print_base64(&print_event_info->body_cache, print_event_info, TRUE); - copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, file); + if (my_b_printf(&print_event_info->head_cache, + "\tTable_map: %`s.%`s mapped to number %lu%s\n", + m_dbnam, m_tblnam, m_table_id, + ((m_flags & TM_BIT_HAS_TRIGGERS_F) ? + " (has triggers)" : ""))) + goto err; + } + if (!print_event_info->short_form || print_event_info->print_row_count) + { + if (print_base64(&print_event_info->body_cache, print_event_info, TRUE) || + copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, + file)) + goto err; } + + return 0; +err: + return 1; } #endif @@ -12735,14 +13256,14 @@ Write_rows_log_event::do_exec_row(rpl_group_info *rgi) #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ #ifdef MYSQL_CLIENT -void Write_rows_log_event::print(FILE *file, PRINT_EVENT_INFO* print_event_info) +bool Write_rows_log_event::print(FILE *file, PRINT_EVENT_INFO* print_event_info) { DBUG_EXECUTE_IF("simulate_cache_read_error", {DBUG_SET("+d,simulate_my_b_fill_error");}); - Rows_log_event::print_helper(file, print_event_info, is_flashback ? "Delete_rows" : "Write_rows"); + return Rows_log_event::print_helper(file, print_event_info, is_flashback ? "Delete_rows" : "Write_rows"); } -void Write_rows_compressed_log_event::print(FILE *file, +bool Write_rows_compressed_log_event::print(FILE *file, PRINT_EVENT_INFO* print_event_info) { char *new_buf; @@ -12754,14 +13275,20 @@ void Write_rows_compressed_log_event::print(FILE *file, { free_temp_buf(); register_temp_buf(new_buf, true); - Rows_log_event::print_helper(file, print_event_info, - "Write_compressed_rows"); + if (Rows_log_event::print_helper(file, print_event_info, + "Write_compressed_rows")) + goto err; } else { - my_b_printf(&print_event_info->head_cache, - "ERROR: uncompress write_compressed_rows failed\n"); + if (my_b_printf(&print_event_info->head_cache, + "ERROR: uncompress write_compressed_rows failed\n")) + goto err; } + + return 0; +err: + return 1; } #endif @@ -13409,13 +13936,13 @@ int Delete_rows_log_event::do_exec_row(rpl_group_info *rgi) #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ #ifdef MYSQL_CLIENT -void Delete_rows_log_event::print(FILE *file, +bool Delete_rows_log_event::print(FILE *file, PRINT_EVENT_INFO* print_event_info) { - Rows_log_event::print_helper(file, print_event_info, is_flashback ? "Write_rows" : "Delete_rows"); + return Rows_log_event::print_helper(file, print_event_info, is_flashback ? "Write_rows" : "Delete_rows"); } -void Delete_rows_compressed_log_event::print(FILE *file, +bool Delete_rows_compressed_log_event::print(FILE *file, PRINT_EVENT_INFO* print_event_info) { char *new_buf; @@ -13427,14 +13954,20 @@ void Delete_rows_compressed_log_event::print(FILE *file, { free_temp_buf(); register_temp_buf(new_buf, true); - Rows_log_event::print_helper(file, print_event_info, - "Delete_compressed_rows"); + if (Rows_log_event::print_helper(file, print_event_info, + "Delete_compressed_rows")) + goto err; } else { - my_b_printf(&print_event_info->head_cache, - "ERROR: uncompress delete_compressed_rows failed\n"); + if (my_b_printf(&print_event_info->head_cache, + "ERROR: uncompress delete_compressed_rows failed\n")) + goto err; } + + return 0; +err: + return 1; } #endif @@ -13670,13 +14203,15 @@ err: #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ #ifdef MYSQL_CLIENT -void Update_rows_log_event::print(FILE *file, +bool Update_rows_log_event::print(FILE *file, PRINT_EVENT_INFO* print_event_info) { - Rows_log_event::print_helper(file, print_event_info, "Update_rows"); + return Rows_log_event::print_helper(file, print_event_info, "Update_rows"); } -void Update_rows_compressed_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) +bool +Update_rows_compressed_log_event::print(FILE *file, + PRINT_EVENT_INFO *print_event_info) { char *new_buf; ulong len; @@ -13687,14 +14222,20 @@ void Update_rows_compressed_log_event::print(FILE *file, PRINT_EVENT_INFO *print { free_temp_buf(); register_temp_buf(new_buf, true); - Rows_log_event::print_helper(file, print_event_info, - "Update_compressed_rows"); + if (Rows_log_event::print_helper(file, print_event_info, + "Update_compressed_rows")) + goto err; } else { - my_b_printf(&print_event_info->head_cache, - "ERROR: uncompress update_compressed_rows failed\n"); + if (my_b_printf(&print_event_info->head_cache, + "ERROR: uncompress update_compressed_rows failed\n")) + goto err; } + + return 0; +err: + return 1; } #endif @@ -13833,16 +14374,18 @@ err: #ifdef MYSQL_CLIENT -void -Incident_log_event::print(FILE *file, - PRINT_EVENT_INFO *print_event_info) +bool Incident_log_event::print(FILE *file, + PRINT_EVENT_INFO *print_event_info) { if (print_event_info->short_form) - return; + return 0; Write_on_release_cache cache(&print_event_info->head_cache, file); - print_header(&cache, print_event_info, FALSE); - my_b_printf(&cache, "\n# Incident: %s\nRELOAD DATABASE; # Shall generate syntax error\n", description()); + + if (print_header(&cache, print_event_info, FALSE) || + my_b_printf(&cache, "\n# Incident: %s\nRELOAD DATABASE; # Shall generate syntax error\n", description())) + return 1; + return cache.flush_data(); } #endif @@ -13918,19 +14461,20 @@ void Ignorable_log_event::pack_info(Protocol *protocol) #ifdef MYSQL_CLIENT /* Print for its unrecognized ignorable event */ -void -Ignorable_log_event::print(FILE *file, - PRINT_EVENT_INFO *print_event_info) +bool Ignorable_log_event::print(FILE *file, + PRINT_EVENT_INFO *print_event_info) { if (print_event_info->short_form) - return; + return 0; - print_header(&print_event_info->head_cache, print_event_info, FALSE); - my_b_printf(&print_event_info->head_cache, "\tIgnorable\n"); - my_b_printf(&print_event_info->head_cache, - "# Ignorable event type %d (%s)\n", number, description); - copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, - file); + if (print_header(&print_event_info->head_cache, print_event_info, FALSE) || + my_b_printf(&print_event_info->head_cache, "\tIgnorable\n") || + my_b_printf(&print_event_info->head_cache, + "# Ignorable event type %d (%s)\n", number, description) || + copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, + file)) + return 1; + return 0; } #endif @@ -13942,15 +14486,8 @@ Ignorable_log_event::print(FILE *file, they will always be printed for the first event. */ st_print_event_info::st_print_event_info() - :flags2_inited(0), sql_mode_inited(0), sql_mode(0), - auto_increment_increment(0),auto_increment_offset(0), charset_inited(0), - lc_time_names_number(~0), - charset_database_number(ILLEGAL_CHARSET_INFO_NUMBER), - thread_id(0), thread_id_printed(false), server_id(0), - server_id_printed(false), domain_id(0), domain_id_printed(false), - allow_parallel(true), allow_parallel_printed(false), skip_replication(0), - base64_output_mode(BASE64_OUTPUT_UNSPEC), printed_fd_event(FALSE) { + myf const flags = MYF(MY_WME | MY_NABP); /* Currently we only use static PRINT_EVENT_INFO objects, so zeroed at program's startup, but these explicit bzero() is for the day someone @@ -13961,14 +14498,67 @@ st_print_event_info::st_print_event_info() bzero(time_zone_str, sizeof(time_zone_str)); delimiter[0]= ';'; delimiter[1]= 0; - myf const flags = MYF(MY_WME | MY_NABP); + flags2_inited= 0; + sql_mode_inited= 0; + row_events= 0; + sql_mode= 0; + auto_increment_increment= 0; + auto_increment_offset= 0; + charset_inited= 0; + lc_time_names_number= ~0; + charset_database_number= ILLEGAL_CHARSET_INFO_NUMBER; + thread_id= 0; + server_id= 0; + domain_id= 0; + thread_id_printed= false; + server_id_printed= false; + domain_id_printed= false; + allow_parallel= true; + allow_parallel_printed= false; + found_row_event= false; + print_row_count= false; + short_form= false; + skip_replication= 0; + printed_fd_event=FALSE; + file= 0; + base64_output_mode=BASE64_OUTPUT_UNSPEC; open_cached_file(&head_cache, NULL, NULL, 0, flags); open_cached_file(&body_cache, NULL, NULL, 0, flags); #ifdef WHEN_FLASHBACK_REVIEW_READY open_cached_file(&review_sql_cache, NULL, NULL, 0, flags); #endif } -#endif + + +bool copy_event_cache_to_string_and_reinit(IO_CACHE *cache, LEX_STRING *to) +{ + reinit_io_cache(cache, READ_CACHE, 0L, FALSE, FALSE); + if (!(to->str= (char*) my_malloc((to->length= cache->end_of_file), MYF(0)))) + { + perror("Out of memory: can't allocate memory in copy_event_cache_to_string_and_reinit()."); + goto err; + } + if (my_b_read(cache, (uchar*) to->str, to->length)) + { + my_free(to->str); + perror("Can't read data from IO_CACHE"); + return true; + } + reinit_io_cache(cache, WRITE_CACHE, 0, FALSE, TRUE); + return false; + +err: + to->str= 0; + to->length= 0; + return true; +} +#endif /* MYSQL_CLIENT */ + +bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache, FILE *file) +{ + return (my_b_copy_to_file(cache, file) || + reinit_io_cache(cache, WRITE_CACHE, 0, FALSE, TRUE)); +} #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) Heartbeat_log_event::Heartbeat_log_event(const char* buf, uint event_len, @@ -14006,4 +14596,4 @@ bool event_that_should_be_ignored(const char *buf) return 1; return 0; } -#endif +#endif /* MYSQL_SERVER */ diff --git a/sql/log_event.h b/sql/log_event.h index 9fb14f0eae1..1feaee86ec7 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -802,6 +802,8 @@ class Format_description_log_event; class Relay_log_info; class binlog_cache_data; +bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache, FILE *file); + #ifdef MYSQL_CLIENT enum enum_base64_output_mode { BASE64_OUTPUT_NEVER= 0, @@ -813,6 +815,8 @@ enum enum_base64_output_mode { BASE64_OUTPUT_MODE_COUNT }; +bool copy_event_cache_to_string_and_reinit(IO_CACHE *cache, LEX_STRING *to); + /* A structure for mysqlbinlog to know how to print events @@ -832,53 +836,38 @@ typedef struct st_print_event_info that was printed. We cache these so that we don't have to print them if they are unchanged. */ - // TODO: have the last catalog here ?? char db[FN_REFLEN+1]; // TODO: make this a LEX_STRING when thd->db is - bool flags2_inited; - uint32 flags2; - bool sql_mode_inited; - sql_mode_t sql_mode; /* must be same as THD.variables.sql_mode */ - ulong auto_increment_increment, auto_increment_offset; - bool charset_inited; char charset[6]; // 3 variables, each of them storable in 2 bytes char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH]; + char delimiter[16]; + sql_mode_t sql_mode; /* must be same as THD.variables.sql_mode */ + my_thread_id thread_id; + ulonglong row_events; + ulong auto_increment_increment, auto_increment_offset; uint lc_time_names_number; uint charset_database_number; - my_thread_id thread_id; - bool thread_id_printed; + uint verbose; + uint32 flags2; uint32 server_id; - bool server_id_printed; uint32 domain_id; + uint8 common_header_len; + enum_base64_output_mode base64_output_mode; + my_off_t hexdump_from; + + table_mapping m_table_map; + table_mapping m_table_map_ignored; + bool flags2_inited; + bool sql_mode_inited; + bool charset_inited; + bool thread_id_printed; + bool server_id_printed; bool domain_id_printed; bool allow_parallel; bool allow_parallel_printed; - - /* - Track when @@skip_replication changes so we need to output a SET - statement for it. - */ - int skip_replication; - - st_print_event_info(); - - ~st_print_event_info() { - close_cached_file(&head_cache); - close_cached_file(&body_cache); -#ifdef WHEN_FLASHBACK_REVIEW_READY - close_cached_file(&review_sql_cache); -#endif - } - bool init_ok() /* tells if construction was successful */ - { return my_b_inited(&head_cache) && my_b_inited(&body_cache) -#ifdef WHEN_FLASHBACK_REVIEW_READY - && my_b_inited(&review_sql_cache) -#endif - ; } - - + bool found_row_event; + bool print_row_count; /* Settings on how to print the events */ bool short_form; - enum_base64_output_mode base64_output_mode; /* This is set whenever a Format_description_event is printed. Later, when an event is printed in base64, this flag is tested: if @@ -886,13 +875,11 @@ typedef struct st_print_event_info the base64 event, so an error message is generated. */ bool printed_fd_event; - my_off_t hexdump_from; - uint8 common_header_len; - char delimiter[16]; - - uint verbose; - table_mapping m_table_map; - table_mapping m_table_map_ignored; + /* + Track when @@skip_replication changes so we need to output a SET + statement for it. + */ + bool skip_replication; /* These two caches are used by the row-based replication events to @@ -905,6 +892,28 @@ typedef struct st_print_event_info /* Storing the SQL for reviewing */ IO_CACHE review_sql_cache; #endif + FILE *file; + st_print_event_info(); + + ~st_print_event_info() { + close_cached_file(&head_cache); + close_cached_file(&body_cache); +#ifdef WHEN_FLASHBACK_REVIEW_READY + close_cached_file(&review_sql_cache); +#endif + } + bool init_ok() /* tells if construction was successful */ + { return my_b_inited(&head_cache) && my_b_inited(&body_cache) +#ifdef WHEN_FLASHBACK_REVIEW_READY + && my_b_inited(&review_sql_cache) +#endif + ; } + void flush_for_error() + { + if (!copy_event_cache_to_file_and_reinit(&head_cache, file)) + copy_event_cache_to_file_and_reinit(&body_cache, file); + fflush(file); + } } PRINT_EVENT_INFO; #endif @@ -1250,11 +1259,11 @@ public: Log_event() : temp_buf(0), when(0), flags(0) {} ha_checksum crc; /* print*() functions are used by mysqlbinlog */ - virtual void print(FILE* file, PRINT_EVENT_INFO* print_event_info) = 0; - void print_timestamp(IO_CACHE* file, time_t *ts = 0); - void print_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info, + virtual bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) = 0; + bool print_timestamp(IO_CACHE* file, time_t *ts = 0); + bool print_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info, bool is_more); - void print_base64(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info, + bool print_base64(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info, bool is_more); #endif /* MYSQL_SERVER */ @@ -2112,8 +2121,8 @@ public: void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ #else - void print_query_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info); - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print_query_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif Query_log_event(); @@ -2452,7 +2461,7 @@ protected: const Format_description_log_event* description_event); public: - void print_query(THD *thd, bool need_db, const char *cs, String *buf, + bool print_query(THD *thd, bool need_db, const char *cs, String *buf, my_off_t *fn_start, my_off_t *fn_end, const char *qualify_db); my_thread_id thread_id; @@ -2518,8 +2527,8 @@ public: void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); - void print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool commented); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool commented); #endif /* @@ -2616,7 +2625,7 @@ public: #endif /* HAVE_REPLICATION */ #else Start_log_event_v3() {} - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif Start_log_event_v3(const char* buf, uint event_len, @@ -2685,7 +2694,7 @@ public: write_data(nonce, BINLOG_NONCE_LENGTH); } #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif Start_encryption_log_event( @@ -2873,7 +2882,7 @@ Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg, void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif Intvar_log_event(const char* buf, @@ -2954,7 +2963,7 @@ class Rand_log_event: public Log_event void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif Rand_log_event(const char* buf, @@ -3004,7 +3013,7 @@ class Xid_log_event: public Log_event void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif Xid_log_event(const char* buf, @@ -3066,7 +3075,7 @@ public: } void pack_info(Protocol* protocol); #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif User_var_log_event(const char* buf, uint event_len, @@ -3114,7 +3123,7 @@ public: Stop_log_event() :Log_event() {} #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif Stop_log_event(const char* buf, @@ -3210,7 +3219,7 @@ public: void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif Rotate_log_event(const char* buf, uint event_len, @@ -3250,7 +3259,7 @@ public: void pack_info(Protocol *protocol); #endif #else - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif Binlog_checkpoint_log_event(const char *buf, uint event_len, const Format_description_log_event *description_event); @@ -3375,7 +3384,7 @@ public: virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); #endif #else - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif Gtid_log_event(const char *buf, uint event_len, const Format_description_log_event *description_event); @@ -3489,7 +3498,7 @@ public: void pack_info(Protocol *protocol); #endif #else - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif Gtid_list_log_event(const char *buf, uint event_len, const Format_description_log_event *description_event); @@ -3553,8 +3562,8 @@ public: void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); - void print(FILE* file, PRINT_EVENT_INFO* print_event_info, + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool enable_local); #endif @@ -3626,7 +3635,7 @@ public: virtual int get_create_or_append() const; #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif Append_block_log_event(const char* buf, uint event_len, @@ -3666,8 +3675,8 @@ public: void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); - void print(FILE* file, PRINT_EVENT_INFO* print_event_info, + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool enable_local); #endif @@ -3707,7 +3716,7 @@ public: void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif Execute_load_log_event(const char* buf, uint event_len, @@ -3803,9 +3812,9 @@ public: void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ #else - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); /* Prints the query as LOAD DATA LOCAL and with rewritten filename */ - void print(FILE* file, PRINT_EVENT_INFO* print_event_info, + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info, const char *local_fname); #endif Execute_load_query_log_event(const char* buf, uint event_len, @@ -3850,7 +3859,7 @@ public: /* constructor for hopelessly corrupted events */ Unknown_log_event(): Log_event(), what(ENCRYPTED) {} ~Unknown_log_event() {} - void print(FILE* file, PRINT_EVENT_INFO* print_event_info); + bool print(FILE* file, PRINT_EVENT_INFO* print_event_info); Log_event_type get_type_code() { return UNKNOWN_EVENT;} bool is_valid() const { return 1; } }; @@ -3895,7 +3904,7 @@ public: #endif #ifdef MYSQL_CLIENT - virtual void print(FILE*, PRINT_EVENT_INFO*); + virtual bool print(FILE*, PRINT_EVENT_INFO*); #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) @@ -4315,7 +4324,7 @@ public: #endif #ifdef MYSQL_CLIENT - virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + virtual bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif @@ -4436,15 +4445,21 @@ public: #ifdef MYSQL_CLIENT /* not for direct call, each derived has its own ::print() */ - virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info)= 0; + virtual bool print(FILE *file, PRINT_EVENT_INFO *print_event_info)= 0; void change_to_flashback_event(PRINT_EVENT_INFO *print_event_info, uchar *rows_buff, Log_event_type ev_type); - void print_verbose(IO_CACHE *file, + bool print_verbose(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info); size_t print_verbose_one_row(IO_CACHE *file, table_def *td, PRINT_EVENT_INFO *print_event_info, MY_BITMAP *cols_bitmap, const uchar *ptr, const uchar *prefix, const my_bool no_fill_output= 0); // if no_fill_output=1, then print result is unnecessary + size_t calc_row_event_length(table_def *td, + PRINT_EVENT_INFO *print_event_info, + MY_BITMAP *cols_bitmap, + const uchar *value); + void count_row_events(PRINT_EVENT_INFO *print_event_info); + #endif #ifdef MYSQL_SERVER @@ -4551,7 +4566,7 @@ protected: void uncompress_buf(); #ifdef MYSQL_CLIENT - void print_helper(FILE *, PRINT_EVENT_INFO *, char const *const name); + bool print_helper(FILE *, PRINT_EVENT_INFO *, char const *const name); #endif #ifdef MYSQL_SERVER @@ -4755,7 +4770,7 @@ private: virtual Log_event_type get_general_type_code() { return (Log_event_type)TYPE_CODE; } #ifdef MYSQL_CLIENT - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) @@ -4779,7 +4794,7 @@ public: #endif private: #if defined(MYSQL_CLIENT) - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif }; @@ -4842,7 +4857,7 @@ protected: virtual Log_event_type get_general_type_code() { return (Log_event_type)TYPE_CODE; } #ifdef MYSQL_CLIENT - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) @@ -4866,7 +4881,7 @@ public: #endif private: #if defined(MYSQL_CLIENT) - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif }; @@ -4926,7 +4941,7 @@ protected: virtual Log_event_type get_general_type_code() { return (Log_event_type)TYPE_CODE; } #ifdef MYSQL_CLIENT - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) @@ -4949,7 +4964,7 @@ public: #endif private: #if defined(MYSQL_CLIENT) - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif }; @@ -5043,7 +5058,7 @@ public: virtual ~Incident_log_event(); #ifdef MYSQL_CLIENT - virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + virtual bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) @@ -5110,7 +5125,7 @@ public: #endif #ifdef MYSQL_CLIENT - virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + virtual bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif virtual Log_event_type get_type_code() { return IGNORABLE_LOG_EVENT; } @@ -5120,38 +5135,6 @@ public: virtual int get_data_size() { return IGNORABLE_HEADER_LEN; } }; - -static inline bool copy_event_cache_to_string_and_reinit(IO_CACHE *cache, LEX_STRING *to) -{ - String tmp; - - reinit_io_cache(cache, READ_CACHE, 0L, FALSE, FALSE); - if (tmp.append(cache, (uint32)cache->end_of_file)) - goto err; - reinit_io_cache(cache, WRITE_CACHE, 0, FALSE, TRUE); - - /* - Can't change the order, because the String::release() will clear the - length. - */ - to->length= tmp.length(); - to->str= tmp.release(); - - return false; - -err: - perror("Out of memory: can't allocate memory in copy_event_cache_to_string_and_reinit()."); - return true; -} - -static inline bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache, - FILE *file) -{ - return - my_b_copy_to_file(cache, file) || - reinit_io_cache(cache, WRITE_CACHE, 0, FALSE, TRUE); -} - #ifdef MYSQL_SERVER /***************************************************************************** diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 2c079a34d56..20986050203 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1845,7 +1845,7 @@ void Old_rows_log_event::pack_info(Protocol *protocol) #ifdef MYSQL_CLIENT -void Old_rows_log_event::print_helper(FILE *file, +bool Old_rows_log_event::print_helper(FILE *file, PRINT_EVENT_INFO *print_event_info, char const *const name) { @@ -1854,18 +1854,23 @@ void Old_rows_log_event::print_helper(FILE *file, if (!print_event_info->short_form) { bool const last_stmt_event= get_flags(STMT_END_F); - print_header(head, print_event_info, !last_stmt_event); - my_b_printf(head, "\t%s: table id %lu%s\n", - name, m_table_id, - last_stmt_event ? " flags: STMT_END_F" : ""); - print_base64(body, print_event_info, !last_stmt_event); + if (print_header(head, print_event_info, !last_stmt_event) || + my_b_printf(head, "\t%s: table id %lu%s\n", + name, m_table_id, + last_stmt_event ? " flags: STMT_END_F" : "") || + print_base64(body, print_event_info, !last_stmt_event)) + goto err; } if (get_flags(STMT_END_F)) { - copy_event_cache_to_file_and_reinit(head, file); - copy_event_cache_to_file_and_reinit(body, file); + if (copy_event_cache_to_file_and_reinit(head, file) || + copy_event_cache_to_file_and_reinit(body, file)) + goto err; } + return 0; +err: + return 1; } #endif @@ -2491,10 +2496,11 @@ Write_rows_log_event_old::do_exec_row(rpl_group_info *rgi) #ifdef MYSQL_CLIENT -void Write_rows_log_event_old::print(FILE *file, +bool Write_rows_log_event_old::print(FILE *file, PRINT_EVENT_INFO* print_event_info) { - Old_rows_log_event::print_helper(file, print_event_info, "Write_rows_old"); + return Old_rows_log_event::print_helper(file, print_event_info, + "Write_rows_old"); } #endif @@ -2598,10 +2604,11 @@ int Delete_rows_log_event_old::do_exec_row(rpl_group_info *rgi) #ifdef MYSQL_CLIENT -void Delete_rows_log_event_old::print(FILE *file, +bool Delete_rows_log_event_old::print(FILE *file, PRINT_EVENT_INFO* print_event_info) { - Old_rows_log_event::print_helper(file, print_event_info, "Delete_rows_old"); + return Old_rows_log_event::print_helper(file, print_event_info, + "Delete_rows_old"); } #endif @@ -2736,9 +2743,10 @@ Update_rows_log_event_old::do_exec_row(rpl_group_info *rgi) #ifdef MYSQL_CLIENT -void Update_rows_log_event_old::print(FILE *file, +bool Update_rows_log_event_old::print(FILE *file, PRINT_EVENT_INFO* print_event_info) { - Old_rows_log_event::print_helper(file, print_event_info, "Update_rows_old"); + return Old_rows_log_event::print_helper(file, print_event_info, + "Update_rows_old"); } #endif diff --git a/sql/log_event_old.h b/sql/log_event_old.h index 40e01d37318..d18c980bdfe 100644 --- a/sql/log_event_old.h +++ b/sql/log_event_old.h @@ -116,7 +116,7 @@ public: #ifdef MYSQL_CLIENT /* not for direct call, each derived has its own ::print() */ - virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info)= 0; + virtual bool print(FILE *file, PRINT_EVENT_INFO *print_event_info)= 0; #endif #ifndef MYSQL_CLIENT @@ -166,7 +166,7 @@ protected: const Format_description_log_event *description_event); #ifdef MYSQL_CLIENT - void print_helper(FILE *, PRINT_EVENT_INFO *, char const *const name); + bool print_helper(FILE *, PRINT_EVENT_INFO *, char const *const name); #endif #ifndef MYSQL_CLIENT @@ -379,7 +379,7 @@ public: private: #ifdef MYSQL_CLIENT - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) @@ -455,7 +455,7 @@ public: protected: #ifdef MYSQL_CLIENT - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) @@ -529,7 +529,7 @@ public: protected: #ifdef MYSQL_CLIENT - void print(FILE *file, PRINT_EVENT_INFO *print_event_info); + bool print(FILE *file, PRINT_EVENT_INFO *print_event_info); #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d0a7bdd83a6..0ec99d6eb96 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3678,8 +3678,6 @@ void my_message_sql(uint error, const char *str, myf MyFlags) extern "C" void *my_str_malloc_mysqld(size_t size); -extern "C" void my_str_free_mysqld(void *ptr); -extern "C" void *my_str_realloc_mysqld(void *ptr, size_t size); void *my_str_malloc_mysqld(size_t size) { @@ -3687,17 +3685,6 @@ void *my_str_malloc_mysqld(size_t size) } -void my_str_free_mysqld(void *ptr) -{ - my_free(ptr); -} - -void *my_str_realloc_mysqld(void *ptr, size_t size) -{ - return my_realloc(ptr, size, MYF(MY_FAE)); -} - - #ifdef __WIN__ pthread_handler_t handle_shutdown(void *arg) @@ -3753,14 +3740,8 @@ check_enough_stack_size(int recurse_level) } -/* - Initialize my_str_malloc() and my_str_free() -*/ static void init_libstrings() { - my_str_malloc= &my_str_malloc_mysqld; - my_str_free= &my_str_free_mysqld; - my_str_realloc= &my_str_realloc_mysqld; #ifndef EMBEDDED_LIBRARY my_string_stack_guard= check_enough_stack_size; #endif @@ -3771,7 +3752,7 @@ ulonglong my_pcre_frame_size; static void init_pcre() { pcre_malloc= pcre_stack_malloc= my_str_malloc_mysqld; - pcre_free= pcre_stack_free= my_str_free_mysqld; + pcre_free= pcre_stack_free= my_free; pcre_stack_guard= check_enough_stack_size_slow; /* See http://pcre.org/original/doc/html/pcrestack.html */ my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0); @@ -7336,7 +7317,7 @@ struct my_option my_long_options[]= "The value has to be a multiple of 256.", &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size, 0, GET_ULONG, REQUIRED_ARG, - /* def_value */ 8192, /* min_value */ 256, /* max_value */ ULONG_MAX, + /* def_value */ 8192, /* min_value */ 256, /* max_value */ UINT_MAX32-1, /* sub_size */ 0, /* block_size */ 256, /* app_type */ 0 }, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3a13a77ade0..24d69701c72 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1541,7 +1541,7 @@ end: head->file= org_file; /* Restore head->read_set (and write_set) to what they had before the call */ - head->column_bitmaps_set(save_read_set, save_write_set); + head->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set); if (reset()) { @@ -6730,7 +6730,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, bool update_tbl_stats, double read_time) { - uint idx, best_idx; + uint idx, UNINIT_VAR(best_idx); SEL_ARG *key_to_read= NULL; ha_rows UNINIT_VAR(best_records); /* protected by key_to_read */ uint UNINIT_VAR(best_mrr_flags), /* protected by key_to_read */ @@ -11387,7 +11387,10 @@ int QUICK_RANGE_SELECT::reset() buf_size/= 2; } if (!mrr_buf_desc) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); + { + error= HA_ERR_OUT_OF_MEM; + goto err; + } /* Initialize the handler buffer. */ mrr_buf_desc->buffer= mrange_buff; diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 0dc9a2638eb..c47c7fc8de9 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -2383,6 +2383,24 @@ end: DBUG_RETURN(result); } + +bool partition_info::error_if_requires_values() const +{ + switch (part_type) { + case NOT_A_PARTITION: + case HASH_PARTITION: + break; + case RANGE_PARTITION: + my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "RANGE", "LESS THAN"); + return true; + case LIST_PARTITION: + my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "LIST", "IN"); + return true; + } + return false; +} + + /** Fix partition data from parser. @@ -2473,6 +2491,8 @@ bool partition_info::fix_parser_data(THD *thd) part_elem= it++; List_iterator<part_elem_value> list_val_it(part_elem->list_val_list); num_elements= part_elem->list_val_list.elements; + if (!num_elements && error_if_requires_values()) + DBUG_RETURN(true); DBUG_ASSERT(part_type == RANGE_PARTITION ? num_elements == 1U : TRUE); diff --git a/sql/partition_info.h b/sql/partition_info.h index 38a353c8507..fc13d48e5ee 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -332,6 +332,7 @@ public: size_t file_name_size, uint32 *part_id); void report_part_expr_error(bool use_subpart_expr); bool has_same_partitioning(partition_info *new_part_info); + bool error_if_requires_values() const; private: static int list_part_cmp(const void* a, const void* b); bool set_up_default_partitions(THD *thd, handler *file, HA_CREATE_INFO *info, diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 369b072ab47..6d6211e4741 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -1673,7 +1673,6 @@ rpl_binlog_state::write_to_iocache(IO_CACHE *dest) mysql_mutex_lock(&LOCK_binlog_state); for (i= 0; i < hash.records; ++i) { - size_t res; element *e= (element *)my_hash_element(&hash, i); if (!e->last_gtid) { @@ -1693,8 +1692,8 @@ rpl_binlog_state::write_to_iocache(IO_CACHE *dest) gtid= e->last_gtid; longlong10_to_str(gtid->seq_no, buf, 10); - res= my_b_printf(dest, "%u-%u-%s\n", gtid->domain_id, gtid->server_id, buf); - if (res == (size_t) -1) + if (my_b_printf(dest, "%u-%u-%s\n", gtid->domain_id, gtid->server_id, + buf)) { res= 1; goto end; diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 061e313c494..349e8f2c533 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -1804,30 +1804,30 @@ ER_WRONG_AUTO_KEY 42000 S1009 ER_BINLOG_CANT_DELETE_GTID_DOMAIN eng "Could not delete gtid domain. Reason: %s." ER_NORMAL_SHUTDOWN - cze "%s (%s): normální ukončení\n" - dan "%s (%s): Normal nedlukning\n" - nla "%s (%s): Normaal afgesloten \n" - eng "%s (%s): Normal shutdown\n" - est "%s (%s): MariaDB lõpetas\n" - fre "%s (%s): Arrêt normal du serveur\n" - ger "%s (%s): Normal heruntergefahren\n" - greek "%s (%s): Φυσιολογική διαδικασία shutdown\n" - hindi "%s (%s): सामान्य शटडाउन\n" - hun "%s (%s): Normal leallitas\n" - ita "%s (%s): Shutdown normale\n" - jpn "%s (%s): 通常シャットダウン\n" - kor "%s (%s): 정상적인 shutdown\n" - nor "%s (%s): Normal avslutning\n" - norwegian-ny "%s (%s): Normal nedkopling\n" - pol "%s (%s): Standardowe zakończenie działania\n" - por "%s (%s): 'Shutdown' normal\n" - rum "%s (%s): Terminare normala\n" - rus "%s (%s): Корректная остановка\n" - serbian "%s (%s): Normalno gašenje\n" - slo "%s (%s): normálne ukončenie\n" - spa "%s (%s): Apagado normal\n" - swe "%s (%s): Normal avslutning\n" - ukr "%s (%s): Нормальне завершення\n" + cze "%s (%s): normální ukončení" + dan "%s (%s): Normal nedlukning" + nla "%s (%s): Normaal afgesloten " + eng "%s (%s): Normal shutdown" + est "%s (%s): MariaDB lõpetas" + fre "%s (%s): Arrêt normal du serveur" + ger "%s (%s): Normal heruntergefahren" + greek "%s (%s): Φυσιολογική διαδικασία shutdown" + hindi "%s (%s): सामान्य शटडाउन" + hun "%s (%s): Normal leallitas" + ita "%s (%s): Shutdown normale" + jpn "%s (%s): 通常シャットダウン" + kor "%s (%s): 정상적인 shutdown" + nor "%s (%s): Normal avslutning" + norwegian-ny "%s (%s): Normal nedkopling" + pol "%s (%s): Standardowe zakończenie działania" + por "%s (%s): 'Shutdown' normal" + rum "%s (%s): Terminare normala" + rus "%s (%s): Корректная остановка" + serbian "%s (%s): Normalno gašenje" + slo "%s (%s): normálne ukončenie" + spa "%s (%s): Apagado normal" + swe "%s (%s): Normal avslutning" + ukr "%s (%s): Нормальне завершення" ER_GOT_SIGNAL cze "%s: přijat signal %d, končím\n" dan "%s: Fangede signal %d. Afslutter!!\n" diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index c99ad088e9f..0452e181e22 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -298,7 +298,9 @@ extern "C" sig_handler handle_fatal_signal(int sig) #ifdef HAVE_WRITE_CORE if (test_flags & TEST_CORE_ON_SIGNAL) { - my_safe_printf_stderr("%s", "Writing a core file\n"); + char buff[80]; + my_getwd(buff, sizeof(buff), 0); + my_safe_printf_stderr("Writing a core file at %s\n", buff); fflush(stderr); my_write_core(sig); } diff --git a/sql/slave.h b/sql/slave.h index 74bb4356dfb..649d55b45b9 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -52,7 +52,7 @@ #define SLAVE_NET_TIMEOUT 60 -#define MAX_SLAVE_ERROR 2000 +#define MAX_SLAVE_ERROR ER_ERROR_LAST+1 #define MAX_REPLICATION_THREAD 64 diff --git a/sql/sp.cc b/sql/sp.cc index 58dd8cfee3d..843c40cf2b6 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1345,8 +1345,8 @@ log: { thd->clear_error(); - String log_query; - log_query.set_charset(system_charset_info); + StringBuffer<128> log_query(thd->variables.character_set_client); + DBUG_ASSERT(log_query.charset()->mbminlen == 1); if (show_create_sp(thd, &log_query, sp->m_explicit_name ? sp->m_db : null_clex_str, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 9d3299a63d4..e4b6fe65f06 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2861,37 +2861,42 @@ static void acl_insert_user(const char *user, const char *host, } -static void acl_update_db(const char *user, const char *host, const char *db, +static bool acl_update_db(const char *user, const char *host, const char *db, ulong privileges) { mysql_mutex_assert_owner(&acl_cache->lock); + bool updated= false; + for (uint i=0 ; i < acl_dbs.elements ; i++) { ACL_DB *acl_db=dynamic_element(&acl_dbs,i,ACL_DB*); if ((!acl_db->user && !user[0]) || - (acl_db->user && - !strcmp(user,acl_db->user))) + (acl_db->user && + !strcmp(user,acl_db->user))) { if ((!acl_db->host.hostname && !host[0]) || - (acl_db->host.hostname && - !strcmp(host, acl_db->host.hostname))) + (acl_db->host.hostname && + !strcmp(host, acl_db->host.hostname))) { - if ((!acl_db->db && !db[0]) || - (acl_db->db && !strcmp(db,acl_db->db))) + if ((!acl_db->db && !db[0]) || + (acl_db->db && !strcmp(db,acl_db->db))) - { - if (privileges) + { + if (privileges) { acl_db->access= privileges; acl_db->initial_access= acl_db->access; } - else - delete_dynamic_element(&acl_dbs,i); - } + else + delete_dynamic_element(&acl_dbs,i); + updated= true; + } } } } + + return updated; } @@ -4383,9 +4388,21 @@ static int replace_db_table(TABLE *table, const char *db, acl_cache->clear(1); // Clear privilege cache if (old_row_exists) acl_update_db(combo.user.str,combo.host.str,db,rights); - else - if (rights) - acl_insert_db(combo.user.str,combo.host.str,db,rights); + else if (rights) + { + /* + If we did not have an already existing row, for users, we must always + insert an ACL_DB entry. For roles however, it is possible that one was + already created when DB privileges were propagated from other granted + roles onto the current role. For this case, first try to update the + existing entry, otherwise insert a new one. + */ + if (!combo.is_role() || + !acl_update_db(combo.user.str, combo.host.str, db, rights)) + { + acl_insert_db(combo.user.str,combo.host.str,db,rights); + } + } DBUG_RETURN(0); /* This could only happen if the grant tables got corrupted */ @@ -6308,9 +6325,12 @@ static int merge_role_privileges(ACL_ROLE *role __attribute__((unused)), { PRIVS_TO_MERGE *data= (PRIVS_TO_MERGE *)context; + DBUG_ASSERT(grantee->counter > 0); if (--grantee->counter) return 1; // don't recurse into grantee just yet + grantee->counter= 1; // Mark the grantee as merged. + /* if we'll do db/table/routine privileges, create a hash of role names */ role_hash_t role_hash(role_key); if (data->what != PRIVS_TO_MERGE::GLOBAL) @@ -7402,11 +7422,10 @@ end_index_init: DBUG_RETURN(return_val); } - -static my_bool role_propagate_grants_action(void *ptr, - void *unused __attribute__((unused))) +static my_bool propagate_role_grants_action(void *role_ptr, + void *ptr __attribute__((unused))) { - ACL_ROLE *role= (ACL_ROLE *)ptr; + ACL_ROLE *role= static_cast<ACL_ROLE *>(role_ptr); if (role->counter) return 0; @@ -7482,7 +7501,7 @@ bool grant_reload(THD *thd) } mysql_mutex_lock(&acl_cache->lock); - my_hash_iterate(&acl_roles, role_propagate_grants_action, NULL); + my_hash_iterate(&acl_roles, propagate_role_grants_action, NULL); mysql_mutex_unlock(&acl_cache->lock); mysql_rwlock_unlock(&LOCK_grant); @@ -10224,13 +10243,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) } } - binlog= true; if (replace_user_table(thd, tables.user_table(), *user_name, 0, 0, 1, 0)) { append_user(thd, &wrong_users, user_name); result= TRUE; continue; } + binlog= true; // every created role is automatically granted to its creator-admin if (handle_as_role) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 2dc977c9b5d..766aa8099ba 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1814,7 +1814,7 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length) sql++; continue; } - /* fall trough */ + /* fall through */ default: break; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 40cf0f2557f..9d83e467c82 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2751,6 +2751,8 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value, MEM_ROOT *runtime_memroot) { Item_change_record *change; + DBUG_ENTER("THD::nocheck_register_item_tree_change"); + DBUG_PRINT("enter", ("Register %p <- %p", old_value, (*place))); /* Now we use one node per change, which adds some memory overhead, but still is rather fast as we use alloc_root for allocations. @@ -2763,12 +2765,13 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value, OOM, thd->fatal_error() is called by the error handler of the memroot. Just return. */ - return; + DBUG_VOID_RETURN; } change= new (change_mem) Item_change_record; change->place= place; change->old_value= old_value; change_list.append(change); + DBUG_VOID_RETURN; } /** @@ -2809,7 +2812,11 @@ void THD::rollback_item_tree_changes() DBUG_ENTER("rollback_item_tree_changes"); while ((change= it++)) + { + DBUG_PRINT("info", ("revert %p -> %p", + change->old_value, (*change->place))); *change->place= change->old_value; + } /* We can forget about changes memory: it's allocated in runtime memroot */ change_list.empty(); DBUG_VOID_RETURN; diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index e428d969db0..1e3994dea66 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -316,13 +316,9 @@ extern "C" void free_user(struct user_conn *uc) void init_max_user_conn(void) { #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (my_hash_init(&hash_user_connections,system_charset_info,max_connections, - 0,0, (my_hash_get_key) get_key_conn, - (my_hash_free_key) free_user, 0)) - { - sql_print_error("Initializing hash_user_connections failed."); - exit(1); - } + my_hash_init(&hash_user_connections, system_charset_info, max_connections, + 0, 0, (my_hash_get_key) get_key_conn, + (my_hash_free_key) free_user, 0); #endif } @@ -481,24 +477,16 @@ void init_user_stats(USER_STATS *user_stats, void init_global_user_stats(void) { - if (my_hash_init(&global_user_stats, system_charset_info, max_connections, - 0, 0, (my_hash_get_key) get_key_user_stats, - (my_hash_free_key)free_user_stats, 0)) - { - sql_print_error("Initializing global_user_stats failed."); - exit(1); - } + my_hash_init(&global_user_stats, system_charset_info, max_connections, + 0, 0, (my_hash_get_key) get_key_user_stats, + (my_hash_free_key) free_user_stats, 0); } void init_global_client_stats(void) { - if (my_hash_init(&global_client_stats, system_charset_info, max_connections, - 0, 0, (my_hash_get_key) get_key_user_stats, - (my_hash_free_key)free_user_stats, 0)) - { - sql_print_error("Initializing global_client_stats failed."); - exit(1); - } + my_hash_init(&global_client_stats, system_charset_info, max_connections, + 0, 0, (my_hash_get_key) get_key_user_stats, + (my_hash_free_key) free_user_stats, 0); } extern "C" uchar *get_key_table_stats(TABLE_STATS *table_stats, size_t *length, @@ -515,12 +503,9 @@ extern "C" void free_table_stats(TABLE_STATS* table_stats) void init_global_table_stats(void) { - if (my_hash_init(&global_table_stats, system_charset_info, max_connections, - 0, 0, (my_hash_get_key) get_key_table_stats, - (my_hash_free_key)free_table_stats, 0)) { - sql_print_error("Initializing global_table_stats failed."); - exit(1); - } + my_hash_init(&global_table_stats, system_charset_info, max_connections, + 0, 0, (my_hash_get_key) get_key_table_stats, + (my_hash_free_key) free_table_stats, 0); } extern "C" uchar *get_key_index_stats(INDEX_STATS *index_stats, size_t *length, @@ -537,13 +522,9 @@ extern "C" void free_index_stats(INDEX_STATS* index_stats) void init_global_index_stats(void) { - if (my_hash_init(&global_index_stats, system_charset_info, max_connections, - 0, 0, (my_hash_get_key) get_key_index_stats, - (my_hash_free_key)free_index_stats, 0)) - { - sql_print_error("Initializing global_index_stats failed."); - exit(1); - } + my_hash_init(&global_index_stats, system_charset_info, max_connections, + 0, 0, (my_hash_get_key) get_key_index_stats, + (my_hash_free_key) free_index_stats, 0); } diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index ff80e198023..9608436226c 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -681,7 +681,7 @@ void With_element::move_anchors_ahead() { st_select_lex *next_sl; st_select_lex *new_pos= spec->first_select(); - st_select_lex *last_sl; + st_select_lex *UNINIT_VAR(last_sl); new_pos->linkage= UNION_TYPE; for (st_select_lex *sl= new_pos; sl; sl= next_sl) { diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 0d237b94af2..f9801d2bf36 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -364,6 +364,9 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) SELECT_LEX *parent_lex= derived->select_lex; Query_arena *arena, backup; DBUG_ENTER("mysql_derived_merge"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); if (derived->merged) DBUG_RETURN(FALSE); @@ -510,7 +513,9 @@ unconditional_materialization: bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) { DBUG_ENTER("mysql_derived_merge_for_insert"); - DBUG_PRINT("enter", ("derived: %p", derived)); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); DBUG_PRINT("info", ("merged_for_insert: %d is_materialized_derived: %d " "is_multitable: %d single_table_updatable: %d " "merge_underlying_list: %d", @@ -566,7 +571,9 @@ bool mysql_derived_init(THD *thd, LEX *lex, TABLE_LIST *derived) { SELECT_LEX_UNIT *unit= derived->get_unit(); DBUG_ENTER("mysql_derived_init"); - DBUG_PRINT("enter", ("derived: %p", derived)); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); // Skip already prepared views/DT if (!unit || unit->prepared) @@ -642,8 +649,9 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) SELECT_LEX_UNIT *unit= derived->get_unit(); DBUG_ENTER("mysql_derived_prepare"); bool res= FALSE; - DBUG_PRINT("enter", ("unit: %p table_list: %p Alias '%s'", - unit, derived, derived->alias)); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + unit)); if (!unit) DBUG_RETURN(FALSE); @@ -876,6 +884,9 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) bool res= FALSE; DBUG_ENTER("mysql_derived_optimize"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); lex->current_select= first_select; @@ -954,6 +965,9 @@ err: bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) { DBUG_ENTER("mysql_derived_create"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); TABLE *table= derived->table; SELECT_LEX_UNIT *unit= derived->get_unit(); @@ -1047,10 +1061,14 @@ bool TABLE_LIST::fill_recursive(THD *thd) bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) { - DBUG_ENTER("mysql_derived_fill"); + Field_iterator_table field_iterator; SELECT_LEX_UNIT *unit= derived->get_unit(); bool derived_is_recursive= derived->is_recursive_with_table(); bool res= FALSE; + DBUG_ENTER("mysql_derived_fill"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); if (unit->executed && !unit->uncacheable && !unit->describe && !derived_is_recursive) @@ -1121,9 +1139,28 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) if (derived_result->flush()) res= TRUE; unit->executed= TRUE; + + if (derived->field_translation) + { + /* reset translation table to materialized table */ + field_iterator.set_table(derived->table); + for (uint i= 0; + !field_iterator.end_of_fields(); + field_iterator.next(), i= i + 1) + { + Item *item; + + if (!(item= field_iterator.create_item(thd))) + { + res= TRUE; + break; + } + thd->change_item_tree(&derived->field_translation[i].item, item); + } + } } err: - if (res || (!lex->describe && !derived_is_recursive && !unit->uncacheable)) + if (res || (!lex->describe && !derived_is_recursive && !unit->uncacheable)) unit->cleanup(); lex->current_select= save_current_select; @@ -1151,6 +1188,9 @@ err: bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) { DBUG_ENTER("mysql_derived_reinit"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); st_select_lex_unit *unit= derived->get_unit(); derived->merged_for_insert= FALSE; diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index fed38a5f4f4..ad80303e1b3 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -974,6 +974,7 @@ Explain_aggr_filesort::Explain_aggr_filesort(MEM_ROOT *mem_root, for (ORDER *ord= filesort->order; ord; ord= ord->next) { sort_items.push_back(ord->item[0], mem_root); + sort_directions.push_back(&ord->direction, mem_root); } filesort->tracker= &tracker; } @@ -987,10 +988,13 @@ void Explain_aggr_filesort::print_json_members(Json_writer *writer, str.length(0); List_iterator_fast<Item> it(sort_items); - Item *item; + List_iterator_fast<ORDER::enum_order> it_dir(sort_directions); + Item* item; + ORDER::enum_order *direction; bool first= true; while ((item= it++)) { + direction= it_dir++; if (first) first= false; else @@ -998,6 +1002,8 @@ void Explain_aggr_filesort::print_json_members(Json_writer *writer, str.append(", "); } append_item_to_str(&str, item); + if (*direction == ORDER::ORDER_DESC) + str.append(" desc"); } writer->add_member("sort_key").add_str(str.c_ptr_safe()); diff --git a/sql/sql_explain.h b/sql/sql_explain.h index 895c059f1b0..7fb50a6cb04 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -286,6 +286,7 @@ public: class Explain_aggr_filesort : public Explain_aggr_node { List<Item> sort_items; + List<ORDER::enum_order> sort_directions; public: enum_explain_aggr_node_type get_type() { return AGGR_OP_FILESORT; } Filesort_tracker tracker; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b40a44b7541..c86bdb94bd9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2428,10 +2428,8 @@ void st_select_lex_node::move_as_slave(st_select_lex_node *new_master) prev= &curr->next; } else - { prev= &new_master->slave; - new_master->slave= this; - } + *prev= this; next= 0; master= new_master; } diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index e47a0e925a6..1080f9d9de2 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4602,16 +4602,11 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0), "LIST", "IN"); } - else if (tab_part_info->part_type == RANGE_PARTITION) - { - my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), - "RANGE", "LESS THAN"); - } else { - DBUG_ASSERT(tab_part_info->part_type == LIST_PARTITION); - my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), - "LIST", "IN"); + DBUG_ASSERT(tab_part_info->part_type == RANGE_PARTITION || + tab_part_info->part_type == LIST_PARTITION); + (void) tab_part_info->error_if_requires_values(); } goto err; } @@ -8076,8 +8071,11 @@ int create_partition_name(char *out, size_t outlen, const char *in1, end= strxnmov(out, outlen-1, in1, "#P#", transl_part, NullS); else if (name_variant == TEMP_PART_NAME) end= strxnmov(out, outlen-1, in1, "#P#", transl_part, "#TMP#", NullS); - else if (name_variant == RENAMED_PART_NAME) + else + { + DBUG_ASSERT(name_variant == RENAMED_PART_NAME); end= strxnmov(out, outlen-1, in1, "#P#", transl_part, "#REN#", NullS); + } if (end - out == static_cast<ptrdiff_t>(outlen-1)) { my_error(ER_PATH_LENGTH, MYF(0), longest_str(in1, transl_part)); @@ -8117,9 +8115,12 @@ int create_subpartition_name(char *out, size_t outlen, else if (name_variant == TEMP_PART_NAME) end= strxnmov(out, outlen-1, in1, "#P#", transl_part_name, "#SP#", transl_subpart_name, "#TMP#", NullS); - else if (name_variant == RENAMED_PART_NAME) + else + { + DBUG_ASSERT(name_variant == RENAMED_PART_NAME); end= strxnmov(out, outlen-1, in1, "#P#", transl_part_name, "#SP#", transl_subpart_name, "#REN#", NullS); + } if (end - out == static_cast<ptrdiff_t>(outlen-1)) { my_error(ER_PATH_LENGTH, MYF(0), diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 243d9d524c2..bea6dc06134 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -4732,7 +4732,19 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) if (error == 0 && this->lex->sql_command == SQLCOM_CALL) { if (is_sql_prepare()) + { + /* + Here we have the diagnostics area status already set to DA_OK. + sent_out_parameters() can raise errors when assigning OUT parameters: + DECLARE a DATETIME; + EXECUTE IMMEDIATE 'CALL p1(?)' USING a; + when the procedure p1 assigns a DATETIME-incompatible value (e.g. 10) + to the out parameter. Allow to overwrite status (to DA_ERROR). + */ + thd->get_stmt_da()->set_overwrite_status(true); thd->protocol_text.send_out_parameters(&this->lex->param_list); + thd->get_stmt_da()->set_overwrite_status(false); + } else thd->protocol->send_out_parameters(&this->lex->param_list); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 82539865d41..8aed093af7f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -861,6 +861,22 @@ JOIN::prepare(TABLE_LIST *tables_init, } } + /* + After setting up window functions, we may have discovered additional + used tables from the PARTITION BY and ORDER BY list. Update all items + that contain window functions. + */ + if (select_lex->have_window_funcs()) + { + List_iterator_fast<Item> it(select_lex->item_list); + Item *item; + while ((item= it++)) + { + if (item->with_window_func) + item->update_used_tables(); + } + } + With_clause *with_clause=select_lex->get_with_clause(); if (with_clause && with_clause->prepare_unreferenced_elements(thd)) DBUG_RETURN(1); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 70ddf7b1241..d0d0e35000d 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -606,7 +606,7 @@ bool String::append(IO_CACHE* file, uint32 arg_length) return TRUE; if (my_b_read(file, (uchar*) Ptr + str_length, arg_length)) { - shrink(str_length); + shrink(str_length ? str_length : 1); return TRUE; } str_length+=arg_length; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3f49d094cf0..6f5d918e0f9 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5115,7 +5115,7 @@ err: /* Write log if no error or if we already deleted a table */ if (!result || thd->log_current_statement) { - if (result && create_info->table_was_deleted) + if (result && create_info->table_was_deleted && pos_in_locked_tables) { /* Possible locked table was dropped. We should remove meta data locks diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index d6c722246e7..be85fb892b0 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1601,7 +1601,7 @@ err_with_lex_cleanup: thd->spcont= save_spcont; thd->variables.sql_mode= save_sql_mode; thd->reset_db(save_db.str, save_db.length); - /* Fall trough to error */ + /* Fall through to error */ } } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index e1225878905..b2be437965e 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -643,7 +643,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, if (!res && mysql_bin_log.is_open()) { - String buff; + StringBuffer<128> buff(thd->variables.character_set_client); + DBUG_ASSERT(buff.charset()->mbminlen == 1); const LEX_STRING command[3]= {{ C_STRING_WITH_LEN("CREATE ") }, { C_STRING_WITH_LEN("ALTER ") }, diff --git a/sql/sql_window.cc b/sql/sql_window.cc index bf393ab1c4d..db34b77ddcb 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -315,14 +315,7 @@ setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, } List_iterator_fast<Item_window_func> li(win_funcs); - Item_window_func *win_func_item; - while ((win_func_item= li++)) - { - win_func_item->update_used_tables(); - } - - li.rewind(); - while ((win_func_item= li++)) + while (Item_window_func * win_func_item= li++) { if (win_func_item->check_result_type_of_order_item()) DBUG_RETURN(1); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 158c09dded1..63194e9d097 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5381,12 +5381,8 @@ opt_part_values: partition_info *part_info= lex->part_info; if (! lex->is_partition_management()) { - if (part_info->part_type == RANGE_PARTITION) - my_yyabort_error((ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), - "RANGE", "LESS THAN")); - if (part_info->part_type == LIST_PARTITION) - my_yyabort_error((ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), - "LIST", "IN")); + if (part_info->error_if_requires_values()) + MYSQL_YYABORT; } else part_info->part_type= HASH_PARTITION; diff --git a/sql/table.cc b/sql/table.cc index 112b1c5ab5c..e6878c42ea2 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -989,7 +989,7 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, Virtual_column_info **check_constraint_ptr= table->check_constraints; sql_mode_t saved_mode= thd->variables.sql_mode; Query_arena backup_arena; - Virtual_column_info *vcol; + Virtual_column_info *vcol= 0; StringBuffer<MAX_FIELD_WIDTH> expr_str; bool res= 1; DBUG_ENTER("parse_vcol_defs"); @@ -1160,7 +1160,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, uint new_frm_ver, field_pack_length, new_field_pack_flag; uint interval_count, interval_parts, read_length, int_length; uint db_create_options, keys, key_parts, n_length; - uint com_length, null_bit_pos, mysql57_vcol_null_bit_pos, bitmap_count; + uint com_length, null_bit_pos, UNINIT_VAR(mysql57_vcol_null_bit_pos), bitmap_count; uint i; uint field_additional_property_length= 0; bool use_hash, mysql57_null_bits= 0; @@ -2127,6 +2127,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } } + key_first_info= keyinfo; for (uint key=0 ; key < keys ; key++,keyinfo++) { uint usable_parts= 0; @@ -2144,9 +2145,6 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, keyinfo->name.length+1); } - if (!key) - key_first_info= keyinfo; - if (ext_key_parts > share->key_parts && key) { KEY_PART_INFO *new_key_part= (keyinfo-1)->key_part + @@ -4631,6 +4629,9 @@ bool TABLE_LIST::create_field_translation(THD *thd) Query_arena *arena, backup; bool res= FALSE; DBUG_ENTER("TABLE_LIST::create_field_translation"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (alias ? alias : "<NULL>"), + get_unit())); if (thd->stmt_arena->is_conventional() || thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) @@ -6843,6 +6844,14 @@ void TABLE::create_key_part_by_field(KEY_PART_INFO *key_part_info, might be reused. */ key_part_info->store_length= key_part_info->length; + /* + For BIT fields null_bit is not set to 0 even if the field is defined + as NOT NULL, look at Field_bit::Field_bit + */ + if (!field->real_maybe_null()) + { + key_part_info->null_bit= 0; + } /* The total store length of the key part is the raw length of the field + @@ -7482,7 +7491,6 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode) swap_values= 1; break; case VCOL_UPDATE_FOR_DELETE: - /* Fall trough */ case VCOL_UPDATE_FOR_WRITE: update= bitmap_is_set(vcol_set, vf->field_index); break; diff --git a/sql/table.h b/sql/table.h index 017db4883f3..8e39964eea9 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2346,6 +2346,9 @@ struct TABLE_LIST inline void set_merged_derived() { DBUG_ENTER("set_merged_derived"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (alias ? alias : "<NULL>"), + get_unit())); derived_type= ((derived_type & DTYPE_MASK) | DTYPE_TABLE | DTYPE_MERGE); set_check_merged(); @@ -2358,6 +2361,9 @@ struct TABLE_LIST void set_materialized_derived() { DBUG_ENTER("set_materialized_derived"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (alias ? alias : "<NULL>"), + get_unit())); derived_type= ((derived_type & (derived ? DTYPE_MASK : DTYPE_VIEW)) | DTYPE_TABLE | DTYPE_MATERIALIZE); set_check_materialized(); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index da92aa9bedb..54313281625 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1264,6 +1264,16 @@ int wsrep_to_buf_helper( if (!ret && writer.write(>id_ev)) ret= 1; } #endif /* GTID_SUPPORT */ + if (wsrep_gtid_mode && thd->variables.gtid_seq_no) + { + Gtid_log_event gtid_event(thd, thd->variables.gtid_seq_no, + thd->variables.gtid_domain_id, + true, LOG_EVENT_SUPPRESS_USE_F, + true, 0); + gtid_event.server_id= thd->variables.server_id; + if (!gtid_event.is_valid()) ret= 0; + ret= writer.write(>id_event); + } /* if there is prepare query, add event for it */ if (!ret && thd->wsrep_TOI_pre_query) |