Commit cd4dd2b6 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-10201 Bad results for CREATE TABLE t1 (a INT DEFAULT b, b INT DEFAULT 4)

Optionally do table->update_default_fields() even for INSERT
that supposedly provides values for all column. Because these
"values" might be DEFAULT, which would need table->update_default_fields()
at the end.

Also set Item_default_value::used_tables() from the default expression.
Non-zero used_field() means that mysql_insert() will initialize all
fields to their default values (with restore_record()) even if
all columns are later provided with values. Because default expressions
may refer to other columns and they must be initialized.
parent 588eca31
...@@ -1553,7 +1553,7 @@ t1 CREATE TABLE `t1` ( ...@@ -1553,7 +1553,7 @@ t1 CREATE TABLE `t1` (
`s` int(11) DEFAULT NULL, `s` int(11) DEFAULT NULL,
`b` timestamp(6) NOT NULL DEFAULT sysdate(6) `b` timestamp(6) NOT NULL DEFAULT sysdate(6)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (DEFAULT, SLEEP(0.1), DEFAULT); INSERT INTO t1 VALUES (DEFAULT(a), SLEEP(0.1), DEFAULT(b));
SELECT b>a FROM t1; SELECT b>a FROM t1;
b>a b>a
1 1
...@@ -3316,7 +3316,6 @@ ERROR 42000: Invalid default value for 'c' ...@@ -3316,7 +3316,6 @@ ERROR 42000: Invalid default value for 'c'
EXECUTE stmt USING @a; EXECUTE stmt USING @a;
ERROR 42000: Invalid default value for 'c' ERROR 42000: Invalid default value for 'c'
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
# end of 10.2 test
set sql_mode=ansi_quotes; set sql_mode=ansi_quotes;
create table t1 (a int, b int default (a+1)); create table t1 (a int, b int default (a+1));
show create table t1; show create table t1;
...@@ -3349,3 +3348,18 @@ a b ...@@ -3349,3 +3348,18 @@ a b
30 31 30 31
drop table t1; drop table t1;
set sql_mode=default; set sql_mode=default;
create table t1 (a int default b, b int default 4, t text);
insert into t1 (b, t) values (5, '1 column is omitted');
insert into t1 values (default, 5, '2 column gets DEFAULT, keyword');
insert into t1 values (default(a), 5, '3 column gets DEFAULT(a), expression');
insert into t1 values (default(a)+0, 5, '4 also expression DEFAULT(0)+0');
insert into t1 values (b, 5, '5 the value of the DEFAULT(a), that is b');
select * from t1 order by t;
a b t
5 5 1 column is omitted
5 5 2 column gets DEFAULT, keyword
4 5 3 column gets DEFAULT(a), expression
4 5 4 also expression DEFAULT(0)+0
4 5 5 the value of the DEFAULT(a), that is b
drop table t1;
# end of 10.2 test
...@@ -1099,7 +1099,7 @@ SET time_zone=DEFAULT, timestamp= DEFAULT; ...@@ -1099,7 +1099,7 @@ SET time_zone=DEFAULT, timestamp= DEFAULT;
# SYSDATE is evaluated during get_date() rather than fix_fields. # SYSDATE is evaluated during get_date() rather than fix_fields.
CREATE TABLE t1 (a TIMESTAMP(6) DEFAULT SYSDATE(6), s INT, b TIMESTAMP(6) DEFAULT SYSDATE(6)); CREATE TABLE t1 (a TIMESTAMP(6) DEFAULT SYSDATE(6), s INT, b TIMESTAMP(6) DEFAULT SYSDATE(6));
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES (DEFAULT, SLEEP(0.1), DEFAULT); INSERT INTO t1 VALUES (DEFAULT(a), SLEEP(0.1), DEFAULT(b));
SELECT b>a FROM t1; SELECT b>a FROM t1;
DROP TABLE t1; DROP TABLE t1;
...@@ -2012,7 +2012,6 @@ INSERT INTO t1 VALUES (1),(2),(3); ...@@ -2012,7 +2012,6 @@ INSERT INTO t1 VALUES (1),(2),(3);
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING DEFAULT,DEFAULT; EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING DEFAULT,DEFAULT;
DROP TABLE t1; DROP TABLE t1;
--echo # --echo #
--echo # MDEV-11134 Assertion `fixed' failed in Item::const_charset_converter(THD*, CHARSET_INFO*, bool, const char*) --echo # MDEV-11134 Assertion `fixed' failed in Item::const_charset_converter(THD*, CHARSET_INFO*, bool, const char*)
--echo # --echo #
...@@ -2041,10 +2040,6 @@ EXECUTE stmt USING @a; ...@@ -2041,10 +2040,6 @@ EXECUTE stmt USING @a;
EXECUTE stmt USING @a; EXECUTE stmt USING @a;
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
--echo # end of 10.2 test
# #
# ANSI_QUOTES # ANSI_QUOTES
# #
...@@ -2062,3 +2057,16 @@ select * from t1; ...@@ -2062,3 +2057,16 @@ select * from t1;
drop table t1; drop table t1;
set sql_mode=default; set sql_mode=default;
#
# MDEV-10201 Bad results for CREATE TABLE t1 (a INT DEFAULT b, b INT DEFAULT 4)
#
create table t1 (a int default b, b int default 4, t text);
insert into t1 (b, t) values (5, '1 column is omitted');
insert into t1 values (default, 5, '2 column gets DEFAULT, keyword');
insert into t1 values (default(a), 5, '3 column gets DEFAULT(a), expression');
insert into t1 values (default(a)+0, 5, '4 also expression DEFAULT(0)+0');
insert into t1 values (b, 5, '5 the value of the DEFAULT(a), that is b');
select * from t1 order by t;
drop table t1;
--echo # end of 10.2 test
...@@ -5264,6 +5264,7 @@ int Field_timestamp::set_time() ...@@ -5264,6 +5264,7 @@ int Field_timestamp::set_time()
Mark the field as having an explicit default value. Mark the field as having an explicit default value.
@param value if available, the value that the field is being set to @param value if available, the value that the field is being set to
@returns whether the explicit default bit was set
@note @note
Fields that have an explicit default value should not be updated Fields that have an explicit default value should not be updated
...@@ -5279,13 +5280,14 @@ int Field_timestamp::set_time() ...@@ -5279,13 +5280,14 @@ int Field_timestamp::set_time()
This is how MySQL has worked since it's start. This is how MySQL has worked since it's start.
*/ */
void Field_timestamp::set_explicit_default(Item *value) bool Field_timestamp::set_explicit_default(Item *value)
{ {
if (((value->type() == Item::DEFAULT_VALUE_ITEM && if (((value->type() == Item::DEFAULT_VALUE_ITEM &&
!((Item_default_value*)value)->arg) || !((Item_default_value*)value)->arg) ||
(!maybe_null() && value->null_value))) (!maybe_null() && value->null_value)))
return; return false;
set_has_explicit_value(); set_has_explicit_value();
return true;
} }
#ifdef NOT_USED #ifdef NOT_USED
...@@ -10790,12 +10792,13 @@ key_map Field::get_possible_keys() ...@@ -10790,12 +10792,13 @@ key_map Field::get_possible_keys()
analyzed to check if it really should count as a value. analyzed to check if it really should count as a value.
*/ */
void Field::set_explicit_default(Item *value) bool Field::set_explicit_default(Item *value)
{ {
if (value->type() == Item::DEFAULT_VALUE_ITEM && if (value->type() == Item::DEFAULT_VALUE_ITEM &&
!((Item_default_value*)value)->arg) !((Item_default_value*)value)->arg)
return; return false;
set_has_explicit_value(); set_has_explicit_value();
return true;
} }
......
...@@ -954,7 +954,7 @@ class Field: public Value_source ...@@ -954,7 +954,7 @@ class Field: public Value_source
{ {
return bitmap_is_set(&table->has_value_set, field_index); return bitmap_is_set(&table->has_value_set, field_index);
} }
virtual void set_explicit_default(Item *value); virtual bool set_explicit_default(Item *value);
/** /**
Evaluates the @c UPDATE default function, if one exists, and stores the Evaluates the @c UPDATE default function, if one exists, and stores the
...@@ -2379,9 +2379,9 @@ class Field_timestamp :public Field_temporal { ...@@ -2379,9 +2379,9 @@ class Field_timestamp :public Field_temporal {
uint32 pack_length() const { return 4; } uint32 pack_length() const { return 4; }
void sql_type(String &str) const; void sql_type(String &str) const;
bool zero_pack() const { return 0; } bool zero_pack() const { return 0; }
virtual int set_time(); int set_time();
virtual void set_explicit_default(Item *value); bool set_explicit_default(Item *value);
virtual int evaluate_update_default_function() int evaluate_update_default_function()
{ {
int res= 0; int res= 0;
if (has_update_default_function()) if (has_update_default_function())
...@@ -2813,8 +2813,8 @@ class Field_datetime :public Field_temporal_with_date { ...@@ -2813,8 +2813,8 @@ class Field_datetime :public Field_temporal_with_date {
void sql_type(String &str) const; void sql_type(String &str) const;
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return Field_datetime::get_TIME(ltime, ptr, fuzzydate); } { return Field_datetime::get_TIME(ltime, ptr, fuzzydate); }
virtual int set_time(); int set_time();
virtual int evaluate_update_default_function() int evaluate_update_default_function()
{ {
int res= 0; int res= 0;
if (has_update_default_function()) if (has_update_default_function())
......
...@@ -8834,15 +8834,23 @@ bool Item_default_value::send(Protocol *protocol, String *buffer) ...@@ -8834,15 +8834,23 @@ bool Item_default_value::send(Protocol *protocol, String *buffer)
int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
{ {
if (arg) if (arg)
calculate();
else
{ {
return field_arg->save_in_field_default_value(context->error_processor == calculate();
&view_error_processor); return Item_field::save_in_field(field_arg, no_conversions);
} }
return Item_field::save_in_field(field_arg, no_conversions);
if (field_arg->default_value && field_arg->default_value->flags)
return 0; // defaut fields will be set later, no need to do it twice
return field_arg->save_in_field_default_value(context->error_processor ==
&view_error_processor);
} }
table_map Item_default_value::used_tables() const
{
if (field && field->default_value && field->default_value->flags)
return field->default_value->expr->used_tables();
return static_cast<table_map>(0);
}
/** /**
This method like the walk method traverses the item tree, but at the This method like the walk method traverses the item tree, but at the
......
...@@ -5185,7 +5185,7 @@ class Item_default_value : public Item_field ...@@ -5185,7 +5185,7 @@ class Item_default_value : public Item_field
param->set_default(); param->set_default();
return false; return false;
} }
table_map used_tables() const { return (table_map)0L; } table_map used_tables() const;
Field *get_tmp_table_field() { return 0; } Field *get_tmp_table_field() { return 0; }
Item *get_tmp_table_item(THD *thd) { return this; } Item *get_tmp_table_item(THD *thd) { return this; }
Item_field *field_for_view_update() { return 0; } Item_field *field_for_view_update() { return 0; }
......
...@@ -8102,6 +8102,7 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values, ...@@ -8102,6 +8102,7 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
{ {
List_iterator_fast<Item> v(values); List_iterator_fast<Item> v(values);
List<TABLE> tbl_list; List<TABLE> tbl_list;
bool all_fields_have_values= true;
Item *value; Item *value;
Field *field; Field *field;
bool abort_on_warning_saved= thd->abort_on_warning; bool abort_on_warning_saved= thd->abort_on_warning;
...@@ -8154,9 +8155,11 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values, ...@@ -8154,9 +8155,11 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
else else
if (value->save_in_field(field, 0) < 0) if (value->save_in_field(field, 0) < 0)
goto err; goto err;
field->set_explicit_default(value); all_fields_have_values &= field->set_explicit_default(value);
} }
/* There is no default fields to update, as all fields are updated */ if (!all_fields_have_values && table->default_field &&
table->update_default_fields(0, ignore_errors))
goto err;
/* Update virtual fields */ /* Update virtual fields */
thd->abort_on_warning= FALSE; thd->abort_on_warning= FALSE;
if (table->vfield && if (table->vfield &&
......
...@@ -991,6 +991,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -991,6 +991,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
share->default_values[share->null_bytes - 1]; share->default_values[share->null_bytes - 1];
} }
} }
table->reset_default_fields();
if (fill_record_n_invoke_before_triggers(thd, table, if (fill_record_n_invoke_before_triggers(thd, table,
table->field_to_fill(), table->field_to_fill(),
*values, 0, TRG_EVENT_INSERT)) *values, 0, TRG_EVENT_INSERT))
......
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