mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-20806 Federated does not work with INET6, returns NULL with warning ER_TRUNCATED_WRONG_VALUE
This commit is contained in:
24
mysql-test/suite/federated/federated_type_inet6.result
Normal file
24
mysql-test/suite/federated/federated_type_inet6.result
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
connect master,127.0.0.1,root,,test,$MASTER_MYPORT,;
|
||||||
|
connect slave,127.0.0.1,root,,test,$SLAVE_MYPORT,;
|
||||||
|
connection master;
|
||||||
|
CREATE DATABASE federated;
|
||||||
|
connection slave;
|
||||||
|
CREATE DATABASE federated;
|
||||||
|
#
|
||||||
|
# MDEV-20806 Federated does not work with INET6, returns NULL with warning ER_TRUNCATED_WRONG_VALUE
|
||||||
|
#
|
||||||
|
connection master;
|
||||||
|
CREATE TABLE t1 (a INET6);
|
||||||
|
INSERT INTO t1 VALUES ('::'),('f::f');
|
||||||
|
CREATE TABLE t2 (a INET6) ENGINE=Federated CONNECTION='mysql://root@127.0.0.1:MASTER_PORT/test/t1';
|
||||||
|
SELECT * FROM t2;
|
||||||
|
a
|
||||||
|
::
|
||||||
|
f::f
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
connection master;
|
||||||
|
DROP TABLE IF EXISTS federated.t1;
|
||||||
|
DROP DATABASE IF EXISTS federated;
|
||||||
|
connection slave;
|
||||||
|
DROP TABLE IF EXISTS federated.t1;
|
||||||
|
DROP DATABASE IF EXISTS federated;
|
17
mysql-test/suite/federated/federated_type_inet6.test
Normal file
17
mysql-test/suite/federated/federated_type_inet6.test
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
source include/federated.inc;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-20806 Federated does not work with INET6, returns NULL with warning ER_TRUNCATED_WRONG_VALUE
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INET6);
|
||||||
|
INSERT INTO t1 VALUES ('::'),('f::f');
|
||||||
|
|
||||||
|
--replace_result $MASTER_MYPORT MASTER_PORT
|
||||||
|
eval CREATE TABLE t2 (a INET6) ENGINE=Federated CONNECTION='mysql://root@127.0.0.1:$MASTER_MYPORT/test/t1';
|
||||||
|
SELECT * FROM t2;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
source include/federated_cleanup.inc;
|
@ -631,6 +631,16 @@ class Field_inet6: public Field
|
|||||||
set_max_value((char*) ptr);
|
set_max_value((char*) ptr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
int store_inet6_null_with_warn(const Inet6_null &inet6,
|
||||||
|
const ErrConvString &err)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(marked_for_write_or_computed());
|
||||||
|
if (inet6.is_null())
|
||||||
|
return maybe_null() ? set_null_with_warn(err) :
|
||||||
|
set_min_value_with_warn(err);
|
||||||
|
inet6.to_binary((char *) ptr, Inet6::binary_length());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Field_inet6(const LEX_CSTRING *field_name_arg, const Record_addr &rec)
|
Field_inet6(const LEX_CSTRING *field_name_arg, const Record_addr &rec)
|
||||||
@ -749,23 +759,26 @@ public:
|
|||||||
|
|
||||||
int store(const char *str, size_t length, CHARSET_INFO *cs) override
|
int store(const char *str, size_t length, CHARSET_INFO *cs) override
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(marked_for_write_or_computed());
|
return cs == &my_charset_bin ? store_binary(str, length) :
|
||||||
Inet6_null tmp= cs == &my_charset_bin ?
|
store_text(str, length, cs);
|
||||||
Inet6_null(str, length) :
|
}
|
||||||
Inet6_null(str, length, cs);
|
|
||||||
if (tmp.is_null())
|
int store_text(const char *str, size_t length, CHARSET_INFO *cs) override
|
||||||
{
|
{
|
||||||
return maybe_null() ?
|
return store_inet6_null_with_warn(Inet6_null(str, length, cs),
|
||||||
set_null_with_warn(ErrConvString(str, length, cs)) :
|
ErrConvString(str, length, cs));
|
||||||
set_min_value_with_warn(ErrConvString(str, length, cs));
|
}
|
||||||
}
|
|
||||||
tmp.to_binary((char *) ptr, Inet6::binary_length());
|
int store_binary(const char *str, size_t length) override
|
||||||
return 0;
|
{
|
||||||
|
return store_inet6_null_with_warn(Inet6_null(str, length),
|
||||||
|
ErrConvString(str, length,
|
||||||
|
&my_charset_bin));
|
||||||
}
|
}
|
||||||
|
|
||||||
int store_hex_hybrid(const char *str, size_t length) override
|
int store_hex_hybrid(const char *str, size_t length) override
|
||||||
{
|
{
|
||||||
return store(str, length, &my_charset_bin);
|
return Field_inet6::store_binary(str, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
int store_decimal(const my_decimal *num) override
|
int store_decimal(const my_decimal *num) override
|
||||||
|
17
sql/field.cc
17
sql/field.cc
@ -1887,13 +1887,16 @@ bool Field::compatible_field_size(uint field_metadata,
|
|||||||
int Field::store(const char *to, size_t length, CHARSET_INFO *cs,
|
int Field::store(const char *to, size_t length, CHARSET_INFO *cs,
|
||||||
enum_check_fields check_level)
|
enum_check_fields check_level)
|
||||||
{
|
{
|
||||||
int res;
|
Check_level_instant_set tmp_level(get_thd(), check_level);
|
||||||
THD *thd= get_thd();
|
return store(to, length, cs);
|
||||||
enum_check_fields old_check_level= thd->count_cuted_fields;
|
}
|
||||||
thd->count_cuted_fields= check_level;
|
|
||||||
res= store(to, length, cs);
|
|
||||||
thd->count_cuted_fields= old_check_level;
|
int Field::store_text(const char *to, size_t length, CHARSET_INFO *cs,
|
||||||
return res;
|
enum_check_fields check_level)
|
||||||
|
{
|
||||||
|
Check_level_instant_set tmp_level(get_thd(), check_level);
|
||||||
|
return store_text(to, length, cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
19
sql/field.h
19
sql/field.h
@ -916,6 +916,23 @@ public:
|
|||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
virtual int store(const char *to, size_t length,CHARSET_INFO *cs)=0;
|
virtual int store(const char *to, size_t length,CHARSET_INFO *cs)=0;
|
||||||
|
/*
|
||||||
|
This is used by engines like CSV and Federated to signal the field
|
||||||
|
that the data is going to be in text (rather than binary) representation,
|
||||||
|
even if cs points to &my_charset_bin.
|
||||||
|
|
||||||
|
If a Field distinguishes between text and binary formats (e.g. INET6),
|
||||||
|
we cannot call store(str,length,&my_charset_bin),
|
||||||
|
to avoid "field" mis-interpreting the data format as binary.
|
||||||
|
*/
|
||||||
|
virtual int store_text(const char *to, size_t length, CHARSET_INFO *cs)
|
||||||
|
{
|
||||||
|
return store(to, length, cs);
|
||||||
|
}
|
||||||
|
virtual int store_binary(const char *to, size_t length)
|
||||||
|
{
|
||||||
|
return store(to, length, &my_charset_bin);
|
||||||
|
}
|
||||||
virtual int store_hex_hybrid(const char *str, size_t length);
|
virtual int store_hex_hybrid(const char *str, size_t length);
|
||||||
virtual int store(double nr)=0;
|
virtual int store(double nr)=0;
|
||||||
virtual int store(longlong nr, bool unsigned_val)=0;
|
virtual int store(longlong nr, bool unsigned_val)=0;
|
||||||
@ -940,6 +957,8 @@ public:
|
|||||||
{ return store_time_dec(ltime, TIME_SECOND_PART_DIGITS); }
|
{ return store_time_dec(ltime, TIME_SECOND_PART_DIGITS); }
|
||||||
int store(const char *to, size_t length, CHARSET_INFO *cs,
|
int store(const char *to, size_t length, CHARSET_INFO *cs,
|
||||||
enum_check_fields check_level);
|
enum_check_fields check_level);
|
||||||
|
int store_text(const char *to, size_t length, CHARSET_INFO *cs,
|
||||||
|
enum_check_fields check_level);
|
||||||
int store(const LEX_STRING *ls, CHARSET_INFO *cs)
|
int store(const LEX_STRING *ls, CHARSET_INFO *cs)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(ls->length < UINT_MAX32);
|
DBUG_ASSERT(ls->length < UINT_MAX32);
|
||||||
|
@ -6884,6 +6884,23 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Check_level_instant_set
|
||||||
|
{
|
||||||
|
THD *m_thd;
|
||||||
|
enum_check_fields m_check_level;
|
||||||
|
public:
|
||||||
|
Check_level_instant_set(THD *thd, enum_check_fields temporary_value)
|
||||||
|
:m_thd(thd), m_check_level(thd->count_cuted_fields)
|
||||||
|
{
|
||||||
|
thd->count_cuted_fields= temporary_value;
|
||||||
|
}
|
||||||
|
~Check_level_instant_set()
|
||||||
|
{
|
||||||
|
m_thd->count_cuted_fields= m_check_level;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class resembles the SQL Standard schema qualified object name:
|
This class resembles the SQL Standard schema qualified object name:
|
||||||
<schema qualified name> ::= [ <schema name> <period> ] <qualified identifier>
|
<schema qualified name> ::= [ <schema name> <period> ] <qualified identifier>
|
||||||
|
@ -820,16 +820,6 @@ int ha_tina::find_current_row(uchar *buf)
|
|||||||
if (read_all || bitmap_is_set(table->read_set, (*field)->field_index))
|
if (read_all || bitmap_is_set(table->read_set, (*field)->field_index))
|
||||||
{
|
{
|
||||||
bool is_enum= ((*field)->real_type() == MYSQL_TYPE_ENUM);
|
bool is_enum= ((*field)->real_type() == MYSQL_TYPE_ENUM);
|
||||||
/*
|
|
||||||
If "field" distinguishes between text and binary formats (e.g. INET6),
|
|
||||||
we cannot pass buffer.char() (which is &my_charset_bin) to store(),
|
|
||||||
to avoid "field" mis-interpreting the data format as binary.
|
|
||||||
Let's pass my_charset_latin1 to tell the field that we're storing
|
|
||||||
in text format.
|
|
||||||
*/
|
|
||||||
CHARSET_INFO *storecs=
|
|
||||||
(*field)->type_handler()->convert_to_binary_using_val_native() ?
|
|
||||||
&my_charset_latin1 : buffer.charset();
|
|
||||||
/*
|
/*
|
||||||
Here CHECK_FIELD_WARN checks that all values in the csv file are valid
|
Here CHECK_FIELD_WARN checks that all values in the csv file are valid
|
||||||
which is normally the case, if they were written by
|
which is normally the case, if they were written by
|
||||||
@ -838,8 +828,8 @@ int ha_tina::find_current_row(uchar *buf)
|
|||||||
Thus, for enums we silence the warning, as it doesn't really mean
|
Thus, for enums we silence the warning, as it doesn't really mean
|
||||||
an invalid value.
|
an invalid value.
|
||||||
*/
|
*/
|
||||||
if ((*field)->store(buffer.ptr(), buffer.length(), storecs,
|
if ((*field)->store_text(buffer.ptr(), buffer.length(), buffer.charset(),
|
||||||
is_enum ? CHECK_FIELD_IGNORE : CHECK_FIELD_WARN))
|
is_enum ? CHECK_FIELD_IGNORE : CHECK_FIELD_WARN))
|
||||||
{
|
{
|
||||||
if (!is_enum)
|
if (!is_enum)
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -959,7 +959,7 @@ uint ha_federated::convert_row_to_internal_format(uchar *record,
|
|||||||
if (bitmap_is_set(table->read_set, (*field)->field_index))
|
if (bitmap_is_set(table->read_set, (*field)->field_index))
|
||||||
{
|
{
|
||||||
(*field)->set_notnull();
|
(*field)->set_notnull();
|
||||||
(*field)->store(*row, *lengths, &my_charset_bin);
|
(*field)->store_text(*row, *lengths, &my_charset_bin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(*field)->move_field_offset(-old_ptr);
|
(*field)->move_field_offset(-old_ptr);
|
||||||
|
@ -893,7 +893,8 @@ uint ha_federatedx::convert_row_to_internal_format(uchar *record,
|
|||||||
if (bitmap_is_set(table->read_set, (*field)->field_index))
|
if (bitmap_is_set(table->read_set, (*field)->field_index))
|
||||||
{
|
{
|
||||||
(*field)->set_notnull();
|
(*field)->set_notnull();
|
||||||
(*field)->store(io->get_column_data(row, column), lengths[column], &my_charset_bin);
|
(*field)->store_text(io->get_column_data(row, column), lengths[column],
|
||||||
|
&my_charset_bin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(*field)->move_field_offset(-old_ptr);
|
(*field)->move_field_offset(-old_ptr);
|
||||||
|
Reference in New Issue
Block a user