github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/interlock/explain.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package interlock 15 16 import ( 17 "context" 18 19 "github.com/cznic/mathutil" 20 "github.com/whtcorpsinc/errors" 21 "github.com/whtcorpsinc/milevadb/causet/embedded" 22 "github.com/whtcorpsinc/milevadb/soliton/chunk" 23 ) 24 25 // ExplainInterDirc represents an explain interlock. 26 type ExplainInterDirc struct { 27 baseInterlockingDirectorate 28 29 explain *embedded.Explain 30 analyzeInterDirc InterlockingDirectorate 31 rows [][]string 32 cursor int 33 } 34 35 // Open implements the InterlockingDirectorate Open interface. 36 func (e *ExplainInterDirc) Open(ctx context.Context) error { 37 if e.analyzeInterDirc != nil { 38 return e.analyzeInterDirc.Open(ctx) 39 } 40 return nil 41 } 42 43 // Close implements the InterlockingDirectorate Close interface. 44 func (e *ExplainInterDirc) Close() error { 45 e.rows = nil 46 return nil 47 } 48 49 // Next implements the InterlockingDirectorate Next interface. 50 func (e *ExplainInterDirc) Next(ctx context.Context, req *chunk.Chunk) error { 51 if e.rows == nil { 52 var err error 53 e.rows, err = e.generateExplainInfo(ctx) 54 if err != nil { 55 return err 56 } 57 } 58 59 req.GrowAndReset(e.maxChunkSize) 60 if e.cursor >= len(e.rows) { 61 return nil 62 } 63 64 numCurEvents := mathutil.Min(req.Capacity(), len(e.rows)-e.cursor) 65 for i := e.cursor; i < e.cursor+numCurEvents; i++ { 66 for j := range e.rows[i] { 67 req.AppendString(j, e.rows[i][j]) 68 } 69 } 70 e.cursor += numCurEvents 71 return nil 72 } 73 74 func (e *ExplainInterDirc) generateExplainInfo(ctx context.Context) (rows [][]string, err error) { 75 closed := false 76 defer func() { 77 if !closed && e.analyzeInterDirc != nil { 78 err = e.analyzeInterDirc.Close() 79 closed = true 80 } 81 }() 82 if e.analyzeInterDirc != nil { 83 chk := newFirstChunk(e.analyzeInterDirc) 84 var nextErr, closeErr error 85 for { 86 nextErr = Next(ctx, e.analyzeInterDirc, chk) 87 if nextErr != nil || chk.NumEvents() == 0 { 88 break 89 } 90 } 91 closeErr = e.analyzeInterDirc.Close() 92 closed = true 93 if nextErr != nil { 94 if closeErr != nil { 95 err = errors.New(nextErr.Error() + ", " + closeErr.Error()) 96 } else { 97 err = nextErr 98 } 99 } else if closeErr != nil { 100 err = closeErr 101 } 102 if err != nil { 103 return nil, err 104 } 105 } 106 if err = e.explain.RenderResult(); err != nil { 107 return nil, err 108 } 109 if e.analyzeInterDirc != nil { 110 e.ctx.GetStochastikVars().StmtCtx.RuntimeStatsDefCausl = nil 111 } 112 return e.explain.Events, nil 113 }