summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2014-11-18 15:42:40 +0100
committerSergei Golubchik <sergii@pisem.net>2014-11-18 15:42:40 +0100
commit5d0122bd7719d1b6125af43e29908cb71922e646 (patch)
treed77cdbfb63c1fbee3f8be7808c27d428dd85b7be
parent84f25c25f260373b54941d9239e8b0d758990601 (diff)
downloadmariadb-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.result5
-rw-r--r--mysql-test/suite/vcol/r/not_supported.result67
-rw-r--r--mysql-test/suite/vcol/t/not_supported.test58
-rw-r--r--mysql-test/t/partition_error.test11
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_func.h4
-rw-r--r--sql/item_timefunc.cc15
-rw-r--r--sql/item_timefunc.h9
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 */