Skip to content

Commit

Permalink
planner: fixup some bugs with DEFAULT expression (#13168)(#13211)(#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Deardrops authored and sre-bot committed Dec 11, 2019
1 parent 969a020 commit cba3e1a
Show file tree
Hide file tree
Showing 7 changed files with 386 additions and 57 deletions.
62 changes: 62 additions & 0 deletions ddl/db_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1894,6 +1894,68 @@ func (s *testIntegrationSuite4) TestDropAutoIncrementIndex(c *C) {
assertErrorCode(c, tk, dropIndexSQL, mysql.ErrWrongAutoKey)
}

func (s *testIntegrationSuite3) TestInsertIntoGeneratedColumnWithDefaultExpr(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("create database if not exists test")
tk.MustExec("use test")

// insert into virtual / stored columns
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (a int, b int as (-a) virtual, c int as (-a) stored)")
tk.MustExec("insert into t1 values (1, default, default)")
tk.MustQuery("select * from t1").Check(testkit.Rows("1 -1 -1"))
tk.MustExec("delete from t1")

// insert multiple rows
tk.MustExec("insert into t1(a,b) values (1, default), (2, default)")
tk.MustQuery("select * from t1").Check(testkit.Rows("1 -1 -1", "2 -2 -2"))
tk.MustExec("delete from t1")

// insert into generated columns only
tk.MustExec("insert into t1(b) values (default)")
tk.MustQuery("select * from t1").Check(testkit.Rows("<nil> <nil> <nil>"))
tk.MustExec("delete from t1")
tk.MustExec("insert into t1(c) values (default)")
tk.MustQuery("select * from t1").Check(testkit.Rows("<nil> <nil> <nil>"))
tk.MustExec("delete from t1")

// generated columns with index
tk.MustExec("drop table if exists t2")
tk.MustExec("create table t2 like t1")
tk.MustExec("alter table t2 add index idx1(a)")
tk.MustExec("alter table t2 add index idx2(b)")
tk.MustExec("insert into t2 values (1, default, default)")
tk.MustQuery("select * from t2").Check(testkit.Rows("1 -1 -1"))
tk.MustExec("delete from t2")
tk.MustExec("alter table t2 drop index idx1")
tk.MustExec("alter table t2 drop index idx2")
tk.MustExec("insert into t2 values (1, default, default)")
tk.MustQuery("select * from t2").Check(testkit.Rows("1 -1 -1"))

// generated columns in different position
tk.MustExec("drop table if exists t3")
tk.MustExec("create table t3 (gc1 int as (r+1), gc2 int as (r+1) stored, gc3 int as (gc2+1), gc4 int as (gc1+1) stored, r int)")
tk.MustExec("insert into t3 values (default, default, default, default, 1)")
tk.MustQuery("select * from t3").Check(testkit.Rows("2 2 3 3 1"))

// generated columns in replace statement
tk.MustExec("create table t4 (a int key, b int, c int as (a+1), d int as (b+1) stored)")
tk.MustExec("insert into t4 values (1, 10, default, default)")
tk.MustQuery("select * from t4").Check(testkit.Rows("1 10 2 11"))
tk.MustExec("replace into t4 values (1, 20, default, default)")
tk.MustQuery("select * from t4").Check(testkit.Rows("1 20 2 21"))

// generated columns with default function is not allowed
tk.MustExec("create table t5 (a int default 10, b int as (a+1))")
assertErrorCode(c, tk, "insert into t5 values (20, default(a))", mysql.ErrBadGeneratedColumn)

tk.MustExec("drop table t1")
tk.MustExec("drop table t2")
tk.MustExec("drop table t3")
tk.MustExec("drop table t4")
tk.MustExec("drop table t5")
}

func (s *testIntegrationSuite3) TestParserIssue284(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
Expand Down
64 changes: 64 additions & 0 deletions ddl/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3048,6 +3048,70 @@ func (s *testDBSuite5) TestModifyGeneratedColumn(c *C) {
tk.MustQuery("select * from t1").Check(testkit.Rows("1 2"))
}

func (s *testDBSuite5) TestDefaultSQLFunction(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("create database if not exists test;")
tk.MustExec("use test;")
tk.MustExec("drop table if exists t1, t2, t3, t4;")

// For issue #13189
// Use `DEFAULT()` in `INSERT` / `INSERT ON DUPLICATE KEY UPDATE` statement
tk.MustExec("create table t1(a int primary key, b int default 20, c int default 30, d int default 40);")
tk.MustExec("insert into t1 set a = 1, b = default(c);")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 30 30 40"))
tk.MustExec("insert into t1 set a = 2, b = default(c), c = default(d), d = default(b);")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 30 30 40", "2 30 40 20"))
tk.MustExec("insert into t1 values (2, 3, 4, 5) on duplicate key update b = default(d), c = default(b);")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 30 30 40", "2 40 20 20"))
tk.MustExec("delete from t1")
tk.MustExec("insert into t1 set a = default(b) + default(c) - default(d)")
tk.MustQuery("select * from t1;").Check(testkit.Rows("10 20 30 40"))
// Use `DEFAULT()` in `UPDATE` statement
tk.MustExec("delete from t1;")
tk.MustExec("insert into t1 value (1, 2, 3, 4);")
tk.MustExec("update t1 set a = 1, c = default(b);")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 2 20 4"))
tk.MustExec("insert into t1 value (2, 2, 3, 4);")
tk.MustExec("update t1 set c = default(b), b = default(c) where a = 2;")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 2 20 4", "2 30 20 4"))
tk.MustExec("delete from t1")
tk.MustExec("insert into t1 set a = 10")
tk.MustExec("update t1 set a = 10, b = default(c) + default(d)")
tk.MustQuery("select * from t1;").Check(testkit.Rows("10 70 30 40"))
// Use `DEFAULT()` in `REPLACE` statement
tk.MustExec("delete from t1;")
tk.MustExec("insert into t1 value (1, 2, 3, 4);")
tk.MustExec("replace into t1 set a = 1, c = default(b);")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 20 20 40"))
tk.MustExec("insert into t1 value (2, 2, 3, 4);")
tk.MustExec("replace into t1 set a = 2, d = default(b), c = default(d);")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 20 20 40", "2 20 40 20"))
tk.MustExec("delete from t1")
tk.MustExec("insert into t1 set a = 10, c = 3")
tk.MustExec("replace into t1 set a = 10, b = default(c) + default(d)")
tk.MustQuery("select * from t1;").Check(testkit.Rows("10 70 30 40"))
tk.MustExec("replace into t1 set a = 20, d = default(c) + default(b)")
tk.MustQuery("select * from t1;").Check(testkit.Rows("10 70 30 40", "20 20 30 50"))

// Use `DEFAULT()` in expression of generate columns, issue #12471
tk.MustExec("create table t2(a int default 9, b int as (1 + default(a)));")
tk.MustExec("insert into t2 values(1, default);")
tk.MustQuery("select * from t2;").Check(testkit.Rows("1 10"))

// Use `DEFAULT()` with subquery, issue #13390
tk.MustExec("create table t3(f1 int default 11);")
tk.MustExec("insert into t3 value ();")
tk.MustQuery("select default(f1) from (select * from t3) t1;").Check(testkit.Rows("11"))
tk.MustQuery("select default(f1) from (select * from (select * from t3) t1 ) t1;").Check(testkit.Rows("11"))

tk.MustExec("create table t4(a int default 4);")
tk.MustExec("insert into t4 value (2);")
tk.MustQuery("select default(c) from (select b as c from (select a as b from t4) t3) t2;").Check(testkit.Rows("4"))
tk.MustGetErrCode("select default(a) from (select a from (select 1 as a) t4) t4;", mysql.ErrNoDefaultForField)

tk.MustExec("drop table t1, t2, t3, t4;")
}

func (s *testDBSuite4) TestIssue9100(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test_db")
Expand Down
10 changes: 3 additions & 7 deletions executor/insert_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,6 @@ func (e *InsertValues) initInsertColumns() error {
for _, v := range e.SetList {
columns = append(columns, v.Col.ColName.O)
}
for _, v := range e.GenColumns {
columns = append(columns, v.Name.O)
}
cols, err = table.FindCols(tableCols, columns, e.Table.Meta().PKIsHandle)
if err != nil {
return errors.Errorf("INSERT INTO %s: %s", e.Table.Meta().Name.O, err)
Expand All @@ -107,9 +104,6 @@ func (e *InsertValues) initInsertColumns() error {
for _, v := range e.Columns {
columns = append(columns, v.Name.O)
}
for _, v := range e.GenColumns {
columns = append(columns, v.Name.O)
}
cols, err = table.FindCols(tableCols, columns, e.Table.Meta().PKIsHandle)
if err != nil {
return errors.Errorf("INSERT INTO %s: %s", e.Table.Meta().Name.O, err)
Expand All @@ -119,6 +113,9 @@ func (e *InsertValues) initInsertColumns() error {
cols = tableCols
}
for _, col := range cols {
if !col.IsGenerated() {
e.insertColumns = append(e.insertColumns, col)
}
if col.Name.L == model.ExtraHandleName.L {
if !e.ctx.GetSessionVars().AllowWriteRowID {
return errors.Errorf("insert, update and replace statements for _tidb_rowid are not supported.")
Expand All @@ -133,7 +130,6 @@ func (e *InsertValues) initInsertColumns() error {
if err != nil {
return err
}
e.insertColumns = cols
return nil
}

Expand Down
146 changes: 146 additions & 0 deletions executor/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,88 @@ func (s *testSuite4) TestInsertIgnoreOnDup(c *C) {
r.Check(testkit.Rows("1 1", "2 2"))
}

func (s *testSuite4) TestInsertSetWithDefault(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
// Assign `DEFAULT` in `INSERT ... SET ...` statement
tk.MustExec("drop table if exists t1, t2;")
tk.MustExec("create table t1 (a int default 10, b int default 20);")
tk.MustExec("insert into t1 set a=default;")
tk.MustQuery("select * from t1;").Check(testkit.Rows("10 20"))
tk.MustExec("delete from t1;")
tk.MustExec("insert into t1 set b=default;")
tk.MustQuery("select * from t1;").Check(testkit.Rows("10 20"))
tk.MustExec("delete from t1;")
tk.MustExec("insert into t1 set b=default, a=1;")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 20"))
tk.MustExec("delete from t1;")
tk.MustExec("insert into t1 set a=default(a);")
tk.MustQuery("select * from t1;").Check(testkit.Rows("10 20"))
tk.MustExec("delete from t1;")
tk.MustExec("insert into t1 set a=default(b), b=default(a)")
tk.MustQuery("select * from t1;").Check(testkit.Rows("20 10"))
tk.MustExec("delete from t1;")
tk.MustExec("insert into t1 set a=default(b)+default(a);")
tk.MustQuery("select * from t1;").Check(testkit.Rows("30 20"))
// With generated columns
tk.MustExec("create table t2 (a int default 10, b int generated always as (-a) virtual, c int generated always as (-a) stored);")
tk.MustExec("insert into t2 set a=default;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("10 -10 -10"))
tk.MustExec("delete from t2;")
tk.MustExec("insert into t2 set a=2, b=default;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("2 -2 -2"))
tk.MustExec("delete from t2;")
tk.MustExec("insert into t2 set c=default, a=3;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("3 -3 -3"))
tk.MustExec("delete from t2;")
tk.MustExec("insert into t2 set a=default, b=default, c=default;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("10 -10 -10"))
tk.MustExec("delete from t2;")
tk.MustExec("insert into t2 set a=default(a), b=default, c=default;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("10 -10 -10"))
tk.MustExec("delete from t2;")
tk.MustGetErrCode("insert into t2 set b=default(a);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("insert into t2 set a=default(b), b=default(b);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("insert into t2 set a=default(a), c=default(c);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("insert into t2 set a=default(a), c=default(a);", mysql.ErrBadGeneratedColumn)
tk.MustExec("drop table t1, t2")
}

func (s *testSuite4) TestInsertOnDupUpdateDefault(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
// Assign `DEFAULT` in `INSERT ... ON DUPLICATE KEY UPDATE ...` statement
tk.MustExec("drop table if exists t1, t2;")
tk.MustExec("create table t1 (a int unique, b int default 20, c int default 30);")
tk.MustExec("insert into t1 values (1,default,default);")
tk.MustExec("insert into t1 values (1,default,default) on duplicate key update b=default;")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 20 30"))
tk.MustExec("insert into t1 values (1,default,default) on duplicate key update c=default, b=default;")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 20 30"))
tk.MustExec("insert into t1 values (1,default,default) on duplicate key update c=default, a=2")
tk.MustQuery("select * from t1;").Check(testkit.Rows("2 20 30"))
tk.MustExec("insert into t1 values (2,default,default) on duplicate key update c=default(b)")
tk.MustQuery("select * from t1;").Check(testkit.Rows("2 20 20"))
tk.MustExec("insert into t1 values (2,default,default) on duplicate key update a=default(b)+default(c)")
tk.MustQuery("select * from t1;").Check(testkit.Rows("50 20 20"))
// With generated columns
tk.MustExec("create table t2 (a int unique, b int generated always as (-a) virtual, c int generated always as (-a) stored);")
tk.MustExec("insert into t2 values (1,default,default);")
tk.MustExec("insert into t2 values (1,default,default) on duplicate key update a=2, b=default;")
tk.MustQuery("select * from t2").Check(testkit.Rows("2 -2 -2"))
tk.MustExec("insert into t2 values (2,default,default) on duplicate key update a=3, c=default;")
tk.MustQuery("select * from t2").Check(testkit.Rows("3 -3 -3"))
tk.MustExec("insert into t2 values (3,default,default) on duplicate key update c=default, b=default, a=4;")
tk.MustQuery("select * from t2").Check(testkit.Rows("4 -4 -4"))
tk.MustExec("insert into t2 values (10,default,default) on duplicate key update b=default, a=20, c=default;")
tk.MustQuery("select * from t2").Check(testkit.Rows("4 -4 -4", "10 -10 -10"))
tk.MustGetErrCode("insert into t2 values (4,default,default) on duplicate key update b=default(a);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("insert into t2 values (4,default,default) on duplicate key update a=default(b), b=default(b);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("insert into t2 values (4,default,default) on duplicate key update a=default(a), c=default(c);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("insert into t2 values (4,default,default) on duplicate key update a=default(a), c=default(a);", mysql.ErrBadGeneratedColumn)
tk.MustExec("drop table t1, t2")
}

func (s *testSuite4) TestReplace(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
Expand Down Expand Up @@ -896,6 +978,36 @@ func (s *testSuite4) TestReplace(c *C) {
tk.MustExec(`replace into t1 select * from (select 1, 2) as tmp;`)
c.Assert(int64(tk.Se.AffectedRows()), Equals, int64(2))
tk.CheckLastMessage("Records: 1 Duplicates: 1 Warnings: 0")

// Assign `DEFAULT` in `REPLACE` statement
tk.MustExec("drop table if exists t1, t2;")
tk.MustExec("create table t1 (a int primary key, b int default 20, c int default 30);")
tk.MustExec("insert into t1 value (1, 2, 3);")
tk.MustExec("replace t1 set a=1, b=default;")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 20 30"))
tk.MustExec("replace t1 set a=2, b=default, c=default")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 20 30", "2 20 30"))
tk.MustExec("replace t1 set a=2, b=default(c), c=default(b);")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 20 30", "2 30 20"))
tk.MustExec("replace t1 set a=default(b)+default(c)")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 20 30", "2 30 20", "50 20 30"))
// With generated columns
tk.MustExec("create table t2 (pk int primary key, a int default 1, b int generated always as (-a) virtual, c int generated always as (-a) stored);")
tk.MustExec("replace t2 set pk=1, b=default;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("1 1 -1 -1"))
tk.MustExec("replace t2 set pk=2, a=10, b=default;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("1 1 -1 -1", "2 10 -10 -10"))
tk.MustExec("replace t2 set pk=2, c=default, a=20;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("1 1 -1 -1", "2 20 -20 -20"))
tk.MustExec("replace t2 set pk=2, a=default, b=default, c=default;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("1 1 -1 -1", "2 1 -1 -1"))
tk.MustExec("replace t2 set pk=3, a=default(a), b=default, c=default;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("1 1 -1 -1", "2 1 -1 -1", "3 1 -1 -1"))
tk.MustGetErrCode("replace t2 set b=default(a);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("replace t2 set a=default(b), b=default(b);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("replace t2 set a=default(a), c=default(c);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("replace t2 set a=default(a), c=default(a);", mysql.ErrBadGeneratedColumn)
tk.MustExec("drop table t1, t2")
}

func (s *testSuite2) TestGeneratedColumnForInsert(c *C) {
Expand Down Expand Up @@ -1393,6 +1505,40 @@ func (s *testSuite) TestUpdate(c *C) {
_, err = tk.Exec("update v set a = '2000-11-11'")
c.Assert(err.Error(), Equals, core.ErrViewInvalid.GenWithStackByArgs("test", "v").Error())
tk.MustExec("drop view v")

// Assign `DEFAULT` in `UPDATE` statement
tk.MustExec("drop table if exists t1, t2;")
tk.MustExec("create table t1 (a int default 1, b int default 2);")
tk.MustExec("insert into t1 values (10, 10), (20, 20);")
tk.MustExec("update t1 set a=default where b=10;")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 10", "20 20"))
tk.MustExec("update t1 set a=30, b=default where a=20;")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 10", "30 2"))
tk.MustExec("update t1 set a=default, b=default where a=30;")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 10", "1 2"))
tk.MustExec("insert into t1 values (40, 40)")
tk.MustExec("update t1 set a=default, b=default")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1 2", "1 2", "1 2"))
tk.MustExec("update t1 set a=default(b), b=default(a)")
tk.MustQuery("select * from t1;").Check(testkit.Rows("2 1", "2 1", "2 1"))
// With generated columns
tk.MustExec("create table t2 (a int default 1, b int generated always as (-a) virtual, c int generated always as (-a) stored);")
tk.MustExec("insert into t2 values (10, default, default), (20, default, default)")
tk.MustExec("update t2 set b=default;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("10 -10 -10", "20 -20 -20"))
tk.MustExec("update t2 set a=30, b=default where a=10;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("30 -30 -30", "20 -20 -20"))
tk.MustExec("update t2 set c=default, a=40 where c=-20;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("30 -30 -30", "40 -40 -40"))
tk.MustExec("update t2 set a=default, b=default, c=default where b=-30;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("1 -1 -1", "40 -40 -40"))
tk.MustExec("update t2 set a=default(a), b=default, c=default;")
tk.MustQuery("select * from t2;").Check(testkit.Rows("1 -1 -1", "1 -1 -1"))
tk.MustGetErrCode("update t2 set b=default(a);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("update t2 set a=default(b), b=default(b);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("update t2 set a=default(a), c=default(c);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("update t2 set a=default(a), c=default(a);", mysql.ErrBadGeneratedColumn)
tk.MustExec("drop table t1, t2")
}

func (s *testSuite4) TestPartitionedTableUpdate(c *C) {
Expand Down
16 changes: 9 additions & 7 deletions expression/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,13 +347,15 @@ func ColumnInfos2ColumnsWithDBName(ctx sessionctx.Context, dbName, tblName model
continue
}
newCol := &Column{
ColName: col.Name,
TblName: tblName,
DBName: dbName,
RetType: &col.FieldType,
ID: col.ID,
UniqueID: ctx.GetSessionVars().AllocPlanColumnID(),
Index: col.Offset,
OrigColName: col.Name,
OrigTblName: tblName,
ColName: col.Name,
TblName: tblName,
DBName: dbName,
RetType: &col.FieldType,
ID: col.ID,
UniqueID: ctx.GetSessionVars().AllocPlanColumnID(),
Index: col.Offset,
}
columns = append(columns, newCol)
}
Expand Down
Loading

0 comments on commit cba3e1a

Please sign in to comment.