1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-15926 MEDIUMINT returns wrong I_S attributes

Problem:

The logic in store_column_type() with a switch on field type was
hard to follow. The part for MEDIUMINT (MYSQL_TYPE_INT24) was not correct.
It erroneously calculated the precision of MEDIUMINT UNSIGNED
as 7 instead of 8.

A similar hard-to-follow switch doing some type specific calculations
resided in adjust_max_effective_column_length(). It was also wrong for
MEDIUMINT (reported as a separate issue in MDEV-15946).

Solution:

1. Introducing a new class Information_schema_numeric_attributes
2. Adding a new virtual method Field::information_schema_numeric_attributes()
3. Splitting the logic in store_column_type() into virtual
   implementations of information_schema_numeric_attributes().
4. In order to avoid adding duplicate code for the integer data types,
   adding a new virtual method Field_int::numeric_precision(),
   which returns the number of digits.

Additional changes:

1. Adding the "const" qualifier to Field::max_display_length()

2. Moving the code from adjust_max_effective_column_length()
  directly to Field::max_display_length().
  There was no any sense to have two implementations:
  - a set of wrong virtual implementations for Field_xxx::max_display_length()
  - additional code in adjust_max_effective_column_length() fixing
    bad results of Field_xxx::max_display_length()
  This change is safe:
  - The code using Field::max_display_length()
    in field.cc, sql_show.cc, sql_type.cc is not affected.
  - The code in rpl_utility.cc is also not affected.
    See a new DBUG_ASSSERT and new comments explaining why.

  In the new reduction, Field_xxx::max_display_length() returns
  correct results for all integer types (except MEDIUMINT, see below).

  Putting implementations of numeric_precision() and max_display_length()
  near each other in field.h made the logic much clearer and thus
  helped to reveal bad results for Field_medium::max_display_length(),
  which returns 9 instead of 8 for signed MEDIUMINT fields.
  This problem will be addressed separately (MDEV-15946).

Note, this change is also useful for pluggable data types (see MDEV-4912),
as now a user defined Field_xxx has a way to control what's returned
in INFORMATION_SCHEMA.COLUMNS.NUMERIC_PRECISION and
INFORMATION_SCHEMA.COLUMNS.NUMERIC_SCALE by implementing
a desired behavior in Field_xxx::information_schema_numeric_attributes().
This commit is contained in:
Alexander Barkov
2018-04-20 18:11:27 +04:00
parent 38c799c9a5
commit 9aaf62d058
11 changed files with 224 additions and 95 deletions

View File

@ -911,6 +911,46 @@ public:
};
class Information_schema_numeric_attributes
{
enum enum_attr
{
ATTR_NONE= 0,
ATTR_PRECISION= 1,
ATTR_SCALE= 2,
ATTR_PRECISION_AND_SCALE= (ATTR_PRECISION|ATTR_SCALE)
};
uint m_precision;
uint m_scale;
enum_attr m_available_attributes;
public:
Information_schema_numeric_attributes()
:m_precision(0), m_scale(0),
m_available_attributes(ATTR_NONE)
{ }
Information_schema_numeric_attributes(uint precision)
:m_precision(precision), m_scale(0),
m_available_attributes(ATTR_PRECISION)
{ }
Information_schema_numeric_attributes(uint precision, uint scale)
:m_precision(precision), m_scale(scale),
m_available_attributes(ATTR_PRECISION_AND_SCALE)
{ }
bool has_precision() const { return m_available_attributes & ATTR_PRECISION; }
bool has_scale() const { return m_available_attributes & ATTR_SCALE; }
uint precision() const
{
DBUG_ASSERT(has_precision());
return (uint) m_precision;
}
uint scale() const
{
DBUG_ASSERT(has_scale());
return (uint) m_scale;
}
};
class Type_handler
{
protected: