summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc9
-rw-r--r--sql/item_func.h11
2 files changed, 17 insertions, 3 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 08599f1d486..015f5591c5d 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -533,7 +533,14 @@ uint Item::decimal_precision() const
unsigned_flag);
return MY_MIN(prec, DECIMAL_MAX_PRECISION);
}
- return MY_MIN(max_char_length(), DECIMAL_MAX_PRECISION);
+ uint res= max_char_length();
+ /*
+ Return at least one decimal digit, even if Item::max_char_length()
+ returned 0. This is important to avoid attempts to create fields of types
+ INT(0) or DECIMAL(0,0) when converting NULL or empty strings to INT/DECIMAL:
+ CREATE TABLE t1 AS SELECT CONVERT(NULL,SIGNED) AS a;
+ */
+ return res ? MY_MIN(res, DECIMAL_MAX_PRECISION) : 1;
}
diff --git a/sql/item_func.h b/sql/item_func.h
index 4a55bd68453..56d7c190181 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -626,8 +626,15 @@ public:
longlong val_int_from_str(int *error);
void fix_length_and_dec()
{
- fix_char_length(MY_MIN(args[0]->max_char_length(),
- MY_INT64_NUM_DECIMAL_DIGITS));
+ uint32 char_length= MY_MIN(args[0]->max_char_length(),
+ MY_INT64_NUM_DECIMAL_DIGITS);
+ /*
+ args[0]->max_char_length() can return 0.
+ Reserve max_length to fit at least one character for one digit,
+ plus one character for the sign (if signed).
+ */
+ set_if_bigger(char_length, 1 + (unsigned_flag ? 0 : 1));
+ fix_char_length(char_length);
}
virtual void print(String *str, enum_query_type query_type);
uint decimal_precision() const { return args[0]->decimal_precision(); }