diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 751dd939361..d7023fea5a5 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -2430,3 +2430,50 @@ a b 1 1 unlock tables; drop table t1,t2; +# +# MDEV-6179: dynamic columns functions/cast()/convert() doesn't +# play nice with CREATE/ALTER TABLE +# +create table t1 ( +color char(32) as (COLUMN_GET(dynamic_cols, 1 as char)) persistent, +cl char(32) as (COLUMN_GET(COLUMN_ADD(COLUMN_CREATE(1 , 'blue' as char), 2, 'ttt'), i as char)) persistent, +item_name varchar(32) primary key, -- A common attribute for all items +i int, +dynamic_cols blob -- Dynamic columns will be stored here +); +INSERT INTO t1(item_name, dynamic_cols, i) VALUES +('MariaDB T-shirt', COLUMN_CREATE(1, 'blue', 2, 'XL'), 1); +INSERT INTO t1(item_name, dynamic_cols, i) VALUES +('Thinkpad Laptop', COLUMN_CREATE(1, 'black', 3, 500), 2); +select item_name, color, cl from t1; +item_name color cl +MariaDB T-shirt blue blue +Thinkpad Laptop black ttt +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `color` char(32) AS (COLUMN_GET(dynamic_cols, 1 as char)) PERSISTENT, + `cl` char(32) AS (COLUMN_GET(COLUMN_ADD(COLUMN_CREATE(1 , 'blue' as char), 2, 'ttt'), i as char)) PERSISTENT, + `item_name` varchar(32) NOT NULL, + `i` int(11) DEFAULT NULL, + `dynamic_cols` blob, + PRIMARY KEY (`item_name`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1 ( +n int, +c char(32) as (convert(cast(n as char), char)) persistent +); +insert into t1(n) values (1),(2),(3); +select * from t1; +n c +1 1 +2 2 +3 3 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `n` int(11) DEFAULT NULL, + `c` char(32) AS (convert(cast(n as char), char)) PERSISTENT +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 1fabb49138c..6de2c50ab36 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -2021,3 +2021,35 @@ connection default; select * from t1; unlock tables; drop table t1,t2; + +--echo # +--echo # MDEV-6179: dynamic columns functions/cast()/convert() doesn't +--echo # play nice with CREATE/ALTER TABLE +--echo # +create table t1 ( + color char(32) as (COLUMN_GET(dynamic_cols, 1 as char)) persistent, + cl char(32) as (COLUMN_GET(COLUMN_ADD(COLUMN_CREATE(1 , 'blue' as char), 2, 'ttt'), i as char)) persistent, + item_name varchar(32) primary key, -- A common attribute for all items + i int, + dynamic_cols blob -- Dynamic columns will be stored here +); +INSERT INTO t1(item_name, dynamic_cols, i) VALUES + ('MariaDB T-shirt', COLUMN_CREATE(1, 'blue', 2, 'XL'), 1); +INSERT INTO t1(item_name, dynamic_cols, i) VALUES + ('Thinkpad Laptop', COLUMN_CREATE(1, 'black', 3, 500), 2); + +select item_name, color, cl from t1; +show create table t1; + +drop table t1; + +create table t1 ( + n int, + c char(32) as (convert(cast(n as char), char)) persistent +); +insert into t1(n) values (1),(2),(3); + +select * from t1; +show create table t1; + +drop table t1; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e0bb5d11cbc..4f424000180 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -105,6 +105,15 @@ struct sys_var_with_base LEX_STRING base_name; }; +struct LEX_TYPE +{ + enum enum_field_types type; + char *length, *dec; + CHARSET_INFO *charset; + void set(int t, char *l, char *d, CHARSET_INFO *cs) + { type= (enum_field_types)t; length= l; dec= d; charset= cs; } +}; + #ifdef MYSQL_SERVER /* The following hack is needed because mysql_yacc.cc does not define diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 47bd3994fd3..777cef517c0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -737,6 +737,7 @@ static bool add_create_index (LEX *lex, Key::Keytype type, LEX_STRING lex_str; LEX_STRING *lex_str_ptr; LEX_SYMBOL symbol; + LEX_TYPE lex_type; Table_ident *table; char *simple_string; Item *item; @@ -1471,13 +1472,15 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type text_string opt_gconcat_separator +%type field_def + %type type type_with_opt_collate int_type real_type order_dir lock_option udf_type if_exists opt_local opt_table_options table_options table_option opt_if_not_exists opt_no_write_to_binlog opt_temporary all_or_any opt_distinct opt_ignore_leaves fulltext_options spatial_type union_option - start_transaction_opts field_def + start_transaction_opts union_opt select_derived_init option_type2 opt_natural_language_mode opt_query_expansion opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment @@ -5483,11 +5486,11 @@ field_spec: field_def { LEX *lex=Lex; - if (add_field_to_list(lex->thd, &$1, (enum enum_field_types) $3, - lex->length,lex->dec,lex->type, + if (add_field_to_list(lex->thd, &$1, $3.type, + $3.length, $3.dec, lex->type, lex->default_value, lex->on_update_value, &lex->comment, - lex->change,&lex->interval_list,lex->charset, + lex->change, &lex->interval_list, $3.charset, lex->uint_geom_type, lex->vcol_info, lex->option_list)) MYSQL_YYABORT; @@ -5495,13 +5498,15 @@ field_spec: ; field_def: - type opt_attribute {} - | type opt_generated_always AS '(' virtual_column_func ')' - vcol_opt_specifier - vcol_opt_attribute + type opt_attribute + { $$.set($1, Lex->length, Lex->dec, Lex->charset); } + | type opt_generated_always AS + { $$.set($1, Lex->length, Lex->dec, Lex->charset); } + '(' virtual_column_func ')' vcol_opt_specifier vcol_opt_attribute { - $$= (enum enum_field_types)MYSQL_TYPE_VIRTUAL; - Lex->vcol_info->set_field_type((enum enum_field_types) $1); + $$= $4; + Lex->vcol_info->set_field_type($$.type); + $$.type= (enum enum_field_types)MYSQL_TYPE_VIRTUAL; } ; @@ -6892,11 +6897,11 @@ alter_list_item: { LEX *lex=Lex; if (add_field_to_list(lex->thd,&$3, - (enum enum_field_types) $5, - lex->length,lex->dec,lex->type, + $5.type, + $5.length, $5.dec, lex->type, lex->default_value, lex->on_update_value, &lex->comment, - $3.str, &lex->interval_list, lex->charset, + $3.str, &lex->interval_list, $5.charset, lex->uint_geom_type, lex->vcol_info, lex->option_list)) MYSQL_YYABORT;