tidb expressions 源码
tidb expressions 代码
文件路径:/parser/ast/expressions.go
// 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"
"io"
"reflect"
"regexp"
"strings"
"github.com/pingcap/errors"
"github.com/pingcap/tidb/parser/format"
"github.com/pingcap/tidb/parser/model"
"github.com/pingcap/tidb/parser/opcode"
)
var (
_ ExprNode = &BetweenExpr{}
_ ExprNode = &BinaryOperationExpr{}
_ ExprNode = &CaseExpr{}
_ ExprNode = &ColumnNameExpr{}
_ ExprNode = &TableNameExpr{}
_ ExprNode = &CompareSubqueryExpr{}
_ ExprNode = &DefaultExpr{}
_ ExprNode = &ExistsSubqueryExpr{}
_ ExprNode = &IsNullExpr{}
_ ExprNode = &IsTruthExpr{}
_ ExprNode = &ParenthesesExpr{}
_ ExprNode = &PatternInExpr{}
_ ExprNode = &PatternLikeExpr{}
_ ExprNode = &PatternRegexpExpr{}
_ ExprNode = &PositionExpr{}
_ ExprNode = &RowExpr{}
_ ExprNode = &SubqueryExpr{}
_ ExprNode = &UnaryOperationExpr{}
_ ExprNode = &ValuesExpr{}
_ ExprNode = &VariableExpr{}
_ ExprNode = &MatchAgainst{}
_ ExprNode = &SetCollationExpr{}
_ Node = &ColumnName{}
_ Node = &WhenClause{}
)
// ValueExpr define a interface for ValueExpr.
type ValueExpr interface {
ExprNode
SetValue(val interface{})
GetValue() interface{}
GetDatumString() string
GetString() string
GetProjectionOffset() int
SetProjectionOffset(offset int)
}
// NewValueExpr creates a ValueExpr with value, and sets default field type.
var NewValueExpr func(value interface{}, charset string, collate string) ValueExpr
// NewParamMarkerExpr creates a ParamMarkerExpr.
var NewParamMarkerExpr func(offset int) ParamMarkerExpr
// 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
}
// Restore implements Node interface.
func (n *BetweenExpr) Restore(ctx *format.RestoreCtx) error {
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore BetweenExpr.Expr")
}
if n.Not {
ctx.WriteKeyWord(" NOT BETWEEN ")
} else {
ctx.WriteKeyWord(" BETWEEN ")
}
if err := n.Left.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore BetweenExpr.Left")
}
ctx.WriteKeyWord(" AND ")
if err := n.Right.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore BetweenExpr.Right ")
}
return nil
}
// Format the ExprNode into a Writer.
func (n *BetweenExpr) Format(w io.Writer) {
n.Expr.Format(w)
if n.Not {
fmt.Fprint(w, " NOT BETWEEN ")
} else {
fmt.Fprint(w, " BETWEEN ")
}
n.Left.Format(w)
fmt.Fprint(w, " AND ")
n.Right.Format(w)
}
// 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
}
func restoreBinaryOpWithSpacesAround(ctx *format.RestoreCtx, op opcode.Op) error {
shouldInsertSpace := ctx.Flags.HasSpacesAroundBinaryOperationFlag() || op.IsKeyword()
if shouldInsertSpace {
ctx.WritePlain(" ")
}
if err := op.Restore(ctx); err != nil {
return err // no need to annotate, the caller will annotate.
}
if shouldInsertSpace {
ctx.WritePlain(" ")
}
return nil
}
// Restore implements Node interface.
func (n *BinaryOperationExpr) Restore(ctx *format.RestoreCtx) error {
if ctx.Flags.HasRestoreBracketAroundBinaryOperation() {
ctx.WritePlain("(")
}
if err := n.L.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred when restore BinaryOperationExpr.L")
}
if err := restoreBinaryOpWithSpacesAround(ctx, n.Op); err != nil {
return errors.Annotate(err, "An error occurred when restore BinaryOperationExpr.Op")
}
if err := n.R.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred when restore BinaryOperationExpr.R")
}
if ctx.Flags.HasRestoreBracketAroundBinaryOperation() {
ctx.WritePlain(")")
}
return nil
}
// Format the ExprNode into a Writer.
func (n *BinaryOperationExpr) Format(w io.Writer) {
n.L.Format(w)
fmt.Fprint(w, " ")
n.Op.Format(w)
fmt.Fprint(w, " ")
n.R.Format(w)
}
// 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
}
// Restore implements Node interface.
func (n *WhenClause) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord("WHEN ")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore WhenClauses.Expr")
}
ctx.WriteKeyWord(" THEN ")
if err := n.Result.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore WhenClauses.Result")
}
return nil
}
// 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
}
// Restore implements Node interface.
func (n *CaseExpr) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord("CASE")
if n.Value != nil {
ctx.WritePlain(" ")
if err := n.Value.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CaseExpr.Value")
}
}
for _, clause := range n.WhenClauses {
ctx.WritePlain(" ")
if err := clause.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CaseExpr.WhenClauses")
}
}
if n.ElseClause != nil {
ctx.WriteKeyWord(" ELSE ")
if err := n.ElseClause.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CaseExpr.ElseClause")
}
}
ctx.WriteKeyWord(" END")
return nil
}
// Format the ExprNode into a Writer.
func (n *CaseExpr) Format(w io.Writer) {
fmt.Fprint(w, "CASE")
// Because the presence of `case when` syntax, `Value` could be nil and we need check this.
if n.Value != nil {
fmt.Fprint(w, " ")
n.Value.Format(w)
}
for _, clause := range n.WhenClauses {
fmt.Fprint(w, " ")
fmt.Fprint(w, "WHEN ")
clause.Expr.Format(w)
fmt.Fprint(w, " THEN ")
clause.Result.Format(w)
}
if n.ElseClause != nil {
fmt.Fprint(w, " ELSE ")
n.ElseClause.Format(w)
}
fmt.Fprint(w, " END")
}
// 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)
}
// SubqueryExpr represents a subquery.
type SubqueryExpr struct {
exprNode
// Query is the query SelectNode.
Query ResultSetNode
Evaluated bool
Correlated bool
MultiRows bool
Exists bool
}
func (*SubqueryExpr) resultSet() {}
// Restore implements Node interface.
func (n *SubqueryExpr) Restore(ctx *format.RestoreCtx) error {
ctx.WritePlain("(")
if err := n.Query.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore SubqueryExpr.Query")
}
ctx.WritePlain(")")
return nil
}
// Format the ExprNode into a Writer.
func (n *SubqueryExpr) Format(w io.Writer) {
panic("Not implemented")
}
// 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)
node, ok := n.Query.Accept(v)
if !ok {
return n, false
}
n.Query = node.(ResultSetNode)
return v.Leave(n)
}
// 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
}
// Restore implements Node interface.
func (n *CompareSubqueryExpr) Restore(ctx *format.RestoreCtx) error {
if err := n.L.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CompareSubqueryExpr.L")
}
if err := restoreBinaryOpWithSpacesAround(ctx, n.Op); err != nil {
return errors.Annotate(err, "An error occurred while restore CompareSubqueryExpr.Op")
}
if n.All {
ctx.WriteKeyWord("ALL ")
} else {
ctx.WriteKeyWord("ANY ")
}
if err := n.R.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CompareSubqueryExpr.R")
}
return nil
}
// Format the ExprNode into a Writer.
func (n *CompareSubqueryExpr) Format(w io.Writer) {
panic("Not implemented")
}
// 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)
}
// TableNameExpr represents a table-level object name expression, such as sequence/table/view etc.
type TableNameExpr struct {
exprNode
// Name is the referenced object name expression.
Name *TableName
}
// Restore implements Node interface.
func (n *TableNameExpr) Restore(ctx *format.RestoreCtx) error {
if err := n.Name.Restore(ctx); err != nil {
return errors.Trace(err)
}
return nil
}
// Format the ExprNode into a Writer.
func (n *TableNameExpr) Format(w io.Writer) {
dbName, tbName := n.Name.Schema.L, n.Name.Name.L
if dbName == "" {
fmt.Fprintf(w, "`%s`", tbName)
} else {
fmt.Fprintf(w, "`%s`.`%s`", dbName, tbName)
}
}
// Accept implements Node Accept interface.
func (n *TableNameExpr) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*TableNameExpr)
node, ok := n.Name.Accept(v)
if !ok {
return n, false
}
n.Name = node.(*TableName)
return v.Leave(n)
}
// ColumnName represents column name.
type ColumnName struct {
node
Schema model.CIStr
Table model.CIStr
Name model.CIStr
}
// Restore implements Node interface.
func (n *ColumnName) Restore(ctx *format.RestoreCtx) error {
if n.Schema.O != "" && !ctx.IsCTETableName(n.Table.L) {
ctx.WriteName(n.Schema.O)
ctx.WritePlain(".")
}
if n.Table.O != "" {
ctx.WriteName(n.Table.O)
ctx.WritePlain(".")
}
ctx.WriteName(n.Name.O)
return nil
}
// 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)
}
// String implements Stringer interface.
func (n *ColumnName) String() string {
result := n.Name.L
if n.Table.L != "" {
result = n.Table.L + "." + result
}
if n.Schema.L != "" {
result = n.Schema.L + "." + result
}
return result
}
// OrigColName returns the full original column name.
func (n *ColumnName) OrigColName() (ret string) {
ret = n.Name.O
if n.Table.O == "" {
return
}
ret = n.Table.O + "." + ret
if n.Schema.O == "" {
return
}
ret = n.Schema.O + "." + ret
return
}
// 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
}
// Restore implements Node interface.
func (n *ColumnNameExpr) Restore(ctx *format.RestoreCtx) error {
if err := n.Name.Restore(ctx); err != nil {
return errors.Trace(err)
}
return nil
}
// Format the ExprNode into a Writer.
func (n *ColumnNameExpr) Format(w io.Writer) {
name := strings.Replace(n.Name.String(), ".", "`.`", -1)
fmt.Fprintf(w, "`%s`", name)
}
// 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
}
// Restore implements Node interface.
func (n *DefaultExpr) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord("DEFAULT")
if n.Name != nil {
ctx.WritePlain("(")
if err := n.Name.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore DefaultExpr.Name")
}
ctx.WritePlain(")")
}
return nil
}
// Format the ExprNode into a Writer.
func (n *DefaultExpr) Format(w io.Writer) {
panic("Not implemented")
}
// 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)
return v.Leave(n)
}
// ExistsSubqueryExpr is the expression for "exists (select ...)".
// See 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
// Not is true, the expression is "not exists".
Not bool
}
// Restore implements Node interface.
func (n *ExistsSubqueryExpr) Restore(ctx *format.RestoreCtx) error {
if n.Not {
ctx.WriteKeyWord("NOT EXISTS ")
} else {
ctx.WriteKeyWord("EXISTS ")
}
if err := n.Sel.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ExistsSubqueryExpr.Sel")
}
return nil
}
// Format the ExprNode into a Writer.
func (n *ExistsSubqueryExpr) Format(w io.Writer) {
panic("Not implemented")
}
// 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
}
// Restore implements Node interface.
func (n *PatternInExpr) Restore(ctx *format.RestoreCtx) error {
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternInExpr.Expr")
}
if n.Not {
ctx.WriteKeyWord(" NOT IN ")
} else {
ctx.WriteKeyWord(" IN ")
}
if n.Sel != nil {
if err := n.Sel.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternInExpr.Sel")
}
} else {
ctx.WritePlain("(")
for i, expr := range n.List {
if i != 0 {
ctx.WritePlain(",")
}
if err := expr.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore PatternInExpr.List[%d]", i)
}
}
ctx.WritePlain(")")
}
return nil
}
// Format the ExprNode into a Writer.
func (n *PatternInExpr) Format(w io.Writer) {
n.Expr.Format(w)
if n.Not {
fmt.Fprint(w, " NOT IN (")
} else {
fmt.Fprint(w, " IN (")
}
for i, expr := range n.List {
if i != 0 {
fmt.Fprint(w, ",")
}
expr.Format(w)
}
fmt.Fprint(w, ")")
}
// 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
}
// Restore implements Node interface.
func (n *IsNullExpr) Restore(ctx *format.RestoreCtx) error {
if err := n.Expr.Restore(ctx); err != nil {
return errors.Trace(err)
}
if n.Not {
ctx.WriteKeyWord(" IS NOT NULL")
} else {
ctx.WriteKeyWord(" IS NULL")
}
return nil
}
// Format the ExprNode into a Writer.
func (n *IsNullExpr) Format(w io.Writer) {
n.Expr.Format(w)
if n.Not {
fmt.Fprint(w, " IS NOT NULL")
return
}
fmt.Fprint(w, " IS NULL")
}
// 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
}
// Restore implements Node interface.
func (n *IsTruthExpr) Restore(ctx *format.RestoreCtx) error {
if err := n.Expr.Restore(ctx); err != nil {
return errors.Trace(err)
}
if n.Not {
ctx.WriteKeyWord(" IS NOT")
} else {
ctx.WriteKeyWord(" IS")
}
if n.True > 0 {
ctx.WriteKeyWord(" TRUE")
} else {
ctx.WriteKeyWord(" FALSE")
}
return nil
}
// Format the ExprNode into a Writer.
func (n *IsTruthExpr) Format(w io.Writer) {
n.Expr.Format(w)
if n.Not {
fmt.Fprint(w, " IS NOT")
} else {
fmt.Fprint(w, " IS")
}
if n.True > 0 {
fmt.Fprint(w, " TRUE")
} else {
fmt.Fprint(w, " FALSE")
}
}
// 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
}
// Restore implements Node interface.
func (n *PatternLikeExpr) Restore(ctx *format.RestoreCtx) error {
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternLikeExpr.Expr")
}
if n.Not {
ctx.WriteKeyWord(" NOT LIKE ")
} else {
ctx.WriteKeyWord(" LIKE ")
}
if err := n.Pattern.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternLikeExpr.Pattern")
}
escape := string(n.Escape)
if escape != "\\" {
ctx.WriteKeyWord(" ESCAPE ")
ctx.WriteString(escape)
}
return nil
}
// Format the ExprNode into a Writer.
func (n *PatternLikeExpr) Format(w io.Writer) {
n.Expr.Format(w)
if n.Not {
fmt.Fprint(w, " NOT LIKE ")
} else {
fmt.Fprint(w, " LIKE ")
}
n.Pattern.Format(w)
if n.Escape != '\\' {
fmt.Fprint(w, " ESCAPE ")
fmt.Fprintf(w, "'%c'", n.Escape)
}
}
// 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 interface {
ValueExpr
SetOrder(int)
}
// ParenthesesExpr is the parentheses expression.
type ParenthesesExpr struct {
exprNode
// Expr is the expression in parentheses.
Expr ExprNode
}
// Restore implements Node interface.
func (n *ParenthesesExpr) Restore(ctx *format.RestoreCtx) error {
ctx.WritePlain("(")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred when restore ParenthesesExpr.Expr")
}
ctx.WritePlain(")")
return nil
}
// Format the ExprNode into a Writer.
func (n *ParenthesesExpr) Format(w io.Writer) {
fmt.Fprint(w, "(")
n.Expr.Format(w)
fmt.Fprint(w, ")")
}
// 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
// P is the parameterized position.
P ExprNode
// Refer is the result field the position refers to.
Refer *ResultField
}
// Restore implements Node interface.
func (n *PositionExpr) Restore(ctx *format.RestoreCtx) error {
ctx.WritePlainf("%d", n.N)
return nil
}
// Format the ExprNode into a Writer.
func (n *PositionExpr) Format(w io.Writer) {
panic("Not implemented")
}
// 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)
if n.P != nil {
node, ok := n.P.Accept(v)
if !ok {
return n, false
}
n.P = node.(ExprNode)
}
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
}
// Restore implements Node interface.
func (n *PatternRegexpExpr) Restore(ctx *format.RestoreCtx) error {
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternRegexpExpr.Expr")
}
if n.Not {
ctx.WriteKeyWord(" NOT REGEXP ")
} else {
ctx.WriteKeyWord(" REGEXP ")
}
if err := n.Pattern.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternRegexpExpr.Pattern")
}
return nil
}
// Format the ExprNode into a Writer.
func (n *PatternRegexpExpr) Format(w io.Writer) {
n.Expr.Format(w)
if n.Not {
fmt.Fprint(w, " NOT REGEXP ")
} else {
fmt.Fprint(w, " REGEXP ")
}
n.Pattern.Format(w)
}
// 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
}
// Restore implements Node interface.
func (n *RowExpr) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord("ROW")
ctx.WritePlain("(")
for i, v := range n.Values {
if i != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred when restore RowExpr.Values[%v]", i)
}
}
ctx.WritePlain(")")
return nil
}
// Format the ExprNode into a Writer.
func (n *RowExpr) Format(w io.Writer) {
panic("Not implemented")
}
// 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
}
// Restore implements Node interface.
func (n *UnaryOperationExpr) Restore(ctx *format.RestoreCtx) error {
if err := n.Op.Restore(ctx); err != nil {
return errors.Trace(err)
}
if err := n.V.Restore(ctx); err != nil {
return errors.Trace(err)
}
return nil
}
// Format the ExprNode into a Writer.
func (n *UnaryOperationExpr) Format(w io.Writer) {
n.Op.Format(w)
n.V.Format(w)
}
// 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
// Column is column name.
Column *ColumnNameExpr
}
// Restore implements Node interface.
func (n *ValuesExpr) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord("VALUES")
ctx.WritePlain("(")
if err := n.Column.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ValuesExpr.Column")
}
ctx.WritePlain(")")
return nil
}
// Format the ExprNode into a Writer.
func (n *ValuesExpr) Format(w io.Writer) {
panic("Not implemented")
}
// 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
}
// `node` may be *ast.ValueExpr, to avoid panic, we write `_` and do not use
// it.
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
// ExplicitScope indicates whether this variable scope is set explicitly.
ExplicitScope bool
// Value is the variable value.
Value ExprNode
}
// Restore implements Node interface.
func (n *VariableExpr) Restore(ctx *format.RestoreCtx) error {
if n.IsSystem {
ctx.WritePlain("@@")
if n.ExplicitScope {
if n.IsGlobal {
ctx.WriteKeyWord("GLOBAL")
} else {
ctx.WriteKeyWord("SESSION")
}
ctx.WritePlain(".")
}
} else {
ctx.WritePlain("@")
}
ctx.WriteName(n.Name)
if n.Value != nil {
ctx.WritePlain(":=")
if err := n.Value.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore VariableExpr.Value")
}
}
return nil
}
// Format the ExprNode into a Writer.
func (n *VariableExpr) Format(w io.Writer) {
panic("Not implemented")
}
// 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)
if n.Value == nil {
return v.Leave(n)
}
node, ok := n.Value.Accept(v)
if !ok {
return n, false
}
n.Value = node.(ExprNode)
return v.Leave(n)
}
// MaxValueExpr is the expression for "maxvalue" used in partition.
type MaxValueExpr struct {
exprNode
}
// Restore implements Node interface.
func (n *MaxValueExpr) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord("MAXVALUE")
return nil
}
// Format the ExprNode into a Writer.
func (n *MaxValueExpr) Format(w io.Writer) {
fmt.Fprint(w, "MAXVALUE")
}
// Accept implements Node Accept interface.
func (n *MaxValueExpr) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
return v.Leave(n)
}
// MatchAgainst is the expression for matching against fulltext index.
type MatchAgainst struct {
exprNode
// ColumnNames are the columns to match.
ColumnNames []*ColumnName
// Against
Against ExprNode
// Modifier
Modifier FulltextSearchModifier
}
func (n *MatchAgainst) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord("MATCH")
ctx.WritePlain(" (")
for i, v := range n.ColumnNames {
if i != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore MatchAgainst.ColumnNames[%d]", i)
}
}
ctx.WritePlain(") ")
ctx.WriteKeyWord("AGAINST")
ctx.WritePlain(" (")
if err := n.Against.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore MatchAgainst.Against")
}
if n.Modifier.IsBooleanMode() {
ctx.WritePlain(" IN BOOLEAN MODE")
if n.Modifier.WithQueryExpansion() {
return errors.New("BOOLEAN MODE doesn't support QUERY EXPANSION")
}
} else if n.Modifier.WithQueryExpansion() {
ctx.WritePlain(" WITH QUERY EXPANSION")
}
ctx.WritePlain(")")
return nil
}
func (n *MatchAgainst) Format(w io.Writer) {
fmt.Fprint(w, "MATCH(")
for i, v := range n.ColumnNames {
if i != 0 {
fmt.Fprintf(w, ",%s", v.String())
} else {
fmt.Fprint(w, v.String())
}
}
fmt.Fprint(w, ") AGAINST(")
n.Against.Format(w)
if n.Modifier.IsBooleanMode() {
fmt.Fprint(w, " IN BOOLEAN MODE")
} else if n.Modifier.WithQueryExpansion() {
fmt.Fprint(w, " WITH QUERY EXPANSION")
}
fmt.Fprint(w, ")")
}
func (n *MatchAgainst) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*MatchAgainst)
for i, colName := range n.ColumnNames {
newColName, ok := colName.Accept(v)
if !ok {
return n, false
}
n.ColumnNames[i] = newColName.(*ColumnName)
}
newAgainst, ok := n.Against.Accept(v)
if !ok {
return n, false
}
n.Against = newAgainst.(ExprNode)
return v.Leave(n)
}
// SetCollationExpr is the expression for the `COLLATE collation_name` clause.
type SetCollationExpr struct {
exprNode
// Expr is the expression to be set.
Expr ExprNode
// Collate is the name of collation to set.
Collate string
}
// Restore implements Node interface.
func (n *SetCollationExpr) Restore(ctx *format.RestoreCtx) error {
if err := n.Expr.Restore(ctx); err != nil {
return errors.Trace(err)
}
ctx.WriteKeyWord(" COLLATE ")
ctx.WritePlain(n.Collate)
return nil
}
// Format the ExprNode into a Writer.
func (n *SetCollationExpr) Format(w io.Writer) {
n.Expr.Format(w)
fmt.Fprintf(w, " COLLATE %s", n.Collate)
}
// Accept implements Node Accept interface.
func (n *SetCollationExpr) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*SetCollationExpr)
node, ok := n.Expr.Accept(v)
if !ok {
return n, false
}
n.Expr = node.(ExprNode)
return v.Leave(n)
}
type exprTextPositionCleaner struct {
oldTextPos []int
restore bool
}
func (e *exprTextPositionCleaner) BeginRestore() {
e.restore = true
}
func (e *exprTextPositionCleaner) Enter(n Node) (node Node, skipChildren bool) {
if e.restore {
n.SetOriginTextPosition(e.oldTextPos[0])
e.oldTextPos = e.oldTextPos[1:]
return n, false
}
e.oldTextPos = append(e.oldTextPos, n.OriginTextPosition())
n.SetOriginTextPosition(0)
return n, false
}
func (e *exprTextPositionCleaner) Leave(n Node) (node Node, ok bool) {
return n, true
}
// ExpressionDeepEqual compares the equivalence of two expressions.
func ExpressionDeepEqual(a ExprNode, b ExprNode) bool {
cleanerA := &exprTextPositionCleaner{}
cleanerB := &exprTextPositionCleaner{}
a.Accept(cleanerA)
b.Accept(cleanerB)
result := reflect.DeepEqual(a, b)
cleanerA.BeginRestore()
cleanerB.BeginRestore()
a.Accept(cleanerA)
b.Accept(cleanerB)
return result
}
相关信息
相关文章
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