summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-12-27 18:20:28 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-12-27 18:20:28 +0200
commit4c25e75ce766440694553e0baf03cc5c6e803fc3 (patch)
treef75cea6e472054b7a15466ea5e31c862ae9e77cc /sql
parent4c57ab34d4852387da4ef8eac862045d1458de1e (diff)
parent808bc919eb94ac888f2014275b443ebdaf733ae5 (diff)
downloadmariadb-git-4c25e75ce766440694553e0baf03cc5c6e803fc3.tar.gz
Merge 10.3 into 10.4
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt19
-rw-r--r--sql/item.cc11
-rw-r--r--sql/item_timefunc.cc16
-rw-r--r--sql/item_timefunc.h22
-rw-r--r--sql/sql_audit.h22
-rw-r--r--sql/sql_insert.cc41
-rw-r--r--sql/sql_lex.h22
-rw-r--r--sql/sql_select.cc36
-rw-r--r--sql/sql_select.h1
-rw-r--r--sql/sql_type.h9
-rw-r--r--sql/threadpool_generic.cc2
-rw-r--r--sql/tztime.cc10
-rw-r--r--sql/unireg.cc3
13 files changed, 114 insertions, 100 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 52fab2a029f..bab8e67fdac 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -418,15 +418,18 @@ IF(WIN32 AND TARGET mysqld AND NOT CMAKE_CROSSCOMPILING)
ENDIF()
MAKE_DIRECTORY(${CMAKE_CURRENT_BINARY_DIR}/data)
ADD_CUSTOM_COMMAND(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/initdb.dep
- COMMAND ${CMAKE_COMMAND} ${CONFIG_PARAM}
- -DTOP_SRCDIR="${CMAKE_SOURCE_DIR}"
- -DBINDIR="${CMAKE_CURRENT_BINARY_DIR}"
- -DMYSQLD_EXECUTABLE="$<TARGET_FILE:mysqld>"
- -DCMAKE_CFG_INTDIR="${CMAKE_CFG_INTDIR}"
- -P ${CMAKE_SOURCE_DIR}/cmake/create_initial_db.cmake
+ OUTPUT initdb.dep
+ COMMAND ${CMAKE_COMMAND} -E remove_directory data
+ COMMAND ${CMAKE_COMMAND} -E make_directory data
+ COMMAND ${CMAKE_COMMAND} -E chdir data ${CMAKE_COMMAND}
+ ${CONFIG_PARAM}
+ -DTOP_SRCDIR="${CMAKE_SOURCE_DIR}"
+ -DBINDIR="${CMAKE_CURRENT_BINARY_DIR}"
+ -DMYSQLD_EXECUTABLE="$<TARGET_FILE:mysqld>"
+ -DCMAKE_CFG_INTDIR="${CMAKE_CFG_INTDIR}"
+ -P ${CMAKE_SOURCE_DIR}/cmake/create_initial_db.cmake
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/initdb.dep
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/
DEPENDS mysqld
)
ADD_CUSTOM_TARGET(initial_database
diff --git a/sql/item.cc b/sql/item.cc
index dc39755f63d..7d7d50da2cf 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -3225,12 +3225,13 @@ bool Item_field::get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate)
bool Item_field::get_date_result(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- if (result_field->is_null() || result_field->get_date(ltime,fuzzydate))
+ if ((null_value= result_field->is_null()) ||
+ result_field->get_date(ltime, fuzzydate))
{
bzero((char*) ltime,sizeof(*ltime));
- return (null_value= 1);
+ return true;
}
- return (null_value= 0);
+ return false;
}
@@ -8229,7 +8230,7 @@ bool Item_ref::val_native(THD *thd, Native *to)
longlong Item_ref::val_datetime_packed(THD *thd)
{
DBUG_ASSERT(fixed);
- longlong tmp= (*ref)->val_datetime_packed(thd);
+ longlong tmp= (*ref)->val_datetime_packed_result(thd);
null_value= (*ref)->null_value;
return tmp;
}
@@ -8238,7 +8239,7 @@ longlong Item_ref::val_datetime_packed(THD *thd)
longlong Item_ref::val_time_packed(THD *thd)
{
DBUG_ASSERT(fixed);
- longlong tmp= (*ref)->val_time_packed(thd);
+ longlong tmp= (*ref)->val_time_packed_result(thd);
null_value= (*ref)->null_value;
return tmp;
}
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 3b2ac55c59d..924fdecffa9 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1101,9 +1101,10 @@ longlong Item_func_weekday::val_int()
{
DBUG_ASSERT(fixed == 1);
THD *thd= current_thd;
- Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd));
- return ((null_value= !d.is_valid_datetime())) ? 0 :
- calc_weekday(d.daynr(), odbc_type) + MY_TEST(odbc_type);
+ Datetime dt(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd));
+ if ((null_value= !dt.is_valid_datetime()))
+ return 0;
+ return dt.weekday(odbc_type) + MY_TEST(odbc_type);
}
bool Item_func_dayname::fix_length_and_dec()
@@ -1122,14 +1123,15 @@ bool Item_func_dayname::fix_length_and_dec()
String* Item_func_dayname::val_str(String* str)
{
DBUG_ASSERT(fixed == 1);
- uint weekday=(uint) val_int(); // Always Item_func_weekday()
const char *day_name;
uint err;
+ THD *thd= current_thd;
+ Datetime dt(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd));
- if (null_value)
+ if ((null_value= !dt.is_valid_datetime()))
return (String*) 0;
-
- day_name= locale->day_names->type_names[weekday];
+
+ day_name= locale->day_names->type_names[dt.weekday(false)];
str->copy(day_name, (uint) strlen(day_name), &my_charset_utf8_bin,
collation.collation, &err);
return str;
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index fe9dc8b43e2..8a69a0a3d5a 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -422,20 +422,13 @@ public:
};
-class Item_func_weekday :public Item_func
+class Item_func_weekday :public Item_long_func
{
bool odbc_type;
public:
Item_func_weekday(THD *thd, Item *a, bool type_arg):
- Item_func(thd, a), odbc_type(type_arg) { collation.set_numeric(); }
+ Item_long_func(thd, a), odbc_type(type_arg) { }
longlong val_int();
- double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
- String *val_str(String *str)
- {
- DBUG_ASSERT(fixed == 1);
- str->set(val_int(), &my_charset_bin);
- return null_value ? 0 : str;
- }
const char *func_name() const
{
return (odbc_type ? "dayofweek" : "weekday");
@@ -444,7 +437,6 @@ public:
{
return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
- const Type_handler *type_handler() const { return &type_handler_long; }
bool fix_length_and_dec()
{
decimals= 0;
@@ -462,11 +454,11 @@ public:
{ return get_item_copy<Item_func_weekday>(thd, this); }
};
-class Item_func_dayname :public Item_func_weekday
+class Item_func_dayname :public Item_str_func
{
MY_LOCALE *locale;
public:
- Item_func_dayname(THD *thd, Item *a): Item_func_weekday(thd, a, 0) {}
+ Item_func_dayname(THD *thd, Item *a): Item_str_func(thd, a) {}
const char *func_name() const { return "dayname"; }
String *val_str(String *str);
const Type_handler *type_handler() const { return &type_handler_varchar; }
@@ -476,6 +468,12 @@ class Item_func_dayname :public Item_func_weekday
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC);
}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_dayname>(thd, this); }
};
diff --git a/sql/sql_audit.h b/sql/sql_audit.h
index 59cced13b0a..97317203e34 100644
--- a/sql/sql_audit.h
+++ b/sql/sql_audit.h
@@ -284,7 +284,9 @@ void mysql_audit_notify_connection_change_user(THD *thd)
}
static inline
-void mysql_audit_external_lock(THD *thd, TABLE_SHARE *share, int lock)
+void mysql_audit_external_lock_ex(THD *thd, my_thread_id thread_id,
+ const char *user, const char *host, const char *ip, query_id_t query_id,
+ TABLE_SHARE *share, int lock)
{
if (lock != F_UNLCK && mysql_audit_table_enabled())
{
@@ -293,25 +295,33 @@ void mysql_audit_external_lock(THD *thd, TABLE_SHARE *share, int lock)
event.event_subclass= MYSQL_AUDIT_TABLE_LOCK;
event.read_only= lock == F_RDLCK;
- event.thread_id= (unsigned long)thd->thread_id;
- event.user= sctx->user;
+ event.thread_id= (unsigned long)thread_id;
+ event.user= user;
event.priv_user= sctx->priv_user;
event.priv_host= sctx->priv_host;
event.external_user= sctx->external_user;
event.proxy_user= sctx->proxy_user;
- event.host= sctx->host;
- event.ip= sctx->ip;
+ event.host= host;
+ event.ip= ip;
event.database= share->db;
event.table= share->table_name;
event.new_database= null_clex_str;
event.new_table= null_clex_str;
- event.query_id= thd->query_id;
+ event.query_id= query_id;
mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, &event);
}
}
static inline
+void mysql_audit_external_lock(THD *thd, TABLE_SHARE *share, int lock)
+{
+ mysql_audit_external_lock_ex(thd, thd->thread_id, thd->security_ctx->user,
+ thd->security_ctx->host, thd->security_ctx->ip, thd->query_id,
+ share, lock);
+}
+
+static inline
void mysql_audit_create_table(TABLE *table)
{
if (mysql_audit_table_enabled())
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index c8f4ac05efc..807dd94c6f0 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2193,36 +2193,16 @@ public:
passed from connection thread to the handler thread.
*/
MDL_request grl_protection;
- my_thread_id orig_thread_id;
- void set_default_user()
- {
- thd.security_ctx->user=(char*) delayed_user;
- thd.security_ctx->host=(char*) my_localhost;
- thd.security_ctx->ip= NULL;
- thd.query_id= 0;
- thd.thread_id= orig_thread_id;
- }
-
- void set_user_from_row(const delayed_row *r)
- {
- if (r)
- {
- thd.security_ctx->user= r->user;
- thd.security_ctx->host= r->host;
- thd.security_ctx->ip= r->ip;
- thd.query_id= r->query_id;
- thd.thread_id= r->thread_id;
- }
- }
-
Delayed_insert(SELECT_LEX *current_select)
:locks_in_memory(0), thd(next_thread_id()),
table(0),tables_in_use(0), stacked_inserts(0),
status(0), retry(0), handler_thread_initialized(FALSE), group_count(0)
{
DBUG_ENTER("Delayed_insert constructor");
- orig_thread_id= thd.thread_id;
- set_default_user();
+ thd.security_ctx->user=(char*) delayed_user;
+ thd.security_ctx->host=(char*) my_localhost;
+ thd.security_ctx->ip= NULL;
+ thd.query_id= 0;
strmake_buf(thd.security_ctx->priv_user, thd.security_ctx->user);
thd.current_tablenr=0;
thd.set_command(COM_DELAYED_INSERT);
@@ -3208,7 +3188,6 @@ pthread_handler_t handle_delayed_insert(void *arg)
if (di->tables_in_use && ! thd->lock &&
(!thd->killed || di->stacked_inserts))
{
- di->set_user_from_row(di->rows.head());
/*
Request for new delayed insert.
Lock the table, but avoid to be blocked by a global read lock.
@@ -3230,16 +3209,18 @@ pthread_handler_t handle_delayed_insert(void *arg)
{
delayed_row *row;
I_List_iterator<delayed_row> it(di->rows);
+ my_thread_id cur_thd= di->thd.thread_id;
+
while ((row= it++))
{
- if (di->thd.thread_id != row->thread_id)
+ if (cur_thd != row->thread_id)
{
- di->set_user_from_row(row);
- mysql_audit_external_lock(&di->thd, di->table->s, F_WRLCK);
+ mysql_audit_external_lock_ex(&di->thd, row->thread_id,
+ row->user, row->host, row->ip, row->query_id,
+ di->table->s, F_WRLCK);
+ cur_thd= row->thread_id;
}
}
- di->set_default_user();
-
if (di->handle_inserts())
{
/* Some fatal error */
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 9d22eb1a8cc..0983cea44d0 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1679,28 +1679,6 @@ public:
uint sroutines_list_own_elements;
/**
- Locking state of tables in this particular statement.
-
- If we under LOCK TABLES or in prelocked mode we consider tables
- for the statement to be "locked" if there was a call to lock_tables()
- (which called handler::start_stmt()) for tables of this statement
- and there was no matching close_thread_tables() call.
-
- As result this state may differ significantly from one represented
- by Open_tables_state::lock/locked_tables_mode more, which are always
- "on" under LOCK TABLES or in prelocked mode.
- */
- enum enum_lock_tables_state {
- LTS_NOT_LOCKED = 0,
- LTS_LOCKED
- };
- enum_lock_tables_state lock_tables_state;
- bool is_query_tables_locked()
- {
- return (lock_tables_state == LTS_LOCKED);
- }
-
- /**
Number of tables which were open by open_tables() and to be locked
by lock_tables().
Note that we set this member only in some cases, when this value
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a685c948a3d..d9d9c229c2f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2121,6 +2121,7 @@ JOIN::optimize_inner()
zero_result_cause= "Zero limit";
}
table_count= top_join_tab_count= 0;
+ handle_implicit_grouping_with_window_funcs();
error= 0;
subq_exit_fl= true;
goto setup_subq_exit;
@@ -2168,6 +2169,7 @@ JOIN::optimize_inner()
table_count= top_join_tab_count= 0;
error=0;
subq_exit_fl= true;
+ handle_implicit_grouping_with_window_funcs();
goto setup_subq_exit;
}
if (res > 1)
@@ -2183,6 +2185,7 @@ JOIN::optimize_inner()
tables_list= 0; // All tables resolved
select_lex->min_max_opt_list.empty();
const_tables= top_join_tab_count= table_count;
+ handle_implicit_grouping_with_window_funcs();
/*
Extract all table-independent conditions and replace the WHERE
clause with them. All other conditions were computed by opt_sum_query
@@ -2331,6 +2334,7 @@ int JOIN::optimize_stage2()
zero_result_cause= "no matching row in const table";
DBUG_PRINT("error",("Error: %s", zero_result_cause));
error= 0;
+ handle_implicit_grouping_with_window_funcs();
goto setup_subq_exit;
}
if (!(thd->variables.option_bits & OPTION_BIG_SELECTS) &&
@@ -2362,6 +2366,7 @@ int JOIN::optimize_stage2()
zero_result_cause=
"Impossible WHERE noticed after reading const tables";
select_lex->mark_const_derived(zero_result_cause);
+ handle_implicit_grouping_with_window_funcs();
goto setup_subq_exit;
}
@@ -2524,6 +2529,7 @@ int JOIN::optimize_stage2()
zero_result_cause=
"Impossible WHERE noticed after reading const tables";
select_lex->mark_const_derived(zero_result_cause);
+ handle_implicit_grouping_with_window_funcs();
goto setup_subq_exit;
}
@@ -15741,7 +15747,7 @@ static COND* substitute_for_best_equal_field(THD *thd, JOIN_TAB *context_tab,
}
}
else if (cond->type() == Item::FUNC_ITEM &&
- ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
+ ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
{
item_equal= (Item_equal *) cond;
item_equal->sort(&compare_fields_by_table_order, table_join_idx);
@@ -19614,7 +19620,8 @@ void set_postjoin_aggr_write_func(JOIN_TAB *tab)
}
}
else if (join->sort_and_group && !tmp_tbl->precomputed_group_by &&
- !join->sort_and_group_aggr_tab && join->tables_list)
+ !join->sort_and_group_aggr_tab && join->tables_list &&
+ join->top_join_tab_count)
{
DBUG_PRINT("info",("Using end_write_group"));
aggr->set_write_func(end_write_group);
@@ -25041,7 +25048,8 @@ change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
for (uint i= 0; (item= it++); i++)
{
Field *field;
- if (item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM)
+ if ((item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM) ||
+ item->with_window_func)
item_field= item;
else if (item->type() == Item::FIELD_ITEM)
{
@@ -28607,6 +28615,28 @@ Item *remove_pushed_top_conjuncts(THD *thd, Item *cond)
}
+/*
+ There are 5 cases in which we shortcut the join optimization process as we
+ conclude that the join would be a degenerate one
+ 1) IMPOSSIBLE WHERE
+ 2) MIN/MAX optimization (@see opt_sum_query)
+ 3) EMPTY CONST TABLE
+ If a window function is present in any of the above cases then to get the
+ result of the window function, we need to execute it. So we need to
+ create a temporary table for its execution. Here we need to take in mind
+ that aggregate functions and non-aggregate function need not be executed.
+
+*/
+
+void JOIN::handle_implicit_grouping_with_window_funcs()
+{
+ if (select_lex->have_window_funcs() && send_row_on_empty_set())
+ {
+ const_tables= top_join_tab_count= table_count= 0;
+ }
+}
+
+
/**
@brief
Look for provision of the select_handler interface by a foreign engine
diff --git a/sql/sql_select.h b/sql/sql_select.h
index dcb8326ed8c..b9043a851e7 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1127,6 +1127,7 @@ protected:
Join_plan_state *save_to);
/* Choose a subquery plan for a table-less subquery. */
bool choose_tableless_subquery_plan();
+ void handle_implicit_grouping_with_window_funcs();
public:
void save_query_plan(Join_plan_state *save_to);
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 0dd82f3dfaf..04eb5a25891 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -1785,6 +1785,10 @@ protected:
{
return (ulong) ::calc_daynr((uint) year, (uint) month, (uint) day);
}
+ int weekday(bool sunday_first_day_of_week) const
+ {
+ return ::calc_weekday(daynr(), sunday_first_day_of_week);
+ }
ulong dayofyear() const
{
return (ulong) (daynr() - ::calc_daynr(year, 1, 1) + 1);
@@ -2165,6 +2169,11 @@ public:
DBUG_ASSERT(is_valid_datetime_slow());
return Temporal_with_date::daynr();
}
+ int weekday(bool sunday_first_day_of_week) const
+ {
+ DBUG_ASSERT(is_valid_datetime_slow());
+ return Temporal_with_date::weekday(sunday_first_day_of_week);
+ }
ulong dayofyear() const
{
DBUG_ASSERT(is_valid_datetime_slow());
diff --git a/sql/threadpool_generic.cc b/sql/threadpool_generic.cc
index eb92846ed07..6f8e1982836 100644
--- a/sql/threadpool_generic.cc
+++ b/sql/threadpool_generic.cc
@@ -1322,7 +1322,7 @@ void wait_begin(thread_group_t *thread_group)
DBUG_ASSERT(thread_group->connection_count > 0);
if ((thread_group->active_thread_count == 0) &&
- (is_queue_empty(thread_group) || !thread_group->listener))
+ (!is_queue_empty(thread_group) || !thread_group->listener))
{
/*
Group might stall while this thread waits, thus wake
diff --git a/sql/tztime.cc b/sql/tztime.cc
index c45a6598d69..46a24a137e5 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -2432,7 +2432,7 @@ print_tz_leaps_as_sql(const TIME_ZONE_INFO *sp)
if (!opt_skip_write_binlog)
printf("\\d |\n"
"IF (select count(*) from information_schema.global_variables where\n"
- "variable_name='wsrep_on') = 1 THEN\n"
+ "variable_name='wsrep_on' and variable_value='ON') = 1 THEN\n"
"ALTER TABLE time_zone_leap_second ENGINE=InnoDB;\n"
"END IF|\n"
"\\d ;\n");
@@ -2452,7 +2452,7 @@ print_tz_leaps_as_sql(const TIME_ZONE_INFO *sp)
if (!opt_skip_write_binlog)
printf("\\d |\n"
"IF (select count(*) from information_schema.global_variables where\n"
- "variable_name='wsrep_on') = 1 THEN\n"
+ "variable_name='wsrep_on' and variable_value='ON') = 1 THEN\n"
"ALTER TABLE time_zone_leap_second ENGINE=Aria;\n"
"END IF|\n"
"\\d ;\n");
@@ -2709,7 +2709,7 @@ main(int argc, char **argv)
sql_log_bin and wsrep_on to avoid Galera replicating below
truncate table clauses. This will allow user to set different
time zones to nodes in Galera cluster. */
- printf("set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?');\n"
+ printf("set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?');\n"
"prepare set_wsrep_write_binlog from @prep1;\n"
"set @toggle=0; execute set_wsrep_write_binlog using @toggle;\n");
@@ -2725,7 +2725,7 @@ main(int argc, char **argv)
// to allow changes to them to replicate with Galera
printf("\\d |\n"
"IF (select count(*) from information_schema.global_variables where\n"
- "variable_name='wsrep_on') = 1 THEN\n"
+ "variable_name='wsrep_on' and variable_value='ON') = 1 THEN\n"
"ALTER TABLE time_zone ENGINE=InnoDB;\n"
"ALTER TABLE time_zone_name ENGINE=InnoDB;\n"
"ALTER TABLE time_zone_transition ENGINE=InnoDB;\n"
@@ -2780,7 +2780,7 @@ main(int argc, char **argv)
// Fall back to Aria
printf("\\d |\n"
"IF (select count(*) from information_schema.global_variables where\n"
- "variable_name='wsrep_on') = 1 THEN\n"
+ "variable_name='wsrep_on' and variable_value='ON') = 1 THEN\n"
"ALTER TABLE time_zone ENGINE=Aria;\n"
"ALTER TABLE time_zone_name ENGINE=Aria;\n"
"ALTER TABLE time_zone_transition ENGINE=Aria;\n"
diff --git a/sql/unireg.cc b/sql/unireg.cc
index d019b5f8a75..a1605dac2e6 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -432,7 +432,8 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
pos+= reclength;
int2store(pos, create_info->connect_string.length);
pos+= 2;
- memcpy(pos, create_info->connect_string.str, create_info->connect_string.length);
+ if (create_info->connect_string.length)
+ memcpy(pos, create_info->connect_string.str, create_info->connect_string.length);
pos+= create_info->connect_string.length;
int2store(pos, str_db_type.length);
pos+= 2;