Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expression: Fix the wrong behavior of const.String() (#17495) #17673

Merged
merged 2 commits into from
Jun 5, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 19 additions & 26 deletions expression/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import (
"github.com/pingcap/tidb/types/json"
"github.com/pingcap/tidb/util/chunk"
"github.com/pingcap/tidb/util/codec"
"github.com/pingcap/tidb/util/logutil"
"go.uber.org/zap"
)

// NewOne stands for a number 1.
Expand Down Expand Up @@ -86,12 +84,7 @@ func (c *Constant) String() string {
dt := c.ParamMarker.GetUserVar()
c.Value.SetValue(dt.GetValue(), c.RetType)
} else if c.DeferredExpr != nil {
dt, err := c.Eval(chunk.Row{})
if err != nil {
logutil.BgLogger().Error("eval constant failed", zap.Error(err))
return ""
}
c.Value.SetValue(dt.GetValue(), c.RetType)
return c.DeferredExpr.String()
}
return fmt.Sprintf("%v", c.Value.GetValue())
}
Expand Down Expand Up @@ -176,7 +169,7 @@ func (c *Constant) VecEvalJSON(ctx sessionctx.Context, input *chunk.Chunk, resul
return c.DeferredExpr.VecEvalJSON(ctx, input, result)
}

func (c *Constant) getLazyDatum() (dt types.Datum, isLazy bool, err error) {
func (c *Constant) getLazyDatum(row chunk.Row) (dt types.Datum, isLazy bool, err error) {
if p := c.ParamMarker; p != nil {
if p.ctx.GetSessionVars().StmtCtx.InExplainStmt {
// Since `ParamMarker` is not nil only in prepare/execute context, the query must be `explain for connection` when coming here.
Expand All @@ -187,16 +180,16 @@ func (c *Constant) getLazyDatum() (dt types.Datum, isLazy bool, err error) {
isLazy = true
return
} else if c.DeferredExpr != nil {
dt, err = c.DeferredExpr.Eval(chunk.Row{})
dt, err = c.DeferredExpr.Eval(row)
isLazy = true
return
}
return
}

// Eval implements Expression interface.
func (c *Constant) Eval(_ chunk.Row) (types.Datum, error) {
if dt, lazy, err := c.getLazyDatum(); lazy {
func (c *Constant) Eval(row chunk.Row) (types.Datum, error) {
if dt, lazy, err := c.getLazyDatum(row); lazy {
if err != nil {
return c.Value, err
}
Expand All @@ -220,8 +213,8 @@ func (c *Constant) Eval(_ chunk.Row) (types.Datum, error) {
}

// EvalInt returns int representation of Constant.
func (c *Constant) EvalInt(ctx sessionctx.Context, _ chunk.Row) (int64, bool, error) {
dt, lazy, err := c.getLazyDatum()
func (c *Constant) EvalInt(ctx sessionctx.Context, row chunk.Row) (int64, bool, error) {
dt, lazy, err := c.getLazyDatum(row)
if err != nil {
return 0, false, err
}
Expand All @@ -241,8 +234,8 @@ func (c *Constant) EvalInt(ctx sessionctx.Context, _ chunk.Row) (int64, bool, er
}

// EvalReal returns real representation of Constant.
func (c *Constant) EvalReal(ctx sessionctx.Context, _ chunk.Row) (float64, bool, error) {
dt, lazy, err := c.getLazyDatum()
func (c *Constant) EvalReal(ctx sessionctx.Context, row chunk.Row) (float64, bool, error) {
dt, lazy, err := c.getLazyDatum(row)
if err != nil {
return 0, false, err
}
Expand All @@ -260,8 +253,8 @@ func (c *Constant) EvalReal(ctx sessionctx.Context, _ chunk.Row) (float64, bool,
}

// EvalString returns string representation of Constant.
func (c *Constant) EvalString(ctx sessionctx.Context, _ chunk.Row) (string, bool, error) {
dt, lazy, err := c.getLazyDatum()
func (c *Constant) EvalString(ctx sessionctx.Context, row chunk.Row) (string, bool, error) {
dt, lazy, err := c.getLazyDatum(row)
if err != nil {
return "", false, err
}
Expand All @@ -276,8 +269,8 @@ func (c *Constant) EvalString(ctx sessionctx.Context, _ chunk.Row) (string, bool
}

// EvalDecimal returns decimal representation of Constant.
func (c *Constant) EvalDecimal(ctx sessionctx.Context, _ chunk.Row) (*types.MyDecimal, bool, error) {
dt, lazy, err := c.getLazyDatum()
func (c *Constant) EvalDecimal(ctx sessionctx.Context, row chunk.Row) (*types.MyDecimal, bool, error) {
dt, lazy, err := c.getLazyDatum(row)
if err != nil {
return nil, false, err
}
Expand All @@ -292,8 +285,8 @@ func (c *Constant) EvalDecimal(ctx sessionctx.Context, _ chunk.Row) (*types.MyDe
}

// EvalTime returns DATE/DATETIME/TIMESTAMP representation of Constant.
func (c *Constant) EvalTime(ctx sessionctx.Context, _ chunk.Row) (val types.Time, isNull bool, err error) {
dt, lazy, err := c.getLazyDatum()
func (c *Constant) EvalTime(ctx sessionctx.Context, row chunk.Row) (val types.Time, isNull bool, err error) {
dt, lazy, err := c.getLazyDatum(row)
if err != nil {
return types.ZeroTime, false, err
}
Expand All @@ -307,8 +300,8 @@ func (c *Constant) EvalTime(ctx sessionctx.Context, _ chunk.Row) (val types.Time
}

// EvalDuration returns Duration representation of Constant.
func (c *Constant) EvalDuration(ctx sessionctx.Context, _ chunk.Row) (val types.Duration, isNull bool, err error) {
dt, lazy, err := c.getLazyDatum()
func (c *Constant) EvalDuration(ctx sessionctx.Context, row chunk.Row) (val types.Duration, isNull bool, err error) {
dt, lazy, err := c.getLazyDatum(row)
if err != nil {
return types.Duration{}, false, err
}
Expand All @@ -322,8 +315,8 @@ func (c *Constant) EvalDuration(ctx sessionctx.Context, _ chunk.Row) (val types.
}

// EvalJSON returns JSON representation of Constant.
func (c *Constant) EvalJSON(ctx sessionctx.Context, _ chunk.Row) (json.BinaryJSON, bool, error) {
dt, lazy, err := c.getLazyDatum()
func (c *Constant) EvalJSON(ctx sessionctx.Context, row chunk.Row) (json.BinaryJSON, bool, error) {
dt, lazy, err := c.getLazyDatum(row)
if err != nil {
return json.BinaryJSON{}, false, err
}
Expand Down
25 changes: 25 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6477,3 +6477,28 @@ func (s *testIntegrationSuite) TestIndexedVirtualGeneratedColumnTruncate(c *C) {
tk.MustExec("commit")
tk.MustExec("admin check table t")
}

func (s *testIntegrationSuite) TestIssue17287(c *C) {
tk := testkit.NewTestKit(c, s.store)
orgEnable := plannercore.PreparedPlanCacheEnabled()
defer func() {
plannercore.SetPreparedPlanCache(orgEnable)
}()
plannercore.SetPreparedPlanCache(true)
var err error
tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{
PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64),
})
c.Assert(err, IsNil)

tk.MustExec("use test;")
tk.MustExec("drop table if exists t;")
tk.MustExec("set @@tidb_enable_vectorized_expression = false;")
tk.MustExec("create table t(a datetime);")
tk.MustExec("insert into t values(from_unixtime(1589873945)), (from_unixtime(1589873946));")
tk.MustExec("prepare stmt7 from 'SELECT unix_timestamp(a) FROM t WHERE a = from_unixtime(?);';")
tk.MustExec("set @val1 = 1589873945;")
tk.MustExec("set @val2 = 1589873946;")
tk.MustQuery("execute stmt7 using @val1;").Check(testkit.Rows("1589873945"))
tk.MustQuery("execute stmt7 using @val2;").Check(testkit.Rows("1589873946"))
}