1
0
Fork 0
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:
Thomas Boerger 2016-11-29 17:26:36 +01:00 committed by Lunny Xiao
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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
}