mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +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:
@@ -93,3 +93,18 @@ DROP TABLE t1;
|
||||
#
|
||||
# End of 10.2 tests
|
||||
#
|
||||
#
|
||||
# Start of 10.3 tests
|
||||
#
|
||||
#
|
||||
# MDEV-15926 MEDIUMINT returns wrong I_S attributes
|
||||
#
|
||||
CREATE TABLE t1 (a MEDIUMINT, b MEDIUMINT UNSIGNED);
|
||||
SELECT COLUMN_NAME, NUMERIC_PRECISION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1' ORDER BY COLUMN_NAME;
|
||||
COLUMN_NAME NUMERIC_PRECISION
|
||||
a 7
|
||||
b 8
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.3 tests
|
||||
#
|
||||
|
||||
@@ -76,3 +76,20 @@ DROP TABLE t1;
|
||||
--echo #
|
||||
--echo # End of 10.2 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.3 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-15926 MEDIUMINT returns wrong I_S attributes
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a MEDIUMINT, b MEDIUMINT UNSIGNED);
|
||||
SELECT COLUMN_NAME, NUMERIC_PRECISION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1' ORDER BY COLUMN_NAME;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.3 tests
|
||||
--echo #
|
||||
|
||||
@@ -427,9 +427,9 @@ def test tb1 f19 19 NULL YES smallint NULL NULL 5 0 NULL NULL NULL smallint(5) u
|
||||
def test tb1 f2 2 NULL YES char 0 0 NULL NULL NULL latin1 latin1_bin char(0) select,insert,update,references NEVER NULL
|
||||
def test tb1 f20 20 NULL YES smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f21 21 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(9) select,insert,update,references NEVER NULL
|
||||
def test tb1 f22 22 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb1 f23 23 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f24 24 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f22 22 NULL YES mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb1 f23 23 NULL YES mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f24 24 NULL YES mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f25 25 NULL YES int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NEVER NULL
|
||||
def test tb1 f26 26 NULL YES int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb1 f27 27 NULL YES int NULL NULL 10 0 NULL NULL NULL int(10) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
@@ -543,9 +543,9 @@ def test tb3 f135 18 999 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) un
|
||||
def test tb3 f136 19 00999 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f137 20 00999 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f138 21 9999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(9) select,insert,update,references NEVER NULL
|
||||
def test tb3 f139 22 9999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb3 f140 23 00009999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f141 24 00009999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f139 22 9999 NO mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb3 f140 23 00009999 NO mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f141 24 00009999 NO mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f142 25 99999 NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NEVER NULL
|
||||
def test tb3 f143 26 99999 NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb3 f144 27 0000099999 NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
|
||||
@@ -434,9 +434,9 @@ def test tb1 f19 11 NULL YES smallint NULL NULL 5 0 NULL NULL NULL smallint(5) u
|
||||
def test tb1 f2 2 NULL YES char 1 1 NULL NULL NULL latin1 latin1_bin char(1) select,insert,update,references NEVER NULL
|
||||
def test tb1 f20 12 NULL YES smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f21 13 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(9) select,insert,update,references NEVER NULL
|
||||
def test tb1 f22 14 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb1 f23 15 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f24 16 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f22 14 NULL YES mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb1 f23 15 NULL YES mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f24 16 NULL YES mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f25 17 NULL YES int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NEVER NULL
|
||||
def test tb1 f26 18 NULL YES int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb1 f27 19 NULL YES int NULL NULL 10 0 NULL NULL NULL int(10) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
@@ -538,9 +538,9 @@ def test tb3 f135 12 999 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) un
|
||||
def test tb3 f136 13 00999 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f137 14 00999 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f138 15 9999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(9) select,insert,update,references NEVER NULL
|
||||
def test tb3 f139 16 9999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb3 f140 17 00009999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f141 18 00009999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f139 16 9999 NO mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb3 f140 17 00009999 NO mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f141 18 00009999 NO mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f142 19 99999 NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NEVER NULL
|
||||
def test tb3 f143 20 99999 NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb3 f144 21 0000099999 NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
|
||||
@@ -476,9 +476,9 @@ def test tb1 f19 19 NULL YES smallint NULL NULL 5 0 NULL NULL NULL smallint(5) u
|
||||
def test tb1 f2 2 NULL YES char 1 1 NULL NULL NULL latin1 latin1_bin char(1) select,insert,update,references NEVER NULL
|
||||
def test tb1 f20 20 NULL YES smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f21 21 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(9) select,insert,update,references NEVER NULL
|
||||
def test tb1 f22 22 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb1 f23 23 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f24 24 NULL YES mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f22 22 NULL YES mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb1 f23 23 NULL YES mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f24 24 NULL YES mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb1 f25 25 NULL YES int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NEVER NULL
|
||||
def test tb1 f26 26 NULL YES int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb1 f27 27 NULL YES int NULL NULL 10 0 NULL NULL NULL int(10) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
@@ -600,9 +600,9 @@ def test tb3 f135 18 999 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) un
|
||||
def test tb3 f136 19 00999 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f137 20 00999 NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f138 21 9999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(9) select,insert,update,references NEVER NULL
|
||||
def test tb3 f139 22 9999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb3 f140 23 00009999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f141 24 00009999 NO mediumint NULL NULL 7 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f139 22 9999 NO mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb3 f140 23 00009999 NO mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f141 24 00009999 NO mediumint NULL NULL 8 0 NULL NULL NULL mediumint(8) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
def test tb3 f142 25 99999 NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NEVER NULL
|
||||
def test tb3 f143 26 99999 NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL
|
||||
def test tb3 f144 27 0000099999 NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned zerofill select,insert,update,references NEVER NULL
|
||||
|
||||
@@ -11072,7 +11072,7 @@ bool Column_definition::set_compressed(const char *method)
|
||||
length
|
||||
*/
|
||||
|
||||
uint32 Field_blob::max_display_length()
|
||||
uint32 Field_blob::max_display_length() const
|
||||
{
|
||||
switch (packlength)
|
||||
{
|
||||
|
||||
126
sql/field.h
126
sql/field.h
@@ -1116,6 +1116,11 @@ public:
|
||||
memcpy(ptr, val, len);
|
||||
}
|
||||
virtual uint decimals() const { return 0; }
|
||||
virtual Information_schema_numeric_attributes
|
||||
information_schema_numeric_attributes() const
|
||||
{
|
||||
return Information_schema_numeric_attributes();
|
||||
}
|
||||
/*
|
||||
Caller beware: sql_type can change str.Ptr, so check
|
||||
ptr() to see if it changed if you are using your own buffer
|
||||
@@ -1390,8 +1395,7 @@ public:
|
||||
}
|
||||
|
||||
/* maximum possible display length */
|
||||
virtual uint32 max_display_length()= 0;
|
||||
|
||||
virtual uint32 max_display_length() const= 0;
|
||||
/**
|
||||
Whether a field being created is compatible with a existing one.
|
||||
|
||||
@@ -1726,7 +1730,7 @@ public:
|
||||
CHARSET_INFO *charset(void) const { return field_charset; }
|
||||
enum Derivation derivation(void) const { return field_derivation; }
|
||||
bool binary() const { return field_charset == &my_charset_bin; }
|
||||
uint32 max_display_length() { return field_length; }
|
||||
uint32 max_display_length() const { return field_length; }
|
||||
friend class Create_field;
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
bool val_bool() { return val_real() != 0e0; }
|
||||
@@ -1817,6 +1821,13 @@ public:
|
||||
{
|
||||
return do_field_real;
|
||||
}
|
||||
Information_schema_numeric_attributes
|
||||
information_schema_numeric_attributes() const
|
||||
{
|
||||
return dec == NOT_FIXED_DEC ?
|
||||
Information_schema_numeric_attributes(field_length) :
|
||||
Information_schema_numeric_attributes(field_length, dec);
|
||||
}
|
||||
int save_in_field(Field *to) { return to->store(val_real()); }
|
||||
bool memcpy_field_possible(const Field *from) const
|
||||
{
|
||||
@@ -1833,7 +1844,7 @@ public:
|
||||
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
bool val_bool() { return val_real() != 0e0; }
|
||||
uint32 max_display_length() { return field_length; }
|
||||
uint32 max_display_length() const { return field_length; }
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item);
|
||||
};
|
||||
@@ -1852,6 +1863,12 @@ public:
|
||||
const Type_handler *type_handler() const { return &type_handler_olddecimal; }
|
||||
enum ha_base_keytype key_type() const
|
||||
{ return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
|
||||
Information_schema_numeric_attributes
|
||||
information_schema_numeric_attributes() const
|
||||
{
|
||||
uint tmp= dec ? 2 : 1; // The sign and the decimal point
|
||||
return Information_schema_numeric_attributes(field_length - tmp, dec);
|
||||
}
|
||||
Copy_func *get_copy_func(const Field *from) const
|
||||
{
|
||||
return eq_def(from) ? get_identical_copy_func() : do_field_string;
|
||||
@@ -1936,7 +1953,12 @@ public:
|
||||
void sort_string(uchar *buff, uint length);
|
||||
bool zero_pack() const { return 0; }
|
||||
void sql_type(String &str) const;
|
||||
uint32 max_display_length() { return field_length; }
|
||||
uint32 max_display_length() const { return field_length; }
|
||||
Information_schema_numeric_attributes
|
||||
information_schema_numeric_attributes() const
|
||||
{
|
||||
return Information_schema_numeric_attributes(precision, dec);
|
||||
}
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
uint32 pack_length() const { return (uint32) bin_size; }
|
||||
uint pack_length_from_metadata(uint field_metadata);
|
||||
@@ -1954,6 +1976,7 @@ class Field_int :public Field_num
|
||||
protected:
|
||||
String *val_str_from_long(String *val_buffer, uint max_char_length,
|
||||
int radix, long nr);
|
||||
uint32 sign_length() const { return (flags & UNSIGNED_FLAG) ? 0 : 1; }
|
||||
public:
|
||||
Field_int(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
|
||||
uchar null_bit_arg, enum utype unireg_check_arg,
|
||||
@@ -1966,6 +1989,12 @@ public:
|
||||
bool val_bool() { return val_int() != 0; }
|
||||
int store_time_dec(const MYSQL_TIME *ltime, uint dec);
|
||||
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
|
||||
virtual uint numeric_precision() const= 0;
|
||||
Information_schema_numeric_attributes
|
||||
information_schema_numeric_attributes() const
|
||||
{
|
||||
return Information_schema_numeric_attributes(numeric_precision(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1994,7 +2023,18 @@ public:
|
||||
void sort_string(uchar *buff,uint length);
|
||||
uint32 pack_length() const { return 1; }
|
||||
void sql_type(String &str) const;
|
||||
uint32 max_display_length() { return 4; }
|
||||
/*
|
||||
SIGNED: -128..127 digits=3 nchars=4
|
||||
UNDIGNED: 0..255 digits=3 nchars=3
|
||||
*/
|
||||
uint numeric_precision() const
|
||||
{
|
||||
return MAX_TINYINT_WIDTH;
|
||||
}
|
||||
uint32 max_display_length() const
|
||||
{
|
||||
return MAX_TINYINT_WIDTH + sign_length();
|
||||
}
|
||||
|
||||
virtual uchar *pack(uchar* to, const uchar *from, uint max_length)
|
||||
{
|
||||
@@ -2044,7 +2084,18 @@ public:
|
||||
void sort_string(uchar *buff,uint length);
|
||||
uint32 pack_length() const { return 2; }
|
||||
void sql_type(String &str) const;
|
||||
uint32 max_display_length() { return 6; }
|
||||
/*
|
||||
SIGNED: -32768..32767 digits=5 nchars=6
|
||||
UNDIGNED: 0..65535 digits=5 nchars=5
|
||||
*/
|
||||
uint numeric_precision() const
|
||||
{
|
||||
return MAX_SMALLINT_WIDTH;
|
||||
}
|
||||
uint32 max_display_length() const
|
||||
{
|
||||
return MAX_SMALLINT_WIDTH + sign_length();
|
||||
}
|
||||
|
||||
virtual uchar *pack(uchar* to, const uchar *from, uint max_length)
|
||||
{ return pack_int16(to, from); }
|
||||
@@ -2079,7 +2130,21 @@ public:
|
||||
void sort_string(uchar *buff,uint length);
|
||||
uint32 pack_length() const { return 3; }
|
||||
void sql_type(String &str) const;
|
||||
uint32 max_display_length() { return 8; }
|
||||
/*
|
||||
MEDIUMINT has a different number of digits for signed and unsigned:
|
||||
MEDIUMINT SIGNED: -8388608 .. 8388607 digits=7 char_length=8
|
||||
MEDIUMINT UNSIGNED 0 .. 16777215 digits=8 char_length=8
|
||||
*/
|
||||
uint numeric_precision() const
|
||||
{
|
||||
uint ndigits= MAX_MEDIUMINT_WIDTH - 1 + MY_TEST(flags & UNSIGNED_FLAG);
|
||||
return ndigits;
|
||||
}
|
||||
uint32 max_display_length() const
|
||||
{
|
||||
// Looks too long for SIGNED: See MDEV-15946
|
||||
return MAX_MEDIUMINT_WIDTH + sign_length();
|
||||
}
|
||||
|
||||
virtual uchar *pack(uchar* to, const uchar *from, uint max_length)
|
||||
{
|
||||
@@ -2119,7 +2184,18 @@ public:
|
||||
void sort_string(uchar *buff,uint length);
|
||||
uint32 pack_length() const { return 4; }
|
||||
void sql_type(String &str) const;
|
||||
uint32 max_display_length() { return MY_INT32_NUM_DECIMAL_DIGITS; }
|
||||
/*
|
||||
SIGNED: -2147483648..2147483647 digits=10 nchars=11
|
||||
UNSIGNED: 0..4294967295 digits=10 nchars=10
|
||||
*/
|
||||
uint numeric_precision() const
|
||||
{
|
||||
return MAX_INT_WIDTH;
|
||||
}
|
||||
uint32 max_display_length() const
|
||||
{
|
||||
return MAX_INT_WIDTH + sign_length();
|
||||
}
|
||||
virtual uchar *pack(uchar* to, const uchar *from,
|
||||
uint max_length __attribute__((unused)))
|
||||
{
|
||||
@@ -2169,7 +2245,15 @@ public:
|
||||
void sort_string(uchar *buff,uint length);
|
||||
uint32 pack_length() const { return 8; }
|
||||
void sql_type(String &str) const;
|
||||
uint32 max_display_length() { return 20; }
|
||||
/*
|
||||
SIGNED: -9223372036854775808..9223372036854775807 digits=19 nchars=20
|
||||
UNSIGNED: 0..18446744073709551615 digits=20 nchars=20
|
||||
*/
|
||||
uint numeric_precision() const
|
||||
{
|
||||
return MAX_BIGINT_WIDTH - sign_length();
|
||||
}
|
||||
uint32 max_display_length() const { return MAX_BIGINT_WIDTH; }
|
||||
virtual uchar *pack(uchar* to, const uchar *from,
|
||||
uint max_length __attribute__((unused)))
|
||||
{
|
||||
@@ -2361,7 +2445,7 @@ public:
|
||||
uint32 pack_length() const { return 0; }
|
||||
void sql_type(String &str) const;
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
uint32 max_display_length() { return 4; }
|
||||
uint32 max_display_length() const { return 4; }
|
||||
void move_field_offset(my_ptrdiff_t ptr_diff) {}
|
||||
bool can_optimize_keypart_ref(const Item_bool_func *cond,
|
||||
const Item *item) const
|
||||
@@ -2400,7 +2484,7 @@ public:
|
||||
return to->store_time_dec(<ime, decimals());
|
||||
}
|
||||
bool memcpy_field_possible(const Field *from) const;
|
||||
uint32 max_display_length() { return field_length; }
|
||||
uint32 max_display_length() const { return field_length; }
|
||||
bool str_needs_quotes() { return TRUE; }
|
||||
enum Derivation derivation(void) const { return DERIVATION_NUMERIC; }
|
||||
uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
|
||||
@@ -2700,7 +2784,12 @@ public:
|
||||
String *val_str(String*,String *);
|
||||
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
|
||||
bool send_binary(Protocol *protocol);
|
||||
uint32 max_display_length() { return field_length; }
|
||||
Information_schema_numeric_attributes
|
||||
information_schema_numeric_attributes() const
|
||||
{
|
||||
return Information_schema_numeric_attributes();
|
||||
}
|
||||
uint32 max_display_length() const { return field_length; }
|
||||
void sql_type(String &str) const;
|
||||
};
|
||||
|
||||
@@ -3355,7 +3444,7 @@ private:
|
||||
Field_varstring::sql_type(str);
|
||||
str.append(STRING_WITH_LEN(" /*!100301 COMPRESSED*/"));
|
||||
}
|
||||
uint32 max_display_length() { return field_length - 1; }
|
||||
uint32 max_display_length() const { return field_length - 1; }
|
||||
int cmp_max(const uchar *a_ptr, const uchar *b_ptr, uint max_len);
|
||||
|
||||
/*
|
||||
@@ -3635,7 +3724,7 @@ public:
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
bool has_charset(void) const
|
||||
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
|
||||
uint32 max_display_length();
|
||||
uint32 max_display_length() const;
|
||||
uint32 char_length() const;
|
||||
uint is_equal(Create_field *new_field);
|
||||
private:
|
||||
@@ -3915,7 +4004,12 @@ public:
|
||||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; }
|
||||
uint32 key_length() const { return (uint32) (field_length + 7) / 8; }
|
||||
uint32 max_data_length() const { return (field_length + 7) / 8; }
|
||||
uint32 max_display_length() { return field_length; }
|
||||
uint32 max_display_length() const { return field_length; }
|
||||
Information_schema_numeric_attributes
|
||||
information_schema_numeric_attributes() const
|
||||
{
|
||||
return Information_schema_numeric_attributes(field_length);
|
||||
}
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
int reset(void) {
|
||||
bzero(ptr, bytes_in_rec);
|
||||
|
||||
27
sql/item.cc
27
sql/item.cc
@@ -3187,33 +3187,6 @@ inline static uint32
|
||||
adjust_max_effective_column_length(Field *field_par, uint32 max_length)
|
||||
{
|
||||
uint32 new_max_length= field_par->max_display_length();
|
||||
uint32 sign_length= (field_par->flags & UNSIGNED_FLAG) ? 0 : 1;
|
||||
|
||||
switch (field_par->type())
|
||||
{
|
||||
case MYSQL_TYPE_INT24:
|
||||
/*
|
||||
Compensate for MAX_MEDIUMINT_WIDTH being 1 too long (8)
|
||||
compared to the actual number of digits that can fit into
|
||||
the column.
|
||||
*/
|
||||
new_max_length+= 1;
|
||||
/* fall through */
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_TINY:
|
||||
case MYSQL_TYPE_SHORT:
|
||||
|
||||
/* Take out the sign and add a conditional sign */
|
||||
new_max_length= new_max_length - 1 + sign_length;
|
||||
break;
|
||||
|
||||
/* BINGINT is always 20 no matter the sign */
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
/* make gcc happy */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Adjust only if the actual precision based one is bigger than specified */
|
||||
return new_max_length > max_length ? new_max_length : max_length;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -5636,7 +5636,6 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs,
|
||||
uint offset)
|
||||
{
|
||||
bool is_blob;
|
||||
int decimals, field_length;
|
||||
const char *tmp_buff;
|
||||
char column_type_buff[MAX_FIELD_WIDTH];
|
||||
String column_type(column_type_buff, sizeof(column_type_buff), cs);
|
||||
@@ -5686,35 +5685,10 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs,
|
||||
They are set to -1 if they should not be set (we should return NULL)
|
||||
*/
|
||||
|
||||
field_length= -1;
|
||||
decimals= field->decimals();
|
||||
Information_schema_numeric_attributes num=
|
||||
field->information_schema_numeric_attributes();
|
||||
|
||||
switch (field->type()) {
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
field_length= ((Field_new_decimal*) field)->precision;
|
||||
break;
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
field_length= field->field_length - (decimals ? 2 : 1);
|
||||
break;
|
||||
case MYSQL_TYPE_TINY:
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_INT24:
|
||||
field_length= field->max_display_length() - 1;
|
||||
break;
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
field_length= field->max_display_length() -
|
||||
((field->flags & UNSIGNED_FLAG) ? 0 : 1);
|
||||
break;
|
||||
case MYSQL_TYPE_BIT:
|
||||
field_length= field->max_display_length();
|
||||
decimals= -1; // return NULL
|
||||
break;
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
field_length= field->field_length;
|
||||
if (decimals == NOT_FIXED_DEC)
|
||||
decimals= -1; // return NULL
|
||||
break;
|
||||
case MYSQL_TYPE_TIME:
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
@@ -5727,15 +5701,15 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs,
|
||||
}
|
||||
|
||||
/* NUMERIC_PRECISION column */
|
||||
if (field_length >= 0)
|
||||
if (num.has_precision())
|
||||
{
|
||||
table->field[offset + 3]->store((longlong) field_length, TRUE);
|
||||
table->field[offset + 3]->store((longlong) num.precision(), true);
|
||||
table->field[offset + 3]->set_notnull();
|
||||
|
||||
/* NUMERIC_SCALE column */
|
||||
if (decimals >= 0)
|
||||
if (num.has_scale())
|
||||
{
|
||||
table->field[offset + 4]->store((longlong) decimals, TRUE);
|
||||
table->field[offset + 4]->store((longlong) num.scale(), true);
|
||||
table->field[offset + 4]->set_notnull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user