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
189
vendor/github.com/pingcap/tidb/ast/ast.go
generated
vendored
Normal file
189
vendor/github.com/pingcap/tidb/ast/ast.go
generated
vendored
Normal file
|
@ -0,0 +1,189 @@
|
|||
// Copyright 2015 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 ast is the abstract syntax tree parsed from a SQL statement by parser.
|
||||
// It can be analysed and transformed by optimizer.
|
||||
package ast
|
||||
|
||||
import (
|
||||
"github.com/pingcap/tidb/context"
|
||||
"github.com/pingcap/tidb/model"
|
||||
"github.com/pingcap/tidb/util/types"
|
||||
)
|
||||
|
||||
// Node is the basic element of the AST.
|
||||
// Interfaces embed Node should have 'Node' name suffix.
|
||||
type Node interface {
|
||||
// Accept accepts Visitor to visit itself.
|
||||
// The returned node should replace original node.
|
||||
// ok returns false to stop visiting.
|
||||
//
|
||||
// Implementation of this method should first call visitor.Enter,
|
||||
// assign the returned node to its method receiver, if skipChildren returns true,
|
||||
// children should be skipped. Otherwise, call its children in particular order that
|
||||
// later elements depends on former elements. Finally, return visitor.Leave.
|
||||
Accept(v Visitor) (node Node, ok bool)
|
||||
// Text returns the original text of the element.
|
||||
Text() string
|
||||
// SetText sets original text to the Node.
|
||||
SetText(text string)
|
||||
}
|
||||
|
||||
// Flags indicates whether an expression contains certain types of expression.
|
||||
const (
|
||||
FlagConstant uint64 = 0
|
||||
FlagHasParamMarker uint64 = 1 << iota
|
||||
FlagHasFunc
|
||||
FlagHasReference
|
||||
FlagHasAggregateFunc
|
||||
FlagHasSubquery
|
||||
FlagHasVariable
|
||||
FlagHasDefault
|
||||
)
|
||||
|
||||
// ExprNode is a node that can be evaluated.
|
||||
// Name of implementations should have 'Expr' suffix.
|
||||
type ExprNode interface {
|
||||
// Node is embeded in ExprNode.
|
||||
Node
|
||||
// SetType sets evaluation type to the expression.
|
||||
SetType(tp *types.FieldType)
|
||||
// GetType gets the evaluation type of the expression.
|
||||
GetType() *types.FieldType
|
||||
// SetValue sets value to the expression.
|
||||
SetValue(val interface{})
|
||||
// GetValue gets value of the expression.
|
||||
GetValue() interface{}
|
||||
// SetDatum sets datum to the expression.
|
||||
SetDatum(datum types.Datum)
|
||||
// GetDatum gets datum of the expression.
|
||||
GetDatum() *types.Datum
|
||||
// SetFlag sets flag to the expression.
|
||||
// Flag indicates whether the expression contains
|
||||
// parameter marker, reference, aggregate function...
|
||||
SetFlag(flag uint64)
|
||||
// GetFlag returns the flag of the expression.
|
||||
GetFlag() uint64
|
||||
}
|
||||
|
||||
// FuncNode represents function call expression node.
|
||||
type FuncNode interface {
|
||||
ExprNode
|
||||
functionExpression()
|
||||
}
|
||||
|
||||
// StmtNode represents statement node.
|
||||
// Name of implementations should have 'Stmt' suffix.
|
||||
type StmtNode interface {
|
||||
Node
|
||||
statement()
|
||||
}
|
||||
|
||||
// DDLNode represents DDL statement node.
|
||||
type DDLNode interface {
|
||||
StmtNode
|
||||
ddlStatement()
|
||||
}
|
||||
|
||||
// DMLNode represents DML statement node.
|
||||
type DMLNode interface {
|
||||
StmtNode
|
||||
dmlStatement()
|
||||
}
|
||||
|
||||
// ResultField represents a result field which can be a column from a table,
|
||||
// or an expression in select field. It is a generated property during
|
||||
// binding process. ResultField is the key element to evaluate a ColumnNameExpr.
|
||||
// After resolving process, every ColumnNameExpr will be resolved to a ResultField.
|
||||
// During execution, every row retrieved from table will set the row value to
|
||||
// ResultFields of that table, so ColumnNameExpr resolved to that ResultField can be
|
||||
// easily evaluated.
|
||||
type ResultField struct {
|
||||
Column *model.ColumnInfo
|
||||
ColumnAsName model.CIStr
|
||||
Table *model.TableInfo
|
||||
TableAsName model.CIStr
|
||||
DBName model.CIStr
|
||||
|
||||
// The expression for the result field. If it is generated from a select field, it would
|
||||
// be the expression of that select field, otherwise the type would be ValueExpr and value
|
||||
// will be set for every retrieved row.
|
||||
Expr ExprNode
|
||||
TableName *TableName
|
||||
}
|
||||
|
||||
// Row represents a single row from Recordset.
|
||||
type Row struct {
|
||||
Data []types.Datum
|
||||
}
|
||||
|
||||
// RecordSet is an abstract result set interface to help get data from Plan.
|
||||
type RecordSet interface {
|
||||
|
||||
// Fields gets result fields.
|
||||
Fields() (fields []*ResultField, err error)
|
||||
|
||||
// Next returns the next row, nil row means there is no more to return.
|
||||
Next() (row *Row, err error)
|
||||
|
||||
// Close closes the underlying iterator, call Next after Close will
|
||||
// restart the iteration.
|
||||
Close() error
|
||||
}
|
||||
|
||||
// ResultSetNode interface has ResultFields property which is computed and set by
|
||||
// optimizer.InfoBinder during binding process. Implementations include SelectStmt,
|
||||
// SubqueryExpr, TableSource, TableName and Join.
|
||||
type ResultSetNode interface {
|
||||
Node
|
||||
// GetResultFields gets result fields of the result set node.
|
||||
GetResultFields() []*ResultField
|
||||
// SetResultFields sets result fields of the result set node.
|
||||
SetResultFields(fields []*ResultField)
|
||||
}
|
||||
|
||||
// Statement is an interface for SQL execution.
|
||||
// NOTE: all Statement implementations must be safe for
|
||||
// concurrent using by multiple goroutines.
|
||||
// If the Exec method requires any Execution domain local data,
|
||||
// they must be held out of the implementing instance.
|
||||
type Statement interface {
|
||||
// Explain gets the execution plans.
|
||||
//Explain(ctx context.Context, w format.Formatter)
|
||||
|
||||
// IsDDL shows whether the statement is an DDL operation.
|
||||
IsDDL() bool
|
||||
|
||||
// OriginText gets the origin SQL text.
|
||||
OriginText() string
|
||||
|
||||
// SetText sets the executive SQL text.
|
||||
SetText(text string)
|
||||
|
||||
// Exec executes SQL and gets a Recordset.
|
||||
Exec(ctx context.Context) (RecordSet, error)
|
||||
}
|
||||
|
||||
// Visitor visits a Node.
|
||||
type Visitor interface {
|
||||
// Enter is called before children nodes are visited.
|
||||
// The returned node must be the same type as the input node n.
|
||||
// skipChildren returns true means children nodes should be skipped,
|
||||
// this is useful when work is done in Enter and there is no need to visit children.
|
||||
Enter(n Node) (node Node, skipChildren bool)
|
||||
// Leave is called after children nodes have been visited.
|
||||
// The returned node's type can be different from the input node if it is a ExprNode,
|
||||
// Non-expression node must be the same type as the input node n.
|
||||
// ok returns false to stop visiting.
|
||||
Leave(n Node) (node Node, ok bool)
|
||||
}
|
119
vendor/github.com/pingcap/tidb/ast/base.go
generated
vendored
Normal file
119
vendor/github.com/pingcap/tidb/ast/base.go
generated
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
// Copyright 2015 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 ast
|
||||
|
||||
import "github.com/pingcap/tidb/util/types"
|
||||
|
||||
// node is the struct implements node interface except for Accept method.
|
||||
// Node implementations should embed it in.
|
||||
type node struct {
|
||||
text string
|
||||
}
|
||||
|
||||
// SetText implements Node interface.
|
||||
func (n *node) SetText(text string) {
|
||||
n.text = text
|
||||
}
|
||||
|
||||
// Text implements Node interface.
|
||||
func (n *node) Text() string {
|
||||
return n.text
|
||||
}
|
||||
|
||||
// stmtNode implements StmtNode interface.
|
||||
// Statement implementations should embed it in.
|
||||
type stmtNode struct {
|
||||
node
|
||||
}
|
||||
|
||||
// statement implements StmtNode interface.
|
||||
func (sn *stmtNode) statement() {}
|
||||
|
||||
// ddlNode implements DDLNode interface.
|
||||
// DDL implementations should embed it in.
|
||||
type ddlNode struct {
|
||||
stmtNode
|
||||
}
|
||||
|
||||
// ddlStatement implements DDLNode interface.
|
||||
func (dn *ddlNode) ddlStatement() {}
|
||||
|
||||
// dmlNode is the struct implements DMLNode interface.
|
||||
// DML implementations should embed it in.
|
||||
type dmlNode struct {
|
||||
stmtNode
|
||||
}
|
||||
|
||||
// dmlStatement implements DMLNode interface.
|
||||
func (dn *dmlNode) dmlStatement() {}
|
||||
|
||||
// expressionNode is the struct implements Expression interface.
|
||||
// Expression implementations should embed it in.
|
||||
type exprNode struct {
|
||||
node
|
||||
types.Datum
|
||||
Type *types.FieldType
|
||||
flag uint64
|
||||
}
|
||||
|
||||
// SetDatum implements Expression interface.
|
||||
func (en *exprNode) SetDatum(datum types.Datum) {
|
||||
en.Datum = datum
|
||||
}
|
||||
|
||||
// GetDatum implements Expression interface.
|
||||
func (en *exprNode) GetDatum() *types.Datum {
|
||||
return &en.Datum
|
||||
}
|
||||
|
||||
// SetType implements Expression interface.
|
||||
func (en *exprNode) SetType(tp *types.FieldType) {
|
||||
en.Type = tp
|
||||
}
|
||||
|
||||
// GetType implements Expression interface.
|
||||
func (en *exprNode) GetType() *types.FieldType {
|
||||
return en.Type
|
||||
}
|
||||
|
||||
// SetFlag implements Expression interface.
|
||||
func (en *exprNode) SetFlag(flag uint64) {
|
||||
en.flag = flag
|
||||
}
|
||||
|
||||
// GetFlag implements Expression interface.
|
||||
func (en *exprNode) GetFlag() uint64 {
|
||||
return en.flag
|
||||
}
|
||||
|
||||
type funcNode struct {
|
||||
exprNode
|
||||
}
|
||||
|
||||
// FunctionExpression implements FounctionNode interface.
|
||||
func (fn *funcNode) functionExpression() {}
|
||||
|
||||
type resultSetNode struct {
|
||||
resultFields []*ResultField
|
||||
}
|
||||
|
||||
// GetResultFields implements ResultSetNode interface.
|
||||
func (rs *resultSetNode) GetResultFields() []*ResultField {
|
||||
return rs.resultFields
|
||||
}
|
||||
|
||||
// GetResultFields implements ResultSetNode interface.
|
||||
func (rs *resultSetNode) SetResultFields(rfs []*ResultField) {
|
||||
rs.resultFields = rfs
|
||||
}
|
170
vendor/github.com/pingcap/tidb/ast/cloner.go
generated
vendored
Normal file
170
vendor/github.com/pingcap/tidb/ast/cloner.go
generated
vendored
Normal file
|
@ -0,0 +1,170 @@
|
|||
// Copyright 2015 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 ast
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Cloner is an ast visitor that clones a node.
|
||||
type Cloner struct {
|
||||
}
|
||||
|
||||
// Enter implements Visitor Enter interface.
|
||||
func (c *Cloner) Enter(node Node) (Node, bool) {
|
||||
return copyStruct(node), false
|
||||
}
|
||||
|
||||
// Leave implements Visitor Leave interface.
|
||||
func (c *Cloner) Leave(in Node) (out Node, ok bool) {
|
||||
return in, true
|
||||
}
|
||||
|
||||
// copyStruct copies a node's struct value, if the struct has slice member,
|
||||
// make a new slice and copy old slice value to new slice.
|
||||
func copyStruct(in Node) (out Node) {
|
||||
switch v := in.(type) {
|
||||
case *ValueExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *BetweenExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *BinaryOperationExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *WhenClause:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *CaseExpr:
|
||||
nv := *v
|
||||
nv.WhenClauses = make([]*WhenClause, len(v.WhenClauses))
|
||||
copy(nv.WhenClauses, v.WhenClauses)
|
||||
out = &nv
|
||||
case *SubqueryExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *CompareSubqueryExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *ColumnName:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *ColumnNameExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *DefaultExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *ExistsSubqueryExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *PatternInExpr:
|
||||
nv := *v
|
||||
nv.List = make([]ExprNode, len(v.List))
|
||||
copy(nv.List, v.List)
|
||||
out = &nv
|
||||
case *IsNullExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *IsTruthExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *PatternLikeExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *ParamMarkerExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *ParenthesesExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *PositionExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *PatternRegexpExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *RowExpr:
|
||||
nv := *v
|
||||
nv.Values = make([]ExprNode, len(v.Values))
|
||||
copy(nv.Values, v.Values)
|
||||
out = &nv
|
||||
case *UnaryOperationExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *ValuesExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *VariableExpr:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *Join:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *TableName:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *TableSource:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *OnCondition:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *WildCardField:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *SelectField:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *FieldList:
|
||||
nv := *v
|
||||
nv.Fields = make([]*SelectField, len(v.Fields))
|
||||
copy(nv.Fields, v.Fields)
|
||||
out = &nv
|
||||
case *TableRefsClause:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *ByItem:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *GroupByClause:
|
||||
nv := *v
|
||||
nv.Items = make([]*ByItem, len(v.Items))
|
||||
copy(nv.Items, v.Items)
|
||||
out = &nv
|
||||
case *HavingClause:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *OrderByClause:
|
||||
nv := *v
|
||||
nv.Items = make([]*ByItem, len(v.Items))
|
||||
copy(nv.Items, v.Items)
|
||||
out = &nv
|
||||
case *SelectStmt:
|
||||
nv := *v
|
||||
out = &nv
|
||||
case *UnionSelectList:
|
||||
nv := *v
|
||||
nv.Selects = make([]*SelectStmt, len(v.Selects))
|
||||
copy(nv.Selects, v.Selects)
|
||||
out = &nv
|
||||
case *UnionStmt:
|
||||
nv := *v
|
||||
out = &nv
|
||||
default:
|
||||
// We currently only handle expression and select statement.
|
||||
// Will add more when we need to.
|
||||
panic("unknown ast Node type " + fmt.Sprintf("%T", v))
|
||||
}
|
||||
return
|
||||
}
|
641
vendor/github.com/pingcap/tidb/ast/ddl.go
generated
vendored
Normal file
641
vendor/github.com/pingcap/tidb/ast/ddl.go
generated
vendored
Normal file
|
@ -0,0 +1,641 @@
|
|||
// Copyright 2015 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 ast
|
||||
|
||||
import (
|
||||
"github.com/pingcap/tidb/model"
|
||||
"github.com/pingcap/tidb/util/types"
|
||||
)
|
||||
|
||||
var (
|
||||
_ DDLNode = &AlterTableStmt{}
|
||||
_ DDLNode = &CreateDatabaseStmt{}
|
||||
_ DDLNode = &CreateIndexStmt{}
|
||||
_ DDLNode = &CreateTableStmt{}
|
||||
_ DDLNode = &DropDatabaseStmt{}
|
||||
_ DDLNode = &DropIndexStmt{}
|
||||
_ DDLNode = &DropTableStmt{}
|
||||
_ DDLNode = &TruncateTableStmt{}
|
||||
|
||||
_ Node = &AlterTableSpec{}
|
||||
_ Node = &ColumnDef{}
|
||||
_ Node = &ColumnOption{}
|
||||
_ Node = &ColumnPosition{}
|
||||
_ Node = &Constraint{}
|
||||
_ Node = &IndexColName{}
|
||||
_ Node = &ReferenceDef{}
|
||||
)
|
||||
|
||||
// CharsetOpt is used for parsing charset option from SQL.
|
||||
type CharsetOpt struct {
|
||||
Chs string
|
||||
Col string
|
||||
}
|
||||
|
||||
// DatabaseOptionType is the type for database options.
|
||||
type DatabaseOptionType int
|
||||
|
||||
// Database option types.
|
||||
const (
|
||||
DatabaseOptionNone DatabaseOptionType = iota
|
||||
DatabaseOptionCharset
|
||||
DatabaseOptionCollate
|
||||
)
|
||||
|
||||
// DatabaseOption represents database option.
|
||||
type DatabaseOption struct {
|
||||
Tp DatabaseOptionType
|
||||
Value string
|
||||
}
|
||||
|
||||
// CreateDatabaseStmt is a statement to create a database.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/create-database.html
|
||||
type CreateDatabaseStmt struct {
|
||||
ddlNode
|
||||
|
||||
IfNotExists bool
|
||||
Name string
|
||||
Options []*DatabaseOption
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *CreateDatabaseStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*CreateDatabaseStmt)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// DropDatabaseStmt is a statement to drop a database and all tables in the database.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/drop-database.html
|
||||
type DropDatabaseStmt struct {
|
||||
ddlNode
|
||||
|
||||
IfExists bool
|
||||
Name string
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *DropDatabaseStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*DropDatabaseStmt)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// IndexColName is used for parsing index column name from SQL.
|
||||
type IndexColName struct {
|
||||
node
|
||||
|
||||
Column *ColumnName
|
||||
Length int
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *IndexColName) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*IndexColName)
|
||||
node, ok := n.Column.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Column = node.(*ColumnName)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ReferenceDef is used for parsing foreign key reference option from SQL.
|
||||
// See: http://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html
|
||||
type ReferenceDef struct {
|
||||
node
|
||||
|
||||
Table *TableName
|
||||
IndexColNames []*IndexColName
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ReferenceDef) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ReferenceDef)
|
||||
node, ok := n.Table.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Table = node.(*TableName)
|
||||
for i, val := range n.IndexColNames {
|
||||
node, ok = val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.IndexColNames[i] = node.(*IndexColName)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ColumnOptionType is the type for ColumnOption.
|
||||
type ColumnOptionType int
|
||||
|
||||
// ColumnOption types.
|
||||
const (
|
||||
ColumnOptionNoOption ColumnOptionType = iota
|
||||
ColumnOptionPrimaryKey
|
||||
ColumnOptionNotNull
|
||||
ColumnOptionAutoIncrement
|
||||
ColumnOptionDefaultValue
|
||||
ColumnOptionUniq
|
||||
ColumnOptionIndex
|
||||
ColumnOptionUniqIndex
|
||||
ColumnOptionKey
|
||||
ColumnOptionUniqKey
|
||||
ColumnOptionNull
|
||||
ColumnOptionOnUpdate // For Timestamp and Datetime only.
|
||||
ColumnOptionFulltext
|
||||
ColumnOptionComment
|
||||
)
|
||||
|
||||
// ColumnOption is used for parsing column constraint info from SQL.
|
||||
type ColumnOption struct {
|
||||
node
|
||||
|
||||
Tp ColumnOptionType
|
||||
// The value For Default or On Update.
|
||||
Expr ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ColumnOption) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ColumnOption)
|
||||
if n.Expr != nil {
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// IndexOption is the index options.
|
||||
// KEY_BLOCK_SIZE [=] value
|
||||
// | index_type
|
||||
// | WITH PARSER parser_name
|
||||
// | COMMENT 'string'
|
||||
// See: http://dev.mysql.com/doc/refman/5.7/en/create-table.html
|
||||
type IndexOption struct {
|
||||
node
|
||||
|
||||
KeyBlockSize uint64
|
||||
Tp model.IndexType
|
||||
Comment string
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *IndexOption) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*IndexOption)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ConstraintType is the type for Constraint.
|
||||
type ConstraintType int
|
||||
|
||||
// ConstraintTypes
|
||||
const (
|
||||
ConstraintNoConstraint ConstraintType = iota
|
||||
ConstraintPrimaryKey
|
||||
ConstraintKey
|
||||
ConstraintIndex
|
||||
ConstraintUniq
|
||||
ConstraintUniqKey
|
||||
ConstraintUniqIndex
|
||||
ConstraintForeignKey
|
||||
ConstraintFulltext
|
||||
)
|
||||
|
||||
// Constraint is constraint for table definition.
|
||||
type Constraint struct {
|
||||
node
|
||||
|
||||
Tp ConstraintType
|
||||
Name string
|
||||
|
||||
// Used for PRIMARY KEY, UNIQUE, ......
|
||||
Keys []*IndexColName
|
||||
|
||||
// Used for foreign key.
|
||||
Refer *ReferenceDef
|
||||
|
||||
// Index Options
|
||||
Option *IndexOption
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *Constraint) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*Constraint)
|
||||
for i, val := range n.Keys {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Keys[i] = node.(*IndexColName)
|
||||
}
|
||||
if n.Refer != nil {
|
||||
node, ok := n.Refer.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Refer = node.(*ReferenceDef)
|
||||
}
|
||||
if n.Option != nil {
|
||||
node, ok := n.Option.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Option = node.(*IndexOption)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ColumnDef is used for parsing column definition from SQL.
|
||||
type ColumnDef struct {
|
||||
node
|
||||
|
||||
Name *ColumnName
|
||||
Tp *types.FieldType
|
||||
Options []*ColumnOption
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ColumnDef) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ColumnDef)
|
||||
node, ok := n.Name.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Name = node.(*ColumnName)
|
||||
for i, val := range n.Options {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Options[i] = node.(*ColumnOption)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// CreateTableStmt is a statement to create a table.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/create-table.html
|
||||
type CreateTableStmt struct {
|
||||
ddlNode
|
||||
|
||||
IfNotExists bool
|
||||
Table *TableName
|
||||
Cols []*ColumnDef
|
||||
Constraints []*Constraint
|
||||
Options []*TableOption
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *CreateTableStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*CreateTableStmt)
|
||||
node, ok := n.Table.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Table = node.(*TableName)
|
||||
for i, val := range n.Cols {
|
||||
node, ok = val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Cols[i] = node.(*ColumnDef)
|
||||
}
|
||||
for i, val := range n.Constraints {
|
||||
node, ok = val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Constraints[i] = node.(*Constraint)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// DropTableStmt is a statement to drop one or more tables.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/drop-table.html
|
||||
type DropTableStmt struct {
|
||||
ddlNode
|
||||
|
||||
IfExists bool
|
||||
Tables []*TableName
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *DropTableStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*DropTableStmt)
|
||||
for i, val := range n.Tables {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Tables[i] = node.(*TableName)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// CreateIndexStmt is a statement to create an index.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/create-index.html
|
||||
type CreateIndexStmt struct {
|
||||
ddlNode
|
||||
|
||||
IndexName string
|
||||
Table *TableName
|
||||
Unique bool
|
||||
IndexColNames []*IndexColName
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *CreateIndexStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*CreateIndexStmt)
|
||||
node, ok := n.Table.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Table = node.(*TableName)
|
||||
for i, val := range n.IndexColNames {
|
||||
node, ok = val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.IndexColNames[i] = node.(*IndexColName)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// DropIndexStmt is a statement to drop the index.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/drop-index.html
|
||||
type DropIndexStmt struct {
|
||||
ddlNode
|
||||
|
||||
IfExists bool
|
||||
IndexName string
|
||||
Table *TableName
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *DropIndexStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*DropIndexStmt)
|
||||
node, ok := n.Table.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Table = node.(*TableName)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// TableOptionType is the type for TableOption
|
||||
type TableOptionType int
|
||||
|
||||
// TableOption types.
|
||||
const (
|
||||
TableOptionNone TableOptionType = iota
|
||||
TableOptionEngine
|
||||
TableOptionCharset
|
||||
TableOptionCollate
|
||||
TableOptionAutoIncrement
|
||||
TableOptionComment
|
||||
TableOptionAvgRowLength
|
||||
TableOptionCheckSum
|
||||
TableOptionCompression
|
||||
TableOptionConnection
|
||||
TableOptionPassword
|
||||
TableOptionKeyBlockSize
|
||||
TableOptionMaxRows
|
||||
TableOptionMinRows
|
||||
TableOptionDelayKeyWrite
|
||||
TableOptionRowFormat
|
||||
)
|
||||
|
||||
// RowFormat types
|
||||
const (
|
||||
RowFormatDefault uint64 = iota + 1
|
||||
RowFormatDynamic
|
||||
RowFormatFixed
|
||||
RowFormatCompressed
|
||||
RowFormatRedundant
|
||||
RowFormatCompact
|
||||
)
|
||||
|
||||
// TableOption is used for parsing table option from SQL.
|
||||
type TableOption struct {
|
||||
Tp TableOptionType
|
||||
StrValue string
|
||||
UintValue uint64
|
||||
}
|
||||
|
||||
// ColumnPositionType is the type for ColumnPosition.
|
||||
type ColumnPositionType int
|
||||
|
||||
// ColumnPosition Types
|
||||
const (
|
||||
ColumnPositionNone ColumnPositionType = iota
|
||||
ColumnPositionFirst
|
||||
ColumnPositionAfter
|
||||
)
|
||||
|
||||
// ColumnPosition represent the position of the newly added column
|
||||
type ColumnPosition struct {
|
||||
node
|
||||
// ColumnPositionNone | ColumnPositionFirst | ColumnPositionAfter
|
||||
Tp ColumnPositionType
|
||||
// RelativeColumn is the column the newly added column after if type is ColumnPositionAfter
|
||||
RelativeColumn *ColumnName
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ColumnPosition) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ColumnPosition)
|
||||
if n.RelativeColumn != nil {
|
||||
node, ok := n.RelativeColumn.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.RelativeColumn = node.(*ColumnName)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// AlterTableType is the type for AlterTableSpec.
|
||||
type AlterTableType int
|
||||
|
||||
// AlterTable types.
|
||||
const (
|
||||
AlterTableOption AlterTableType = iota + 1
|
||||
AlterTableAddColumn
|
||||
AlterTableAddConstraint
|
||||
AlterTableDropColumn
|
||||
AlterTableDropPrimaryKey
|
||||
AlterTableDropIndex
|
||||
AlterTableDropForeignKey
|
||||
|
||||
// TODO: Add more actions
|
||||
)
|
||||
|
||||
// AlterTableSpec represents alter table specification.
|
||||
type AlterTableSpec struct {
|
||||
node
|
||||
|
||||
Tp AlterTableType
|
||||
Name string
|
||||
Constraint *Constraint
|
||||
Options []*TableOption
|
||||
Column *ColumnDef
|
||||
DropColumn *ColumnName
|
||||
Position *ColumnPosition
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *AlterTableSpec) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*AlterTableSpec)
|
||||
if n.Constraint != nil {
|
||||
node, ok := n.Constraint.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Constraint = node.(*Constraint)
|
||||
}
|
||||
if n.Column != nil {
|
||||
node, ok := n.Column.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Column = node.(*ColumnDef)
|
||||
}
|
||||
if n.DropColumn != nil {
|
||||
node, ok := n.DropColumn.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.DropColumn = node.(*ColumnName)
|
||||
}
|
||||
if n.Position != nil {
|
||||
node, ok := n.Position.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Position = node.(*ColumnPosition)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// AlterTableStmt is a statement to change the structure of a table.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/alter-table.html
|
||||
type AlterTableStmt struct {
|
||||
ddlNode
|
||||
|
||||
Table *TableName
|
||||
Specs []*AlterTableSpec
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *AlterTableStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*AlterTableStmt)
|
||||
node, ok := n.Table.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Table = node.(*TableName)
|
||||
for i, val := range n.Specs {
|
||||
node, ok = val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Specs[i] = node.(*AlterTableSpec)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// TruncateTableStmt is a statement to empty a table completely.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/truncate-table.html
|
||||
type TruncateTableStmt struct {
|
||||
ddlNode
|
||||
|
||||
Table *TableName
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *TruncateTableStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*TruncateTableStmt)
|
||||
node, ok := n.Table.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Table = node.(*TableName)
|
||||
return v.Leave(n)
|
||||
}
|
891
vendor/github.com/pingcap/tidb/ast/dml.go
generated
vendored
Normal file
891
vendor/github.com/pingcap/tidb/ast/dml.go
generated
vendored
Normal file
|
@ -0,0 +1,891 @@
|
|||
// Copyright 2015 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 ast
|
||||
|
||||
import (
|
||||
"github.com/pingcap/tidb/model"
|
||||
)
|
||||
|
||||
var (
|
||||
_ DMLNode = &DeleteStmt{}
|
||||
_ DMLNode = &InsertStmt{}
|
||||
_ DMLNode = &UnionStmt{}
|
||||
_ DMLNode = &UpdateStmt{}
|
||||
_ DMLNode = &SelectStmt{}
|
||||
_ DMLNode = &ShowStmt{}
|
||||
|
||||
_ Node = &Assignment{}
|
||||
_ Node = &ByItem{}
|
||||
_ Node = &FieldList{}
|
||||
_ Node = &GroupByClause{}
|
||||
_ Node = &HavingClause{}
|
||||
_ Node = &Join{}
|
||||
_ Node = &Limit{}
|
||||
_ Node = &OnCondition{}
|
||||
_ Node = &OrderByClause{}
|
||||
_ Node = &SelectField{}
|
||||
_ Node = &TableName{}
|
||||
_ Node = &TableRefsClause{}
|
||||
_ Node = &TableSource{}
|
||||
_ Node = &UnionSelectList{}
|
||||
_ Node = &WildCardField{}
|
||||
)
|
||||
|
||||
// JoinType is join type, including cross/left/right/full.
|
||||
type JoinType int
|
||||
|
||||
const (
|
||||
// CrossJoin is cross join type.
|
||||
CrossJoin JoinType = iota + 1
|
||||
// LeftJoin is left Join type.
|
||||
LeftJoin
|
||||
// RightJoin is right Join type.
|
||||
RightJoin
|
||||
)
|
||||
|
||||
// Join represents table join.
|
||||
type Join struct {
|
||||
node
|
||||
resultSetNode
|
||||
|
||||
// Left table can be TableSource or JoinNode.
|
||||
Left ResultSetNode
|
||||
// Right table can be TableSource or JoinNode or nil.
|
||||
Right ResultSetNode
|
||||
// Tp represents join type.
|
||||
Tp JoinType
|
||||
// On represents join on condition.
|
||||
On *OnCondition
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *Join) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*Join)
|
||||
node, ok := n.Left.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Left = node.(ResultSetNode)
|
||||
if n.Right != nil {
|
||||
node, ok = n.Right.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Right = node.(ResultSetNode)
|
||||
}
|
||||
if n.On != nil {
|
||||
node, ok = n.On.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.On = node.(*OnCondition)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// TableName represents a table name.
|
||||
type TableName struct {
|
||||
node
|
||||
resultSetNode
|
||||
|
||||
Schema model.CIStr
|
||||
Name model.CIStr
|
||||
|
||||
DBInfo *model.DBInfo
|
||||
TableInfo *model.TableInfo
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *TableName) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*TableName)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// DeleteTableList is the tablelist used in delete statement multi-table mode.
|
||||
type DeleteTableList struct {
|
||||
node
|
||||
Tables []*TableName
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *DeleteTableList) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*DeleteTableList)
|
||||
if n != nil {
|
||||
for i, t := range n.Tables {
|
||||
node, ok := t.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Tables[i] = node.(*TableName)
|
||||
}
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// OnCondition represetns JOIN on condition.
|
||||
type OnCondition struct {
|
||||
node
|
||||
|
||||
Expr ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *OnCondition) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*OnCondition)
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// TableSource represents table source with a name.
|
||||
type TableSource struct {
|
||||
node
|
||||
|
||||
// Source is the source of the data, can be a TableName,
|
||||
// a SelectStmt, a UnionStmt, or a JoinNode.
|
||||
Source ResultSetNode
|
||||
|
||||
// AsName is the alias name of the table source.
|
||||
AsName model.CIStr
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *TableSource) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*TableSource)
|
||||
node, ok := n.Source.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Source = node.(ResultSetNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// SetResultFields implements ResultSetNode interface.
|
||||
func (n *TableSource) SetResultFields(rfs []*ResultField) {
|
||||
n.Source.SetResultFields(rfs)
|
||||
}
|
||||
|
||||
// GetResultFields implements ResultSetNode interface.
|
||||
func (n *TableSource) GetResultFields() []*ResultField {
|
||||
return n.Source.GetResultFields()
|
||||
}
|
||||
|
||||
// SelectLockType is the lock type for SelectStmt.
|
||||
type SelectLockType int
|
||||
|
||||
// Select lock types.
|
||||
const (
|
||||
SelectLockNone SelectLockType = iota
|
||||
SelectLockForUpdate
|
||||
SelectLockInShareMode
|
||||
)
|
||||
|
||||
// WildCardField is a special type of select field content.
|
||||
type WildCardField struct {
|
||||
node
|
||||
|
||||
Table model.CIStr
|
||||
Schema model.CIStr
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *WildCardField) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*WildCardField)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// SelectField represents fields in select statement.
|
||||
// There are two type of select field: wildcard
|
||||
// and expression with optional alias name.
|
||||
type SelectField struct {
|
||||
node
|
||||
|
||||
// Offset is used to get original text.
|
||||
Offset int
|
||||
// If WildCard is not nil, Expr will be nil.
|
||||
WildCard *WildCardField
|
||||
// If Expr is not nil, WildCard will be nil.
|
||||
Expr ExprNode
|
||||
// Alias name for Expr.
|
||||
AsName model.CIStr
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *SelectField) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*SelectField)
|
||||
if n.Expr != nil {
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// FieldList represents field list in select statement.
|
||||
type FieldList struct {
|
||||
node
|
||||
|
||||
Fields []*SelectField
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *FieldList) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*FieldList)
|
||||
for i, val := range n.Fields {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Fields[i] = node.(*SelectField)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// TableRefsClause represents table references clause in dml statement.
|
||||
type TableRefsClause struct {
|
||||
node
|
||||
|
||||
TableRefs *Join
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *TableRefsClause) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*TableRefsClause)
|
||||
node, ok := n.TableRefs.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.TableRefs = node.(*Join)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ByItem represents an item in order by or group by.
|
||||
type ByItem struct {
|
||||
node
|
||||
|
||||
Expr ExprNode
|
||||
Desc bool
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ByItem) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ByItem)
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// GroupByClause represents group by clause.
|
||||
type GroupByClause struct {
|
||||
node
|
||||
Items []*ByItem
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *GroupByClause) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*GroupByClause)
|
||||
for i, val := range n.Items {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Items[i] = node.(*ByItem)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// HavingClause represents having clause.
|
||||
type HavingClause struct {
|
||||
node
|
||||
Expr ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *HavingClause) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*HavingClause)
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// OrderByClause represents order by clause.
|
||||
type OrderByClause struct {
|
||||
node
|
||||
Items []*ByItem
|
||||
ForUnion bool
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *OrderByClause) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*OrderByClause)
|
||||
for i, val := range n.Items {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Items[i] = node.(*ByItem)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// SelectStmt represents the select query node.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/select.html
|
||||
type SelectStmt struct {
|
||||
dmlNode
|
||||
resultSetNode
|
||||
|
||||
// Distinct represents if the select has distinct option.
|
||||
Distinct bool
|
||||
// From is the from clause of the query.
|
||||
From *TableRefsClause
|
||||
// Where is the where clause in select statement.
|
||||
Where ExprNode
|
||||
// Fields is the select expression list.
|
||||
Fields *FieldList
|
||||
// GroupBy is the group by expression list.
|
||||
GroupBy *GroupByClause
|
||||
// Having is the having condition.
|
||||
Having *HavingClause
|
||||
// OrderBy is the ordering expression list.
|
||||
OrderBy *OrderByClause
|
||||
// Limit is the limit clause.
|
||||
Limit *Limit
|
||||
// Lock is the lock type
|
||||
LockTp SelectLockType
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *SelectStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
|
||||
n = newNode.(*SelectStmt)
|
||||
if n.From != nil {
|
||||
node, ok := n.From.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.From = node.(*TableRefsClause)
|
||||
}
|
||||
|
||||
if n.Where != nil {
|
||||
node, ok := n.Where.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Where = node.(ExprNode)
|
||||
}
|
||||
|
||||
if n.Fields != nil {
|
||||
node, ok := n.Fields.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Fields = node.(*FieldList)
|
||||
}
|
||||
|
||||
if n.GroupBy != nil {
|
||||
node, ok := n.GroupBy.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.GroupBy = node.(*GroupByClause)
|
||||
}
|
||||
|
||||
if n.Having != nil {
|
||||
node, ok := n.Having.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Having = node.(*HavingClause)
|
||||
}
|
||||
|
||||
if n.OrderBy != nil {
|
||||
node, ok := n.OrderBy.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.OrderBy = node.(*OrderByClause)
|
||||
}
|
||||
|
||||
if n.Limit != nil {
|
||||
node, ok := n.Limit.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Limit = node.(*Limit)
|
||||
}
|
||||
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// UnionSelectList represents the select list in a union statement.
|
||||
type UnionSelectList struct {
|
||||
node
|
||||
|
||||
Selects []*SelectStmt
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *UnionSelectList) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*UnionSelectList)
|
||||
for i, sel := range n.Selects {
|
||||
node, ok := sel.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Selects[i] = node.(*SelectStmt)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// UnionStmt represents "union statement"
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/union.html
|
||||
type UnionStmt struct {
|
||||
dmlNode
|
||||
resultSetNode
|
||||
|
||||
Distinct bool
|
||||
SelectList *UnionSelectList
|
||||
OrderBy *OrderByClause
|
||||
Limit *Limit
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *UnionStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*UnionStmt)
|
||||
if n.SelectList != nil {
|
||||
node, ok := n.SelectList.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.SelectList = node.(*UnionSelectList)
|
||||
}
|
||||
if n.OrderBy != nil {
|
||||
node, ok := n.OrderBy.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.OrderBy = node.(*OrderByClause)
|
||||
}
|
||||
if n.Limit != nil {
|
||||
node, ok := n.Limit.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Limit = node.(*Limit)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// Assignment is the expression for assignment, like a = 1.
|
||||
type Assignment struct {
|
||||
node
|
||||
// Column is the column name to be assigned.
|
||||
Column *ColumnName
|
||||
// Expr is the expression assigning to ColName.
|
||||
Expr ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *Assignment) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*Assignment)
|
||||
node, ok := n.Column.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Column = node.(*ColumnName)
|
||||
node, ok = n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// Priority const values.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/insert.html
|
||||
const (
|
||||
NoPriority = iota
|
||||
LowPriority
|
||||
HighPriority
|
||||
DelayedPriority
|
||||
)
|
||||
|
||||
// InsertStmt is a statement to insert new rows into an existing table.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/insert.html
|
||||
type InsertStmt struct {
|
||||
dmlNode
|
||||
|
||||
IsReplace bool
|
||||
Table *TableRefsClause
|
||||
Columns []*ColumnName
|
||||
Lists [][]ExprNode
|
||||
Setlist []*Assignment
|
||||
Priority int
|
||||
OnDuplicate []*Assignment
|
||||
Select ResultSetNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *InsertStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
|
||||
n = newNode.(*InsertStmt)
|
||||
if n.Select != nil {
|
||||
node, ok := n.Select.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Select = node.(ResultSetNode)
|
||||
}
|
||||
|
||||
node, ok := n.Table.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Table = node.(*TableRefsClause)
|
||||
|
||||
for i, val := range n.Columns {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Columns[i] = node.(*ColumnName)
|
||||
}
|
||||
for i, list := range n.Lists {
|
||||
for j, val := range list {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Lists[i][j] = node.(ExprNode)
|
||||
}
|
||||
}
|
||||
for i, val := range n.Setlist {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Setlist[i] = node.(*Assignment)
|
||||
}
|
||||
for i, val := range n.OnDuplicate {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.OnDuplicate[i] = node.(*Assignment)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// DeleteStmt is a statement to delete rows from table.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/delete.html
|
||||
type DeleteStmt struct {
|
||||
dmlNode
|
||||
|
||||
// Used in both single table and multiple table delete statement.
|
||||
TableRefs *TableRefsClause
|
||||
// Only used in multiple table delete statement.
|
||||
Tables *DeleteTableList
|
||||
Where ExprNode
|
||||
Order *OrderByClause
|
||||
Limit *Limit
|
||||
LowPriority bool
|
||||
Ignore bool
|
||||
Quick bool
|
||||
IsMultiTable bool
|
||||
BeforeFrom bool
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *DeleteStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
|
||||
n = newNode.(*DeleteStmt)
|
||||
node, ok := n.TableRefs.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.TableRefs = node.(*TableRefsClause)
|
||||
|
||||
node, ok = n.Tables.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Tables = node.(*DeleteTableList)
|
||||
|
||||
if n.Where != nil {
|
||||
node, ok = n.Where.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Where = node.(ExprNode)
|
||||
}
|
||||
if n.Order != nil {
|
||||
node, ok = n.Order.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Order = node.(*OrderByClause)
|
||||
}
|
||||
if n.Limit != nil {
|
||||
node, ok = n.Limit.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Limit = node.(*Limit)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// UpdateStmt is a statement to update columns of existing rows in tables with new values.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/update.html
|
||||
type UpdateStmt struct {
|
||||
dmlNode
|
||||
|
||||
TableRefs *TableRefsClause
|
||||
List []*Assignment
|
||||
Where ExprNode
|
||||
Order *OrderByClause
|
||||
Limit *Limit
|
||||
LowPriority bool
|
||||
Ignore bool
|
||||
MultipleTable bool
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *UpdateStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*UpdateStmt)
|
||||
node, ok := n.TableRefs.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.TableRefs = node.(*TableRefsClause)
|
||||
for i, val := range n.List {
|
||||
node, ok = val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.List[i] = node.(*Assignment)
|
||||
}
|
||||
if n.Where != nil {
|
||||
node, ok = n.Where.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Where = node.(ExprNode)
|
||||
}
|
||||
if n.Order != nil {
|
||||
node, ok = n.Order.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Order = node.(*OrderByClause)
|
||||
}
|
||||
if n.Limit != nil {
|
||||
node, ok = n.Limit.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Limit = node.(*Limit)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// Limit is the limit clause.
|
||||
type Limit struct {
|
||||
node
|
||||
|
||||
Offset uint64
|
||||
Count uint64
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *Limit) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*Limit)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ShowStmtType is the type for SHOW statement.
|
||||
type ShowStmtType int
|
||||
|
||||
// Show statement types.
|
||||
const (
|
||||
ShowNone = iota
|
||||
ShowEngines
|
||||
ShowDatabases
|
||||
ShowTables
|
||||
ShowTableStatus
|
||||
ShowColumns
|
||||
ShowWarnings
|
||||
ShowCharset
|
||||
ShowVariables
|
||||
ShowStatus
|
||||
ShowCollation
|
||||
ShowCreateTable
|
||||
ShowGrants
|
||||
ShowTriggers
|
||||
ShowProcedureStatus
|
||||
ShowIndex
|
||||
)
|
||||
|
||||
// ShowStmt is a statement to provide information about databases, tables, columns and so on.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/show.html
|
||||
type ShowStmt struct {
|
||||
dmlNode
|
||||
resultSetNode
|
||||
|
||||
Tp ShowStmtType // Databases/Tables/Columns/....
|
||||
DBName string
|
||||
Table *TableName // Used for showing columns.
|
||||
Column *ColumnName // Used for `desc table column`.
|
||||
Flag int // Some flag parsed from sql, such as FULL.
|
||||
Full bool
|
||||
User string // Used for show grants.
|
||||
|
||||
// Used by show variables
|
||||
GlobalScope bool
|
||||
Pattern *PatternLikeExpr
|
||||
Where ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ShowStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ShowStmt)
|
||||
if n.Table != nil {
|
||||
node, ok := n.Table.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Table = node.(*TableName)
|
||||
}
|
||||
if n.Column != nil {
|
||||
node, ok := n.Column.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Column = node.(*ColumnName)
|
||||
}
|
||||
if n.Pattern != nil {
|
||||
node, ok := n.Pattern.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Pattern = node.(*PatternLikeExpr)
|
||||
}
|
||||
if n.Where != nil {
|
||||
node, ok := n.Where.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Where = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
749
vendor/github.com/pingcap/tidb/ast/expressions.go
generated
vendored
Normal file
749
vendor/github.com/pingcap/tidb/ast/expressions.go
generated
vendored
Normal file
|
@ -0,0 +1,749 @@
|
|||
// Copyright 2015 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 ast
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"github.com/pingcap/tidb/context"
|
||||
"github.com/pingcap/tidb/model"
|
||||
"github.com/pingcap/tidb/mysql"
|
||||
"github.com/pingcap/tidb/parser/opcode"
|
||||
"github.com/pingcap/tidb/util/types"
|
||||
)
|
||||
|
||||
var (
|
||||
_ ExprNode = &BetweenExpr{}
|
||||
_ ExprNode = &BinaryOperationExpr{}
|
||||
_ ExprNode = &CaseExpr{}
|
||||
_ ExprNode = &ColumnNameExpr{}
|
||||
_ ExprNode = &CompareSubqueryExpr{}
|
||||
_ ExprNode = &DefaultExpr{}
|
||||
_ ExprNode = &ExistsSubqueryExpr{}
|
||||
_ ExprNode = &IsNullExpr{}
|
||||
_ ExprNode = &IsTruthExpr{}
|
||||
_ ExprNode = &ParamMarkerExpr{}
|
||||
_ ExprNode = &ParenthesesExpr{}
|
||||
_ ExprNode = &PatternInExpr{}
|
||||
_ ExprNode = &PatternLikeExpr{}
|
||||
_ ExprNode = &PatternRegexpExpr{}
|
||||
_ ExprNode = &PositionExpr{}
|
||||
_ ExprNode = &RowExpr{}
|
||||
_ ExprNode = &SubqueryExpr{}
|
||||
_ ExprNode = &UnaryOperationExpr{}
|
||||
_ ExprNode = &ValueExpr{}
|
||||
_ ExprNode = &ValuesExpr{}
|
||||
_ ExprNode = &VariableExpr{}
|
||||
|
||||
_ Node = &ColumnName{}
|
||||
_ Node = &WhenClause{}
|
||||
)
|
||||
|
||||
// ValueExpr is the simple value expression.
|
||||
type ValueExpr struct {
|
||||
exprNode
|
||||
}
|
||||
|
||||
// NewValueExpr creates a ValueExpr with value, and sets default field type.
|
||||
func NewValueExpr(value interface{}) *ValueExpr {
|
||||
if ve, ok := value.(*ValueExpr); ok {
|
||||
return ve
|
||||
}
|
||||
ve := &ValueExpr{}
|
||||
ve.SetValue(value)
|
||||
if _, ok := value.(UnquoteString); ok {
|
||||
ve.Type = types.NewFieldType(mysql.TypeVarchar)
|
||||
ve.Type.Charset = mysql.DefaultCharset
|
||||
ve.Type.Collate = mysql.DefaultCollationName
|
||||
return ve
|
||||
}
|
||||
ve.Type = types.DefaultTypeForValue(value)
|
||||
return ve
|
||||
}
|
||||
|
||||
// Accept implements Node interface.
|
||||
func (n *ValueExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ValueExpr)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// BetweenExpr is for "between and" or "not between and" expression.
|
||||
type BetweenExpr struct {
|
||||
exprNode
|
||||
// Expr is the expression to be checked.
|
||||
Expr ExprNode
|
||||
// Left is the expression for minimal value in the range.
|
||||
Left ExprNode
|
||||
// Right is the expression for maximum value in the range.
|
||||
Right ExprNode
|
||||
// Not is true, the expression is "not between and".
|
||||
Not bool
|
||||
}
|
||||
|
||||
// Accept implements Node interface.
|
||||
func (n *BetweenExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
|
||||
n = newNode.(*BetweenExpr)
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
|
||||
node, ok = n.Left.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Left = node.(ExprNode)
|
||||
|
||||
node, ok = n.Right.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Right = node.(ExprNode)
|
||||
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// BinaryOperationExpr is for binary operation like `1 + 1`, `1 - 1`, etc.
|
||||
type BinaryOperationExpr struct {
|
||||
exprNode
|
||||
// Op is the operator code for BinaryOperation.
|
||||
Op opcode.Op
|
||||
// L is the left expression in BinaryOperation.
|
||||
L ExprNode
|
||||
// R is the right expression in BinaryOperation.
|
||||
R ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node interface.
|
||||
func (n *BinaryOperationExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
|
||||
n = newNode.(*BinaryOperationExpr)
|
||||
node, ok := n.L.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.L = node.(ExprNode)
|
||||
|
||||
node, ok = n.R.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.R = node.(ExprNode)
|
||||
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// WhenClause is the when clause in Case expression for "when condition then result".
|
||||
type WhenClause struct {
|
||||
node
|
||||
// Expr is the condition expression in WhenClause.
|
||||
Expr ExprNode
|
||||
// Result is the result expression in WhenClause.
|
||||
Result ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *WhenClause) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
|
||||
n = newNode.(*WhenClause)
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
|
||||
node, ok = n.Result.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Result = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// CaseExpr is the case expression.
|
||||
type CaseExpr struct {
|
||||
exprNode
|
||||
// Value is the compare value expression.
|
||||
Value ExprNode
|
||||
// WhenClauses is the condition check expression.
|
||||
WhenClauses []*WhenClause
|
||||
// ElseClause is the else result expression.
|
||||
ElseClause ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *CaseExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
|
||||
n = newNode.(*CaseExpr)
|
||||
if n.Value != nil {
|
||||
node, ok := n.Value.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Value = node.(ExprNode)
|
||||
}
|
||||
for i, val := range n.WhenClauses {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.WhenClauses[i] = node.(*WhenClause)
|
||||
}
|
||||
if n.ElseClause != nil {
|
||||
node, ok := n.ElseClause.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.ElseClause = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// SubqueryExec represents a subquery executor interface.
|
||||
// This interface is implemented in executor and used in plan/evaluator.
|
||||
// It will execute the subselect and get the result.
|
||||
type SubqueryExec interface {
|
||||
ExprNode
|
||||
|
||||
// EvalRows executes the subquery and returns the multi rows with rowCount.
|
||||
// rowCount < 0 means no limit.
|
||||
// If the ColumnCount is 1, we will return a column result like {1, 2, 3},
|
||||
// otherwise, we will return a table result like {{1, 1}, {2, 2}}.
|
||||
EvalRows(ctx context.Context, rowCount int) ([]interface{}, error)
|
||||
|
||||
// ColumnCount returns column count for the sub query.
|
||||
ColumnCount() (int, error)
|
||||
}
|
||||
|
||||
// SubqueryExpr represents a subquery.
|
||||
type SubqueryExpr struct {
|
||||
exprNode
|
||||
// Query is the query SelectNode.
|
||||
Query ResultSetNode
|
||||
SubqueryExec SubqueryExec
|
||||
Evaluated bool
|
||||
UseOuterContext bool
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *SubqueryExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*SubqueryExpr)
|
||||
|
||||
if n.SubqueryExec != nil {
|
||||
t, ok := n.SubqueryExec.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
sq, ok := t.(SubqueryExec)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.SubqueryExec = sq
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
node, ok := n.Query.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Query = node.(ResultSetNode)
|
||||
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// SetResultFields implements ResultSetNode interface.
|
||||
func (n *SubqueryExpr) SetResultFields(rfs []*ResultField) {
|
||||
n.Query.SetResultFields(rfs)
|
||||
}
|
||||
|
||||
// GetResultFields implements ResultSetNode interface.
|
||||
func (n *SubqueryExpr) GetResultFields() []*ResultField {
|
||||
return n.Query.GetResultFields()
|
||||
}
|
||||
|
||||
// CompareSubqueryExpr is the expression for "expr cmp (select ...)".
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/comparisons-using-subqueries.html
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/any-in-some-subqueries.html
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/all-subqueries.html
|
||||
type CompareSubqueryExpr struct {
|
||||
exprNode
|
||||
// L is the left expression
|
||||
L ExprNode
|
||||
// Op is the comparison opcode.
|
||||
Op opcode.Op
|
||||
// R is the subquery for right expression, may be rewritten to other type of expression.
|
||||
R ExprNode
|
||||
// All is true, we should compare all records in subquery.
|
||||
All bool
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *CompareSubqueryExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*CompareSubqueryExpr)
|
||||
node, ok := n.L.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.L = node.(ExprNode)
|
||||
node, ok = n.R.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.R = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ColumnName represents column name.
|
||||
type ColumnName struct {
|
||||
node
|
||||
Schema model.CIStr
|
||||
Table model.CIStr
|
||||
Name model.CIStr
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ColumnName) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ColumnName)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ColumnNameExpr represents a column name expression.
|
||||
type ColumnNameExpr struct {
|
||||
exprNode
|
||||
|
||||
// Name is the referenced column name.
|
||||
Name *ColumnName
|
||||
|
||||
// Refer is the result field the column name refers to.
|
||||
// The value of Refer.Expr is used as the value of the expression.
|
||||
Refer *ResultField
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ColumnNameExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ColumnNameExpr)
|
||||
node, ok := n.Name.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Name = node.(*ColumnName)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// DefaultExpr is the default expression using default value for a column.
|
||||
type DefaultExpr struct {
|
||||
exprNode
|
||||
// Name is the column name.
|
||||
Name *ColumnName
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *DefaultExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*DefaultExpr)
|
||||
if n.Name != nil {
|
||||
node, ok := n.Name.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Name = node.(*ColumnName)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ExistsSubqueryExpr is the expression for "exists (select ...)".
|
||||
// https://dev.mysql.com/doc/refman/5.7/en/exists-and-not-exists-subqueries.html
|
||||
type ExistsSubqueryExpr struct {
|
||||
exprNode
|
||||
// Sel is the subquery, may be rewritten to other type of expression.
|
||||
Sel ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ExistsSubqueryExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ExistsSubqueryExpr)
|
||||
node, ok := n.Sel.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Sel = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// PatternInExpr is the expression for in operator, like "expr in (1, 2, 3)" or "expr in (select c from t)".
|
||||
type PatternInExpr struct {
|
||||
exprNode
|
||||
// Expr is the value expression to be compared.
|
||||
Expr ExprNode
|
||||
// List is the list expression in compare list.
|
||||
List []ExprNode
|
||||
// Not is true, the expression is "not in".
|
||||
Not bool
|
||||
// Sel is the subquery, may be rewritten to other type of expression.
|
||||
Sel ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *PatternInExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*PatternInExpr)
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
for i, val := range n.List {
|
||||
node, ok = val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.List[i] = node.(ExprNode)
|
||||
}
|
||||
if n.Sel != nil {
|
||||
node, ok = n.Sel.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Sel = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// IsNullExpr is the expression for null check.
|
||||
type IsNullExpr struct {
|
||||
exprNode
|
||||
// Expr is the expression to be checked.
|
||||
Expr ExprNode
|
||||
// Not is true, the expression is "is not null".
|
||||
Not bool
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *IsNullExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*IsNullExpr)
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// IsTruthExpr is the expression for true/false check.
|
||||
type IsTruthExpr struct {
|
||||
exprNode
|
||||
// Expr is the expression to be checked.
|
||||
Expr ExprNode
|
||||
// Not is true, the expression is "is not true/false".
|
||||
Not bool
|
||||
// True indicates checking true or false.
|
||||
True int64
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *IsTruthExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*IsTruthExpr)
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// PatternLikeExpr is the expression for like operator, e.g, expr like "%123%"
|
||||
type PatternLikeExpr struct {
|
||||
exprNode
|
||||
// Expr is the expression to be checked.
|
||||
Expr ExprNode
|
||||
// Pattern is the like expression.
|
||||
Pattern ExprNode
|
||||
// Not is true, the expression is "not like".
|
||||
Not bool
|
||||
|
||||
Escape byte
|
||||
|
||||
PatChars []byte
|
||||
PatTypes []byte
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *PatternLikeExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*PatternLikeExpr)
|
||||
if n.Expr != nil {
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
}
|
||||
if n.Pattern != nil {
|
||||
node, ok := n.Pattern.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Pattern = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ParamMarkerExpr expression holds a place for another expression.
|
||||
// Used in parsing prepare statement.
|
||||
type ParamMarkerExpr struct {
|
||||
exprNode
|
||||
Offset int
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ParamMarkerExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ParamMarkerExpr)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ParenthesesExpr is the parentheses expression.
|
||||
type ParenthesesExpr struct {
|
||||
exprNode
|
||||
// Expr is the expression in parentheses.
|
||||
Expr ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ParenthesesExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ParenthesesExpr)
|
||||
if n.Expr != nil {
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// PositionExpr is the expression for order by and group by position.
|
||||
// MySQL use position expression started from 1, it looks a little confused inner.
|
||||
// maybe later we will use 0 at first.
|
||||
type PositionExpr struct {
|
||||
exprNode
|
||||
// N is the position, started from 1 now.
|
||||
N int
|
||||
// Refer is the result field the position refers to.
|
||||
Refer *ResultField
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *PositionExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*PositionExpr)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// PatternRegexpExpr is the pattern expression for pattern match.
|
||||
type PatternRegexpExpr struct {
|
||||
exprNode
|
||||
// Expr is the expression to be checked.
|
||||
Expr ExprNode
|
||||
// Pattern is the expression for pattern.
|
||||
Pattern ExprNode
|
||||
// Not is true, the expression is "not rlike",
|
||||
Not bool
|
||||
|
||||
// Re is the compiled regexp.
|
||||
Re *regexp.Regexp
|
||||
// Sexpr is the string for Expr expression.
|
||||
Sexpr *string
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *PatternRegexpExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*PatternRegexpExpr)
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
node, ok = n.Pattern.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Pattern = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// RowExpr is the expression for row constructor.
|
||||
// See https://dev.mysql.com/doc/refman/5.7/en/row-subqueries.html
|
||||
type RowExpr struct {
|
||||
exprNode
|
||||
|
||||
Values []ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *RowExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*RowExpr)
|
||||
for i, val := range n.Values {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Values[i] = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// UnaryOperationExpr is the expression for unary operator.
|
||||
type UnaryOperationExpr struct {
|
||||
exprNode
|
||||
// Op is the operator opcode.
|
||||
Op opcode.Op
|
||||
// V is the unary expression.
|
||||
V ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *UnaryOperationExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*UnaryOperationExpr)
|
||||
node, ok := n.V.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.V = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ValuesExpr is the expression used in INSERT VALUES
|
||||
type ValuesExpr struct {
|
||||
exprNode
|
||||
// model.CIStr is column name.
|
||||
Column *ColumnNameExpr
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ValuesExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ValuesExpr)
|
||||
node, ok := n.Column.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Column = node.(*ColumnNameExpr)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// VariableExpr is the expression for variable.
|
||||
type VariableExpr struct {
|
||||
exprNode
|
||||
// Name is the variable name.
|
||||
Name string
|
||||
// IsGlobal indicates whether this variable is global.
|
||||
IsGlobal bool
|
||||
// IsSystem indicates whether this variable is a system variable in current session.
|
||||
IsSystem bool
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *VariableExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*VariableExpr)
|
||||
return v.Leave(n)
|
||||
}
|
165
vendor/github.com/pingcap/tidb/ast/flag.go
generated
vendored
Normal file
165
vendor/github.com/pingcap/tidb/ast/flag.go
generated
vendored
Normal file
|
@ -0,0 +1,165 @@
|
|||
// Copyright 2015 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 ast
|
||||
|
||||
const preEvaluable = FlagHasParamMarker | FlagHasFunc | FlagHasVariable | FlagHasDefault
|
||||
|
||||
// IsPreEvaluable checks if the expression can be evaluated before execution.
|
||||
func IsPreEvaluable(expr ExprNode) bool {
|
||||
return expr.GetFlag()|preEvaluable == preEvaluable
|
||||
}
|
||||
|
||||
// IsConstant checks if the expression is constant.
|
||||
// A constant expression is safe to be rewritten to value expression.
|
||||
func IsConstant(expr ExprNode) bool {
|
||||
return expr.GetFlag() == FlagConstant
|
||||
}
|
||||
|
||||
// HasAggFlag checks if the expr contains FlagHasAggregateFunc.
|
||||
func HasAggFlag(expr ExprNode) bool {
|
||||
return expr.GetFlag()&FlagHasAggregateFunc > 0
|
||||
}
|
||||
|
||||
// SetFlag sets flag for expression.
|
||||
func SetFlag(n Node) {
|
||||
var setter flagSetter
|
||||
n.Accept(&setter)
|
||||
}
|
||||
|
||||
type flagSetter struct {
|
||||
}
|
||||
|
||||
func (f *flagSetter) Enter(in Node) (Node, bool) {
|
||||
return in, false
|
||||
}
|
||||
|
||||
func (f *flagSetter) Leave(in Node) (Node, bool) {
|
||||
switch x := in.(type) {
|
||||
case *AggregateFuncExpr:
|
||||
f.aggregateFunc(x)
|
||||
case *BetweenExpr:
|
||||
x.SetFlag(x.Expr.GetFlag() | x.Left.GetFlag() | x.Right.GetFlag())
|
||||
case *BinaryOperationExpr:
|
||||
x.SetFlag(x.L.GetFlag() | x.R.GetFlag())
|
||||
case *CaseExpr:
|
||||
f.caseExpr(x)
|
||||
case *ColumnNameExpr:
|
||||
x.SetFlag(FlagHasReference)
|
||||
case *CompareSubqueryExpr:
|
||||
x.SetFlag(x.L.GetFlag() | x.R.GetFlag())
|
||||
case *DefaultExpr:
|
||||
x.SetFlag(FlagHasDefault)
|
||||
case *ExistsSubqueryExpr:
|
||||
x.SetFlag(x.Sel.GetFlag())
|
||||
case *FuncCallExpr:
|
||||
f.funcCall(x)
|
||||
case *FuncCastExpr:
|
||||
x.SetFlag(FlagHasFunc | x.Expr.GetFlag())
|
||||
case *IsNullExpr:
|
||||
x.SetFlag(x.Expr.GetFlag())
|
||||
case *IsTruthExpr:
|
||||
x.SetFlag(x.Expr.GetFlag())
|
||||
case *ParamMarkerExpr:
|
||||
x.SetFlag(FlagHasParamMarker)
|
||||
case *ParenthesesExpr:
|
||||
x.SetFlag(x.Expr.GetFlag())
|
||||
case *PatternInExpr:
|
||||
f.patternIn(x)
|
||||
case *PatternLikeExpr:
|
||||
f.patternLike(x)
|
||||
case *PatternRegexpExpr:
|
||||
f.patternRegexp(x)
|
||||
case *PositionExpr:
|
||||
x.SetFlag(FlagHasReference)
|
||||
case *RowExpr:
|
||||
f.row(x)
|
||||
case *SubqueryExpr:
|
||||
x.SetFlag(FlagHasSubquery)
|
||||
case *UnaryOperationExpr:
|
||||
x.SetFlag(x.V.GetFlag())
|
||||
case *ValueExpr:
|
||||
case *ValuesExpr:
|
||||
x.SetFlag(FlagHasReference)
|
||||
case *VariableExpr:
|
||||
x.SetFlag(FlagHasVariable)
|
||||
}
|
||||
|
||||
return in, true
|
||||
}
|
||||
|
||||
func (f *flagSetter) caseExpr(x *CaseExpr) {
|
||||
var flag uint64
|
||||
if x.Value != nil {
|
||||
flag |= x.Value.GetFlag()
|
||||
}
|
||||
for _, val := range x.WhenClauses {
|
||||
flag |= val.Expr.GetFlag()
|
||||
flag |= val.Result.GetFlag()
|
||||
}
|
||||
if x.ElseClause != nil {
|
||||
flag |= x.ElseClause.GetFlag()
|
||||
}
|
||||
x.SetFlag(flag)
|
||||
}
|
||||
|
||||
func (f *flagSetter) patternIn(x *PatternInExpr) {
|
||||
flag := x.Expr.GetFlag()
|
||||
for _, val := range x.List {
|
||||
flag |= val.GetFlag()
|
||||
}
|
||||
if x.Sel != nil {
|
||||
flag |= x.Sel.GetFlag()
|
||||
}
|
||||
x.SetFlag(flag)
|
||||
}
|
||||
|
||||
func (f *flagSetter) patternLike(x *PatternLikeExpr) {
|
||||
flag := x.Pattern.GetFlag()
|
||||
if x.Expr != nil {
|
||||
flag |= x.Expr.GetFlag()
|
||||
}
|
||||
x.SetFlag(flag)
|
||||
}
|
||||
|
||||
func (f *flagSetter) patternRegexp(x *PatternRegexpExpr) {
|
||||
flag := x.Pattern.GetFlag()
|
||||
if x.Expr != nil {
|
||||
flag |= x.Expr.GetFlag()
|
||||
}
|
||||
x.SetFlag(flag)
|
||||
}
|
||||
|
||||
func (f *flagSetter) row(x *RowExpr) {
|
||||
var flag uint64
|
||||
for _, val := range x.Values {
|
||||
flag |= val.GetFlag()
|
||||
}
|
||||
x.SetFlag(flag)
|
||||
}
|
||||
|
||||
func (f *flagSetter) funcCall(x *FuncCallExpr) {
|
||||
flag := FlagHasFunc
|
||||
for _, val := range x.Args {
|
||||
flag |= val.GetFlag()
|
||||
}
|
||||
x.SetFlag(flag)
|
||||
}
|
||||
|
||||
func (f *flagSetter) aggregateFunc(x *AggregateFuncExpr) {
|
||||
flag := FlagHasAggregateFunc
|
||||
for _, val := range x.Args {
|
||||
flag |= val.GetFlag()
|
||||
}
|
||||
x.SetFlag(flag)
|
||||
}
|
403
vendor/github.com/pingcap/tidb/ast/functions.go
generated
vendored
Normal file
403
vendor/github.com/pingcap/tidb/ast/functions.go
generated
vendored
Normal file
|
@ -0,0 +1,403 @@
|
|||
// Copyright 2015 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 ast
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/juju/errors"
|
||||
"github.com/pingcap/tidb/model"
|
||||
"github.com/pingcap/tidb/util/distinct"
|
||||
"github.com/pingcap/tidb/util/types"
|
||||
)
|
||||
|
||||
var (
|
||||
_ FuncNode = &AggregateFuncExpr{}
|
||||
_ FuncNode = &FuncCallExpr{}
|
||||
_ FuncNode = &FuncCastExpr{}
|
||||
)
|
||||
|
||||
// UnquoteString is not quoted when printed.
|
||||
type UnquoteString string
|
||||
|
||||
// FuncCallExpr is for function expression.
|
||||
type FuncCallExpr struct {
|
||||
funcNode
|
||||
// FnName is the function name.
|
||||
FnName model.CIStr
|
||||
// Args is the function args.
|
||||
Args []ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node interface.
|
||||
func (n *FuncCallExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*FuncCallExpr)
|
||||
for i, val := range n.Args {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Args[i] = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// CastFunctionType is the type for cast function.
|
||||
type CastFunctionType int
|
||||
|
||||
// CastFunction types
|
||||
const (
|
||||
CastFunction CastFunctionType = iota + 1
|
||||
CastConvertFunction
|
||||
CastBinaryOperator
|
||||
)
|
||||
|
||||
// FuncCastExpr is the cast function converting value to another type, e.g, cast(expr AS signed).
|
||||
// See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html
|
||||
type FuncCastExpr struct {
|
||||
funcNode
|
||||
// Expr is the expression to be converted.
|
||||
Expr ExprNode
|
||||
// Tp is the conversion type.
|
||||
Tp *types.FieldType
|
||||
// Cast, Convert and Binary share this struct.
|
||||
FunctionType CastFunctionType
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *FuncCastExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*FuncCastExpr)
|
||||
node, ok := n.Expr.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Expr = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// TrimDirectionType is the type for trim direction.
|
||||
type TrimDirectionType int
|
||||
|
||||
const (
|
||||
// TrimBothDefault trims from both direction by default.
|
||||
TrimBothDefault TrimDirectionType = iota
|
||||
// TrimBoth trims from both direction with explicit notation.
|
||||
TrimBoth
|
||||
// TrimLeading trims from left.
|
||||
TrimLeading
|
||||
// TrimTrailing trims from right.
|
||||
TrimTrailing
|
||||
)
|
||||
|
||||
// DateArithType is type for DateArith type.
|
||||
type DateArithType byte
|
||||
|
||||
const (
|
||||
// DateAdd is to run adddate or date_add function option.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-add
|
||||
DateAdd DateArithType = iota + 1
|
||||
// DateSub is to run subdate or date_sub function option.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-sub
|
||||
DateSub
|
||||
)
|
||||
|
||||
// DateArithInterval is the struct of DateArith interval part.
|
||||
type DateArithInterval struct {
|
||||
Unit string
|
||||
Interval ExprNode
|
||||
}
|
||||
|
||||
const (
|
||||
// AggFuncCount is the name of Count function.
|
||||
AggFuncCount = "count"
|
||||
// AggFuncSum is the name of Sum function.
|
||||
AggFuncSum = "sum"
|
||||
// AggFuncAvg is the name of Avg function.
|
||||
AggFuncAvg = "avg"
|
||||
// AggFuncFirstRow is the name of FirstRowColumn function.
|
||||
AggFuncFirstRow = "firstrow"
|
||||
// AggFuncMax is the name of max function.
|
||||
AggFuncMax = "max"
|
||||
// AggFuncMin is the name of min function.
|
||||
AggFuncMin = "min"
|
||||
// AggFuncGroupConcat is the name of group_concat function.
|
||||
AggFuncGroupConcat = "group_concat"
|
||||
)
|
||||
|
||||
// AggregateFuncExpr represents aggregate function expression.
|
||||
type AggregateFuncExpr struct {
|
||||
funcNode
|
||||
// F is the function name.
|
||||
F string
|
||||
// Args is the function args.
|
||||
Args []ExprNode
|
||||
// If distinct is true, the function only aggregate distinct values.
|
||||
// For example, column c1 values are "1", "2", "2", "sum(c1)" is "5",
|
||||
// but "sum(distinct c1)" is "3".
|
||||
Distinct bool
|
||||
|
||||
CurrentGroup string
|
||||
// contextPerGroupMap is used to store aggregate evaluation context.
|
||||
// Each entry for a group.
|
||||
contextPerGroupMap map[string](*AggEvaluateContext)
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *AggregateFuncExpr) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*AggregateFuncExpr)
|
||||
for i, val := range n.Args {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Args[i] = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// Clear clears aggregate computing context.
|
||||
func (n *AggregateFuncExpr) Clear() {
|
||||
n.CurrentGroup = ""
|
||||
n.contextPerGroupMap = nil
|
||||
}
|
||||
|
||||
// Update is used for update aggregate context.
|
||||
func (n *AggregateFuncExpr) Update() error {
|
||||
name := strings.ToLower(n.F)
|
||||
switch name {
|
||||
case AggFuncCount:
|
||||
return n.updateCount()
|
||||
case AggFuncFirstRow:
|
||||
return n.updateFirstRow()
|
||||
case AggFuncGroupConcat:
|
||||
return n.updateGroupConcat()
|
||||
case AggFuncMax:
|
||||
return n.updateMaxMin(true)
|
||||
case AggFuncMin:
|
||||
return n.updateMaxMin(false)
|
||||
case AggFuncSum, AggFuncAvg:
|
||||
return n.updateSum()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetContext gets aggregate evaluation context for the current group.
|
||||
// If it is nil, add a new context into contextPerGroupMap.
|
||||
func (n *AggregateFuncExpr) GetContext() *AggEvaluateContext {
|
||||
if n.contextPerGroupMap == nil {
|
||||
n.contextPerGroupMap = make(map[string](*AggEvaluateContext))
|
||||
}
|
||||
if _, ok := n.contextPerGroupMap[n.CurrentGroup]; !ok {
|
||||
c := &AggEvaluateContext{}
|
||||
if n.Distinct {
|
||||
c.distinctChecker = distinct.CreateDistinctChecker()
|
||||
}
|
||||
n.contextPerGroupMap[n.CurrentGroup] = c
|
||||
}
|
||||
return n.contextPerGroupMap[n.CurrentGroup]
|
||||
}
|
||||
|
||||
func (n *AggregateFuncExpr) updateCount() error {
|
||||
ctx := n.GetContext()
|
||||
vals := make([]interface{}, 0, len(n.Args))
|
||||
for _, a := range n.Args {
|
||||
value := a.GetValue()
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
vals = append(vals, value)
|
||||
}
|
||||
if n.Distinct {
|
||||
d, err := ctx.distinctChecker.Check(vals)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
if !d {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
ctx.Count++
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *AggregateFuncExpr) updateFirstRow() error {
|
||||
ctx := n.GetContext()
|
||||
if ctx.evaluated {
|
||||
return nil
|
||||
}
|
||||
if len(n.Args) != 1 {
|
||||
return errors.New("Wrong number of args for AggFuncFirstRow")
|
||||
}
|
||||
ctx.Value = n.Args[0].GetValue()
|
||||
ctx.evaluated = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *AggregateFuncExpr) updateMaxMin(max bool) error {
|
||||
ctx := n.GetContext()
|
||||
if len(n.Args) != 1 {
|
||||
return errors.New("Wrong number of args for AggFuncFirstRow")
|
||||
}
|
||||
v := n.Args[0].GetValue()
|
||||
if !ctx.evaluated {
|
||||
ctx.Value = v
|
||||
ctx.evaluated = true
|
||||
return nil
|
||||
}
|
||||
c, err := types.Compare(ctx.Value, v)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
if max {
|
||||
if c == -1 {
|
||||
ctx.Value = v
|
||||
}
|
||||
} else {
|
||||
if c == 1 {
|
||||
ctx.Value = v
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *AggregateFuncExpr) updateSum() error {
|
||||
ctx := n.GetContext()
|
||||
a := n.Args[0]
|
||||
value := a.GetValue()
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
if n.Distinct {
|
||||
d, err := ctx.distinctChecker.Check([]interface{}{value})
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
if !d {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
var err error
|
||||
ctx.Value, err = types.CalculateSum(ctx.Value, value)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
ctx.Count++
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *AggregateFuncExpr) updateGroupConcat() error {
|
||||
ctx := n.GetContext()
|
||||
vals := make([]interface{}, 0, len(n.Args))
|
||||
for _, a := range n.Args {
|
||||
value := a.GetValue()
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
vals = append(vals, value)
|
||||
}
|
||||
if n.Distinct {
|
||||
d, err := ctx.distinctChecker.Check(vals)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
if !d {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if ctx.Buffer == nil {
|
||||
ctx.Buffer = &bytes.Buffer{}
|
||||
} else {
|
||||
// now use comma separator
|
||||
ctx.Buffer.WriteString(",")
|
||||
}
|
||||
for _, val := range vals {
|
||||
ctx.Buffer.WriteString(fmt.Sprintf("%v", val))
|
||||
}
|
||||
// TODO: if total length is greater than global var group_concat_max_len, truncate it.
|
||||
return nil
|
||||
}
|
||||
|
||||
// AggregateFuncExtractor visits Expr tree.
|
||||
// It converts ColunmNameExpr to AggregateFuncExpr and collects AggregateFuncExpr.
|
||||
type AggregateFuncExtractor struct {
|
||||
inAggregateFuncExpr bool
|
||||
// AggFuncs is the collected AggregateFuncExprs.
|
||||
AggFuncs []*AggregateFuncExpr
|
||||
extracting bool
|
||||
}
|
||||
|
||||
// Enter implements Visitor interface.
|
||||
func (a *AggregateFuncExtractor) Enter(n Node) (node Node, skipChildren bool) {
|
||||
switch n.(type) {
|
||||
case *AggregateFuncExpr:
|
||||
a.inAggregateFuncExpr = true
|
||||
case *SelectStmt, *InsertStmt, *DeleteStmt, *UpdateStmt:
|
||||
// Enter a new context, skip it.
|
||||
// For example: select sum(c) + c + exists(select c from t) from t;
|
||||
if a.extracting {
|
||||
return n, true
|
||||
}
|
||||
}
|
||||
a.extracting = true
|
||||
return n, false
|
||||
}
|
||||
|
||||
// Leave implements Visitor interface.
|
||||
func (a *AggregateFuncExtractor) Leave(n Node) (node Node, ok bool) {
|
||||
switch v := n.(type) {
|
||||
case *AggregateFuncExpr:
|
||||
a.inAggregateFuncExpr = false
|
||||
a.AggFuncs = append(a.AggFuncs, v)
|
||||
case *ColumnNameExpr:
|
||||
// compose new AggregateFuncExpr
|
||||
if !a.inAggregateFuncExpr {
|
||||
// For example: select sum(c) + c from t;
|
||||
// The c in sum() should be evaluated for each row.
|
||||
// The c after plus should be evaluated only once.
|
||||
agg := &AggregateFuncExpr{
|
||||
F: AggFuncFirstRow,
|
||||
Args: []ExprNode{v},
|
||||
}
|
||||
a.AggFuncs = append(a.AggFuncs, agg)
|
||||
return agg, true
|
||||
}
|
||||
}
|
||||
return n, true
|
||||
}
|
||||
|
||||
// AggEvaluateContext is used to store intermediate result when caculation aggregate functions.
|
||||
type AggEvaluateContext struct {
|
||||
distinctChecker *distinct.Checker
|
||||
Count int64
|
||||
Value interface{}
|
||||
Buffer *bytes.Buffer // Buffer is used for group_concat.
|
||||
evaluated bool
|
||||
}
|
507
vendor/github.com/pingcap/tidb/ast/misc.go
generated
vendored
Normal file
507
vendor/github.com/pingcap/tidb/ast/misc.go
generated
vendored
Normal file
|
@ -0,0 +1,507 @@
|
|||
// Copyright 2015 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 ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pingcap/tidb/context"
|
||||
"github.com/pingcap/tidb/model"
|
||||
"github.com/pingcap/tidb/mysql"
|
||||
"github.com/pingcap/tidb/sessionctx/db"
|
||||
)
|
||||
|
||||
var (
|
||||
_ StmtNode = &AdminStmt{}
|
||||
_ StmtNode = &BeginStmt{}
|
||||
_ StmtNode = &CommitStmt{}
|
||||
_ StmtNode = &CreateUserStmt{}
|
||||
_ StmtNode = &DeallocateStmt{}
|
||||
_ StmtNode = &DoStmt{}
|
||||
_ StmtNode = &ExecuteStmt{}
|
||||
_ StmtNode = &ExplainStmt{}
|
||||
_ StmtNode = &GrantStmt{}
|
||||
_ StmtNode = &PrepareStmt{}
|
||||
_ StmtNode = &RollbackStmt{}
|
||||
_ StmtNode = &SetCharsetStmt{}
|
||||
_ StmtNode = &SetPwdStmt{}
|
||||
_ StmtNode = &SetStmt{}
|
||||
_ StmtNode = &UseStmt{}
|
||||
|
||||
_ Node = &PrivElem{}
|
||||
_ Node = &VariableAssignment{}
|
||||
)
|
||||
|
||||
// TypeOpt is used for parsing data type option from SQL.
|
||||
type TypeOpt struct {
|
||||
IsUnsigned bool
|
||||
IsZerofill bool
|
||||
}
|
||||
|
||||
// FloatOpt is used for parsing floating-point type option from SQL.
|
||||
// See: http://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html
|
||||
type FloatOpt struct {
|
||||
Flen int
|
||||
Decimal int
|
||||
}
|
||||
|
||||
// AuthOption is used for parsing create use statement.
|
||||
type AuthOption struct {
|
||||
// AuthString/HashString can be empty, so we need to decide which one to use.
|
||||
ByAuthString bool
|
||||
AuthString string
|
||||
HashString string
|
||||
// TODO: support auth_plugin
|
||||
}
|
||||
|
||||
// ExplainStmt is a statement to provide information about how is SQL statement executed
|
||||
// or get columns information in a table.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/explain.html
|
||||
type ExplainStmt struct {
|
||||
stmtNode
|
||||
|
||||
Stmt StmtNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ExplainStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ExplainStmt)
|
||||
node, ok := n.Stmt.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Stmt = node.(DMLNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// PrepareStmt is a statement to prepares a SQL statement which contains placeholders,
|
||||
// and it is executed with ExecuteStmt and released with DeallocateStmt.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/prepare.html
|
||||
type PrepareStmt struct {
|
||||
stmtNode
|
||||
|
||||
Name string
|
||||
SQLText string
|
||||
SQLVar *VariableExpr
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *PrepareStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*PrepareStmt)
|
||||
if n.SQLVar != nil {
|
||||
node, ok := n.SQLVar.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.SQLVar = node.(*VariableExpr)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// DeallocateStmt is a statement to release PreparedStmt.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/deallocate-prepare.html
|
||||
type DeallocateStmt struct {
|
||||
stmtNode
|
||||
|
||||
Name string
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *DeallocateStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*DeallocateStmt)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ExecuteStmt is a statement to execute PreparedStmt.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/execute.html
|
||||
type ExecuteStmt struct {
|
||||
stmtNode
|
||||
|
||||
Name string
|
||||
UsingVars []ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *ExecuteStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*ExecuteStmt)
|
||||
for i, val := range n.UsingVars {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.UsingVars[i] = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// BeginStmt is a statement to start a new transaction.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/commit.html
|
||||
type BeginStmt struct {
|
||||
stmtNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *BeginStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*BeginStmt)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// CommitStmt is a statement to commit the current transaction.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/commit.html
|
||||
type CommitStmt struct {
|
||||
stmtNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *CommitStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*CommitStmt)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// RollbackStmt is a statement to roll back the current transaction.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/commit.html
|
||||
type RollbackStmt struct {
|
||||
stmtNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *RollbackStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*RollbackStmt)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// UseStmt is a statement to use the DBName database as the current database.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/use.html
|
||||
type UseStmt struct {
|
||||
stmtNode
|
||||
|
||||
DBName string
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *UseStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*UseStmt)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// VariableAssignment is a variable assignment struct.
|
||||
type VariableAssignment struct {
|
||||
node
|
||||
Name string
|
||||
Value ExprNode
|
||||
IsGlobal bool
|
||||
IsSystem bool
|
||||
}
|
||||
|
||||
// Accept implements Node interface.
|
||||
func (n *VariableAssignment) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*VariableAssignment)
|
||||
node, ok := n.Value.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Value = node.(ExprNode)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// SetStmt is the statement to set variables.
|
||||
type SetStmt struct {
|
||||
stmtNode
|
||||
// Variables is the list of variable assignment.
|
||||
Variables []*VariableAssignment
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *SetStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*SetStmt)
|
||||
for i, val := range n.Variables {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Variables[i] = node.(*VariableAssignment)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// SetCharsetStmt is a statement to assign values to character and collation variables.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/set-statement.html
|
||||
type SetCharsetStmt struct {
|
||||
stmtNode
|
||||
|
||||
Charset string
|
||||
Collate string
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *SetCharsetStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*SetCharsetStmt)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// SetPwdStmt is a statement to assign a password to user account.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/set-password.html
|
||||
type SetPwdStmt struct {
|
||||
stmtNode
|
||||
|
||||
User string
|
||||
Password string
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *SetPwdStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*SetPwdStmt)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// UserSpec is used for parsing create user statement.
|
||||
type UserSpec struct {
|
||||
User string
|
||||
AuthOpt *AuthOption
|
||||
}
|
||||
|
||||
// CreateUserStmt creates user account.
|
||||
// See: https://dev.mysql.com/doc/refman/5.7/en/create-user.html
|
||||
type CreateUserStmt struct {
|
||||
stmtNode
|
||||
|
||||
IfNotExists bool
|
||||
Specs []*UserSpec
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *CreateUserStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*CreateUserStmt)
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// DoStmt is the struct for DO statement.
|
||||
type DoStmt struct {
|
||||
stmtNode
|
||||
|
||||
Exprs []ExprNode
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *DoStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*DoStmt)
|
||||
for i, val := range n.Exprs {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Exprs[i] = node.(ExprNode)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// AdminStmtType is the type for admin statement.
|
||||
type AdminStmtType int
|
||||
|
||||
// Admin statement types.
|
||||
const (
|
||||
AdminShowDDL = iota + 1
|
||||
AdminCheckTable
|
||||
)
|
||||
|
||||
// AdminStmt is the struct for Admin statement.
|
||||
type AdminStmt struct {
|
||||
stmtNode
|
||||
|
||||
Tp AdminStmtType
|
||||
Tables []*TableName
|
||||
}
|
||||
|
||||
// Accept implements Node Accpet interface.
|
||||
func (n *AdminStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
|
||||
n = newNode.(*AdminStmt)
|
||||
for i, val := range n.Tables {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Tables[i] = node.(*TableName)
|
||||
}
|
||||
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// PrivElem is the privilege type and optional column list.
|
||||
type PrivElem struct {
|
||||
node
|
||||
|
||||
Priv mysql.PrivilegeType
|
||||
Cols []*ColumnName
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *PrivElem) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*PrivElem)
|
||||
for i, val := range n.Cols {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Cols[i] = node.(*ColumnName)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// ObjectTypeType is the type for object type.
|
||||
type ObjectTypeType int
|
||||
|
||||
const (
|
||||
// ObjectTypeNone is for empty object type.
|
||||
ObjectTypeNone ObjectTypeType = iota + 1
|
||||
// ObjectTypeTable means the following object is a table.
|
||||
ObjectTypeTable
|
||||
)
|
||||
|
||||
// GrantLevelType is the type for grant level.
|
||||
type GrantLevelType int
|
||||
|
||||
const (
|
||||
// GrantLevelNone is the dummy const for default value.
|
||||
GrantLevelNone GrantLevelType = iota + 1
|
||||
// GrantLevelGlobal means the privileges are administrative or apply to all databases on a given server.
|
||||
GrantLevelGlobal
|
||||
// GrantLevelDB means the privileges apply to all objects in a given database.
|
||||
GrantLevelDB
|
||||
// GrantLevelTable means the privileges apply to all columns in a given table.
|
||||
GrantLevelTable
|
||||
)
|
||||
|
||||
// GrantLevel is used for store the privilege scope.
|
||||
type GrantLevel struct {
|
||||
Level GrantLevelType
|
||||
DBName string
|
||||
TableName string
|
||||
}
|
||||
|
||||
// GrantStmt is the struct for GRANT statement.
|
||||
type GrantStmt struct {
|
||||
stmtNode
|
||||
|
||||
Privs []*PrivElem
|
||||
ObjectType ObjectTypeType
|
||||
Level *GrantLevel
|
||||
Users []*UserSpec
|
||||
}
|
||||
|
||||
// Accept implements Node Accept interface.
|
||||
func (n *GrantStmt) Accept(v Visitor) (Node, bool) {
|
||||
newNode, skipChildren := v.Enter(n)
|
||||
if skipChildren {
|
||||
return v.Leave(newNode)
|
||||
}
|
||||
n = newNode.(*GrantStmt)
|
||||
for i, val := range n.Privs {
|
||||
node, ok := val.Accept(v)
|
||||
if !ok {
|
||||
return n, false
|
||||
}
|
||||
n.Privs[i] = node.(*PrivElem)
|
||||
}
|
||||
return v.Leave(n)
|
||||
}
|
||||
|
||||
// Ident is the table identifier composed of schema name and table name.
|
||||
type Ident struct {
|
||||
Schema model.CIStr
|
||||
Name model.CIStr
|
||||
}
|
||||
|
||||
// Full returns an Ident which set schema to the current schema if it is empty.
|
||||
func (i Ident) Full(ctx context.Context) (full Ident) {
|
||||
full.Name = i.Name
|
||||
if i.Schema.O != "" {
|
||||
full.Schema = i.Schema
|
||||
} else {
|
||||
full.Schema = model.NewCIStr(db.GetCurrentSchema(ctx))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer interface
|
||||
func (i Ident) String() string {
|
||||
if i.Schema.O == "" {
|
||||
return i.Name.O
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", i.Schema, i.Name)
|
||||
}
|
57
vendor/github.com/pingcap/tidb/ast/stringer.go
generated
vendored
Normal file
57
vendor/github.com/pingcap/tidb/ast/stringer.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2015 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 ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pingcap/tidb/util/types"
|
||||
)
|
||||
|
||||
// ToString converts a node to a string for debugging purpose.
|
||||
func ToString(node Node) string {
|
||||
s := &stringer{strMap: map[Node]string{}}
|
||||
node.Accept(s)
|
||||
return s.strMap[node]
|
||||
}
|
||||
|
||||
type stringer struct {
|
||||
strMap map[Node]string
|
||||
}
|
||||
|
||||
// Enter implements Visitor Enter interface.
|
||||
func (c *stringer) Enter(node Node) (Node, bool) {
|
||||
return node, false
|
||||
}
|
||||
|
||||
// Leave implements Visitor Leave interface.
|
||||
func (c *stringer) Leave(in Node) (out Node, ok bool) {
|
||||
switch x := in.(type) {
|
||||
case *BinaryOperationExpr:
|
||||
left := c.strMap[x.L]
|
||||
right := c.strMap[x.R]
|
||||
c.strMap[x] = left + " " + x.Op.String() + " " + right
|
||||
case *ValueExpr:
|
||||
str, _ := types.ToString(x.GetValue())
|
||||
c.strMap[x] = str
|
||||
case *ParenthesesExpr:
|
||||
c.strMap[x] = "(" + c.strMap[x.Expr] + ")"
|
||||
case *ColumnNameExpr:
|
||||
c.strMap[x] = x.Name.Table.O + "." + x.Name.Name.O
|
||||
case *BetweenExpr:
|
||||
c.strMap[x] = c.strMap[x.Expr] + " BETWWEN " + c.strMap[x.Left] + " AND " + c.strMap[x.Right]
|
||||
default:
|
||||
c.strMap[in] = fmt.Sprintf("%T", in)
|
||||
}
|
||||
return in, true
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue