summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2022-10-04 13:32:38 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2022-10-04 13:32:38 +0200
commitbb76dcbec77d31818ec7dfc0d0dc1f4b49185bc5 (patch)
tree0c288f685ac6fbc8d4bd4cdbc60bcf9942f019f7 /sql
parent1ac8149b83f002cd4754e1eca225560bc02b22e4 (diff)
parent55e07d9ade51e9e969f528d903509806142f4d1e (diff)
downloadmariadb-git-bb76dcbec77d31818ec7dfc0d0dc1f4b49185bc5.tar.gz
Merge branch '10.9' into 10.10
Diffstat (limited to 'sql')
-rw-r--r--sql/debug_sync.cc27
-rw-r--r--sql/event_queue.cc2
-rw-r--r--sql/field.cc6
-rw-r--r--sql/gcalc_slicescan.cc4
-rw-r--r--sql/ha_partition.cc15
-rw-r--r--sql/handler.cc9
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_create.cc2
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_subselect.cc44
-rw-r--r--sql/item_subselect.h1
-rw-r--r--sql/json_table.cc2
-rw-r--r--sql/log.cc10
-rw-r--r--sql/log.h2
-rw-r--r--sql/log_event.cc4
-rw-r--r--sql/mdl.cc6
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/net_serv.cc4
-rw-r--r--sql/parse_file.cc21
-rw-r--r--sql/records.cc4
-rw-r--r--sql/rpl_injector.h4
-rw-r--r--sql/rpl_parallel.cc12
-rw-r--r--sql/rpl_record.cc6
-rw-r--r--sql/semisync_master.cc6
-rw-r--r--sql/share/errmsg-utf8.txt38
-rw-r--r--sql/slave.cc8
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sql_acl.cc13
-rw-r--r--sql/sql_analyse.cc60
-rw-r--r--sql/sql_base.cc35
-rw-r--r--sql/sql_binlog.cc15
-rw-r--r--sql/sql_cache.cc5
-rw-r--r--sql/sql_class.cc7
-rw-r--r--sql/sql_class.h12
-rw-r--r--sql/sql_cte.cc100
-rw-r--r--sql/sql_cte.h20
-rw-r--r--sql/sql_debug.h168
-rw-r--r--sql/sql_lex.cc24
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc28
-rw-r--r--sql/sql_prepare.cc4
-rw-r--r--sql/sql_priv.h1
-rw-r--r--sql/sql_repl.cc8
-rw-r--r--sql/sql_show.cc30
-rw-r--r--sql/sql_string.cc11
-rw-r--r--sql/sql_string.h51
-rw-r--r--sql/sql_table.cc11
-rw-r--r--sql/sql_trigger.cc29
-rw-r--r--sql/sql_trigger.h4
-rw-r--r--sql/sql_tvc.cc2
-rw-r--r--sql/sql_udf.cc5
-rw-r--r--sql/sql_union.cc9
-rw-r--r--sql/sql_view.cc84
-rw-r--r--sql/sql_yacc.yy47
-rw-r--r--sql/table.cc69
-rw-r--r--sql/table.h67
-rw-r--r--sql/tztime.cc3
-rw-r--r--sql/wsrep_high_priority_service.cc8
-rw-r--r--sql/wsrep_mysqld.cc7
-rw-r--r--sql/wsrep_server_service.cc2
-rw-r--r--sql/wsrep_sst.cc2
-rw-r--r--sql/wsrep_thd.cc2
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(&current->thd->LOCK_thd_data);
run_commit_ordered(current->thd, current->all);
+ mysql_mutex_unlock(&current->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(&timestamp,
- (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(&timestamp,
+ (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(&timestamp, 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(&timestamp,
- (my_time_t)(trigger->create_time/100));
- timestamp.second_part= (trigger->create_time % 100) * 10000;
+ thd->variables.time_zone->
+ gmt_sec_to_TIME(&timestamp,
+ (my_time_t)
+ hrtime_to_time(trigger->hr_create_time));
+ timestamp.second_part= hrtime_sec_part(trigger->hr_create_time);
p->store_datetime(&timestamp, 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())
{