// 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 ( "strings" "github.com/pingcap/errors" "github.com/pingcap/parser/auth" "github.com/pingcap/parser/model" "github.com/pingcap/parser/mysql" ) var ( _ DMLNode = &DeleteStmt{} _ DMLNode = &InsertStmt{} _ DMLNode = &UnionStmt{} _ DMLNode = &UpdateStmt{} _ DMLNode = &SelectStmt{} _ DMLNode = &ShowStmt{} _ DMLNode = &LoadDataStmt{} _ 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{} _ Node = &WindowSpec{} _ Node = &PartitionByClause{} _ Node = &FrameClause{} _ Node = &FrameBound{} ) // 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 // Using represents join using clause. Using []*ColumnName // NaturalJoin represents join is natural join. NaturalJoin bool // StraightJoin represents a straight join. StraightJoin bool } // Restore implements Recoverable interface. func (n *Join) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 IndexHints []*IndexHint } // Restore implements Recoverable interface. func (n *TableName) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // IndexHintType is the type for index hint use, ignore or force. type IndexHintType int // IndexHintUseType values. const ( HintUse IndexHintType = 1 HintIgnore IndexHintType = 2 HintForce IndexHintType = 3 ) // IndexHintScope is the type for index hint for join, order by or group by. type IndexHintScope int // Index hint scopes. const ( HintForScan IndexHintScope = 1 HintForJoin IndexHintScope = 2 HintForOrderBy IndexHintScope = 3 HintForGroupBy IndexHintScope = 4 ) // IndexHint represents a hint for optimizer to use/ignore/force for join/order by/group by. type IndexHint struct { IndexNames []model.CIStr HintType IndexHintType HintScope IndexHintScope } // 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 } // Restore implements Recoverable interface. func (n *DeleteTableList) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 represents JOIN on condition. type OnCondition struct { node Expr ExprNode } // Restore implements Recoverable interface. func (n *OnCondition) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 } // Restore implements Recoverable interface. func (n *TableSource) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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) } // SelectLockType is the lock type for SelectStmt. type SelectLockType int // Select lock types. const ( SelectLockNone SelectLockType = iota SelectLockForUpdate SelectLockInShareMode ) // String implements fmt.Stringer. func (slt SelectLockType) String() string { switch slt { case SelectLockNone: return "none" case SelectLockForUpdate: return "for update" case SelectLockInShareMode: return "in share mode" } return "unsupported select lock type" } // WildCardField is a special type of select field content. type WildCardField struct { node Table model.CIStr Schema model.CIStr } // Restore implements Recoverable interface. func (n *WildCardField) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 // WildCard is not nil, Expr will be nil. WildCard *WildCardField // Expr is not nil, WildCard will be nil. Expr ExprNode // AsName is alias name for Expr. AsName model.CIStr // Auxiliary stands for if this field is auxiliary. // When we add a Field into SelectField list which is used for having/orderby clause but the field is not in select clause, // we should set its Auxiliary to true. Then the TrimExec will trim the field. Auxiliary bool } // Restore implements Recoverable interface. func (n *SelectField) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 } // Restore implements Recoverable interface. func (n *FieldList) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 } // Restore implements Recoverable interface. func (n *TableRefsClause) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 } // Restore implements Recoverable interface. func (n *ByItem) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 } // Restore implements Recoverable interface. func (n *GroupByClause) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 } // Restore implements Recoverable interface. func (n *HavingClause) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 } // Restore implements Recoverable interface. func (n *OrderByClause) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 // SelectStmtOpts wraps around select hints and switches. *SelectStmtOpts // Distinct represents whether 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 // WindowSpecs is the window specification list. WindowSpecs []WindowSpec // OrderBy is the ordering expression list. OrderBy *OrderByClause // Limit is the limit clause. Limit *Limit // LockTp is the lock type LockTp SelectLockType // TableHints represents the table level Optimizer Hint for join type TableHints []*TableOptimizerHint // IsAfterUnionDistinct indicates whether it's a stmt after "union distinct". IsAfterUnionDistinct bool // IsInBraces indicates whether it's a stmt in brace. IsInBraces bool } // Restore implements Recoverable interface. func (n *SelectStmt) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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.TableHints != nil && len(n.TableHints) != 0 { newHints := make([]*TableOptimizerHint, len(n.TableHints)) for i, hint := range n.TableHints { node, ok := hint.Accept(v) if !ok { return n, false } newHints[i] = node.(*TableOptimizerHint) } n.TableHints = newHints } 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) } for i, spec := range n.WindowSpecs { node, ok := spec.Accept(v) if !ok { return n, false } n.WindowSpecs[i] = *node.(*WindowSpec) } 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 } // Restore implements Recoverable interface. func (n *UnionSelectList) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 SelectList *UnionSelectList OrderBy *OrderByClause Limit *Limit } // Restore implements Recoverable interface. func (n *UnionStmt) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 } // Restore implements Recoverable interface. func (n *Assignment) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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) } // LoadDataStmt is a statement to load data from a specified file, then insert this rows into an existing table. // See https://dev.mysql.com/doc/refman/5.7/en/load-data.html type LoadDataStmt struct { dmlNode IsLocal bool Path string Table *TableName Columns []*ColumnName FieldsInfo *FieldsClause LinesInfo *LinesClause IgnoreLines uint64 } // Restore implements Recoverable interface. func (n *LoadDataStmt) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // Accept implements Node Accept interface. func (n *LoadDataStmt) Accept(v Visitor) (Node, bool) { newNode, skipChildren := v.Enter(n) if skipChildren { return v.Leave(newNode) } n = newNode.(*LoadDataStmt) if n.Table != nil { node, ok := n.Table.Accept(v) if !ok { return n, false } n.Table = node.(*TableName) } for i, val := range n.Columns { node, ok := val.Accept(v) if !ok { return n, false } n.Columns[i] = node.(*ColumnName) } return v.Leave(n) } // FieldsClause represents fields references clause in load data statement. type FieldsClause struct { Terminated string Enclosed byte Escaped byte } // LinesClause represents lines references clause in load data statement. type LinesClause struct { Starting string Terminated string } // 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 IgnoreErr bool Table *TableRefsClause Columns []*ColumnName Lists [][]ExprNode Setlist []*Assignment Priority mysql.PriorityEnum OnDuplicate []*Assignment Select ResultSetNode } // Restore implements Recoverable interface. func (n *InsertStmt) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 // TableRefs is used in both single table and multiple table delete statement. TableRefs *TableRefsClause // Tables is only used in multiple table delete statement. Tables *DeleteTableList Where ExprNode Order *OrderByClause Limit *Limit Priority mysql.PriorityEnum IgnoreErr bool Quick bool IsMultiTable bool BeforeFrom bool // TableHints represents the table level Optimizer Hint for join type. TableHints []*TableOptimizerHint } // Restore implements Recoverable interface. func (n *DeleteStmt) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 Priority mysql.PriorityEnum IgnoreErr bool MultipleTable bool TableHints []*TableOptimizerHint } // Restore implements Recoverable interface. func (n *UpdateStmt) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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 Count ExprNode Offset ExprNode } // Restore implements Recoverable interface. func (n *Limit) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // Accept implements Node Accept interface. func (n *Limit) Accept(v Visitor) (Node, bool) { newNode, skipChildren := v.Enter(n) if skipChildren { return v.Leave(newNode) } if n.Count != nil { node, ok := n.Count.Accept(v) if !ok { return n, false } n.Count = node.(ExprNode) } if n.Offset != nil { node, ok := n.Offset.Accept(v) if !ok { return n, false } n.Offset = node.(ExprNode) } 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 ShowProcessList ShowCreateDatabase ShowEvents ShowStatsMeta ShowStatsHistograms ShowStatsBuckets ShowStatsHealthy ShowPlugins ShowProfiles ShowMasterStatus ShowPrivileges ShowErrors ) // 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 *auth.UserIdentity // Used for show grants. // GlobalScope is used by show variables GlobalScope bool Pattern *PatternLikeExpr Where ExprNode } // Restore implements Recoverable interface. func (n *ShowStmt) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // 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) } switch n.Tp { case ShowTriggers, ShowProcedureStatus, ShowProcessList, ShowEvents: // We don't have any data to return for those types, // but visiting Where may cause resolving error, so return here to avoid error. return v.Leave(n) } if n.Where != nil { node, ok := n.Where.Accept(v) if !ok { return n, false } n.Where = node.(ExprNode) } return v.Leave(n) } // WindowSpec is the specification of a window. type WindowSpec struct { node Name model.CIStr // Ref is the reference window of this specification. For example, in `w2 as (w1 order by a)`, // the definition of `w2` references `w1`. Ref model.CIStr PartitionBy *PartitionByClause OrderBy *OrderByClause Frame *FrameClause } // Restore implements Recoverable interface. func (n *WindowSpec) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // Accept implements Node Accept interface. func (n *WindowSpec) Accept(v Visitor) (Node, bool) { newNode, skipChildren := v.Enter(n) if skipChildren { return v.Leave(newNode) } n = newNode.(*WindowSpec) if n.PartitionBy != nil { node, ok := n.PartitionBy.Accept(v) if !ok { return n, false } n.PartitionBy = node.(*PartitionByClause) } if n.OrderBy != nil { node, ok := n.OrderBy.Accept(v) if !ok { return n, false } n.OrderBy = node.(*OrderByClause) } if n.Frame != nil { node, ok := n.Frame.Accept(v) if !ok { return n, false } n.Frame = node.(*FrameClause) } return v.Leave(n) } // PartitionByClause represents partition by clause. type PartitionByClause struct { node Items []*ByItem } // Restore implements Recoverable interface. func (n *PartitionByClause) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // Accept implements Node Accept interface. func (n *PartitionByClause) Accept(v Visitor) (Node, bool) { newNode, skipChildren := v.Enter(n) if skipChildren { return v.Leave(newNode) } n = newNode.(*PartitionByClause) 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) } // FrameType is the type of window function frame. type FrameType int // Window function frame types. // MySQL only supports `ROWS` and `RANGES`. const ( Rows = iota Ranges Groups ) // FrameClause represents frame clause. type FrameClause struct { node Type FrameType Extent FrameExtent } // Restore implements Recoverable interface. func (n *FrameClause) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // Accept implements Node Accept interface. func (n *FrameClause) Accept(v Visitor) (Node, bool) { newNode, skipChildren := v.Enter(n) if skipChildren { return v.Leave(newNode) } n = newNode.(*FrameClause) node, ok := n.Extent.Start.Accept(v) if !ok { return n, false } n.Extent.Start = *node.(*FrameBound) node, ok = n.Extent.End.Accept(v) if !ok { return n, false } n.Extent.End = *node.(*FrameBound) return v.Leave(n) } // FrameExtent represents frame extent. type FrameExtent struct { Start FrameBound End FrameBound } // FrameType is the type of window function frame bound. type BoundType int // Frame bound types. const ( Following = iota Preceding CurrentRow ) // FrameBound represents frame bound. type FrameBound struct { node Type BoundType UnBounded bool Expr ExprNode // `Unit` is used to indicate the units in which the `Expr` should be interpreted. // For example: '2:30' MINUTE_SECOND. Unit ExprNode } // Restore implements Recoverable interface. func (n *FrameBound) Restore(sb *strings.Builder) error { return errors.New("Not implemented") } // Accept implements Node Accept interface. func (n *FrameBound) Accept(v Visitor) (Node, bool) { newNode, skipChildren := v.Enter(n) if skipChildren { return v.Leave(newNode) } n = newNode.(*FrameBound) if n.Expr != nil { node, ok := n.Expr.Accept(v) if !ok { return n, false } n.Expr = node.(ExprNode) } if n.Unit != nil { node, ok := n.Unit.Accept(v) if !ok { return n, false } n.Unit = node.(ExprNode) } return v.Leave(n) }