You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							749 lines
						
					
					
						
							17 KiB
						
					
					
				
			
		
		
	
	
							749 lines
						
					
					
						
							17 KiB
						
					
					
				| // 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)
 | |
| }
 | |
| 
 |