Skip to content
/ server Public
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 74 additions & 39 deletions sql/log_event.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@


#include "mariadb.h"
#include "mysql/psi/psi_base.h"
#include "sql_priv.h"
#include "handler.h"
#ifndef MYSQL_CLIENT
Expand Down Expand Up @@ -3718,17 +3719,32 @@ Table_map_log_event::~Table_map_log_event()
/**
Parses SIGNEDNESS field.

@param[out] vec stores the signedness flags extracted from field.
@param[out] column_metadata store all column metadata here (including signedness)
@param[in] field SIGNEDNESS field in table_map_event.
@param[in] length length of the field
*/
static void parse_signedness(std::vector<bool> &vec,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait a minute.
The implementation of C++ std::vector<bool> may specialize to use a bit array rather than a resizable array of bools (which typically occupy the space of a char each).
Dynamic_array<bool> isn’t also specialized AFAIA.

Reference: https://www.en.cppreference.com/w/cpp/container/vector_bool.html

unsigned char *field, unsigned int length)
static void parse_signedness(
Dynamic_array<Table_map_log_event::Optional_metadata_fields::Column_metadata>& column_metadata,
unsigned char *field, unsigned int length)
{
for (unsigned int i= 0; i < length; i++)
unsigned char *field_end= field + length;
unsigned char unsigned_bitfield= 0;
unsigned char mask= 0;

for (uint col= 0; col < column_metadata.size(); col++)
{
for (unsigned char c= 0x80; c != 0; c>>= 1)
vec.push_back(field[i] & c);
auto &col_meta= column_metadata.at(col);
if (!is_numeric_type(col_meta.column_type))
continue;
if (mask == 0)
{
if (field >= field_end)
return;
unsigned_bitfield= *field++;
mask= 0x80;
}
col_meta.is_unsigned= unsigned_bitfield & mask;
mask >>= 1;
}
}

Expand All @@ -3751,8 +3767,8 @@ static void parse_default_charset(Table_map_log_event::Optional_metadata_fields:
unsigned int col_index= net_field_length(&p);
unsigned int col_charset= net_field_length(&p);

default_charset.charset_pairs.push_back(std::make_pair(col_index,
col_charset));
default_charset.charset_pairs.append(std::make_pair(col_index,
col_charset));
}
}

