summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2019-10-10 08:12:14 +0400
committerAlexander Barkov <bar@mariadb.com>2019-10-10 08:12:14 +0400
commit312ba3cc3dd13fe3da1aeac8a32887be98c8a7ae (patch)
tree608d138c261c1b20fea2daaa0a88b53139b3643f
parentb37386d854b37743a7b4ae578312dd27bec055ce (diff)
downloadmariadb-git-312ba3cc3dd13fe3da1aeac8a32887be98c8a7ae.tar.gz
MDEV-20783 INET6 cannot be converted to BINARY(16)
-rw-r--r--plugin/type_inet/mysql-test/type_inet/type_inet6.result118
-rw-r--r--plugin/type_inet/mysql-test/type_inet/type_inet6.test114
-rw-r--r--plugin/type_inet/sql_type_inet.cc50
-rw-r--r--sql/field.h5
-rw-r--r--sql/field_conv.cc6
5 files changed, 271 insertions, 22 deletions
diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.result b/plugin/type_inet/mysql-test/type_inet/type_inet6.result
index b402e1cae2a..3e5905cecec 100644
--- a/plugin/type_inet/mysql-test/type_inet/type_inet6.result
+++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.result
@@ -1266,6 +1266,16 @@ Warning 1292 Incorrect inet6 value: '::192.168.0.1'
Warning 1292 Incorrect inet6 value: '::ffff:192.168.0.1'
DROP TABLE t1;
#
+# ALTER from INET6 to INET6
+#
+CREATE TABLE t1 (a INET6, b INT);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329', 1);
+ALTER TABLE t1 MODIFY b DECIMAL(10,2);
+SELECT * FROM t1;
+a b
+2001:db8::ff00:42:8329 1.00
+DROP TABLE t1;
+#
# ALTER to character string data types
#
CREATE OR REPLACE TABLE t1 (a INET6);
@@ -1377,6 +1387,104 @@ a
2001:db8::ff00:42:8329
DROP TABLE t1;
#
+# ALTER to binary string data types
+#
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a BINARY(16);
+SELECT HEX(a) FROM t1;
+HEX(a)
+20010DB8000000000000FF0000428329
+DROP TABLE t1;
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a BINARY(17);
+SELECT HEX(a) FROM t1;
+HEX(a)
+20010DB8000000000000FF000042832900
+DROP TABLE t1;
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a BINARY(15);
+ERROR 22001: Data too long for column 'a' at row 1
+DROP TABLE t1;
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a TINYBLOB;
+SELECT HEX(a) FROM t1;
+HEX(a)
+20010DB8000000000000FF0000428329
+DROP TABLE t1;
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a BLOB;
+SELECT HEX(a) FROM t1;
+HEX(a)
+20010DB8000000000000FF0000428329
+DROP TABLE t1;
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a MEDIUMBLOB;
+SELECT HEX(a) FROM t1;
+HEX(a)
+20010DB8000000000000FF0000428329
+DROP TABLE t1;
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a LONGBLOB;
+SELECT HEX(a) FROM t1;
+HEX(a)
+20010DB8000000000000FF0000428329
+DROP TABLE t1;
+#
+# ALTER from binary string data types
+#
+CREATE TABLE t1 (a BINARY(16));
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF0000428329');
+ALTER TABLE t1 MODIFY a INET6;
+SELECT a FROM t1;
+a
+2001:db8::ff00:42:8329
+DROP TABLE t1;
+CREATE TABLE t1 (a BINARY(17));
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF000042832900');
+ALTER TABLE t1 MODIFY a INET6;
+ERROR 22007: Incorrect inet6 value: ' \x01\x0D\xB8\x00\x00\x00\x00\x00\x00\xFF\x00\x00B\x83)\x00' for column `test`.`t1`.`a` at row 1
+DROP TABLE t1;
+CREATE TABLE t1 (a BINARY(15));
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF00004283');
+ALTER TABLE t1 MODIFY a INET6;
+ERROR 22007: Incorrect inet6 value: ' \x01\x0D\xB8\x00\x00\x00\x00\x00\x00\xFF\x00\x00B\x83' for column `test`.`t1`.`a` at row 1
+DROP TABLE t1;
+CREATE TABLE t1 (a TINYBLOB);
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF0000428329');
+ALTER TABLE t1 MODIFY a INET6;
+SELECT a FROM t1;
+a
+2001:db8::ff00:42:8329
+DROP TABLE t1;
+CREATE TABLE t1 (a BLOB);
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF0000428329');
+ALTER TABLE t1 MODIFY a INET6;
+SELECT a FROM t1;
+a
+2001:db8::ff00:42:8329
+DROP TABLE t1;
+CREATE TABLE t1 (a MEDIUMBLOB);
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF0000428329');
+ALTER TABLE t1 MODIFY a INET6;
+SELECT a FROM t1;
+a
+2001:db8::ff00:42:8329
+DROP TABLE t1;
+CREATE TABLE t1 (a BLOB);
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF0000428329');
+ALTER TABLE t1 MODIFY a INET6;
+SELECT a FROM t1;
+a
+2001:db8::ff00:42:8329
+DROP TABLE t1;
+#
# Limit clause parameter
# TODO: this should fail.
# The test for a valid data type should be moved
@@ -1398,3 +1506,13 @@ SELECT * FROM t1;
a
2001:db8::ff00:42:8329
DROP TABLE t1;
+#
+# MDEV-20783 INET6 cannot be converted to BINARY(16) (requires clarification in documentation)
+#
+CREATE OR REPLACE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a BINARY(16);
+SELECT HEX(a) FROM t1;
+HEX(a)
+20010DB8000000000000FF0000428329
+DROP TABLE t1;
diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.test b/plugin/type_inet/mysql-test/type_inet/type_inet6.test
index 2abcb2a9fc5..03b83214edc 100644
--- a/plugin/type_inet/mysql-test/type_inet/type_inet6.test
+++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.test
@@ -815,6 +815,16 @@ DROP TABLE t1;
--echo #
+--echo # ALTER from INET6 to INET6
+--echo #
+
+CREATE TABLE t1 (a INET6, b INT);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329', 1);
+ALTER TABLE t1 MODIFY b DECIMAL(10,2);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
--echo # ALTER to character string data types
--echo #
@@ -904,6 +914,100 @@ DROP TABLE t1;
--echo #
+--echo # ALTER to binary string data types
+--echo #
+
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a BINARY(16);
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a BINARY(17);
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+--error ER_DATA_TOO_LONG
+ALTER TABLE t1 MODIFY a BINARY(15);
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a TINYBLOB;
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a BLOB;
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a MEDIUMBLOB;
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a LONGBLOB;
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # ALTER from binary string data types
+--echo #
+
+CREATE TABLE t1 (a BINARY(16));
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF0000428329');
+ALTER TABLE t1 MODIFY a INET6;
+SELECT a FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BINARY(17));
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF000042832900');
+--error ER_TRUNCATED_WRONG_VALUE
+ALTER TABLE t1 MODIFY a INET6;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BINARY(15));
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF00004283');
+--error ER_TRUNCATED_WRONG_VALUE
+ALTER TABLE t1 MODIFY a INET6;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TINYBLOB);
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF0000428329');
+ALTER TABLE t1 MODIFY a INET6;
+SELECT a FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BLOB);
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF0000428329');
+ALTER TABLE t1 MODIFY a INET6;
+SELECT a FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a MEDIUMBLOB);
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF0000428329');
+ALTER TABLE t1 MODIFY a INET6;
+SELECT a FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BLOB);
+INSERT INTO t1 VALUES (X'20010DB8000000000000FF0000428329');
+ALTER TABLE t1 MODIFY a INET6;
+SELECT a FROM t1;
+DROP TABLE t1;
+
+
+--echo #
--echo # Limit clause parameter
--echo # TODO: this should fail.
--echo # The test for a valid data type should be moved
@@ -935,3 +1039,13 @@ SELECT CAST(a AS CHAR(39)) FROM t1;
ALTER TABLE t1 MODIFY a CHAR(39);
SELECT * FROM t1;
DROP TABLE t1;
+
+--echo #
+--echo # MDEV-20783 INET6 cannot be converted to BINARY(16) (requires clarification in documentation)
+--echo #
+
+CREATE OR REPLACE TABLE t1 (a INET6);
+INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
+ALTER TABLE t1 MODIFY a BINARY(16);
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
diff --git a/plugin/type_inet/sql_type_inet.cc b/plugin/type_inet/sql_type_inet.cc
index 4cd104af206..0c50cfe034c 100644
--- a/plugin/type_inet/sql_type_inet.cc
+++ b/plugin/type_inet/sql_type_inet.cc
@@ -823,26 +823,38 @@ public:
Copy_func *get_copy_func(const Field *from) const override
{
// ALTER to INET6 from another field
- /*
- if (eq_def(from))
- return get_identical_copy_func();
- switch (from->cmp_type()) {
- case STRING_RESULT:
- return do_field_string;
- case TIME_RESULT:
- return do_field_temporal;
- case DECIMAL_RESULT:
- return do_field_decimal;
- case REAL_RESULT:
- return do_field_real;
- case INT_RESULT:
- return do_field_int;
- case ROW_RESULT:
- DBUG_ASSERT(0);
- break;
+ return do_field_string;
+ }
+
+ Copy_func *get_copy_func_to(const Field *to) const override
+ {
+ if (type_handler() == to->type_handler())
+ {
+ // ALTER from INET6 to INET6
+ DBUG_ASSERT(pack_length() == to->pack_length());
+ DBUG_ASSERT(charset() == to->charset());
+ DBUG_ASSERT(sort_charset() == to->sort_charset());
+ return Field::do_field_eq;
}
- */
- return do_field_string;//QQ
+ // ALTER from INET6 to another data type
+ if (to->charset() == &my_charset_bin &&
+ dynamic_cast<const Type_handler_general_purpose_string*>
+ (to->type_handler()))
+ {
+ /*
+ ALTER from INET6 to a binary string type, e.g.:
+ BINARY, TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB
+ */
+ return do_field_inet6_native_to_binary;
+ }
+ return do_field_string;
+ }
+
+ static void do_field_inet6_native_to_binary(Copy_field *copy)
+ {
+ NativeBufferInet6 res;
+ copy->from_field->val_native(&res);
+ copy->to_field->store(res.ptr(), res.length(), &my_charset_bin);
}
bool memcpy_field_possible(const Field *from) const override
diff --git a/sql/field.h b/sql/field.h
index 9c98ea810f6..a0d8476df94 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -742,6 +742,7 @@ protected:
}
void error_generated_column_function_is_not_allowed(THD *thd, bool error)
const;
+ static void do_field_eq(Copy_field *copy);
static void do_field_int(Copy_field *copy);
static void do_field_real(Copy_field *copy);
static void do_field_string(Copy_field *copy);
@@ -893,6 +894,10 @@ public:
*/
typedef void Copy_func(Copy_field*);
virtual Copy_func *get_copy_func(const Field *from) const= 0;
+ virtual Copy_func *get_copy_func_to(const Field *to) const
+ {
+ return to->get_copy_func(this);
+ }
/* Store functions returns 1 on overflow and -1 on fatal error */
virtual int store_field(Field *from) { return from->save_in_field(this); }
virtual int save_in_field(Field *to)= 0;
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index f96c6742ea7..f975597cf70 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -30,7 +30,7 @@
#include "sql_class.h" // THD
#include <m_ctype.h>
-static void do_field_eq(Copy_field *copy)
+void Field::do_field_eq(Copy_field *copy)
{
memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
}
@@ -638,7 +638,7 @@ void Copy_field::set(uchar *to,Field *from)
else
{
to_null_ptr= 0; // For easy debugging
- do_copy= do_field_eq;
+ do_copy= Field::do_field_eq;
}
}
@@ -719,7 +719,7 @@ void Copy_field::set(Field *to,Field *from,bool save)
if ((to->flags & BLOB_FLAG) && save)
do_copy2= do_save_blob;
else
- do_copy2= to->get_copy_func(from);
+ do_copy2= from->get_copy_func_to(to);
if (!do_copy) // Not null
do_copy=do_copy2;
}