Commit b424420f authored by Alexander Barkov's avatar Alexander Barkov

MDEV-9316 Add Field::store_hex_hybrid()

parent 12b86bea
......@@ -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.
*/
......
......@@ -280,6 +280,16 @@ class Value_source
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 @@ class Field: public Value_source
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 @@ class Field_str :public Field {
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 @@ class Field_temporal: public Field {
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; }
......
......@@ -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)
{
......
......@@ -3312,7 +3312,12 @@ class Item_hex_hybrid: public Item_hex_constant
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 @@ class Item_hex_hybrid: public Item_hex_constant
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);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment