diff options
-rw-r--r-- | mysql-test/main/ctype_ucs.result | 12 | ||||
-rw-r--r-- | mysql-test/main/ctype_ucs.test | 15 | ||||
-rw-r--r-- | sql/item_inetfunc.cc | 83 | ||||
-rw-r--r-- | sql/item_inetfunc.h | 35 | ||||
-rw-r--r-- | sql/sql_type.cc | 9 | ||||
-rw-r--r-- | sql/sql_type.h | 52 |
6 files changed, 141 insertions, 65 deletions
diff --git a/mysql-test/main/ctype_ucs.result b/mysql-test/main/ctype_ucs.result index 5641726a831..c2411ff6898 100644 --- a/mysql-test/main/ctype_ucs.result +++ b/mysql-test/main/ctype_ucs.result @@ -6383,3 +6383,15 @@ DEALLOCATE PREPARE stmt; # # End of 10.2 tests # +# +# Start of 10.4 tests +# +# +# MDEV-17995 INET6_NTOA(ucs2_input) erroneously returns NULL +# +SELECT HEX(INET6_ATON('1::1')), HEX(INET6_ATON(CONVERT('1::1' USING ucs2))); +HEX(INET6_ATON('1::1')) HEX(INET6_ATON(CONVERT('1::1' USING ucs2))) +00010000000000000000000000000001 00010000000000000000000000000001 +# +# End of 10.4 tests +# diff --git a/mysql-test/main/ctype_ucs.test b/mysql-test/main/ctype_ucs.test index d0d463c0340..983f48edbc5 100644 --- a/mysql-test/main/ctype_ucs.test +++ b/mysql-test/main/ctype_ucs.test @@ -1094,3 +1094,18 @@ DEALLOCATE PREPARE stmt; --echo # --echo # End of 10.2 tests --echo # + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-17995 INET6_NTOA(ucs2_input) erroneously returns NULL +--echo # + +SELECT HEX(INET6_ATON('1::1')), HEX(INET6_ATON(CONVERT('1::1' USING ucs2))); + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/item_inetfunc.cc b/sql/item_inetfunc.cc index 8a3345ecc81..5f587cfb2aa 100644 --- a/sql/item_inetfunc.cc +++ b/sql/item_inetfunc.cc @@ -162,41 +162,6 @@ longlong Item_func_inet_bool_base::val_int() return calc_value(arg_str) ? 1 : 0; } -/////////////////////////////////////////////////////////////////////////// - -/** - Check the function argument, handle errors properly. - - @param [out] buffer Buffer for string operations. - - @return The function value. -*/ - -String *Item_func_inet_str_base::val_str_ascii(String *buffer) -{ - DBUG_ASSERT(fixed); - - // String argument expected - if (unlikely(args[0]->result_type() != STRING_RESULT)) - { - null_value= true; - return NULL; - } - - StringBuffer<STRING_BUFFER_USUAL_SIZE> tmp; - String *arg_str= args[0]->val_str(&tmp); - if (unlikely(!arg_str)) - { - // Out-of memory happened. error has been reported. - // Or: the underlying field is NULL - null_value= true; - return NULL; - } - - null_value= !calc_value(arg_str, buffer); - - return unlikely(null_value) ? NULL : buffer; -} /////////////////////////////////////////////////////////////////////////// @@ -673,6 +638,23 @@ static void ipv6_to_str(const in6_addr *ipv6, char *str) /////////////////////////////////////////////////////////////////////////// +String *Item_func_inet6_aton::val_str(String *buffer) +{ + DBUG_ASSERT(fixed); + + // String argument expected + if (unlikely(args[0]->result_type() != STRING_RESULT)) + { + null_value= true; + return NULL; + } + + Ascii_ptr_and_buffer<STRING_BUFFER_USUAL_SIZE> tmp(args[0]); + null_value= tmp.is_null() || !calc_value(tmp.string(), buffer); + return unlikely(null_value) ? NULL : buffer; +} + + /** Converts IP-address-string to IP-address-data. @@ -714,6 +696,32 @@ bool Item_func_inet6_aton::calc_value(const String *arg, String *buffer) /////////////////////////////////////////////////////////////////////////// /** + Check the function argument, handle errors properly. + + @param [out] buffer Buffer for string operations. + + @return The function value. +*/ + +String *Item_func_inet6_ntoa::val_str_ascii(String *buffer) +{ + DBUG_ASSERT(fixed); + + // Binary string argument expected + if (unlikely(args[0]->result_type() != STRING_RESULT || + args[0]->collation.collation != &my_charset_bin)) + { + null_value= true; + return NULL; + } + + String_ptr_and_buffer<STRING_BUFFER_USUAL_SIZE> tmp(args[0]); + null_value= tmp.is_null() || !calc_value(tmp.string(), buffer); + return unlikely(null_value) ? NULL : buffer; +} + + +/** Converts IP-address-data to IP-address-string. @param arg IP-address-data. @@ -724,11 +732,8 @@ bool Item_func_inet6_aton::calc_value(const String *arg, String *buffer) @retval true The string has been converted sucessfully. */ -bool Item_func_inet6_ntoa::calc_value(const String *arg, String *buffer) +bool Item_func_inet6_ntoa::calc_value(const Binary_string *arg, String *buffer) { - if (arg->charset() != &my_charset_bin) - return false; - if ((int) arg->length() == IN_ADDR_SIZE) { char str[INET_ADDRSTRLEN]; diff --git a/sql/item_inetfunc.h b/sql/item_inetfunc.h index 024ff8ce4f0..4159d3db8e3 100644 --- a/sql/item_inetfunc.h +++ b/sql/item_inetfunc.h @@ -92,34 +92,14 @@ protected: /************************************************************************* - Item_func_inet_str_base implements common code for INET6/IP-related - functions returning string value. -*************************************************************************/ - -class Item_func_inet_str_base : public Item_str_ascii_func -{ -public: - inline Item_func_inet_str_base(THD *thd, Item *arg): - Item_str_ascii_func(thd, arg) - { } - -public: - virtual String *val_str_ascii(String *buffer); - -protected: - virtual bool calc_value(const String *arg, String *buffer) = 0; -}; - - -/************************************************************************* Item_func_inet6_aton implements INET6_ATON() SQL-function. *************************************************************************/ -class Item_func_inet6_aton : public Item_func_inet_str_base +class Item_func_inet6_aton : public Item_str_func { public: inline Item_func_inet6_aton(THD *thd, Item *ip_addr): - Item_func_inet_str_base(thd, ip_addr) + Item_str_func(thd, ip_addr) { } public: @@ -136,8 +116,10 @@ public: Item *get_copy(THD *thd) { return get_item_copy<Item_func_inet6_aton>(thd, this); } + String *val_str(String *to); + protected: - virtual bool calc_value(const String *arg, String *buffer); + bool calc_value(const String *arg, String *buffer); }; @@ -145,11 +127,11 @@ protected: Item_func_inet6_ntoa implements INET6_NTOA() SQL-function. *************************************************************************/ -class Item_func_inet6_ntoa : public Item_func_inet_str_base +class Item_func_inet6_ntoa : public Item_str_ascii_func { public: inline Item_func_inet6_ntoa(THD *thd, Item *ip_addr): - Item_func_inet_str_base(thd, ip_addr) + Item_str_ascii_func(thd, ip_addr) { } public: @@ -168,11 +150,12 @@ public: maybe_null= 1; return FALSE; } + String *val_str_ascii(String *to); Item *get_copy(THD *thd) { return get_item_copy<Item_func_inet6_ntoa>(thd, this); } protected: - virtual bool calc_value(const String *arg, String *buffer); + bool calc_value(const Binary_string *arg, String *buffer); }; diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 168f66d4c99..576601bb5fa 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -134,6 +134,15 @@ bool Type_handler_data::init() Type_handler_data *type_handler_data= NULL; +String_ptr::String_ptr(Item *item, String *buffer) + :m_string_ptr(item->val_str(buffer)) +{ } + + +Ascii_ptr::Ascii_ptr(Item *item, String *buffer) + :String_ptr(item->val_str_ascii(buffer)) +{ } + void VDec::set(Item *item) { diff --git a/sql/sql_type.h b/sql/sql_type.h index abd574a4475..0a5fd74bb08 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -110,6 +110,58 @@ public: }; +class String_ptr +{ +protected: + String *m_string_ptr; +public: + String_ptr(String *str) + :m_string_ptr(str) + { } + String_ptr(Item *item, String *buffer); + const String *string() const { return m_string_ptr; } + const char *ptr() const + { + DBUG_ASSERT(m_string_ptr); + return m_string_ptr->ptr(); + } + uint32 length() const + { + DBUG_ASSERT(m_string_ptr); + return m_string_ptr->length(); + } + bool is_null() const { return m_string_ptr == NULL; } +}; + + +class Ascii_ptr: public String_ptr +{ +public: + Ascii_ptr(Item *item, String *buffer); +}; + + +template<size_t buff_sz> +class String_ptr_and_buffer: public StringBuffer<buff_sz>, + public String_ptr +{ +public: + String_ptr_and_buffer(Item *item) + :String_ptr(item, this) + { } +}; + + +template<size_t buff_sz> +class Ascii_ptr_and_buffer: public StringBuffer<buff_sz>, + public Ascii_ptr +{ +public: + Ascii_ptr_and_buffer(Item *item) + :Ascii_ptr(item, this) + { } +}; + class Dec_ptr { |