From 6aa624786a945151b463f890cbb7c12ddd1ec231 Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Mon, 9 Mar 2020 13:20:02 +0800 Subject: [PATCH 01/10] default expr cache --- ddl/sequence_test.go | 27 +++++++++++++++++++++++++++ executor/insert_common.go | 36 ++++++++++++++++++++++++++++++------ table/column.go | 26 ++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/ddl/sequence_test.go b/ddl/sequence_test.go index 467e0c11740a0..c58dd9e5ef729 100644 --- a/ddl/sequence_test.go +++ b/ddl/sequence_test.go @@ -744,3 +744,30 @@ func (s *testSequenceSuite) TestUnflodSequence(c *C) { // `select nextval(seq), a from t1 union select nextval(seq), a from t2` // The executing order of nextval and lastval is implicit, don't make any assumptions on it. } + +// before this PR: +// insert consume: 50.498672ms +// after this PR: +// insert consume: 33.213615ms +func (s *testSequenceSuite) TestBenchInsertCacheDefaultExpr(c *C) { + s.tk = testkit.NewTestKit(c, s.store) + s.tk.MustExec("use test") + s.tk.MustExec("drop sequence if exists seq") + s.tk.MustExec("drop table if exists t") + s.tk.MustExec("create sequence seq") + s.tk.MustExec("create table t(a int default next value for seq)") + sql := "insert into t values " + for i := 0; i < 1000; i++ { + if i == 0 { + sql += "()" + } else { + sql += ",()" + } + } + // start := time.Now() + for i := 0; i < 100; i++ { + s.tk.MustExec(sql) + } + // fmt.Println(time.Now().Sub(start) / 100) +} + diff --git a/executor/insert_common.go b/executor/insert_common.go index c4b6bc8445eee..b43e12912eb19 100644 --- a/executor/insert_common.go +++ b/executor/insert_common.go @@ -74,7 +74,10 @@ type InsertValues struct { } type defaultVal struct { + // common default value is a constant. val types.Datum + // default expr like `nextval(seq)` should be evaluated row by row. + expr ast.ExprNode // valid indicates whether the val is evaluated. We evaluate the default value lazily. valid bool } @@ -508,16 +511,37 @@ func (e *InsertValues) getRowInPlace(ctx context.Context, vals []types.Datum, ro // getColDefaultValue gets the column default value. func (e *InsertValues) getColDefaultValue(idx int, col *table.Column) (d types.Datum, err error) { - if !col.DefaultIsExpr && e.colDefaultVals != nil && e.colDefaultVals[idx].valid { - return e.colDefaultVals[idx].val, nil + if e.colDefaultVals != nil && e.colDefaultVals[idx].valid { + if !col.DefaultIsExpr { + return e.colDefaultVals[idx].val, nil + } else { + return table.EvalColDefaultExprNode(e.ctx, col.ToInfo(), e.colDefaultVals[idx].expr) + } + } + var ( + defaultVal types.Datum + defaultExpr ast.ExprNode + ) + if !col.DefaultIsExpr { + defaultVal, err = table.GetColDefaultValue(e.ctx, col.ToInfo()) + } else { + defaultExpr, err = table.GetColDefaultExpr(col.ToInfo()) + if err != nil { + return types.Datum{}, err + } + defaultVal, err = table.EvalColDefaultExprNode(e.ctx, col.ToInfo(), defaultExpr) } - defaultVal, err := table.GetColDefaultValue(e.ctx, col.ToInfo()) if err != nil { return types.Datum{}, err } - if initialized := e.lazilyInitColDefaultValBuf(); initialized && !col.DefaultIsExpr { - e.colDefaultVals[idx].val = defaultVal - e.colDefaultVals[idx].valid = true + if initialized := e.lazilyInitColDefaultValBuf(); initialized { + if !col.DefaultIsExpr { + e.colDefaultVals[idx].val = defaultVal + e.colDefaultVals[idx].valid = true + } else { + e.colDefaultVals[idx].expr = defaultExpr + e.colDefaultVals[idx].valid = true + } } return defaultVal, nil diff --git a/table/column.go b/table/column.go index 4dedd7eb2fa51..bbaae57df6ede 100644 --- a/table/column.go +++ b/table/column.go @@ -379,6 +379,32 @@ func GetColDefaultValue(ctx sessionctx.Context, col *model.ColumnInfo) (types.Da return getColDefaultExprValue(ctx, col, defaultValue.(string)) } +// GetColDefaultExpr gets default expr node of the column with expr default value. +func GetColDefaultExpr(col *model.ColumnInfo) (ast.ExprNode, error) { + var defaultExpr ast.ExprNode + expr := fmt.Sprintf("select %s", col.GetDefaultValue().(string)) + stmts, _, err := parser.New().Parse(expr, "", "") + if err != nil { + return nil, err + } + defaultExpr = stmts[0].(*ast.SelectStmt).Fields.Fields[0].Expr + return defaultExpr, nil +} + +// EvalColDefaultExpr eval default expr node to explicit default value. +func EvalColDefaultExprNode(ctx sessionctx.Context, col *model.ColumnInfo, defaultExpr ast.ExprNode) (types.Datum, error) { + d, err := expression.EvalAstExpr(ctx, defaultExpr) + if err != nil { + return types.Datum{}, err + } + // Check the evaluated data type by cast. + value, err := CastValue(ctx, d, col) + if err != nil { + return types.Datum{}, err + } + return value, nil +} + func getColDefaultExprValue(ctx sessionctx.Context, col *model.ColumnInfo, defaultValue string) (types.Datum, error) { var defaultExpr ast.ExprNode expr := fmt.Sprintf("select %s", defaultValue) From 1f136c7dae89b977282325fa03861c59c549546e Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Mon, 9 Mar 2020 13:31:45 +0800 Subject: [PATCH 02/10] fmt --- executor/insert_common.go | 5 ++--- table/column.go | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/executor/insert_common.go b/executor/insert_common.go index b43e12912eb19..62bc12cfc83c9 100644 --- a/executor/insert_common.go +++ b/executor/insert_common.go @@ -514,9 +514,8 @@ func (e *InsertValues) getColDefaultValue(idx int, col *table.Column) (d types.D if e.colDefaultVals != nil && e.colDefaultVals[idx].valid { if !col.DefaultIsExpr { return e.colDefaultVals[idx].val, nil - } else { - return table.EvalColDefaultExprNode(e.ctx, col.ToInfo(), e.colDefaultVals[idx].expr) } + return table.EvalColDefaultExpr(e.ctx, col.ToInfo(), e.colDefaultVals[idx].expr) } var ( defaultVal types.Datum @@ -529,7 +528,7 @@ func (e *InsertValues) getColDefaultValue(idx int, col *table.Column) (d types.D if err != nil { return types.Datum{}, err } - defaultVal, err = table.EvalColDefaultExprNode(e.ctx, col.ToInfo(), defaultExpr) + defaultVal, err = table.EvalColDefaultExpr(e.ctx, col.ToInfo(), defaultExpr) } if err != nil { return types.Datum{}, err diff --git a/table/column.go b/table/column.go index bbaae57df6ede..11baf4c109bfe 100644 --- a/table/column.go +++ b/table/column.go @@ -392,7 +392,7 @@ func GetColDefaultExpr(col *model.ColumnInfo) (ast.ExprNode, error) { } // EvalColDefaultExpr eval default expr node to explicit default value. -func EvalColDefaultExprNode(ctx sessionctx.Context, col *model.ColumnInfo, defaultExpr ast.ExprNode) (types.Datum, error) { +func EvalColDefaultExpr(ctx sessionctx.Context, col *model.ColumnInfo, defaultExpr ast.ExprNode) (types.Datum, error) { d, err := expression.EvalAstExpr(ctx, defaultExpr) if err != nil { return types.Datum{}, err From 7dc9eb618d326033a63266e9b9695559b6b02af8 Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Mon, 9 Mar 2020 13:37:26 +0800 Subject: [PATCH 03/10] . --- ddl/sequence_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/ddl/sequence_test.go b/ddl/sequence_test.go index c58dd9e5ef729..db21946631cbd 100644 --- a/ddl/sequence_test.go +++ b/ddl/sequence_test.go @@ -34,6 +34,7 @@ type testSequenceSuite struct{ *testDBSuite } func (s *testSequenceSuite) TestCreateSequence(c *C) { s.tk = testkit.NewTestKit(c, s.store) s.tk.MustExec("use test") + s.tk.MustExec("drop sequence if exists seq") s.tk.MustGetErrCode("create sequence `seq `", mysql.ErrWrongTableName) // increment should not be set as 0. From e7251c7b4cf31fa028f93905612120c0d682177b Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Tue, 10 Mar 2020 15:19:17 +0800 Subject: [PATCH 04/10] fmt --- ddl/sequence_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/ddl/sequence_test.go b/ddl/sequence_test.go index db21946631cbd..6b7ba601a444e 100644 --- a/ddl/sequence_test.go +++ b/ddl/sequence_test.go @@ -771,4 +771,3 @@ func (s *testSequenceSuite) TestBenchInsertCacheDefaultExpr(c *C) { } // fmt.Println(time.Now().Sub(start) / 100) } - From b2995b643104ae7d22acb223d7275c2dcf747fe3 Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Tue, 10 Mar 2020 15:58:24 +0800 Subject: [PATCH 05/10] . --- ddl/sequence_test.go | 6 ++---- executor/insert_common.go | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ddl/sequence_test.go b/ddl/sequence_test.go index 6b7ba601a444e..801c38faae631 100644 --- a/ddl/sequence_test.go +++ b/ddl/sequence_test.go @@ -747,9 +747,9 @@ func (s *testSequenceSuite) TestUnflodSequence(c *C) { } // before this PR: -// insert consume: 50.498672ms +// single insert consume: 50.498672ms // after this PR: -// insert consume: 33.213615ms +// single insert consume: 33.213615ms func (s *testSequenceSuite) TestBenchInsertCacheDefaultExpr(c *C) { s.tk = testkit.NewTestKit(c, s.store) s.tk.MustExec("use test") @@ -765,9 +765,7 @@ func (s *testSequenceSuite) TestBenchInsertCacheDefaultExpr(c *C) { sql += ",()" } } - // start := time.Now() for i := 0; i < 100; i++ { s.tk.MustExec(sql) } - // fmt.Println(time.Now().Sub(start) / 100) } diff --git a/executor/insert_common.go b/executor/insert_common.go index 62bc12cfc83c9..761d660cb745c 100644 --- a/executor/insert_common.go +++ b/executor/insert_common.go @@ -76,7 +76,7 @@ type InsertValues struct { type defaultVal struct { // common default value is a constant. val types.Datum - // default expr like `nextval(seq)` should be evaluated row by row. + // default expr(nextval(seq)) should be evaluated row by row. expr ast.ExprNode // valid indicates whether the val is evaluated. We evaluate the default value lazily. valid bool From bbb0ac5ae01a08aea84c347b95f3c3390ce58bf5 Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Tue, 17 Mar 2020 10:43:04 +0800 Subject: [PATCH 06/10] benchmark test under gocheck --- ddl/sequence_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ddl/sequence_test.go b/ddl/sequence_test.go index b1d5a9521c92b..41985be876b60 100644 --- a/ddl/sequence_test.go +++ b/ddl/sequence_test.go @@ -750,7 +750,8 @@ func (s *testSequenceSuite) TestUnflodSequence(c *C) { // single insert consume: 50.498672ms // after this PR: // single insert consume: 33.213615ms -func (s *testSequenceSuite) TestBenchInsertCacheDefaultExpr(c *C) { +// Notice: use go test -check.b Benchmarkxxx to test it. +func (s *testSequenceSuite) BenchmarkInsertCacheDefaultExpr(c *C) { s.tk = testkit.NewTestKit(c, s.store) s.tk.MustExec("use test") s.tk.MustExec("drop sequence if exists seq") @@ -765,7 +766,8 @@ func (s *testSequenceSuite) TestBenchInsertCacheDefaultExpr(c *C) { sql += ",()" } } - for i := 0; i < 100; i++ { + c.ResetTimer() + for i := 0; i < c.N; i++ { s.tk.MustExec(sql) } } From 8842b95b8ffd56e7f9dcef9f7503eaf7c7a4d067 Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Wed, 18 Mar 2020 18:04:18 +0800 Subject: [PATCH 07/10] cache default expr node in column(tableCommon) --- executor/insert_common.go | 32 ++++++++------------------------ planner/core/planbuilder.go | 10 +++++++++- table/column.go | 20 +++++++------------- table/tables/tables.go | 8 ++++++++ 4 files changed, 32 insertions(+), 38 deletions(-) diff --git a/executor/insert_common.go b/executor/insert_common.go index cec02b3037d11..59a19723b10db 100644 --- a/executor/insert_common.go +++ b/executor/insert_common.go @@ -76,8 +76,6 @@ type InsertValues struct { type defaultVal struct { // common default value is a constant. val types.Datum - // default expr(nextval(seq)) should be evaluated row by row. - expr ast.ExprNode // valid indicates whether the val is evaluated. We evaluate the default value lazily. valid bool } @@ -497,36 +495,22 @@ func (e *InsertValues) getRow(ctx context.Context, vals []types.Datum) ([]types. // getColDefaultValue gets the column default value. func (e *InsertValues) getColDefaultValue(idx int, col *table.Column) (d types.Datum, err error) { - if e.colDefaultVals != nil && e.colDefaultVals[idx].valid { - if !col.DefaultIsExpr { - return e.colDefaultVals[idx].val, nil - } - return table.EvalColDefaultExpr(e.ctx, col.ToInfo(), e.colDefaultVals[idx].expr) + if !col.DefaultIsExpr && e.colDefaultVals != nil && e.colDefaultVals[idx].valid { + return e.colDefaultVals[idx].val, nil } - var ( - defaultVal types.Datum - defaultExpr ast.ExprNode - ) + + var defaultVal types.Datum if !col.DefaultIsExpr { defaultVal, err = table.GetColDefaultValue(e.ctx, col.ToInfo()) } else { - defaultExpr, err = table.GetColDefaultExpr(col.ToInfo()) - if err != nil { - return types.Datum{}, err - } - defaultVal, err = table.EvalColDefaultExpr(e.ctx, col.ToInfo(), defaultExpr) + defaultVal, err = table.EvalColDefaultExpr(e.ctx, col.ToInfo(), col.DefaultExpr) } if err != nil { return types.Datum{}, err } - if initialized := e.lazilyInitColDefaultValBuf(); initialized { - if !col.DefaultIsExpr { - e.colDefaultVals[idx].val = defaultVal - e.colDefaultVals[idx].valid = true - } else { - e.colDefaultVals[idx].expr = defaultExpr - e.colDefaultVals[idx].valid = true - } + if initialized := e.lazilyInitColDefaultValBuf(); initialized && !col.DefaultIsExpr { + e.colDefaultVals[idx].val = defaultVal + e.colDefaultVals[idx].valid = true } return defaultVal, nil diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 353cbeabfe8bf..34e63a2210d87 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -1812,7 +1812,15 @@ func collectVisitInfoFromGrantStmt(sctx sessionctx.Context, vi []visitInfo, stmt } func (b *PlanBuilder) getDefaultValue(col *table.Column) (*expression.Constant, error) { - value, err := table.GetColDefaultValue(b.ctx, col.ToInfo()) + var ( + value types.Datum + err error + ) + if !col.DefaultIsExpr { + value, err = table.GetColDefaultValue(b.ctx, col.ToInfo()) + } else { + value, err = table.EvalColDefaultExpr(b.ctx, col.ToInfo(), col.DefaultExpr) + } if err != nil { return nil, err } diff --git a/table/column.go b/table/column.go index 11baf4c109bfe..769fd2d9e77d9 100644 --- a/table/column.go +++ b/table/column.go @@ -19,12 +19,12 @@ package table import ( "fmt" + "github.com/pingcap/parser" "strconv" "strings" "time" "unicode/utf8" - "github.com/pingcap/parser" "github.com/pingcap/parser/ast" "github.com/pingcap/parser/charset" "github.com/pingcap/parser/model" @@ -47,6 +47,8 @@ type Column struct { *model.ColumnInfo // If this column is a generated column, the expression will be stored here. GeneratedExpr ast.ExprNode + // If this column has default expr value, this expression will be stored here. + DefaultExpr ast.ExprNode } // String implements fmt.Stringer interface. @@ -82,6 +84,7 @@ func ToColumn(col *model.ColumnInfo) *Column { return &Column{ col, nil, + nil, } } @@ -376,21 +379,12 @@ func GetColDefaultValue(ctx sessionctx.Context, col *model.ColumnInfo) (types.Da if !col.DefaultIsExpr { return getColDefaultValue(ctx, col, defaultValue) } + // This is reserved for some cases like: `columnInfo` call `ToColumn` to be column, and then get its default value. + // In this case, the default expr node is not cached in column, but we still need to guarantee the correct result + // for default expr. return getColDefaultExprValue(ctx, col, defaultValue.(string)) } -// GetColDefaultExpr gets default expr node of the column with expr default value. -func GetColDefaultExpr(col *model.ColumnInfo) (ast.ExprNode, error) { - var defaultExpr ast.ExprNode - expr := fmt.Sprintf("select %s", col.GetDefaultValue().(string)) - stmts, _, err := parser.New().Parse(expr, "", "") - if err != nil { - return nil, err - } - defaultExpr = stmts[0].(*ast.SelectStmt).Fields.Fields[0].Expr - return defaultExpr, nil -} - // EvalColDefaultExpr eval default expr node to explicit default value. func EvalColDefaultExpr(ctx sessionctx.Context, col *model.ColumnInfo, defaultExpr ast.ExprNode) (types.Datum, error) { d, err := expression.EvalAstExpr(ctx, defaultExpr) diff --git a/table/tables/tables.go b/table/tables/tables.go index db293c1c415c8..18601493b2e59 100644 --- a/table/tables/tables.go +++ b/table/tables/tables.go @@ -122,6 +122,14 @@ func TableFromMeta(allocs autoid.Allocators, tblInfo *model.TableInfo) (table.Ta } col.GeneratedExpr = expr } + // default value is expr. + if col.DefaultIsExpr { + expr, err := parseExpression(colInfo.DefaultValue.(string)) + if err != nil { + return nil, err + } + col.DefaultExpr = expr + } columns = append(columns, col) } From f50b24a35c589de9da898976f6dba9d54360a0f8 Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Wed, 18 Mar 2020 18:10:44 +0800 Subject: [PATCH 08/10] fmt --- executor/insert_common.go | 1 - table/column.go | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/executor/insert_common.go b/executor/insert_common.go index d8daf4935f745..520d594fb41a7 100644 --- a/executor/insert_common.go +++ b/executor/insert_common.go @@ -74,7 +74,6 @@ type InsertValues struct { } type defaultVal struct { - // common default value is a constant. val types.Datum // valid indicates whether the val is evaluated. We evaluate the default value lazily. valid bool diff --git a/table/column.go b/table/column.go index 769fd2d9e77d9..e2a347ac8940a 100644 --- a/table/column.go +++ b/table/column.go @@ -19,12 +19,12 @@ package table import ( "fmt" - "github.com/pingcap/parser" "strconv" "strings" "time" "unicode/utf8" + "github.com/pingcap/parser" "github.com/pingcap/parser/ast" "github.com/pingcap/parser/charset" "github.com/pingcap/parser/model" From 925449324377f001bced0ca070b852feeb6639da Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Wed, 18 Mar 2020 18:14:58 +0800 Subject: [PATCH 09/10] fmt --- table/column.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/table/column.go b/table/column.go index e2a347ac8940a..60c4b4f974f65 100644 --- a/table/column.go +++ b/table/column.go @@ -379,9 +379,6 @@ func GetColDefaultValue(ctx sessionctx.Context, col *model.ColumnInfo) (types.Da if !col.DefaultIsExpr { return getColDefaultValue(ctx, col, defaultValue) } - // This is reserved for some cases like: `columnInfo` call `ToColumn` to be column, and then get its default value. - // In this case, the default expr node is not cached in column, but we still need to guarantee the correct result - // for default expr. return getColDefaultExprValue(ctx, col, defaultValue.(string)) } From 9bf6ef12f6de61d0e9ac037c8b48e6f4fd57d39b Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Thu, 19 Mar 2020 10:30:06 +0800 Subject: [PATCH 10/10] . --- executor/insert_common.go | 6 +++--- go.sum | 2 -- planner/core/planbuilder.go | 6 +++--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/executor/insert_common.go b/executor/insert_common.go index 520d594fb41a7..a4ea2a566b5f6 100644 --- a/executor/insert_common.go +++ b/executor/insert_common.go @@ -499,10 +499,10 @@ func (e *InsertValues) getColDefaultValue(idx int, col *table.Column) (d types.D } var defaultVal types.Datum - if !col.DefaultIsExpr { - defaultVal, err = table.GetColDefaultValue(e.ctx, col.ToInfo()) - } else { + if col.DefaultIsExpr && col.DefaultExpr != nil { defaultVal, err = table.EvalColDefaultExpr(e.ctx, col.ToInfo(), col.DefaultExpr) + } else { + defaultVal, err = table.GetColDefaultValue(e.ctx, col.ToInfo()) } if err != nil { return types.Datum{}, err diff --git a/go.sum b/go.sum index ed94b8ad844a1..79473a8cb3cd0 100644 --- a/go.sum +++ b/go.sum @@ -195,8 +195,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lawyerphx/parser v0.0.0-20200316023126-7af13c9e0b85 h1:my5oTuBLzT1knvQnwaF7RXxNuzvzqhioNM8OcHYF2/A= -github.com/lawyerphx/parser v0.0.0-20200316023126-7af13c9e0b85/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 68c85eabf9900..ec0787d756848 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -1821,10 +1821,10 @@ func (b *PlanBuilder) getDefaultValue(col *table.Column) (*expression.Constant, value types.Datum err error ) - if !col.DefaultIsExpr { - value, err = table.GetColDefaultValue(b.ctx, col.ToInfo()) - } else { + if col.DefaultIsExpr && col.DefaultExpr != nil { value, err = table.EvalColDefaultExpr(b.ctx, col.ToInfo(), col.DefaultExpr) + } else { + value, err = table.GetColDefaultValue(b.ctx, col.ToInfo()) } if err != nil { return nil, err