Commit 0e8544cd authored by Alexander Barkov's avatar Alexander Barkov

MDEV-29355 Backport templatized INET6 implementation from 10.7 to 10.6

parent 4feb9df1
......@@ -158,7 +158,7 @@ String *Item_func_inet6_aton::val_str(String *buffer)
return buffer;
}
Inet6_null ipv6(*tmp.string());
Inet6Bundle::Fbt_null ipv6(*tmp.string());
if (!ipv6.is_null())
{
ipv6.to_binary(buffer);
......@@ -197,7 +197,7 @@ String *Item_func_inet6_ntoa::val_str_ascii(String *buffer)
return buffer;
}
Inet6_null ipv6(static_cast<const Binary_string&>(*tmp.string()));
Inet6Bundle::Fbt_null ipv6(static_cast<const Binary_string&>(*tmp.string()));
if (!ipv6.is_null())
{
ipv6.to_string(buffer);
......@@ -221,6 +221,22 @@ longlong Item_func_is_ipv4::val_int()
return !tmp.is_null() && !Inet4_null(*tmp.string()).is_null();
}
class IP6 : public Inet6Bundle::Fbt_null
{
public:
IP6(Item* arg) : Inet6Bundle::Fbt_null(arg) {}
bool is_v4compat() const
{
static_assert(sizeof(in6_addr) == IN6_ADDR_SIZE, "unexpected in6_addr size");
return IN6_IS_ADDR_V4COMPAT((struct in6_addr *) m_buffer);
}
bool is_v4mapped() const
{
static_assert(sizeof(in6_addr) == IN6_ADDR_SIZE, "unexpected in6_addr size");
return IN6_IS_ADDR_V4MAPPED((struct in6_addr *) m_buffer);
}
};
/**
Checks if the passed string represents an IPv6-address.
......@@ -230,17 +246,16 @@ longlong Item_func_is_ipv6::val_int()
{
DBUG_ASSERT(fixed());
String_ptr_and_buffer<STRING_BUFFER_USUAL_SIZE> tmp(args[0]);
return !tmp.is_null() && !Inet6_null(*tmp.string()).is_null();
return !tmp.is_null() && !Inet6Bundle::Fbt_null(*tmp.string()).is_null();
}
/**
Checks if the passed IPv6-address is an IPv4-compat IPv6-address.
*/
longlong Item_func_is_ipv4_compat::val_int()
{
Inet6_null ip6(args[0]);
IP6 ip6(args[0]);
return !ip6.is_null() && ip6.is_v4compat();
}
......@@ -251,6 +266,6 @@ longlong Item_func_is_ipv4_compat::val_int()
longlong Item_func_is_ipv4_mapped::val_int()
{
Inet6_null ip6(args[0]);
IP6 ip6(args[0]);
return !ip6.is_null() && ip6.is_v4mapped();
}
......@@ -2229,3 +2229,31 @@ SELECT * FROM t1 WHERE d >= ALL (SELECT * FROM t1);
d
12::
DROP TABLE t1;
#
# MDEV-27015 Assertion `!is_null()' failed in FixedBinTypeBundle<FbtImpl>::Fbt FixedBinTypeBundle<FbtImpl>::Field_fbt::to_fbt()
#
CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a INET6(6) DEFAULT '::10');
INSERT INTO t1(id) VALUES (1), (2), (3), (4);
INSERT INTO t1 VALUES (5,'::5'), (6,'::6');
SELECT * FROM t1 ORDER BY a;
id a
5 ::5
6 ::6
1 ::10
2 ::10
3 ::10
4 ::10
CREATE VIEW v1(a, m) AS SELECT a, MIN(id) FROM t1 GROUP BY a;
CREATE TABLE t2 SELECT * FROM v1;
SELECT * FROM v1 ORDER BY a;
a m
::5 5
::6 6
::10 1
SELECT * FROM t2 ORDER BY a;
a m
::5 5
::6 6
::10 1
DROP VIEW v1;
DROP TABLE t1, t2;
......@@ -1641,3 +1641,18 @@ SELECT * FROM t1 ORDER BY d;
SELECT * FROM t1 WHERE d <= ALL (SELECT * FROM t1);
SELECT * FROM t1 WHERE d >= ALL (SELECT * FROM t1);
DROP TABLE t1;
--echo #
--echo # MDEV-27015 Assertion `!is_null()' failed in FixedBinTypeBundle<FbtImpl>::Fbt FixedBinTypeBundle<FbtImpl>::Field_fbt::to_fbt()
--echo #
CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a INET6(6) DEFAULT '::10');
INSERT INTO t1(id) VALUES (1), (2), (3), (4);
INSERT INTO t1 VALUES (5,'::5'), (6,'::6');
SELECT * FROM t1 ORDER BY a;
CREATE VIEW v1(a, m) AS SELECT a, MIN(id) FROM t1 GROUP BY a;
CREATE TABLE t2 SELECT * FROM v1;
SELECT * FROM v1 ORDER BY a;
SELECT * FROM t2 ORDER BY a;
DROP VIEW v1;
DROP TABLE t1, t2;
/* Copyright (c) 2019 MariaDB Corporation
/* Copyright (c) 2019,2021 MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -21,14 +21,10 @@
#include <mysql/plugin_data_type.h>
#include <mysql/plugin_function.h>
Type_handler_inet6 type_handler_inet6;
static struct st_mariadb_data_type plugin_descriptor_type_inet6=
{
MariaDB_DATA_TYPE_INTERFACE_VERSION,
&type_handler_inet6
Inet6Bundle::type_handler_fbt()
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -484,6 +484,11 @@ class Binary_string: public Sql_alloc
if (str.Alloced_length)
Alloced_length= (uint32) (str.Alloced_length - offset);
}
LEX_CSTRING to_lex_cstring() const
{
LEX_CSTRING tmp= {Ptr, str_length};
return tmp;
}
inline LEX_CSTRING *get_value(LEX_CSTRING *res)
{
res->str= Ptr;
......
This diff is collapsed.
#ifndef SQL_TYPE_FIXEDBIN_STORAGE
#define SQL_TYPE_FIXEDBIN_STORAGE
/* Copyright (c) 2019,2021 MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
/*
This is a common code for plugin (?) types that are generally
handled like strings, but have their own fixed size on-disk binary storage
format and their own (variable size) canonical string representation.
Examples are INET6 and UUID types.
The MariaDB server uses three binary representations of a data type:
1. In-memory binary representation (user visible)
This representation:
- can be used in INSERT..VALUES (X'AABBCC')
- can be used in WHERE conditions: WHERE c1=X'AABBCC'
- is returned by CAST(x AS BINARY(N))
- is returned by Field::val_native() and Item::val_native()
2. In-record binary representation (user invisible)
This representation:
- is used in records (is pointed by Field::ptr)
- must be comparable by memcmp()
3. Binlog binary (row) representation
Usually, for string data types the binlog representation
is based on the in-record representation with trailing byte compression:
- trailing space compression for text string data types
- trailing zero compression for binary string data types
We have to have separate in-memory and in-record representations
because we use HA_KEYTYPE_BINARY for indexing. The engine API
does not have a way to pass a comparison function as a parameter.
The default implementation below assumes that:
- the in-memory and in-record representations are equal
- the binlog representation is compatible with BINARY(N)
This is OK for simple data types, like INET6.
Data type implementations that need different representations
can override the default implementation (like e.g. UUID does).
*/
/***********************************************************************/
template<size_t NATIVE_LEN, size_t MAX_CHAR_LEN>
class FixedBinTypeStorage
{
protected:
// The buffer that stores the in-memory binary representation
char m_buffer[NATIVE_LEN];
// Non-initializing constructor
FixedBinTypeStorage()
{ }
FixedBinTypeStorage & set_zero()
{
bzero(&m_buffer, sizeof(m_buffer));
return *this;
}
public:
// Initialize from the in-memory binary representation
FixedBinTypeStorage(const char *str, size_t length)
{
if (length != binary_length())
set_zero();
else
memcpy(&m_buffer, str, sizeof(m_buffer));
}
// Return the buffer with the in-memory representation
Lex_cstring to_lex_cstring() const
{
return Lex_cstring(m_buffer, sizeof(m_buffer));
}
static constexpr uint binary_length() { return NATIVE_LEN; }
static constexpr uint max_char_length() { return MAX_CHAR_LEN; }
// Compare the in-memory binary representations of two values
static int cmp(const LEX_CSTRING &a, const LEX_CSTRING &b)
{
DBUG_ASSERT(a.length == binary_length());
DBUG_ASSERT(b.length == binary_length());
return memcmp(a.str, b.str, b.length);
}
/*
Convert from the in-memory to the in-record representation.
Used in Field::store_native().
*/
static void memory_to_record(char *to, const char *from)
{
memcpy(to, from, NATIVE_LEN);
}
/*
Convert from the in-record to the in-memory representation
Used in Field::val_native().
*/
static void record_to_memory(char *to, const char *from)
{
memcpy(to, from, NATIVE_LEN);
}
/*
Hash the in-record representation
Used in Field::hash().
*/
static void hash_record(const uchar *ptr, ulong *nr, ulong *nr2)
{
my_charset_bin.hash_sort(ptr, binary_length(), nr, nr2);
}
static bool only_zero_bytes(const char *ptr, size_t length)
{
for (uint i= 0 ; i < length; i++)
{
if (ptr[i] != 0)
return false;
}
return true;
}
static ulong KEY_pack_flags(uint column_nr)
{
/*
Return zero by default. A particular data type can override
this method return some flags, e.g. HA_PACK_KEY to enable
key prefix compression.
*/
return 0;
}
/*
Convert from the in-record to the binlog representation.
Used in Field::pack(), and in filesort to store the addon fields.
By default, do what BINARY(N) does.
*/
static uchar *pack(uchar *to, const uchar *from, uint max_length)
{
return StringPack(&my_charset_bin, binary_length()).pack(to, from, max_length);
}
/*
Convert from the in-binary-log to the in-record representation.
Used in Field::unpack().
By default, do what BINARY(N) does.
*/
static const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end,
uint param_data)
{
return StringPack(&my_charset_bin, binary_length()).unpack(to, from, from_end,
param_data);
}
};
#endif /* SQL_TYPE_FIXEDBIN_STORAGE */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment