diff options
author | Sergei Golubchik <sergii@pisem.net> | 2014-11-18 15:42:40 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2014-11-18 15:42:40 +0100 |
commit | 5d0122bd7719d1b6125af43e29908cb71922e646 (patch) | |
tree | d77cdbfb63c1fbee3f8be7808c27d428dd85b7be | |
parent | 84f25c25f260373b54941d9239e8b0d758990601 (diff) | |
download | mariadb-git-5d0122bd7719d1b6125af43e29908cb71922e646.tar.gz |
MDEV-7113 difference between check_vcol_func_processor and check_partition_func_processor
MDEV-6789 segfault in Item_func_from_unixtime::get_date on updating table with virtual columns
* prohibit VALUES in partitioning expression
* prohibit user and system variables in virtual column expressions
* fix Item_func_date_format to cache locale (for %M/%W to return the same as MONTHNAME/DAYNAME)
* fix Item_func_from_unixtime to cache time_zone directly, not THD (and not to crash)
* added tests for other incorrectly allowed (in vcols) functions to see that they don't crash
-rw-r--r-- | mysql-test/r/partition_error.result | 5 | ||||
-rw-r--r-- | mysql-test/suite/vcol/r/not_supported.result | 67 | ||||
-rw-r--r-- | mysql-test/suite/vcol/t/not_supported.test | 58 | ||||
-rw-r--r-- | mysql-test/t/partition_error.test | 11 | ||||
-rw-r--r-- | sql/item.h | 1 | ||||
-rw-r--r-- | sql/item_func.h | 4 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 15 | ||||
-rw-r--r-- | sql/item_timefunc.h | 9 |
8 files changed, 155 insertions, 15 deletions
diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 851c97c5ec3..0fe1034d447 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -1754,3 +1754,8 @@ PARTITION pmax VALUES LESS THAN MAXVALUE); ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed DROP TABLE t1; End of 5.1 tests +create table t1 (a int) partition by list (values(a) div 1) (partition p0 values in (0), partition p1 values in (1)); +ERROR HY000: This partition function is not allowed +create table t1 (a int) partition by list (uuid_short()) (partition p0 values in (0), partition p1 values in (1)); +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') (partition p0 values in (0), partition p1 values in (1))' at line 1 +End of 5.5 tests diff --git a/mysql-test/suite/vcol/r/not_supported.result b/mysql-test/suite/vcol/r/not_supported.result new file mode 100644 index 00000000000..06627fccf8b --- /dev/null +++ b/mysql-test/suite/vcol/r/not_supported.result @@ -0,0 +1,67 @@ +set lc_time_names = 'es_MX'; +set time_zone='+10:00'; +set div_precision_increment=20; +create table t1 (a int, b int, v decimal(20,19) as (a/3)); +create table t2 (a int, b int, v int as (a+@a)); +ERROR HY000: Function or expression is not allowed for column 'v' +create table t3 (a int, b int, v int as (a+@@error_count)); +ERROR HY000: Function or expression is not allowed for column 'v' +create table t4 (a int, b int, v int as (@a:=a)); +ERROR HY000: Function or expression is not allowed for column 'v' +create table t5 (a int, b int, v varchar(100) as (monthname(a))); +create table t6 (a int, b int, v varchar(100) as (dayname(a))); +create table t7 (a int, b int, v varchar(100) as (date_format(a, '%W %a %M %b'))); +create table t8 (a int, b int, v varchar(100) as (from_unixtime(a))); +insert t1 (a,b) values (1,2); +insert t5 (a,b) values (20141010,2); +insert t6 (a,b) values (20141010,2); +insert t7 (a,b) values (20141010,2); +insert t8 (a,b) values (1234567890,2); +select * from t1; +a b v +1 2 0.3333333333333333333 +select * from t5; +a b v +20141010 2 octubre +select * from t6; +a b v +20141010 2 viernes +select * from t7; +a b v +20141010 2 viernes vie octubre oct +select * from t8; +a b v +1234567890 2 2009-02-14 09:31:30 +set time_zone='+1:00'; +select * from t1; +a b v +1 2 0.3333333333333333333 +select * from t5; +a b v +20141010 2 octubre +select * from t6; +a b v +20141010 2 viernes +select * from t7; +a b v +20141010 2 viernes vie octubre oct +select * from t8; +a b v +1234567890 2 2009-02-14 09:31:30 +flush tables; +select * from t1; +a b v +1 2 0.3333333330000000000 +select * from t5; +a b v +20141010 2 October +select * from t6; +a b v +20141010 2 Friday +select * from t7; +a b v +20141010 2 Friday Fri October Oct +select * from t8; +a b v +1234567890 2 2009-02-14 00:31:30 +drop table t1, t5, t6, t7, t8; diff --git a/mysql-test/suite/vcol/t/not_supported.test b/mysql-test/suite/vcol/t/not_supported.test new file mode 100644 index 00000000000..70b9dea69fd --- /dev/null +++ b/mysql-test/suite/vcol/t/not_supported.test @@ -0,0 +1,58 @@ +# +# MDEV-7113 difference between check_vcol_func_processor and check_partition_func_processor +# + +# the following functions must not be supported in virtual columns. +# but for compatibility reasons it won't be done in a GA version, +# we'll only fix most critical issues (inconsistent results, crashes) + +connect (con1, localhost, root); + +set lc_time_names = 'es_MX'; +set time_zone='+10:00'; +set div_precision_increment=20; + +create table t1 (a int, b int, v decimal(20,19) as (a/3)); +--error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED +create table t2 (a int, b int, v int as (a+@a)); +--error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED +create table t3 (a int, b int, v int as (a+@@error_count)); +--error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED +create table t4 (a int, b int, v int as (@a:=a)); +create table t5 (a int, b int, v varchar(100) as (monthname(a))); +create table t6 (a int, b int, v varchar(100) as (dayname(a))); +create table t7 (a int, b int, v varchar(100) as (date_format(a, '%W %a %M %b'))); +create table t8 (a int, b int, v varchar(100) as (from_unixtime(a))); + +insert t1 (a,b) values (1,2); +insert t5 (a,b) values (20141010,2); +insert t6 (a,b) values (20141010,2); +insert t7 (a,b) values (20141010,2); +insert t8 (a,b) values (1234567890,2); + +select * from t1; +select * from t5; +select * from t6; +select * from t7; +select * from t8; + +disconnect con1; +connection default; +set time_zone='+1:00'; + +select * from t1; +select * from t5; +select * from t6; +select * from t7; +select * from t8; + +flush tables; + +select * from t1; +select * from t5; +select * from t6; +select * from t7; +select * from t8; + +drop table t1, t5, t6, t7, t8; + diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index f8f09e4b5e7..64799574140 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -2005,3 +2005,14 @@ PARTITION pmax VALUES LESS THAN MAXVALUE); DROP TABLE t1; --echo End of 5.1 tests + +# +# MDEV-7113 difference between check_vcol_func_processor and check_partition_func_processor +# +--error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +create table t1 (a int) partition by list (values(a) div 1) (partition p0 values in (0), partition p1 values in (1)); + +--error ER_PARSE_ERROR +create table t1 (a int) partition by list (uuid_short()) (partition p0 values in (0), partition p1 values in (1)); + +--echo End of 5.5 tests diff --git a/sql/item.h b/sql/item.h index f7ee860390f..57e91e5b3d8 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3939,6 +3939,7 @@ public: return arg->walk(processor, walk_subquery, args) || (this->*processor)(args); } + bool check_partition_func_processor(uchar *int_arg) {return TRUE;} bool check_vcol_func_processor(uchar *arg) { return trace_unsupported_by_check_vcol_func_processor("values"); diff --git a/sql/item_func.h b/sql/item_func.h index 49966964fbb..ab0ae5f0bda 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1696,6 +1696,7 @@ public: bool register_field_in_bitmap(uchar *arg); bool set_entry(THD *thd, bool create_if_not_exists); void cleanup(); + bool check_vcol_func_processor(uchar *int_arg) {return TRUE;} }; @@ -1735,6 +1736,7 @@ public: { return this; } + bool check_vcol_func_processor(uchar *int_arg) { return TRUE;} }; @@ -1817,6 +1819,7 @@ public: bool eq(const Item *item, bool binary_cmp) const; void cleanup(); + bool check_vcol_func_processor(uchar *int_arg) { return TRUE;} }; @@ -2090,7 +2093,6 @@ public: longlong val_int(); void fix_length_and_dec() { max_length= 21; unsigned_flag=1; } - bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return trace_unsupported_by_check_vcol_func_processor(func_name()); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 15701658015..59a5f1849f8 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -450,16 +450,14 @@ err: Create a formated date/time value in a string. */ -bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, - timestamp_type type, String *str) +static bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, + timestamp_type type, MY_LOCALE *locale, String *str) { char intbuff[15]; uint hours_i; uint weekday; ulong length; const char *ptr, *end; - THD *thd= current_thd; - MY_LOCALE *locale= thd->variables.lc_time_names; str->length(0); @@ -1726,6 +1724,8 @@ overflow: void Item_func_date_format::fix_length_and_dec() { THD* thd= current_thd; + locale= thd->variables.lc_time_names; + /* Must use this_item() in case it's a local SP variable (for ->max_length and ->str_value) @@ -1889,7 +1889,7 @@ String *Item_func_date_format::val_str(String *str) if (!make_date_time(&date_time_format, &l_time, is_time_format ? MYSQL_TIMESTAMP_TIME : MYSQL_TIMESTAMP_DATE, - str)) + locale, str)) return str; null_date: @@ -1900,8 +1900,9 @@ null_date: void Item_func_from_unixtime::fix_length_and_dec() { - thd= current_thd; + THD *thd= current_thd; thd->time_zone_used= 1; + tz= thd->variables.time_zone; decimals= args[0]->decimals; Item_temporal_func::fix_length_and_dec(); } @@ -1922,7 +1923,7 @@ bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime, if (args[0]->null_value || sign || sec > TIMESTAMP_MAX_VALUE) return (null_value= 1); - thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)sec); + tz->gmt_sec_to_TIME(ltime, (my_time_t)sec); ltime->second_part= sec_part; diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 455540c4b0d..3a03ee4b27a 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -688,6 +688,7 @@ public: class Item_func_date_format :public Item_str_func { + MY_LOCALE *locale; int fixed_length; const bool is_time_format; String value; @@ -705,7 +706,7 @@ public: class Item_func_from_unixtime :public Item_temporal_func { - THD *thd; + Time_zone *tz; public: Item_func_from_unixtime(Item *a) :Item_temporal_func(a) {} const char *func_name() const { return "from_unixtime"; } @@ -1046,10 +1047,4 @@ public: bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); }; - -/* Function prototypes */ - -bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, - timestamp_type type, String *str); - #endif /* ITEM_TIMEFUNC_INCLUDED */ |