mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-9238 Wrap create_virtual_tmp_table() into a class, split into different steps
This commit is contained in:
@ -922,6 +922,51 @@ table_def::compatible_with(THD *thd, rpl_group_info *rgi,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
A wrapper to Virtual_tmp_table, to get access to its constructor,
|
||||
which is protected for safety purposes (against illegal use on stack).
|
||||
*/
|
||||
class Virtual_conversion_table: public Virtual_tmp_table
|
||||
{
|
||||
public:
|
||||
Virtual_conversion_table(THD *thd) :Virtual_tmp_table(thd) { }
|
||||
/**
|
||||
Add a new field into the virtual table.
|
||||
@param sql_type - The real_type of the field.
|
||||
@param metadata - The RBR binary log metadata for this field.
|
||||
@param target_field - The field from the target table, to get extra
|
||||
attributes from (e.g. typelib in case of ENUM).
|
||||
*/
|
||||
bool add(enum_field_types sql_type,
|
||||
uint16 metadata, const Field *target_field)
|
||||
{
|
||||
const Type_handler *handler= Type_handler::get_handler_by_real_type(sql_type);
|
||||
if (!handler)
|
||||
{
|
||||
sql_print_error("In RBR mode, Slave received unknown field type field %d "
|
||||
" for column Name: %s.%s.%s.",
|
||||
(int) sql_type,
|
||||
target_field->table->s->db.str,
|
||||
target_field->table->s->table_name.str,
|
||||
target_field->field_name);
|
||||
return true;
|
||||
}
|
||||
Field *tmp= handler->make_conversion_table_field(this, metadata,
|
||||
target_field);
|
||||
if (!tmp)
|
||||
return true;
|
||||
Virtual_tmp_table::add(tmp);
|
||||
DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d,"
|
||||
" maybe_null: %d, unsigned_flag: %d, pack_length: %u",
|
||||
sql_type, target_field->field_name,
|
||||
tmp->field_length, tmp->decimals(), TRUE,
|
||||
tmp->flags, tmp->pack_length()));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Create a conversion table.
|
||||
|
||||
@ -937,8 +982,7 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi,
|
||||
{
|
||||
DBUG_ENTER("table_def::create_conversion_table");
|
||||
|
||||
List<Column_definition> field_list;
|
||||
TABLE *conv_table= NULL;
|
||||
Virtual_conversion_table *conv_table;
|
||||
Relay_log_info *rli= rgi->rli;
|
||||
/*
|
||||
At slave, columns may differ. So we should create
|
||||
@ -946,101 +990,35 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi,
|
||||
conversion table.
|
||||
*/
|
||||
uint const cols_to_create= MY_MIN(target_table->s->fields, size());
|
||||
if (!(conv_table= new(thd) Virtual_conversion_table(thd)) ||
|
||||
conv_table->init(cols_to_create))
|
||||
goto err;
|
||||
for (uint col= 0 ; col < cols_to_create; ++col)
|
||||
{
|
||||
Column_definition *field_def=
|
||||
(Create_field*) alloc_root(thd->mem_root, sizeof(Create_field));
|
||||
bool unsigned_flag= 0;
|
||||
if (field_list.push_back(field_def, thd->mem_root))
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
uint decimals= 0;
|
||||
TYPELIB* interval= NULL;
|
||||
uint pack_length= 0;
|
||||
uint32 max_length=
|
||||
max_display_length_for_field(type(col), field_metadata(col));
|
||||
|
||||
switch(type(col)) {
|
||||
int precision;
|
||||
case MYSQL_TYPE_ENUM:
|
||||
case MYSQL_TYPE_SET:
|
||||
interval= static_cast<Field_enum*>(target_table->field[col])->typelib;
|
||||
pack_length= field_metadata(col) & 0x00ff;
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
/*
|
||||
The display length of a DECIMAL type is not the same as the
|
||||
length that should be supplied to make_field, so we correct
|
||||
the length here.
|
||||
*/
|
||||
precision= field_metadata(col) >> 8;
|
||||
decimals= field_metadata(col) & 0x00ff;
|
||||
max_length=
|
||||
my_decimal_precision_to_length(precision, decimals, FALSE);
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
sql_print_error("In RBR mode, Slave received incompatible DECIMAL field "
|
||||
"(old-style decimal field) from Master while creating "
|
||||
"conversion table. Please consider changing datatype on "
|
||||
"Master to new style decimal by executing ALTER command for"
|
||||
" column Name: %s.%s.%s.",
|
||||
target_table->s->db.str,
|
||||
target_table->s->table_name.str,
|
||||
target_table->field[col]->field_name);
|
||||
if (conv_table->add(type(col), field_metadata(col),
|
||||
target_table->field[col]))
|
||||
{
|
||||
DBUG_PRINT("debug", ("binlog_type: %d, metadata: %04X, target_field: '%s'"
|
||||
" make_conversion_table_field() failed",
|
||||
binlog_type(col), field_metadata(col),
|
||||
target_table->field[col]->field_name));
|
||||
goto err;
|
||||
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_GEOMETRY:
|
||||
pack_length= field_metadata(col) & 0x00ff;
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_TINY:
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_INT24:
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
/*
|
||||
As we don't know if the integer was signed or not on the master,
|
||||
assume we have same sign on master and slave. This is true when not
|
||||
using conversions so it should be true also when using conversions.
|
||||
*/
|
||||
unsigned_flag= ((Field_num*) target_table->field[col])->unsigned_flag;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d,"
|
||||
" maybe_null: %d, unsigned_flag: %d, pack_length: %u",
|
||||
binlog_type(col), target_table->field[col]->field_name,
|
||||
max_length, decimals, TRUE, unsigned_flag,
|
||||
pack_length));
|
||||
field_def->init_for_tmp_table(type(col),
|
||||
max_length,
|
||||
decimals,
|
||||
TRUE, // maybe_null
|
||||
unsigned_flag,
|
||||
pack_length);
|
||||
field_def->charset= target_table->field[col]->charset();
|
||||
field_def->interval= interval;
|
||||
}
|
||||
|
||||
conv_table= create_virtual_tmp_table(thd, field_list);
|
||||
if (conv_table->open())
|
||||
goto err; // Could not allocate record buffer?
|
||||
|
||||
DBUG_RETURN(conv_table);
|
||||
|
||||
err:
|
||||
if (conv_table == NULL)
|
||||
{
|
||||
rli->report(ERROR_LEVEL, ER_SLAVE_CANT_CREATE_CONVERSION, rgi->gtid_info(),
|
||||
ER_THD(thd, ER_SLAVE_CANT_CREATE_CONVERSION),
|
||||
target_table->s->db.str,
|
||||
target_table->s->table_name.str);
|
||||
}
|
||||
DBUG_RETURN(conv_table);
|
||||
if (conv_table)
|
||||
delete conv_table;
|
||||
rli->report(ERROR_LEVEL, ER_SLAVE_CANT_CREATE_CONVERSION, rgi->gtid_info(),
|
||||
ER_THD(thd, ER_SLAVE_CANT_CREATE_CONVERSION),
|
||||
target_table->s->db.str,
|
||||
target_table->s->table_name.str);
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
#endif /* MYSQL_CLIENT */
|
||||
|
||||
|
Reference in New Issue
Block a user