Skip to content

Commit

Permalink
function DEFAULT(x) now works for expression defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
vuvova committed Jun 30, 2016
1 parent 3205da7 commit e8bdb73
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 12 deletions.
11 changes: 7 additions & 4 deletions mysql-test/r/default.result
Original file line number Diff line number Diff line change
Expand Up @@ -413,11 +413,11 @@ ERROR 01000: Expression for field `a` is refering to uninitialized field `b`
create or replace table t1 (a int default 1, b int as (c), c int as (a+1));
ERROR 01000: Expression for field `b` is refering to uninitialized field `c`
CREATE TABLE t1 (a INT DEFAULT (DEFAULT(a)));
ERROR HY000: Field 'a' doesn't have a default value
ERROR 01000: Expression for field `a` is refering to uninitialized field `a`
CREATE TABLE t1 (a INT DEFAULT(DEFAULT(b)), b INT DEFAULT(DEFAULT(a)));
ERROR HY000: Field 'b' doesn't have a default value
ERROR 01000: Expression for field `a` is refering to uninitialized field `b`
CREATE TABLE t1 (a INT DEFAULT(DEFAULT(b)) NOT NULL, b INT DEFAULT(DEFAULT(a)) NOT NULL);
ERROR HY000: Field 'b' doesn't have a default value
ERROR 01000: Expression for field `a` is refering to uninitialized field `b`
#
# Allow defaults to refer to not default fields
#
Expand Down Expand Up @@ -1193,7 +1193,10 @@ a b
2 2
6 1000
select default(a),b from t1;
ERROR HY000: Field 'a' doesn't have a default value
default(a) b
6 1
6 2
6 1000
select a,default(b) from t1;
a default(b)
1 1000
Expand Down
11 changes: 11 additions & 0 deletions mysql-test/r/func_default.result
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,14 @@ INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL;
ERROR HY000: Field 'mi' doesn't have a default value
DROP TABLE t1;
set timestamp=unix_timestamp('2001-01-01 10:20:30.123456');
create table t1 (a int default 1, b int default (a+1),
c varchar(100) default 'foo', d text default 'bar',
e timestamp default now(), f timestamp(6) default now(2));
insert t1 () values ();
insert t1 (a) values (10);
select default(a),default(b),default(c),default(d),default(e),default(f) from t1;
default(a) default(b) default(c) default(d) default(e) default(f)
1 2 foo bar 2001-01-01 10:20:30 2001-01-01 10:20:30.123456
1 11 foo bar 2001-01-01 10:20:30 2001-01-01 10:20:30.123456
drop table t1;
7 changes: 3 additions & 4 deletions mysql-test/t/default.test
Original file line number Diff line number Diff line change
Expand Up @@ -299,11 +299,11 @@ create or replace table t1 (a int default a);
create or replace table t1 (a int default b, b int default (1+1));
--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
create or replace table t1 (a int default 1, b int as (c), c int as (a+1));
--error ER_NO_DEFAULT_FOR_FIELD
--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
CREATE TABLE t1 (a INT DEFAULT (DEFAULT(a)));
--error ER_NO_DEFAULT_FOR_FIELD
--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
CREATE TABLE t1 (a INT DEFAULT(DEFAULT(b)), b INT DEFAULT(DEFAULT(a)));
--error ER_NO_DEFAULT_FOR_FIELD
--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
CREATE TABLE t1 (a INT DEFAULT(DEFAULT(b)) NOT NULL, b INT DEFAULT(DEFAULT(a)) NOT NULL);

--echo #
Expand Down Expand Up @@ -879,7 +879,6 @@ SHOW CREATE TABLE t1;
insert into t1 values (1,1),(2,2);
insert into t1 values (default,default);
select * from t1;
--error ER_NO_DEFAULT_FOR_FIELD
select default(a),b from t1;
select a,default(b) from t1;
drop table t1;
Expand Down
12 changes: 12 additions & 0 deletions mysql-test/t/func_default.test
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,15 @@ INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL;
DROP TABLE t1;

#
# 10.2 tests
#

set timestamp=unix_timestamp('2001-01-01 10:20:30.123456');
create table t1 (a int default 1, b int default (a+1),
c varchar(100) default 'foo', d text default 'bar',
e timestamp default now(), f timestamp(6) default now(2));
insert t1 () values ();
insert t1 (a) values (10);
select default(a),default(b),default(c),default(d),default(e),default(f) from t1;
drop table t1;
54 changes: 51 additions & 3 deletions sql/item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8211,8 +8211,7 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
}

field_arg= (Item_field *)real_arg;
if ((field_arg->field->flags & NO_DEFAULT_VALUE_FLAG) ||
field_arg->field->default_value)
if ((field_arg->field->flags & NO_DEFAULT_VALUE_FLAG))
{
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name);
goto error;
Expand All @@ -8225,6 +8224,12 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
(def_field->table->s->default_values -
def_field->table->record[0]));
set_field(def_field);
if (field->default_value)
{
if (field->default_value->expr_item) // it's NULL during CREATE TABLE
field->default_value->expr_item->walk(&Item::register_field_in_read_map, 1, 0);
IF_DBUG(def_field->is_stat_field=1,); // a hack to fool ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED
}
return FALSE;

error:
Expand All @@ -8245,10 +8250,53 @@ void Item_default_value::print(String *str, enum_query_type query_type)
str->append(')');
}

void Item_default_value::calculate()
{
if (field->default_value || field->has_insert_default_function())
field->set_default();
}

String *Item_default_value::val_str(String *str)
{
calculate();
return Item_field::val_str(str);
}

double Item_default_value::val_real()
{
calculate();
return Item_field::val_real();
}

longlong Item_default_value::val_int()
{
calculate();
return Item_field::val_int();
}

my_decimal *Item_default_value::val_decimal(my_decimal *decimal_value)
{
calculate();
return Item_field::val_decimal(decimal_value);
}

bool Item_default_value::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
{
calculate();
return Item_field::get_date(ltime, fuzzydate);
}

bool Item_default_value::send(Protocol *protocol, String *buffer)
{
calculate();
return Item_field::send(protocol, buffer);
}

int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
{
if (!arg)
if (arg)
calculate();
else
{
TABLE *table= field_arg->table;
THD *thd= table->in_use;
Expand Down
9 changes: 8 additions & 1 deletion sql/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -4877,6 +4877,7 @@ class Cached_item_field :public Cached_item

class Item_default_value : public Item_field
{
void calculate();
public:
Item *arg;
Item_default_value(THD *thd, Name_resolution_context *context_arg)
Expand All @@ -4890,7 +4891,13 @@ class Item_default_value : public Item_field
enum Type type() const { return DEFAULT_VALUE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
bool fix_fields(THD *, Item **);
virtual void print(String *str, enum_query_type query_type);
void print(String *str, enum_query_type query_type);
String *val_str(String *str);
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate);
bool send(Protocol *protocol, String *buffer);
int save_in_field(Field *field_arg, bool no_conversions);
table_map used_tables() const { return (table_map)0L; }

Expand Down

0 comments on commit e8bdb73

Please sign in to comment.