diff options
-rw-r--r-- | mysql-test/suite/vcol/r/vcol_misc.result | 36 | ||||
-rw-r--r-- | mysql-test/suite/vcol/t/vcol_misc.test | 23 | ||||
-rw-r--r-- | sql/field.h | 4 | ||||
-rw-r--r-- | sql/opt_range.h | 2 | ||||
-rw-r--r-- | sql/table.cc | 20 | ||||
-rw-r--r-- | sql/unireg.cc | 23 | ||||
-rw-r--r-- | sql/unireg.h | 5 | ||||
-rw-r--r-- | storage/myisam/mi_keycache.c | 2 |
8 files changed, 95 insertions, 20 deletions
diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result index c27b36089c6..17b38b7d7af 100644 --- a/mysql-test/suite/vcol/r/vcol_misc.result +++ b/mysql-test/suite/vcol/r/vcol_misc.result @@ -146,6 +146,42 @@ table_schema table_name column_name column_type extra test t2 a int(11) test t2 b int(11) VIRTUAL DROP TABLE t1,t2; +create table t1 ( +a int not null, b char(2) not null, +c enum('Y','N') as (case when b = 'aa' then 'Y' else 'N' end) persistent +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` char(2) NOT NULL, + `c` enum('Y','N') AS (case when b = 'aa' then 'Y' else 'N' end) PERSISTENT +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +insert into t1(a,b) values (1,'bb'), (2,'aa'), (3,'cc'); +select * from t1; +a b c +1 bb N +2 aa Y +3 cc N +create table t2 ( +a int, b int, +c set("y","n") +as (if(a=0,if(b=0,('n,n'),('n,y')),if(b=0,('y,n'),('y,y')))) persistent +); +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` set('y','n') AS (if(a=0,if(b=0,('n,n'),('n,y')),if(b=0,('y,n'),('y,y')))) PERSISTENT +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +insert into t2(a,b) values (7,0), (2,3), (0,1); +select * from t2; +a b c +7 0 y,n +2 3 y +0 1 y,n +drop table t1,t2; create table t1 (a int, b int); insert into t1 values (3, 30), (4, 20), (1, 20); create table t2 (c int, d int, v int as (d+1), index idx(c)); diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test index 6f576f61513..01404046cde 100644 --- a/mysql-test/suite/vcol/t/vcol_misc.test +++ b/mysql-test/suite/vcol/t/vcol_misc.test @@ -156,6 +156,29 @@ SELECT table_schema, table_name, column_name, column_type, extra DROP TABLE t1,t2; # +# Bug mdev-354: virtual columns of ENUM and SET types +# + +create table t1 ( + a int not null, b char(2) not null, + c enum('Y','N') as (case when b = 'aa' then 'Y' else 'N' end) persistent +); +show create table t1; +insert into t1(a,b) values (1,'bb'), (2,'aa'), (3,'cc'); +select * from t1; + +create table t2 ( + a int, b int, + c set("y","n") + as (if(a=0,if(b=0,('n,n'),('n,y')),if(b=0,('y,n'),('y,y')))) persistent +); +show create table t2; +insert into t2(a,b) values (7,0), (2,3), (0,1); +select * from t2; + +drop table t1,t2; + +# # SELECT that uses a virtual column and executed with BKA # diff --git a/sql/field.h b/sql/field.h index dbb2e030f74..3838c924419 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2244,6 +2244,10 @@ public: { return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0; } + uint virtual_col_expr_maxlen() + { + return 255 - FRM_VCOL_HEADER_SIZE(interval != NULL); + } private: const String empty_set_string; }; diff --git a/sql/opt_range.h b/sql/opt_range.h index 545e9e3c7b8..efb45f96345 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -990,7 +990,7 @@ class SQL_SELECT :public Sql_alloc { key_map quick_keys; // Possible quick keys key_map needed_reg; // Possible quick keys after prev tables. table_map const_tables,read_tables; - bool free_cond; + bool free_cond; /* Currently not used and always FALSE */ SQL_SELECT(); ~SQL_SELECT(); diff --git a/sql/table.cc b/sql/table.cc index bc7ad0e5831..2a11098caed 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1439,25 +1439,33 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, { /* Get virtual column data stored in the .frm file as follows: - byte 1 = 1 (always 1 to allow for future extensions) + byte 1 = 1 | 2 byte 2 = sql_type byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored) - byte 4-... = virtual column expression (text data) + [byte 4] = optional interval_id for sql_type (only if byte 1 == 2) + next byte ... = virtual column expression (text data) */ vcol_info= new Virtual_column_info(); - if ((uint)vcol_screen_pos[0] != 1) + bool opt_interval_id= (uint)vcol_screen_pos[0] == 2; + field_type= (enum_field_types) (uchar) vcol_screen_pos[1]; + if (opt_interval_id) + interval_nr= (uint)vcol_screen_pos[3]; + else if ((uint)vcol_screen_pos[0] != 1) { error= 4; goto err; } - field_type= (enum_field_types) (uchar) vcol_screen_pos[1]; fld_stored_in_db= (bool) (uint) vcol_screen_pos[2]; - vcol_expr_length= vcol_info_length-(uint)FRM_VCOL_HEADER_SIZE; + vcol_expr_length= vcol_info_length - + (uint)(FRM_VCOL_HEADER_SIZE(opt_interval_id)); if (!(vcol_info->expr_str.str= (char *)memdup_root(&share->mem_root, - vcol_screen_pos+(uint)FRM_VCOL_HEADER_SIZE, + vcol_screen_pos + + (uint) FRM_VCOL_HEADER_SIZE(opt_interval_id), vcol_expr_length))) goto err; + if (opt_interval_id) + interval_nr= (uint) vcol_screen_pos[3]; vcol_info->expr_str.length= vcol_expr_length; vcol_screen_pos+= vcol_info_length; share->vfields++; diff --git a/sql/unireg.cc b/sql/unireg.cc index c9b0f91d9f7..edcfe9eb934 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -726,18 +726,19 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, } if (field->vcol_info) { + uint col_expr_maxlen= field->virtual_col_expr_maxlen(); tmp_len= system_charset_info->cset->charpos(system_charset_info, field->vcol_info->expr_str.str, field->vcol_info->expr_str.str + field->vcol_info->expr_str.length, - VIRTUAL_COLUMN_EXPRESSION_MAXLEN); + col_expr_maxlen); if (tmp_len < field->vcol_info->expr_str.length) { my_error(ER_WRONG_STRING_LENGTH, MYF(0), field->vcol_info->expr_str.str,"VIRTUAL COLUMN EXPRESSION", - (uint) VIRTUAL_COLUMN_EXPRESSION_MAXLEN); + col_expr_maxlen); DBUG_RETURN(1); } /* @@ -746,7 +747,7 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, expressions saved in the frm file for virtual columns. */ vcol_info_length+= field->vcol_info->expr_str.length+ - (uint)FRM_VCOL_HEADER_SIZE; + FRM_VCOL_HEADER_SIZE(field->interval!=NULL); } totlength+= field->length; @@ -949,8 +950,9 @@ static bool pack_fields(File file, List<Create_field> &create_fields, the additional data saved for the virtual field */ buff[12]= cur_vcol_expr_len= field->vcol_info->expr_str.length + - (uint)FRM_VCOL_HEADER_SIZE; - vcol_info_length+= cur_vcol_expr_len+(uint)FRM_VCOL_HEADER_SIZE; + FRM_VCOL_HEADER_SIZE(field->interval!=NULL); + vcol_info_length+= cur_vcol_expr_len + + FRM_VCOL_HEADER_SIZE(field->interval!=NULL); buff[13]= (uchar) MYSQL_TYPE_VIRTUAL; } int2store(buff+15, field->comment.length); @@ -1055,17 +1057,20 @@ static bool pack_fields(File file, List<Create_field> &create_fields, { /* Pack each virtual field as follows: - byte 1 = 1 (always 1 to allow for future extensions) + byte 1 = interval_id == 0 ? 1 : 2 byte 2 = sql_type byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored) - byte 4-... = virtual column expression (text data) + [byte 4] = possible interval_id for sql_type + next byte ... = virtual column expression (text data) */ if (field->vcol_info && field->vcol_info->expr_str.length) { - buff[0]= (uchar)1; + buff[0]= (uchar)(1 + test(field->interval_id)); buff[1]= (uchar) field->sql_type; buff[2]= (uchar) field->stored_in_db; - if (my_write(file, buff, 3, MYF_RW)) + if (field->interval_id) + buff[3]= (uchar) field->interval_id; + if (my_write(file, buff, 3 + test(field->interval_id), MYF_RW)) DBUG_RETURN(1); if (my_write(file, (uchar*) field->vcol_info->expr_str.str, diff --git a/sql/unireg.h b/sql/unireg.h index f8317a89c8c..950cfc2cc31 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -162,10 +162,7 @@ typedef struct st_ha_create_information HA_CREATE_INFO; #define DEFAULT_KEY_CACHE_NAME "default" /* The length of the header part for each virtual column in the .frm file */ -#define FRM_VCOL_HEADER_SIZE 3 - -/* Maximum length of the defining expression for a virtual columns */ -#define VIRTUAL_COLUMN_EXPRESSION_MAXLEN 255 - FRM_VCOL_HEADER_SIZE +#define FRM_VCOL_HEADER_SIZE(b) (3 + test(b)) /* Include prototypes for unireg */ diff --git a/storage/myisam/mi_keycache.c b/storage/myisam/mi_keycache.c index a2422b71bbf..b45f0efa2f7 100644 --- a/storage/myisam/mi_keycache.c +++ b/storage/myisam/mi_keycache.c @@ -76,6 +76,7 @@ int mi_assign_to_key_cache(MI_INFO *info, in the old key cache. */ + pthread_mutex_lock(&share->key_cache->op_lock); if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map, FLUSH_RELEASE)) { @@ -83,6 +84,7 @@ int mi_assign_to_key_cache(MI_INFO *info, mi_print_error(info->s, HA_ERR_CRASHED); mi_mark_crashed(info); /* Mark that table must be checked */ } + pthread_mutex_unlock(&share->key_cache->op_lock); /* Flush the new key cache for this file. This is needed to ensure |