mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 08:02:36 +09:00 
			
		
		
		
	Integrate public as bindata optionally (#293)
* Dropped unused codekit config * Integrated dynamic and static bindata for public * Ignore public bindata * Add a general generate make task * Integrated flexible public assets into web command * Updated vendoring, added all missiong govendor deps * Made the linter happy with the bindata and dynamic code * Moved public bindata definition to modules directory * Ignoring the new bindata path now * Updated to the new public modules import path * Updated public bindata command and drop the new prefix
This commit is contained in:
		
				
					committed by
					
						
						Lunny Xiao
					
				
			
			
				
	
			
			
			
						parent
						
							4680c349dd
						
					
				
				
					commit
					b6a95a8cb3
				
			
							
								
								
									
										217
									
								
								vendor/github.com/pingcap/tidb/executor/explain.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								vendor/github.com/pingcap/tidb/executor/explain.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,217 @@
 | 
			
		||||
// Copyright 2016 PingCAP, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
package executor
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/pingcap/tidb/ast"
 | 
			
		||||
	"github.com/pingcap/tidb/optimizer/plan"
 | 
			
		||||
	"github.com/pingcap/tidb/parser/opcode"
 | 
			
		||||
	"github.com/pingcap/tidb/util/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type explainEntry struct {
 | 
			
		||||
	ID           int64
 | 
			
		||||
	selectType   string
 | 
			
		||||
	table        string
 | 
			
		||||
	joinType     string
 | 
			
		||||
	possibleKeys string
 | 
			
		||||
	key          string
 | 
			
		||||
	keyLen       string
 | 
			
		||||
	ref          string
 | 
			
		||||
	rows         int64
 | 
			
		||||
	extra        []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *explainEntry) setJoinTypeForTableScan(p *plan.TableScan) {
 | 
			
		||||
	if len(p.AccessConditions) == 0 {
 | 
			
		||||
		e.joinType = "ALL"
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if p.RefAccess {
 | 
			
		||||
		e.joinType = "eq_ref"
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	for _, con := range p.AccessConditions {
 | 
			
		||||
		if x, ok := con.(*ast.BinaryOperationExpr); ok {
 | 
			
		||||
			if x.Op == opcode.EQ {
 | 
			
		||||
				e.joinType = "const"
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	e.joinType = "range"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *explainEntry) setJoinTypeForIndexScan(p *plan.IndexScan) {
 | 
			
		||||
	if len(p.AccessConditions) == 0 {
 | 
			
		||||
		e.joinType = "index"
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if len(p.AccessConditions) == p.AccessEqualCount {
 | 
			
		||||
		if p.RefAccess {
 | 
			
		||||
			if p.Index.Unique {
 | 
			
		||||
				e.joinType = "eq_ref"
 | 
			
		||||
			} else {
 | 
			
		||||
				e.joinType = "ref"
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			if p.Index.Unique {
 | 
			
		||||
				e.joinType = "const"
 | 
			
		||||
			} else {
 | 
			
		||||
				e.joinType = "range"
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	e.joinType = "range"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExplainExec represents an explain executor.
 | 
			
		||||
// See: https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
 | 
			
		||||
type ExplainExec struct {
 | 
			
		||||
	StmtPlan plan.Plan
 | 
			
		||||
	fields   []*ast.ResultField
 | 
			
		||||
	rows     []*Row
 | 
			
		||||
	cursor   int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Fields implements Executor Fields interface.
 | 
			
		||||
func (e *ExplainExec) Fields() []*ast.ResultField {
 | 
			
		||||
	return e.fields
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Next implements Execution Next interface.
 | 
			
		||||
func (e *ExplainExec) Next() (*Row, error) {
 | 
			
		||||
	if e.rows == nil {
 | 
			
		||||
		e.fetchRows()
 | 
			
		||||
	}
 | 
			
		||||
	if e.cursor >= len(e.rows) {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	row := e.rows[e.cursor]
 | 
			
		||||
	e.cursor++
 | 
			
		||||
	return row, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *ExplainExec) fetchRows() {
 | 
			
		||||
	visitor := &explainVisitor{id: 1}
 | 
			
		||||
	e.StmtPlan.Accept(visitor)
 | 
			
		||||
	for _, entry := range visitor.entries {
 | 
			
		||||
		row := &Row{}
 | 
			
		||||
		row.Data = types.MakeDatums(
 | 
			
		||||
			entry.ID,
 | 
			
		||||
			entry.selectType,
 | 
			
		||||
			entry.table,
 | 
			
		||||
			entry.joinType,
 | 
			
		||||
			entry.key,
 | 
			
		||||
			entry.key,
 | 
			
		||||
			entry.keyLen,
 | 
			
		||||
			entry.ref,
 | 
			
		||||
			entry.rows,
 | 
			
		||||
			strings.Join(entry.extra, "; "),
 | 
			
		||||
		)
 | 
			
		||||
		for i := range row.Data {
 | 
			
		||||
			if row.Data[i].Kind() == types.KindString && row.Data[i].GetString() == "" {
 | 
			
		||||
				row.Data[i].SetNull()
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		e.rows = append(e.rows, row)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close implements Executor Close interface.
 | 
			
		||||
func (e *ExplainExec) Close() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type explainVisitor struct {
 | 
			
		||||
	id int64
 | 
			
		||||
 | 
			
		||||
	// Sort extra should be appended in the first table in a join.
 | 
			
		||||
	sort    bool
 | 
			
		||||
	entries []*explainEntry
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v *explainVisitor) Enter(p plan.Plan) (plan.Plan, bool) {
 | 
			
		||||
	switch x := p.(type) {
 | 
			
		||||
	case *plan.TableScan:
 | 
			
		||||
		v.entries = append(v.entries, v.newEntryForTableScan(x))
 | 
			
		||||
	case *plan.IndexScan:
 | 
			
		||||
		v.entries = append(v.entries, v.newEntryForIndexScan(x))
 | 
			
		||||
	case *plan.Sort:
 | 
			
		||||
		v.sort = true
 | 
			
		||||
	}
 | 
			
		||||
	return p, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v *explainVisitor) Leave(p plan.Plan) (plan.Plan, bool) {
 | 
			
		||||
	return p, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v *explainVisitor) newEntryForTableScan(p *plan.TableScan) *explainEntry {
 | 
			
		||||
	entry := &explainEntry{
 | 
			
		||||
		ID:         v.id,
 | 
			
		||||
		selectType: "SIMPLE",
 | 
			
		||||
		table:      p.Table.Name.O,
 | 
			
		||||
	}
 | 
			
		||||
	entry.setJoinTypeForTableScan(p)
 | 
			
		||||
	if entry.joinType != "ALL" {
 | 
			
		||||
		entry.key = "PRIMARY"
 | 
			
		||||
		entry.keyLen = "8"
 | 
			
		||||
	}
 | 
			
		||||
	if len(p.AccessConditions)+len(p.FilterConditions) > 0 {
 | 
			
		||||
		entry.extra = append(entry.extra, "Using where")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v.setSortExtra(entry)
 | 
			
		||||
	return entry
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v *explainVisitor) newEntryForIndexScan(p *plan.IndexScan) *explainEntry {
 | 
			
		||||
	entry := &explainEntry{
 | 
			
		||||
		ID:         v.id,
 | 
			
		||||
		selectType: "SIMPLE",
 | 
			
		||||
		table:      p.Table.Name.O,
 | 
			
		||||
		key:        p.Index.Name.O,
 | 
			
		||||
	}
 | 
			
		||||
	if len(p.AccessConditions) != 0 {
 | 
			
		||||
		keyLen := 0
 | 
			
		||||
		for i := 0; i < len(p.Index.Columns); i++ {
 | 
			
		||||
			if i < p.AccessEqualCount {
 | 
			
		||||
				keyLen += p.Index.Columns[i].Length
 | 
			
		||||
			} else if i < len(p.AccessConditions) {
 | 
			
		||||
				keyLen += p.Index.Columns[i].Length
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		entry.keyLen = strconv.Itoa(keyLen)
 | 
			
		||||
	}
 | 
			
		||||
	entry.setJoinTypeForIndexScan(p)
 | 
			
		||||
	if len(p.AccessConditions)+len(p.FilterConditions) > 0 {
 | 
			
		||||
		entry.extra = append(entry.extra, "Using where")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v.setSortExtra(entry)
 | 
			
		||||
	return entry
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v *explainVisitor) setSortExtra(entry *explainEntry) {
 | 
			
		||||
	if v.sort {
 | 
			
		||||
		entry.extra = append(entry.extra, "Using filesort")
 | 
			
		||||
		v.sort = false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user