diff options
author | Alexander Barkov <bar@mariadb.com> | 2019-05-28 15:50:11 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2019-05-28 15:50:11 +0400 |
commit | f021317ae1bceb1a70fd6b72a9e4afd72e5e5fbe (patch) | |
tree | dc98c989edd63a886444d6b2f2d17469579ddb91 | |
parent | d1d6fe9abf6dc11745ee4432ab97a46cbb244bf5 (diff) | |
download | mariadb-git-f021317ae1bceb1a70fd6b72a9e4afd72e5e5fbe.tar.gz |
MDEV-19612 Split ALTER related data type specific code in sql_table.cc to Type_handler
-rw-r--r-- | mysql-test/main/alter_table_debug.result | 26 | ||||
-rw-r--r-- | mysql-test/main/alter_table_debug.test | 31 | ||||
-rw-r--r-- | sql/sql_alter.cc | 18 | ||||
-rw-r--r-- | sql/sql_alter.h | 3 | ||||
-rw-r--r-- | sql/sql_table.cc | 36 | ||||
-rw-r--r-- | sql/sql_type.cc | 71 | ||||
-rw-r--r-- | sql/sql_type.h | 22 |
7 files changed, 174 insertions, 33 deletions
diff --git a/mysql-test/main/alter_table_debug.result b/mysql-test/main/alter_table_debug.result new file mode 100644 index 00000000000..3366f1721cd --- /dev/null +++ b/mysql-test/main/alter_table_debug.result @@ -0,0 +1,26 @@ +# +# Start of 10.5 tests +# +# +# MDEV-19612 Split ALTER related data type specific code in sql_table.cc to Type_handler +# +SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE'; +CREATE TABLE t1 (a INT); +ALTER TABLE t1 ALGORITHM=COPY, ADD b INT NOT NULL; +DROP TABLE t1; +SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE'; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0); +ALTER TABLE t1 ALGORITHM=COPY, ADD b INT NOT NULL; +DROP TABLE t1; +SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE'; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0); +SET debug_dbug='+d,validate_implicit_default_value_error'; +ALTER TABLE t1 ALGORITHM=COPY, ADD b INT NOT NULL; +ERROR 22007: Incorrect int value: '0' for column `test`.`t1`.`b` at row 1 +SET debug_dbug='-d,validate_implicit_default_value_error'; +DROP TABLE t1; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/alter_table_debug.test b/mysql-test/main/alter_table_debug.test new file mode 100644 index 00000000000..43a1f1bcbd8 --- /dev/null +++ b/mysql-test/main/alter_table_debug.test @@ -0,0 +1,31 @@ +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-19612 Split ALTER related data type specific code in sql_table.cc to Type_handler +--echo # + +SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE'; +CREATE TABLE t1 (a INT); +ALTER TABLE t1 ALGORITHM=COPY, ADD b INT NOT NULL; +DROP TABLE t1; + +SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE'; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0); +ALTER TABLE t1 ALGORITHM=COPY, ADD b INT NOT NULL; +DROP TABLE t1; + +SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE'; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0); +SET debug_dbug='+d,validate_implicit_default_value_error'; +--error ER_TRUNCATED_WRONG_VALUE +ALTER TABLE t1 ALGORITHM=COPY, ADD b INT NOT NULL; +SET debug_dbug='-d,validate_implicit_default_value_error'; +DROP TABLE t1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index fd39113a44b..2a87d8069bc 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -239,7 +239,8 @@ bool Alter_info::vers_prohibited(THD *thd) const Alter_table_ctx::Alter_table_ctx() - : datetime_field(NULL), error_if_not_empty(false), + : implicit_default_value_error_field(NULL), + error_if_not_empty(false), tables_opened(0), db(null_clex_str), table_name(null_clex_str), alias(null_clex_str), new_db(null_clex_str), new_name(null_clex_str), new_alias(null_clex_str), @@ -260,7 +261,7 @@ Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list, uint tables_opened_arg, const LEX_CSTRING *new_db_arg, const LEX_CSTRING *new_name_arg) - : datetime_field(NULL), error_if_not_empty(false), + : implicit_default_value_error_field(NULL), error_if_not_empty(false), tables_opened(tables_opened_arg), new_db(*new_db_arg), new_name(*new_name_arg), fk_error_if_delete_row(false), fk_error_id(NULL), @@ -352,6 +353,19 @@ Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list, } +void Alter_table_ctx::report_implicit_default_value_error(THD *thd, + const TABLE_SHARE *s) + const +{ + Create_field *error_field= implicit_default_value_error_field; + const Type_handler *h= error_field->type_handler(); + thd->push_warning_truncated_value_for_field(Sql_condition::WARN_LEVEL_WARN, + h->name().ptr(), + h->default_value().ptr(), + s, error_field->field_name.str); +} + + bool Sql_cmd_alter_table::execute(THD *thd) { LEX *lex= thd->lex; diff --git a/sql/sql_alter.h b/sql/sql_alter.h index a40c980b692..113df10054b 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -287,8 +287,9 @@ public: fk_error_table= fk->foreign_table->str; } + void report_implicit_default_value_error(THD *thd, const TABLE_SHARE *) const; public: - Create_field *datetime_field; + Create_field *implicit_default_value_error_field; bool error_if_not_empty; uint tables_opened; LEX_CSTRING db; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 95bc483bc39..a5c6f1336c5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -8197,15 +8197,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, If the '0000-00-00' value isn't allowed then raise the error_if_not_empty flag to allow ALTER TABLE only if the table to be altered is empty. */ - if ((def->real_field_type() == MYSQL_TYPE_DATE || - def->real_field_type() == MYSQL_TYPE_NEWDATE || - def->real_field_type() == MYSQL_TYPE_DATETIME || - def->real_field_type() == MYSQL_TYPE_DATETIME2) && - !alter_ctx->datetime_field && - !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) && - thd->variables.sql_mode & MODE_NO_ZERO_DATE) - { - alter_ctx->datetime_field= def; + if (!alter_ctx->implicit_default_value_error_field && + !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) && + def->type_handler()->validate_implicit_default_value(thd, *def)) + { + alter_ctx->implicit_default_value_error_field= def; alter_ctx->error_if_not_empty= TRUE; } if (def->flags & VERS_SYSTEM_FIELD && @@ -10392,28 +10388,8 @@ err_new_table_cleanup: if (unlikely(alter_ctx.error_if_not_empty && thd->get_stmt_da()->current_row_for_warning())) { - const char *f_val= "0000-00-00"; - const char *f_type= "date"; - switch (alter_ctx.datetime_field->real_field_type()) - { - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_NEWDATE: - break; - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_DATETIME2: - f_val= "0000-00-00 00:00:00"; - f_type= "datetime"; - break; - default: - /* Shouldn't get here. */ - DBUG_ASSERT(0); - } Abort_on_warning_instant_set aws(thd, true); - thd->push_warning_truncated_value_for_field(Sql_condition::WARN_LEVEL_WARN, - f_type, f_val, - new_table->s, - alter_ctx.datetime_field-> - field_name.str); + alter_ctx.report_implicit_default_value_error(thd, new_table->s); } if (new_table) diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 2b042cc38bd..ee5a20a08cf 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -8514,6 +8514,77 @@ Type_handler_timestamp_common::Item_param_val_native(THD *thd, } +/***************************************************************************/ + +bool Type_handler::validate_implicit_default_value(THD *thd, + const Column_definition &def) const +{ + DBUG_EXECUTE_IF("validate_implicit_default_value_error", return true;); + return false; +} + + +bool Type_handler_date_common::validate_implicit_default_value(THD *thd, + const Column_definition &def) const +{ + return thd->variables.sql_mode & MODE_NO_ZERO_DATE; +} + + +bool Type_handler_datetime_common::validate_implicit_default_value(THD *thd, + const Column_definition &def) const +{ + return thd->variables.sql_mode & MODE_NO_ZERO_DATE; +} + + +/***************************************************************************/ + +const Name & Type_handler_row::default_value() const +{ + DBUG_ASSERT(0); + static Name def(STRING_WITH_LEN("")); + return def; +} + +const Name & Type_handler_numeric::default_value() const +{ + static Name def(STRING_WITH_LEN("0")); + return def; +} + +const Name & Type_handler_string_result::default_value() const +{ + static Name def(STRING_WITH_LEN("")); + return def; +} + +const Name & Type_handler_time_common::default_value() const +{ + static Name def(STRING_WITH_LEN("00:00:00")); + return def; +} + +const Name & Type_handler_date_common::default_value() const +{ + static Name def(STRING_WITH_LEN("0000-00-00")); + return def; +} + +const Name & Type_handler_datetime_common::default_value() const +{ + static Name def(STRING_WITH_LEN("0000-00-00 00:00:00")); + return def; +} + +const Name & Type_handler_timestamp_common::default_value() const +{ + static Name def(STRING_WITH_LEN("0000-00-00 00:00:00")); + return def; +} + +/***************************************************************************/ + LEX_CSTRING Charset::collation_specific_name() const { /* diff --git a/sql/sql_type.h b/sql/sql_type.h index 06b72dd7d27..2a96e7ca654 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3207,6 +3207,7 @@ public: virtual const Name name() const= 0; virtual const Name version() const { return m_version_default; } + virtual const Name &default_value() const= 0; virtual enum_field_types field_type() const= 0; virtual enum_field_types real_field_type() const { return field_type(); } /** @@ -3395,6 +3396,10 @@ public: { return false; } + // Check if the implicit default value is Ok in the current sql_mode + virtual bool validate_implicit_default_value(THD *thd, + const Column_definition &def) + const; // Automatic upgrade, e.g. for ALTER TABLE t1 FORCE virtual void Column_definition_implicit_upgrade(Column_definition *c) const { } @@ -3758,6 +3763,13 @@ class Type_handler_row: public Type_handler public: virtual ~Type_handler_row() {} const Name name() const { return m_name_row; } + const Name &default_value() const; + bool validate_implicit_default_value(THD *thd, + const Column_definition &def) const + { + DBUG_ASSERT(0); + return true; + } bool is_scalar_type() const { return false; } bool can_return_int() const { return false; } bool can_return_decimal() const { return false; } @@ -4111,6 +4123,7 @@ protected: const Type_handler *handler) const; public: + const Name &default_value() const; String *print_item_value(THD *thd, Item *item, String *str) const; double Item_func_min_max_val_real(Item_func_min_max *) const; longlong Item_func_min_max_val_int(Item_func_min_max *) const; @@ -4612,6 +4625,7 @@ class Type_handler_string_result: public Type_handler { uint Item_temporal_precision(THD *thd, Item *item, bool is_time) const; public: + const Name &default_value() const; protocol_send_type_t protocol_send_type() const { return PROTOCOL_SEND_STRING; @@ -5244,6 +5258,7 @@ class Type_handler_time_common: public Type_handler_temporal_result public: virtual ~Type_handler_time_common() { } const Name name() const { return m_name_time; } + const Name &default_value() const; enum_field_types field_type() const { return MYSQL_TYPE_TIME; } protocol_send_type_t protocol_send_type() const { @@ -5408,6 +5423,7 @@ class Type_handler_date_common: public Type_handler_temporal_with_date public: virtual ~Type_handler_date_common() {} const Name name() const { return m_name_date; } + const Name &default_value() const; const Type_handler *type_handler_for_comparison() const; enum_field_types field_type() const { return MYSQL_TYPE_DATE; } protocol_send_type_t protocol_send_type() const @@ -5430,6 +5446,8 @@ public: CHARSET_INFO *cs, bool send_error) const; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const; + bool validate_implicit_default_value(THD *thd, + const Column_definition &def) const; bool Column_definition_fix_attributes(Column_definition *c) const; uint Item_decimal_precision(const Item *item) const; String *print_item_value(THD *thd, Item *item, String *str) const; @@ -5505,6 +5523,7 @@ class Type_handler_datetime_common: public Type_handler_temporal_with_date public: virtual ~Type_handler_datetime_common() {} const Name name() const { return m_name_datetime; } + const Name &default_value() const; const Type_handler *type_handler_for_comparison() const; enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } protocol_send_type_t protocol_send_type() const @@ -5525,6 +5544,8 @@ public: bool show_field) const; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const; + bool validate_implicit_default_value(THD *thd, + const Column_definition &def) const; void Column_definition_implicit_upgrade(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const; uint Item_decimal_scale(const Item *item) const @@ -5621,6 +5642,7 @@ protected: public: virtual ~Type_handler_timestamp_common() {} const Name name() const { return m_name_timestamp; } + const Name &default_value() const; const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_native_format() const; enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; } |