diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index b67fa9322ee..9cde630e4ed 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -176,21 +176,6 @@ a 1 2 3 -select * from t1 union select sql_cache * from t1; -a -1 -2 -3 -select * from t1 where a IN (select sql_cache a from t1); -a -1 -2 -3 -select * from t1 where a IN (select a from t1 union select sql_cache a from t1); -a -1 -2 -3 show status like "Qcache_hits"; Variable_name Value Qcache_hits 4 @@ -207,41 +192,6 @@ a 1 2 3 -select * from t1 union select sql_no_cache * from t1; -a -1 -2 -3 -select * from t1 where a IN (select sql_no_cache a from t1); -a -1 -2 -3 -select * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); -a -1 -2 -3 -select sql_cache sql_no_cache * from t1; -a -1 -2 -3 -select sql_cache * from t1 union select sql_no_cache * from t1; -a -1 -2 -3 -select sql_cache * from t1 where a IN (select sql_no_cache a from t1); -a -1 -2 -3 -select sql_cache * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); -a -1 -2 -3 show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 @@ -1490,12 +1440,6 @@ insert into t1 values ('c'); a drop table t1; set GLOBAL query_cache_size= default; -set GLOBAL query_cache_size=1000000; -create table t1 (a char); -insert into t1 values ('c'); -a -drop table t1; -set GLOBAL query_cache_size= default; SET GLOBAL query_cache_size=64*1024*1024; CREATE TABLE t1 (id INT); CREATE PROCEDURE proc29856(IN theUPC TEXT) @@ -1723,4 +1667,55 @@ SELECT 1 FROM t1 GROUP BY 1 DROP TABLE t1; SET GLOBAL query_cache_size= default; +CREATE TABLE t1( a INT ); +SET @v = ( SELECT SQL_CACHE 1 ); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1 )' at line 1 +SET @v = ( SELECT SQL_NO_CACHE 1 ); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1 )' at line 1 +SELECT a FROM t1 WHERE a IN ( SELECT SQL_CACHE a FROM t1 ); +ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +SELECT a FROM t1 WHERE a IN ( SELECT SQL_NO_CACHE a FROM t1 ); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +SELECT ( SELECT SQL_CACHE a FROM t1 ); +ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +SELECT ( SELECT SQL_NO_CACHE a FROM t1 ); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +SELECT SQL_CACHE * FROM t1; +a +SELECT SQL_NO_CACHE * FROM t1; +a +SELECT * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' +SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' +SELECT * FROM t1 WHERE a IN (SELECT SQL_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' +SELECT * FROM t1 WHERE a IN (SELECT SQL_NO_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +SELECT * FROM t1 WHERE a IN +(SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +SELECT SQL_CACHE SQL_NO_CACHE * FROM t1; +ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE +SELECT SQL_NO_CACHE SQL_CACHE * FROM t1; +ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE +SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' +SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' +SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' +SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' +SELECT SQL_CACHE * FROM t1 WHERE a IN +(SELECT SQL_NO_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +SELECT SQL_CACHE * FROM t1 WHERE a IN +(SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 50384149a26..44544724848 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -737,20 +737,11 @@ View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache now() AS `NOW()` binary binary DROP VIEW v1; CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE NOW(); -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache now() AS `NOW()` binary binary -DROP VIEW v1; +ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE CREATE VIEW v1 AS SELECT SQL_NO_CACHE SQL_CACHE NOW(); -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache now() AS `NOW()` binary binary -DROP VIEW v1; +ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE SQL_CACHE NOW(); -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache now() AS `NOW()` binary binary -DROP VIEW v1; +ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE CREATE PROCEDURE p1() BEGIN SET @s= 'CREATE VIEW v1 AS SELECT SQL_CACHE 1'; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 0edc9cca385..d6e73cbc88d 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -94,10 +94,6 @@ select sql_cache * from t1 union select * from t1; set query_cache_type=2; select sql_cache * from t1 union select * from t1; -# all sql_cache statements, except for the first select, are ignored. -select * from t1 union select sql_cache * from t1; -select * from t1 where a IN (select sql_cache a from t1); -select * from t1 where a IN (select a from t1 union select sql_cache a from t1); show status like "Qcache_hits"; show status like "Qcache_queries_in_cache"; set query_cache_type=on; @@ -110,15 +106,6 @@ show status like "Qcache_queries_in_cache"; # SELECT SQL_NO_CACHE # select sql_no_cache * from t1; -# sql_no_cache can occur in any nested select to turn on cacheing for the whole -# expression and it will always override a sql_cache statement. -select * from t1 union select sql_no_cache * from t1; -select * from t1 where a IN (select sql_no_cache a from t1); -select * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); -select sql_cache sql_no_cache * from t1; -select sql_cache * from t1 union select sql_no_cache * from t1; -select sql_cache * from t1 where a IN (select sql_no_cache a from t1); -select sql_cache * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); show status like "Qcache_queries_in_cache"; drop table t1; # @@ -1044,22 +1031,25 @@ set GLOBAL query_cache_size= default; # Bug #29053 SQL_CACHE in UNION causes non-deterministic functions to be cached # -set GLOBAL query_cache_size=1000000; - -create table t1 (a char); -insert into t1 values ('c'); - -let $q1= `select RAND() from t1 union select sql_cache 1 from t1;`; -let $q2= `select RAND() from t1 union select sql_cache 1 from t1;`; - +# This syntax is no longer allowed, therefore the test case has been commented +# out. +# See test for Bug#35020 below. +#set GLOBAL query_cache_size=1000000; +# +#create table t1 (a char); +#insert into t1 values ('c'); +# +#let $q1= `select RAND() from t1 union select sql_cache 1 from t1;`; +#let $q2= `select RAND() from t1 union select sql_cache 1 from t1;`; +# # disabling the logging of the query because the times are different each run. ---disable_query_log -eval select a from t1 where "$q1" = "$q2"; ---enable_query_log - -drop table t1; - -set GLOBAL query_cache_size= default; +#--disable_query_log +#eval select a from t1 where "$q1" = "$q2"; +#--enable_query_log +# +#drop table t1; +# +#set GLOBAL query_cache_size= default; # # Bug#29856: Insufficient buffer space led to a server crash. @@ -1307,5 +1297,69 @@ SELECT 1 FROM t1 GROUP BY DROP TABLE t1; SET GLOBAL query_cache_size= default; ---echo End of 5.1 tests +# +# Bug#35020: illegal sql_cache select syntax +# +CREATE TABLE t1( a INT ); + +--error ER_PARSE_ERROR +SET @v = ( SELECT SQL_CACHE 1 ); +--error ER_PARSE_ERROR +SET @v = ( SELECT SQL_NO_CACHE 1 ); + +# +# Keywords 'SQL_CACHE' and 'SQL_NO_CACHE' are allowed as column names. +# Hence the error messages are not intuitive. +# +--error ER_BAD_FIELD_ERROR +SELECT a FROM t1 WHERE a IN ( SELECT SQL_CACHE a FROM t1 ); +--error ER_BAD_FIELD_ERROR +SELECT a FROM t1 WHERE a IN ( SELECT SQL_NO_CACHE a FROM t1 ); +--error ER_BAD_FIELD_ERROR +SELECT ( SELECT SQL_CACHE a FROM t1 ); +--error ER_BAD_FIELD_ERROR +SELECT ( SELECT SQL_NO_CACHE a FROM t1 ); + +SELECT SQL_CACHE * FROM t1; +SELECT SQL_NO_CACHE * FROM t1; + +# SQL_CACHE is only allowed once in first top-level select. +--error ER_CANT_USE_OPTION_HERE +SELECT * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +--error ER_CANT_USE_OPTION_HERE +SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +--error ER_BAD_FIELD_ERROR +SELECT * FROM t1 WHERE a IN (SELECT SQL_CACHE a FROM t1); +--error ER_BAD_FIELD_ERROR +SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_CACHE a FROM t1); + +--error ER_CANT_USE_OPTION_HERE +SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +--error ER_BAD_FIELD_ERROR +SELECT * FROM t1 WHERE a IN (SELECT SQL_NO_CACHE a FROM t1); +--error ER_BAD_FIELD_ERROR +SELECT * FROM t1 WHERE a IN + (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); +--error ER_WRONG_USAGE +SELECT SQL_CACHE SQL_NO_CACHE * FROM t1; +--error ER_WRONG_USAGE +SELECT SQL_NO_CACHE SQL_CACHE * FROM t1; +--error ER_CANT_USE_OPTION_HERE +SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +--error ER_CANT_USE_OPTION_HERE +SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +--error ER_CANT_USE_OPTION_HERE +SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +--error ER_CANT_USE_OPTION_HERE +SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +--error ER_BAD_FIELD_ERROR +SELECT SQL_CACHE * FROM t1 WHERE a IN + (SELECT SQL_NO_CACHE a FROM t1); +--error ER_BAD_FIELD_ERROR +SELECT SQL_CACHE * FROM t1 WHERE a IN + (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); + +DROP TABLE t1; + +--echo End of 5.1 tests diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 6e07f717db6..6d1d493168c 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -550,18 +550,14 @@ CREATE VIEW v1 AS SELECT SQL_NO_CACHE NOW(); SHOW CREATE VIEW v1; DROP VIEW v1; -# Check that SQL_NO_CACHE always wins. +--error ER_WRONG_USAGE CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE NOW(); -SHOW CREATE VIEW v1; -DROP VIEW v1; +--error ER_WRONG_USAGE CREATE VIEW v1 AS SELECT SQL_NO_CACHE SQL_CACHE NOW(); -SHOW CREATE VIEW v1; -DROP VIEW v1; +--error ER_WRONG_USAGE CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE SQL_CACHE NOW(); -SHOW CREATE VIEW v1; -DROP VIEW v1; # Check CREATE VIEW in a prepared statement in a procedure. delimiter |; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a57897f4eac..533db6fdd6e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -735,10 +735,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %pure_parser /* We have threads */ /* - Currently there are 173 shift/reduce conflicts. + Currently there are 172 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 173 +%expect 172 /* Comments for TOKENS. @@ -7098,50 +7098,63 @@ select_option_list: ; select_option: - STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; } - | HIGH_PRIORITY - { - if (check_simple_select()) - MYSQL_YYABORT; - Lex->lock_option= TL_READ_HIGH_PRIORITY; - Lex->current_select->lock_option= TL_READ_HIGH_PRIORITY; - } - | DISTINCT { Select->options|= SELECT_DISTINCT; } - | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } - | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; } - | SQL_BUFFER_RESULT - { - if (check_simple_select()) - MYSQL_YYABORT; - Select->options|= OPTION_BUFFER_RESULT; - } - | SQL_CALC_FOUND_ROWS - { - if (check_simple_select()) - MYSQL_YYABORT; - Select->options|= OPTION_FOUND_ROWS; - } + query_expression_option | SQL_NO_CACHE_SYM { - Lex->safe_to_cache_query=0; - Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE; - Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE; + /* + Allow this flag only on the first top-level SELECT statement, if + SQL_CACHE wasn't specified, and only once per query. + */ + if (Lex->current_select != &Lex->select_lex) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"); + MYSQL_YYABORT; + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE) + { + my_error(ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"); + MYSQL_YYABORT; + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE) + { + my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"); + MYSQL_YYABORT; + } + else + { + Lex->safe_to_cache_query=0; + Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE; + Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE; + } } | SQL_CACHE_SYM { - /* - Honor this flag only if SQL_NO_CACHE wasn't specified AND - we are parsing the outermost SELECT in the query. - */ - if (Lex->select_lex.sql_cache != SELECT_LEX::SQL_NO_CACHE && - Lex->current_select == &Lex->select_lex) + /* + Allow this flag only on the first top-level SELECT statement, if + SQL_NO_CACHE wasn't specified, and only once per query. + */ + if (Lex->current_select != &Lex->select_lex) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"); + MYSQL_YYABORT; + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE) + { + my_error(ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"); + MYSQL_YYABORT; + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE) + { + my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"); + MYSQL_YYABORT; + } + else { Lex->safe_to_cache_query=1; Lex->select_lex.options|= OPTION_TO_QUERY_CACHE; Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE; } } - | ALL { Select->options|= SELECT_ALL; } ; select_lock_type: @@ -9213,7 +9226,7 @@ select_part2_derived: mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LIST; } - select_options select_item_list + opt_query_expression_options select_item_list { Select->parsing_place= NO_MATTER; } @@ -13561,6 +13574,43 @@ subselect_end: } ; +opt_query_expression_options: + /* empty */ + | query_expression_option_list + ; + +query_expression_option_list: + query_expression_option_list query_expression_option + | query_expression_option + ; + +query_expression_option: + STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; } + | HIGH_PRIORITY + { + if (check_simple_select()) + MYSQL_YYABORT; + Lex->lock_option= TL_READ_HIGH_PRIORITY; + Lex->current_select->lock_option= TL_READ_HIGH_PRIORITY; + } + | DISTINCT { Select->options|= SELECT_DISTINCT; } + | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } + | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; } + | SQL_BUFFER_RESULT + { + if (check_simple_select()) + MYSQL_YYABORT; + Select->options|= OPTION_BUFFER_RESULT; + } + | SQL_CALC_FOUND_ROWS + { + if (check_simple_select()) + MYSQL_YYABORT; + Select->options|= OPTION_FOUND_ROWS; + } + | ALL { Select->options|= SELECT_ALL; } + ; + /************************************************************************** CREATE VIEW | TRIGGER | PROCEDURE statements.