vitess.io/vitess@v0.16.2/go/vt/vtgate/engine/plan.go (about) 1 /* 2 Copyright 2022 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package engine 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "sync/atomic" 23 "time" 24 25 "vitess.io/vitess/go/vt/proto/query" 26 "vitess.io/vitess/go/vt/sqlparser" 27 ) 28 29 // Plan represents the execution strategy for a given query. 30 // For now it's a simple wrapper around the real instructions. 31 // An instruction (aka Primitive) is typically a tree where 32 // each node does its part by combining the results of the 33 // sub-nodes. 34 type Plan struct { 35 Type sqlparser.StatementType // The type of query we have 36 Original string // Original is the original query. 37 Instructions Primitive // Instructions contains the instructions needed to fulfil the query. 38 BindVarNeeds *sqlparser.BindVarNeeds // Stores BindVars needed to be provided as part of expression rewriting 39 Warnings []*query.QueryWarning // Warnings that need to be yielded every time this query runs 40 TablesUsed []string // TablesUsed is the list of tables that this plan will query 41 42 ExecCount uint64 // Count of times this plan was executed 43 ExecTime uint64 // Total execution time 44 ShardQueries uint64 // Total number of shard queries 45 RowsReturned uint64 // Total number of rows 46 RowsAffected uint64 // Total number of rows 47 Errors uint64 // Total number of errors 48 } 49 50 // AddStats updates the plan execution statistics 51 func (p *Plan) AddStats(execCount uint64, execTime time.Duration, shardQueries, rowsAffected, rowsReturned, errors uint64) { 52 atomic.AddUint64(&p.ExecCount, execCount) 53 atomic.AddUint64(&p.ExecTime, uint64(execTime)) 54 atomic.AddUint64(&p.ShardQueries, shardQueries) 55 atomic.AddUint64(&p.RowsAffected, rowsAffected) 56 atomic.AddUint64(&p.RowsReturned, rowsReturned) 57 atomic.AddUint64(&p.Errors, errors) 58 } 59 60 // Stats returns a copy of the plan execution statistics 61 func (p *Plan) Stats() (execCount uint64, execTime time.Duration, shardQueries, rowsAffected, rowsReturned, errors uint64) { 62 execCount = atomic.LoadUint64(&p.ExecCount) 63 execTime = time.Duration(atomic.LoadUint64(&p.ExecTime)) 64 shardQueries = atomic.LoadUint64(&p.ShardQueries) 65 rowsAffected = atomic.LoadUint64(&p.RowsAffected) 66 rowsReturned = atomic.LoadUint64(&p.RowsReturned) 67 errors = atomic.LoadUint64(&p.Errors) 68 return 69 } 70 71 // MarshalJSON serializes the plan into a JSON representation. 72 func (p *Plan) MarshalJSON() ([]byte, error) { 73 var instructions *PrimitiveDescription 74 if p.Instructions != nil { 75 description := PrimitiveToPlanDescription(p.Instructions) 76 instructions = &description 77 } 78 79 marshalPlan := struct { 80 QueryType string 81 Original string `json:",omitempty"` 82 Instructions *PrimitiveDescription `json:",omitempty"` 83 ExecCount uint64 `json:",omitempty"` 84 ExecTime time.Duration `json:",omitempty"` 85 ShardQueries uint64 `json:",omitempty"` 86 RowsAffected uint64 `json:",omitempty"` 87 RowsReturned uint64 `json:",omitempty"` 88 Errors uint64 `json:",omitempty"` 89 TablesUsed []string `json:",omitempty"` 90 }{ 91 QueryType: p.Type.String(), 92 Original: p.Original, 93 Instructions: instructions, 94 ExecCount: atomic.LoadUint64(&p.ExecCount), 95 ExecTime: time.Duration(atomic.LoadUint64(&p.ExecTime)), 96 ShardQueries: atomic.LoadUint64(&p.ShardQueries), 97 RowsAffected: atomic.LoadUint64(&p.RowsAffected), 98 RowsReturned: atomic.LoadUint64(&p.RowsReturned), 99 Errors: atomic.LoadUint64(&p.Errors), 100 TablesUsed: p.TablesUsed, 101 } 102 103 b := new(bytes.Buffer) 104 enc := json.NewEncoder(b) 105 enc.SetEscapeHTML(false) 106 err := enc.Encode(marshalPlan) 107 if err != nil { 108 return nil, err 109 } 110 111 return b.Bytes(), nil 112 }