-
Notifications
You must be signed in to change notification settings - Fork 6k
planner, expr: eval readonly user var during plan phase | tidb-test=pr/2419 #54462
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
Changes from 12 commits
6ba6125
c8dc5cb
fab2e53
ae03a7a
4911a52
d92be4f
97e1a35
4e79cfb
2698c57
b5c3af9
155a816
7ed8fc9
e44a001
8aeca9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -27,6 +27,7 @@ import ( | |||||||
"github.com/pingcap/tidb/pkg/types" | ||||||||
"github.com/pingcap/tidb/pkg/util/chunk" | ||||||||
"github.com/pingcap/tidb/pkg/util/collate" | ||||||||
"github.com/pingcap/tidb/pkg/util/intest" | ||||||||
"github.com/pingcap/tidb/pkg/util/set" | ||||||||
"github.com/pingcap/tidb/pkg/util/stringutil" | ||||||||
"github.com/pingcap/tipb/go-tipb" | ||||||||
|
@@ -989,11 +990,38 @@ func BuildGetVarFunction(ctx BuildContext, expr Expression, retType *types.Field | |||||||
if builtinRetTp := f.getRetTp(); builtinRetTp.GetType() != mysql.TypeUnspecified || retType.GetType() == mysql.TypeUnspecified { | ||||||||
retType = builtinRetTp | ||||||||
} | ||||||||
return &ScalarFunction{ | ||||||||
sf := &ScalarFunction{ | ||||||||
FuncName: model.NewCIStr(ast.GetVar), | ||||||||
RetType: retType, | ||||||||
Function: f, | ||||||||
}, nil | ||||||||
} | ||||||||
return optimizeReadonlyVar(ctx, sf), nil | ||||||||
} | ||||||||
|
||||||||
// optimizeReadonlyVar tries to convert the readonly user variables to constants. | ||||||||
func optimizeReadonlyVar(ctx BuildContext, getVar *ScalarFunction) Expression { | ||||||||
arg0, isConst := getVar.GetArgs()[0].(*Constant) | ||||||||
if !isConst || arg0.DeferredExpr != nil { | ||||||||
return getVar | ||||||||
} | ||||||||
isReadonly := ctx.IsReadonlyUserVar(arg0.Value.GetString()) | ||||||||
|
isReadonly := ctx.IsReadonlyUserVar(arg0.Value.GetString()) | |
varName := arg.Value.GetString() | |
isReadonly := ctx.IsReadonlyUserVar(varName) |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d, ok := ctx.GetEvalCtx().GetUserVarsReader().GetUserVarVal(arg0.Value.GetString()) | |
d, ok := ctx.GetEvalCtx().GetUserVarsReader().GetUserVarVal(varName) |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we need a reuse here to avoid a read-only var evaluated multiple times
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -60,7 +60,11 @@ func SetParameterValuesIntoSCtx(sctx base.PlanContext, isNonPrep bool, markers [ | |||||||||||||
vars := sctx.GetSessionVars() | ||||||||||||||
vars.PlanCacheParams.Reset() | ||||||||||||||
for i, usingParam := range params { | ||||||||||||||
val, err := usingParam.Eval(sctx.GetExprCtx().GetEvalCtx(), chunk.Row{}) | ||||||||||||||
var ( | ||||||||||||||
val types.Datum | ||||||||||||||
err error | ||||||||||||||
) | ||||||||||||||
val, err = usingParam.Eval(sctx.GetExprCtx().GetEvalCtx(), chunk.Row{}) | ||||||||||||||
Comment on lines
+67
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
if err != nil { | ||||||||||||||
return err | ||||||||||||||
} | ||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,6 +132,8 @@ func Preprocess(ctx context.Context, sctx sessionctx.Context, node *resolve.Node | |
tableAliasInJoin: make([]map[string]any, 0), | ||
preprocessWith: &preprocessWith{cteCanUsed: make([]string, 0), cteBeforeOffset: make([]int, 0)}, | ||
staleReadProcessor: staleread.NewStaleReadProcessor(ctx, sctx), | ||
varsChanged: make(map[string]struct{}), | ||
varsReadonly: make(map[string]struct{}), | ||
resolveCtx: node.GetResolveContext(), | ||
} | ||
for _, optFn := range preprocessOpt { | ||
|
@@ -144,6 +146,10 @@ func Preprocess(ctx context.Context, sctx sessionctx.Context, node *resolve.Node | |
node.Node.Accept(&v) | ||
// InfoSchema must be non-nil after preprocessing | ||
v.ensureInfoSchema() | ||
sctx.GetPlanCtx().SetReadonlyUserVarMap(v.varsReadonly) | ||
if len(v.varsReadonly) > 0 { | ||
sctx.GetSessionVars().StmtCtx.SetSkipPlanCache("read-only variables are used") | ||
} | ||
return errors.Trace(v.err) | ||
} | ||
|
||
|
@@ -236,6 +242,9 @@ type preprocessor struct { | |
|
||
staleReadProcessor staleread.Processor | ||
|
||
varsChanged map[string]struct{} | ||
|
||
varsReadonly map[string]struct{} | ||
|
||
// values that may be returned | ||
*PreprocessorReturn | ||
err error | ||
|
@@ -419,6 +428,17 @@ func (p *preprocessor) Enter(in ast.Node) (out ast.Node, skipChildren bool) { | |
} | ||
case *ast.AnalyzeTableStmt: | ||
p.flag |= inAnalyze | ||
case *ast.VariableExpr: | ||
if node.Value != nil { | ||
p.varsChanged[node.Name] = struct{}{} | ||
delete(p.varsReadonly, node.Name) | ||
} else if p.stmtTp == TypeSelect { | ||
// Only check the variable in select statement. | ||
_, ok := p.varsChanged[node.Name] | ||
if !ok { | ||
p.varsReadonly[node.Name] = struct{}{} | ||
} | ||
} | ||
default: | ||
p.flag &= ^parentIsJoin | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.