diff --git a/mysql-test/r/analyze_stmt.result b/mysql-test/r/analyze_stmt.result index 7a18dc836e0..256c66ea204 100644 --- a/mysql-test/r/analyze_stmt.result +++ b/mysql-test/r/analyze_stmt.result @@ -16,7 +16,7 @@ id select_type table type possible_keys key key_len ref rows r_rows filtered r_f # ANALYZE DELETE will delete rows: analyze delete from t1 where a in (2,3,4); id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 10 NULL 100.00 30.00 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10 100.00 30.00 Using where select * from t1; a 0 @@ -32,7 +32,7 @@ create table t1(a int, b int); insert into t1 select a,a from t0; analyze update t1 set b=100+b where a in (6,7,8); id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 10 NULL 100.00 30.00 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10 100.00 30.00 Using where select * from t1; a b 0 0 @@ -233,3 +233,12 @@ analyze update t1 set b=12345 where a > 30 and a < 10; id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE drop table t1; +# +# MDEV-6398: ANALYZE UPDATE does not populate r_rows +# +create table t1 (i int); +insert into t1 values (1),(2),(3),(4); +analyze update t1 set i=8; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 4 100.00 100.00 +drop table t1; diff --git a/mysql-test/t/analyze_stmt.test b/mysql-test/t/analyze_stmt.test index 67a7456a473..d2ec554e825 100644 --- a/mysql-test/t/analyze_stmt.test +++ b/mysql-test/t/analyze_stmt.test @@ -183,4 +183,11 @@ analyze update t1 set b=12345 where 1 > 2; analyze update t1 set b=12345 where a > 30 and a < 10; drop table t1; +--echo # +--echo # MDEV-6398: ANALYZE UPDATE does not populate r_rows +--echo # +create table t1 (i int); +insert into t1 values (1),(2),(3),(4); +analyze update t1 set i=8; +drop table t1; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d149d09949f..c241cbf67c2 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -539,10 +539,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, } explain= (Explain_delete*)thd->lex->explain->get_upd_del_plan(); + explain->tracker.on_scan_init(); + while (!(error=info.read_record(&info)) && !thd->killed && ! thd->is_error()) { - explain->on_record_read(); + explain->tracker.on_record_read(); if (table->vfield) update_virtual_fields(thd, table, table->triggers ? VCOL_UPDATE_ALL : @@ -551,7 +553,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, // thd->is_error() is tested to disallow delete row on error if (!select || select->skip_record(thd) > 0) { - explain->on_record_after_where(); + explain->tracker.on_record_after_where(); if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_BEFORE, FALSE)) diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index af51c5fc382..9df4fd965a5 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -957,7 +957,8 @@ int Explain_update::print_explain(Explain_query *query, Single-table DELETE commands do not do "Using temporary". "Using index condition" is also not possible (which is an unjustified limitation) */ - double r_filtered= 100 * (r_rows?((double)r_rows_after_where/r_rows):1.0); + double r_filtered= 100 * tracker.get_filtered_after_where(); + ha_rows r_rows= tracker.get_avg_rows(); print_explain_row(output, explain_flags, is_analyze, 1, /* id */ @@ -970,7 +971,7 @@ int Explain_update::print_explain(Explain_query *query, key_len_buf.length() ? key_len_buf.c_ptr() : NULL, NULL, /* 'ref' is always NULL in single-table EXPLAIN DELETE */ &rows, - &r_rows, + tracker.has_scans()? &r_rows : NULL, r_filtered, extra_str.c_ptr_safe()); diff --git a/sql/sql_explain.h b/sql/sql_explain.h index a36f1676c57..a2b4ea282b7 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -44,6 +44,10 @@ public: return r_filtered; } + + inline void on_scan_init() { r_scans++; } + inline void on_record_read() { r_rows++; } + inline void on_record_after_where() { r_rows_after_where++; } }; @@ -576,14 +580,8 @@ public: bool using_io_buffer; /* ANALYZE members and methods */ - ha_rows r_rows; - ha_rows r_rows_after_where; - inline void on_record_read() { r_rows++; } - inline void on_record_after_where() { r_rows_after_where++; } + Table_access_tracker tracker; - Explain_update() : - r_rows(0), r_rows_after_where(0) - {} virtual int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze); }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 39fc81afc02..05c88a5f534 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -23131,7 +23131,15 @@ int print_explain_row(select_result_sink *result, /* 'r_rows' */ if (is_analyze) - item_list.push_back(item_null); + { + if (r_rows) + { + item_list.push_back(new Item_int(*r_rows, + MY_INT64_NUM_DECIMAL_DIGITS)); + } + else + item_list.push_back(item_null); + } /* 'filtered' */ const double filtered=100.0; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 44d3784becf..d71afe8eab0 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -725,9 +725,11 @@ int mysql_update(THD *thd, if all updated columns are read */ can_compare_record= records_are_comparable(table); + explain->tracker.on_scan_init(); + while (!(error=info.read_record(&info)) && !thd->killed) { - explain->on_record_read(); + explain->tracker.on_record_read(); if (table->vfield) update_virtual_fields(thd, table, table->triggers ? VCOL_UPDATE_ALL : @@ -738,7 +740,7 @@ int mysql_update(THD *thd, if (table->file->was_semi_consistent_read()) continue; /* repeat the read of the same row if it still exists */ - explain->on_record_after_where(); + explain->tracker.on_record_after_where(); store_record(table,record[1]); if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0, TRG_EVENT_UPDATE)) @@ -947,6 +949,7 @@ int mysql_update(THD *thd, end_read_record(&info); delete select; + select= NULL; THD_STAGE_INFO(thd, stage_end); (void) table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); @@ -996,11 +999,7 @@ int mysql_update(THD *thd, id= thd->arg_of_last_insert_id_function ? thd->first_successful_insert_id_in_prev_stmt : 0; - if (thd->lex->analyze_stmt) - { - error= thd->lex->explain->send_explain(thd); - } - else if (error < 0) + if (error < 0 && !thd->lex->analyze_stmt) { char buff[MYSQL_ERRMSG_SIZE]; my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, @@ -1019,10 +1018,14 @@ int mysql_update(THD *thd, } *found_return= found; *updated_return= updated; + + + if (thd->lex->analyze_stmt) + goto emit_explain_and_leave; + DBUG_RETURN((error >= 0 || thd->is_error()) ? 1 : 0); err: - delete select; free_underlaid_joins(thd, select_lex); table->disable_keyread(); @@ -1036,6 +1039,7 @@ produce_explain_and_leave: */ query_plan.save_explain_data(thd->lex->explain); +emit_explain_and_leave: int err2= thd->lex->explain->send_explain(thd); delete select;