diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2022-10-04 13:32:38 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2022-10-04 13:32:38 +0200 |
commit | bb76dcbec77d31818ec7dfc0d0dc1f4b49185bc5 (patch) | |
tree | 0c288f685ac6fbc8d4bd4cdbc60bcf9942f019f7 /sql | |
parent | 1ac8149b83f002cd4754e1eca225560bc02b22e4 (diff) | |
parent | 55e07d9ade51e9e969f528d903509806142f4d1e (diff) | |
download | mariadb-git-bb76dcbec77d31818ec7dfc0d0dc1f4b49185bc5.tar.gz |
Merge branch '10.9' into 10.10
Diffstat (limited to 'sql')
62 files changed, 847 insertions, 342 deletions
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index debda4c8970..55523a728f8 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2009, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2020, MariaDB Corporation. + Copyright (c) 2009, 2022, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -353,7 +353,7 @@ static char *debug_sync_bmove_len(char *to, char *to_end, } -#if !defined(DBUG_OFF) +#ifdef DBUG_TRACE /** Create a string that describes an action. @@ -443,8 +443,7 @@ static void debug_sync_print_actions(THD *thd) DBUG_VOID_RETURN; } - -#endif /* !defined(DBUG_OFF) */ +#endif /* defined(DBUG_TRACE) */ /** @@ -775,6 +774,7 @@ static bool debug_sync_set_action(THD *thd, st_debug_sync_action *action) else { const char *dsp_name= action->sync_point.c_ptr(); +#ifdef DBUG_TRACE DBUG_EXECUTE("debug_sync", { /* Functions as DBUG_PRINT args can change keyword and line nr. */ const char *sig_emit= action->signal.c_ptr(); @@ -785,6 +785,7 @@ static bool debug_sync_set_action(THD *thd, st_debug_sync_action *action) dsp_name, action->activation_count, action->hit_limit, action->execute, action->timeout, sig_emit, sig_wait));}); +#endif /* Check this before sorting the array. action may move. */ is_dsp_now= !my_strcasecmp(system_charset_info, dsp_name, "now"); @@ -797,7 +798,9 @@ static bool debug_sync_set_action(THD *thd, st_debug_sync_action *action) sizeof(st_debug_sync_action), debug_sync_qsort_cmp); } } +#ifdef DBUG_TRACE DBUG_EXECUTE("debug_sync_list", debug_sync_print_actions(thd);); +#endif /* Execute the special sync point 'now' if activated above. */ if (is_dsp_now) @@ -1367,7 +1370,7 @@ uchar *debug_sync_value_ptr(THD *thd) static void debug_sync_execute(THD *thd, st_debug_sync_action *action) { -#ifndef DBUG_OFF +#ifdef DBUG_TRACE const char *dsp_name= action->sync_point.c_ptr(); const char *sig_emit= action->signal.c_ptr(); const char *sig_wait= action->wait_for.c_ptr(); @@ -1458,12 +1461,12 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) restore_current_mutex = false; set_timespec(abstime, action->timeout); - DBUG_EXECUTE("debug_sync_exec", { + DBUG_EXECUTE("debug_sync_exec", /* Functions as DBUG_PRINT args can change keyword and line nr. */ - const char *sig_glob= debug_sync_global.ds_signal.c_ptr(); DBUG_PRINT("debug_sync_exec", ("wait for '%s' at: '%s' curr: '%s'", - sig_wait, dsp_name, sig_glob));}); + sig_wait, dsp_name, + debug_sync_global.ds_signal.c_ptr()));); /* Wait until global signal string matches the wait_for string. @@ -1472,17 +1475,17 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) the required dynamic memory allocated. */ while (stringcmp(&debug_sync_global.ds_signal, &action->wait_for) && - !thd->killed && opt_debug_sync_timeout) + !(thd->killed & KILL_HARD_BIT) && opt_debug_sync_timeout) { error= mysql_cond_timedwait(&debug_sync_global.ds_cond, &debug_sync_global.ds_mutex, &abstime); - DBUG_EXECUTE("debug_sync", { + DBUG_EXECUTE("debug_sync", /* Functions as DBUG_PRINT args can change keyword and line nr. */ - const char *sig_glob= debug_sync_global.ds_signal.c_ptr(); DBUG_PRINT("debug_sync", ("awoke from %s global: %s error: %d", - sig_wait, sig_glob, error));}); + sig_wait, debug_sync_global.ds_signal.c_ptr(), + error));); if (unlikely(error == ETIMEDOUT || error == ETIME)) { // We should not make the statement fail, even if in strict mode. diff --git a/sql/event_queue.cc b/sql/event_queue.cc index 873be03faac..ebd2dfeefd6 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -544,7 +544,7 @@ Event_queue::empty_queue() void Event_queue::dbug_dump_queue(my_time_t when) { -#ifndef DBUG_OFF +#ifdef DBUG_TRACE my_time_t now= when; Event_queue_element *et; uint i; diff --git a/sql/field.cc b/sql/field.cc index 028a1961943..c7f63282f0f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3443,7 +3443,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value, DBUG_ASSERT(marked_for_write_or_computed()); int error= 0; DBUG_ENTER("Field_new_decimal::store_value"); -#ifndef DBUG_OFF +#ifdef DBUG_TRACE { char dbug_buff[DECIMAL_MAX_STR_LENGTH+2]; DBUG_PRINT("enter", ("value: %s", dbug_decimal_as_string(dbug_buff, decimal_value))); @@ -3458,7 +3458,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value, error= 1; decimal_value= &decimal_zero; } -#ifndef DBUG_OFF +#ifdef DBUG_TRACE { char dbug_buff[DECIMAL_MAX_STR_LENGTH+2]; DBUG_PRINT("info", ("saving with precision %d scale: %d value %s", @@ -3550,7 +3550,7 @@ int Field_new_decimal::store(const char *from, size_t length, } } -#ifndef DBUG_OFF +#ifdef DBUG_TRACE char dbug_buff[DECIMAL_MAX_STR_LENGTH+2]; DBUG_PRINT("enter", ("value: %s", dbug_decimal_as_string(dbug_buff, &decimal_value))); diff --git a/sql/gcalc_slicescan.cc b/sql/gcalc_slicescan.cc index e35f9155967..f94c7190532 100644 --- a/sql/gcalc_slicescan.cc +++ b/sql/gcalc_slicescan.cc @@ -116,16 +116,20 @@ static void GCALC_DBUG_PRINT_PI(const Gcalc_heap::Info *pi) int n_buf; if (pi->type == Gcalc_heap::nt_intersection) { +#ifdef DBUG_TRACE const Gcalc_scan_iterator::intersection_info *ic= i_data(pi); GCALC_DBUG_PRINT(("intersection point %d %d", ic->edge_a->thread, ic->edge_b->thread)); +#endif return; } if (pi->type == Gcalc_heap::nt_eq_node) { +#ifdef DBUG_TRACE const Gcalc_scan_iterator::point *e= eq_sp(pi); GCALC_DBUG_PRINT(("eq point %d", e->thread)); +#endif return; } n_buf= gcalc_pi_str(buf, pi, ""); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index ec122e01d6d..19e25af4cb8 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3782,7 +3782,22 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) for (i= 0; i < m_tot_parts; i++) { if (!bitmap_is_set(&m_is_clone_of->m_opened_partitions, i)) + { + /* Here we should just create the handler instance, not open it. */ + if (!(m_file[i]= get_new_handler(table->s, m_clone_mem_root, + file[i]->ht))) + { + error= HA_ERR_INITIALIZATION; + file= &m_file[i]; + goto err_handler; + } + if (m_file[i]->set_ha_share_ref(file[i]->ha_share)) + { + error= HA_ERR_INITIALIZATION; + goto err_handler; + } continue; + } if (unlikely((error= create_partition_name(name_buff, sizeof(name_buff), name, name_buffer_ptr, diff --git a/sql/handler.cc b/sql/handler.cc index 5743fc2a455..d31d7f50ba2 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -899,15 +899,14 @@ void ha_close_connection(THD* thd) { for (auto i= 0; i < MAX_HA; i++) { - if (thd->ha_data[i].lock) + if (plugin_ref plugin= thd->ha_data[i].lock) { - handlerton *hton= plugin_hton(thd->ha_data[i].lock); + thd->ha_data[i].lock= NULL; + handlerton *hton= plugin_hton(plugin); if (hton->close_connection) hton->close_connection(hton, thd); - /* make sure SE didn't reset ha_data in close_connection() */ - DBUG_ASSERT(thd->ha_data[i].lock); - /* make sure ha_data is reset and ha_data_lock is released */ thd_set_ha_data(thd, hton, 0); + plugin_unlock(NULL, plugin); } DBUG_ASSERT(!thd->ha_data[i].ha_ptr); } diff --git a/sql/item.h b/sql/item.h index 4d85a654dd4..5240042adcd 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2173,7 +2173,6 @@ public: virtual bool enumerate_field_refs_processor(void *arg) { return 0; } virtual bool mark_as_eliminated_processor(void *arg) { return 0; } virtual bool eliminate_subselect_processor(void *arg) { return 0; } - virtual bool set_fake_select_as_master_processor(void *arg) { return 0; } virtual bool view_used_tables_processor(void *arg) { return 0; } virtual bool eval_not_null_tables(void *arg) { return 0; } virtual bool is_subquery_processor(void *arg) { return 0; } diff --git a/sql/item_create.cc b/sql/item_create.cc index 6deb2e9f400..53acc7946be 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -5919,7 +5919,7 @@ int item_create_init() DBUG_RETURN(1); #endif -#ifndef DBUG_OFF +#ifdef DBUG_TRACE for (uint i=0 ; i < native_functions_hash.records ; i++) { Native_func_registry *func; diff --git a/sql/item_func.cc b/sql/item_func.cc index a7b99bdb3e6..a07595cbbd8 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4609,10 +4609,12 @@ longlong Item_func_sleep::val_int() mysql_cond_destroy(&cond); +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("sleep_inject_query_done_debug_sync", { debug_sync_set_action (thd, STRING_WITH_LEN("dispatch_command_end SIGNAL query_done")); };); +#endif return MY_TEST(!error); // Return 1 killed } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 24c4cc505eb..c79735e9a37 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -399,50 +399,6 @@ bool Item_subselect::eliminate_subselect_processor(void *arg) } -/** - Adjust the master select of the subquery to be the fake_select which - represents the whole UNION right above the subquery, instead of the - last query of the UNION. - - @param arg pointer to the fake select - - @return - FALSE to force the evaluation of the processor for the subsequent items. -*/ - -bool Item_subselect::set_fake_select_as_master_processor(void *arg) -{ - SELECT_LEX *fake_select= (SELECT_LEX*) arg; - /* - Move the st_select_lex_unit of a subquery from a global ORDER BY clause to - become a direct child of the fake_select of a UNION. In this way the - ORDER BY that is applied to the temporary table that contains the result of - the whole UNION, and all columns in the subquery are resolved against this - table. The transformation is applied only for immediate child subqueries of - a UNION query. - */ - if (unit->outer_select()->master_unit()->fake_select_lex == fake_select) - { - /* - Set the master of the subquery to be the fake select (i.e. the whole - UNION), instead of the last query in the UNION. - */ - fake_select->add_slave(unit); - DBUG_ASSERT(unit->outer_select() == fake_select); - /* Adjust the name resolution context hierarchy accordingly. */ - for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) - sl->context.outer_context= &(fake_select->context); - /* - Undo Item_subselect::eliminate_subselect_processor because at that phase - we don't know yet that the ORDER clause will be moved to the fake select. - */ - unit->item= this; - eliminated= FALSE; - } - return FALSE; -} - - bool Item_subselect::mark_as_dependent(THD *thd, st_select_lex *select, Item *item) { diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 54e4f8f0ced..4b672243ee0 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -240,7 +240,6 @@ public: bool unknown_splocal_processor(void *arg) override; bool mark_as_eliminated_processor(void *arg) override; bool eliminate_subselect_processor(void *arg) override; - bool set_fake_select_as_master_processor(void *arg) override; bool enumerate_field_refs_processor(void *arg) override; bool check_vcol_func_processor(void *arg) override { diff --git a/sql/json_table.cc b/sql/json_table.cc index e51b71d5650..5f9ba8d3351 100644 --- a/sql/json_table.cc +++ b/sql/json_table.cc @@ -984,7 +984,7 @@ int Json_table_column::print(THD *thd, Field **f, String *str) ((*f)->has_charset() && m_explicit_cs && (str->append(STRING_WITH_LEN(" CHARSET ")) || str->append(&m_explicit_cs->cs_name) || - (!(m_explicit_cs->state & MY_CS_PRIMARY) && + (Charset(m_explicit_cs).can_have_collate_clause() && (str->append(STRING_WITH_LEN(" COLLATE ")) || str->append(&m_explicit_cs->coll_name))))) || str->append(m_column_type == PATH ? &path : &exists_path) || diff --git a/sql/log.cc b/sql/log.cc index 7be9eb736b1..ddcbecf511b 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -8371,10 +8371,12 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) DBUG_ENTER("MYSQL_BIN_LOG::trx_group_commit_leader"); { +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("inject_binlog_commit_before_get_LOCK_log", DBUG_ASSERT(!debug_sync_set_action(leader->thd, STRING_WITH_LEN ("commit_before_get_LOCK_log SIGNAL waiting WAIT_FOR cont TIMEOUT 1"))); ); +#endif /* Lock the LOCK_log(), and once we get it, collect any additional writes that queued up while we were waiting. @@ -8664,7 +8666,11 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) ++num_commits; if (current->cache_mngr->using_xa && likely(!current->error) && !DBUG_IF("skip_commit_ordered")) + { + mysql_mutex_lock(¤t->thd->LOCK_thd_data); run_commit_ordered(current->thd, current->all); + mysql_mutex_unlock(¤t->thd->LOCK_thd_data); + } current->thd->wakeup_subsequent_commits(current->error); /* @@ -10718,6 +10724,7 @@ binlog_background_thread(void *arg __attribute__((unused))) mysql_mutex_unlock(&mysql_bin_log.LOCK_binlog_background_thread); /* Process any incoming commit_checkpoint_notify() calls. */ +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("inject_binlog_background_thread_before_mark_xid_done", DBUG_ASSERT(!debug_sync_set_action( thd, @@ -10726,6 +10733,7 @@ binlog_background_thread(void *arg __attribute__((unused))) "WAIT_FOR something_that_will_never_happen " "TIMEOUT 2"))); ); +#endif while (queue) { long count= queue->notify_count; @@ -10740,11 +10748,13 @@ binlog_background_thread(void *arg __attribute__((unused))) mysql_bin_log.mark_xid_done(queue->binlog_id, true); queue= next; +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("binlog_background_checkpoint_processed", DBUG_ASSERT(!debug_sync_set_action( thd, STRING_WITH_LEN("now SIGNAL binlog_background_checkpoint_processed"))); ); +#endif } if (stop) diff --git a/sql/log.h b/sql/log.h index f5a87d8a6f7..65f70712bbf 100644 --- a/sql/log.h +++ b/sql/log.h @@ -735,7 +735,7 @@ public: } void harvest_bytes_written(Atomic_counter<uint64> *counter) { -#ifndef DBUG_OFF +#ifdef DBUG_TRACE char buf1[22],buf2[22]; #endif DBUG_ENTER("harvest_bytes_written"); diff --git a/sql/log_event.cc b/sql/log_event.cc index c85216d9347..d4d672e1dca 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2018, Oracle and/or its affiliates. - Copyright (c) 2009, 2021, MariaDB + Copyright (c) 2009, 2022, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1359,7 +1359,7 @@ static void copy_str_and_move(const char **src, Log_event::Byte **dst, } -#ifndef DBUG_OFF +#ifdef DBUG_TRACE static char const * code_name(int code) { diff --git a/sql/mdl.cc b/sql/mdl.cc index 2c6c49ab615..2f5fdd0d60a 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -1187,6 +1187,7 @@ MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout, wait_result != ETIMEDOUT && wait_result != ETIME) { #ifdef WITH_WSREP +# ifdef ENABLED_DEBUG_SYNC // Allow tests to block the applier thread using the DBUG facilities DBUG_EXECUTE_IF("sync.wsrep_before_mdl_wait", { @@ -1196,6 +1197,7 @@ MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout, DBUG_ASSERT(!debug_sync_set_action((owner->get_thd()), STRING_WITH_LEN(act))); };); +# endif if (WSREP_ON && wsrep_thd_is_BF(owner->get_thd(), false)) { wait_result= mysql_cond_wait(&m_COND_wait_status, &m_LOCK_wait_status); @@ -2281,7 +2283,7 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) MDL_ticket *ticket; MDL_wait::enum_wait_status wait_status; DBUG_ENTER("MDL_context::acquire_lock"); -#ifndef DBUG_OFF +#ifdef DBUG_TRACE const char *mdl_lock_name= get_mdl_lock_name( mdl_request->key.mdl_namespace(), mdl_request->type)->str; #endif @@ -2307,7 +2309,7 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) DBUG_RETURN(FALSE); } -#ifndef DBUG_OFF +#ifdef DBUG_TRACE const char *ticket_msg= dbug_print_mdl(ticket); #endif diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 719f7b347f0..4a6182ab41a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1711,6 +1711,7 @@ void kill_mysql(THD *thd) shutdown_thread_id= thd->thread_id; DBUG_EXECUTE_IF("mysql_admin_shutdown_wait_for_slaves", thd->lex->is_shutdown_wait_for_slaves= true;); +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("simulate_delay_at_shutdown", { DBUG_ASSERT(binlog_dump_thread_count == 3); @@ -1720,6 +1721,7 @@ void kill_mysql(THD *thd) DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); };); +#endif if (thd->lex->is_shutdown_wait_for_slaves) shutdown_wait_for_slaves= true; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 39b4290a161..70e71d9a21b 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2012, 2020, MariaDB Corporation. + Copyright (c) 2012, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -507,6 +507,7 @@ net_write_command(NET *net,uchar command, DBUG_ENTER("net_write_command"); DBUG_PRINT("enter",("length: %lu", (ulong) len)); +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("simulate_error_on_packet_write", { if (command == COM_BINLOG_DUMP) @@ -518,6 +519,7 @@ net_write_command(NET *net,uchar command, DBUG_RETURN(true); } };); +#endif MYSQL_NET_WRITE_START(length); buff[4]=command; /* For first packet */ diff --git a/sql/parse_file.cc b/sql/parse_file.cc index 57140019341..f4aae1300e2 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -175,11 +175,12 @@ write_parameter(IO_CACHE *file, const uchar* base, File_option *parameter) { /* string have to be allocated already */ LEX_STRING *val_s= (LEX_STRING *)(base + parameter->offset); - time_t tm= my_time(0); - - get_date(val_s->str, GETDATE_DATE_TIME|GETDATE_GMT|GETDATE_FIXEDLENGTH, - tm); - val_s->length= PARSE_FILE_TIMESTAMPLENGTH; + // number of microseconds since Epoch, timezone-independent + my_hrtime_t tm= my_hrtime(); + // Paded to 19 characters for compatibility + val_s->length= snprintf(val_s->str, MICROSECOND_TIMESTAMP_BUFFER_SIZE, + "%019lld", tm.val); + DBUG_ASSERT(val_s->length == MICROSECOND_TIMESTAMP_BUFFER_SIZE-1); if (my_b_write(file, (const uchar *)val_s->str, PARSE_FILE_TIMESTAMPLENGTH)) DBUG_RETURN(TRUE); @@ -884,16 +885,16 @@ File_parser::parse(uchar* base, MEM_ROOT *mem_root, { /* string have to be allocated already */ LEX_STRING *val= (LEX_STRING *)(base + parameter->offset); - /* yyyy-mm-dd HH:MM:SS = 19(PARSE_FILE_TIMESTAMPLENGTH) characters */ - if (ptr[PARSE_FILE_TIMESTAMPLENGTH] != '\n') + /* 19 characters of timestamp */ + if (ptr[MICROSECOND_TIMESTAMP_BUFFER_SIZE-1] != '\n') { my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0), parameter->name.str, line); DBUG_RETURN(TRUE); } - memcpy(val->str, ptr, PARSE_FILE_TIMESTAMPLENGTH); - val->str[val->length= PARSE_FILE_TIMESTAMPLENGTH]= '\0'; - ptr+= (PARSE_FILE_TIMESTAMPLENGTH+1); + memcpy(val->str, ptr, MICROSECOND_TIMESTAMP_BUFFER_SIZE-1); + val->str[val->length= MICROSECOND_TIMESTAMP_BUFFER_SIZE-1]= '\0'; + ptr+= MICROSECOND_TIMESTAMP_BUFFER_SIZE; break; } case FILE_OPTIONS_STRLIST: diff --git a/sql/records.cc b/sql/records.cc index b3b69f19665..3aad36ca862 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB Corporation + Copyright (c) 2009, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -568,7 +568,7 @@ template<bool Packed_addon_fields> static int rr_unpack_from_tempfile(READ_RECORD *info) { uchar *destination= info->rec_buf; -#ifndef DBUG_OFF +#ifdef DBUG_TRACE my_off_t where= my_b_tell(info->io_cache); #endif if (Packed_addon_fields) diff --git a/sql/rpl_injector.h b/sql/rpl_injector.h index 669a8e29543..28359d9555a 100644 --- a/sql/rpl_injector.h +++ b/sql/rpl_injector.h @@ -264,14 +264,14 @@ public: */ int check_state(enum_state const target_state) { -#ifndef DBUG_OFF +#ifdef DBUG_TRACE static char const *state_name[] = { "START_STATE", "TABLE_STATE", "ROW_STATE", "STATE_COUNT" }; - DBUG_ASSERT(target_state <= STATE_COUNT); DBUG_PRINT("info", ("In state %s", state_name[m_state])); #endif + DBUG_ASSERT(target_state <= STATE_COUNT); if (m_state <= target_state && target_state <= m_state + 1 && m_state < STATE_COUNT) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index 4b305e9a57a..d8510d7becd 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -250,6 +250,7 @@ finish_event_group(rpl_parallel_thread *rpt, uint64 sub_id, entry->stop_on_error_sub_id == (uint64)ULONGLONG_MAX) entry->stop_on_error_sub_id= sub_id; mysql_mutex_unlock(&entry->LOCK_parallel_entry); +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("hold_worker_on_schedule", { if (entry->stop_on_error_sub_id < (uint64)ULONGLONG_MAX) { @@ -264,6 +265,7 @@ finish_event_group(rpl_parallel_thread *rpt, uint64 sub_id, STRING_WITH_LEN("now WAIT_FOR proceed_by_1000")); } }); +#endif if (rgi->killed_for_retry == rpl_group_info::RETRY_KILL_PENDING) wait_for_pending_deadlock_kill(thd, rgi); @@ -807,6 +809,7 @@ do_retry: rgi->killed_for_retry= rpl_group_info::RETRY_KILL_KILLED; thd->set_killed(KILL_CONNECTION); }); +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("rpl_parallel_simulate_wait_at_retry", { if (rgi->current_gtid.seq_no == 1001) { debug_sync_set_action(thd, @@ -814,6 +817,7 @@ do_retry: } DEBUG_SYNC(thd, "rpl_parallel_simulate_wait_at_retry"); }); +#endif rgi->cleanup_context(thd, 1); wait_for_pending_deadlock_kill(thd, rgi); @@ -1237,6 +1241,7 @@ handle_rpl_parallel_thread(void *arg) bool did_enter_cond= false; PSI_stage_info old_stage; +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("hold_worker_on_schedule", { if (rgi->current_gtid.domain_id == 0 && rgi->current_gtid.seq_no == 100) { @@ -1251,6 +1256,7 @@ handle_rpl_parallel_thread(void *arg) STRING_WITH_LEN("now SIGNAL scheduled_gtid_0_x_100")); } }); +#endif if(unlikely(thd->wait_for_commit_ptr) && group_rgi != NULL) { @@ -2437,11 +2443,13 @@ rpl_parallel_thread * rpl_parallel_entry::choose_thread_internal(uint idx, unlock_or_exit_cond(rli->sql_driver_thd, &thr->LOCK_rpl_thread, did_enter_cond, old_stage); my_error(ER_CONNECTION_KILLED, MYF(0)); +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("rpl_parallel_wait_queue_max", { debug_sync_set_action(rli->sql_driver_thd, STRING_WITH_LEN("now SIGNAL wait_queue_killed")); };); +#endif slave_output_error_info(rgi, rli->sql_driver_thd); return NULL; } @@ -2459,11 +2467,13 @@ rpl_parallel_thread * rpl_parallel_entry::choose_thread_internal(uint idx, Because debug_sync changes the thd->mysys_var->current_mutex, and this can cause THD::awake to use the wrong mutex. */ +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("rpl_parallel_wait_queue_max", { debug_sync_set_action(rli->sql_driver_thd, STRING_WITH_LEN("now SIGNAL wait_queue_ready")); };); +#endif rli->sql_driver_thd->ENTER_COND(&thr->COND_rpl_thread_queue, &thr->LOCK_rpl_thread, &stage_waiting_for_room_in_worker_thread, @@ -2625,11 +2635,13 @@ rpl_parallel::wait_for_done(THD *thd, Relay_log_info *rli) } } } +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("rpl_parallel_wait_for_done_trigger", { debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL wait_for_done_waiting")); };); +#endif global_rpl_thread_pool.copy_pool_for_pfs(rli); /* diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 7da296b47d9..6266acf7805 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2007, 2013, Oracle and/or its affiliates. - Copyright (c) 2008, 2019, MariaDB Corporation. + Copyright (c) 2008, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -319,7 +319,9 @@ unpack_row(rpl_group_info *rgi, normal unpack operation. */ uint16 const metadata= tabledef->field_metadata(i); - IF_DBUG(uchar const *const old_pack_ptr= pack_ptr;,) +#ifdef DBUG_TRACE + uchar const *const old_pack_ptr= pack_ptr; +#endif pack_ptr= f->unpack(f->ptr, pack_ptr, row_end, metadata); DBUG_PRINT("debug", ("field: %s; metadata: 0x%x;" diff --git a/sql/semisync_master.cc b/sql/semisync_master.cc index 0e72ff441c4..b57fc199826 100644 --- a/sql/semisync_master.cc +++ b/sql/semisync_master.cc @@ -1,6 +1,6 @@ /* Copyright (C) 2007 Google Inc. Copyright (c) 2008, 2013, Oracle and/or its affiliates. - Copyright (c) 2011, 2016, MariaDB + Copyright (c) 2011, 2022, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -275,12 +275,16 @@ void Active_tranx::clear_active_tranx_nodes(const char *log_file_name, Tranx_node *curr_node, *next_node; /* Delete all transaction nodes before the confirmation point. */ +#ifdef DBUG_TRACE int n_frees = 0; +#endif curr_node = m_trx_front; while (curr_node != new_front) { next_node = curr_node->next; +#ifdef DBUG_TRACE n_frees++; +#endif /* Remove the node from the hash table. */ unsigned int hash_val = get_hash_value(curr_node->log_name, curr_node->log_pos); diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 51e6fdc372b..1338d85865f 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -3389,25 +3389,25 @@ ER_NONEXISTING_GRANT 42000 swe "Det finns inget privilegium definierat för användare '%-.48s' på '%-.64s'" ukr "Повноважень не визначено для користувача '%-.48s' з хосту '%-.64s'" ER_TABLEACCESS_DENIED_ERROR 42000 - chi "%-.100T 命令的权限拒绝用户 '%s'@'%s' 用在表 '%-.192s'" - cze "%-.100T příkaz nepřístupný pro uživatele: '%s'@'%s' pro tabulku '%-.192s'" - dan "%-.100T-kommandoen er ikke tilladt for brugeren '%s'@'%s' for tabellen '%-.192s'" - eng "%-.100T command denied to user '%s'@'%s' for table '%-.192s'" - est "%-.100T käsk ei ole lubatud kasutajale '%s'@'%s' tabelis '%-.192s'" - fre "La commande '%-.100T' est interdite à l'utilisateur: '%s'@'%s' sur la table '%-.192s'" - ger "%-.100T Befehl nicht erlaubt für Benutzer '%s'@'%s' auf Tabelle '%-.192s'" - hun "%-.100T parancs a '%s'@'%s' felhasznalo szamara nem engedelyezett a '%-.192s' tablaban" - ita "Comando %-.100T negato per l'utente: '%s'@'%s' sulla tabella '%-.192s'" - jpn "コマンド %-.100T は ユーザー '%s'@'%s' ,テーブル '%-.192s' に対して許可されていません" - kor "'%-.100T' 명령은 다음 사용자에게 거부되었습니다. : '%s'@'%s' for 테이블 '%-.192s'" - nla "%-.100T commando geweigerd voor gebruiker: '%s'@'%s' voor tabel '%-.192s'" - por "Comando '%-.100T' negado para o usuário '%s'@'%s' na tabela '%-.192s'" - rum "Comanda %-.100T interzisa utilizatorului: '%s'@'%s' pentru tabela '%-.192s'" - rus "Команда %-.100T запрещена пользователю '%s'@'%s' для таблицы '%-.192s'" - serbian "%-.100T komanda zabranjena za korisnika '%s'@'%s' za tabelu '%-.192s'" - spa "%-.100T comando denegado a usuario '%s'@'%s' para la tabla '%-.192s'" - swe "%-.100T ej tillåtet för '%s'@'%s' för tabell '%-.192s'" - ukr "%-.100T команда заборонена користувачу: '%s'@'%s' у таблиці '%-.192s'" + chi "%-.100T 命令的权限拒绝用户 '%s'@'%s' 用在表 %`s.%`s" + cze "%-.100T příkaz nepřístupný pro uživatele: '%s'@'%s' pro tabulku %`s.%`s" + dan "%-.100T-kommandoen er ikke tilladt for brugeren '%s'@'%s' for tabellen %`s.%`s" + nla "%-.100T commando geweigerd voor gebruiker: '%s'@'%s' voor tabel %`s.%`s" + eng "%-.100T command denied to user '%s'@'%s' for table %`s.%`s" + est "%-.100T käsk ei ole lubatud kasutajale '%s'@'%s' tabelis %`s.%`s" + fre "La commande '%-.100T' est interdite à l'utilisateur: '%s'@'%s' sur la table %`s.%`s" + ger "%-.100T Befehl nicht erlaubt für Benutzer '%s'@'%s' auf Tabelle %`s.%`s" + hun "%-.100T parancs a '%s'@'%s' felhasznalo szamara nem engedelyezett a %`s.%`s tablaban" + ita "Comando %-.100T negato per l'utente: '%s'@'%s' sulla tabella %`s.%`s" + jpn "コマンド %-.100T は ユーザー '%s'@'%s' ,テーブル %`s.%`s に対して許可されていません" + kor "'%-.100T' 명령은 다음 사용자에게 거부되었습니다. : '%s'@'%s' for 테이블 %`s.%`s" + por "Comando '%-.100T' negado para o usuário '%s'@'%s' na tabela %`s.%`s" + rum "Comanda %-.100T interzisa utilizatorului: '%s'@'%s' pentru tabela %`s.%`s" + rus "Команда %-.100T запрещена пользователю '%s'@'%s' для таблицы %`s.%`s" + serbian "%-.100T komanda zabranjena za korisnika '%s'@'%s' za tabelu %`s.%`s" + spa "%-.100T comando denegado a usuario '%s'@'%s' para la tabla %`s.%`s" + swe "%-.100T ej tillåtet för '%s'@'%s' för tabell %`s.%`s" + ukr "%-.100T команда заборонена користувачу: '%s'@'%s' у таблиці %`s.%`s" ER_COLUMNACCESS_DENIED_ERROR 42000 chi "%-.32s 命令的权限拒绝用户 '%s'@'%s' 用在列 '%-.192s' 在表 '%-.192s'" cze "%-.32s příkaz nepřístupný pro uživatele: '%s'@'%s' pro sloupec '%-.192s' v tabulce '%-.192s'" diff --git a/sql/slave.cc b/sql/slave.cc index 26743e1c781..e39efcc6bbc 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3882,12 +3882,14 @@ apply_event_and_update_pos_apply(Log_event* ev, THD* thd, rpl_group_info *rgi, Relay_log_info* rli= rgi->rli; DBUG_ENTER("apply_event_and_update_pos_apply"); +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("inject_slave_sql_before_apply_event", { DBUG_ASSERT(!debug_sync_set_action (thd, STRING_WITH_LEN("now WAIT_FOR continue"))); DBUG_SET_INITIAL("-d,inject_slave_sql_before_apply_event"); };); +#endif if (reason == Log_event::EVENT_SKIP_NOT) exec_res= ev->apply_event(rgi); @@ -3916,7 +3918,7 @@ apply_event_and_update_pos_apply(Log_event* ev, THD* thd, rpl_group_info *rgi, } #endif -#ifndef DBUG_OFF +#ifdef DBUG_TRACE /* This only prints information to the debug trace. @@ -3946,7 +3948,7 @@ apply_event_and_update_pos_apply(Log_event* ev, THD* thd, rpl_group_info *rgi, thd->rgi_slave->get_finish_event_group_called()) DBUG_RETURN(exec_res ? 1 : 0); int error= ev->update_pos(rgi); - #ifndef DBUG_OFF +#ifdef DBUG_TRACE DBUG_PRINT("info", ("update_pos error = %d", error)); if (!rli->belongs_to_client()) { @@ -4528,6 +4530,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, #ifdef WITH_WSREP wsrep_after_statement(thd); #endif /* WITH_WSREP */ +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF( "pause_sql_thread_on_fde", if (ev && typ == FORMAT_DESCRIPTION_EVENT) { @@ -4536,6 +4539,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, STRING_WITH_LEN( "now SIGNAL paused_on_fde WAIT_FOR sql_thread_continue"))); }); +#endif DBUG_RETURN(exec_res); } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 8465eef5449..bb1ebb04e26 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1904,7 +1904,7 @@ sp_head::execute_trigger(THD *thd, my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), priv_desc, thd->security_ctx->priv_user, thd->security_ctx->host_or_ip, - table_name->str); + db_name->str, table_name->str); m_security_ctx.restore_security_context(thd, save_ctx); DBUG_RETURN(TRUE); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index becf519901a..95ca8b233ce 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7134,7 +7134,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, table_list->grant.want_privilege); my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), command, thd->security_ctx->priv_user, - thd->security_ctx->host_or_ip, table_list->alias.str); + thd->security_ctx->host_or_ip, table_list->db.str, + table_list->alias.str); DBUG_RETURN(-1); } } @@ -8186,8 +8187,8 @@ bool grant_reload(THD *thd) @see check_table_access @note - This functions assumes that either number of tables to be inspected - by it is limited explicitly (i.e. is is not UINT_MAX) or table list + This function assumes that either number of tables to be inspected + by it is limited explicitly (i.e. is not UINT_MAX) or table list used and thd->lex->query_tables_own_last value correspond to each other (the latter should be either 0 or point to next_global member of one of elements of this table list). @@ -8392,7 +8393,7 @@ err: my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), command, sctx->priv_user, - sctx->host_or_ip, + sctx->host_or_ip, tl ? tl->db.str : "unknown", tl ? tl->get_table_name() : "unknown"); } DBUG_RETURN(TRUE); @@ -8576,7 +8577,7 @@ bool check_grant_all_columns(THD *thd, privilege_t want_access_arg, Security_context *sctx= thd->security_ctx; privilege_t want_access(NO_ACL); const char *table_name= NULL; - const char* db_name; + const char* db_name= NULL; GRANT_INFO *grant; GRANT_TABLE *UNINIT_VAR(grant_table); GRANT_TABLE *UNINIT_VAR(grant_table_role); @@ -8665,7 +8666,7 @@ err: if (using_column_privileges) my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), command, sctx->priv_user, - sctx->host_or_ip, table_name); + sctx->host_or_ip, db_name, table_name); else my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), command, diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index d609fff5487..a0d32145abe 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -409,7 +409,7 @@ void field_real::add() if ((decs = decimals()) >= FLOATING_POINT_DECIMALS) { - length= sprintf(buff, "%g", num); + length= snprintf(buff, sizeof(buff), "%g", num); if (rint(num) != num) max_notzero_dec_len = 1; } @@ -420,7 +420,7 @@ void field_real::add() snprintf(buff, sizeof(buff)-1, "%-.*f", (int) decs, num); length = (uint) strlen(buff); #else - length= sprintf(buff, "%-.*f", (int) decs, num); + length= snprintf(buff, sizeof(buff), "%-.*f", (int) decs, num); #endif // We never need to check further than this @@ -814,32 +814,32 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows) if (can_be_still_num) { if (num_info.is_float) - sprintf(buff, "DOUBLE"); // number was like 1e+50... TODO: + snprintf(buff, sizeof(buff), "DOUBLE"); // number was like 1e+50... TODO: else if (num_info.decimals) // DOUBLE(%d,%d) sometime { if (num_info.dval > -FLT_MAX && num_info.dval < FLT_MAX) - sprintf(buff, "FLOAT(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals); + snprintf(buff, sizeof(buff), "FLOAT(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals); else - sprintf(buff, "DOUBLE(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals); + snprintf(buff, sizeof(buff), "DOUBLE(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals); } else if (ev_num_info.llval >= -128 && ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ? 255 : 127)) - sprintf(buff, "TINYINT(%d)", num_info.integers); + snprintf(buff, sizeof(buff), "TINYINT(%d)", num_info.integers); else if (ev_num_info.llval >= INT_MIN16 && ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ? UINT_MAX16 : INT_MAX16)) - sprintf(buff, "SMALLINT(%d)", num_info.integers); + snprintf(buff, sizeof(buff), "SMALLINT(%d)", num_info.integers); else if (ev_num_info.llval >= INT_MIN24 && ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ? UINT_MAX24 : INT_MAX24)) - sprintf(buff, "MEDIUMINT(%d)", num_info.integers); + snprintf(buff, sizeof(buff), "MEDIUMINT(%d)", num_info.integers); else if (ev_num_info.llval >= INT_MIN32 && ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ? UINT_MAX32 : INT_MAX32)) - sprintf(buff, "INT(%d)", num_info.integers); + snprintf(buff, sizeof(buff), "INT(%d)", num_info.integers); else - sprintf(buff, "BIGINT(%d)", num_info.integers); + snprintf(buff, sizeof(buff), "BIGINT(%d)", num_info.integers); answer->append(buff, (uint) strlen(buff)); if (ev_num_info.llval >= 0 && ev_num_info.min_dval >= 0) answer->append(STRING_WITH_LEN(" UNSIGNED")); @@ -857,12 +857,12 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows) } else if ((max_length * (total_rows - nulls)) < (sum + total_rows)) { - sprintf(buff, "CHAR(%d)", (int) max_length); + snprintf(buff, sizeof(buff), "CHAR(%d)", (int) max_length); answer->append(buff, (uint) strlen(buff)); } else { - sprintf(buff, "VARCHAR(%d)", (int) max_length); + snprintf(buff, sizeof(buff), "VARCHAR(%d)", (int) max_length); answer->append(buff, (uint) strlen(buff)); } } @@ -901,18 +901,18 @@ void field_real::get_opt_type(String *answer, 0 : (item->decimals + 1)); if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127)) - sprintf(buff, "TINYINT(%d)", len); + snprintf(buff, sizeof(buff), "TINYINT(%d)", len); else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ? UINT_MAX16 : INT_MAX16)) - sprintf(buff, "SMALLINT(%d)", len); + snprintf(buff, sizeof(buff), "SMALLINT(%d)", len); else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ? UINT_MAX24 : INT_MAX24)) - sprintf(buff, "MEDIUMINT(%d)", len); + snprintf(buff, sizeof(buff), "MEDIUMINT(%d)", len); else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ? UINT_MAX32 : INT_MAX32)) - sprintf(buff, "INT(%d)", len); + snprintf(buff, sizeof(buff), "INT(%d)", len); else - sprintf(buff, "BIGINT(%d)", len); + snprintf(buff, sizeof(buff), "BIGINT(%d)", len); answer->append(buff, (uint) strlen(buff)); if (min_arg >= 0) answer->append(STRING_WITH_LEN(" UNSIGNED")); @@ -927,10 +927,10 @@ void field_real::get_opt_type(String *answer, else { if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX) - sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len, + snprintf(buff, sizeof(buff), "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len, max_notzero_dec_len); else - sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len, + snprintf(buff, sizeof(buff), "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len, max_notzero_dec_len); answer->append(buff, (uint) strlen(buff)); } @@ -949,18 +949,18 @@ void field_longlong::get_opt_type(String *answer, char buff[MAX_FIELD_WIDTH]; if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127)) - sprintf(buff, "TINYINT(%d)", (int) max_length); + snprintf(buff, sizeof(buff), "TINYINT(%d)", (int) max_length); else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ? UINT_MAX16 : INT_MAX16)) - sprintf(buff, "SMALLINT(%d)", (int) max_length); + snprintf(buff, sizeof(buff), "SMALLINT(%d)", (int) max_length); else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ? UINT_MAX24 : INT_MAX24)) - sprintf(buff, "MEDIUMINT(%d)", (int) max_length); + snprintf(buff, sizeof(buff), "MEDIUMINT(%d)", (int) max_length); else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ? UINT_MAX32 : INT_MAX32)) - sprintf(buff, "INT(%d)", (int) max_length); + snprintf(buff, sizeof(buff), "INT(%d)", (int) max_length); else - sprintf(buff, "BIGINT(%d)", (int) max_length); + snprintf(buff, sizeof(buff), "BIGINT(%d)", (int) max_length); answer->append(buff, (uint) strlen(buff)); if (min_arg >= 0) answer->append(STRING_WITH_LEN(" UNSIGNED")); @@ -980,15 +980,15 @@ void field_ulonglong::get_opt_type(String *answer, char buff[MAX_FIELD_WIDTH]; if (max_arg < 256) - sprintf(buff, "TINYINT(%d) UNSIGNED", (int) max_length); + snprintf(buff, sizeof(buff), "TINYINT(%d) UNSIGNED", (int) max_length); else if (max_arg <= ((2 * INT_MAX16) + 1)) - sprintf(buff, "SMALLINT(%d) UNSIGNED", (int) max_length); + snprintf(buff, sizeof(buff), "SMALLINT(%d) UNSIGNED", (int) max_length); else if (max_arg <= ((2 * INT_MAX24) + 1)) - sprintf(buff, "MEDIUMINT(%d) UNSIGNED", (int) max_length); + snprintf(buff, sizeof(buff), "MEDIUMINT(%d) UNSIGNED", (int) max_length); else if (max_arg < (((ulonglong) 1) << 32)) - sprintf(buff, "INT(%d) UNSIGNED", (int) max_length); + snprintf(buff, sizeof(buff), "INT(%d) UNSIGNED", (int) max_length); else - sprintf(buff, "BIGINT(%d) UNSIGNED", (int) max_length); + snprintf(buff, sizeof(buff), "BIGINT(%d) UNSIGNED", (int) max_length); // if item is FIELD_ITEM, it _must_be_ Field_num in this class answer->append(buff, (uint) strlen(buff)); if (item->type() == Item::FIELD_ITEM && @@ -1009,7 +1009,7 @@ void field_decimal::get_opt_type(String *answer, my_decimal_set_zero(&zero); my_bool is_unsigned= (zero.cmp(&min_arg) >= 0); - length= sprintf(buff, "DECIMAL(%d, %d)", + length= snprintf(buff, sizeof(buff), "DECIMAL(%d, %d)", (int) (max_length - (item->decimals ? 1 : 0)), item->decimals); if (is_unsigned) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 54296af5a0b..53999ba4dc2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2075,6 +2075,11 @@ retry_share: table_list->alias.str); goto err_lock; } + + /* Open view */ + if (mysql_make_view(thd, share, table_list, false)) + goto err_lock; + /* This table is a view. Validate its metadata version: in particular, that it was a view when the statement was prepared. @@ -2082,10 +2087,6 @@ retry_share: if (check_and_update_table_version(thd, table_list, share)) goto err_lock; - /* Open view */ - if (mysql_make_view(thd, share, table_list, false)) - goto err_lock; - /* TODO: Don't free this */ tdc_release_share(share); @@ -2991,7 +2992,7 @@ static bool inject_reprepare(THD *thd) @sa Execute_observer @sa check_prepared_statement() to see cases when an observer is installed - @sa TABLE_LIST::is_table_ref_id_equal() + @sa TABLE_LIST::is_the_same_definition() @sa TABLE_SHARE::get_table_ref_id() @param[in] thd used to report errors @@ -3014,7 +3015,7 @@ check_and_update_table_version(THD *thd, created with TABLE_LIST::init_one_table() have a short life time and aren't linked anywhere. */ - if (tables->prev_global && !tables->is_table_ref_id_equal(table_share)) + if (tables->prev_global && !tables->is_the_same_definition(thd, table_share)) { if (thd->m_reprepare_observer && thd->m_reprepare_observer->report_error(thd)) @@ -3120,7 +3121,9 @@ bool tdc_open_view(THD *thd, TABLE_LIST *table_list, uint flags) DBUG_ASSERT(share->is_view); - if (flags & CHECK_METADATA_VERSION) + err= mysql_make_view(thd, share, table_list, (flags & OPEN_VIEW_NO_PARSE)); + + if (!err && (flags & CHECK_METADATA_VERSION)) { /* Check TABLE_SHARE-version of view only if we have been instructed to do @@ -3135,7 +3138,6 @@ bool tdc_open_view(THD *thd, TABLE_LIST *table_list, uint flags) goto ret; } - err= mysql_make_view(thd, share, table_list, (flags & OPEN_VIEW_NO_PARSE)); ret: tdc_release_share(share); @@ -7833,10 +7835,12 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, Item *item; List_iterator<Item> it(fields); Query_arena *arena, backup; + uint *with_wild= returning_field ? &(thd->lex->returning()->with_wild) : + &(select_lex->with_wild); DBUG_ENTER("setup_wild"); - if (!select_lex->with_wild) - DBUG_RETURN(0); + if (!(*with_wild)) + DBUG_RETURN(0); /* Don't use arena if we are not in prepared statements or stored procedures @@ -7845,7 +7849,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, arena= thd->activate_stmt_arena_if_needed(&backup); thd->lex->current_select->cur_pos_in_select_list= 0; - while (select_lex->with_wild && (item= it++)) + while (*with_wild && (item= it++)) { if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name.str == star_clex_str.str && @@ -7883,12 +7887,12 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, */ sum_func_list->elements+= fields.elements - elem; } - select_lex->with_wild--; + (*with_wild)--; } else thd->lex->current_select->cur_pos_in_select_list++; } - DBUG_ASSERT(!select_lex->with_wild); + DBUG_ASSERT(!(*with_wild)); thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS; if (arena) thd->restore_active_arena(arena, &backup); @@ -8559,19 +8563,20 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, tables->is_natural_join); DBUG_ASSERT(item->type() == Item::FIELD_ITEM); Item_field *fld= (Item_field*) item; + const char *field_db_name= field_iterator.get_db_name(); const char *field_table_name= field_iterator.get_table_name(); if (!tables->schema_table && !(fld->have_privileges= (get_column_grant(thd, field_iterator.grant(), - field_iterator.get_db_name(), + field_db_name, field_table_name, fld->field_name.str) & VIEW_ANY_ACL))) { my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "ANY", thd->security_ctx->priv_user, thd->security_ctx->host_or_ip, - field_table_name); + field_db_name, field_table_name); DBUG_RETURN(TRUE); } } diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index c229655e915..e71c7015238 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -43,14 +43,13 @@ static int check_event_type(int type, Relay_log_info *rli) */ if (fd_event && fd_event->event_type_permutation) { - IF_DBUG({ - int new_type= fd_event->event_type_permutation[type]; - DBUG_PRINT("info", - ("converting event type %d to %d (%s)", - type, new_type, - Log_event::get_type_str((Log_event_type)new_type))); - }, - (void)0); +#ifdef DBUG_TRACE + int new_type= fd_event->event_type_permutation[type]; + DBUG_PRINT("info", + ("converting event type %d to %d (%s)", + type, new_type, + Log_event::get_type_str((Log_event_type)new_type))); +#endif type= fd_event->event_type_permutation[type]; } diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 9e8f0a8fe68..81ea002ce32 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -4770,7 +4770,7 @@ void Query_cache::cache_dump() void Query_cache::queries_dump() { - +#ifdef DBUG_TRACE if (!initialized) { DBUG_PRINT("qcache", ("Query Cache not initialized")); @@ -4831,11 +4831,13 @@ void Query_cache::queries_dump() DBUG_PRINT("qcache", ("no queries in list")); } DBUG_PRINT("qcache", ("------------------")); +#endif } void Query_cache::tables_dump() { +#ifdef DBUG_TRACE if (!initialized || query_cache_size == 0) { DBUG_PRINT("qcache", ("Query Cache not initialized")); @@ -4858,6 +4860,7 @@ void Query_cache::tables_dump() else DBUG_PRINT("qcache", ("no tables in list")); DBUG_PRINT("qcache", ("--------------------")); +#endif } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9e0762ff0be..68dfa249449 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -452,6 +452,7 @@ void thd_storage_lock_wait(THD *thd, long long value) extern "C" void *thd_get_ha_data(const THD *thd, const struct handlerton *hton) { + DBUG_ASSERT(thd == current_thd || mysql_mutex_is_owner(&thd->LOCK_thd_data)); return thd->ha_data[hton->slot].ha_ptr; } @@ -1520,6 +1521,8 @@ void THD::cleanup(void) wsrep_client_thread= false; #endif /* WITH_WSREP */ + DEBUG_SYNC(this, "THD_cleanup_after_set_killed"); + mysql_ha_cleanup(this); locked_tables_list.unlock_locked_tables(this); @@ -3935,6 +3938,7 @@ Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg, lex(lex_arg), db(null_clex_str) { + hr_prepare_time.val= 0, name= null_clex_str; } @@ -3951,6 +3955,7 @@ void Statement::set_statement(Statement *stmt) column_usage= stmt->column_usage; lex= stmt->lex; query_string= stmt->query_string; + hr_prepare_time= stmt->hr_prepare_time; } @@ -7403,7 +7408,7 @@ bool THD::binlog_for_noop_dml(bool transactional_table) } -#if !defined(DBUG_OFF) && !defined(_lint) +#if defined(DBUG_TRACE) && !defined(_lint) static const char * show_query_type(THD::enum_binlog_query_type qtype) { diff --git a/sql/sql_class.h b/sql/sql_class.h index c505ee68630..53d15e44b64 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -121,8 +121,8 @@ enum enum_slave_type_conversions { SLAVE_TYPE_CONVERSIONS_ALL_LOSSY, SLAVE_TYPE_CONVERSIONS_ALL_NON_LOSSY}; /* - MARK_COLUMNS_READ: A column is goind to be read. - MARK_COLUMNS_WRITE: A column is going to be written to. + COLUMNS_READ: A column is goind to be read. + COLUMNS_WRITE: A column is going to be written to. MARK_COLUMNS_READ: A column is goind to be read. A bit in read set is set to inform handler that the field is to be read. If field list contains duplicates, then @@ -1315,6 +1315,7 @@ public: LEX_CSTRING name; /* name for named prepared statements */ LEX *lex; // parse tree descriptor + my_hrtime_t hr_prepare_time; // time of preparation in microseconds /* Points to the query associated with this statement. It's const, but we need to declare it char * because all table handlers are written @@ -7332,7 +7333,12 @@ public: inline bool add_item_to_list(THD *thd, Item *item) { - bool res= thd->lex->current_select->add_item_to_list(thd, item); + bool res; + LEX *lex= thd->lex; + if (lex->current_select->parsing_place == IN_RETURNING) + res= lex->returning()->add_item_to_list(thd, item); + else + res= lex->current_select->add_item_to_list(thd, item); return res; } diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 445bc97a3b5..a526bfee2d2 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -410,9 +410,17 @@ bool With_element::check_dependencies_in_spec() { for (st_select_lex *sl= spec->first_select(); sl; sl= sl->next_select()) { - st_unit_ctxt_elem ctxt0= {NULL, owner->owner}; - st_unit_ctxt_elem ctxt1= {&ctxt0, spec}; - check_dependencies_in_select(sl, &ctxt1, false, &sl->with_dep); + if (owner->with_recursive) + { + st_unit_ctxt_elem ctxt0= {NULL, owner->owner}; + st_unit_ctxt_elem ctxt1= {&ctxt0, spec}; + check_dependencies_in_select(sl, &ctxt1, false, &sl->with_dep); + } + else + { + st_unit_ctxt_elem ctxt= {NULL, spec}; + check_dependencies_in_select(sl, &ctxt, false, &sl->with_dep); + } base_dep_map|= sl->with_dep; } return false; @@ -480,29 +488,50 @@ With_element *With_clause::find_table_def(TABLE_LIST *table, With_element *find_table_def_in_with_clauses(TABLE_LIST *tbl, st_unit_ctxt_elem *ctxt) { - With_element *barrier= NULL; + With_element *found= 0; for (st_unit_ctxt_elem *unit_ctxt_elem= ctxt; unit_ctxt_elem; unit_ctxt_elem= unit_ctxt_elem->prev) { st_select_lex_unit *unit= unit_ctxt_elem->unit; With_clause *with_clause= unit->with_clause; - if (with_clause && - (tbl->with= with_clause->find_table_def(tbl, barrier))) - return tbl->with; - barrier= NULL; - if (unit->with_element && !unit->with_element->get_owner()->with_recursive) + /* + First look for the table definition in the with clause attached to 'unit' + if there is any such clause. + */ + if (with_clause) { - /* - This unit is the specification if the with element unit->with_element. - The with element belongs to a with clause without the specifier RECURSIVE. - So when searching for the matching definition of tbl this with clause must - be looked up to this with element - */ - barrier= unit->with_element; + found= with_clause->find_table_def(tbl, NULL); + if (found) + break; + } + /* + If 'unit' is the unit that defines a with element then reset 'unit' + to the unit whose attached with clause contains this with element. + */ + With_element *with_elem= unit->with_element; + if (with_elem) + { + if (!(unit_ctxt_elem= unit_ctxt_elem->prev)) + break; + unit= unit_ctxt_elem->unit; + } + with_clause= unit->with_clause; + /* + Now look for the table definition in this with clause. If the with clause + contains RECURSIVE the search is performed through all CTE definitions in + clause, otherwise up to the definition of 'with_elem' unless it is NULL. + */ + if (with_clause) + { + found= with_clause->find_table_def(tbl, + with_clause->with_recursive ? + NULL : with_elem); + if (found) + break; } } - return NULL; + return found; } @@ -532,22 +561,30 @@ void With_element::check_dependencies_in_select(st_select_lex *sl, bool in_subq, table_map *dep_map) { - With_clause *with_clause= sl->get_with_clause(); + bool is_spec_select= sl->get_with_element() == this; + for (TABLE_LIST *tbl= sl->table_list.first; tbl; tbl= tbl->next_local) { - if (tbl->derived || tbl->nested_join) + if (tbl->with || tbl->derived || tbl->nested_join) continue; tbl->with_internal_reference_map= 0; /* - If there is a with clause attached to the unit containing sl - look first for the definition of tbl in this with clause. - If such definition is not found there look in the with - clauses of the upper levels. + Look first for the definition of tbl in the with clause to which + this with element belongs. If such definition is not found there + look in the with clauses of the upper levels via the context + chain of embedding with elements. If the definition of tbl is found somewhere in with clauses - then tbl->with is set to point to this definition + then tbl->with is set to point to this definition. */ - if (with_clause && !tbl->with) - tbl->with= with_clause->find_table_def(tbl, NULL); + if (is_spec_select) + { + With_clause *with_clause= sl->master_unit()->with_clause; + if (with_clause) + tbl->with= with_clause->find_table_def(tbl, NULL); + if (!tbl->with) + tbl->with= owner->find_table_def(tbl, + owner->with_recursive ? NULL : this); + } if (!tbl->with) tbl->with= find_table_def_in_with_clauses(tbl, ctxt); @@ -574,8 +611,7 @@ void With_element::check_dependencies_in_select(st_select_lex *sl, st_select_lex_unit *inner_unit= sl->first_inner_unit(); for (; inner_unit; inner_unit= inner_unit->next_unit()) { - if (!inner_unit->with_element) - check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map); + check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map); } } @@ -653,10 +689,14 @@ void With_element::check_dependencies_in_unit(st_select_lex_unit *unit, bool in_subq, table_map *dep_map) { + st_unit_ctxt_elem unit_ctxt_elem= {ctxt, unit}; if (unit->with_clause) - check_dependencies_in_with_clause(unit->with_clause, ctxt, in_subq, dep_map); + { + (void) unit->with_clause->check_dependencies(); + check_dependencies_in_with_clause(unit->with_clause, &unit_ctxt_elem, + in_subq, dep_map); + } in_subq |= unit->item != NULL; - st_unit_ctxt_elem unit_ctxt_elem= {ctxt, unit}; st_select_lex *sl= unit->first_select(); for (; sl; sl= sl->next_select()) { diff --git a/sql/sql_cte.h b/sql/sql_cte.h index 4cec1240d1f..e0fbd79803b 100644 --- a/sql/sql_cte.h +++ b/sql/sql_cte.h @@ -393,10 +393,24 @@ public: bool add_with_element(With_element *elem); /* Add this with clause to the list of with clauses used in the statement */ - void add_to_list(With_clause ** &last_next) + void add_to_list(With_clause **ptr, With_clause ** &last_next) { - *last_next= this; - last_next= &this->next_with_clause; + if (embedding_with_clause) + { + /* + An embedded with clause is always placed before the embedding one + in the list of with clauses used in the query. + */ + while (*ptr != embedding_with_clause) + ptr= &(*ptr)->next_with_clause; + *ptr= this; + next_with_clause= embedding_with_clause; + } + else + { + *last_next= this; + last_next= &this->next_with_clause; + } } st_select_lex_unit *get_owner() { return owner; } diff --git a/sql/sql_debug.h b/sql/sql_debug.h new file mode 100644 index 00000000000..cb4bfcec3ed --- /dev/null +++ b/sql/sql_debug.h @@ -0,0 +1,168 @@ +#ifndef SQL_DEBUG_INCLUDED +#define SQL_DEBUG_INCLUDED +/* + Copyright (c) 2022, MariaDB + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA +*/ + + +class Debug_key: public String +{ +public: + Debug_key() { }; + void print(THD *thd) const + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_UNKNOWN_ERROR, "DBUG: %.*s", length(), ptr()); + } + + bool append_key_type(ha_base_keytype type) + { + static LEX_CSTRING names[20]= + { + STRING_WITH_LEN("END"), + STRING_WITH_LEN("TEXT"), + STRING_WITH_LEN("BINARY"), + STRING_WITH_LEN("SHORT_INT"), + STRING_WITH_LEN("LONG_INT"), + STRING_WITH_LEN("FLOAT"), + STRING_WITH_LEN("DOUBLE"), + STRING_WITH_LEN("NUM"), + STRING_WITH_LEN("USHORT_INT"), + STRING_WITH_LEN("ULONG_INT"), + STRING_WITH_LEN("LONGLONG"), + STRING_WITH_LEN("ULONGLONG"), + STRING_WITH_LEN("INT24"), + STRING_WITH_LEN("UINT24"), + STRING_WITH_LEN("INT8"), + STRING_WITH_LEN("VARTEXT1"), + STRING_WITH_LEN("VARBINARY1"), + STRING_WITH_LEN("VARTEXT2"), + STRING_WITH_LEN("VARBINARY2"), + STRING_WITH_LEN("BIT") + }; + if ((uint) type >= array_elements(names)) + return append(STRING_WITH_LEN("???")); + return append(names[(uint) type]); + } + + bool append_KEY_flag_names(ulong flags) + { + static LEX_CSTRING names[17]= + { + STRING_WITH_LEN("HA_NOSAME"), + STRING_WITH_LEN("HA_PACK_KEY"), + STRING_WITH_LEN("HA_SPACE_PACK_USED"), + STRING_WITH_LEN("HA_VAR_LENGTH_KEY"), + STRING_WITH_LEN("HA_AUTO_KEY"), + STRING_WITH_LEN("HA_BINARY_PACK_KEY"), + STRING_WITH_LEN("HA_NULL_PART_KEY"), + STRING_WITH_LEN("HA_FULLTEXT"), + STRING_WITH_LEN("HA_UNIQUE_CHECK"), + STRING_WITH_LEN("HA_SORT_ALLOWS_SAME"), + STRING_WITH_LEN("HA_SPATIAL"), + STRING_WITH_LEN("HA_NULL_ARE_EQUAL"), + STRING_WITH_LEN("HA_GENERATED_KEY"), + STRING_WITH_LEN("HA_USES_COMMENT"), + STRING_WITH_LEN("HA_USES_PARSER"), + STRING_WITH_LEN("HA_USES_BLOCK_SIZE"), + STRING_WITH_LEN("HA_KEY_HAS_PART_KEY_SEG") + }; + return append_flag32_names((uint) flags, names, array_elements(names)); + } + + bool append_HA_KEYSEG_flag_names(uint32 flags) + { + static LEX_CSTRING names[]= + { + STRING_WITH_LEN("HA_SPACE_PACK"), // 1 + STRING_WITH_LEN("??? 2 ???"), // 2 + STRING_WITH_LEN("HA_PART_KEY_SEG"), // 4 + STRING_WITH_LEN("HA_VAR_LENGTH_PART"), // 8 + STRING_WITH_LEN("HA_NULL_PART"), // 16 + STRING_WITH_LEN("HA_BLOB_PART"), // 32 + STRING_WITH_LEN("HA_SWAP_KEY"), // 64 + STRING_WITH_LEN("HA_REVERSE_SORT"), // 128 + STRING_WITH_LEN("HA_NO_SORT"), // 256 + STRING_WITH_LEN("??? 512 ???"), // 512 + STRING_WITH_LEN("HA_BIT_PART"), // 1024 + STRING_WITH_LEN("HA_CAN_MEMCMP") // 2048 + }; + return append_flag32_names(flags, names, array_elements(names)); + } + + bool append_HA_KEYSEG_type(ha_base_keytype type) + { + return append_ulonglong(type) || + append(' ') || + append_key_type(type); + } + + bool append_HA_KEYSEG_flags(uint32 flags) + { + return append_hex_uint32(flags) || + append(' ') || + append_HA_KEYSEG_flag_names(flags); + } + + bool append_key(const LEX_CSTRING &name, uint32 flags) + { + return + append_name_value(Lex_cstring(STRING_WITH_LEN("name")), name, '`') || + append(Lex_cstring(STRING_WITH_LEN(" flags="))) || + append_hex_uint32(flags) || + append(' ') || + append_KEY_flag_names(flags); + } + + bool append_KEY(const KEY &key) + { + return append_key(key.name, key.flags); + } + + static void print_keysegs(THD *thd, const HA_KEYSEG *seg, uint count) + { + for (uint i= 0; i < count; i++) + { + Debug_key tmp; + if (!tmp.append(Lex_cstring(STRING_WITH_LEN(" seg["))) && + !tmp.append_ulonglong(i) && + !tmp.append(Lex_cstring(STRING_WITH_LEN("].type="))) && + !tmp.append_HA_KEYSEG_type((ha_base_keytype) seg[i].type)) + tmp.print(thd); + tmp.length(0); + if (!tmp.append(Lex_cstring(STRING_WITH_LEN(" seg["))) && + !tmp.append_ulonglong(i) && + !tmp.append(Lex_cstring(STRING_WITH_LEN("].flag="))) && + !tmp.append_HA_KEYSEG_flags(seg[i].flag)) + tmp.print(thd); + } + } + + static void print_keys(THD *thd, const char *where, + const KEY *keys, uint key_count) + { + for (uint i= 0; i < key_count; i++) + { + Debug_key tmp; + if (!tmp.append(where, strlen(where)) && !tmp.append_KEY(keys[i])) + tmp.print(thd); + } + } +}; + + +#endif // SQL_DEBUG_INCLUDED diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 24e7633a6fe..2c91b4cc9c6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3048,23 +3048,9 @@ void st_select_lex_node::include_down(st_select_lex_node *upper) } -void st_select_lex_node::add_slave(st_select_lex_node *slave_arg) +void st_select_lex_node::attach_single(st_select_lex_node *slave_arg) { - for (; slave; slave= slave->next) - if (slave == slave_arg) - return; - - if (slave) - { - st_select_lex_node *slave_arg_slave= slave_arg->slave; - /* Insert in the front of list of slaves if any. */ - slave_arg->include_neighbour(slave); - /* include_neighbour() sets slave_arg->slave=0, restore it. */ - slave_arg->slave= slave_arg_slave; - /* Count on include_neighbour() setting the master. */ - DBUG_ASSERT(slave_arg->master == this); - } - else + DBUG_ASSERT(slave == 0); { slave= slave_arg; slave_arg->master= this; @@ -9647,7 +9633,8 @@ Item *LEX::create_item_qualified_asterisk(THD *thd, null_clex_str, *name, star_clex_str))) return NULL; - current_select->with_wild++; + current_select->parsing_place == IN_RETURNING ? + thd->lex->returning()->with_wild++ : current_select->with_wild++; return item; } @@ -9662,7 +9649,8 @@ Item *LEX::create_item_qualified_asterisk(THD *thd, if (!(item= new (thd->mem_root) Item_field(thd, current_context(), schema, *b, star_clex_str))) return NULL; - current_select->with_wild++; + current_select->parsing_place == IN_RETURNING ? + thd->lex->returning()->with_wild++ : current_select->with_wild++; return item; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index cbe76849ea7..14629052c2e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -769,7 +769,7 @@ public: inline st_select_lex_node* get_master() { return master; } void include_down(st_select_lex_node *upper); - void add_slave(st_select_lex_node *slave_arg); + void attach_single(st_select_lex_node *slave_arg); void include_neighbour(st_select_lex_node *before); void link_chain_down(st_select_lex_node *first); void link_neighbour(st_select_lex_node *neighbour) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8b8ab430308..75e1a00232a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7313,7 +7313,6 @@ bool check_fk_parent_table_access(THD *thd, if (key->type == Key::FOREIGN_KEY) { TABLE_LIST parent_table; - bool is_qualified_table_name; Foreign_key *fk_key= (Foreign_key *)key; LEX_CSTRING db_name; LEX_CSTRING table_name= { fk_key->ref_table.str, @@ -7330,7 +7329,6 @@ bool check_fk_parent_table_access(THD *thd, if (fk_key->ref_db.str) { - is_qualified_table_name= true; if (!(db_name.str= (char *) thd->memdup(fk_key->ref_db.str, fk_key->ref_db.length+1))) return true; @@ -7352,7 +7350,6 @@ bool check_fk_parent_table_access(THD *thd, if (!(db_name.str= (char *) thd->memdup(create_db, db_name.length+1))) return true; - is_qualified_table_name= true; if (check_db_name((LEX_STRING*) &db_name)) { @@ -7364,8 +7361,6 @@ bool check_fk_parent_table_access(THD *thd, { if (thd->lex->copy_db_to(&db_name)) return true; - else - is_qualified_table_name= false; } } @@ -7391,22 +7386,11 @@ bool check_fk_parent_table_access(THD *thd, if (check_some_access(thd, privileges, &parent_table) || parent_table.grant.want_privilege) { - if (is_qualified_table_name) - { - const size_t qualified_table_name_len= NAME_LEN + 1 + NAME_LEN + 1; - char *qualified_table_name= (char *) thd->alloc(qualified_table_name_len); - - my_snprintf(qualified_table_name, qualified_table_name_len, "%s.%s", - db_name.str, table_name.str); - table_name.str= qualified_table_name; - } - my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), - "REFERENCES", - thd->security_ctx->priv_user, - thd->security_ctx->host_or_ip, - table_name.str); - + "REFERENCES", + thd->security_ctx->priv_user, + thd->security_ctx->host_or_ip, + db_name.str, table_name.str); return true; } } @@ -7885,6 +7869,7 @@ static bool wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, thd->lex->sql_command != SQLCOM_SELECT && thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit) { +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("sync.wsrep_retry_autocommit", { const char act[]= @@ -7893,6 +7878,7 @@ static bool wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, "WAIT_FOR wsrep_retry_autocommit_continue"; DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); }); +#endif WSREP_DEBUG("wsrep retrying AC query: %lu %s", thd->wsrep_retry_counter, wsrep_thd_query(thd)); @@ -9213,7 +9199,7 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ tmp= find_thread_by_id(id, type == KILL_TYPE_QUERY); if (!tmp) DBUG_RETURN(error); - + DEBUG_SYNC(thd, "found_killee"); if (tmp->get_command() != COM_DAEMON) { /* diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index fbb36f7171f..2f9e8eb81ff 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -4505,6 +4505,8 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) if (thd->spcont == NULL) general_log_write(thd, COM_STMT_PREPARE, query(), query_length()); } + // The same format as for triggers to compare + hr_prepare_time= my_hrtime(); DBUG_RETURN(error); } @@ -4598,8 +4600,8 @@ Prepared_statement::execute_loop(String *expanded_query, uchar *packet_end) { Reprepare_observer reprepare_observer; - bool error; int reprepare_attempt= 0; + bool error; iterations= FALSE; /* diff --git a/sql/sql_priv.h b/sql/sql_priv.h index 9afbd4c4927..381ac26f3a3 100644 --- a/sql/sql_priv.h +++ b/sql/sql_priv.h @@ -379,6 +379,7 @@ enum enum_parsing_place BEFORE_OPT_LIST, AFTER_LIST, FOR_LOOP_BOUND, + IN_RETURNING, PARSING_PLACE_SIZE /* always should be the last */ }; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 352d5ab8ae9..d338dc302e6 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2018, Oracle and/or its affiliates. - Copyright (c) 2008, 2020, MariaDB Corporation + Copyright (c) 2008, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2876,6 +2876,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, info->error= ER_UNKNOWN_ERROR; goto err; } +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("simulate_delay_at_shutdown", { const char act[]= @@ -2884,6 +2885,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); };); +#endif /* heartbeat_period from @master_heartbeat_period user variable @@ -2973,12 +2975,14 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, if (should_stop(info)) break; +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("wait_after_binlog_EOF", { const char act[]= "now wait_for signal.rotate_finished"; DBUG_ASSERT(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act))); };); +#endif THD_STAGE_INFO(thd, stage_finished_reading_one_binlog_switching_to_next_binlog); @@ -4203,7 +4207,7 @@ bool mysql_show_binlog_events(THD* thd) binlog_size= s.st_size; if (lex_mi->pos > binlog_size) { - sprintf(errmsg_buf, "Invalid pos specified. Requested from pos:%llu is " + snprintf(errmsg_buf, sizeof(errmsg_buf), "Invalid pos specified. Requested from pos:%llu is " "greater than actual file size:%lu\n", lex_mi->pos, (ulong)s.st_size); errmsg= errmsg_buf; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 746ebad0e43..6d7299d26c7 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1072,7 +1072,8 @@ public: my_snprintf(m_view_access_denied_message, MYSQL_ERRMSG_SIZE, ER_THD(thd, ER_TABLEACCESS_DENIED_ERROR), "SHOW VIEW", m_sctx->priv_user, - m_sctx->host_or_ip, m_top_view->get_table_name()); + m_sctx->host_or_ip, + m_top_view->get_db_name(), m_top_view->get_table_name()); } return m_view_access_denied_message_ptr; } @@ -1164,7 +1165,8 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, DBUG_PRINT("debug", ("check_table_access failed")); my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "SHOW", thd->security_ctx->priv_user, - thd->security_ctx->host_or_ip, table_list->alias.str); + thd->security_ctx->host_or_ip, + table_list->db.str, table_list->alias.str); goto exit; } DBUG_PRINT("debug", ("check_table_access succeeded")); @@ -1193,7 +1195,8 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, { my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "SHOW", thd->security_ctx->priv_user, - thd->security_ctx->host_or_ip, table_list->alias.str); + thd->security_ctx->host_or_ip, + table_list->db.str, table_list->alias.str); goto exit; } } @@ -7225,13 +7228,14 @@ static bool store_trigger(THD *thd, Trigger *trigger, table->field[14]->store(STRING_WITH_LEN("OLD"), cs); table->field[15]->store(STRING_WITH_LEN("NEW"), cs); - if (trigger->create_time) + if (trigger->hr_create_time.val) { + /* timestamp is in microseconds */ table->field[16]->set_notnull(); - thd->variables.time_zone->gmt_sec_to_TIME(×tamp, - (my_time_t)(trigger->create_time/100)); - /* timestamp is with 6 digits */ - timestamp.second_part= (trigger->create_time % 100) * 10000; + thd->variables.time_zone-> + gmt_sec_to_TIME(×tamp, + (my_time_t) hrtime_to_time(trigger->hr_create_time)); + timestamp.second_part= hrtime_sec_part(trigger->hr_create_time); table->field[16]->store_time_dec(×tamp, 2); } @@ -10086,12 +10090,14 @@ static bool show_create_trigger_impl(THD *thd, Trigger *trigger) p->store(&trigger->db_cl_name, system_charset_info); - if (trigger->create_time) + if (trigger->hr_create_time.val) { MYSQL_TIME timestamp; - thd->variables.time_zone->gmt_sec_to_TIME(×tamp, - (my_time_t)(trigger->create_time/100)); - timestamp.second_part= (trigger->create_time % 100) * 10000; + thd->variables.time_zone-> + gmt_sec_to_TIME(×tamp, + (my_time_t) + hrtime_to_time(trigger->hr_create_time)); + timestamp.second_part= hrtime_sec_part(trigger->hr_create_time); p->store_datetime(×tamp, 2); } else diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 90693f407fb..fbc97ab54fb 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -173,6 +173,17 @@ void Binary_string::qs_append_hex(const char *str, uint32 len) } +void Binary_string::qs_append_hex_uint32(uint32 num) +{ + char *to= Ptr + str_length; + APPEND_HEX(to, (uchar) (num >> 24)); + APPEND_HEX(to, (uchar) (num >> 16)); + APPEND_HEX(to, (uchar) (num >> 8)); + APPEND_HEX(to, (uchar) num); + str_length+= 8; +} + + // Convert a string to its HEX representation bool Binary_string::set_hex(const char *str, uint32 len) { diff --git a/sql/sql_string.h b/sql/sql_string.h index f9fe895b40b..b1f02bdb43b 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -399,6 +399,7 @@ public: } void qs_append(const char *str, size_t len); void qs_append_hex(const char *str, uint32 len); + void qs_append_hex_uint32(uint32 num); void qs_append(double d); void qs_append(const double *d); inline void qs_append(const char c) @@ -614,7 +615,13 @@ public: } return false; } - + bool append_hex_uint32(uint32 num) + { + if (reserve(8)) + return true; + qs_append_hex_uint32(num); + return false; + } bool append_with_step(const char *s, uint32 arg_length, uint32 step_alloc) { uint32 new_length= arg_length + str_length; @@ -987,6 +994,17 @@ public: { return append(&ls); } + bool append_name_value(const LEX_CSTRING &name, + const LEX_CSTRING &value, + uchar quot= '\0') + { + return + append(name) || + append('=') || + (quot && append(quot)) || + append(value) || + (quot && append(quot)); + } bool append(const char *s, size_t size); bool append_with_prefill(const char *s, uint32 arg_length, uint32 full_length, char fill_char); @@ -999,6 +1017,37 @@ public: return append(s.str, s.length, cs); } + /* + Append a bitmask in an uint32 with a translation into a + C-style human readable representation, e.g.: + 0x05 -> "(flag04|flag01)" + + @param flags - the flags to translate + @param names - an array of flag names + @param count - the number of available elements in "names" + */ + bool append_flag32_names(uint32 flags, LEX_CSTRING names[], size_t count) + { + bool added= false; + if (flags && append('(')) + return true; + for (ulong i= 0; i <= 31; i++) + { + ulong bit= 31 - i; + if (flags & (1 << bit)) + { + if (added && append('|')) + return true; + if (bit < count ? append(names[bit]) : append('?')) + return true; + added= true; + } + } + if (flags && append(')')) + return true; + return false; + } + void strip_sp(); friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); friend class Field; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 840f251b6da..a861bee1cc8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -63,7 +63,7 @@ #include "rpl_mi.h" #include "rpl_rli.h" #include "log.h" - +#include "sql_debug.h" #ifdef _WIN32 #include <io.h> @@ -3815,6 +3815,13 @@ without_overlaps_err: thd->mem_root)) DBUG_RETURN(TRUE); +#ifndef DBUG_OFF + DBUG_EXECUTE_IF("key", + Debug_key::print_keys(thd, "prep_create_table: ", + *key_info_buffer, *key_count); + ); +#endif + DBUG_RETURN(FALSE); } @@ -9961,7 +9968,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, DEBUG_SYNC(thd, "alter_opened_table"); -#ifdef WITH_WSREP +#if defined WITH_WSREP && defined ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("sync.alter_opened_table", { const char act[]= diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 911c4e7349c..d29ef532382 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -38,6 +38,8 @@ #include "debug.h" // debug_crash_here #include "mysql/psi/mysql_sp.h" #include "wsrep_mysqld.h" +#include <my_time.h> +#include <mysql_time.h> /*************************************************************************/ @@ -222,7 +224,7 @@ static File_option triggers_file_parameters[]= }, { { STRING_WITH_LEN("created") }, - my_offsetof(class Table_triggers_list, create_times), + my_offsetof(class Table_triggers_list, hr_create_times), FILE_OPTIONS_ULLLIST }, { { 0, 0 }, 0, FILE_OPTIONS_STRING } @@ -644,7 +646,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) goto end; } -#ifdef WITH_WSREP +#if defined WITH_WSREP && defined ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("sync.mdev_20225", { const char act[]= @@ -653,7 +655,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); };); -#endif /* WITH_WSREP */ +#endif /* WITH_WSREP && ENABLED_DEBUG_SYNC */ if (create) result= table->triggers->create_trigger(thd, tables, &stmt_query, @@ -1057,6 +1059,10 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, if (!(trigger= new (&table->mem_root) Trigger(this, 0))) goto err; + /* Time with in microseconds */ + trigger->hr_create_time= make_hr_time(thd->query_start(), + thd->query_start_sec_part()); + /* Create trigger_name.TRN file to ensure trigger name is unique */ if (sql_create_definition_file(NULL, &trigname_file, &trigname_file_type, (uchar*)&trigname, trigname_file_parameters)) @@ -1069,8 +1075,6 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, /* Populate the trigger object */ trigger->sql_mode= thd->variables.sql_mode; - /* Time with 2 decimals, like in MySQL 5.7 */ - trigger->create_time= ((ulonglong) thd->query_start())*100 + thd->query_start_sec_part()/10000; build_trig_stmt_query(thd, tables, stmt_query, &trigger_definition, &trigger->definer, trg_definer_holder); @@ -1138,7 +1142,7 @@ void Table_triggers_list::empty_lists() client_cs_names.empty(); connection_cl_names.empty(); db_cl_names.empty(); - create_times.empty(); + hr_create_times.empty(); } @@ -1174,7 +1178,7 @@ bool Trigger::add_to_file_list(void* param_arg) base->client_cs_names.push_back(&client_cs_name, mem_root) || base->connection_cl_names.push_back(&connection_cl_name, mem_root) || base->db_cl_names.push_back(&db_cl_name, mem_root) || - base->create_times.push_back(&create_time, mem_root)) + base->hr_create_times.push_back(&hr_create_time.val, mem_root)) return 1; return 0; } @@ -1584,7 +1588,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db, List_iterator_fast<LEX_CSTRING> it_client_cs_name(trigger_list->client_cs_names); List_iterator_fast<LEX_CSTRING> it_connection_cl_name(trigger_list->connection_cl_names); List_iterator_fast<LEX_CSTRING> it_db_cl_name(trigger_list->db_cl_names); - List_iterator_fast<ulonglong> it_create_times(trigger_list->create_times); + List_iterator_fast<ulonglong> + it_create_times(trigger_list->hr_create_times); LEX *old_lex= thd->lex; LEX lex; sp_rcontext *save_spcont= thd->spcont; @@ -1670,7 +1675,13 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db, trigger->sql_mode= sql_mode; trigger->definition= *trg_create_str; - trigger->create_time= trg_create_time ? *trg_create_time : 0; + trigger->hr_create_time.val= trg_create_time ? *trg_create_time : 0; + /* + Fix time if in 100th of second (comparison with max uint * 100 + (max possible timestamp in the old format)) + */ + if (trigger->hr_create_time.val < 429496729400ULL) + trigger->hr_create_time.val*= 10000; trigger->name= sp ? sp->m_name : empty_clex_str; trigger->on_table_name.str= (char*) lex.raw_trg_on_table_name_begin; trigger->on_table_name.length= (lex.raw_trg_on_table_name_end - diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 739669c86a5..774dca7cba1 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -140,7 +140,7 @@ public: GRANT_INFO subject_table_grants; sql_mode_t sql_mode; /* Store create time. Can't be mysql_time_t as this holds also sub seconds */ - ulonglong create_time; + my_hrtime_t hr_create_time; // Create time timestamp in microseconds trg_event_type event; trg_action_time_type action_time; uint action_order; @@ -223,7 +223,7 @@ public: */ List<ulonglong> definition_modes_list; /** Create times for triggers */ - List<ulonglong> create_times; + List<ulonglong> hr_create_times; List<LEX_CSTRING> definers_list; diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index d80342a8395..a045d0e3908 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -743,7 +743,7 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl, Attach the select used of TVC as the only slave to the unit for the derived table tvc_x of the transformation */ - derived_unit->add_slave(tvc_sl); + derived_unit->attach_single(tvc_sl); tvc_sl->set_linkage(DERIVED_TABLE_TYPE); /* diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index b55bbc7ffac..02f068e9bbc 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -620,7 +620,7 @@ int mysql_create_function(THD *thd,udf_func *udf) /* Allow creation of functions even if we can't open func table */ if (unlikely(!table)) - goto err; + goto err_open_func_table; table->use_all_columns(); restore_record(table, s->default_values); // Default values for fields table->field[0]->store(u_d->name.str, u_d->name.length, system_charset_info); @@ -634,7 +634,7 @@ int mysql_create_function(THD *thd,udf_func *udf) { my_error(ER_ERROR_ON_WRITE, MYF(0), "mysql.func", error); del_udf(u_d); - goto err; + goto err_open_func_table; } done: @@ -649,6 +649,7 @@ done: err: if (new_dl) dlclose(dl); +err_open_func_table: mysql_rwlock_unlock(&THR_LOCK_udf); DBUG_RETURN(1); } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index e8bdbcba2f2..758edbdcbaa 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1075,15 +1075,6 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg, order= order->next) order->item= &order->item_ptr; } - for (ORDER *order= global_parameters()->order_list.first; - order; - order=order->next) - { - (*order->item)->walk(&Item::change_context_processor, 0, - &fake_select_lex->context); - (*order->item)->walk(&Item::set_fake_select_as_master_processor, 0, - fake_select_lex); - } } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 6dedd5e85be..7a52b822b9d 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -306,7 +306,8 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, { my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "ANY", thd->security_ctx->priv_user, - thd->security_ctx->priv_host, tbl->table_name.str); + thd->security_ctx->priv_host, + tbl->db.str, tbl->table_name.str); goto err; } /* @@ -834,7 +835,7 @@ static File_option view_parameters[]= my_offsetof(TABLE_LIST, with_check), FILE_OPTIONS_ULONGLONG}, {{ STRING_WITH_LEN("timestamp")}, - my_offsetof(TABLE_LIST, timestamp), + my_offsetof(TABLE_LIST, hr_timestamp), FILE_OPTIONS_TIMESTAMP}, {{ STRING_WITH_LEN("create-version")}, my_offsetof(TABLE_LIST, file_version), @@ -858,6 +859,15 @@ static File_option view_parameters[]= FILE_OPTIONS_STRING} }; + +static File_option view_timestamp_parameters[]= +{ + + {{ C_STRING_WITH_LEN("timestamp")}, 0, FILE_OPTIONS_TIMESTAMP}, + {{NullS, 0}, 0, FILE_OPTIONS_STRING} +}; + + static LEX_CSTRING view_file_type[]= {{STRING_WITH_LEN("VIEW") }}; @@ -875,8 +885,8 @@ int mariadb_fix_view(THD *thd, TABLE_LIST *view, bool wrong_checksum, &path, path_buff, sizeof(path_buff), &file, view); /* init timestamp */ - if (!view->timestamp.str) - view->timestamp.str= view->timestamp_buffer; + if (!view->hr_timestamp.str) + view->hr_timestamp.str= view->timestamp_buffer; if (swap_alg && view->algorithm != VIEW_ALGORITHM_UNDEFINED) { @@ -891,13 +901,13 @@ int mariadb_fix_view(THD *thd, TABLE_LIST *view, bool wrong_checksum, swap_alg= 0; if (wrong_checksum) { - if (view->md5.length != 32) + if (view->md5.length != VIEW_MD5_LEN) { - if ((view->md5.str= (char *)thd->alloc(32 + 1)) == NULL) + if ((view->md5.str= (char *)thd->alloc(VIEW_MD5_LEN + 1)) == NULL) DBUG_RETURN(HA_ADMIN_FAILED); } view->calc_md5(const_cast<char*>(view->md5.str)); - view->md5.length= 32; + view->md5.length= VIEW_MD5_LEN; } view->mariadb_version= MYSQL_VERSION_ID; @@ -1021,13 +1031,13 @@ static int mysql_register_view(THD *thd, DDL_LOG_STATE *ddl_log_state, view->file_version= 2; view->mariadb_version= MYSQL_VERSION_ID; view->calc_md5(md5); - if (!(view->md5.str= (char*) thd->memdup(md5, 32))) + if (!(view->md5.str= (char*) thd->memdup(md5, VIEW_MD5_LEN))) { my_error(ER_OUT_OF_RESOURCES, MYF(0)); error= -1; goto err; } - view->md5.length= 32; + view->md5.length= VIEW_MD5_LEN; can_be_merged= lex->can_be_merged(); if (lex->create_view->algorithm == VIEW_ALGORITHM_MERGE && !lex->can_be_merged()) @@ -1078,8 +1088,8 @@ loop_out: &path, path_buff, sizeof(path_buff), &file, view); /* init timestamp */ - if (!view->timestamp.str) - view->timestamp.str= view->timestamp_buffer; + if (!view->hr_timestamp.str) + view->hr_timestamp.str= view->timestamp_buffer; /* check old .frm */ { @@ -1224,7 +1234,32 @@ err: DBUG_RETURN(error); } +/** + Reads view definition "version" + @param[in] share Share object of view + + @return true on error, otherwise false +*/ + +bool mariadb_view_version_get(TABLE_SHARE *share) +{ + DBUG_ASSERT(share->is_view); + + if (!(share->tabledef_version.str= + (uchar*) alloc_root(&share->mem_root, + MICROSECOND_TIMESTAMP_BUFFER_SIZE))) + return TRUE; + share->tabledef_version.length= 0; // safety if the drfinition file is brocken + + DBUG_ASSERT(share->view_def != NULL); + if (share->view_def->parse((uchar *) &share->tabledef_version, NULL, + view_timestamp_parameters, 1, + &file_parser_dummy_hook)) + return TRUE; + DBUG_ASSERT(share->tabledef_version.length == MICROSECOND_TIMESTAMP_BUFFER_SIZE-1); + return FALSE; +} /** read VIEW .frm and create structures @@ -1287,6 +1322,10 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, mysql_handle_single_derived(thd->lex, table, DT_REINIT); DEBUG_SYNC(thd, "after_cached_view_opened"); + if (!share->tabledef_version.length) + { + mariadb_view_version_get(share); + } DBUG_RETURN(0); } @@ -1323,8 +1362,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, arena= thd->activate_stmt_arena_if_needed(&backup); /* init timestamp */ - if (!table->timestamp.str) - table->timestamp.str= table->timestamp_buffer; + if (!table->hr_timestamp.str) + table->hr_timestamp.str= table->timestamp_buffer; /* prepare default values for old format */ table->view_suid= TRUE; table->definer.user.str= table->definer.host.str= 0; @@ -1340,6 +1379,19 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, required_view_parameters, &file_parser_dummy_hook))) goto end; + if (!share->tabledef_version.length) + { + share->tabledef_version.str= (const uchar *) + memdup_root(&share->mem_root, + (const void *) + table->hr_timestamp.str, + (share->tabledef_version.length= + table->hr_timestamp.length)); + } + if (!table->tabledef_version.length) + { + table->set_view_def_version(&table->hr_timestamp); + } /* check old format view .frm @@ -2196,10 +2248,10 @@ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view) int view_checksum(THD *thd, TABLE_LIST *view) { char md5[MD5_BUFF_LENGTH]; - if (!view->view || view->md5.length != 32) + if (!view->view || view->md5.length != VIEW_MD5_LEN) return HA_ADMIN_NOT_IMPLEMENTED; view->calc_md5(md5); - return (strncmp(md5, view->md5.str, 32) ? + return (strncmp(md5, view->md5.str, VIEW_MD5_LEN) ? HA_ADMIN_WRONG_CHECKSUM : HA_ADMIN_OK); } @@ -2304,7 +2356,7 @@ mysql_rename_view(THD *thd, object for it. */ view_def.reset(); - view_def.timestamp.str= view_def.timestamp_buffer; + view_def.hr_timestamp.str= view_def.timestamp_buffer; view_def.view_suid= TRUE; /* get view definition and source */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b583a7c8266..76c6270d95e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8941,14 +8941,20 @@ select_item_list: | select_item | '*' { + bool is_parsing_returning= + thd->lex->current_select->parsing_place == + IN_RETURNING; + SELECT_LEX *correct_select= is_parsing_returning ? + thd->lex->returning() : + thd->lex->current_select; Item *item= new (thd->mem_root) - Item_field(thd, &thd->lex->current_select->context, + Item_field(thd, &correct_select->context, star_clex_str); if (unlikely(item == NULL)) MYSQL_YYABORT; if (unlikely(add_item_to_list(thd, item))) MYSQL_YYABORT; - (thd->lex->current_select->with_wild)++; + correct_select->with_wild++; } ; @@ -13425,19 +13431,33 @@ opt_returning: | RETURNING_SYM { DBUG_ASSERT(!Lex->has_returning()); - if (($<num>$= (Select != Lex->returning()))) - { - SELECT_LEX *sl= Lex->returning(); - sl->set_master_unit(0); - Select->add_slave(Lex->create_unit(sl)); - sl->include_global((st_select_lex_node**)&Lex->all_selects_list); - Lex->push_select(sl); - } + /* + When parsing_place is IN_RETURNING, we push select items to + item_list of builtin_select instead of current_select. + But set parsing_place of current_select to true. + + Because parsing_place for builtin_select will be IN_RETURNING, + regardless there is SELECT in RETURNING. Example, if + there is RETURNING (SELECT...), then when we parse + SELECT inside RETURNING, builtin_select->parsing_place + will still be true. So the select items of SELECT inside + RETURNING will be added to item_list of builtin_select which + is incorrect. We want to prevent this from happening. + Since for every new select, a new SELECT_LEX + object is created and pushed to select stack, current_select + will point to SELECT inside RETURNING, and also has + parsing_place not set to IN_RETURNING by default. + So items are correctly added to item_list of SELECT inside + RETURNING instead of builtin_select. + */ + + thd->lex->current_select->parsing_place= IN_RETURNING; + thd->lex->push_context(&thd->lex->returning()->context); } select_item_list { - if ($<num>2) - Lex->pop_select(); + thd->lex->pop_context(); + thd->lex->current_select->parsing_place= NO_MATTER; } ; @@ -14993,7 +15013,8 @@ with_clause: lex->derived_tables|= DERIVED_WITH; lex->with_cte_resolution= true; lex->curr_with_clause= with_clause; - with_clause->add_to_list(Lex->with_clauses_list_last_next); + with_clause->add_to_list(&lex->with_clauses_list, + lex->with_clauses_list_last_next); if (lex->current_select && lex->current_select->parsing_place == BEFORE_OPT_LIST) lex->current_select->parsing_place= NO_MATTER; diff --git a/sql/table.cc b/sql/table.cc index 5e17eb60b30..b8397c7b013 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8862,7 +8862,7 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode) { /* Compute the actual value of the virtual fields */ DBUG_FIX_WRITE_SET(vf); -# ifndef DBUG_OFF +# ifdef DBUG_TRACE int field_error= # endif vcol_info->expr->save_in_field(vf, 0); @@ -9770,6 +9770,73 @@ bool TABLE_LIST::is_with_table() return derived && derived->with_element; } + +/** + Check if the definition are the same. + + If versions do not match it check definitions (with checking and setting + trigger definition versions (times) + + @param[in] view TABLE_LIST of the view + @param[in] share Share object of view + + @return false on error or different definitions. + + @sa check_and_update_table_version() +*/ + +bool TABLE_LIST::is_the_same_definition(THD* thd, TABLE_SHARE *s) +{ + enum enum_table_ref_type tp= s->get_table_ref_type(); + if (m_table_ref_type == tp) + { + /* + Cache have not changed which means that definition was not changed + including triggers + */ + if (m_table_ref_version == s->get_table_ref_version()) + return TRUE; + + /* + If cache changed then check content version + */ + if ((tabledef_version.length && + tabledef_version.length == s->tabledef_version.length && + memcmp(tabledef_version.str, s->tabledef_version.str, + tabledef_version.length) == 0)) + { + // Definition have not changed, let's check if triggers changed. + if (table && table->triggers) + { + + my_hrtime_t hr_stmt_prepare= thd->hr_prepare_time; + if (hr_stmt_prepare.val) + for(uint i= 0; i < TRG_EVENT_MAX; i++) + for (uint j= 0; j < TRG_ACTION_MAX; j++) + { + Trigger *tr= + table->triggers->get_trigger((trg_event_type)i, + (trg_action_time_type)j); + if (tr) + if (hr_stmt_prepare.val <= tr->hr_create_time.val) + { + set_tabledef_version(s); + return FALSE; + } + } + } + set_table_id(s); + return TRUE; + } + else + tabledef_version.length= 0; + } + else + set_tabledef_version(s); + return FALSE; +} + + uint TABLE_SHARE::actual_n_key_parts(THD *thd) { return use_ext_keys && diff --git a/sql/table.h b/sql/table.h index cb917594131..31af1663026 100644 --- a/sql/table.h +++ b/sql/table.h @@ -36,6 +36,19 @@ #include "sql_type.h" /* vers_kind_t */ #include "privilege.h" /* privilege_t */ +/* + Buffer for unix timestamp in microseconds: + 9,223,372,036,854,775,807 (signed int64 maximal value) + 1 234 567 890 123 456 789 + + Note: we can use unsigned for calculation, but practically they + are the same by probability to overflow them (signed int64 in + microseconds is enough for almost 3e5 years) and signed allow to + avoid increasing the buffer (the old buffer for human readable + date was 19+1). +*/ +#define MICROSECOND_TIMESTAMP_BUFFER_SIZE (19 + 1) + /* Structs that defines the TABLE */ class Item; /* Needed by ORDER */ @@ -73,6 +86,8 @@ class Open_table_context; */ typedef ulonglong nested_join_map; +#define VIEW_MD5_LEN 32 + #define tmp_file_prefix "#sql" /**< Prefix for tmp tables */ #define tmp_file_prefix_length 4 @@ -1104,7 +1119,7 @@ struct TABLE_SHARE with a base table, a base table is replaced with a temporary table and so on. - @sa TABLE_LIST::is_table_ref_id_equal() + @sa TABLE_LIST::is_the_same_definition() */ ulong get_table_ref_version() const { @@ -2478,6 +2493,12 @@ struct TABLE_LIST to view with SQL SECURITY DEFINER) */ Security_context *security_ctx; + uchar tabledef_version_buf[MY_UUID_SIZE > + MICROSECOND_TIMESTAMP_BUFFER_SIZE-1 ? + MY_UUID_SIZE + 1 : + MICROSECOND_TIMESTAMP_BUFFER_SIZE]; + LEX_CUSTRING tabledef_version; + /* This view security context (non-zero only for views with SQL SECURITY DEFINER) @@ -2491,7 +2512,7 @@ struct TABLE_LIST LEX_CSTRING source; /* source of CREATE VIEW */ LEX_CSTRING view_db; /* saved view database */ LEX_CSTRING view_name; /* saved view name */ - LEX_STRING timestamp; /* GMT time stamp of last operation */ + LEX_STRING hr_timestamp; /* time stamp of last operation */ LEX_USER definer; /* definer of view */ ulonglong file_version; /* version of file's field set */ ulonglong mariadb_version; /* version of server on creation */ @@ -2575,7 +2596,7 @@ struct TABLE_LIST /* TABLE_TYPE_UNKNOWN if any type is acceptable */ Table_type required_type; handlerton *db_type; /* table_type for handler */ - char timestamp_buffer[MAX_DATETIME_WIDTH + 1]; + char timestamp_buffer[MICROSECOND_TIMESTAMP_BUFFER_SIZE]; /* This TABLE_LIST object is just placeholder for prelocking, it will be used for implicit LOCK TABLES only and won't be used in real statement. @@ -2780,19 +2801,7 @@ struct TABLE_LIST */ bool process_index_hints(TABLE *table); - /** - Compare the version of metadata from the previous execution - (if any) with values obtained from the current table - definition cache element. - - @sa check_and_update_table_version() - */ - inline bool is_table_ref_id_equal(TABLE_SHARE *s) const - { - return (m_table_ref_type == s->get_table_ref_type() && - m_table_ref_version == s->get_table_ref_version()); - } - + bool is_the_same_definition(THD *thd, TABLE_SHARE *s); /** Record the value of metadata version of the corresponding table definition cache element in this parse tree node. @@ -2809,6 +2818,26 @@ struct TABLE_LIST m_table_ref_version= table_ref_version_arg; } + void set_table_id(TABLE_SHARE *s) + { + set_table_ref_id(s); + set_tabledef_version(s); + } + + void set_tabledef_version(TABLE_SHARE *s) + { + if (!tabledef_version.length && s->tabledef_version.length) + { + DBUG_ASSERT(s->tabledef_version.length < + sizeof(tabledef_version_buf)); + tabledef_version.str= tabledef_version_buf; + memcpy(tabledef_version_buf, s->tabledef_version.str, + (tabledef_version.length= s->tabledef_version.length)); + // safety + tabledef_version_buf[tabledef_version.length]= 0; + } + } + /* Set of functions returning/setting state of a derived table/view. */ bool is_non_derived() const { return (!derived_type); } bool is_view_or_derived() const { return derived_type; } @@ -2922,6 +2951,12 @@ struct TABLE_LIST } } + inline void set_view_def_version(LEX_STRING *version) + { + m_table_ref_type= TABLE_REF_VIEW; + tabledef_version.str= (const uchar *) version->str; + tabledef_version.length= version->length; + } private: bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_where(THD *thd, Item **conds, bool no_where_clause); diff --git a/sql/tztime.cc b/sql/tztime.cc index 4b5f1d1f6d6..2e39a20fc91 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2768,7 +2768,8 @@ main(int argc, char **argv) trunc_tables= trunc_tables_const; printf("set @wsrep_is_on=(%s);\n", wsrep_is_on); - printf("SELECT concat('%%', GROUP_CONCAT(OPTION), '%%') INTO @replicate_opt " + printf("SET STATEMENT SQL_MODE='' FOR " + "SELECT concat('%%', GROUP_CONCAT(OPTION), '%%') INTO @replicate_opt " " FROM" " (SELECT DISTINCT concat('REPLICATE_', UPPER(ENGINE)) AS OPTION" " FROM information_schema.TABLES" diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc index e165a204f56..708eb552866 100644 --- a/sql/wsrep_high_priority_service.cc +++ b/sql/wsrep_high_priority_service.cc @@ -405,6 +405,7 @@ int Wsrep_high_priority_service::apply_toi(const wsrep::ws_meta& ws_meta, WSREP_DEBUG("Wsrep_high_priority_service::apply_toi: %lld", client_state.toi_meta().seqno().get()); +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("sync.wsrep_apply_toi", { const char act[]= @@ -414,6 +415,7 @@ int Wsrep_high_priority_service::apply_toi(const wsrep::ws_meta& ws_meta, DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); };); +#endif int ret= apply_events(thd, m_rli, data, err); wsrep_thd_set_ignored_error(thd, false); @@ -459,6 +461,7 @@ int Wsrep_high_priority_service::log_dummy_write_set(const wsrep::ws_handle& ws_ DBUG_PRINT("info", ("Wsrep_high_priority_service::log_dummy_write_set: seqno=%lld", ws_meta.seqno().get())); +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("sync.wsrep_log_dummy_write_set", { const char act[]= @@ -467,6 +470,7 @@ int Wsrep_high_priority_service::log_dummy_write_set(const wsrep::ws_handle& ws_ DBUG_ASSERT(!debug_sync_set_action(m_thd, STRING_WITH_LEN(act))); };); +#endif if (ws_meta.ordered()) { @@ -562,8 +566,8 @@ int Wsrep_applier_service::apply_write_set(const wsrep::ws_meta& ws_meta, /* moved dbug sync point here, after possible THD switch for SR transactions has ben done */ - /* Allow tests to block the applier thread using the DBUG facilities */ #ifdef ENABLED_DEBUG_SYNC + /* Allow tests to block the applier thread using the DBUG facilities */ DBUG_EXECUTE_IF("sync.wsrep_apply_cb", { const char act[]= @@ -716,6 +720,7 @@ int Wsrep_replayer_service::apply_write_set(const wsrep::ws_meta& ws_meta, DBUG_ASSERT(thd->wsrep_trx().active()); DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_replaying); +#ifdef ENABLED_DEBUG_SYNC /* Allow tests to block the replayer thread using the DBUG facilities */ DBUG_EXECUTE_IF("sync.wsrep_replay_cb", { @@ -726,6 +731,7 @@ int Wsrep_replayer_service::apply_write_set(const wsrep::ws_meta& ws_meta, DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); };); +#endif wsrep_setup_uk_and_fk_checks(thd); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index caea02c38f3..a31a0364df5 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -721,11 +721,14 @@ static std::string wsrep_server_incoming_address() /* In case port is not specified in wsrep_node_incoming_address, we use mysqld_port. + Note that we might get here before we execute set_ports(). */ - int port= (addr.get_port() > 0) ? addr.get_port() : (int) mysqld_port; + int local_port= (addr.get_port() > 0) ? addr.get_port() : (int) mysqld_port; + if (!local_port) + local_port= MYSQL_PORT; const char *fmt= (addr.is_ipv6()) ? "[%s]:%u" : "%s:%u"; - snprintf(inc_addr, inc_addr_max, fmt, addr.get_address(), port); + snprintf(inc_addr, inc_addr_max, fmt, addr.get_address(), local_port); } done: diff --git a/sql/wsrep_server_service.cc b/sql/wsrep_server_service.cc index 4916005e7ed..9be6af71c56 100644 --- a/sql/wsrep_server_service.cc +++ b/sql/wsrep_server_service.cc @@ -391,6 +391,7 @@ int Wsrep_server_service::wait_committing_transactions(int timeout) void Wsrep_server_service::debug_sync(const char* sync_point) { +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF(sync_point, { std::stringstream dbug_action; dbug_action << "now " @@ -401,4 +402,5 @@ void Wsrep_server_service::debug_sync(const char* sync_point) action.c_str(), action.length())); };); +#endif } diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 448153f55de..c09a9392cb6 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1842,6 +1842,7 @@ wait_signal: WSREP_INFO("Donor state reached"); +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("sync.wsrep_donor_state", { const char act[]= @@ -1851,6 +1852,7 @@ wait_signal: assert(!debug_sync_set_action(thd.ptr, STRING_WITH_LEN(act))); };); +#endif goto wait_signal; } diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index a615b7f609b..64b7faa2957 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -346,6 +346,7 @@ bool wsrep_bf_abort(THD* bf_thd, THD* victim_thd) WSREP_LOG_THD(bf_thd, "BF aborter before"); WSREP_LOG_THD(victim_thd, "victim before"); +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("sync.wsrep_bf_abort", { const char act[]= @@ -355,6 +356,7 @@ bool wsrep_bf_abort(THD* bf_thd, THD* victim_thd) DBUG_ASSERT(!debug_sync_set_action(bf_thd, STRING_WITH_LEN(act))); };); +#endif if (WSREP(victim_thd) && !victim_thd->wsrep_trx().active()) { |