Commit d44dd54b authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-6400: "ANALYZE SELECT ... INTO @var" doesn't set @var

Make ANALYZE work for
- ANALYZE SELECT ... INTO @var
- ANALYZE INSERT SELECT ...;
- ANALYZE SELECT .. INTO OUTFILE
parent fec5ab5a
...@@ -276,3 +276,20 @@ select * from t1; ...@@ -276,3 +276,20 @@ select * from t1;
a b a b
1 2 1 2
drop table t1; drop table t1;
#
# MDEV-6400 "ANALYZE SELECT ... INTO @var" doesn't set @var
#
create table t1(a int);
insert into t1 values (1),(2);
analyze select a from t1 where a <2 into @var;
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 2 2 100.00 50.00 Using where
analyze select a from t1 into @var;
ERROR 42000: Result consisted of more than one row
analyze insert into t1 select * from t1;
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 2 2 100.00 100.00 Using temporary
analyze select * into outfile '../../tmp/data1.tmp' from t1;
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;
...@@ -217,3 +217,19 @@ analyze replace t1 values (1,2); ...@@ -217,3 +217,19 @@ analyze replace t1 values (1,2);
select * from t1; select * from t1;
drop table t1; drop table t1;
--echo #
--echo # MDEV-6400 "ANALYZE SELECT ... INTO @var" doesn't set @var
--echo #
create table t1(a int);
insert into t1 values (1),(2);
analyze select a from t1 where a <2 into @var;
--error ER_TOO_MANY_ROWS
analyze select a from t1 into @var;
analyze insert into t1 select * from t1;
analyze select * into outfile '../../tmp/data1.tmp' from t1;
--remove_file $MYSQLTEST_VARDIR/tmp/data1.tmp
drop table t1;
...@@ -2710,7 +2710,7 @@ bool select_to_file::send_eof() ...@@ -2710,7 +2710,7 @@ bool select_to_file::send_eof()
if (mysql_file_close(file, MYF(MY_WME)) || thd->is_error()) if (mysql_file_close(file, MYF(MY_WME)) || thd->is_error())
error= true; error= true;
if (!error) if (!error && !suppress_my_ok)
{ {
::my_ok(thd,row_count); ::my_ok(thd,row_count);
} }
...@@ -3786,11 +3786,14 @@ bool select_dumpvar::send_eof() ...@@ -3786,11 +3786,14 @@ bool select_dumpvar::send_eof()
if (thd->is_error()) if (thd->is_error())
return true; return true;
::my_ok(thd,row_count); if (!suppress_my_ok)
::my_ok(thd,row_count);
return 0; return 0;
} }
bool bool
select_materialize_with_stats:: select_materialize_with_stats::
create_result_table(THD *thd_arg, List<Item> *column_types, create_result_table(THD *thd_arg, List<Item> *column_types,
......
...@@ -3956,6 +3956,14 @@ public: ...@@ -3956,6 +3956,14 @@ public:
{ {
unit->offset_limit_cnt= 0; unit->offset_limit_cnt= 0;
} }
/*
This returns
- FALSE if the class sends output row to the client
- TRUE if the output is set elsewhere (a file, @variable, or table).
Currently all intercepting classes derive from select_result_interceptor.
*/
virtual bool is_result_interceptor()=0;
}; };
...@@ -3986,6 +3994,8 @@ public: ...@@ -3986,6 +3994,8 @@ public:
/* /*
This is a select_result_sink which stores the data in text form. This is a select_result_sink which stores the data in text form.
It is only used to save EXPLAIN output.
*/ */
class select_result_text_buffer : public select_result_sink class select_result_text_buffer : public select_result_sink
...@@ -4014,7 +4024,7 @@ private: ...@@ -4014,7 +4024,7 @@ private:
class select_result_interceptor: public select_result class select_result_interceptor: public select_result
{ {
public: public:
select_result_interceptor() select_result_interceptor() : suppress_my_ok(false)
{ {
DBUG_ENTER("select_result_interceptor::select_result_interceptor"); DBUG_ENTER("select_result_interceptor::select_result_interceptor");
DBUG_PRINT("enter", ("this 0x%lx", (ulong) this)); DBUG_PRINT("enter", ("this 0x%lx", (ulong) this));
...@@ -4022,6 +4032,15 @@ public: ...@@ -4022,6 +4032,15 @@ public:
} /* Remove gcc warning */ } /* Remove gcc warning */
uint field_count(List<Item> &fields) const { return 0; } uint field_count(List<Item> &fields) const { return 0; }
bool send_result_set_metadata(List<Item> &fields, uint flag) { return FALSE; } bool send_result_set_metadata(List<Item> &fields, uint flag) { return FALSE; }
bool is_result_interceptor() { return true; }
/*
Instruct the object to not call my_ok(). Client output will be handled
elsewhere. (this is used by ANALYZE $stmt feature).
*/
void disable_my_ok_calls() { suppress_my_ok= true; }
protected:
bool suppress_my_ok;
}; };
...@@ -4040,6 +4059,7 @@ public: ...@@ -4040,6 +4059,7 @@ public:
virtual bool check_simple_select() const { return FALSE; } virtual bool check_simple_select() const { return FALSE; }
void abort_result_set(); void abort_result_set();
virtual void cleanup(); virtual void cleanup();
bool is_result_interceptor() { return true; }
}; };
......
...@@ -3712,6 +3712,10 @@ bool select_insert::send_eof() ...@@ -3712,6 +3712,10 @@ bool select_insert::send_eof()
table->file->print_error(error,MYF(0)); table->file->print_error(error,MYF(0));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (suppress_my_ok)
DBUG_RETURN(0);
char buff[160]; char buff[160];
if (info.ignore) if (info.ignore)
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
......
...@@ -3814,6 +3814,9 @@ end_with_restore_list: ...@@ -3814,6 +3814,9 @@ end_with_restore_list:
lex->duplicates, lex->duplicates,
lex->ignore))) lex->ignore)))
{ {
if (lex->analyze_stmt)
((select_result_interceptor*)sel_result)->disable_my_ok_calls();
res= handle_select(thd, lex, sel_result, OPTION_SETUP_TABLES_DONE); res= handle_select(thd, lex, sel_result, OPTION_SETUP_TABLES_DONE);
/* /*
Invalidate the table in the query cache if something changed Invalidate the table in the query cache if something changed
...@@ -3833,7 +3836,7 @@ end_with_restore_list: ...@@ -3833,7 +3836,7 @@ end_with_restore_list:
delete sel_result; delete sel_result;
} }
if (!res && explain) if (!res && (explain || lex->analyze_stmt))
res= thd->lex->explain->send_explain(thd); res= thd->lex->explain->send_explain(thd);
/* revert changes for SP */ /* revert changes for SP */
...@@ -5649,12 +5652,18 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) ...@@ -5649,12 +5652,18 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
} }
else else
{ {
Protocol *save_protocol; Protocol *save_protocol= NULL;
if (lex->analyze_stmt) if (lex->analyze_stmt)
{ {
result= new select_send_analyze(); if (result && result->is_result_interceptor())
save_protocol= thd->protocol; ((select_result_interceptor*)result)->disable_my_ok_calls();
thd->protocol= new Protocol_discard(thd); else
{
DBUG_ASSERT(thd->protocol);
result= new select_send_analyze();
save_protocol= thd->protocol;
thd->protocol= new Protocol_discard(thd);
}
} }
else else
{ {
...@@ -5668,8 +5677,11 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) ...@@ -5668,8 +5677,11 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
if (lex->analyze_stmt) if (lex->analyze_stmt)
{ {
delete thd->protocol; if (save_protocol)
thd->protocol= save_protocol; {
delete thd->protocol;
thd->protocol= save_protocol;
}
if (!res) if (!res)
res= thd->lex->explain->send_explain(thd); res= thd->lex->explain->send_explain(thd);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment