diff options
-rw-r--r-- | mysql-test/main/type_int.result | 15 | ||||
-rw-r--r-- | mysql-test/main/type_int.test | 17 | ||||
-rw-r--r-- | mysql-test/suite/funcs_1/r/is_columns_innodb.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/funcs_1/r/is_columns_memory.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/funcs_1/r/is_columns_myisam.result | 12 | ||||
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/field.h | 126 | ||||
-rw-r--r-- | sql/item.cc | 27 | ||||
-rw-r--r-- | sql/rpl_utility.cc | 16 | ||||
-rw-r--r-- | sql/sql_show.cc | 40 | ||||
-rw-r--r-- | sql/sql_type.h | 40 |
11 files changed, 224 insertions, 95 deletions
diff --git a/mysql-test/main/type_int.result b/mysql-test/main/type_int.result index 39e2e91ecc7..bd24641fd65 100644 --- a/mysql-test/main/type_int.result +++ b/mysql-test/main/type_int.result @@ -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 +# diff --git a/mysql-test/main/type_int.test b/mysql-test/main/type_int.test index 271b4d5862a..f0df08ffa2c 100644 --- a/mysql-test/main/type_int.test +++ b/mysql-test/main/type_int.test @@ -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 # diff --git a/mysql-test/suite/funcs_1/r/is_columns_innodb.result b/mysql-test/suite/funcs_1/r/is_columns_innodb.result index 297dc2d33f8..8f2ba33b591 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_innodb.result +++ b/mysql-test/suite/funcs_1/r/is_columns_innodb.result @@ -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 diff --git a/mysql-test/suite/funcs_1/r/is_columns_memory.result b/mysql-test/suite/funcs_1/r/is_columns_memory.result index e94d4c9123a..5eaa5b08cc2 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_memory.result +++ b/mysql-test/suite/funcs_1/r/is_columns_memory.result @@ -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 diff --git a/mysql-test/suite/funcs_1/r/is_columns_myisam.result b/mysql-test/suite/funcs_1/r/is_columns_myisam.result index c4e11e3f48b..4426583ac4c 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_myisam.result +++ b/mysql-test/suite/funcs_1/r/is_columns_myisam.result @@ -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 diff --git a/sql/field.cc b/sql/field.cc index 58b8105c00f..fceb3cc17d7 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -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) { diff --git a/sql/field.h b/sql/field.h index 7bd79630265..cdb62d6af16 100644 --- a/sql/field.h +++ b/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); diff --git a/sql/item.cc b/sql/item.cc index 56af69be427..35c5ab8cc3d 100644 --- a/sql/item.cc +++ b/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; } diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 58711078db6..31035fb5dcc 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -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)); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 38a13c49278..a45ca325d1a 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -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(); } } diff --git a/sql/sql_type.h b/sql/sql_type.h index dd37e2ba96c..e9307db7125 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -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: |