forked from forgejo/forgejo
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:
parent
4680c349dd
commit
b6a95a8cb3
691 changed files with 305318 additions and 1272 deletions
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
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue