Commit 2954ed1e authored by Igor Babaev's avatar Igor Babaev

Merge 5.3->5.5.

parents f8f65acc 20f3f4a2
...@@ -146,6 +146,42 @@ table_schema table_name column_name column_type extra ...@@ -146,6 +146,42 @@ table_schema table_name column_name column_type extra
test t2 a int(11) test t2 a int(11)
test t2 b int(11) VIRTUAL test t2 b int(11) VIRTUAL
DROP TABLE t1,t2; 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); create table t1 (a int, b int);
insert into t1 values (3, 30), (4, 20), (1, 20); 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)); create table t2 (c int, d int, v int as (d+1), index idx(c));
......
...@@ -155,6 +155,29 @@ SELECT table_schema, table_name, column_name, column_type, extra ...@@ -155,6 +155,29 @@ SELECT table_schema, table_name, column_name, column_type, extra
DROP TABLE t1,t2; 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 # SELECT that uses a virtual column and executed with BKA
# #
......
...@@ -2244,6 +2244,10 @@ class Create_field :public Sql_alloc ...@@ -2244,6 +2244,10 @@ class Create_field :public Sql_alloc
{ {
return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0; return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0;
} }
uint virtual_col_expr_maxlen()
{
return 255 - FRM_VCOL_HEADER_SIZE(interval != NULL);
}
private: private:
const String empty_set_string; const String empty_set_string;
}; };
......
...@@ -990,7 +990,7 @@ class SQL_SELECT :public Sql_alloc { ...@@ -990,7 +990,7 @@ class SQL_SELECT :public Sql_alloc {
key_map quick_keys; // Possible quick keys key_map quick_keys; // Possible quick keys
key_map needed_reg; // Possible quick keys after prev tables. key_map needed_reg; // Possible quick keys after prev tables.
table_map const_tables,read_tables; table_map const_tables,read_tables;
bool free_cond; bool free_cond; /* Currently not used and always FALSE */
SQL_SELECT(); SQL_SELECT();
~SQL_SELECT(); ~SQL_SELECT();
......
...@@ -1439,25 +1439,33 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, ...@@ -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: 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 2 = sql_type
byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored) 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(); 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; error= 4;
goto err; goto err;
} }
field_type= (enum_field_types) (uchar) vcol_screen_pos[1];
fld_stored_in_db= (bool) (uint) vcol_screen_pos[2]; 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= if (!(vcol_info->expr_str.str=
(char *)memdup_root(&share->mem_root, (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))) vcol_expr_length)))
goto err; goto err;
if (opt_interval_id)
interval_nr= (uint) vcol_screen_pos[3];
vcol_info->expr_str.length= vcol_expr_length; vcol_info->expr_str.length= vcol_expr_length;
vcol_screen_pos+= vcol_info_length; vcol_screen_pos+= vcol_info_length;
share->vfields++; share->vfields++;
......
...@@ -726,18 +726,19 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, ...@@ -726,18 +726,19 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
} }
if (field->vcol_info) if (field->vcol_info)
{ {
uint col_expr_maxlen= field->virtual_col_expr_maxlen();
tmp_len= tmp_len=
system_charset_info->cset->charpos(system_charset_info, 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.str + field->vcol_info->expr_str.str +
field->vcol_info->expr_str.length, field->vcol_info->expr_str.length,
VIRTUAL_COLUMN_EXPRESSION_MAXLEN); col_expr_maxlen);
if (tmp_len < field->vcol_info->expr_str.length) if (tmp_len < field->vcol_info->expr_str.length)
{ {
my_error(ER_WRONG_STRING_LENGTH, MYF(0), my_error(ER_WRONG_STRING_LENGTH, MYF(0),
field->vcol_info->expr_str.str,"VIRTUAL COLUMN EXPRESSION", field->vcol_info->expr_str.str,"VIRTUAL COLUMN EXPRESSION",
(uint) VIRTUAL_COLUMN_EXPRESSION_MAXLEN); col_expr_maxlen);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
/* /*
...@@ -746,7 +747,7 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, ...@@ -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. expressions saved in the frm file for virtual columns.
*/ */
vcol_info_length+= field->vcol_info->expr_str.length+ vcol_info_length+= field->vcol_info->expr_str.length+
(uint)FRM_VCOL_HEADER_SIZE; FRM_VCOL_HEADER_SIZE(field->interval!=NULL);
} }
totlength+= field->length; totlength+= field->length;
...@@ -949,8 +950,9 @@ static bool pack_fields(File file, List<Create_field> &create_fields, ...@@ -949,8 +950,9 @@ static bool pack_fields(File file, List<Create_field> &create_fields,
the additional data saved for the virtual field the additional data saved for the virtual field
*/ */
buff[12]= cur_vcol_expr_len= field->vcol_info->expr_str.length + buff[12]= cur_vcol_expr_len= field->vcol_info->expr_str.length +
(uint)FRM_VCOL_HEADER_SIZE; FRM_VCOL_HEADER_SIZE(field->interval!=NULL);
vcol_info_length+= cur_vcol_expr_len+(uint)FRM_VCOL_HEADER_SIZE; vcol_info_length+= cur_vcol_expr_len +
FRM_VCOL_HEADER_SIZE(field->interval!=NULL);
buff[13]= (uchar) MYSQL_TYPE_VIRTUAL; buff[13]= (uchar) MYSQL_TYPE_VIRTUAL;
} }
int2store(buff+15, field->comment.length); int2store(buff+15, field->comment.length);
...@@ -1055,17 +1057,20 @@ static bool pack_fields(File file, List<Create_field> &create_fields, ...@@ -1055,17 +1057,20 @@ static bool pack_fields(File file, List<Create_field> &create_fields,
{ {
/* /*
Pack each virtual field as follows: 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 2 = sql_type
byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored) 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) 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[1]= (uchar) field->sql_type;
buff[2]= (uchar) field->stored_in_db; 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); DBUG_RETURN(1);
if (my_write(file, if (my_write(file,
(uchar*) field->vcol_info->expr_str.str, (uchar*) field->vcol_info->expr_str.str,
......
...@@ -162,10 +162,7 @@ typedef struct st_ha_create_information HA_CREATE_INFO; ...@@ -162,10 +162,7 @@ typedef struct st_ha_create_information HA_CREATE_INFO;
#define DEFAULT_KEY_CACHE_NAME "default" #define DEFAULT_KEY_CACHE_NAME "default"
/* The length of the header part for each virtual column in the .frm file */ /* The length of the header part for each virtual column in the .frm file */
#define FRM_VCOL_HEADER_SIZE 3 #define FRM_VCOL_HEADER_SIZE(b) (3 + test(b))
/* Maximum length of the defining expression for a virtual columns */
#define VIRTUAL_COLUMN_EXPRESSION_MAXLEN 255 - FRM_VCOL_HEADER_SIZE
/* Include prototypes for unireg */ /* Include prototypes for unireg */
......
...@@ -76,6 +76,7 @@ int mi_assign_to_key_cache(MI_INFO *info, ...@@ -76,6 +76,7 @@ int mi_assign_to_key_cache(MI_INFO *info,
in the old key cache. 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, if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_RELEASE)) FLUSH_RELEASE))
{ {
...@@ -83,6 +84,7 @@ int mi_assign_to_key_cache(MI_INFO *info, ...@@ -83,6 +84,7 @@ int mi_assign_to_key_cache(MI_INFO *info,
mi_print_error(info->s, HA_ERR_CRASHED); mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Mark that table must be checked */ 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 Flush the new key cache for this file. This is needed to ensure
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment