Commit f021317a authored by Alexander Barkov's avatar Alexander Barkov

MDEV-19612 Split ALTER related data type specific code in sql_table.cc to Type_handler

parent d1d6fe9a
#
# 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
#
--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 #
...@@ -239,7 +239,8 @@ bool Alter_info::vers_prohibited(THD *thd) const ...@@ -239,7 +239,8 @@ bool Alter_info::vers_prohibited(THD *thd) const
Alter_table_ctx::Alter_table_ctx() 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), tables_opened(0),
db(null_clex_str), table_name(null_clex_str), alias(null_clex_str), 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), 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, ...@@ -260,7 +261,7 @@ Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list,
uint tables_opened_arg, uint tables_opened_arg,
const LEX_CSTRING *new_db_arg, const LEX_CSTRING *new_db_arg,
const LEX_CSTRING *new_name_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), tables_opened(tables_opened_arg),
new_db(*new_db_arg), new_name(*new_name_arg), new_db(*new_db_arg), new_name(*new_name_arg),
fk_error_if_delete_row(false), fk_error_id(NULL), 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, ...@@ -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) bool Sql_cmd_alter_table::execute(THD *thd)
{ {
LEX *lex= thd->lex; LEX *lex= thd->lex;
......
...@@ -287,8 +287,9 @@ class Alter_table_ctx ...@@ -287,8 +287,9 @@ class Alter_table_ctx
fk_error_table= fk->foreign_table->str; fk_error_table= fk->foreign_table->str;
} }
void report_implicit_default_value_error(THD *thd, const TABLE_SHARE *) const;
public: public:
Create_field *datetime_field; Create_field *implicit_default_value_error_field;
bool error_if_not_empty; bool error_if_not_empty;
uint tables_opened; uint tables_opened;
LEX_CSTRING db; LEX_CSTRING db;
......
...@@ -8197,15 +8197,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -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 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. flag to allow ALTER TABLE only if the table to be altered is empty.
*/ */
if ((def->real_field_type() == MYSQL_TYPE_DATE || if (!alter_ctx->implicit_default_value_error_field &&
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)) && !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
thd->variables.sql_mode & MODE_NO_ZERO_DATE) def->type_handler()->validate_implicit_default_value(thd, *def))
{ {
alter_ctx->datetime_field= def; alter_ctx->implicit_default_value_error_field= def;
alter_ctx->error_if_not_empty= TRUE; alter_ctx->error_if_not_empty= TRUE;
} }
if (def->flags & VERS_SYSTEM_FIELD && if (def->flags & VERS_SYSTEM_FIELD &&
...@@ -10392,28 +10388,8 @@ do_continue:; ...@@ -10392,28 +10388,8 @@ do_continue:;
if (unlikely(alter_ctx.error_if_not_empty && if (unlikely(alter_ctx.error_if_not_empty &&
thd->get_stmt_da()->current_row_for_warning())) 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); Abort_on_warning_instant_set aws(thd, true);
thd->push_warning_truncated_value_for_field(Sql_condition::WARN_LEVEL_WARN, alter_ctx.report_implicit_default_value_error(thd, new_table->s);
f_type, f_val,
new_table->s,
alter_ctx.datetime_field->
field_name.str);
} }
if (new_table) if (new_table)
......
...@@ -8514,6 +8514,77 @@ Type_handler_timestamp_common::Item_param_val_native(THD *thd, ...@@ -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 LEX_CSTRING Charset::collation_specific_name() const
{ {
/* /*
......
...@@ -3207,6 +3207,7 @@ class Type_handler ...@@ -3207,6 +3207,7 @@ class Type_handler
virtual const Name name() const= 0; virtual const Name name() const= 0;
virtual const Name version() const { return m_version_default; } 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 field_type() const= 0;
virtual enum_field_types real_field_type() const { return field_type(); } virtual enum_field_types real_field_type() const { return field_type(); }
/** /**
...@@ -3395,6 +3396,10 @@ class Type_handler ...@@ -3395,6 +3396,10 @@ class Type_handler
{ {
return false; 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 // Automatic upgrade, e.g. for ALTER TABLE t1 FORCE
virtual void Column_definition_implicit_upgrade(Column_definition *c) const virtual void Column_definition_implicit_upgrade(Column_definition *c) const
{ } { }
...@@ -3758,6 +3763,13 @@ class Type_handler_row: public Type_handler ...@@ -3758,6 +3763,13 @@ class Type_handler_row: public Type_handler
public: public:
virtual ~Type_handler_row() {} virtual ~Type_handler_row() {}
const Name name() const { return m_name_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 is_scalar_type() const { return false; }
bool can_return_int() const { return false; } bool can_return_int() const { return false; }
bool can_return_decimal() const { return false; } bool can_return_decimal() const { return false; }
...@@ -4111,6 +4123,7 @@ class Type_handler_numeric: public Type_handler ...@@ -4111,6 +4123,7 @@ class Type_handler_numeric: public Type_handler
const Type_handler *handler) const Type_handler *handler)
const; const;
public: public:
const Name &default_value() const;
String *print_item_value(THD *thd, Item *item, String *str) const; String *print_item_value(THD *thd, Item *item, String *str) const;
double Item_func_min_max_val_real(Item_func_min_max *) 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; longlong Item_func_min_max_val_int(Item_func_min_max *) const;
...@@ -4612,6 +4625,7 @@ class Type_handler_string_result: public Type_handler ...@@ -4612,6 +4625,7 @@ class Type_handler_string_result: public Type_handler
{ {
uint Item_temporal_precision(THD *thd, Item *item, bool is_time) const; uint Item_temporal_precision(THD *thd, Item *item, bool is_time) const;
public: public:
const Name &default_value() const;
protocol_send_type_t protocol_send_type() const protocol_send_type_t protocol_send_type() const
{ {
return PROTOCOL_SEND_STRING; return PROTOCOL_SEND_STRING;
...@@ -5244,6 +5258,7 @@ class Type_handler_time_common: public Type_handler_temporal_result ...@@ -5244,6 +5258,7 @@ class Type_handler_time_common: public Type_handler_temporal_result
public: public:
virtual ~Type_handler_time_common() { } virtual ~Type_handler_time_common() { }
const Name name() const { return m_name_time; } const Name name() const { return m_name_time; }
const Name &default_value() const;
enum_field_types field_type() const { return MYSQL_TYPE_TIME; } enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
protocol_send_type_t protocol_send_type() const protocol_send_type_t protocol_send_type() const
{ {
...@@ -5408,6 +5423,7 @@ class Type_handler_date_common: public Type_handler_temporal_with_date ...@@ -5408,6 +5423,7 @@ class Type_handler_date_common: public Type_handler_temporal_with_date
public: public:
virtual ~Type_handler_date_common() {} virtual ~Type_handler_date_common() {}
const Name name() const { return m_name_date; } const Name name() const { return m_name_date; }
const Name &default_value() const;
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
enum_field_types field_type() const { return MYSQL_TYPE_DATE; } enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
protocol_send_type_t protocol_send_type() const protocol_send_type_t protocol_send_type() const
...@@ -5430,6 +5446,8 @@ class Type_handler_date_common: public Type_handler_temporal_with_date ...@@ -5430,6 +5446,8 @@ class Type_handler_date_common: public Type_handler_temporal_with_date
CHARSET_INFO *cs, bool send_error) const; CHARSET_INFO *cs, bool send_error) const;
Item *create_typecast_item(THD *thd, Item *item, Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const; 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; bool Column_definition_fix_attributes(Column_definition *c) const;
uint Item_decimal_precision(const Item *item) const; uint Item_decimal_precision(const Item *item) const;
String *print_item_value(THD *thd, Item *item, String *str) 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 ...@@ -5505,6 +5523,7 @@ class Type_handler_datetime_common: public Type_handler_temporal_with_date
public: public:
virtual ~Type_handler_datetime_common() {} virtual ~Type_handler_datetime_common() {}
const Name name() const { return m_name_datetime; } const Name name() const { return m_name_datetime; }
const Name &default_value() const;
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
protocol_send_type_t protocol_send_type() const protocol_send_type_t protocol_send_type() const
...@@ -5525,6 +5544,8 @@ class Type_handler_datetime_common: public Type_handler_temporal_with_date ...@@ -5525,6 +5544,8 @@ class Type_handler_datetime_common: public Type_handler_temporal_with_date
bool show_field) const; bool show_field) const;
Item *create_typecast_item(THD *thd, Item *item, Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const; 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; void Column_definition_implicit_upgrade(Column_definition *c) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
uint Item_decimal_scale(const Item *item) const uint Item_decimal_scale(const Item *item) const
...@@ -5621,6 +5642,7 @@ class Type_handler_timestamp_common: public Type_handler_temporal_with_date ...@@ -5621,6 +5642,7 @@ class Type_handler_timestamp_common: public Type_handler_temporal_with_date
public: public:
virtual ~Type_handler_timestamp_common() {} virtual ~Type_handler_timestamp_common() {}
const Name name() const { return m_name_timestamp; } 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_comparison() const;
const Type_handler *type_handler_for_native_format() const; const Type_handler *type_handler_for_native_format() const;
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; } enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment