@@ -17,6 +17,12 @@ package stmtctx_test
17
17
import (
18
18
"context"
19
19
"fmt"
20
+ << << << < HEAD
21
+ == == == =
22
+ "math/rand"
23
+ "reflect"
24
+ "sort"
25
+ >> >> >> > c34f6fc83d6 (planner : store the hints of session variable (#45814 ))
20
26
"testing"
21
27
"time"
22
28
@@ -143,3 +149,151 @@ func TestWeakConsistencyRead(t *testing.T) {
143
149
execAndCheck ("execute s" , testkit .Rows ("1 1 2" ), kv .SI )
144
150
tk .MustExec ("rollback" )
145
151
}
152
+ << << << < HEAD
153
+ == == == =
154
+
155
+ func TestMarshalSQLWarn (t * testing.T ) {
156
+ warns := []stmtctx.SQLWarn {
157
+ {
158
+ Level : stmtctx .WarnLevelError ,
159
+ Err : errors .New ("any error" ),
160
+ },
161
+ {
162
+ Level : stmtctx .WarnLevelError ,
163
+ Err : errors .Trace (errors .New ("any error" )),
164
+ },
165
+ {
166
+ Level : stmtctx .WarnLevelWarning ,
167
+ Err : variable .ErrUnknownSystemVar .GenWithStackByArgs ("unknown" ),
168
+ },
169
+ {
170
+ Level : stmtctx .WarnLevelWarning ,
171
+ Err : errors .Trace (variable .ErrUnknownSystemVar .GenWithStackByArgs ("unknown" )),
172
+ },
173
+ }
174
+
175
+ store := testkit .CreateMockStore (t )
176
+ tk := testkit .NewTestKit (t , store )
177
+ // First query can trigger loading global variables, which produces warnings.
178
+ tk .MustQuery ("select 1" )
179
+ tk .Session ().GetSessionVars ().StmtCtx .SetWarnings (warns )
180
+ rows := tk .MustQuery ("show warnings" ).Rows ()
181
+ require .Equal (t , len (warns ), len (rows ))
182
+
183
+ // The unmarshalled result doesn't need to be exactly the same with the original one.
184
+ // We only need that the results of `show warnings` are the same.
185
+ bytes , err := json .Marshal (warns )
186
+ require .NoError (t , err )
187
+ var newWarns []stmtctx.SQLWarn
188
+ err = json .Unmarshal (bytes , & newWarns )
189
+ require .NoError (t , err )
190
+ tk .Session ().GetSessionVars ().StmtCtx .SetWarnings (newWarns )
191
+ tk .MustQuery ("show warnings" ).Check (rows )
192
+ }
193
+
194
+ func TestApproxRuntimeInfo (t * testing.T ) {
195
+ var n = rand .Intn (19000 ) + 1000
196
+ var valRange = rand .Int31n (10000 ) + 1000
197
+ backoffs := []string {"tikvRPC" , "pdRPC" , "regionMiss" }
198
+ details := []* execdetails.ExecDetails {}
199
+ for i := 0 ; i < n ; i ++ {
200
+ d := & execdetails.ExecDetails {
201
+ DetailsNeedP90 : execdetails.DetailsNeedP90 {
202
+ CalleeAddress : fmt .Sprintf ("%v" , i + 1 ),
203
+ BackoffSleep : make (map [string ]time.Duration ),
204
+ BackoffTimes : make (map [string ]int ),
205
+ TimeDetail : util.TimeDetail {
206
+ ProcessTime : time .Second * time .Duration (rand .Int31n (valRange )),
207
+ WaitTime : time .Millisecond * time .Duration (rand .Int31n (valRange )),
208
+ },
209
+ },
210
+ }
211
+ details = append (details , d )
212
+ for _ , backoff := range backoffs {
213
+ d .BackoffSleep [backoff ] = time .Millisecond * 100 * time .Duration (rand .Int31n (valRange ))
214
+ d .BackoffTimes [backoff ] = rand .Intn (int (valRange ))
215
+ }
216
+ }
217
+
218
+ // Make CalleeAddress for each max value is deterministic.
219
+ details [rand .Intn (n )].DetailsNeedP90 .TimeDetail .ProcessTime = time .Second * time .Duration (valRange )
220
+ details [rand .Intn (n )].DetailsNeedP90 .TimeDetail .WaitTime = time .Millisecond * time .Duration (valRange )
221
+ for _ , backoff := range backoffs {
222
+ details [rand .Intn (n )].BackoffSleep [backoff ] = time .Millisecond * 100 * time .Duration (valRange )
223
+ }
224
+
225
+ ctx := new (stmtctx.StatementContext )
226
+ for i := 0 ; i < n ; i ++ {
227
+ ctx .MergeExecDetails (details [i ], nil )
228
+ }
229
+ d := ctx .CopTasksDetails ()
230
+
231
+ require .Equal (t , d .NumCopTasks , n )
232
+ sort .Slice (details , func (i , j int ) bool {
233
+ return details [i ].TimeDetail .ProcessTime .Nanoseconds () < details [j ].TimeDetail .ProcessTime .Nanoseconds ()
234
+ })
235
+ var timeSum time.Duration
236
+ for _ , detail := range details {
237
+ timeSum += detail .TimeDetail .ProcessTime
238
+ }
239
+ require .Equal (t , d .AvgProcessTime , timeSum / time .Duration (n ))
240
+ require .InEpsilon (t , d .P90ProcessTime .Nanoseconds (), details [n * 9 / 10 ].TimeDetail .ProcessTime .Nanoseconds (), 0.05 )
241
+ require .Equal (t , d .MaxProcessTime , details [n - 1 ].TimeDetail .ProcessTime )
242
+ require .Equal (t , d .MaxProcessAddress , details [n - 1 ].CalleeAddress )
243
+
244
+ sort .Slice (details , func (i , j int ) bool {
245
+ return details [i ].TimeDetail .WaitTime .Nanoseconds () < details [j ].TimeDetail .WaitTime .Nanoseconds ()
246
+ })
247
+ timeSum = 0
248
+ for _ , detail := range details {
249
+ timeSum += detail .TimeDetail .WaitTime
250
+ }
251
+ require .Equal (t , d .AvgWaitTime , timeSum / time .Duration (n ))
252
+ require .InEpsilon (t , d .P90WaitTime .Nanoseconds (), details [n * 9 / 10 ].TimeDetail .WaitTime .Nanoseconds (), 0.05 )
253
+ require .Equal (t , d .MaxWaitTime , details [n - 1 ].TimeDetail .WaitTime )
254
+ require .Equal (t , d .MaxWaitAddress , details [n - 1 ].CalleeAddress )
255
+
256
+ fields := d .ToZapFields ()
257
+ require .Equal (t , 9 , len (fields ))
258
+ for _ , backoff := range backoffs {
259
+ sort .Slice (details , func (i , j int ) bool {
260
+ return details [i ].BackoffSleep [backoff ].Nanoseconds () < details [j ].BackoffSleep [backoff ].Nanoseconds ()
261
+ })
262
+ timeSum = 0
263
+ var timesSum = 0
264
+ for _ , detail := range details {
265
+ timeSum += detail .BackoffSleep [backoff ]
266
+ timesSum += detail .BackoffTimes [backoff ]
267
+ }
268
+ require .Equal (t , d .MaxBackoffAddress [backoff ], details [n - 1 ].CalleeAddress )
269
+ require .Equal (t , d .MaxBackoffTime [backoff ], details [n - 1 ].BackoffSleep [backoff ])
270
+ require .InEpsilon (t , d .P90BackoffTime [backoff ], details [n * 9 / 10 ].BackoffSleep [backoff ], 0.1 )
271
+ require .Equal (t , d .AvgBackoffTime [backoff ], timeSum / time .Duration (n ))
272
+
273
+ require .Equal (t , d .TotBackoffTimes [backoff ], timesSum )
274
+ require .Equal (t , d .TotBackoffTime [backoff ], timeSum )
275
+ }
276
+ }
277
+
278
+ func TestStmtHintsClone (t * testing.T ) {
279
+ hints := stmtctx.StmtHints {}
280
+ value := reflect .ValueOf (& hints ).Elem ()
281
+ for i := 0 ; i < value .NumField (); i ++ {
282
+ field := value .Field (i )
283
+ switch field .Kind () {
284
+ case reflect .Int , reflect .Int32 , reflect .Int64 :
285
+ field .SetInt (1 )
286
+ case reflect .Uint , reflect .Uint32 , reflect .Uint64 :
287
+ field .SetUint (1 )
288
+ case reflect .Uint8 : // byte
289
+ field .SetUint (1 )
290
+ case reflect .Bool :
291
+ field .SetBool (true )
292
+ case reflect .String :
293
+ field .SetString ("test" )
294
+ default :
295
+ }
296
+ }
297
+ require .Equal (t , hints , * hints .Clone ())
298
+ }
299
+ >> >> >> > c34f6fc83d6 (planner : store the hints of session variable (#45814 ))
0 commit comments