Description:
When serializing and deserializing a table with DECIMAL data type the m_numeric_scale_null member variable of ColumnImpl is not updated. This seems to be since the deserialize code bypasses the member function setters for the member variables. Thus the m_numeric_scale_null variable is not set to false when m_numeric_scale is assigned a value.
The setter:
virtual void dd::ColumnImpl::set_numeric_scale(uint numeric_scale)
{
m_numeric_scale_null= false;
m_numeric_scale= numeric_scale;
}
The deserialize:
bool
Column_impl::deserialize(Sdi_rcontext *rctx, const RJ_Value &val)
{
<snip>
read(&m_char_length, val, "char_length");
read(&m_numeric_precision, val, "numeric_precision");
read(&m_numeric_scale, val, "numeric_scale");
^^^^^^^^^^^^^^^^^^^ leaving m_numeric_scale_null at default value true.
This is then later detected by a DBUG_ASSERT in fill_column_from_dd:
// Decimals
if (field_type == MYSQL_TYPE_DECIMAL || field_type == MYSQL_TYPE_NEWDECIMAL)
{
DBUG_ASSERT(col_obj->is_numeric_scale_null() == false);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ HERE
decimals= col_obj->numeric_scale();
}
else if (field_type == MYSQL_TYPE_FLOAT || field_type == MYSQL_TYPE_DOUBLE)
{
decimals= col_obj->is_numeric_scale_null() ? NOT_FIXED_DEC :
col_obj->numeric_scale();
}
else
decimals= 0;
Most likely also m_datetime_precision_null is affected by same problem.
How to repeat:
CREATE TABLE product (category INT NOT NULL, id INT NOT NULL, price DECIMAL, PRIMARY KEY(category, id));
serialize
deserialize
insert the deserialized table into DD
open table from dd
check the is_numeric_scale_null() for column price is false
Suggested fix:
Set m_numeric_scale_null (and most likely also m_datetime_precision_null) to false when deserializing a value for m_numeric_scale.
Improve unit test to check that roundtrip works also for DECIMAL and DATETIME data types.