@@ -76,12 +76,15 @@ func collectGenerateColumn(lp LogicalPlan, exprToColumn ExprColumnMap) {
76
76
}
77
77
}
78
78
79
- func tryToSubstituteExpr (expr * expression.Expression , lp LogicalPlan , candidateExpr expression.Expression , tp types.EvalType , schema * expression.Schema , col * expression.Column , opt * logicalOptimizeOp ) {
79
+ func tryToSubstituteExpr (expr * expression.Expression , lp LogicalPlan , candidateExpr expression.Expression , tp types.EvalType , schema * expression.Schema , col * expression.Column , opt * logicalOptimizeOp ) bool {
80
+ changed := false
80
81
if (* expr ).Equal (lp .SCtx (), candidateExpr ) && candidateExpr .GetType ().EvalType () == tp &&
81
82
schema .ColumnIndex (col ) != - 1 {
82
83
* expr = col
83
84
appendSubstituteColumnStep (lp , candidateExpr , col , opt )
85
+ changed = true
84
86
}
87
+ return changed
85
88
}
86
89
87
90
func appendSubstituteColumnStep (lp LogicalPlan , candidateExpr expression.Expression , col * expression.Column , opt * logicalOptimizeOp ) {
@@ -97,26 +100,38 @@ func appendSubstituteColumnStep(lp LogicalPlan, candidateExpr expression.Express
97
100
opt .appendStepToCurrent (lp .ID (), lp .TP (), reason , action )
98
101
}
99
102
100
- func substituteExpression (cond expression.Expression , lp LogicalPlan , exprToColumn ExprColumnMap , schema * expression.Schema , opt * logicalOptimizeOp ) {
103
+ // SubstituteExpression is Exported for bench
104
+ func SubstituteExpression (cond expression.Expression , lp LogicalPlan , exprToColumn ExprColumnMap , schema * expression.Schema , opt * logicalOptimizeOp ) bool {
105
+ return substituteExpression (cond , lp , exprToColumn , schema , opt )
106
+ }
107
+
108
+ func substituteExpression (cond expression.Expression , lp LogicalPlan , exprToColumn ExprColumnMap , schema * expression.Schema , opt * logicalOptimizeOp ) bool {
101
109
sf , ok := cond .(* expression.ScalarFunction )
102
110
if ! ok {
103
- return
111
+ return false
104
112
}
105
113
sctx := lp .SCtx ().GetSessionVars ().StmtCtx
114
+ changed := false
115
+ collectChanged := func (partial bool ) {
116
+ if partial && ! changed {
117
+ changed = true
118
+ }
119
+ }
106
120
defer func () {
107
121
// If the argument is not changed, hash code doesn't need to recount again.
108
- // But we always do it to keep the code simple and stupid.
109
- expression .ReHashCode (sf , sctx )
122
+ if changed {
123
+ expression .ReHashCode (sf , sctx )
124
+ }
110
125
}()
111
126
var expr * expression.Expression
112
127
var tp types.EvalType
113
128
switch sf .FuncName .L {
114
129
case ast .EQ , ast .LT , ast .LE , ast .GT , ast .GE :
115
130
for candidateExpr , column := range exprToColumn {
116
- tryToSubstituteExpr (& sf .GetArgs ()[1 ], lp , candidateExpr , sf .GetArgs ()[0 ].GetType ().EvalType (), schema , column , opt )
131
+ collectChanged ( tryToSubstituteExpr (& sf .GetArgs ()[1 ], lp , candidateExpr , sf .GetArgs ()[0 ].GetType ().EvalType (), schema , column , opt ) )
117
132
}
118
133
for candidateExpr , column := range exprToColumn {
119
- tryToSubstituteExpr (& sf .GetArgs ()[0 ], lp , candidateExpr , sf .GetArgs ()[1 ].GetType ().EvalType (), schema , column , opt )
134
+ collectChanged ( tryToSubstituteExpr (& sf .GetArgs ()[0 ], lp , candidateExpr , sf .GetArgs ()[1 ].GetType ().EvalType (), schema , column , opt ) )
120
135
}
121
136
case ast .In :
122
137
expr = & sf .GetArgs ()[0 ]
@@ -132,21 +147,22 @@ func substituteExpression(cond expression.Expression, lp LogicalPlan, exprToColu
132
147
}
133
148
if canSubstitute {
134
149
for candidateExpr , column := range exprToColumn {
135
- tryToSubstituteExpr (expr , lp , candidateExpr , tp , schema , column , opt )
150
+ collectChanged ( tryToSubstituteExpr (expr , lp , candidateExpr , tp , schema , column , opt ) )
136
151
}
137
152
}
138
153
case ast .Like :
139
154
expr = & sf .GetArgs ()[0 ]
140
155
tp = sf .GetArgs ()[1 ].GetType ().EvalType ()
141
156
for candidateExpr , column := range exprToColumn {
142
- tryToSubstituteExpr (expr , lp , candidateExpr , tp , schema , column , opt )
157
+ collectChanged ( tryToSubstituteExpr (expr , lp , candidateExpr , tp , schema , column , opt ) )
143
158
}
144
159
case ast .LogicOr , ast .LogicAnd :
145
- substituteExpression (sf .GetArgs ()[0 ], lp , exprToColumn , schema , opt )
146
- substituteExpression (sf .GetArgs ()[1 ], lp , exprToColumn , schema , opt )
160
+ collectChanged ( substituteExpression (sf .GetArgs ()[0 ], lp , exprToColumn , schema , opt ) )
161
+ collectChanged ( substituteExpression (sf .GetArgs ()[1 ], lp , exprToColumn , schema , opt ) )
147
162
case ast .UnaryNot :
148
- substituteExpression (sf .GetArgs ()[0 ], lp , exprToColumn , schema , opt )
163
+ collectChanged ( substituteExpression (sf .GetArgs ()[0 ], lp , exprToColumn , schema , opt ) )
149
164
}
165
+ return changed
150
166
}
151
167
152
168
func (gc * gcSubstituter ) substitute (ctx context.Context , lp LogicalPlan , exprToColumn ExprColumnMap , opt * logicalOptimizeOp ) LogicalPlan {
0 commit comments