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

planner: unify the behavior of prepare/execute limit to mysql #40360

Merged
merged 34 commits into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0557606
commit
fzzf678 Jan 6, 2023
5d45069
Merge branch 'master' into planCache_limit_behaviour
fzzf678 Jan 6, 2023
28dd3f6
Merge branch 'master' into planCache_limit_behaviour
fzzf678 Jan 6, 2023
a723944
Update logical_plan_builder.go
fzzf678 Jan 6, 2023
349d284
Merge branch 'planCache_limit_behaviour' of https://github.com/fzzf67…
fzzf678 Jan 6, 2023
d1b95cf
Update logical_plan_builder.go
fzzf678 Jan 6, 2023
463b85f
Update plan_cache_test.go
fzzf678 Jan 6, 2023
ed925f9
fix ut
fzzf678 Jan 6, 2023
47cfbfa
Merge branch 'master' into planCache_limit_behaviour
fzzf678 Jan 6, 2023
39b8b7b
Merge branch 'master' into planCache_limit_behaviour
fzzf678 Jan 9, 2023
5c383c8
Update logical_plan_builder.go
fzzf678 Jan 9, 2023
26d1455
Merge branch 'planCache_limit_behaviour' of https://github.com/fzzf67…
fzzf678 Jan 9, 2023
b7c7c59
Update logical_plan_builder.go
fzzf678 Jan 9, 2023
87ad598
rename
fzzf678 Jan 9, 2023
6094e46
reanme
fzzf678 Jan 9, 2023
ffc51a3
Merge branch 'master' into planCache_limit_behaviour
fzzf678 Jan 9, 2023
7c3a2cc
test
fzzf678 Jan 9, 2023
e44d8ca
Update prepared_test.go
fzzf678 Jan 9, 2023
49855b0
Update logical_plan_builder.go
fzzf678 Jan 9, 2023
850b34a
amazing
fzzf678 Jan 9, 2023
253f14a
Update plan_cache_test.go
fzzf678 Jan 9, 2023
eddee4f
Update plan_cache_test.go
fzzf678 Jan 9, 2023
f9e204f
Update plan_cache_test.go
fzzf678 Jan 9, 2023
924cd7d
Merge branch 'master' into planCache_limit_behaviour
fzzf678 Jan 9, 2023
00e2abd
Update plan_cache_test.go
fzzf678 Jan 9, 2023
f9b93a8
Merge branch 'planCache_limit_behaviour' of https://github.com/fzzf67…
fzzf678 Jan 9, 2023
f774bd6
Update plan_cache_test.go
fzzf678 Jan 9, 2023
55bac3b
Update plan_cache_test.go
fzzf678 Jan 9, 2023
858d59f
Update plan_cache_test.go
fzzf678 Jan 9, 2023
d11cafe
Update plan_cache_test.go
fzzf678 Jan 9, 2023
32e4337
Update plan_cache_test.go
fzzf678 Jan 9, 2023
68546d5
test
fzzf678 Jan 9, 2023
d269e8c
Update prepared_test.go
fzzf678 Jan 9, 2023
d556fc8
WhyThisWorks
fzzf678 Jan 9, 2023
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
26 changes: 23 additions & 3 deletions executor/seqtest/prepared_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,11 +280,11 @@ func TestPreparedLimitOffset(t *testing.T) {
r.Check(testkit.Rows("2"))

tk.MustExec(`set @a=1.1`)
r = tk.MustQuery(`execute stmt_test_1 using @a, @b;`)
r.Check(testkit.Rows("2"))
_, err := tk.Exec(`execute stmt_test_1 using @a, @b;`)
require.True(t, plannercore.ErrWrongArguments.Equal(err))

tk.MustExec(`set @c="-1"`)
_, err := tk.Exec("execute stmt_test_1 using @c, @c")
_, err = tk.Exec("execute stmt_test_1 using @c, @c")
require.True(t, plannercore.ErrWrongArguments.Equal(err))

stmtID, _, _, err := tk.Session().PrepareStmt("select id from prepare_test limit ?")
Expand Down Expand Up @@ -767,3 +767,23 @@ func TestPreparedIssue17419(t *testing.T) {
// _, ok := tk1.Session().ShowProcess().Plan.(*plannercore.Execute)
// require.True(t, ok)
}

func TestLimitUnsupportedCase(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, key(a))")
tk.MustExec("prepare stmt from 'select * from t limit ?'")

tk.MustExec("set @a = 1.2")
tk.MustGetErrMsg("execute stmt using @a", "[planner:1210]Incorrect arguments to LIMIT")
tk.MustExec("set @a = 1.")
tk.MustGetErrMsg("execute stmt using @a", "[planner:1210]Incorrect arguments to LIMIT")
tk.MustExec("set @a = '0'")
tk.MustGetErrMsg("execute stmt using @a", "[planner:1210]Incorrect arguments to LIMIT")
tk.MustExec("set @a = '1'")
tk.MustGetErrMsg("execute stmt using @a", "[planner:1210]Incorrect arguments to LIMIT")
tk.MustExec("set @a = 1_2")
tk.MustGetErrMsg("execute stmt using @a", "[planner:1210]Incorrect arguments to LIMIT")
}
34 changes: 27 additions & 7 deletions planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func (a *aggOrderByResolver) Enter(inNode ast.Node) (ast.Node, bool) {
a.exprDepth++
if n, ok := inNode.(*driver.ParamMarkerExpr); ok {
if a.exprDepth == 1 {
_, isNull, isExpectedType := getUintFromNode(a.ctx, n)
_, isNull, isExpectedType := getUintFromNode(a.ctx, n, false)
// For constant uint expression in top level, it should be treated as position expression.
if !isNull && isExpectedType {
return expression.ConstructPositionExpr(n), true
Expand Down Expand Up @@ -2005,7 +2005,7 @@ CheckReferenced:
// getUintFromNode gets uint64 value from ast.Node.
// For ordinary statement, node should be uint64 constant value.
// For prepared statement, node is string. We should convert it to uint64.
func getUintFromNode(ctx sessionctx.Context, n ast.Node) (uVal uint64, isNull bool, isExpectedType bool) {
func getUintFromNode(ctx sessionctx.Context, n ast.Node, mustInt64orUint64 bool) (uVal uint64, isNull bool, isExpectedType bool) {
var val interface{}
switch v := n.(type) {
case *driver.ValueExpr:
Expand All @@ -2014,6 +2014,11 @@ func getUintFromNode(ctx sessionctx.Context, n ast.Node) (uVal uint64, isNull bo
if !v.InExecute {
return 0, false, true
}
if mustInt64orUint64 {
if expected := checkParamTypeInt64orUint64(v); !expected {
return 0, false, false
}
}
param, err := expression.ParamMarkerExpression(ctx, v, false)
if err != nil {
return 0, false, false
Expand Down Expand Up @@ -2047,17 +2052,32 @@ func getUintFromNode(ctx sessionctx.Context, n ast.Node) (uVal uint64, isNull bo
return 0, false, false
}

// check param type for plan cache limit, only allow int64 and uint64 now
// eg: set @a = 1;
func checkParamTypeInt64orUint64(param *driver.ParamMarkerExpr) bool {
val := param.GetValue()
switch v := val.(type) {
case int64:
qw4990 marked this conversation as resolved.
Show resolved Hide resolved
if v >= 0 {
return true
}
case uint64:
return true
}
return false
}

func extractLimitCountOffset(ctx sessionctx.Context, limit *ast.Limit) (count uint64,
offset uint64, err error) {
var isExpectedType bool
if limit.Count != nil {
count, _, isExpectedType = getUintFromNode(ctx, limit.Count)
count, _, isExpectedType = getUintFromNode(ctx, limit.Count, true)
if !isExpectedType {
return 0, 0, ErrWrongArguments.GenWithStackByArgs("LIMIT")
}
}
if limit.Offset != nil {
offset, _, isExpectedType = getUintFromNode(ctx, limit.Offset)
offset, _, isExpectedType = getUintFromNode(ctx, limit.Offset, true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some test cases for this situation.

if !isExpectedType {
return 0, 0, ErrWrongArguments.GenWithStackByArgs("LIMIT")
}
Expand Down Expand Up @@ -2838,7 +2858,7 @@ func (g *gbyResolver) Enter(inNode ast.Node) (ast.Node, bool) {
case *driver.ParamMarkerExpr:
g.isParam = true
if g.exprDepth == 1 {
_, isNull, isExpectedType := getUintFromNode(g.ctx, n)
_, isNull, isExpectedType := getUintFromNode(g.ctx, n, false)
// For constant uint expression in top level, it should be treated as position expression.
if !isNull && isExpectedType {
return expression.ConstructPositionExpr(n), true
Expand Down Expand Up @@ -6203,7 +6223,7 @@ func (b *PlanBuilder) buildWindowFunctionFrameBound(_ context.Context, spec *ast
if bound.Type == ast.CurrentRow {
return bound, nil
}
numRows, _, _ := getUintFromNode(b.ctx, boundClause.Expr)
numRows, _, _ := getUintFromNode(b.ctx, boundClause.Expr, false)
bound.Num = numRows
return bound, nil
}
Expand Down Expand Up @@ -6519,7 +6539,7 @@ func (b *PlanBuilder) checkOriginWindowFrameBound(bound *ast.FrameBound, spec *a
if bound.Unit != ast.TimeUnitInvalid {
return ErrWindowRowsIntervalUse.GenWithStackByArgs(getWindowName(spec.Name.O))
}
_, isNull, isExpectedType := getUintFromNode(b.ctx, bound.Expr)
_, isNull, isExpectedType := getUintFromNode(b.ctx, bound.Expr, false)
if isNull || !isExpectedType {
return ErrWindowFrameIllegal.GenWithStackByArgs(getWindowName(spec.Name.O))
}
Expand Down