diff --git a/mysql-test/r/type_timestamp_hires.result b/mysql-test/r/type_timestamp_hires.result index 070f3032987..cc2cb6a403d 100644 --- a/mysql-test/r/type_timestamp_hires.result +++ b/mysql-test/r/type_timestamp_hires.result @@ -278,3 +278,23 @@ select * from t1; a 2011-01-01 01:01:01.12345 drop table t1; +create table t1 (a timestamp(5) default current_timestamp); +drop table t1; +create table t1 (a timestamp(5) default current_timestamp()); +drop table t1; +create table t1 (a timestamp(5) default current_timestamp(2)); +ERROR 42000: Invalid default value for 'a' +create table t1 (a timestamp(5) default current_timestamp(5)); +drop table t1; +create table t1 (a timestamp(5) default current_timestamp(6)); +drop table t1; +create table t1 (a timestamp(5) on update current_timestamp); +drop table t1; +create table t1 (a timestamp(5) on update current_timestamp()); +drop table t1; +create table t1 (a timestamp(5) on update current_timestamp(3)); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +create table t1 (a timestamp(5) on update current_timestamp(5)); +drop table t1; +create table t1 (a timestamp(5) on update current_timestamp(6)); +drop table t1; diff --git a/mysql-test/t/type_timestamp_hires.test b/mysql-test/t/type_timestamp_hires.test index 8e1f8586956..17a2c3e1f1f 100644 --- a/mysql-test/t/type_timestamp_hires.test +++ b/mysql-test/t/type_timestamp_hires.test @@ -14,3 +14,18 @@ insert t1 values (); select * from t1; drop table t1; +# +# MDEV-438 Microseconds: Precision is ignored in CURRENT_TIMESTAMP(N) when it is given as a default column value +# +create table t1 (a timestamp(5) default current_timestamp); drop table t1; +create table t1 (a timestamp(5) default current_timestamp()); drop table t1; +--error ER_INVALID_DEFAULT +create table t1 (a timestamp(5) default current_timestamp(2)); +create table t1 (a timestamp(5) default current_timestamp(5)); drop table t1; +create table t1 (a timestamp(5) default current_timestamp(6)); drop table t1; +create table t1 (a timestamp(5) on update current_timestamp); drop table t1; +create table t1 (a timestamp(5) on update current_timestamp()); drop table t1; +--error ER_INVALID_ON_UPDATE +create table t1 (a timestamp(5) on update current_timestamp(3)); +create table t1 (a timestamp(5) on update current_timestamp(5)); drop table t1; +create table t1 (a timestamp(5) on update current_timestamp(6)); drop table t1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7bc4f8f1833..3cab8e17533 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5955,6 +5955,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, { register Create_field *new_field; LEX *lex= thd->lex; + uint8 datetime_precision= length ? atoi(length) : 0; DBUG_ENTER("add_field_to_list"); if (check_string_char_length(field_name, "", NAME_CHAR_LEN, @@ -5994,8 +5995,10 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, NOW() as default for TIMESTAMP and DATETIME type. */ if (default_value->type() == Item::FUNC_ITEM && - !(((Item_func*)default_value)->functype() == Item_func::NOW_FUNC && - (type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_DATETIME))) + (static_cast(default_value)->functype() != + Item_func::NOW_FUNC || + (mysql_type_to_time_type(type) != MYSQL_TIMESTAMP_DATETIME) || + default_value->decimals < datetime_precision)) { my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str); DBUG_RETURN(1); @@ -6018,7 +6021,8 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, } if (on_update_value && - !(type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_DATETIME)) + (mysql_type_to_time_type(type) != MYSQL_TIMESTAMP_DATETIME || + on_update_value->decimals < datetime_precision)) { my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name->str); DBUG_RETURN(1); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2d99b054e14..ae3a1009f64 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1483,6 +1483,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt optional_flush_tables_arguments opt_dyncol_type dyncol_type opt_time_precision kill_type kill_option int_num + opt_default_time_precision %type opt_chain opt_release @@ -5898,7 +5899,7 @@ attribute: NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; } | not NULL_SYM { Lex->type|= NOT_NULL_FLAG; } | DEFAULT now_or_signed_literal { Lex->default_value=$2; } - | ON UPDATE_SYM NOW_SYM opt_time_precision + | ON UPDATE_SYM NOW_SYM opt_default_time_precision { Item *item= new (YYTHD->mem_root) Item_func_now_local($4); if (item == NULL) @@ -5992,7 +5993,7 @@ type_with_opt_collate: now_or_signed_literal: - NOW_SYM opt_time_precision + NOW_SYM opt_default_time_precision { $$= new (YYTHD->mem_root) Item_func_now_local($2); if ($$ == NULL) @@ -7782,6 +7783,12 @@ select_alias: | TEXT_STRING_sys { $$=$1; } ; +opt_default_time_precision: + /* empty */ { $$= NOT_FIXED_DEC; } + | '(' ')' { $$= NOT_FIXED_DEC; } + | '(' real_ulong_num ')' { $$= $2; }; + ; + opt_time_precision: /* empty */ { $$= 0; } | '(' ')' { $$= 0; }