github.com/influxdata/influxdb/v2@v2.7.6/influxql/query/explain.go (about) 1 package query 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "io" 8 "strings" 9 10 "github.com/influxdata/influxql" 11 ) 12 13 func (p *preparedStatement) Explain(ctx context.Context) (string, error) { 14 // Determine the cost of all iterators created as part of this plan. 15 ic := &explainIteratorCreator{ic: p.ic} 16 p.ic = ic 17 cur, err := p.Select(ctx) 18 p.ic = ic.ic 19 20 if err != nil { 21 return "", err 22 } 23 cur.Close() 24 25 var buf bytes.Buffer 26 for i, node := range ic.nodes { 27 if i > 0 { 28 buf.WriteString("\n") 29 } 30 31 expr := "<nil>" 32 if node.Expr != nil { 33 expr = node.Expr.String() 34 } 35 fmt.Fprintf(&buf, "EXPRESSION: %s\n", expr) 36 if len(node.Aux) != 0 { 37 refs := make([]string, len(node.Aux)) 38 for i, ref := range node.Aux { 39 refs[i] = ref.String() 40 } 41 fmt.Fprintf(&buf, "AUXILIARY FIELDS: %s\n", strings.Join(refs, ", ")) 42 } 43 fmt.Fprintf(&buf, "NUMBER OF SHARDS: %d\n", node.Cost.NumShards) 44 fmt.Fprintf(&buf, "NUMBER OF SERIES: %d\n", node.Cost.NumSeries) 45 fmt.Fprintf(&buf, "CACHED VALUES: %d\n", node.Cost.CachedValues) 46 fmt.Fprintf(&buf, "NUMBER OF FILES: %d\n", node.Cost.NumFiles) 47 fmt.Fprintf(&buf, "NUMBER OF BLOCKS: %d\n", node.Cost.BlocksRead) 48 fmt.Fprintf(&buf, "SIZE OF BLOCKS: %d\n", node.Cost.BlockSize) 49 } 50 return buf.String(), nil 51 } 52 53 type planNode struct { 54 Expr influxql.Expr 55 Aux []influxql.VarRef 56 Cost IteratorCost 57 } 58 59 type explainIteratorCreator struct { 60 ic interface { 61 IteratorCreator 62 io.Closer 63 } 64 nodes []planNode 65 } 66 67 func (e *explainIteratorCreator) CreateIterator(ctx context.Context, m *influxql.Measurement, opt IteratorOptions) (Iterator, error) { 68 cost, err := e.ic.IteratorCost(ctx, m, opt) 69 if err != nil { 70 return nil, err 71 } 72 e.nodes = append(e.nodes, planNode{ 73 Expr: opt.Expr, 74 Aux: opt.Aux, 75 Cost: cost, 76 }) 77 return &nilFloatIterator{}, nil 78 } 79 80 func (e *explainIteratorCreator) IteratorCost(ctx context.Context, m *influxql.Measurement, opt IteratorOptions) (IteratorCost, error) { 81 return e.ic.IteratorCost(ctx, m, opt) 82 } 83 84 func (e *explainIteratorCreator) Close() error { 85 return e.ic.Close() 86 }