[Commits] Rev 4345: MDEV-6179: dynamic columns functions/cast()/convert() doesn't play nice with CREATE/ALTER TABLE in lp:~maria-captains/maria/5.5

Sergei Golubchik serg at mariadb.org
Mon Nov 10 20:19:40 EET 2014


At lp:~maria-captains/maria/5.5

------------------------------------------------------------
revno: 4345
revision-id: sergii at pisem.net-20141108185442-tfqpm94wli78jqzd
parent: bar at mnogosearch.org-20141110140817-ba18dq3tuhku5k7b
committer: Sergei Golubchik <sergii at pisem.net>
branch nick: 5.5
timestamp: Sat 2014-11-08 19:54:42 +0100
message:
  MDEV-6179: dynamic columns functions/cast()/convert() doesn't play nice with CREATE/ALTER TABLE
  
  When parsing a field declaration, grab type information from LEX before it's overwritten
  by further rules. Pass type information through the parser stack to the rule that needs it.
=== modified file 'mysql-test/r/create.result'
--- a/mysql-test/r/create.result	2013-05-11 17:31:50 +0000
+++ b/mysql-test/r/create.result	2014-11-08 18:54:42 +0000
@@ -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;

=== modified file 'mysql-test/t/create.test'
--- a/mysql-test/t/create.test	2012-12-17 20:34:56 +0000
+++ b/mysql-test/t/create.test	2014-11-08 18:54:42 +0000
@@ -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;

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2014-08-02 19:26:16 +0000
+++ b/sql/sql_lex.h	2014-11-08 18:54:42 +0000
@@ -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

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2014-08-02 19:26:16 +0000
+++ b/sql/sql_yacc.yy	2014-11-08 18:54:42 +0000
@@ -737,6 +737,7 @@ static bool add_create_index (LEX *lex,
   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 **
 %type <string>
         text_string opt_gconcat_separator
 
+%type <lex_type> field_def
+
 %type <num>
         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
-          {
-            $$= (enum enum_field_types)MYSQL_TYPE_VIRTUAL;
-            Lex->vcol_info->set_field_type((enum enum_field_types) $1);
+          type opt_attribute
+          { $$.set($1, Lex->length, Lex->dec, Lex->charset); }
+        | type opt_generated_always AS
+          { $<lex_type>$.set($1, Lex->length, Lex->dec, Lex->charset); }
+          '(' virtual_column_func ')' vcol_opt_specifier vcol_opt_attribute
+          {
+            $$= $<lex_type>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;



More information about the commits mailing list