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