mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-19612 Split ALTER related data type specific code in sql_table.cc to Type_handler
This commit is contained in:
26
mysql-test/main/alter_table_debug.result
Normal file
26
mysql-test/main/alter_table_debug.result
Normal file
@ -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
|
||||
#
|
31
mysql-test/main/alter_table_debug.test
Normal file
31
mysql-test/main/alter_table_debug.test
Normal file
@ -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 #
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 &&
|
||||
if (!alter_ctx->implicit_default_value_error_field &&
|
||||
!(~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;
|
||||
}
|
||||
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)
|
||||
|
@ -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
|
||||
{
|
||||
/*
|
||||
|
@ -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; }
|
||||
|
Reference in New Issue
Block a user