mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +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:
@@ -42,6 +42,12 @@ max_display_length_for_temporal2_field(uint32 int_display_length,
|
||||
@param sql_type Type of the field
|
||||
@param metadata The metadata from the master for the field.
|
||||
@return Maximum length of the field in bytes.
|
||||
|
||||
The precise values calculated by field->max_display_length() and
|
||||
calculated by max_display_length_for_field() can differ (by +1 or -1)
|
||||
for integer data types (TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT).
|
||||
This slight difference is not important here, because we call
|
||||
this function only for two *different* integer data types.
|
||||
*/
|
||||
static uint32
|
||||
max_display_length_for_field(enum_field_types sql_type, unsigned int metadata)
|
||||
@@ -737,6 +743,16 @@ can_convert_field_to(Field *field,
|
||||
case MYSQL_TYPE_INT24:
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
/*
|
||||
max_display_length_for_field() is not fully precise for the integer
|
||||
data types. So its result cannot be compared to the result of
|
||||
field->max_dispay_length() when the table field and the binlog field
|
||||
are of the same type.
|
||||
This code should eventually be rewritten not to use
|
||||
compare_lengths(), to detect subtype/supetype relations
|
||||
just using the type codes.
|
||||
*/
|
||||
DBUG_ASSERT(source_type != field->real_type());
|
||||
*order_var= compare_lengths(field, source_type, metadata);
|
||||
DBUG_ASSERT(*order_var != 0);
|
||||
DBUG_RETURN(is_conversion_ok(*order_var, rli));
|
||||
|
||||
Reference in New Issue
Block a user