MDEV-11298 Split Item_func_hex::val_str_ascii() into virtual methods in Type_handler
This commit is contained in:
parent
9185f8d4a7
commit
69f80e5ecf
@ -3634,53 +3634,41 @@ void Item_func_weight_string::print(String *str, enum_query_type query_type)
|
||||
}
|
||||
|
||||
|
||||
String *Item_func_hex::val_str_ascii(String *str)
|
||||
String *Item_func_hex::val_str_ascii_from_val_real(String *str)
|
||||
{
|
||||
String *res;
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (args[0]->result_type() != STRING_RESULT)
|
||||
{
|
||||
ulonglong dec;
|
||||
char ans[65],*ptr;
|
||||
/* Return hex of unsigned longlong value */
|
||||
if (args[0]->result_type() == REAL_RESULT ||
|
||||
args[0]->result_type() == DECIMAL_RESULT)
|
||||
{
|
||||
double val= args[0]->val_real();
|
||||
if ((val <= (double) LONGLONG_MIN) ||
|
||||
(val >= (double) (ulonglong) ULONGLONG_MAX))
|
||||
dec= ~(longlong) 0;
|
||||
else
|
||||
dec= (ulonglong) (val + (val > 0 ? 0.5 : -0.5));
|
||||
}
|
||||
else
|
||||
dec= (ulonglong) args[0]->val_int();
|
||||
|
||||
if ((null_value= args[0]->null_value))
|
||||
return 0;
|
||||
|
||||
if (!(ptr= longlong2str(dec, ans, 16)) ||
|
||||
str->copy(ans,(uint32) (ptr - ans),
|
||||
&my_charset_numeric))
|
||||
return make_empty_result(); // End of memory
|
||||
return str;
|
||||
}
|
||||
|
||||
/* Convert given string to a hex string, character by character */
|
||||
res= args[0]->val_str(str);
|
||||
if (!res || tmp_value.alloc(res->length()*2+1))
|
||||
{
|
||||
null_value=1;
|
||||
ulonglong dec;
|
||||
double val= args[0]->val_real();
|
||||
if ((null_value= args[0]->null_value))
|
||||
return 0;
|
||||
}
|
||||
null_value=0;
|
||||
tmp_value.length(res->length()*2);
|
||||
tmp_value.set_charset(&my_charset_latin1);
|
||||
|
||||
octet2hex((char*) tmp_value.ptr(), res->ptr(), res->length());
|
||||
return &tmp_value;
|
||||
if ((val <= (double) LONGLONG_MIN) ||
|
||||
(val >= (double) (ulonglong) ULONGLONG_MAX))
|
||||
dec= ~(longlong) 0;
|
||||
else
|
||||
dec= (ulonglong) (val + (val > 0 ? 0.5 : -0.5));
|
||||
return str->set_hex(dec) ? make_empty_result() : str;
|
||||
}
|
||||
|
||||
|
||||
String *Item_func_hex::val_str_ascii_from_val_str(String *str)
|
||||
{
|
||||
DBUG_ASSERT(&tmp_value != str);
|
||||
String *res= args[0]->val_str(&tmp_value);
|
||||
DBUG_ASSERT(res != str);
|
||||
if ((null_value= (res == NULL)))
|
||||
return NULL;
|
||||
return str->set_hex(res->ptr(), res->length()) ? make_empty_result() : str;
|
||||
}
|
||||
|
||||
|
||||
String *Item_func_hex::val_str_ascii_from_val_int(String *str)
|
||||
{
|
||||
ulonglong dec= (ulonglong) args[0]->val_int();
|
||||
if ((null_value= args[0]->null_value))
|
||||
return 0;
|
||||
return str->set_hex(dec) ? make_empty_result() : str;
|
||||
}
|
||||
|
||||
|
||||
/** Convert given hex string to a binary string. */
|
||||
|
||||
String *Item_func_unhex::val_str(String *str)
|
||||
|
@ -913,17 +913,33 @@ public:
|
||||
|
||||
class Item_func_hex :public Item_str_ascii_func
|
||||
{
|
||||
protected:
|
||||
String tmp_value;
|
||||
/*
|
||||
Calling arg[0]->type_handler() can be expensive on every row.
|
||||
It's a virtual method, and in case if args[0] is a complex Item,
|
||||
its type_handler() can call more virtual methods.
|
||||
So let's cache it during fix_length_and_dec().
|
||||
*/
|
||||
const Type_handler *m_arg0_type_handler;
|
||||
public:
|
||||
Item_func_hex(THD *thd, Item *a):
|
||||
Item_str_ascii_func(thd, a) {}
|
||||
Item_str_ascii_func(thd, a), m_arg0_type_handler(NULL) {}
|
||||
const char *func_name() const { return "hex"; }
|
||||
String *val_str_ascii(String *);
|
||||
String *val_str_ascii_from_val_int(String *str);
|
||||
String *val_str_ascii_from_val_real(String *str);
|
||||
String *val_str_ascii_from_val_str(String *str);
|
||||
String *val_str_ascii(String *str)
|
||||
{
|
||||
DBUG_ASSERT(fixed);
|
||||
return m_arg0_type_handler->Item_func_hex_val_str_ascii(this, str);
|
||||
}
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
collation.set(default_charset());
|
||||
decimals=0;
|
||||
fix_char_length(args[0]->max_length * 2);
|
||||
m_arg0_type_handler= args[0]->type_handler();
|
||||
}
|
||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||
{ return get_item_copy<Item_func_hex>(thd, mem_root, this); }
|
||||
|
@ -130,6 +130,61 @@ bool String::set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
// Convert a number into its HEX representation
|
||||
bool String::set_hex(ulonglong num)
|
||||
{
|
||||
char *n_end;
|
||||
if (alloc(65) || !(n_end= longlong2str(num, Ptr, 16)))
|
||||
return true;
|
||||
length((uint32) (n_end - Ptr));
|
||||
set_charset(&my_charset_latin1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Append a hex representation of the byte "value" into "to".
|
||||
Note:
|
||||
"to" is incremented for the caller by two bytes. It's passed by reference!
|
||||
So it resembles a macros, hence capital letters in the name.
|
||||
*/
|
||||
static inline void APPEND_HEX(char *&to, uchar value)
|
||||
{
|
||||
*to++= _dig_vec_upper[((uchar) value) >> 4];
|
||||
*to++= _dig_vec_upper[((uchar) value) & 0x0F];
|
||||
}
|
||||
|
||||
|
||||
void String::qs_append_hex(const char *str, uint32 len)
|
||||
{
|
||||
const char *str_end= str + len;
|
||||
for (char *to= Ptr + str_length ; str < str_end; str++)
|
||||
APPEND_HEX(to, (uchar) *str);
|
||||
str_length+= len * 2;
|
||||
}
|
||||
|
||||
|
||||
// Convert a string to its HEX representation
|
||||
bool String::set_hex(const char *str, uint32 len)
|
||||
{
|
||||
/*
|
||||
Safety: cut the source string if "len" is too large.
|
||||
Note, alloc() can allocate some more space than requested, due to:
|
||||
- ALIGN_SIZE
|
||||
- one extra byte for a null terminator
|
||||
So cut the source string to 0x7FFFFFF0 rather than 0x7FFFFFFE.
|
||||
*/
|
||||
set_if_smaller(len, 0x7FFFFFF0);
|
||||
if (alloc(len * 2))
|
||||
return true;
|
||||
length(0);
|
||||
qs_append_hex(str, len);
|
||||
set_charset(&my_charset_latin1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool String::set_real(double num,uint decimals, CHARSET_INFO *cs)
|
||||
{
|
||||
char buff[FLOATING_POINT_BUFFER];
|
||||
@ -960,8 +1015,7 @@ my_copy_with_hex_escaping(CHARSET_INFO *cs,
|
||||
break; /* purecov: inspected */
|
||||
*dst++= '\\';
|
||||
*dst++= 'x';
|
||||
*dst++= _dig_vec_upper[((unsigned char) *src) >> 4];
|
||||
*dst++= _dig_vec_upper[((unsigned char) *src) & 15];
|
||||
APPEND_HEX(dst, (uchar) *src);
|
||||
src++;
|
||||
dstlen-= 4;
|
||||
}
|
||||
@ -1146,8 +1200,7 @@ uint convert_to_printable(char *to, size_t to_len,
|
||||
break;
|
||||
*t++= '\\';
|
||||
*t++= 'x';
|
||||
*t++= _dig_vec_upper[((unsigned char) *f) >> 4];
|
||||
*t++= _dig_vec_upper[((unsigned char) *f) & 0x0F];
|
||||
APPEND_HEX(t, *f);
|
||||
}
|
||||
if (t_end - t >= 3) // '...'
|
||||
dots= t;
|
||||
|
@ -293,6 +293,9 @@ public:
|
||||
bool set(ulonglong num, CHARSET_INFO *cs) { return set_int((longlong)num, true, cs); }
|
||||
bool set_real(double num,uint decimals, CHARSET_INFO *cs);
|
||||
|
||||
bool set_hex(ulonglong num);
|
||||
bool set_hex(const char *str, uint32 len);
|
||||
|
||||
/* Take over handling of buffer from some other object */
|
||||
void reset(char *ptr_arg, uint32 length_arg, uint32 alloced_length_arg,
|
||||
CHARSET_INFO *cs)
|
||||
@ -567,6 +570,7 @@ public:
|
||||
qs_append(str, (uint32)strlen(str));
|
||||
}
|
||||
void qs_append(const char *str, uint32 len);
|
||||
void qs_append_hex(const char *str, uint32 len);
|
||||
void qs_append(double d);
|
||||
void qs_append(double *d);
|
||||
inline void qs_append(const char c)
|
||||
|
@ -859,3 +859,44 @@ bool Type_handler_temporal_result::
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
String *
|
||||
Type_handler_real_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
|
||||
String *str) const
|
||||
{
|
||||
return item->val_str_ascii_from_val_real(str);
|
||||
}
|
||||
|
||||
|
||||
String *
|
||||
Type_handler_decimal_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
|
||||
String *str) const
|
||||
{
|
||||
return item->val_str_ascii_from_val_real(str);
|
||||
}
|
||||
|
||||
|
||||
String *
|
||||
Type_handler_int_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
|
||||
String *str) const
|
||||
{
|
||||
return item->val_str_ascii_from_val_int(str);
|
||||
}
|
||||
|
||||
|
||||
String *
|
||||
Type_handler_temporal_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
|
||||
String *str) const
|
||||
{
|
||||
return item->val_str_ascii_from_val_str(str);
|
||||
}
|
||||
|
||||
|
||||
String *
|
||||
Type_handler_string_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
|
||||
String *str) const
|
||||
{
|
||||
return item->val_str_ascii_from_val_str(str);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
@ -27,6 +27,7 @@ class Field;
|
||||
class Item;
|
||||
class Item_cache;
|
||||
class Item_sum_hybrid;
|
||||
class Item_func_hex;
|
||||
class Type_std_attributes;
|
||||
class Sort_param;
|
||||
class Arg_comparator;
|
||||
@ -291,6 +292,8 @@ public:
|
||||
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
|
||||
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
|
||||
virtual bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const= 0;
|
||||
virtual String *Item_func_hex_val_str_ascii(Item_func_hex *item,
|
||||
String *str) const= 0;
|
||||
};
|
||||
|
||||
|
||||
@ -349,6 +352,11 @@ public:
|
||||
DBUG_ASSERT(0);
|
||||
return true;
|
||||
}
|
||||
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -383,6 +391,7 @@ public:
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
|
||||
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
|
||||
};
|
||||
|
||||
|
||||
@ -402,6 +411,7 @@ public:
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
|
||||
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
|
||||
};
|
||||
|
||||
|
||||
@ -421,6 +431,7 @@ public:
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
|
||||
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
|
||||
};
|
||||
|
||||
|
||||
@ -438,6 +449,7 @@ public:
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
|
||||
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
|
||||
};
|
||||
|
||||
|
||||
@ -459,6 +471,7 @@ public:
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
|
||||
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user