diff options
author | unknown <gkodinov/kgeorge@macbook.gmz> | 2006-11-28 15:44:11 +0200 |
---|---|---|
committer | unknown <gkodinov/kgeorge@macbook.gmz> | 2006-11-28 15:44:11 +0200 |
commit | 9221a5482bb39be7391f46d81e1e85dc41b47729 (patch) | |
tree | fa4c02c70637d0f12ec543e10f073cc0738788a3 /sql | |
parent | 1019dd404c273b722daa4039d42b1a920439e6b1 (diff) | |
download | mariadb-git-9221a5482bb39be7391f46d81e1e85dc41b47729.tar.gz |
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
When implicitly converting string fields to numbers the
string-to-number conversion error was not sent to the client.
Added code to send the conversion error as warning.
We also need to prevent generation of warnings from the places
where val_xxx() methods are called for the sole purpose of updating
the Item::null_value flag.
To achieve that a special function is added (and called) :
update_null_value(). This function will set the no_errors flag and
will call val_xxx(). The warning generation in Field_string::val_xxx()
will use the flag when generating the conversion warnings.
mysql-test/r/compare.result:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- non-convertible strings in arithmetic operations
mysql-test/r/func_gconcat.result:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- non-convertible strings in arithmetic operations
mysql-test/r/func_group.result:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- non-convertible strings in arithmetic operations
mysql-test/r/type_varchar.result:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- test case
mysql-test/t/type_varchar.test:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- test case
sql/field.cc:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- send conversion warning to the client
sql/item.cc:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- send conversion warning to the client
sql/item.h:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- added a special function to explicitly update the null_value
sql/item_func.h:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- added a special function to explicitly update the null_value
sql/item_subselect.h:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- added a special function to explicitly update the null_value
sql/item_sum.cc:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- added a special function to explicitly update the null_value
sql/item_sum.h:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- added a special function to explicitly update the null_value
sql/sql_string.h:
BUG#11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
- send conversion warning to the client
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 60 | ||||
-rw-r--r-- | sql/item.cc | 24 | ||||
-rw-r--r-- | sql/item.h | 6 | ||||
-rw-r--r-- | sql/item_func.h | 4 | ||||
-rw-r--r-- | sql/item_subselect.h | 2 | ||||
-rw-r--r-- | sql/item_sum.cc | 8 | ||||
-rw-r--r-- | sql/item_sum.h | 4 | ||||
-rw-r--r-- | sql/sql_string.h | 6 |
8 files changed, 90 insertions, 24 deletions
diff --git a/sql/field.cc b/sql/field.cc index 61bbea5e615..a45caf4fa4e 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -47,6 +47,8 @@ uchar Field_null::null[1]={1}; const char field_separator=','; #define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE 320 +#define LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE 128 +#define DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE 128 #define BLOB_PACK_LENGTH_TO_MAX_LENGH(arg) \ ((ulong) ((LL(1) << min(arg, 4) * 8) - LL(1))) @@ -5954,19 +5956,49 @@ int Field_longstr::store_decimal(const my_decimal *d) double Field_string::val_real(void) { - int not_used; - char *end_not_used; + int error; + char *end; CHARSET_INFO *cs= charset(); - return my_strntod(cs,ptr,field_length,&end_not_used,¬_used); + double result; + + result= my_strntod(cs,ptr,field_length,&end,&error); + if (!table->in_use->no_errors && + (error || (field_length != (uint32)(end - ptr) && + !check_if_only_end_space(cs, end, ptr + field_length)))) + { + char buf[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; + String tmp(buf, sizeof(buf), cs); + tmp.copy(ptr, field_length, cs); + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), + "DOUBLE", tmp.c_ptr()); + } + return result; } longlong Field_string::val_int(void) { - int not_used; - char *end_not_used; - CHARSET_INFO *cs=charset(); - return my_strntoll(cs,ptr,field_length,10,&end_not_used,¬_used); + int error; + char *end; + CHARSET_INFO *cs= charset(); + longlong result; + + result= my_strntoll(cs,ptr,field_length,10,&end,&error); + if (!table->in_use->no_errors && + (error || (field_length != (uint32)(end - ptr) && + !check_if_only_end_space(cs, end, ptr + field_length)))) + { + char buf[LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE]; + String tmp(buf, sizeof(buf), cs); + tmp.copy(ptr, field_length, cs); + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), + "INTEGER", tmp.c_ptr()); + } + return result; } @@ -5983,8 +6015,20 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)), my_decimal *Field_string::val_decimal(my_decimal *decimal_value) { - str2my_decimal(E_DEC_FATAL_ERROR, ptr, field_length, charset(), + int err= str2my_decimal(E_DEC_FATAL_ERROR, ptr, field_length, charset(), decimal_value); + if (!table->in_use->no_errors && err) + { + char buf[DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE]; + CHARSET_INFO *cs= charset(); + String tmp(buf, sizeof(buf), cs); + tmp.copy(ptr, field_length, cs); + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), + "DECIMAL", tmp.c_ptr()); + } + return decimal_value; } diff --git a/sql/item.cc b/sql/item.cc index 76f0332b4ab..79822fb0a12 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2175,12 +2175,6 @@ void Item_string::print(String *str) } -inline bool check_if_only_end_space(CHARSET_INFO *cs, char *str, char *end) -{ - return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end; -} - - double Item_string::val_real() { DBUG_ASSERT(fixed == 1); @@ -4764,6 +4758,22 @@ bool Item_field::send(Protocol *protocol, String *buffer) } +void Item_field::update_null_value() +{ + /* + need to set no_errors to prevent warnings about type conversion + popping up. + */ + THD *thd= field->table->in_use; + int no_errors; + + no_errors= thd->no_errors; + thd->no_errors= 1; + Item::update_null_value(); + thd->no_errors= no_errors; +} + + Item_ref::Item_ref(Name_resolution_context *context_arg, Item **item, const char *table_name_arg, const char *field_name_arg) @@ -6120,7 +6130,7 @@ bool Item_cache_row::null_inside() } else { - values[i]->val_int(); + values[i]->update_null_value(); if (values[i]->null_value) return 1; } diff --git a/sql/item.h b/sql/item.h index c1a04e4281d..20a674514b2 100644 --- a/sql/item.h +++ b/sql/item.h @@ -716,6 +716,11 @@ public: virtual bool is_null() { return 0; } /* + Make sure the null_value member has a correct value. + */ + virtual void update_null_value () { (void) val_int(); } + + /* Inform the item that there will be no distinction between its result being FALSE or NULL. @@ -1282,6 +1287,7 @@ public: bool get_date_result(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); bool is_null() { return field->is_null(); } + void update_null_value(); Item *get_tmp_table_item(THD *thd); bool collect_item_field_processor(byte * arg); bool find_item_in_field_list_processor(byte *arg); diff --git a/sql/item_func.h b/sql/item_func.h index 99f7d16855e..af4e4bdbcbc 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -157,7 +157,7 @@ public: return (null_value=args[0]->get_time(ltime)); } bool is_null() { - (void) val_int(); /* Discard result. It sets null_value as side-effect. */ + update_null_value(); return null_value; } void signal_divide_by_null(); @@ -241,7 +241,7 @@ public: virtual double real_op()= 0; virtual my_decimal *decimal_op(my_decimal *)= 0; virtual String *str_op(String *)= 0; - bool is_null() { (void) val_real(); return null_value; } + bool is_null() { update_null_value(); return null_value; } }; /* function where type of result detected by first argument */ diff --git a/sql/item_subselect.h b/sql/item_subselect.h index f1be99353cc..35ded79b75d 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -91,7 +91,7 @@ public: enum Type type() const; bool is_null() { - val_int(); + update_null_value(); return null_value; } bool fix_fields(THD *thd, Item **ref); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index fccbdfa7925..c6f29efa5ca 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1050,7 +1050,7 @@ bool Item_sum_count::add() count++; else { - (void) args[0]->val_int(); + args[0]->update_null_value(); if (!args[0]->null_value) count++; } @@ -1956,7 +1956,7 @@ void Item_sum_count::reset_field() nr=1; else { - (void) args[0]->val_int(); + args[0]->update_null_value(); if (!args[0]->null_value) nr=1; } @@ -2066,7 +2066,7 @@ void Item_sum_count::update_field() nr++; else { - (void) args[0]->val_int(); + args[0]->update_null_value(); if (!args[0]->null_value) nr++; } @@ -2546,7 +2546,7 @@ bool Item_sum_count_distinct::setup(THD *thd) return TRUE; // End of memory if (item->const_item()) { - (void) item->val_int(); + item->update_null_value(); if (item->null_value) always_null=1; } diff --git a/sql/item_sum.h b/sql/item_sum.h index a2b2f7cab92..42129008047 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -587,7 +587,7 @@ public: double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *); - bool is_null() { (void) val_int(); return null_value; } + bool is_null() { update_null_value(); return null_value; } String *val_str(String*); enum_field_types field_type() const { @@ -649,7 +649,7 @@ public: { /* can't be fix_fields()ed */ return (longlong) rint(val_real()); } String *val_str(String*); my_decimal *val_decimal(my_decimal *); - bool is_null() { (void) val_int(); return null_value; } + bool is_null() { update_null_value(); return null_value; } enum_field_types field_type() const { return hybrid_type == DECIMAL_RESULT ? diff --git a/sql/sql_string.h b/sql/sql_string.h index 0659f684afe..812ab8b4d61 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -355,3 +355,9 @@ public: return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length); } }; + +static inline bool check_if_only_end_space(CHARSET_INFO *cs, char *str, + char *end) +{ + return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end; +} |