diff options
author | Alexander Barkov <bar@mariadb.org> | 2015-12-23 14:15:00 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2015-12-23 14:15:00 +0400 |
commit | b424420f1028bfc0fdbaf646681950e5b52b9da5 (patch) | |
tree | 696b498cd59dc702cb4cfa02174c42c65b962b8e /sql | |
parent | 12b86beac8e395eb9aeada820f83a0737949f937 (diff) | |
download | mariadb-git-b424420f1028bfc0fdbaf646681950e5b52b9da5.tar.gz |
MDEV-9316 Add Field::store_hex_hybrid()
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 25 | ||||
-rw-r--r-- | sql/field.h | 19 | ||||
-rw-r--r-- | sql/item.cc | 44 | ||||
-rw-r--r-- | sql/item.h | 13 |
4 files changed, 55 insertions, 46 deletions
diff --git a/sql/field.cc b/sql/field.cc index 4d25b4eb060..30678a9fd89 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1322,6 +1322,31 @@ bool Field::can_optimize_range(const Item_bool_func *cond, } +int Field::store_hex_hybrid(const char *str, uint length) +{ + DBUG_ASSERT(result_type() != STRING_RESULT); + ulonglong nr; + + if (length > 8) + { + nr= flags & UNSIGNED_FLAG ? ULONGLONG_MAX : LONGLONG_MAX; + goto warn; + } + nr= (ulonglong) longlong_from_hex_hybrid(str, length); + if ((length == 8) && !(flags & UNSIGNED_FLAG) && (nr > LONGLONG_MAX)) + { + nr= LONGLONG_MAX; + goto warn; + } + return store((longlong) nr, true); // Assume hex numbers are unsigned + +warn: + if (!store((longlong) nr, true)) + set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + return 1; +} + + /** Numeric fields base class constructor. */ diff --git a/sql/field.h b/sql/field.h index c4cbb94eaaf..6ea3408c327 100644 --- a/sql/field.h +++ b/sql/field.h @@ -280,6 +280,16 @@ protected: return decimal_value; } + longlong longlong_from_hex_hybrid(const char *str, uint32 length) + { + const char *end= str + length; + const char *ptr= end - MY_MIN(length, sizeof(longlong)); + ulonglong value= 0; + for ( ; ptr != end ; ptr++) + value= (value << 8) + (ulonglong) (uchar) *ptr; + return (longlong) value; + } + longlong longlong_from_string_with_check(const String *str) const { return longlong_from_string_with_check(str->charset(), @@ -720,6 +730,7 @@ public: virtual ~Field() {} /* Store functions returns 1 on overflow and -1 on fatal error */ virtual int store(const char *to, uint length,CHARSET_INFO *cs)=0; + virtual int store_hex_hybrid(const char *str, uint length); virtual int store(double nr)=0; virtual int store(longlong nr, bool unsigned_val)=0; virtual int store_decimal(const my_decimal *d)=0; @@ -1527,6 +1538,10 @@ public: int store(longlong nr, bool unsigned_val)=0; int store_decimal(const my_decimal *); int store(const char *to,uint length,CHARSET_INFO *cs)=0; + int store_hex_hybrid(const char *str, uint length) + { + return store(str, length, &my_charset_bin); + } uint repertoire(void) const { return my_charset_repertoire(field_charset); @@ -2068,6 +2083,10 @@ public: field_name_arg) { flags|= BINARY_FLAG; } Item_result result_type () const { return STRING_RESULT; } + int store_hex_hybrid(const char *str, uint length) + { + return store(str, length, &my_charset_bin); + } uint32 max_display_length() { return field_length; } bool str_needs_quotes() { return TRUE; } enum Derivation derivation(void) const { return DERIVATION_NUMERIC; } diff --git a/sql/item.cc b/sql/item.cc index 7e30afc7db3..d0795508a54 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6079,50 +6079,6 @@ void Item_hex_constant::hex_string_init(THD *thd, const char *str, unsigned_flag= 1; } -longlong Item_hex_hybrid::val_int() -{ - // following assert is redundant, because fixed=1 assigned in constructor - DBUG_ASSERT(fixed == 1); - char *end=(char*) str_value.ptr()+str_value.length(), - *ptr=end-MY_MIN(str_value.length(),sizeof(longlong)); - - ulonglong value=0; - for (; ptr != end ; ptr++) - value=(value << 8)+ (ulonglong) (uchar) *ptr; - return (longlong) value; -} - - -int Item_hex_hybrid::save_in_field(Field *field, bool no_conversions) -{ - field->set_notnull(); - if (field->result_type() == STRING_RESULT) - return field->store(str_value.ptr(), str_value.length(), - collation.collation); - - ulonglong nr; - uint32 length= str_value.length(); - - if (length > 8) - { - nr= field->flags & UNSIGNED_FLAG ? ULONGLONG_MAX : LONGLONG_MAX; - goto warn; - } - nr= (ulonglong) val_int(); - if ((length == 8) && !(field->flags & UNSIGNED_FLAG) && (nr > LONGLONG_MAX)) - { - nr= LONGLONG_MAX; - goto warn; - } - return field->store((longlong) nr, TRUE); // Assume hex numbers are unsigned - -warn: - if (!field->store((longlong) nr, TRUE)) - field->set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, - 1); - return 1; -} - void Item_hex_hybrid::print(String *str, enum_query_type query_type) { diff --git a/sql/item.h b/sql/item.h index e64e3191d51..ef42b92c8db 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3312,7 +3312,12 @@ public: DBUG_ASSERT(fixed == 1); return (double) (ulonglong) Item_hex_hybrid::val_int(); } - longlong val_int(); + longlong val_int() + { + // following assert is redundant, because fixed=1 assigned in constructor + DBUG_ASSERT(fixed == 1); + return longlong_from_hex_hybrid(str_value.ptr(), str_value.length()); + } my_decimal *val_decimal(my_decimal *decimal_value) { // following assert is redundant, because fixed=1 assigned in constructor @@ -3321,7 +3326,11 @@ public: int2my_decimal(E_DEC_FATAL_ERROR, value, TRUE, decimal_value); return decimal_value; } - int save_in_field(Field *field, bool no_conversions); + int save_in_field(Field *field, bool no_conversions) + { + field->set_notnull(); + return field->store_hex_hybrid(str_value.ptr(), str_value.length()); + } enum Item_result cast_to_int_type() const { return INT_RESULT; } void print(String *str, enum_query_type query_type); }; |