Skip to content

Commit

Permalink
expression: disable int_col <cmp> non-int const folding for plan ca…
Browse files Browse the repository at this point in the history
…che (#14120)
  • Loading branch information
eurekaka authored and sre-bot committed Jan 15, 2020
1 parent d65e23f commit 1d64195
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 8 deletions.
22 changes: 14 additions & 8 deletions expression/builtin_compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -1098,8 +1098,10 @@ func tryToConvertConstantInt(ctx sessionctx.Context, targetFieldType *types.Fiel
if err != nil {
if terror.ErrorEqual(err, types.ErrOverflow) {
return &Constant{
Value: dt,
RetType: targetFieldType,
Value: dt,
RetType: targetFieldType,
DeferredExpr: con.DeferredExpr,
ParamMarker: con.ParamMarker,
}, true
}
return con, false
Expand Down Expand Up @@ -1134,8 +1136,10 @@ func RefineComparedConstant(ctx sessionctx.Context, targetFieldType types.FieldT
if err != nil {
if terror.ErrorEqual(err, types.ErrOverflow) {
return &Constant{
Value: intDatum,
RetType: &targetFieldType,
Value: intDatum,
RetType: &targetFieldType,
DeferredExpr: con.DeferredExpr,
ParamMarker: con.ParamMarker,
}, true
}
return con, false
Expand Down Expand Up @@ -1201,6 +1205,9 @@ func RefineComparedConstant(ctx sessionctx.Context, targetFieldType types.FieldT
// refineArgs will rewrite the arguments if the compare expression is `int column <cmp> non-int constant` or
// `non-int constant <cmp> int column`. E.g., `a < 1.1` will be rewritten to `a < 2`.
func (c *compareFunctionClass) refineArgs(ctx sessionctx.Context, args []Expression) []Expression {
if ctx.GetSessionVars().StmtCtx.UseCache && ContainLazyConst(args) {
return args
}
arg0Type, arg1Type := args[0].GetType(), args[1].GetType()
arg0IsInt := arg0Type.EvalType() == types.ETInt
arg1IsInt := arg1Type.EvalType() == types.ETInt
Expand Down Expand Up @@ -1239,24 +1246,23 @@ func (c *compareFunctionClass) refineArgs(ctx sessionctx.Context, args []Express
}
}
}

if isExceptional && (c.op == opcode.EQ || c.op == opcode.NullEQ) {
// This will always be false.
return []Expression{Zero.Clone(), One.Clone()}
return []Expression{Zero, One}
}
if isPositiveInfinite {
// If the op is opcode.LT, opcode.LE
// This will always be true.
// If the op is opcode.GT, opcode.GE
// This will always be false.
return []Expression{Zero.Clone(), One.Clone()}
return []Expression{Zero, One}
}
if isNegativeInfinite {
// If the op is opcode.GT, opcode.GE
// This will always be true.
// If the op is opcode.LT, opcode.LE
// This will always be false.
return []Expression{One.Clone(), Zero.Clone()}
return []Expression{One, Zero}
}

return []Expression{finalArg0, finalArg1}
Expand Down
35 changes: 35 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5277,3 +5277,38 @@ func (s *testIntegrationSuite) TestCacheRegexpr(c *C) {
tk.MustExec("set @a='^R.*'")
tk.MustQuery("execute stmt1 using @a").Check(testkit.Rows("R1"))
}

func (s *testIntegrationSuite) TestCacheRefineArgs(c *C) {
tk := testkit.NewTestKit(c, s.store)
orgEnable := plannercore.PreparedPlanCacheEnabled()
orgCapacity := plannercore.PreparedPlanCacheCapacity
orgMemGuardRatio := plannercore.PreparedPlanCacheMemoryGuardRatio
orgMaxMemory := plannercore.PreparedPlanCacheMaxMemory
defer func() {
plannercore.SetPreparedPlanCache(orgEnable)
plannercore.PreparedPlanCacheCapacity = orgCapacity
plannercore.PreparedPlanCacheMemoryGuardRatio = orgMemGuardRatio
plannercore.PreparedPlanCacheMaxMemory = orgMaxMemory
}()
plannercore.SetPreparedPlanCache(true)
plannercore.PreparedPlanCacheCapacity = 100
plannercore.PreparedPlanCacheMemoryGuardRatio = 0.1
// PreparedPlanCacheMaxMemory is set to MAX_UINT64 to make sure the cache
// behavior would not be effected by the uncertain memory utilization.
plannercore.PreparedPlanCacheMaxMemory.Store(math.MaxUint64)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(col_int int)")
tk.MustExec("insert into t values(null)")
tk.MustExec("prepare stmt from 'SELECT ((col_int is true) = ?) AS res FROM t'")
tk.MustExec("set @p0='0.8'")
tk.MustQuery("execute stmt using @p0").Check(testkit.Rows("0"))
tk.MustExec("set @p0='0'")
tk.MustQuery("execute stmt using @p0").Check(testkit.Rows("1"))

tk.MustExec("delete from t")
tk.MustExec("insert into t values(1)")
tk.MustExec("prepare stmt from 'SELECT col_int < ? FROM t'")
tk.MustExec("set @p0='-184467440737095516167.1'")
tk.MustQuery("execute stmt using @p0").Check(testkit.Rows("0"))
}
17 changes: 17 additions & 0 deletions expression/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -803,3 +803,20 @@ func ContainVirtualColumn(exprs []Expression) bool {
}
return false
}

// ContainLazyConst checks if the expressions contain a lazy constant.
func ContainLazyConst(exprs []Expression) bool {
for _, expr := range exprs {
switch v := expr.(type) {
case *Constant:
if v.ParamMarker != nil || v.DeferredExpr != nil {
return true
}
case *ScalarFunction:
if ContainLazyConst(v.GetArgs()) {
return true
}
}
}
return false
}

0 comments on commit 1d64195

Please sign in to comment.