diff --git a/mysql-test/main/parser.result b/mysql-test/main/parser.result index 1f4681b2ab0..6899f8df153 100644 --- a/mysql-test/main/parser.result +++ b/mysql-test/main/parser.result @@ -109,7 +109,7 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp create table SUM (a int); drop table SUM; create table SYSDATE(a int); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SYSDATE(a int)' at line 1 +DROP TABLE SYSDATE; create table SYSDATE (a int); drop table SYSDATE; create table SYSTEM_USER(a int); @@ -246,9 +246,9 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp create table SUM (a int); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SUM (a int)' at line 1 create table SYSDATE(a int); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SYSDATE(a int)' at line 1 +DROP TABLE SYSDATE; create table SYSDATE (a int); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SYSDATE (a int)' at line 1 +DROP TABLE SYSDATE; create table SYSTEM_USER(a int); drop table SYSTEM_USER; create table SYSTEM_USER (a int); @@ -2128,5 +2128,44 @@ Warnings: Note 1003 (select `test`.`t1`.`x` AS `x` from `test`.`t1` limit 1) drop table t1; # +# MDEV-19682 sql_mode="oracle" does not support sysdate +# +SELECT sysdate LIKE '____-__-__ __:__:__'; +ERROR 42S22: Unknown column 'sysdate' in 'field list' +SELECT sysdate = sysdate(); +ERROR 42S22: Unknown column 'sysdate' in 'field list' +SELECT sysdate = sysdate(0); +ERROR 42S22: Unknown column 'sysdate' in 'field list' +CREATE DATABASE sysdate; +DROP DATABASE sysdate; +CREATE TABLE sysdate (a INT); +DROP TABLE sysdate; +CREATE TABLE t1 (sysdate INT); +DROP TABLE t1; +CREATE FUNCTION sysdate() RETURNS INT +BEGIN +RETURN 1; +END; +$$ +Warnings: +Note 1585 This function 'sysdate' has the same name as a native function +DROP FUNCTION sysdate; +BEGIN NOT ATOMIC +DECLARE sysdate INT DEFAULT 10; +SELECT sysdate; +END; +$$ +sysdate +10 +BEGIN NOT ATOMIC +DECLARE a INT DEFAULT 0; +sysdate: +WHILE a DO +SELECT 1; +LEAVE sysdate; +END WHILE ; +END; +$$ +# # End of 10.6 tests # diff --git a/mysql-test/main/parser.test b/mysql-test/main/parser.test index 302cd8fbbb3..816e55435d1 100644 --- a/mysql-test/main/parser.test +++ b/mysql-test/main/parser.test @@ -158,8 +158,8 @@ create table SUM(a int); create table SUM (a int); drop table SUM; ---error ER_PARSE_ERROR create table SYSDATE(a int); +DROP TABLE SYSDATE; create table SYSDATE (a int); drop table SYSDATE; @@ -332,10 +332,10 @@ create table SUM(a int); --error ER_PARSE_ERROR create table SUM (a int); ---error ER_PARSE_ERROR create table SYSDATE(a int); ---error ER_PARSE_ERROR +DROP TABLE SYSDATE; create table SYSDATE (a int); +DROP TABLE SYSDATE; create table SYSTEM_USER(a int); drop table SYSTEM_USER; @@ -1900,6 +1900,54 @@ insert into t1 values (1),(2); explain extended (SELECT x FROM t1 WINDOW w1 as () FOR UPDATE) LIMIT 1; explain extended (SELECT x FROM t1 FOR UPDATE) LIMIT 1; drop table t1; +--echo # +--echo # MDEV-19682 sql_mode="oracle" does not support sysdate +--echo # + +--error ER_BAD_FIELD_ERROR +SELECT sysdate LIKE '____-__-__ __:__:__'; +--error ER_BAD_FIELD_ERROR +SELECT sysdate = sysdate(); +--error ER_BAD_FIELD_ERROR +SELECT sysdate = sysdate(0); + +CREATE DATABASE sysdate; +DROP DATABASE sysdate; + +CREATE TABLE sysdate (a INT); +DROP TABLE sysdate; + +CREATE TABLE t1 (sysdate INT); +DROP TABLE t1; + +DELIMITER $$; +CREATE FUNCTION sysdate() RETURNS INT +BEGIN + RETURN 1; +END; +$$ +DELIMITER ;$$ +DROP FUNCTION sysdate; + +DELIMITER $$; +BEGIN NOT ATOMIC + DECLARE sysdate INT DEFAULT 10; + SELECT sysdate; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +BEGIN NOT ATOMIC + DECLARE a INT DEFAULT 0; +sysdate: + WHILE a DO + SELECT 1; + LEAVE sysdate; + END WHILE ; +END; +$$ +DELIMITER ;$$ --echo # --echo # End of 10.6 tests diff --git a/mysql-test/suite/compat/oracle/r/parser.result b/mysql-test/suite/compat/oracle/r/parser.result index 3f02382b6e4..32ea444ea25 100644 --- a/mysql-test/suite/compat/oracle/r/parser.result +++ b/mysql-test/suite/compat/oracle/r/parser.result @@ -806,3 +806,65 @@ ERROR HY000: Unknown data type: 'BEGIN' # # End of 10.5 tests # +# +# Start of 10.6 tests +# +# +# MDEV-19682 sql_mode="oracle" does not support sysdate +# +SELECT sysdate LIKE '____-__-__ __:__:__'; +sysdate LIKE '____-__-__ __:__:__' +1 +SELECT sysdate = sysdate(); +sysdate = sysdate() +1 +SELECT sysdate = sysdate(0); +sysdate = sysdate(0) +1 +CREATE DATABASE sysdate; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sysdate' at line 1 +CREATE TABLE sysdate (a INT); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sysdate (a INT)' at line 1 +CREATE TABLE t1 (sysdate INT); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sysdate INT)' at line 1 +CREATE TABLE t1 (a sysdate); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sysdate)' at line 1 +CREATE FUNCTION sysdate RETURN INT AS +BEGIN +RETURN 1; +END; +$$ +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sysdate RETURN INT AS +BEGIN +RETURN 1; +END' at line 1 +CREATE FUNCTION sysdate() RETURN INT AS +BEGIN +RETURN 1; +END; +$$ +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sysdate() RETURN INT AS +BEGIN +RETURN 1; +END' at line 1 +DECLARE +sysdate INT := 10; +BEGIN +NULL; +END; +$$ +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sysdate INT := 10; +BEGIN +NULL; +END' at line 2 +BEGIN +<> +NULL; +END; +$$ +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sysdate>> +NULL; +END' at line 2 +# +# End of 10.6 tests +# diff --git a/mysql-test/suite/compat/oracle/t/parser.test b/mysql-test/suite/compat/oracle/t/parser.test index d5d3b39f0b9..c2019f258ce 100644 --- a/mysql-test/suite/compat/oracle/t/parser.test +++ b/mysql-test/suite/compat/oracle/t/parser.test @@ -653,3 +653,75 @@ SELECT CAST(1 AS BEGIN); --echo # --echo # End of 10.5 tests --echo # + + +--echo # +--echo # Start of 10.6 tests +--echo # + +--echo # +--echo # MDEV-19682 sql_mode="oracle" does not support sysdate +--echo # + +# SYSDATE is not deterministic. Let's use LIKE and equality. +# The main point here is only to check that SYSDATE +# gets parsed without parentheses. The actial value is not important. +SELECT sysdate LIKE '____-__-__ __:__:__'; +SELECT sysdate = sysdate(); +SELECT sysdate = sysdate(0); + +--error ER_PARSE_ERROR +CREATE DATABASE sysdate; + +--error ER_PARSE_ERROR +CREATE TABLE sysdate (a INT); + +--error ER_PARSE_ERROR +CREATE TABLE t1 (sysdate INT); + +--error ER_PARSE_ERROR +CREATE TABLE t1 (a sysdate); + +DELIMITER $$; +--error ER_PARSE_ERROR +CREATE FUNCTION sysdate RETURN INT AS +BEGIN + RETURN 1; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_PARSE_ERROR +CREATE FUNCTION sysdate() RETURN INT AS +BEGIN + RETURN 1; +END; +$$ +DELIMITER ;$$ + + +DELIMITER $$; +--error ER_PARSE_ERROR +DECLARE + sysdate INT := 10; +BEGIN + NULL; +END; +$$ +DELIMITER ;$$ + + +DELIMITER $$; +--error ER_PARSE_ERROR +BEGIN +<> + NULL; +END; +$$ +DELIMITER ;$$ + + +--echo # +--echo # End of 10.6 tests +--echo # diff --git a/sql/lex.h b/sql/lex.h index fb701f0afd4..ba0450f1de9 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -648,6 +648,7 @@ static SYMBOL symbols[] = { { "SUSPEND", SYM(SUSPEND_SYM)}, { "SWAPS", SYM(SWAPS_SYM)}, { "SWITCHES", SYM(SWITCHES_SYM)}, + { "SYSDATE", SYM(SYSDATE)}, { "SYSTEM", SYM(SYSTEM)}, { "SYSTEM_TIME", SYM(SYSTEM_TIME_SYM)}, { "TABLE", SYM(TABLE_SYM)}, @@ -787,7 +788,6 @@ static SYMBOL sql_functions[] = { { "SUBSTR", SYM(SUBSTRING)}, { "SUBSTRING", SYM(SUBSTRING)}, { "SUM", SYM(SUM_SYM)}, - { "SYSDATE", SYM(SYSDATE)}, { "SYSTEM_USER", SYM(USER_SYM)}, { "TRIM", SYM(TRIM)}, { "TRIM_ORACLE", SYM(TRIM_ORACLE)}, diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a9d1832d662..c347dd06420 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -9341,6 +9341,26 @@ Item *LEX::make_item_func_substr(THD *thd, Item *a, Item *b) } +Item *LEX::make_item_func_sysdate(THD *thd, uint fsp) +{ + /* + Unlike other time-related functions, SYSDATE() is + replication-unsafe because it is not affected by the + TIMESTAMP variable. It is unsafe even if + sysdate_is_now=1, because the slave may have + sysdate_is_now=0. + */ + set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); + Item *item= global_system_variables.sysdate_is_now == 0 ? + (Item *) new (thd->mem_root) Item_func_sysdate_local(thd, fsp) : + (Item *) new (thd->mem_root) Item_func_now_local(thd, fsp); + if (unlikely(item == NULL)) + return NULL; + safe_to_cache_query=0; + return item; +} + + Item *LEX::make_item_func_replace(THD *thd, Item *org, Item *find, diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 498e8edcf50..4c0bbb0c9e3 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -4101,6 +4101,7 @@ public: Item *make_item_func_replace(THD *thd, Item *org, Item *find, Item *replace); Item *make_item_func_substr(THD *thd, Item *a, Item *b, Item *c); Item *make_item_func_substr(THD *thd, Item *a, Item *b); + Item *make_item_func_sysdate(THD *thd, uint fsp); Item *make_item_func_call_generic(THD *thd, Lex_ident_cli_st *db, Lex_ident_cli_st *name, List *args); Item *make_item_func_call_native_or_parse_error(THD *thd, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f589bbf5b99..056f0e02f41 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -10361,23 +10361,22 @@ function_call_nonkeyword: if (unlikely(!($$= Lex->make_item_func_substr(thd, $3, $5)))) MYSQL_YYABORT; } - | SYSDATE opt_time_precision +/* Start SQL_MODE_ORACLE_SPECIFIC + | SYSDATE { - /* - Unlike other time-related functions, SYSDATE() is - replication-unsafe because it is not affected by the - TIMESTAMP variable. It is unsafe even if - sysdate_is_now=1, because the slave may have - sysdate_is_now=0. - */ - Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); - if (global_system_variables.sysdate_is_now == 0) - $$= new (thd->mem_root) Item_func_sysdate_local(thd, $2); - else - $$= new (thd->mem_root) Item_func_now_local(thd, $2); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - Lex->safe_to_cache_query=0; + if (unlikely(!($$= Lex->make_item_func_sysdate(thd, 0)))) + MYSQL_YYABORT; + } +End SQL_MODE_ORACLE_SPECIFIC */ + | SYSDATE '(' ')' + { + if (unlikely(!($$= Lex->make_item_func_sysdate(thd, 0)))) + MYSQL_YYABORT; + } + | SYSDATE '(' real_ulong_num ')' + { + if (unlikely(!($$= Lex->make_item_func_sysdate(thd, (uint) $3)))) + MYSQL_YYABORT; } | TIMESTAMP_ADD '(' interval_time_stamp ',' expr ',' expr ')' { @@ -16144,6 +16143,9 @@ keyword_sp_var_and_label: | SUSPEND_SYM | SWAPS_SYM | SWITCHES_SYM +/* Start SQL_MODE_DEFAULT_SPECIFIC */ + | SYSDATE +/* End SQL_MODE_DEFAULT_SPECIFIC */ | SYSTEM | SYSTEM_TIME_SYM | TABLE_NAME_SYM @@ -16393,7 +16395,6 @@ reserved_keyword_udt_not_param_type: | STRAIGHT_JOIN | SUBSTRING | SUM_SYM - | SYSDATE | TABLE_REF_PRIORITY | TABLE_SYM | TERMINATED