diff --git a/mysql-test/main/mdev_31342.result b/mysql-test/main/mdev_31342.result index e59d1092309..aba61517d19 100644 --- a/mysql-test/main/mdev_31342.result +++ b/mysql-test/main/mdev_31342.result @@ -794,6 +794,11 @@ EXPLAIN } } # +# MDEV-41164: SELECT INTO OUTFILE must use the fallback path +# +SELECT TABLE_NAME INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/mdev_31342_outfile.txt' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='mysql' AND TABLE_NAME='user'; +user +# # MDEV-41167: LIMIT 1 must stop after a matching row, not the first scan # CREATE DATABASE mdev41167; diff --git a/mysql-test/main/mdev_31342.test b/mysql-test/main/mdev_31342.test index 4d642b6dff9..d1a542f93f2 100644 --- a/mysql-test/main/mdev_31342.test +++ b/mysql-test/main/mdev_31342.test @@ -302,6 +302,15 @@ DEALLOCATE PREPARE stmt3; EXPLAIN FORMAT=JSON SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'mysql' AND TABLE_NAME = 'user'; +--echo # +--echo # MDEV-41164: SELECT INTO OUTFILE must use the fallback path +--echo # +--let $outfile= $MYSQLTEST_VARDIR/tmp/mdev_31342_outfile.txt +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT TABLE_NAME INTO OUTFILE '$outfile' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='mysql' AND TABLE_NAME='user' +--cat_file $outfile +--remove_file $outfile + --echo # --echo # MDEV-41167: LIMIT 1 must stop after a matching row, not the first scan --echo # diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e4b07b942f9..baf0ee7534d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4241,6 +4241,37 @@ static bool is_simple_is_query(THD *thd) } } } + /* + ANALYZE SELECT also executes the query, then sends EXPLAIN via a + second result set. Streaming + my_eof() here races that. + */ + if (thd->lex->analyze_stmt) + { + DBUG_PRINT("info", ("ANALYZE statement, using fallback path")); + return false; + } + /* + INTO OUTFILE / DUMPFILE / @var need the interceptor result sink, + not the client protocol. + */ + if (thd->lex->exchange || + (thd->lex->result && thd->lex->result->result_interceptor())) + { + DBUG_PRINT("info", ("result interceptor, using fallback path")); + return false; + } + /* PROCEDURE ANALYSE() rewrites the result set. */ + if (thd->lex->proc_list.elements) + { + DBUG_PRINT("info", ("PROCEDURE ANALYSE, using fallback path")); + return false; + } + /* SQL_BUFFER_RESULT materializes into a tmp table first. */ + if (sel->options & OPTION_BUFFER_RESULT) + { + DBUG_PRINT("info", ("SQL_BUFFER_RESULT, using fallback path")); + return false; + } /* Only allow no LIMIT, or LIMIT 1 exactly. Any other explicit LIMIT n is rejected until a general LIMIT implementation is validated. @@ -10234,8 +10265,15 @@ bool get_schema_tables_result(JOIN *join, !thd->bootstrap && !thd->spcont && !is_show_command(thd) && join->result && + !join->result->result_interceptor() && + !thd->lex->analyze_stmt && + !thd->lex->exchange && + !thd->lex->proc_list.elements && + !thd->is_cursor_execution() && thd->lex->sql_command == SQLCOM_SELECT && - !(join->select_options & SELECT_DESCRIBE) && + !(join->select_options & + (SELECT_DESCRIBE | OPTION_BUFFER_RESULT)) && + thd->protocol->type() != Protocol::PROTOCOL_DISCARD && join->table_count == 1 && thd->lex->query_tables == table_list && !table_list->next_global &&