diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-12-27 18:20:28 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-12-27 18:20:28 +0200 |
commit | 4c25e75ce766440694553e0baf03cc5c6e803fc3 (patch) | |
tree | f75cea6e472054b7a15466ea5e31c862ae9e77cc /sql | |
parent | 4c57ab34d4852387da4ef8eac862045d1458de1e (diff) | |
parent | 808bc919eb94ac888f2014275b443ebdaf733ae5 (diff) | |
download | mariadb-git-4c25e75ce766440694553e0baf03cc5c6e803fc3.tar.gz |
Merge 10.3 into 10.4
Diffstat (limited to 'sql')
-rw-r--r-- | sql/CMakeLists.txt | 19 | ||||
-rw-r--r-- | sql/item.cc | 11 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 16 | ||||
-rw-r--r-- | sql/item_timefunc.h | 22 | ||||
-rw-r--r-- | sql/sql_audit.h | 22 | ||||
-rw-r--r-- | sql/sql_insert.cc | 41 | ||||
-rw-r--r-- | sql/sql_lex.h | 22 | ||||
-rw-r--r-- | sql/sql_select.cc | 36 | ||||
-rw-r--r-- | sql/sql_select.h | 1 | ||||
-rw-r--r-- | sql/sql_type.h | 9 | ||||
-rw-r--r-- | sql/threadpool_generic.cc | 2 | ||||
-rw-r--r-- | sql/tztime.cc | 10 | ||||
-rw-r--r-- | sql/unireg.cc | 3 |
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; |