diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_string.h | 5 | ||||
-rw-r--r-- | sql/sql_type_fixedbin.h | 72 | ||||
-rw-r--r-- | sql/sql_type_fixedbin_storage.h | 107 |
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 */ |