summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/main/ctype_ucs.result12
-rw-r--r--mysql-test/main/ctype_ucs.test15
-rw-r--r--sql/item_inetfunc.cc83
-rw-r--r--sql/item_inetfunc.h35
-rw-r--r--sql/sql_type.cc9
-rw-r--r--sql/sql_type.h52
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
{