summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_string.h5
-rw-r--r--sql/sql_type_fixedbin.h72
-rw-r--r--sql/sql_type_fixedbin_storage.h107
3 files changed, 160 insertions, 24 deletions
diff --git a/sql/sql_string.h b/sql/sql_string.h
index fe57c8153bb..795f80c3e08 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -484,6 +484,11 @@ public:
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;
diff --git a/sql/sql_type_fixedbin.h b/sql/sql_type_fixedbin.h
index c6e3d20bcfa..5141cb9fad4 100644
--- a/sql/sql_type_fixedbin.h
+++ b/sql/sql_type_fixedbin.h
@@ -111,6 +111,12 @@ public:
return fbt;
}
+ static Fbt record_to_memory(const char *ptr)
+ {
+ Fbt fbt;
+ FbtImpl::record_to_memory(fbt.m_buffer, ptr);
+ return fbt;
+ }
/*
Check at Item's fix_fields() time if "item" can return a nullable value
on conversion to Fbt, or conversion produces a NOT NULL Fbt value.
@@ -132,10 +138,10 @@ public:
{
*error= make_from_item(item, warn);
}
- void to_binary(char *str, size_t str_size) const
+ void to_record(char *str, size_t str_size) const
{
DBUG_ASSERT(str_size >= sizeof(m_buffer));
- memcpy(str, m_buffer, sizeof(m_buffer));
+ FbtImpl::memory_to_record(str, m_buffer);
}
bool to_binary(String *to) const
{
@@ -154,18 +160,13 @@ public:
FbtImpl::max_char_length()+1));
return false;
}
- int cmp(const char *str, size_t length) const
- {
- DBUG_ASSERT(length == sizeof(m_buffer));
- return memcmp(m_buffer, str, length);
- }
int cmp(const Binary_string &other) const
{
- return cmp(other.ptr(), other.length());
+ return FbtImpl::cmp(FbtImpl::to_lex_cstring(), other.to_lex_cstring());
}
int cmp(const Fbt &other) const
{
- return memcmp(m_buffer, other.m_buffer, sizeof(m_buffer));
+ return FbtImpl::cmp(FbtImpl::to_lex_cstring(), other.to_lex_cstring());
}
};
@@ -191,9 +192,9 @@ public:
DBUG_ASSERT(!is_null());
return *this;
}
- void to_binary(char *str, size_t str_size) const
+ void to_record(char *str, size_t str_size) const
{
- to_fbt().to_binary(str, str_size);
+ to_fbt().to_record(str, str_size);
}
bool to_binary(String *to) const
{
@@ -257,6 +258,10 @@ public:
{
return FbtImpl::default_value();
}
+ ulong KEY_pack_flags(uint column_nr) const override
+ {
+ return FbtImpl::KEY_pack_flags(column_nr);
+ }
protocol_send_type_t protocol_send_type() const override
{
return PROTOCOL_SEND_STRING;
@@ -480,7 +485,7 @@ public:
DBUG_ASSERT(!item->null_value);
DBUG_ASSERT(FbtImpl::binary_length() == tmp.length());
DBUG_ASSERT(FbtImpl::binary_length() == sort_field->length);
- memcpy(to, tmp.ptr(), tmp.length());
+ FbtImpl::memory_to_record((char*) to, tmp.ptr());
}
uint make_packed_sort_key_part(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field,
@@ -501,7 +506,7 @@ public:
DBUG_ASSERT(!item->null_value);
DBUG_ASSERT(FbtImpl::binary_length() == tmp.length());
DBUG_ASSERT(FbtImpl::binary_length() == sort_field->length);
- memcpy(to, tmp.ptr(), tmp.length());
+ FbtImpl::memory_to_record((char*) to, tmp.ptr());
return tmp.length();
}
void sort_length(THD *thd, const Type_std_attributes *item,
@@ -697,9 +702,7 @@ public:
int cmp_native(const Native &a, const Native &b) const override
{
- DBUG_ASSERT(a.length() == FbtImpl::binary_length());
- DBUG_ASSERT(b.length() == FbtImpl::binary_length());
- return memcmp(a.ptr(), b.ptr(), FbtImpl::binary_length());
+ return FbtImpl::cmp(a.to_lex_cstring(), b.to_lex_cstring());
}
bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override
{
@@ -1104,7 +1107,7 @@ public:
if (fbt.is_null())
return maybe_null() ? set_null_with_warn(err)
: set_min_value_with_warn(err);
- fbt.to_binary((char *) ptr, FbtImpl::binary_length());
+ fbt.to_record((char *) ptr, FbtImpl::binary_length());
return 0;
}
@@ -1181,11 +1184,27 @@ public:
return false;
}
- String *val_str(String *val_buffer, String *) override
+ bool val_native(Native *to) override
+ {
+ DBUG_ASSERT(marked_for_read());
+ DBUG_ASSERT(!is_null());
+ if (to->alloc(FbtImpl::binary_length()))
+ return true;
+ to->length(FbtImpl::binary_length());
+ FbtImpl::record_to_memory((char*) to->ptr(), (const char*) ptr);
+ return false;
+ }
+
+ Fbt to_fbt() const
{
DBUG_ASSERT(marked_for_read());
- Fbt_null tmp((const char *) ptr, pack_length());
- return tmp.to_string(val_buffer) ? NULL : val_buffer;
+ DBUG_ASSERT(!is_null());
+ return Fbt::record_to_memory((const char*) ptr);
+ }
+
+ String *val_str(String *val_buffer, String *) override
+ {
+ return to_fbt().to_string(val_buffer) ? NULL : val_buffer;
}
my_decimal *val_decimal(my_decimal *to) override
@@ -1224,7 +1243,7 @@ public:
{
DBUG_ASSERT(marked_for_write_or_computed());
DBUG_ASSERT(value.length() == FbtImpl::binary_length());
- memcpy(ptr, value.ptr(), value.length());
+ FbtImpl::memory_to_record((char*) ptr, value.ptr());
return 0;
}
@@ -1406,6 +1425,13 @@ public:
item->type_handler() == type_handler());
return true;
}
+ void hash(ulong *nr, ulong *nr2)
+ {
+ if (is_null())
+ *nr^= (*nr << 1) | 1;
+ else
+ FbtImpl::hash_record(ptr, nr, nr2);
+ }
SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *prm, KEY_PART *key_part,
const Item_bool_func *cond,
scalar_comparison_op op, Item *value) override
@@ -1447,13 +1473,13 @@ public:
uchar *pack(uchar *to, const uchar *from, uint max_length) override
{
DBUG_PRINT("debug", ("Packing field '%s'", field_name.str));
- return StringPack(&my_charset_bin, FbtImpl::binary_length()).pack(to, from, max_length);
+ return FbtImpl::pack(to, from, max_length);
}
const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end,
uint param_data) override
{
- return StringPack(&my_charset_bin, FbtImpl::binary_length()).unpack(to, from, from_end, param_data);
+ return FbtImpl::unpack(to, from, from_end, param_data);
}
uint max_packed_col_length(uint max_length) override
diff --git a/sql/sql_type_fixedbin_storage.h b/sql/sql_type_fixedbin_storage.h
index 0e8ac81ab59..6e18335bd4c 100644
--- a/sql/sql_type_fixedbin_storage.h
+++ b/sql/sql_type_fixedbin_storage.h
@@ -21,6 +21,38 @@
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).
*/
/***********************************************************************/
@@ -29,6 +61,7 @@ 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
@@ -42,7 +75,7 @@ protected:
}
public:
- // Initialize from binary representation
+ // Initialize from the in-memory binary representation
FixedBinTypeStorage(const char *str, size_t length)
{
if (length != binary_length())
@@ -51,9 +84,49 @@ public:
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++)
@@ -64,5 +137,37 @@ public:
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 */