summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2015-12-23 14:15:00 +0400
committerAlexander Barkov <bar@mariadb.org>2015-12-23 14:15:00 +0400
commitb424420f1028bfc0fdbaf646681950e5b52b9da5 (patch)
tree696b498cd59dc702cb4cfa02174c42c65b962b8e /sql
parent12b86beac8e395eb9aeada820f83a0737949f937 (diff)
downloadmariadb-git-b424420f1028bfc0fdbaf646681950e5b52b9da5.tar.gz
MDEV-9316 Add Field::store_hex_hybrid()
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc25
-rw-r--r--sql/field.h19
-rw-r--r--sql/item.cc44
-rw-r--r--sql/item.h13
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);
};