Expand All @@ -3763,36 +3779,38 @@ static void parse_default_charset(Table_map_log_event::Optional_metadata_fields:
@param[in] field COLUMN_CHARSET field in table_map_event.
@param[in] length length of the field
*/
static void parse_column_charset(std::vector<unsigned int> &vec,
static void parse_column_charset(Dynamic_array<uint> &vec,
unsigned char *field, unsigned int length)
{
unsigned char* p= field;

while (p < field + length)
vec.push_back(net_field_length(&p));
vec.append(net_field_length(&p));
}

/**
Parses COLUMN_NAME field.

@param[in] root Allocate memory here
@param[out] name Store column names extracted from field here
@param[out] column_metadata store all column metadata here (including column names)
@param[in] field COLUMN_NAME field in table_map_event.
@param[in] length length of the field
*/
static bool parse_column_name(MEM_ROOT *root, LEX_CSTRING *name,
unsigned char *field, unsigned int length)
static bool parse_column_name(MEM_ROOT *root,
Dynamic_array<Table_map_log_event::Optional_metadata_fields::Column_metadata>& column_metadata,
unsigned char *field, unsigned int length)
{
for (uchar *end= field+length; field < end ; name++)
unsigned int col = 0;
for (uchar *end= field+length; field < end && col < column_metadata.size(); col++)
{
LEX_CSTRING& name = column_metadata.at(col).column_name;
uint name_length= net_field_length(&field);
if (!(name->str= strmake_root(root, (char*) field, name_length)))
if (!(name.str= strmake_root(root, (char*) field, name_length)))
return 1;
name->length= name_length;
name.length= name_length;
field+= name_length;
}

name->str= 0; // End marker
return 0;
}

Expand All @@ -3806,21 +3824,25 @@ static bool parse_column_name(MEM_ROOT *root, LEX_CSTRING *name,
@param[in] field COLUMN_NAME field in table_map_event.
@param[in] length length of the field
*/
static void parse_set_str_value(std::vector<Table_map_log_event::
Optional_metadata_fields::str_vector> &vec,
unsigned char *field, unsigned int length)
static void parse_set_str_value(
Dynamic_array<Table_map_log_event::Optional_metadata_fields::str_vector>
&vec,
unsigned char *field, unsigned int length)
{
unsigned char* p= field;

while (p < field + length)
{
unsigned int count= net_field_length(&p);

vec.push_back(std::vector<std::string>());
if (vec.reserve(vec.elements() + 1))
return;
vec.elements(vec.elements() + 1);
vec.back()->init(PSI_INSTRUMENT_MEM);
for (unsigned int i= 0; i < count; i++)
{
unsigned len1= net_field_length(&p);
vec.back().push_back(std::string(reinterpret_cast<char *>(p), len1));
vec.back()->append(LEX_CSTRING{reinterpret_cast<char *>(p), len1});
p+= len1;
}
}
Expand All @@ -3833,13 +3855,13 @@ static void parse_set_str_value(std::vector<Table_map_log_event::
@param[in] field GEOMETRY_TYPE field in table_map_event.
@param[in] length length of the field
*/
static void parse_geometry_type(std::vector<unsigned int> &vec,
static void parse_geometry_type(Dynamic_array<uint> &vec,
unsigned char *field, unsigned int length)
{
unsigned char* p= field;

while (p < field + length)
vec.push_back(net_field_length(&p));
vec.append(net_field_length(&p));
}

/**
Expand All @@ -3852,14 +3874,15 @@ static void parse_geometry_type(std::vector<unsigned int> &vec,
@param[in] field SIMPLE_PRIMARY_KEY field in table_map_event.
@param[in] length length of the field
*/
static void parse_simple_pk(std::vector<Table_map_log_event::
Optional_metadata_fields::uint_pair> &vec,
unsigned char *field, unsigned int length)
static void parse_simple_pk(
Dynamic_array<Table_map_log_event::Optional_metadata_fields::uint_pair>
&vec,
unsigned char *field, unsigned int length)
{
unsigned char* p= field;

while (p < field + length)
vec.push_back(std::make_pair(net_field_length(&p), 0));
vec.append(std::make_pair(net_field_length(&p), 0));
}

/**
Expand All @@ -3872,31 +3895,47 @@ static void parse_simple_pk(std::vector<Table_map_log_event::
@param[in] length length of the field
*/

static void parse_pk_with_prefix(std::vector<Table_map_log_event::
Optional_metadata_fields::uint_pair> &vec,
unsigned char *field, unsigned int length)
static void parse_pk_with_prefix(
Dynamic_array<Table_map_log_event::Optional_metadata_fields::uint_pair>
&vec,
unsigned char *field, unsigned int length)
{
unsigned char* p= field;

while (p < field + length)
{
unsigned int col_index= net_field_length(&p);
unsigned int col_prefix= net_field_length(&p);
vec.push_back(std::make_pair(col_index, col_prefix));
vec.append(std::make_pair(col_index, col_prefix));
}
}

Table_map_log_event::Optional_metadata_fields::
Optional_metadata_fields(MEM_ROOT *root, uint master_columns,
const uchar* column_types,
uchar* optional_metadata,
size_t optional_metadata_len,
bool only_column_names)
: m_column_charset(PSI_INSTRUMENT_MEM),
m_enum_and_set_column_charset(PSI_INSTRUMENT_MEM),
m_enum_str_value(PSI_INSTRUMENT_MEM),
m_set_str_value(PSI_INSTRUMENT_MEM), m_geometry_type(PSI_INSTRUMENT_MEM),
m_primary_key(PSI_INSTRUMENT_MEM),
m_column_metadata(PSI_INSTRUMENT_MEM, master_columns)
{
unsigned int len;
uchar *metadata_end;

allocation_error= 0;
m_column_name= 0;

for (uint i= 0; i < master_columns; i++)
{
Column_metadata column_metadata{};
column_metadata.column_type = column_types[i];
if (m_column_metadata.append(column_metadata))
goto error;
}

if (optional_metadata == NULL)
return;

Expand All @@ -3914,7 +3953,7 @@ Optional_metadata_fields(MEM_ROOT *root, uint master_columns,

switch(type) {
case SIGNEDNESS:
parse_signedness(m_signedness, field, len);
parse_signedness(m_column_metadata, field, len);
break;
case DEFAULT_CHARSET:
parse_default_charset(m_default_charset, field, len);
Expand All @@ -3923,11 +3962,7 @@ Optional_metadata_fields(MEM_ROOT *root, uint master_columns,
parse_column_charset(m_column_charset, field, len);
break;
case COLUMN_NAME:
if (!(m_column_name= (LEX_CSTRING*) alloc_root(root,
sizeof(LEX_CSTRING) *
(master_columns +1 ))))
goto error;
if (parse_column_name(root, m_column_name, field, len))
if (parse_column_name(root, m_column_metadata, field, len))
goto error;
break;
case SET_STR_VALUE:
Expand Down
52 changes: 41 additions & 11 deletions sql/log_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,32 @@

#include <my_bitmap.h>
#include "rpl_constants.h"
#include "sql_array.h"
#include <vector>
#include <string>
#include <functional>
#include <memory>
#include <map>
#include <lex_charset.h>

static inline bool is_numeric_type(uint type)
{
switch (type)
{
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
return true;
default:
return false;
}
}

#ifdef MYSQL_CLIENT
#include "sql_const.h"
#include "rpl_utility.h"
Expand Down Expand Up @@ -4502,41 +4521,51 @@ class Table_map_log_event : public Log_event
struct Optional_metadata_fields
{
typedef std::pair<unsigned int, unsigned int> uint_pair;
typedef std::vector<std::string> str_vector;
typedef Dynamic_array<LEX_CSTRING> str_vector;
bool allocation_error; /* Set if allocation of data structures fails */

struct Default_charset
{
Default_charset() : default_charset(0) {}
Default_charset() : default_charset(0), charset_pairs(PSI_INSTRUMENT_MEM)
{
}
bool empty() const { return default_charset == 0; }

// Default charset for the columns which are not in charset_pairs.
unsigned int default_charset;

/* The uint_pair means <column index, column charset number>. */
std::vector<uint_pair> charset_pairs;
// std::vector<uint_pair> charset_pairs;
Dynamic_array<uint_pair> charset_pairs;
};

// Contents of DEFAULT_CHARSET field is converted into Default_charset.
Default_charset m_default_charset;
// Contents of ENUM_AND_SET_DEFAULT_CHARSET are converted into
// Default_charset.
Default_charset m_enum_and_set_default_charset;
std::vector<bool> m_signedness;
// Character set number of every string column
std::vector<unsigned int> m_column_charset;
Dynamic_array<uint> m_column_charset;
// Character set number of every ENUM or SET column.
std::vector<unsigned int> m_enum_and_set_column_charset;
LEX_CSTRING *m_column_name;
Dynamic_array<uint> m_enum_and_set_column_charset;
// each str_vector stores values of one enum/set column
std::vector<str_vector> m_enum_str_value;
std::vector<str_vector> m_set_str_value;
std::vector<unsigned int> m_geometry_type;
Dynamic_array<str_vector> m_enum_str_value;
Dynamic_array<str_vector> m_set_str_value;
Dynamic_array<uint> m_geometry_type;
/*
The uint_pair means <column index, prefix length>. Prefix length is 0 if
whole column value is used.
*/
std::vector<uint_pair> m_primary_key;
Dynamic_array<uint_pair> m_primary_key;

struct Column_metadata
{
LEX_CSTRING column_name{ nullptr, 0 };
uchar column_type{};
bool is_unsigned{ false };
};

Dynamic_array<Column_metadata> m_column_metadata;

/*
It parses m_optional_metadata and populates into above variables.
Expand All @@ -4549,6 +4578,7 @@ class Table_map_log_event : public Log_event
@param[in] only_column_names Only read column names
*/
Optional_metadata_fields(MEM_ROOT *root, uint master_cols,
const uchar* column_types,
uchar* optional_metadata,
size_t optional_metadata_len,
bool only_column_names);
Expand Down
Loading