Commit 5b4c8469 authored by Monty's avatar Monty

Added CHECK_FIELD_EXPRESSION

This is needed for MDEV 13679 Enabled sequences to be used in DEFAULT

Added new option for count_cuted_fields: CHECK_FIELD_EXPRESSION
which is used to check if a DEFAULT expression is correct before
ALTER TABLE starts

Changed also all test:
  if (thd->count_cuted_fields)
  to
  if (thd->count_cuted_fields > CHECK_FIELD_EXPRESSION)
parent 139e8afc
...@@ -1518,7 +1518,7 @@ bool Field_num::get_int(CHARSET_INFO *cs, const char *from, uint len, ...@@ -1518,7 +1518,7 @@ bool Field_num::get_int(CHARSET_INFO *cs, const char *from, uint len,
goto out_of_range; goto out_of_range;
} }
} }
if (get_thd()->count_cuted_fields && if (get_thd()->count_cuted_fields > CHECK_FIELD_EXPRESSION &&
check_int(cs, from, len, end, error)) check_int(cs, from, len, end, error))
return 1; return 1;
return 0; return 0;
...@@ -1539,7 +1539,7 @@ double Field_real::get_double(const char *str, uint length, CHARSET_INFO *cs, ...@@ -1539,7 +1539,7 @@ double Field_real::get_double(const char *str, uint length, CHARSET_INFO *cs,
set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
*error= 1; *error= 1;
} }
else if (get_thd()->count_cuted_fields && else if (get_thd()->count_cuted_fields > CHECK_FIELD_EXPRESSION &&
check_edom_and_truncation("double", str == end, check_edom_and_truncation("double", str == end,
cs, str, length, end)) cs, str, length, end))
*error= 1; *error= 1;
...@@ -1874,7 +1874,7 @@ void Field::make_field(Send_field *field) ...@@ -1874,7 +1874,7 @@ void Field::make_field(Send_field *field)
if (orig_table && orig_table->s->db.str && *orig_table->s->db.str) if (orig_table && orig_table->s->db.str && *orig_table->s->db.str)
{ {
field->db_name= orig_table->s->db.str; field->db_name= orig_table->s->db.str;
if (orig_table->pos_in_table_list && if (orig_table->pos_in_table_list &&
orig_table->pos_in_table_list->schema_table) orig_table->pos_in_table_list->schema_table)
field->org_table_name= (orig_table->pos_in_table_list-> field->org_table_name= (orig_table->pos_in_table_list->
schema_table->table_name); schema_table->table_name);
...@@ -2492,7 +2492,7 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs) ...@@ -2492,7 +2492,7 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs)
it makes the code easer to read. it makes the code easer to read.
*/ */
if (get_thd()->count_cuted_fields) if (get_thd()->count_cuted_fields > CHECK_FIELD_EXPRESSION)
{ {
// Skip end spaces // Skip end spaces
for (;from != end && my_isspace(&my_charset_bin, *from); from++) ; for (;from != end && my_isspace(&my_charset_bin, *from); from++) ;
...@@ -2662,7 +2662,8 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs) ...@@ -2662,7 +2662,8 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs)
{ {
if (pos == right_wall) if (pos == right_wall)
{ {
if (get_thd()->count_cuted_fields && !is_cuted_fields_incr) if (get_thd()->count_cuted_fields > CHECK_FIELD_EXPRESSION &&
!is_cuted_fields_incr)
break; // Go on below to see if we lose non zero digits break; // Go on below to see if we lose non zero digits
return 0; return 0;
} }
...@@ -3055,7 +3056,7 @@ int Field_new_decimal::store(const char *from, uint length, ...@@ -3055,7 +3056,7 @@ int Field_new_decimal::store(const char *from, uint length,
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (thd->count_cuted_fields) if (thd->count_cuted_fields > CHECK_FIELD_EXPRESSION)
{ {
if (check_edom_and_important_data_truncation("decimal", if (check_edom_and_important_data_truncation("decimal",
err && err != E_DEC_TRUNCATED, err && err != E_DEC_TRUNCATED,
...@@ -3100,7 +3101,7 @@ int Field_new_decimal::store(const char *from, uint length, ...@@ -3100,7 +3101,7 @@ int Field_new_decimal::store(const char *from, uint length,
- in err2: store_value() truncated 1.123 to 1.12, e.g. for DECIMAL(10,2) - in err2: store_value() truncated 1.123 to 1.12, e.g. for DECIMAL(10,2)
Also, we send a note if a string had some trailing spaces: '1.12 ' Also, we send a note if a string had some trailing spaces: '1.12 '
*/ */
if (thd->count_cuted_fields && if (thd->count_cuted_fields > CHECK_FIELD_EXPRESSION &&
(err == E_DEC_TRUNCATED || (err == E_DEC_TRUNCATED ||
err2 == E_DEC_TRUNCATED || err2 == E_DEC_TRUNCATED ||
end < from + length)) end < from + length))
...@@ -4177,7 +4178,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) ...@@ -4177,7 +4178,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1; error= 1;
} }
else if (get_thd()->count_cuted_fields && else if (get_thd()->count_cuted_fields > CHECK_FIELD_EXPRESSION &&
check_int(cs, from, len, end, error)) check_int(cs, from, len, end, error))
error= 1; error= 1;
else else
...@@ -6077,7 +6078,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) ...@@ -6077,7 +6078,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1; return 1;
} }
if (get_thd()->count_cuted_fields && if (get_thd()->count_cuted_fields > CHECK_FIELD_EXPRESSION &&
(error= check_int(cs, from, len, end, error))) (error= check_int(cs, from, len, end, error)))
{ {
if (error == 1) /* empty or incorrect string */ if (error == 1) /* empty or incorrect string */
...@@ -6785,7 +6786,7 @@ Field_longstr::report_if_important_data(const char *pstr, const char *end, ...@@ -6785,7 +6786,7 @@ Field_longstr::report_if_important_data(const char *pstr, const char *end,
bool count_spaces) bool count_spaces)
{ {
THD *thd= get_thd(); THD *thd= get_thd();
if ((pstr < end) && thd->count_cuted_fields) if ((pstr < end) && thd->count_cuted_fields > CHECK_FIELD_EXPRESSION)
{ {
if (test_if_important_data(field_charset, pstr, end)) if (test_if_important_data(field_charset, pstr, end))
{ {
...@@ -8719,7 +8720,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs) ...@@ -8719,7 +8720,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
wkb_type > (uint32) Geometry::wkb_last) wkb_type > (uint32) Geometry::wkb_last)
goto err; goto err;
if (geom_type != Field::GEOM_GEOMETRY && if (geom_type != Field::GEOM_GEOMETRY &&
geom_type != Field::GEOM_GEOMETRYCOLLECTION && geom_type != Field::GEOM_GEOMETRYCOLLECTION &&
(uint32) geom_type != wkb_type) (uint32) geom_type != wkb_type)
{ {
...@@ -8859,7 +8860,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) ...@@ -8859,7 +8860,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
set_warning(WARN_DATA_TRUNCATED, 1); set_warning(WARN_DATA_TRUNCATED, 1);
err= 1; err= 1;
} }
if (!get_thd()->count_cuted_fields && !length) if ((get_thd()->count_cuted_fields <= CHECK_FIELD_EXPRESSION) && !length)
err= 0; err= 0;
} }
else else
...@@ -8886,7 +8887,7 @@ int Field_enum::store(longlong nr, bool unsigned_val) ...@@ -8886,7 +8887,7 @@ int Field_enum::store(longlong nr, bool unsigned_val)
if ((ulonglong) nr > typelib->count || nr == 0) if ((ulonglong) nr > typelib->count || nr == 0)
{ {
set_warning(WARN_DATA_TRUNCATED, 1); set_warning(WARN_DATA_TRUNCATED, 1);
if (nr != 0 || get_thd()->count_cuted_fields) if (nr != 0 || get_thd()->count_cuted_fields > CHECK_FIELD_EXPRESSION)
{ {
nr= 0; nr= 0;
error= 1; error= 1;
...@@ -10112,6 +10113,8 @@ bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name, ...@@ -10112,6 +10113,8 @@ bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
uint filter= VCOL_IMPOSSIBLE; uint filter= VCOL_IMPOSSIBLE;
if (type != VCOL_GENERATED_VIRTUAL && type != VCOL_DEFAULT) if (type != VCOL_GENERATED_VIRTUAL && type != VCOL_DEFAULT)
filter|= VCOL_NOT_STRICTLY_DETERMINISTIC; filter|= VCOL_NOT_STRICTLY_DETERMINISTIC;
if (type == VCOL_GENERATED_VIRTUAL)
filter|= VCOL_NOT_VIRTUAL;
if (ret || (res.errors & filter)) if (ret || (res.errors & filter))
{ {
...@@ -10920,11 +10923,12 @@ uint32 Field_blob::max_display_length() ...@@ -10920,11 +10923,12 @@ uint32 Field_blob::max_display_length()
@param cut_increment - whenever we should increase cut fields count @param cut_increment - whenever we should increase cut fields count
@note @note
This function won't produce warning and increase cut fields counter This function won't produce warning or notes or increase cut fields counter
if count_cuted_fields == CHECK_FIELD_IGNORE for current thread. if count_cuted_fields == CHECK_FIELD_IGNORE or CHECK_FIELD_EXPRESSION
for the current thread.
if count_cuted_fields == CHECK_FIELD_IGNORE then we ignore notes. This allows us to avoid notes in optimisation, like
This allows us to avoid notes in optimisation, like convert_constant_item(). convert_constant_item().
@retval @retval
1 if count_cuted_fields == CHECK_FIELD_IGNORE and error level is not NOTE 1 if count_cuted_fields == CHECK_FIELD_IGNORE and error level is not NOTE
...@@ -10941,7 +10945,7 @@ Field::set_warning(Sql_condition::enum_warning_level level, uint code, ...@@ -10941,7 +10945,7 @@ Field::set_warning(Sql_condition::enum_warning_level level, uint code,
will have table == NULL. will have table == NULL.
*/ */
THD *thd= get_thd(); THD *thd= get_thd();
if (thd->count_cuted_fields) if (thd->count_cuted_fields > CHECK_FIELD_EXPRESSION)
{ {
thd->cuted_fields+= cut_increment; thd->cuted_fields+= cut_increment;
push_warning_printf(thd, level, code, ER_THD(thd, code), field_name.str, push_warning_printf(thd, level, code, ER_THD(thd, code), field_name.str,
......
...@@ -50,8 +50,9 @@ class Virtual_tmp_table; ...@@ -50,8 +50,9 @@ class Virtual_tmp_table;
enum enum_check_fields enum enum_check_fields
{ {
CHECK_FIELD_IGNORE, CHECK_FIELD_IGNORE,
CHECK_FIELD_EXPRESSION,
CHECK_FIELD_WARN, CHECK_FIELD_WARN,
CHECK_FIELD_ERROR_FOR_NULL CHECK_FIELD_ERROR_FOR_NULL,
}; };
/* /*
...@@ -558,6 +559,7 @@ static inline const char *vcol_type_name(enum_vcol_info_type type) ...@@ -558,6 +559,7 @@ static inline const char *vcol_type_name(enum_vcol_info_type type)
#define VCOL_TIME_FUNC 8 #define VCOL_TIME_FUNC 8
#define VCOL_AUTO_INC 16 #define VCOL_AUTO_INC 16
#define VCOL_IMPOSSIBLE 32 #define VCOL_IMPOSSIBLE 32
#define VCOL_NOT_VIRTUAL 64 /* Function can't be virtual */
#define VCOL_NOT_STRICTLY_DETERMINISTIC \ #define VCOL_NOT_STRICTLY_DETERMINISTIC \
(VCOL_NON_DETERMINISTIC | VCOL_TIME_FUNC | VCOL_SESSION_FUNC) (VCOL_NON_DETERMINISTIC | VCOL_TIME_FUNC | VCOL_SESSION_FUNC)
......
...@@ -122,6 +122,7 @@ static int set_bad_null_error(Field *field, int err) ...@@ -122,6 +122,7 @@ static int set_bad_null_error(Field *field, int err)
field->set_warning(Sql_condition::WARN_LEVEL_WARN, err, 1); field->set_warning(Sql_condition::WARN_LEVEL_WARN, err, 1);
/* fall through */ /* fall through */
case CHECK_FIELD_IGNORE: case CHECK_FIELD_IGNORE:
case CHECK_FIELD_EXPRESSION:
return 0; return 0;
case CHECK_FIELD_ERROR_FOR_NULL: case CHECK_FIELD_ERROR_FOR_NULL:
if (!field->table->in_use->no_errors) if (!field->table->in_use->no_errors)
...@@ -528,7 +529,8 @@ static void do_varstring1(Copy_field *copy) ...@@ -528,7 +529,8 @@ static void do_varstring1(Copy_field *copy)
if (length > copy->to_length- 1) if (length > copy->to_length- 1)
{ {
length=copy->to_length - 1; length=copy->to_length - 1;
if (copy->from_field->table->in_use->count_cuted_fields && if (copy->from_field->table->in_use->count_cuted_fields >
CHECK_FIELD_EXPRESSION &&
copy->to_field) copy->to_field)
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN, copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1); WARN_DATA_TRUNCATED, 1);
...@@ -547,7 +549,7 @@ static void do_varstring1_mb(Copy_field *copy) ...@@ -547,7 +549,7 @@ static void do_varstring1_mb(Copy_field *copy)
Well_formed_prefix prefix(cs, (char*) from_ptr, from_length, to_char_length); Well_formed_prefix prefix(cs, (char*) from_ptr, from_length, to_char_length);
if (prefix.length() < from_length) if (prefix.length() < from_length)
{ {
if (current_thd->count_cuted_fields) if (current_thd->count_cuted_fields > CHECK_FIELD_EXPRESSION)
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN, copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1); WARN_DATA_TRUNCATED, 1);
} }
...@@ -562,7 +564,8 @@ static void do_varstring2(Copy_field *copy) ...@@ -562,7 +564,8 @@ static void do_varstring2(Copy_field *copy)
if (length > copy->to_length- HA_KEY_BLOB_LENGTH) if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
{ {
length=copy->to_length-HA_KEY_BLOB_LENGTH; length=copy->to_length-HA_KEY_BLOB_LENGTH;
if (copy->from_field->table->in_use->count_cuted_fields && if (copy->from_field->table->in_use->count_cuted_fields >
CHECK_FIELD_EXPRESSION &&
copy->to_field) copy->to_field)
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN, copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1); WARN_DATA_TRUNCATED, 1);
...@@ -582,7 +585,7 @@ static void do_varstring2_mb(Copy_field *copy) ...@@ -582,7 +585,7 @@ static void do_varstring2_mb(Copy_field *copy)
Well_formed_prefix prefix(cs, (char*) from_beg, from_length, char_length); Well_formed_prefix prefix(cs, (char*) from_beg, from_length, char_length);
if (prefix.length() < from_length) if (prefix.length() < from_length)
{ {
if (current_thd->count_cuted_fields) if (current_thd->count_cuted_fields > CHECK_FIELD_EXPRESSION)
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN, copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1); WARN_DATA_TRUNCATED, 1);
} }
......
...@@ -9311,10 +9311,12 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, ...@@ -9311,10 +9311,12 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name,
&altered_table->s->all_set); &altered_table->s->all_set);
restore_record(altered_table, s->default_values); // Create empty record restore_record(altered_table, s->default_values); // Create empty record
/* Check that we can call default functions with default field values */ /* Check that we can call default functions with default field values */
thd->count_cuted_fields= CHECK_FIELD_EXPRESSION;
altered_table->reset_default_fields(); altered_table->reset_default_fields();
if (altered_table->default_field && if (altered_table->default_field &&
altered_table->update_default_fields(0, 1)) altered_table->update_default_fields(0, 1))
goto err_new_table_cleanup; goto err_new_table_cleanup;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
// Ask storage engine whether to use copy or in-place // Ask storage engine whether to use copy or in-place
enum_alter_inplace_result inplace_supported= enum_alter_inplace_result inplace_supported=
......
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