mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +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()
|
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 @@ public:
|
|||||||
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,
|
|||||||
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->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
|
||||||
def->real_field_type() == MYSQL_TYPE_DATETIME ||
|
def->type_handler()->validate_implicit_default_value(thd, *def))
|
||||||
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;
|
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 @@ err_new_table_cleanup:
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
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 @@ public:
|
|||||||
|
|
||||||
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 @@ public:
|
|||||||
{
|
{
|
||||||
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
|
|||||||
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 @@ protected:
|
|||||||
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
|
|||||||
{
|
{
|
||||||
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
|
|||||||
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
|
|||||||
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 @@ public:
|
|||||||
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
|
|||||||
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 @@ public:
|
|||||||
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 @@ protected:
|
|||||||
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; }
|
||||||
|
Reference in New Issue
Block a user