diff --git a/go/mysql/conn.go b/go/mysql/conn.go index 64161fe6ee1..b5734243a5f 100644 --- a/go/mysql/conn.go +++ b/go/mysql/conn.go @@ -857,15 +857,15 @@ func (c *Conn) handleNextCommand(handler Handler) error { } paramsCount := uint16(0) - _ = sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) { + sqlparser.VisitAll(statement, func(node sqlparser.SQLNode) bool { switch node := node.(type) { case *sqlparser.SQLVal: if strings.HasPrefix(string(node.Val), ":v") { paramsCount++ } } - return true, nil - }, statement) + return true + }) if paramsCount > 0 { prepare.ParamsCount = paramsCount diff --git a/go/vt/sqlparser/ast.go b/go/vt/sqlparser/ast.go index cb74aff4f2a..cfd65b36e74 100644 --- a/go/vt/sqlparser/ast.go +++ b/go/vt/sqlparser/ast.go @@ -97,12 +97,19 @@ func Parse(sql string) (Statement, error) { } return nil, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, tokenizer.LastError.Error()) } - if tokenizer.ParseTree == nil { + ast := tokenizer.ParseTree + if ast == nil { return nil, ErrEmpty } - return tokenizer.ParseTree, nil + //noinspection GoBoolExpressions + if testAstRewriter { + Walk(ast, Identity) + } + return ast, nil } +const testAstRewriter = true + // ParseStrictDDL is the same as Parse except it errors on // partially parsed DDL statements. func ParseStrictDDL(sql string) (Statement, error) { @@ -219,39 +226,13 @@ func SplitStatementToPieces(blob string) (pieces []string, err error) { // generated by the parser. type SQLNode interface { Format(buf *TrackedBuffer) - // walkSubtree calls visit on all underlying nodes - // of the subtree, but not the current one. Walking - // must be interrupted if visit returns an error. - walkSubtree(visit Visit) error + walk(fn WalkFunc) SQLNode } // Visit defines the signature of a function that // can be used to visit all nodes of a parse tree. type Visit func(node SQLNode) (kontinue bool, err error) -// Walk calls visit on every node. -// If visit returns true, the underlying nodes -// are also visited. If it returns an error, walking -// is interrupted, and the error is returned. -func Walk(visit Visit, nodes ...SQLNode) error { - for _, node := range nodes { - if node == nil { - continue - } - kontinue, err := visit(node) - if err != nil { - return err - } - if kontinue { - err = node.walkSubtree(visit) - if err != nil { - return err - } - } - } - return nil -} - // String returns a string representation of an SQLNode. func String(node SQLNode) string { if node == nil { @@ -366,23 +347,6 @@ func (node *Select) Format(buf *TrackedBuffer) { node.Limit, node.Lock) } -func (node *Select) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.SelectExprs, - node.From, - node.Where, - node.GroupBy, - node.Having, - node.OrderBy, - node.Limit, - ) -} - // AddWhere adds the boolean expression to the // WHERE clause as an AND condition. If the expression // is an OR clause, it parenthesizes it. Currently, @@ -447,16 +411,6 @@ func (node *ParenSelect) Format(buf *TrackedBuffer) { buf.Myprintf("(%v)", node.Select) } -func (node *ParenSelect) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Select, - ) -} - // Union represents a UNION statement. type Union struct { Type string @@ -489,17 +443,6 @@ func (node *Union) Format(buf *TrackedBuffer) { node.OrderBy, node.Limit, node.Lock) } -func (node *Union) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.Right, - ) -} - // Stream represents a SELECT statement. type Stream struct { Comments Comments @@ -513,18 +456,6 @@ func (node *Stream) Format(buf *TrackedBuffer) { node.Comments, node.SelectExpr, node.Table) } -func (node *Stream) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.SelectExpr, - node.Table, - ) -} - // Insert represents an INSERT or REPLACE statement. // Per the MySQL docs, http://dev.mysql.com/doc/refman/5.7/en/replace.html // Replace is the counterpart to `INSERT IGNORE`, and works exactly like a @@ -558,20 +489,6 @@ func (node *Insert) Format(buf *TrackedBuffer) { node.Table, node.Partitions, node.Columns, node.Rows, node.OnDup) } -func (node *Insert) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.Table, - node.Columns, - node.Rows, - node.OnDup, - ) -} - // InsertRows represents the rows for an INSERT statement. type InsertRows interface { iInsertRows() @@ -602,21 +519,6 @@ func (node *Update) Format(buf *TrackedBuffer) { node.Exprs, node.Where, node.OrderBy, node.Limit) } -func (node *Update) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.TableExprs, - node.Exprs, - node.Where, - node.OrderBy, - node.Limit, - ) -} - // Delete represents a DELETE statement. // If you add fields here, consider adding them to calls to validateUnshardedRoute. type Delete struct { @@ -638,21 +540,6 @@ func (node *Delete) Format(buf *TrackedBuffer) { buf.Myprintf("from %v%v%v%v%v", node.TableExprs, node.Partitions, node.Where, node.OrderBy, node.Limit) } -func (node *Delete) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.Targets, - node.TableExprs, - node.Where, - node.OrderBy, - node.Limit, - ) -} - // Set represents a SET statement. type Set struct { Comments Comments @@ -677,17 +564,6 @@ func (node *Set) Format(buf *TrackedBuffer) { } } -func (node *Set) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.Exprs, - ) -} - // DBDDL represents a CREATE, DROP database statement. type DBDDL struct { Action string @@ -711,11 +587,6 @@ func (node *DBDDL) Format(buf *TrackedBuffer) { } } -// walkSubtree walks the nodes of the subtree. -func (node *DBDDL) walkSubtree(visit Visit) error { - return nil -} - // DDL represents a CREATE, ALTER, DROP, RENAME, TRUNCATE or ANALYZE statement. type DDL struct { Action string @@ -828,18 +699,6 @@ func (node *DDL) Format(buf *TrackedBuffer) { } } -func (node *DDL) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - for _, t := range node.AffectedTables() { - if err := Walk(visit, t); err != nil { - return err - } - } - return nil -} - // AffectedTables returns the list table names affected by the DDL. func (node *DDL) AffectedTables() TableNames { if node.Action == RenameStr || node.Action == DropStr { @@ -866,13 +725,6 @@ func (node *OptLike) Format(buf *TrackedBuffer) { buf.Myprintf("like %v", node.LikeTable) } -func (node *OptLike) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk(visit, node.LikeTable) -} - // PartitionSpec describe partition actions (for alter and create) type PartitionSpec struct { Action string @@ -896,21 +748,6 @@ func (node *PartitionSpec) Format(buf *TrackedBuffer) { } } -func (node *PartitionSpec) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - if err := Walk(visit, node.Name); err != nil { - return err - } - for _, def := range node.Definitions { - if err := Walk(visit, def); err != nil { - return err - } - } - return nil -} - // PartitionDefinition describes a very minimal partition definition type PartitionDefinition struct { Name ColIdent @@ -927,17 +764,6 @@ func (node *PartitionDefinition) Format(buf *TrackedBuffer) { } } -func (node *PartitionDefinition) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Name, - node.Limit, - ) -} - // TableSpec describes the structure of a table from a CREATE TABLE statement type TableSpec struct { Columns []*ColumnDefinition @@ -981,32 +807,6 @@ func (ts *TableSpec) AddConstraint(cd *ConstraintDefinition) { ts.Constraints = append(ts.Constraints, cd) } -func (ts *TableSpec) walkSubtree(visit Visit) error { - if ts == nil { - return nil - } - - for _, n := range ts.Columns { - if err := Walk(visit, n); err != nil { - return err - } - } - - for _, n := range ts.Indexes { - if err := Walk(visit, n); err != nil { - return err - } - } - - for _, n := range ts.Constraints { - if err := Walk(visit, n); err != nil { - return err - } - } - - return nil -} - // ColumnDefinition describes a column in a CREATE TABLE statement type ColumnDefinition struct { Name ColIdent @@ -1018,17 +818,6 @@ func (col *ColumnDefinition) Format(buf *TrackedBuffer) { buf.Myprintf("%v %v", col.Name, &col.Type) } -func (col *ColumnDefinition) walkSubtree(visit Visit) error { - if col == nil { - return nil - } - return Walk( - visit, - col.Name, - &col.Type, - ) -} - // ColumnType represents a sql type in a CREATE TABLE statement // All optional fields are nil if not specified type ColumnType struct { @@ -1247,10 +1036,6 @@ func (ct *ColumnType) SQLType() querypb.Type { panic("unimplemented type " + ct.Type) } -func (ct *ColumnType) walkSubtree(visit Visit) error { - return nil -} - // IndexDefinition describes an index in a CREATE TABLE statement type IndexDefinition struct { Info *IndexInfo @@ -1283,20 +1068,6 @@ func (idx *IndexDefinition) Format(buf *TrackedBuffer) { } } -func (idx *IndexDefinition) walkSubtree(visit Visit) error { - if idx == nil { - return nil - } - - for _, n := range idx.Columns { - if err := Walk(visit, n.Column); err != nil { - return err - } - } - - return nil -} - // IndexInfo describes the name and type of an index in a CREATE TABLE statement type IndexInfo struct { Type string @@ -1318,10 +1089,6 @@ func (ii *IndexInfo) Format(buf *TrackedBuffer) { } } -func (ii *IndexInfo) walkSubtree(visit Visit) error { - return Walk(visit, ii.Name) -} - // IndexColumn describes a column in an index definition with optional length type IndexColumn struct { Column ColIdent @@ -1374,11 +1141,6 @@ func (node *AutoIncSpec) Format(buf *TrackedBuffer) { buf.Myprintf("using %v", node.Sequence) } -func (node *AutoIncSpec) walkSubtree(visit Visit) error { - err := Walk(visit, node.Sequence, node.Column) - return err -} - // ParseParams parses the vindex parameter list, pulling out the special-case // "owner" parameter func (node *VindexSpec) ParseParams() (string, map[string]string) { @@ -1412,25 +1174,6 @@ func (node *VindexSpec) Format(buf *TrackedBuffer) { } } -func (node *VindexSpec) walkSubtree(visit Visit) error { - err := Walk(visit, - node.Name, - ) - - if err != nil { - return err - } - - for _, p := range node.Params { - err := Walk(visit, p) - - if err != nil { - return err - } - } - return nil -} - // VindexParam defines a key/value parameter for a CREATE VINDEX statement type VindexParam struct { Key ColIdent @@ -1442,12 +1185,6 @@ func (node VindexParam) Format(buf *TrackedBuffer) { buf.Myprintf("%s=%s", node.Key.String(), node.Val) } -func (node VindexParam) walkSubtree(visit Visit) error { - return Walk(visit, - node.Key, - ) -} - // ConstraintDefinition describes a constraint in a CREATE TABLE statement type ConstraintDefinition struct { Name string @@ -1468,10 +1205,6 @@ func (c *ConstraintDefinition) Format(buf *TrackedBuffer) { c.Details.Format(buf) } -func (c *ConstraintDefinition) walkSubtree(visit Visit) error { - return Walk(visit, c.Details) -} - // ReferenceAction indicates the action takes by a referential constraint e.g. // the `CASCADE` in a `FOREIGN KEY .. ON DELETE CASCADE` table definition. type ReferenceAction int @@ -1488,8 +1221,6 @@ const ( SetDefault ) -func (a ReferenceAction) walkSubtree(visit Visit) error { return nil } - // Format formats the node. func (a ReferenceAction) Format(buf *TrackedBuffer) { switch a { @@ -1530,16 +1261,6 @@ func (f *ForeignKeyDefinition) Format(buf *TrackedBuffer) { func (f *ForeignKeyDefinition) constraintInfo() {} -func (f *ForeignKeyDefinition) walkSubtree(visit Visit) error { - if err := Walk(visit, f.Source); err != nil { - return err - } - if err := Walk(visit, f.ReferencedTable); err != nil { - return err - } - return Walk(visit, f.ReferencedColumns) -} - // Show represents a show statement. type Show struct { Type string @@ -1547,7 +1268,7 @@ type Show struct { Table TableName ShowTablesOpt *ShowTablesOpt Scope string - ShowCollationFilterOpt *Expr + ShowCollationFilterOpt Expr } // Format formats the node. @@ -1573,7 +1294,7 @@ func (node *Show) Format(buf *TrackedBuffer) { buf.Myprintf(" on %v", node.OnTable) } if node.Type == "collation" && node.ShowCollationFilterOpt != nil { - buf.Myprintf(" where %v", *node.ShowCollationFilterOpt) + buf.Myprintf(" where %v", node.ShowCollationFilterOpt) } if node.HasTable() { buf.Myprintf(" %v", node.Table) @@ -1591,10 +1312,6 @@ func (node *Show) HasTable() bool { return node.Table.Name.v != "" } -func (node *Show) walkSubtree(visit Visit) error { - return nil -} - // ShowTablesOpt is show tables option type ShowTablesOpt struct { Full string @@ -1620,10 +1337,6 @@ func (node *ShowFilter) Format(buf *TrackedBuffer) { } } -func (node *ShowFilter) walkSubtree(visit Visit) error { - return nil -} - // Use represents a use statement. type Use struct { DBName TableIdent @@ -1638,10 +1351,6 @@ func (node *Use) Format(buf *TrackedBuffer) { } } -func (node *Use) walkSubtree(visit Visit) error { - return Walk(visit, node.DBName) -} - // Begin represents a Begin statement. type Begin struct{} @@ -1650,10 +1359,6 @@ func (node *Begin) Format(buf *TrackedBuffer) { buf.WriteString("begin") } -func (node *Begin) walkSubtree(visit Visit) error { - return nil -} - // Commit represents a Commit statement. type Commit struct{} @@ -1662,10 +1367,6 @@ func (node *Commit) Format(buf *TrackedBuffer) { buf.WriteString("commit") } -func (node *Commit) walkSubtree(visit Visit) error { - return nil -} - // Rollback represents a Rollback statement. type Rollback struct{} @@ -1674,10 +1375,6 @@ func (node *Rollback) Format(buf *TrackedBuffer) { buf.WriteString("rollback") } -func (node *Rollback) walkSubtree(visit Visit) error { - return nil -} - // OtherRead represents a DESCRIBE, or EXPLAIN statement. // It should be used only as an indicator. It does not contain // the full AST for the statement. @@ -1688,10 +1385,6 @@ func (node *OtherRead) Format(buf *TrackedBuffer) { buf.WriteString("otherread") } -func (node *OtherRead) walkSubtree(visit Visit) error { - return nil -} - // OtherAdmin represents a misc statement that relies on ADMIN privileges, // such as REPAIR, OPTIMIZE, or TRUNCATE statement. // It should be used only as an indicator. It does not contain @@ -1703,10 +1396,6 @@ func (node *OtherAdmin) Format(buf *TrackedBuffer) { buf.WriteString("otheradmin") } -func (node *OtherAdmin) walkSubtree(visit Visit) error { - return nil -} - // Comments represents a list of comments. type Comments [][]byte @@ -1717,10 +1406,6 @@ func (node Comments) Format(buf *TrackedBuffer) { } } -func (node Comments) walkSubtree(visit Visit) error { - return nil -} - // SelectExprs represents SELECT expressions. type SelectExprs []SelectExpr @@ -1733,15 +1418,6 @@ func (node SelectExprs) Format(buf *TrackedBuffer) { } } -func (node SelectExprs) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // SelectExpr represents a SELECT expression. type SelectExpr interface { iSelectExpr() @@ -1765,16 +1441,6 @@ func (node *StarExpr) Format(buf *TrackedBuffer) { buf.Myprintf("*") } -func (node *StarExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.TableName, - ) -} - // AliasedExpr defines an aliased SELECT expression. type AliasedExpr struct { Expr Expr @@ -1789,17 +1455,6 @@ func (node *AliasedExpr) Format(buf *TrackedBuffer) { } } -func (node *AliasedExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - node.As, - ) -} - // Nextval defines the NEXT VALUE expression. type Nextval struct { Expr Expr @@ -1810,10 +1465,6 @@ func (node Nextval) Format(buf *TrackedBuffer) { buf.Myprintf("next %v values", node.Expr) } -func (node Nextval) walkSubtree(visit Visit) error { - return Walk(visit, node.Expr) -} - // Columns represents an insert column list. type Columns []ColIdent @@ -1830,15 +1481,6 @@ func (node Columns) Format(buf *TrackedBuffer) { buf.WriteString(")") } -func (node Columns) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // FindColumn finds a column in the column list, returning // the index if it exists or -1 otherwise func (node Columns) FindColumn(col ColIdent) int { @@ -1866,15 +1508,6 @@ func (node Partitions) Format(buf *TrackedBuffer) { buf.WriteString(")") } -func (node Partitions) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // TableExprs represents a list of table expressions. type TableExprs []TableExpr @@ -1887,15 +1520,6 @@ func (node TableExprs) Format(buf *TrackedBuffer) { } } -func (node TableExprs) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // TableExpr represents a table expression. type TableExpr interface { iTableExpr() @@ -1928,18 +1552,6 @@ func (node *AliasedTableExpr) Format(buf *TrackedBuffer) { } } -func (node *AliasedTableExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - node.As, - node.Hints, - ) -} - // RemoveHints returns a new AliasedTableExpr with the hints removed. func (node *AliasedTableExpr) RemoveHints() *AliasedTableExpr { noHints := *node @@ -1968,15 +1580,6 @@ func (node TableNames) Format(buf *TrackedBuffer) { } } -func (node TableNames) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // TableName represents a table name. // Qualifier, if specified, represents a database or keyspace. // TableName is a value struct whose fields are case sensitive. @@ -1997,14 +1600,6 @@ func (node TableName) Format(buf *TrackedBuffer) { buf.Myprintf("%v", node.Name) } -func (node TableName) walkSubtree(visit Visit) error { - return Walk( - visit, - node.Name, - node.Qualifier, - ) -} - // IsEmpty returns true if TableName is nil or empty. func (node TableName) IsEmpty() bool { // If Name is empty, Qualifier is also empty. @@ -2031,16 +1626,6 @@ func (node *ParenTableExpr) Format(buf *TrackedBuffer) { buf.Myprintf("(%v)", node.Exprs) } -func (node *ParenTableExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Exprs, - ) -} - // JoinCondition represents the join conditions (either a ON or USING clause) // of a JoinTableExpr. type JoinCondition struct { @@ -2058,14 +1643,6 @@ func (node JoinCondition) Format(buf *TrackedBuffer) { } } -func (node JoinCondition) walkSubtree(visit Visit) error { - return Walk( - visit, - node.On, - node.Using, - ) -} - // JoinTableExpr represents a TableExpr that's a JOIN operation. type JoinTableExpr struct { LeftExpr TableExpr @@ -2090,18 +1667,6 @@ func (node *JoinTableExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v %s %v%v", node.LeftExpr, node.Join, node.RightExpr, node.Condition) } -func (node *JoinTableExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.LeftExpr, - node.RightExpr, - node.Condition, - ) -} - // IndexHints represents a list of index hints. type IndexHints struct { Type string @@ -2126,18 +1691,6 @@ func (node *IndexHints) Format(buf *TrackedBuffer) { buf.Myprintf(")") } -func (node *IndexHints) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - for _, n := range node.Indexes { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // Where represents a WHERE or HAVING clause. type Where struct { Type string @@ -2167,23 +1720,9 @@ func (node *Where) Format(buf *TrackedBuffer) { buf.Myprintf(" %s %v", node.Type, node.Expr) } -func (node *Where) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - // Expr represents an expression. type Expr interface { iExpr() - // replace replaces any subexpression that matches - // from with to. The implementation can use the - // replaceExprs convenience function. - replace(from, to Expr) bool SQLNode } @@ -2225,26 +1764,13 @@ func ReplaceExpr(root, from, to Expr) Expr { if root == from { return to } - root.replace(from, to) - return root -} -// replaceExprs is a convenience function used by implementors -// of the replace method. -func replaceExprs(from, to Expr, exprs ...*Expr) bool { - for _, expr := range exprs { - if *expr == nil { - continue - } - if *expr == from { - *expr = to - return true + return Walk(root, func(node SQLNode) (SQLNode, bool) { + if node == from { + return to, true } - if (*expr).replace(from, to) { - return true - } - } - return false + return node, true + }).(Expr) } // Exprs represents a list of value expressions. @@ -2260,15 +1786,6 @@ func (node Exprs) Format(buf *TrackedBuffer) { } } -func (node Exprs) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // AndExpr represents an AND expression. type AndExpr struct { Left, Right Expr @@ -2279,21 +1796,6 @@ func (node *AndExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v and %v", node.Left, node.Right) } -func (node *AndExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.Right, - ) -} - -func (node *AndExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Left, &node.Right) -} - // OrExpr represents an OR expression. type OrExpr struct { Left, Right Expr @@ -2304,21 +1806,6 @@ func (node *OrExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v or %v", node.Left, node.Right) } -func (node *OrExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.Right, - ) -} - -func (node *OrExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Left, &node.Right) -} - // NotExpr represents a NOT expression. type NotExpr struct { Expr Expr @@ -2329,20 +1816,6 @@ func (node *NotExpr) Format(buf *TrackedBuffer) { buf.Myprintf("not %v", node.Expr) } -func (node *NotExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *NotExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - // ParenExpr represents a parenthesized boolean expression. type ParenExpr struct { Expr Expr @@ -2353,20 +1826,6 @@ func (node *ParenExpr) Format(buf *TrackedBuffer) { buf.Myprintf("(%v)", node.Expr) } -func (node *ParenExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *ParenExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - // ComparisonExpr represents a two-value comparison expression. type ComparisonExpr struct { Operator string @@ -2401,22 +1860,6 @@ func (node *ComparisonExpr) Format(buf *TrackedBuffer) { } } -func (node *ComparisonExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.Right, - node.Escape, - ) -} - -func (node *ComparisonExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Left, &node.Right, &node.Escape) -} - // IsImpossible returns true if the comparison in the expression can never evaluate to true. // Note that this is not currently exhaustive to ALL impossible comparisons. func (node *ComparisonExpr) IsImpossible() bool { @@ -2461,22 +1904,6 @@ func (node *RangeCond) Format(buf *TrackedBuffer) { buf.Myprintf("%v %s %v and %v", node.Left, node.Operator, node.From, node.To) } -func (node *RangeCond) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.From, - node.To, - ) -} - -func (node *RangeCond) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Left, &node.From, &node.To) -} - // IsExpr represents an IS ... or an IS NOT ... expression. type IsExpr struct { Operator string @@ -2498,20 +1925,6 @@ func (node *IsExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v %s", node.Expr, node.Operator) } -func (node *IsExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *IsExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - // ExistsExpr represents an EXISTS expression. type ExistsExpr struct { Subquery *Subquery @@ -2522,20 +1935,6 @@ func (node *ExistsExpr) Format(buf *TrackedBuffer) { buf.Myprintf("exists %v", node.Subquery) } -func (node *ExistsExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Subquery, - ) -} - -func (node *ExistsExpr) replace(from, to Expr) bool { - return false -} - // ExprFromValue converts the given Value into an Expr or returns an error. func ExprFromValue(value sqltypes.Value) (Expr, error) { // The type checks here follow the rules defined in sqltypes/types.go. @@ -2631,14 +2030,6 @@ func (node *SQLVal) Format(buf *TrackedBuffer) { } } -func (node *SQLVal) walkSubtree(visit Visit) error { - return nil -} - -func (node *SQLVal) replace(from, to Expr) bool { - return false -} - // HexDecode decodes the hexval into bytes. func (node *SQLVal) HexDecode() ([]byte, error) { dst := make([]byte, hex.DecodedLen(len([]byte(node.Val)))) @@ -2657,14 +2048,6 @@ func (node *NullVal) Format(buf *TrackedBuffer) { buf.Myprintf("null") } -func (node *NullVal) walkSubtree(visit Visit) error { - return nil -} - -func (node *NullVal) replace(from, to Expr) bool { - return false -} - // BoolVal is true or false. type BoolVal bool @@ -2677,14 +2060,6 @@ func (node BoolVal) Format(buf *TrackedBuffer) { } } -func (node BoolVal) walkSubtree(visit Visit) error { - return nil -} - -func (node BoolVal) replace(from, to Expr) bool { - return false -} - // ColName represents a column name. type ColName struct { // Metadata is not populated by the parser. @@ -2704,21 +2079,6 @@ func (node *ColName) Format(buf *TrackedBuffer) { buf.Myprintf("%v", node.Name) } -func (node *ColName) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Name, - node.Qualifier, - ) -} - -func (node *ColName) replace(from, to Expr) bool { - return false -} - // Equal returns true if the column names match. func (node *ColName) Equal(c *ColName) bool { // Failsafe: ColName should not be empty. @@ -2747,19 +2107,6 @@ func (node ValTuple) Format(buf *TrackedBuffer) { buf.Myprintf("(%v)", Exprs(node)) } -func (node ValTuple) walkSubtree(visit Visit) error { - return Walk(visit, Exprs(node)) -} - -func (node ValTuple) replace(from, to Expr) bool { - for i := range node { - if replaceExprs(from, to, &node[i]) { - return true - } - } - return false -} - // Subquery represents a subquery. type Subquery struct { Select SelectStatement @@ -2770,20 +2117,6 @@ func (node *Subquery) Format(buf *TrackedBuffer) { buf.Myprintf("(%v)", node.Select) } -func (node *Subquery) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Select, - ) -} - -func (node *Subquery) replace(from, to Expr) bool { - return false -} - // ListArg represents a named list argument. type ListArg []byte @@ -2792,14 +2125,6 @@ func (node ListArg) Format(buf *TrackedBuffer) { buf.WriteArg(string(node)) } -func (node ListArg) walkSubtree(visit Visit) error { - return nil -} - -func (node ListArg) replace(from, to Expr) bool { - return false -} - // BinaryExpr represents a binary value expression. type BinaryExpr struct { Operator string @@ -2826,21 +2151,6 @@ func (node *BinaryExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v %s %v", node.Left, node.Operator, node.Right) } -func (node *BinaryExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.Right, - ) -} - -func (node *BinaryExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Left, &node.Right) -} - // UnaryExpr represents a unary value expression. type UnaryExpr struct { Operator string @@ -2867,20 +2177,6 @@ func (node *UnaryExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%s%v", node.Operator, node.Expr) } -func (node *UnaryExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *UnaryExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - // IntervalExpr represents a date-time INTERVAL expression. type IntervalExpr struct { Expr Expr @@ -2892,20 +2188,6 @@ func (node *IntervalExpr) Format(buf *TrackedBuffer) { buf.Myprintf("interval %v %s", node.Expr, node.Unit) } -func (node *IntervalExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *IntervalExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - // TimestampFuncExpr represents the function and arguments for TIMESTAMP{ADD,DIFF} functions. type TimestampFuncExpr struct { Name string @@ -2919,27 +2201,6 @@ func (node *TimestampFuncExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%s(%s, %v, %v)", node.Name, node.Unit, node.Expr1, node.Expr2) } -func (node *TimestampFuncExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr1, - node.Expr2, - ) -} - -func (node *TimestampFuncExpr) replace(from, to Expr) bool { - if replaceExprs(from, to, &node.Expr1) { - return true - } - if replaceExprs(from, to, &node.Expr2) { - return true - } - return false -} - // CurTimeFuncExpr represents the function and arguments for CURRENT DATE/TIME functions // supported functions are documented in the grammar type CurTimeFuncExpr struct { @@ -2952,20 +2213,6 @@ func (node *CurTimeFuncExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%s(%v)", node.Name.String(), node.Fsp) } -func (node *CurTimeFuncExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Fsp, - ) -} - -func (node *CurTimeFuncExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Fsp) -} - // CollateExpr represents dynamic collate operator. type CollateExpr struct { Expr Expr @@ -2977,20 +2224,6 @@ func (node *CollateExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v collate %s", node.Expr, node.Charset) } -func (node *CollateExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *CollateExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - // FuncExpr represents a function call. type FuncExpr struct { Qualifier TableIdent @@ -3014,31 +2247,6 @@ func (node *FuncExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%s(%s%v)", node.Name.String(), distinct, node.Exprs) } -func (node *FuncExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Qualifier, - node.Name, - node.Exprs, - ) -} - -func (node *FuncExpr) replace(from, to Expr) bool { - for _, sel := range node.Exprs { - aliased, ok := sel.(*AliasedExpr) - if !ok { - continue - } - if replaceExprs(from, to, &aliased.Expr) { - return true - } - } - return false -} - // Aggregates is a map of all aggregate functions. var Aggregates = map[string]bool{ "avg": true, @@ -3077,35 +2285,6 @@ func (node *GroupConcatExpr) Format(buf *TrackedBuffer) { buf.Myprintf("group_concat(%s%v%v%s)", node.Distinct, node.Exprs, node.OrderBy, node.Separator) } -func (node *GroupConcatExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Exprs, - node.OrderBy, - ) -} - -func (node *GroupConcatExpr) replace(from, to Expr) bool { - for _, sel := range node.Exprs { - aliased, ok := sel.(*AliasedExpr) - if !ok { - continue - } - if replaceExprs(from, to, &aliased.Expr) { - return true - } - } - for _, order := range node.OrderBy { - if replaceExprs(from, to, &order.Expr) { - return true - } - } - return false -} - // ValuesFuncExpr represents a function call. type ValuesFuncExpr struct { Name *ColName @@ -3116,20 +2295,6 @@ func (node *ValuesFuncExpr) Format(buf *TrackedBuffer) { buf.Myprintf("values(%v)", node.Name) } -func (node *ValuesFuncExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Name, - ) -} - -func (node *ValuesFuncExpr) replace(from, to Expr) bool { - return false -} - // SubstrExpr represents a call to SubstrExpr(column, value_expression) or SubstrExpr(column, value_expression,value_expression) // also supported syntax SubstrExpr(column from value_expression for value_expression). // Additionally to column names, SubstrExpr is also supported for string values, e.g.: @@ -3158,22 +2323,6 @@ func (node *SubstrExpr) Format(buf *TrackedBuffer) { } } -func (node *SubstrExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.From, &node.To) -} - -func (node *SubstrExpr) walkSubtree(visit Visit) error { - if node == nil || node.Name == nil { - return nil - } - return Walk( - visit, - node.Name, - node.From, - node.To, - ) -} - // ConvertExpr represents a call to CONVERT(expr, type) // or it's equivalent CAST(expr AS type). Both are rewritten to the former. type ConvertExpr struct { @@ -3186,21 +2335,6 @@ func (node *ConvertExpr) Format(buf *TrackedBuffer) { buf.Myprintf("convert(%v, %v)", node.Expr, node.Type) } -func (node *ConvertExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - node.Type, - ) -} - -func (node *ConvertExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - // ConvertUsingExpr represents a call to CONVERT(expr USING charset). type ConvertUsingExpr struct { Expr Expr @@ -3212,20 +2346,6 @@ func (node *ConvertUsingExpr) Format(buf *TrackedBuffer) { buf.Myprintf("convert(%v using %s)", node.Expr, node.Type) } -func (node *ConvertUsingExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *ConvertUsingExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - // ConvertType represents the type in call to CONVERT(expr, type) type ConvertType struct { Type string @@ -3256,10 +2376,6 @@ func (node *ConvertType) Format(buf *TrackedBuffer) { } } -func (node *ConvertType) walkSubtree(visit Visit) error { - return nil -} - // MatchExpr represents a call to the MATCH function type MatchExpr struct { Columns SelectExprs @@ -3280,30 +2396,6 @@ func (node *MatchExpr) Format(buf *TrackedBuffer) { buf.Myprintf("match(%v) against (%v%s)", node.Columns, node.Expr, node.Option) } -func (node *MatchExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Columns, - node.Expr, - ) -} - -func (node *MatchExpr) replace(from, to Expr) bool { - for _, sel := range node.Columns { - aliased, ok := sel.(*AliasedExpr) - if !ok { - continue - } - if replaceExprs(from, to, &aliased.Expr) { - return true - } - } - return replaceExprs(from, to, &node.Expr) -} - // CaseExpr represents a CASE expression. type CaseExpr struct { Expr Expr @@ -3326,30 +2418,6 @@ func (node *CaseExpr) Format(buf *TrackedBuffer) { buf.Myprintf("end") } -func (node *CaseExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - if err := Walk(visit, node.Expr); err != nil { - return err - } - for _, n := range node.Whens { - if err := Walk(visit, n); err != nil { - return err - } - } - return Walk(visit, node.Else) -} - -func (node *CaseExpr) replace(from, to Expr) bool { - for _, when := range node.Whens { - if replaceExprs(from, to, &when.Cond, &when.Val) { - return true - } - } - return replaceExprs(from, to, &node.Expr, &node.Else) -} - // Default represents a DEFAULT expression. type Default struct { ColName string @@ -3363,14 +2431,6 @@ func (node *Default) Format(buf *TrackedBuffer) { } } -func (node *Default) walkSubtree(visit Visit) error { - return nil -} - -func (node *Default) replace(from, to Expr) bool { - return false -} - // When represents a WHEN sub-expression. type When struct { Cond Expr @@ -3382,17 +2442,6 @@ func (node *When) Format(buf *TrackedBuffer) { buf.Myprintf("when %v then %v", node.Cond, node.Val) } -func (node *When) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Cond, - node.Val, - ) -} - // GroupBy represents a GROUP BY clause. type GroupBy []Expr @@ -3405,15 +2454,6 @@ func (node GroupBy) Format(buf *TrackedBuffer) { } } -func (node GroupBy) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // OrderBy represents an ORDER By clause. type OrderBy []*Order @@ -3426,15 +2466,6 @@ func (node OrderBy) Format(buf *TrackedBuffer) { } } -func (node OrderBy) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // Order represents an ordering expression. type Order struct { Expr Expr @@ -3463,16 +2494,6 @@ func (node *Order) Format(buf *TrackedBuffer) { buf.Myprintf("%v %s", node.Expr, node.Direction) } -func (node *Order) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - // Limit represents a LIMIT clause. type Limit struct { Offset, Rowcount Expr @@ -3490,17 +2511,6 @@ func (node *Limit) Format(buf *TrackedBuffer) { buf.Myprintf("%v", node.Rowcount) } -func (node *Limit) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Offset, - node.Rowcount, - ) -} - // Values represents a VALUES clause. type Values []ValTuple @@ -3513,15 +2523,6 @@ func (node Values) Format(buf *TrackedBuffer) { } } -func (node Values) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // UpdateExprs represents a list of update expressions. type UpdateExprs []*UpdateExpr @@ -3534,15 +2535,6 @@ func (node UpdateExprs) Format(buf *TrackedBuffer) { } } -func (node UpdateExprs) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // UpdateExpr represents an update expression. type UpdateExpr struct { Name *ColName @@ -3554,17 +2546,6 @@ func (node *UpdateExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v = %v", node.Name, node.Expr) } -func (node *UpdateExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Name, - node.Expr, - ) -} - // SetExprs represents a list of set expressions. type SetExprs []*SetExpr @@ -3577,15 +2558,6 @@ func (node SetExprs) Format(buf *TrackedBuffer) { } } -func (node SetExprs) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - // SetExpr represents a set expression. type SetExpr struct { Name ColIdent @@ -3619,17 +2591,6 @@ func (node *SetExpr) Format(buf *TrackedBuffer) { } } -func (node *SetExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Name, - node.Expr, - ) -} - // OnDup represents an ON DUPLICATE KEY clause. type OnDup UpdateExprs @@ -3641,10 +2602,6 @@ func (node OnDup) Format(buf *TrackedBuffer) { buf.Myprintf(" on duplicate key update %v", UpdateExprs(node)) } -func (node OnDup) walkSubtree(visit Visit) error { - return Walk(visit, UpdateExprs(node)) -} - // ColIdent is a case insensitive SQL identifier. It will be escaped with // backquotes if necessary. type ColIdent struct { @@ -3667,10 +2624,6 @@ func (node ColIdent) Format(buf *TrackedBuffer) { formatID(buf, node.val, node.Lowered()) } -func (node ColIdent) walkSubtree(visit Visit) error { - return nil -} - // IsEmpty returns true if the name is empty. func (node ColIdent) IsEmpty() bool { return node.val == "" @@ -3745,10 +2698,6 @@ func (node TableIdent) Format(buf *TrackedBuffer) { formatID(buf, node.v, strings.ToLower(node.v)) } -func (node TableIdent) walkSubtree(visit Visit) error { - return nil -} - // IsEmpty returns true if TabIdent is empty. func (node TableIdent) IsEmpty() bool { return node.v == "" diff --git a/go/vt/sqlparser/ast_test.go b/go/vt/sqlparser/ast_test.go index 1f18bcb07fa..bc7f58c2046 100644 --- a/go/vt/sqlparser/ast_test.go +++ b/go/vt/sqlparser/ast_test.go @@ -570,13 +570,13 @@ func TestReplaceExpr(t *testing.T) { t.Fatal(err) } var from *Subquery - _ = Walk(func(node SQLNode) (kontinue bool, err error) { + VisitAll(tree, func(node SQLNode) bool { if sq, ok := node.(*Subquery); ok { from = sq - return false, nil + return false } - return true, nil - }, tree) + return true + }) if from == nil { t.Fatalf("from is nil for %s", tcase.in) } diff --git a/go/vt/sqlparser/astrewrite.go b/go/vt/sqlparser/astrewrite.go new file mode 100644 index 00000000000..ab83c066dfe --- /dev/null +++ b/go/vt/sqlparser/astrewrite.go @@ -0,0 +1,817 @@ +/* +Copyright 2019 The Vitess Authors. + +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, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package sqlparser + +import ( + "unsafe" +) + +// WalkFunc describes a function to be called for each node during a Walk. The +// returned node can be used to rewrite the AST. Walking stops if the returned +// bool is false. +type WalkFunc func(SQLNode) (SQLNode, bool) + +// VisitFunc describes a function to be called for each node during a Walk. +// If the function returns false, walking will stop. +type VisitFunc func(SQLNode) bool + +// Identity is a function that will return the same AST after passing through every element in it +var Identity = func(in SQLNode) (SQLNode, bool) { + return in, true +} + +// VisitAll will visit all elements of the AST until one of them returns false +func VisitAll(root SQLNode, fn VisitFunc) { + Walk(root, func(node SQLNode) (SQLNode, bool) { + return node, fn(node) + }) +} + +// do nothing +func (node *Begin) walk(_ WalkFunc) SQLNode { return node } +func (node BoolVal) walk(_ WalkFunc) SQLNode { return node } +func (node Comments) walk(_ WalkFunc) SQLNode { return node } +func (node *Commit) walk(_ WalkFunc) SQLNode { return node } +func (node ColIdent) walk(_ WalkFunc) SQLNode { return node } +func (node *DBDDL) walk(_ WalkFunc) SQLNode { return node } +func (node *Default) walk(_ WalkFunc) SQLNode { return node } +func (node ListArg) walk(_ WalkFunc) SQLNode { return node } +func (node *NullVal) walk(_ WalkFunc) SQLNode { return node } +func (node *OtherRead) walk(_ WalkFunc) SQLNode { return node } +func (node *OtherAdmin) walk(_ WalkFunc) SQLNode { return node } +func (node *SQLVal) walk(_ WalkFunc) SQLNode { return node } +func (node *Rollback) walk(_ WalkFunc) SQLNode { return node } +func (node TableIdent) walk(_ WalkFunc) SQLNode { return node } + +func (node *AliasedExpr) walk(fn WalkFunc) SQLNode { + node.As = Walk(node.As, fn).(ColIdent) + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +func (node *AliasedTableExpr) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(SimpleTableExpr) + } + if node.Partitions != nil { + node.Partitions = Walk(node.Partitions, fn).(Partitions) + } + node.As = Walk(node.As, fn).(TableIdent) + if node.Hints != nil { + node.Hints = Walk(node.Hints, fn).(*IndexHints) + } + return node +} + +func (node *AndExpr) walk(fn WalkFunc) SQLNode { + if node.Left != nil { + node.Left = Walk(node.Left, fn).(Expr) + } + if node.Right != nil { + node.Right = Walk(node.Right, fn).(Expr) + } + return node +} + +func (node *AutoIncSpec) walk(fn WalkFunc) SQLNode { + node.Column = Walk(node.Column, fn).(ColIdent) + node.Sequence = Walk(node.Sequence, fn).(TableName) + return node +} + +func (node *BinaryExpr) walk(fn WalkFunc) SQLNode { + if node.Left != nil { + node.Left = Walk(node.Left, fn).(Expr) + } + if node.Right != nil { + node.Right = Walk(node.Right, fn).(Expr) + } + return node +} + +func (node *CaseExpr) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + for i, p := range node.Whens { + node.Whens[i] = Walk(p, fn).(*When) + } + if node.Else != nil { + node.Else = Walk(node.Else, fn).(Expr) + } + return node +} + +func (node *ColName) walk(fn WalkFunc) SQLNode { + node.Name = Walk(node.Name, fn).(ColIdent) + node.Qualifier = Walk(node.Qualifier, fn).(TableName) + return node +} + +func (node *CollateExpr) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +func (col *ColumnDefinition) walk(fn WalkFunc) SQLNode { + col.Name = Walk(col.Name, fn).(ColIdent) + return col +} + +func (ct *ColumnType) walk(fn WalkFunc) SQLNode { + ct.NotNull = Walk(ct.NotNull, fn).(BoolVal) + ct.Autoincrement = Walk(ct.Autoincrement, fn).(BoolVal) + if ct.Default != nil { + ct.Default = Walk(ct.Default, fn).(Expr) + } + if ct.OnUpdate != nil { + ct.OnUpdate = Walk(ct.OnUpdate, fn).(Expr) + } + if ct.Comment != nil { + ct.Comment = Walk(ct.Comment, fn).(*SQLVal) + } + if ct.Length != nil { + ct.Length = Walk(ct.Length, fn).(*SQLVal) + } + ct.Unsigned = Walk(ct.Unsigned, fn).(BoolVal) + ct.Zerofill = Walk(ct.Zerofill, fn).(BoolVal) + if ct.Scale != nil { + ct.Scale = Walk(ct.Scale, fn).(*SQLVal) + } + return ct +} + +func (node Columns) walk(fn WalkFunc) SQLNode { + for i, p := range node { + node[i] = Walk(p, fn).(ColIdent) + } + return node +} + +func (node *ComparisonExpr) walk(fn WalkFunc) SQLNode { + if node.Left != nil { + node.Left = Walk(node.Left, fn).(Expr) + } + if node.Right != nil { + node.Right = Walk(node.Right, fn).(Expr) + } + if node.Escape != nil { + node.Escape = Walk(node.Escape, fn).(Expr) + } + return node +} + +func (c *ConstraintDefinition) walk(fn WalkFunc) SQLNode { + c.Details = Walk(c.Details, fn).(ConstraintInfo) + return c +} + +func (node *ConvertExpr) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + if node.Type != nil { + node.Type = Walk(node.Type, fn).(*ConvertType) + } + return node +} + +func (node *ConvertType) walk(fn WalkFunc) SQLNode { + if node.Length != nil { + node.Length = Walk(node.Length, fn).(*SQLVal) + } + if node.Scale != nil { + node.Scale = Walk(node.Scale, fn).(*SQLVal) + } + return node +} + +func (node *ConvertUsingExpr) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +func (node *CurTimeFuncExpr) walk(fn WalkFunc) SQLNode { + node.Name = Walk(node.Name, fn).(ColIdent) + if node.Fsp != nil { + node.Fsp = Walk(node.Fsp, fn).(Expr) + } + return node +} + +func (node *Delete) walk(fn WalkFunc) SQLNode { + if node.Comments != nil { + node.Comments = Walk(node.Comments, fn).(Comments) + } + if node.Targets != nil { + node.Targets = Walk(node.Targets, fn).(TableNames) + } + if node.TableExprs != nil { + node.TableExprs = Walk(node.TableExprs, fn).(TableExprs) + } + if node.Partitions != nil { + node.Partitions = Walk(node.Partitions, fn).(Partitions) + } + if node.Where != nil { + node.Where = Walk(node.Where, fn).(*Where) + } + if node.OrderBy != nil { + node.OrderBy = Walk(node.OrderBy, fn).(OrderBy) + } + if node.Limit != nil { + node.Limit = Walk(node.Limit, fn).(*Limit) + } + return node +} + +func (node *DDL) walk(fn WalkFunc) SQLNode { + if node.FromTables != nil { + node.FromTables = Walk(node.FromTables, fn).(TableNames) + } + if node.ToTables != nil { + node.ToTables = Walk(node.ToTables, fn).(TableNames) + } + node.Table = Walk(node.Table, fn).(TableName) + if node.TableSpec != nil { + node.TableSpec = Walk(node.TableSpec, fn).(*TableSpec) + } + if node.OptLike != nil { + node.OptLike = Walk(node.OptLike, fn).(*OptLike) + } + if node.PartitionSpec != nil { + node.PartitionSpec = Walk(node.PartitionSpec, fn).(*PartitionSpec) + } + if node.VindexSpec != nil { + node.VindexSpec = Walk(node.VindexSpec, fn).(*VindexSpec) + } + if node.AutoIncSpec != nil { + node.AutoIncSpec = Walk(node.AutoIncSpec, fn).(*AutoIncSpec) + } + for i, c := range node.VindexCols { + node.VindexCols[i] = Walk(c, fn).(ColIdent) + } + return node +} + +func (node *GroupConcatExpr) walk(fn WalkFunc) SQLNode { + if node.Exprs != nil { + node.Exprs = Walk(node.Exprs, fn).(SelectExprs) + } + if node.OrderBy != nil { + node.OrderBy = Walk(node.OrderBy, fn).(OrderBy) + } + return node +} + +func (node *ExistsExpr) walk(fn WalkFunc) SQLNode { + //node.Subquery = Walk(node.Subquery, fn).(*Subquery) + // TODO - Keep this and document why or rewrite like everything else + // We don't descend into the subquery to keep parity with old behaviour. + if node.Subquery != nil && !isNilValue(node.Subquery) { + _, _ = fn(node.Subquery) + } + return node +} + +func (node Exprs) walk(fn WalkFunc) SQLNode { + for i, p := range node { + node[i] = Walk(p, fn).(Expr) + } + + return node +} + +func (node *FuncExpr) walk(fn WalkFunc) SQLNode { + node.Qualifier = Walk(node.Qualifier, fn).(TableIdent) + node.Name = Walk(node.Name, fn).(ColIdent) + if node.Exprs != nil { + node.Exprs = Walk(node.Exprs, fn).(SelectExprs) + } + return node +} + +func (f *ForeignKeyDefinition) walk(fn WalkFunc) SQLNode { + if f.Source != nil { + f.Source = Walk(f.Source, fn).(Columns) + } + f.ReferencedTable = Walk(f.ReferencedTable, fn).(TableName) + if f.ReferencedColumns != nil { + f.ReferencedColumns = Walk(f.ReferencedColumns, fn).(Columns) + } + return f +} + +func (node GroupBy) walk(fn WalkFunc) SQLNode { + for i, e := range node { + node[i] = Walk(e, fn).(Expr) + } + return node +} +func (idx *IndexDefinition) walk(fn WalkFunc) SQLNode { + if idx.Info != nil { + idx.Info = Walk(idx.Info, fn).(*IndexInfo) + } + return idx +} + +func (ii *IndexInfo) walk(fn WalkFunc) SQLNode { + ii.Name = Walk(ii.Name, fn).(ColIdent) + return ii +} + +func (node *IndexHints) walk(fn WalkFunc) SQLNode { + for i, p := range node.Indexes { + node.Indexes[i] = Walk(p, fn).(ColIdent) + } + return node +} + +func (node *IntervalExpr) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +func (node *Insert) walk(fn WalkFunc) SQLNode { + if node.Comments != nil { + node.Comments = Walk(node.Comments, fn).(Comments) + } + node.Table = Walk(node.Table, fn).(TableName) + if node.Partitions != nil { + node.Partitions = Walk(node.Partitions, fn).(Partitions) + } + if node.Columns != nil { + node.Columns = Walk(node.Columns, fn).(Columns) + } + if node.Rows != nil { + node.Rows = Walk(node.Rows, fn).(InsertRows) + } + if node.OnDup != nil { + node.OnDup = Walk(node.OnDup, fn).(OnDup) + } + return node +} + +func (node *IsExpr) walk(fn WalkFunc) SQLNode { + node.Expr = Walk(node.Expr, fn).(Expr) + return node +} + +func (node *JoinTableExpr) walk(fn WalkFunc) SQLNode { + if node.LeftExpr != nil { + node.LeftExpr = Walk(node.LeftExpr, fn).(TableExpr) + } + if node.RightExpr != nil { + node.RightExpr = Walk(node.RightExpr, fn).(TableExpr) + } + node.Condition = Walk(node.Condition, fn).(JoinCondition) + return node +} + +func (node JoinCondition) walk(fn WalkFunc) SQLNode { + if node.On != nil { + node.On = Walk(node.On, fn).(Expr) + } + if node.Using != nil { + node.Using = Walk(node.Using, fn).(Columns) + } + return node +} + +func (node *Limit) walk(fn WalkFunc) SQLNode { + if node.Offset != nil { + node.Offset = Walk(node.Offset, fn).(Expr) + } + if node.Rowcount != nil { + node.Rowcount = Walk(node.Rowcount, fn).(Expr) + } + return node +} + +func (node *MatchExpr) walk(fn WalkFunc) SQLNode { + if node.Columns != nil { + node.Columns = Walk(node.Columns, fn).(SelectExprs) + } + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +func (node Nextval) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +func (node *NotExpr) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +func (node *OptLike) walk(fn WalkFunc) SQLNode { + node.LikeTable = Walk(node.LikeTable, fn).(TableName) + return node +} + +func (node *Order) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +func (node OnDup) walk(fn WalkFunc) SQLNode { + for i, t := range node { + node[i] = Walk(t, fn).(*UpdateExpr) + } + return node +} + +func (node OrderBy) walk(fn WalkFunc) SQLNode { + for i, p := range node { + node[i] = Walk(p, fn).(*Order) + } + return node +} + +func (node *OrExpr) walk(fn WalkFunc) SQLNode { + if node.Left != nil { + node.Left = Walk(node.Left, fn).(Expr) + } + if node.Right != nil { + node.Right = Walk(node.Right, fn).(Expr) + } + return node +} + +func (node *ParenExpr) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +func (node *ParenSelect) walk(fn WalkFunc) SQLNode { + node.Select = Walk(node.Select, fn).(SelectStatement) + return node +} + +func (node *ParenTableExpr) walk(fn WalkFunc) SQLNode { + if node.Exprs != nil { + node.Exprs = Walk(node.Exprs, fn).(TableExprs) + } + return node +} + +func (node Partitions) walk(fn WalkFunc) SQLNode { + for i, p := range node { + node[i] = Walk(p, fn).(ColIdent) + } + return node +} + +func (node *PartitionSpec) walk(fn WalkFunc) SQLNode { + node.Name = Walk(node.Name, fn).(ColIdent) + for i, pd := range node.Definitions { + node.Definitions[i] = Walk(pd, fn).(*PartitionDefinition) + } + return node +} + +func (node *PartitionDefinition) walk(fn WalkFunc) SQLNode { + node.Name = Walk(node.Name, fn).(ColIdent) + if node.Limit != nil { + node.Limit = Walk(node.Limit, fn).(Expr) + } + return node +} + +func (node *Set) walk(fn WalkFunc) SQLNode { + if node.Comments != nil { + node.Comments = Walk(node.Comments, fn).(Comments) + } + if node.Exprs != nil { + node.Exprs = Walk(node.Exprs, fn).(SetExprs) + } + return node +} + +func (node *SetExpr) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + node.Name = Walk(node.Name, fn).(ColIdent) + return node +} + +func (node *Select) walk(fn WalkFunc) SQLNode { + if node.Comments != nil { + node.Comments = Walk(node.Comments, fn).(Comments) + } + if node.SelectExprs != nil { + node.SelectExprs = Walk(node.SelectExprs, fn).(SelectExprs) + } + if node.From != nil { + node.From = Walk(node.From, fn).(TableExprs) + } + if node.Where != nil { + node.Where = Walk(node.Where, fn).(*Where) + } + if node.GroupBy != nil { + node.GroupBy = Walk(node.GroupBy, fn).(GroupBy) + } + if node.Having != nil { + node.Having = Walk(node.Having, fn).(*Where) + } + if node.OrderBy != nil { + node.OrderBy = Walk(node.OrderBy, fn).(OrderBy) + } + if node.Limit != nil { + node.Limit = Walk(node.Limit, fn).(*Limit) + } + return node +} + +func (node SelectExprs) walk(fn WalkFunc) SQLNode { + for i, e := range node { + node[i] = Walk(e, fn).(SelectExpr) + } + return node +} + +func (node SetExprs) walk(fn WalkFunc) SQLNode { + for i, e := range node { + node[i] = Walk(e, fn).(*SetExpr) + } + return node +} + +func (node *Show) walk(fn WalkFunc) SQLNode { + node.OnTable = Walk(node.OnTable, fn).(TableName) + node.Table = Walk(node.Table, fn).(TableName) + if node.ShowCollationFilterOpt != nil { + node.ShowCollationFilterOpt = Walk(node.ShowCollationFilterOpt, fn).(Expr) + } + return node +} + +func (node *ShowFilter) walk(fn WalkFunc) SQLNode { + if node.Filter != nil { + node.Filter = Walk(node.Filter, fn).(Expr) + } + return node +} + +func (node *StarExpr) walk(fn WalkFunc) SQLNode { + node.TableName = Walk(node.TableName, fn).(TableName) + return node +} + +func (node *Stream) walk(fn WalkFunc) SQLNode { + if node.Comments != nil { + node.Comments = Walk(node.Comments, fn).(Comments) + } + if node.SelectExpr != nil { + node.SelectExpr = Walk(node.SelectExpr, fn).(SelectExpr) + } + node.Table = Walk(node.Table, fn).(TableName) + return node +} + +func (node *Subquery) walk(fn WalkFunc) SQLNode { + if node.Select != nil { + node.Select = Walk(node.Select, fn).(SelectStatement) + } + return node +} + +func (node *SubstrExpr) walk(fn WalkFunc) SQLNode { + if node.Name != nil { + node.Name = Walk(node.Name, fn).(*ColName) + } + if node.StrVal != nil { + node.StrVal = Walk(node.StrVal, fn).(*SQLVal) + } + if node.From != nil { + node.From = Walk(node.From, fn).(Expr) + } + if node.To != nil { + node.To = Walk(node.To, fn).(Expr) + } + return node +} + +func (node *RangeCond) walk(fn WalkFunc) SQLNode { + if node.Left != nil { + node.Left = Walk(node.Left, fn).(Expr) + } + if node.From != nil { + node.From = Walk(node.From, fn).(Expr) + } + if node.To != nil { + node.To = Walk(node.To, fn).(Expr) + } + return node +} + +func (node TableExprs) walk(fn WalkFunc) SQLNode { + for i, t := range node { + node[i] = Walk(t, fn).(TableExpr) + } + return node +} + +func (node TableNames) walk(fn WalkFunc) SQLNode { + for i, t := range node { + node[i] = Walk(t, fn).(TableName) + } + return node +} + +func (node TableName) walk(fn WalkFunc) SQLNode { + node.Name = Walk(node.Name, fn).(TableIdent) + node.Qualifier = Walk(node.Qualifier, fn).(TableIdent) + return node +} + +func (ts *TableSpec) walk(fn WalkFunc) SQLNode { + for i, o := range ts.Columns { + ts.Columns[i] = Walk(o, fn).(*ColumnDefinition) + } + for i, o := range ts.Indexes { + ts.Indexes[i] = Walk(o, fn).(*IndexDefinition) + } + for i, o := range ts.Constraints { + ts.Constraints[i] = Walk(o, fn).(*ConstraintDefinition) + } + return ts +} + +func (node *TimestampFuncExpr) walk(fn WalkFunc) SQLNode { + if node.Expr1 != nil { + node.Expr1 = Walk(node.Expr1, fn).(Expr) + } + if node.Expr2 != nil { + node.Expr2 = Walk(node.Expr2, fn).(Expr) + } + return node +} + +func (node *UnaryExpr) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +func (node *Union) walk(fn WalkFunc) SQLNode { + if node.Left != nil { + node.Left = Walk(node.Left, fn).(SelectStatement) + } + if node.Right != nil { + node.Right = Walk(node.Right, fn).(SelectStatement) + } + if node.OrderBy != nil { + node.OrderBy = Walk(node.OrderBy, fn).(OrderBy) + } + if node.Limit != nil { + node.Limit = Walk(node.Limit, fn).(*Limit) + } + return node +} + +func (node *Update) walk(fn WalkFunc) SQLNode { + if node.Comments != nil { + node.Comments = Walk(node.Comments, fn).(Comments) + } + if node.TableExprs != nil { + node.TableExprs = Walk(node.TableExprs, fn).(TableExprs) + } + if node.Exprs != nil { + node.Exprs = Walk(node.Exprs, fn).(UpdateExprs) + } + if node.Where != nil { + node.Where = Walk(node.Where, fn).(*Where) + } + if node.OrderBy != nil { + node.OrderBy = Walk(node.OrderBy, fn).(OrderBy) + } + if node.Limit != nil { + node.Limit = Walk(node.Limit, fn).(*Limit) + } + return node +} + +func (node *UpdateExpr) walk(fn WalkFunc) SQLNode { + node.Name = Walk(node.Name, fn).(*ColName) + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +func (node UpdateExprs) walk(fn WalkFunc) SQLNode { + for i, t := range node { + node[i] = Walk(t, fn).(*UpdateExpr) + } + return node +} + +func (node *Use) walk(fn WalkFunc) SQLNode { + node.DBName = Walk(node.DBName, fn).(TableIdent) + return node +} + +func (node Values) walk(fn WalkFunc) SQLNode { + for i, v := range node { + node[i] = Walk(v, fn).(ValTuple) + } + return node +} + +func (node *ValuesFuncExpr) walk(fn WalkFunc) SQLNode { + if node.Name != nil { + node.Name = Walk(node.Name, fn).(*ColName) + } + return node +} + +func (node ValTuple) walk(fn WalkFunc) SQLNode { + for i, v := range node { + node[i] = Walk(v, fn).(Expr) + } + return node +} + +func (node *VindexSpec) walk(fn WalkFunc) SQLNode { + node.Name = Walk(node.Name, fn).(ColIdent) + node.Type = Walk(node.Type, fn).(ColIdent) + return node +} + +func (node *When) walk(fn WalkFunc) SQLNode { + if node.Cond != nil { + node.Cond = Walk(node.Cond, fn).(Expr) + } + if node.Val != nil { + node.Val = Walk(node.Val, fn).(Expr) + } + return node +} + +func (node *Where) walk(fn WalkFunc) SQLNode { + if node.Expr != nil { + node.Expr = Walk(node.Expr, fn).(Expr) + } + return node +} + +// Walk traverses an AST in depth-first order: It starts by calling +// fn(node); node must not be nil. It returns the rewritten node. If fn returns +// true, Walk invokes fn recursively for each of the non-nil children of node, +// followed by a call of fn(nil). The returned node of fn can be used to +// rewrite the passed node to fn. Panics if the returned type is not the same +// type as the original one. +func Walk(root SQLNode, fn WalkFunc) SQLNode { + if root == nil || isNilValue(root) { + return nil + } + + rewritten, continueDown := fn(root) + if !continueDown { + return rewritten + } + + return rewritten.walk(fn) +} + +// This hack is for speed and less code. +// It allows us to not have to do explicit nil checks in every single `walk` implementation in this file +func isNilValue(i interface{}) bool { + return (*[2]uintptr)(unsafe.Pointer(&i))[1] == 0 +} diff --git a/go/vt/sqlparser/astrewrite_test.go b/go/vt/sqlparser/astrewrite_test.go new file mode 100644 index 00000000000..bf3650f7cbe --- /dev/null +++ b/go/vt/sqlparser/astrewrite_test.go @@ -0,0 +1,49 @@ +/* +Copyright 2019 The Vitess Authors. + +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, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package sqlparser + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSimple(t *testing.T) { + statement, err := Parse("select 1 + 2") + assert.NoError(t, err) + + result := Walk(statement, func(node SQLNode) (SQLNode, bool) { + + a, ok := node.(*BinaryExpr) + if ok { + tmp := a.Left + a.Left = a.Right + a.Right = tmp + return a, true + } + + return node, true + }) + + expected, err := Parse("select 2 + 1") + assert.NoError(t, err) + + buf := NewTrackedBuffer(nil) + result.Format(buf) + fmt.Println(buf.String()) + assert.Equal(t, expected, result) +} diff --git a/go/vt/sqlparser/normalizer.go b/go/vt/sqlparser/normalizer.go index f715c8f4620..65d29a7a3eb 100644 --- a/go/vt/sqlparser/normalizer.go +++ b/go/vt/sqlparser/normalizer.go @@ -33,7 +33,7 @@ import ( // treated as distinct. func Normalize(stmt Statement, bindVars map[string]*querypb.BindVariable, prefix string) { nz := newNormalizer(stmt, bindVars, prefix) - _ = Walk(nz.WalkStatement, stmt) + VisitAll(stmt, nz.WalkStatement) } type normalizer struct { @@ -59,12 +59,12 @@ func newNormalizer(stmt Statement, bindVars map[string]*querypb.BindVariable, pr // WalkStatement is the top level walk function. // If it encounters a Select, it switches to a mode // where variables are deduped. -func (nz *normalizer) WalkStatement(node SQLNode) (bool, error) { +func (nz *normalizer) WalkStatement(node SQLNode) bool { switch node := node.(type) { case *Select: - _ = Walk(nz.WalkSelect, node) + VisitAll(node, nz.WalkSelect) // Don't continue - return false, nil + return false case *SQLVal: nz.convertSQLVal(node) case *ComparisonExpr: @@ -72,13 +72,13 @@ func (nz *normalizer) WalkStatement(node SQLNode) (bool, error) { case *ColName, TableName: // Common node types that never contain SQLVals or ListArgs but create a lot of object // allocations. - return false, nil + return false } - return true, nil + return true } // WalkSelect normalizes the AST in Select mode. -func (nz *normalizer) WalkSelect(node SQLNode) (bool, error) { +func (nz *normalizer) WalkSelect(node SQLNode) bool { switch node := node.(type) { case *SQLVal: nz.convertSQLValDedup(node) @@ -87,12 +87,12 @@ func (nz *normalizer) WalkSelect(node SQLNode) (bool, error) { case *ColName, TableName: // Common node types that never contain SQLVals or ListArgs but create a lot of object // allocations. - return false, nil + return false case OrderBy, GroupBy: // do not make a bind var for order by column_position - return false, nil + return false } - return true, nil + return true } func (nz *normalizer) convertSQLValDedup(node *SQLVal) { @@ -220,12 +220,12 @@ func (nz *normalizer) newName() string { // Ideally, this should be done only once. func GetBindvars(stmt Statement) map[string]struct{} { bindvars := make(map[string]struct{}) - _ = Walk(func(node SQLNode) (kontinue bool, err error) { + VisitAll(stmt, func(node SQLNode) bool { switch node := node.(type) { case *ColName, TableName: // Common node types that never contain SQLVals or ListArgs but create a lot of object // allocations. - return false, nil + return false case *SQLVal: if node.Type == ValArg { bindvars[string(node.Val[1:])] = struct{}{} @@ -233,7 +233,7 @@ func GetBindvars(stmt Statement) map[string]struct{} { case ListArg: bindvars[string(node[2:])] = struct{}{} } - return true, nil - }, stmt) + return true + }) return bindvars } diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index 564edccefc5..e8d058da344 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -1489,9 +1489,7 @@ func TestValid(t *testing.T) { // There's no way automated way to verify that a node calls // all its children. But we can examine code coverage and // ensure that all walkSubtree functions were called. - Walk(func(node SQLNode) (bool, error) { - return true, nil - }, tree) + Walk(tree, Identity) } } diff --git a/go/vt/sqlparser/sql.go b/go/vt/sqlparser/sql.go index ab9a9ad7337..4df257b734d 100644 --- a/go/vt/sqlparser/sql.go +++ b/go/vt/sqlparser/sql.go @@ -5198,429 +5198,427 @@ yydefault: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:1585 { - // Cannot dereference $4 directly, or else the parser stackcannot be pooled. See yyParsePooled - showCollationFilterOpt := yyDollar[4].expr - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), ShowCollationFilterOpt: &showCollationFilterOpt} + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), ShowCollationFilterOpt: yyDollar[4].expr} } case 280: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1591 +//line sql.y:1589 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[4].showFilter} yyVAL.statement = &Show{Scope: string(yyDollar[2].bytes), Type: string(yyDollar[3].bytes), ShowTablesOpt: showTablesOpt} } case 281: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1596 +//line sql.y:1594 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 282: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1600 +//line sql.y:1598 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } case 283: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1604 +//line sql.y:1602 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), OnTable: yyDollar[5].tableName} } case 284: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1608 +//line sql.y:1606 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 285: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1622 +//line sql.y:1620 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } case 286: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1628 +//line sql.y:1626 { yyVAL.str = string(yyDollar[1].bytes) } case 287: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1632 +//line sql.y:1630 { yyVAL.str = string(yyDollar[1].bytes) } case 288: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1638 +//line sql.y:1636 { yyVAL.str = "" } case 289: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1642 +//line sql.y:1640 { yyVAL.str = "full " } case 290: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1648 +//line sql.y:1646 { yyVAL.str = string(yyDollar[1].bytes) } case 291: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1652 +//line sql.y:1650 { yyVAL.str = string(yyDollar[1].bytes) } case 292: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1658 +//line sql.y:1656 { yyVAL.str = "" } case 293: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1662 +//line sql.y:1660 { yyVAL.str = yyDollar[2].tableIdent.v } case 294: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1666 +//line sql.y:1664 { yyVAL.str = yyDollar[2].tableIdent.v } case 295: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1672 +//line sql.y:1670 { yyVAL.showFilter = nil } case 296: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1676 +//line sql.y:1674 { yyVAL.showFilter = &ShowFilter{Like: string(yyDollar[2].bytes)} } case 297: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1680 +//line sql.y:1678 { yyVAL.showFilter = &ShowFilter{Filter: yyDollar[2].expr} } case 298: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1686 +//line sql.y:1684 { yyVAL.showFilter = nil } case 299: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1690 +//line sql.y:1688 { yyVAL.showFilter = &ShowFilter{Like: string(yyDollar[2].bytes)} } case 300: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1696 +//line sql.y:1694 { yyVAL.str = "" } case 301: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1700 +//line sql.y:1698 { yyVAL.str = SessionStr } case 302: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1704 +//line sql.y:1702 { yyVAL.str = GlobalStr } case 303: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1710 +//line sql.y:1708 { yyVAL.statement = &Use{DBName: yyDollar[2].tableIdent} } case 304: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1714 +//line sql.y:1712 { yyVAL.statement = &Use{DBName: TableIdent{v: ""}} } case 305: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1720 +//line sql.y:1718 { yyVAL.statement = &Begin{} } case 306: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1724 +//line sql.y:1722 { yyVAL.statement = &Begin{} } case 307: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1730 +//line sql.y:1728 { yyVAL.statement = &Commit{} } case 308: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1736 +//line sql.y:1734 { yyVAL.statement = &Rollback{} } case 309: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1742 +//line sql.y:1740 { yyVAL.statement = &OtherRead{} } case 310: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1746 +//line sql.y:1744 { yyVAL.statement = &OtherRead{} } case 311: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1750 +//line sql.y:1748 { yyVAL.statement = &OtherRead{} } case 312: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1754 +//line sql.y:1752 { yyVAL.statement = &OtherAdmin{} } case 313: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1758 +//line sql.y:1756 { yyVAL.statement = &OtherAdmin{} } case 314: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1762 +//line sql.y:1760 { yyVAL.statement = &OtherAdmin{} } case 315: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1766 +//line sql.y:1764 { yyVAL.statement = &OtherAdmin{} } case 316: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1772 +//line sql.y:1770 { yyVAL.statement = &DDL{Action: FlushStr} } case 317: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1776 +//line sql.y:1774 { setAllowComments(yylex, true) } case 318: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1780 +//line sql.y:1778 { yyVAL.bytes2 = yyDollar[2].bytes2 setAllowComments(yylex, false) } case 319: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1786 +//line sql.y:1784 { yyVAL.bytes2 = nil } case 320: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1790 +//line sql.y:1788 { yyVAL.bytes2 = append(yyDollar[1].bytes2, yyDollar[2].bytes) } case 321: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1796 +//line sql.y:1794 { yyVAL.str = UnionStr } case 322: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1800 +//line sql.y:1798 { yyVAL.str = UnionAllStr } case 323: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1804 +//line sql.y:1802 { yyVAL.str = UnionDistinctStr } case 324: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1809 +//line sql.y:1807 { yyVAL.str = "" } case 325: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1813 +//line sql.y:1811 { yyVAL.str = SQLNoCacheStr } case 326: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1817 +//line sql.y:1815 { yyVAL.str = SQLCacheStr } case 327: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1822 +//line sql.y:1820 { yyVAL.str = "" } case 328: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1826 +//line sql.y:1824 { yyVAL.str = DistinctStr } case 329: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1831 +//line sql.y:1829 { yyVAL.str = "" } case 330: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1835 +//line sql.y:1833 { yyVAL.str = StraightJoinHint } case 331: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1840 +//line sql.y:1838 { yyVAL.selectExprs = nil } case 332: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1844 +//line sql.y:1842 { yyVAL.selectExprs = yyDollar[1].selectExprs } case 333: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1850 +//line sql.y:1848 { yyVAL.selectExprs = SelectExprs{yyDollar[1].selectExpr} } case 334: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1854 +//line sql.y:1852 { yyVAL.selectExprs = append(yyVAL.selectExprs, yyDollar[3].selectExpr) } case 335: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1860 +//line sql.y:1858 { yyVAL.selectExpr = &StarExpr{} } case 336: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1864 +//line sql.y:1862 { yyVAL.selectExpr = &AliasedExpr{Expr: yyDollar[1].expr, As: yyDollar[2].colIdent} } case 337: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1868 +//line sql.y:1866 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Name: yyDollar[1].tableIdent}} } case 338: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1872 +//line sql.y:1870 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}} } case 339: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1877 +//line sql.y:1875 { yyVAL.colIdent = ColIdent{} } case 340: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1881 +//line sql.y:1879 { yyVAL.colIdent = yyDollar[1].colIdent } case 341: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1885 +//line sql.y:1883 { yyVAL.colIdent = yyDollar[2].colIdent } case 343: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1892 +//line sql.y:1890 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } case 344: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1897 +//line sql.y:1895 { yyVAL.tableExprs = TableExprs{&AliasedTableExpr{Expr: TableName{Name: NewTableIdent("dual")}}} } case 345: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1901 +//line sql.y:1899 { yyVAL.tableExprs = yyDollar[2].tableExprs } case 346: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1907 +//line sql.y:1905 { yyVAL.tableExprs = TableExprs{yyDollar[1].tableExpr} } case 347: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1911 +//line sql.y:1909 { yyVAL.tableExprs = append(yyVAL.tableExprs, yyDollar[3].tableExpr) } case 350: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1921 +//line sql.y:1919 { yyVAL.tableExpr = yyDollar[1].aliasedTableName } case 351: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1925 +//line sql.y:1923 { yyVAL.tableExpr = &AliasedTableExpr{Expr: yyDollar[1].subquery, As: yyDollar[3].tableIdent} } case 352: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1929 +//line sql.y:1927 { // missed alias for subquery yylex.Error("Every derived table must have its own alias") @@ -5628,199 +5626,199 @@ yydefault: } case 353: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1935 +//line sql.y:1933 { yyVAL.tableExpr = &ParenTableExpr{Exprs: yyDollar[2].tableExprs} } case 354: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1941 +//line sql.y:1939 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, As: yyDollar[2].tableIdent, Hints: yyDollar[3].indexHints} } case 355: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1945 +//line sql.y:1943 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, Partitions: yyDollar[4].partitions, As: yyDollar[6].tableIdent, Hints: yyDollar[7].indexHints} } case 356: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1951 +//line sql.y:1949 { yyVAL.columns = Columns{yyDollar[1].colIdent} } case 357: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1955 +//line sql.y:1953 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } case 358: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1961 +//line sql.y:1959 { yyVAL.partitions = Partitions{yyDollar[1].colIdent} } case 359: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1965 +//line sql.y:1963 { yyVAL.partitions = append(yyVAL.partitions, yyDollar[3].colIdent) } case 360: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1978 +//line sql.y:1976 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } case 361: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1982 +//line sql.y:1980 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } case 362: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1986 +//line sql.y:1984 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } case 363: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1990 +//line sql.y:1988 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr} } case 364: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1996 +//line sql.y:1994 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } case 365: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1998 +//line sql.y:1996 { yyVAL.joinCondition = JoinCondition{Using: yyDollar[3].columns} } case 366: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2002 +//line sql.y:2000 { yyVAL.joinCondition = JoinCondition{} } case 367: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2004 +//line sql.y:2002 { yyVAL.joinCondition = yyDollar[1].joinCondition } case 368: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2008 +//line sql.y:2006 { yyVAL.joinCondition = JoinCondition{} } case 369: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2010 +//line sql.y:2008 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } case 370: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2013 +//line sql.y:2011 { yyVAL.empty = struct{}{} } case 371: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2015 +//line sql.y:2013 { yyVAL.empty = struct{}{} } case 372: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2018 +//line sql.y:2016 { yyVAL.tableIdent = NewTableIdent("") } case 373: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2022 +//line sql.y:2020 { yyVAL.tableIdent = yyDollar[1].tableIdent } case 374: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2026 +//line sql.y:2024 { yyVAL.tableIdent = yyDollar[2].tableIdent } case 376: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2033 +//line sql.y:2031 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } case 377: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2039 +//line sql.y:2037 { yyVAL.str = JoinStr } case 378: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2043 +//line sql.y:2041 { yyVAL.str = JoinStr } case 379: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2047 +//line sql.y:2045 { yyVAL.str = JoinStr } case 380: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2053 +//line sql.y:2051 { yyVAL.str = StraightJoinStr } case 381: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2059 +//line sql.y:2057 { yyVAL.str = LeftJoinStr } case 382: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2063 +//line sql.y:2061 { yyVAL.str = LeftJoinStr } case 383: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2067 +//line sql.y:2065 { yyVAL.str = RightJoinStr } case 384: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2071 +//line sql.y:2069 { yyVAL.str = RightJoinStr } case 385: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2077 +//line sql.y:2075 { yyVAL.str = NaturalJoinStr } case 386: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2081 +//line sql.y:2079 { if yyDollar[2].str == LeftJoinStr { yyVAL.str = NaturalLeftJoinStr @@ -5830,463 +5828,463 @@ yydefault: } case 387: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2091 +//line sql.y:2089 { yyVAL.tableName = yyDollar[2].tableName } case 388: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2095 +//line sql.y:2093 { yyVAL.tableName = yyDollar[1].tableName } case 389: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2101 +//line sql.y:2099 { yyVAL.tableName = TableName{Name: yyDollar[1].tableIdent} } case 390: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2105 +//line sql.y:2103 { yyVAL.tableName = TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent} } case 391: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2111 +//line sql.y:2109 { yyVAL.tableName = TableName{Name: yyDollar[1].tableIdent} } case 392: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2116 +//line sql.y:2114 { yyVAL.indexHints = nil } case 393: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2120 +//line sql.y:2118 { yyVAL.indexHints = &IndexHints{Type: UseStr, Indexes: yyDollar[4].columns} } case 394: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2124 +//line sql.y:2122 { yyVAL.indexHints = &IndexHints{Type: IgnoreStr, Indexes: yyDollar[4].columns} } case 395: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2128 +//line sql.y:2126 { yyVAL.indexHints = &IndexHints{Type: ForceStr, Indexes: yyDollar[4].columns} } case 396: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2133 +//line sql.y:2131 { yyVAL.expr = nil } case 397: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2137 +//line sql.y:2135 { yyVAL.expr = yyDollar[2].expr } case 398: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2143 +//line sql.y:2141 { yyVAL.expr = yyDollar[1].expr } case 399: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2147 +//line sql.y:2145 { yyVAL.expr = &AndExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } case 400: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2151 +//line sql.y:2149 { yyVAL.expr = &OrExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } case 401: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2155 +//line sql.y:2153 { yyVAL.expr = &NotExpr{Expr: yyDollar[2].expr} } case 402: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2159 +//line sql.y:2157 { yyVAL.expr = &IsExpr{Operator: yyDollar[3].str, Expr: yyDollar[1].expr} } case 403: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2163 +//line sql.y:2161 { yyVAL.expr = yyDollar[1].expr } case 404: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2167 +//line sql.y:2165 { yyVAL.expr = &Default{ColName: yyDollar[2].str} } case 405: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2173 +//line sql.y:2171 { yyVAL.str = "" } case 406: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2177 +//line sql.y:2175 { yyVAL.str = string(yyDollar[2].bytes) } case 407: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2183 +//line sql.y:2181 { yyVAL.boolVal = BoolVal(true) } case 408: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2187 +//line sql.y:2185 { yyVAL.boolVal = BoolVal(false) } case 409: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2193 +//line sql.y:2191 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: yyDollar[2].str, Right: yyDollar[3].expr} } case 410: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2197 +//line sql.y:2195 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: InStr, Right: yyDollar[3].colTuple} } case 411: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2201 +//line sql.y:2199 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotInStr, Right: yyDollar[4].colTuple} } case 412: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2205 +//line sql.y:2203 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: LikeStr, Right: yyDollar[3].expr, Escape: yyDollar[4].expr} } case 413: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2209 +//line sql.y:2207 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotLikeStr, Right: yyDollar[4].expr, Escape: yyDollar[5].expr} } case 414: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2213 +//line sql.y:2211 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: RegexpStr, Right: yyDollar[3].expr} } case 415: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2217 +//line sql.y:2215 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotRegexpStr, Right: yyDollar[4].expr} } case 416: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2221 +//line sql.y:2219 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: BetweenStr, From: yyDollar[3].expr, To: yyDollar[5].expr} } case 417: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2225 +//line sql.y:2223 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: NotBetweenStr, From: yyDollar[4].expr, To: yyDollar[6].expr} } case 418: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2229 +//line sql.y:2227 { yyVAL.expr = &ExistsExpr{Subquery: yyDollar[2].subquery} } case 419: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2235 +//line sql.y:2233 { yyVAL.str = IsNullStr } case 420: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2239 +//line sql.y:2237 { yyVAL.str = IsNotNullStr } case 421: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2243 +//line sql.y:2241 { yyVAL.str = IsTrueStr } case 422: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2247 +//line sql.y:2245 { yyVAL.str = IsNotTrueStr } case 423: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2251 +//line sql.y:2249 { yyVAL.str = IsFalseStr } case 424: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2255 +//line sql.y:2253 { yyVAL.str = IsNotFalseStr } case 425: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2261 +//line sql.y:2259 { yyVAL.str = EqualStr } case 426: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2265 +//line sql.y:2263 { yyVAL.str = LessThanStr } case 427: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2269 +//line sql.y:2267 { yyVAL.str = GreaterThanStr } case 428: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2273 +//line sql.y:2271 { yyVAL.str = LessEqualStr } case 429: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2277 +//line sql.y:2275 { yyVAL.str = GreaterEqualStr } case 430: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2281 +//line sql.y:2279 { yyVAL.str = NotEqualStr } case 431: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2285 +//line sql.y:2283 { yyVAL.str = NullSafeEqualStr } case 432: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2290 +//line sql.y:2288 { yyVAL.expr = nil } case 433: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2294 +//line sql.y:2292 { yyVAL.expr = yyDollar[2].expr } case 434: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2300 +//line sql.y:2298 { yyVAL.colTuple = yyDollar[1].valTuple } case 435: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2304 +//line sql.y:2302 { yyVAL.colTuple = yyDollar[1].subquery } case 436: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2308 +//line sql.y:2306 { yyVAL.colTuple = ListArg(yyDollar[1].bytes) } case 437: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2314 +//line sql.y:2312 { yyVAL.subquery = &Subquery{yyDollar[2].selStmt} } case 438: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2320 +//line sql.y:2318 { yyVAL.exprs = Exprs{yyDollar[1].expr} } case 439: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2324 +//line sql.y:2322 { yyVAL.exprs = append(yyDollar[1].exprs, yyDollar[3].expr) } case 440: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2330 +//line sql.y:2328 { yyVAL.expr = yyDollar[1].expr } case 441: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2334 +//line sql.y:2332 { yyVAL.expr = yyDollar[1].boolVal } case 442: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2338 +//line sql.y:2336 { yyVAL.expr = yyDollar[1].colName } case 443: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2342 +//line sql.y:2340 { yyVAL.expr = yyDollar[1].expr } case 444: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2346 +//line sql.y:2344 { yyVAL.expr = yyDollar[1].subquery } case 445: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2350 +//line sql.y:2348 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitAndStr, Right: yyDollar[3].expr} } case 446: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2354 +//line sql.y:2352 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitOrStr, Right: yyDollar[3].expr} } case 447: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2358 +//line sql.y:2356 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitXorStr, Right: yyDollar[3].expr} } case 448: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2362 +//line sql.y:2360 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: PlusStr, Right: yyDollar[3].expr} } case 449: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2366 +//line sql.y:2364 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MinusStr, Right: yyDollar[3].expr} } case 450: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2370 +//line sql.y:2368 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MultStr, Right: yyDollar[3].expr} } case 451: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2374 +//line sql.y:2372 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: DivStr, Right: yyDollar[3].expr} } case 452: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2378 +//line sql.y:2376 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: IntDivStr, Right: yyDollar[3].expr} } case 453: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2382 +//line sql.y:2380 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModStr, Right: yyDollar[3].expr} } case 454: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2386 +//line sql.y:2384 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModStr, Right: yyDollar[3].expr} } case 455: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2390 +//line sql.y:2388 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftLeftStr, Right: yyDollar[3].expr} } case 456: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2394 +//line sql.y:2392 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftRightStr, Right: yyDollar[3].expr} } case 457: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2398 +//line sql.y:2396 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONExtractOp, Right: yyDollar[3].expr} } case 458: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2402 +//line sql.y:2400 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONUnquoteExtractOp, Right: yyDollar[3].expr} } case 459: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2406 +//line sql.y:2404 { yyVAL.expr = &CollateExpr{Expr: yyDollar[1].expr, Charset: yyDollar[3].str} } case 460: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2410 +//line sql.y:2408 { yyVAL.expr = &UnaryExpr{Operator: BinaryStr, Expr: yyDollar[2].expr} } case 461: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2414 +//line sql.y:2412 { yyVAL.expr = &UnaryExpr{Operator: UBinaryStr, Expr: yyDollar[2].expr} } case 462: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2418 +//line sql.y:2416 { yyVAL.expr = &UnaryExpr{Operator: Utf8mb4Str, Expr: yyDollar[2].expr} } case 463: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2422 +//line sql.y:2420 { if num, ok := yyDollar[2].expr.(*SQLVal); ok && num.Type == IntVal { yyVAL.expr = num @@ -6296,7 +6294,7 @@ yydefault: } case 464: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2430 +//line sql.y:2428 { if num, ok := yyDollar[2].expr.(*SQLVal); ok && num.Type == IntVal { // Handle double negative @@ -6312,19 +6310,19 @@ yydefault: } case 465: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2444 +//line sql.y:2442 { yyVAL.expr = &UnaryExpr{Operator: TildaStr, Expr: yyDollar[2].expr} } case 466: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2448 +//line sql.y:2446 { yyVAL.expr = &UnaryExpr{Operator: BangStr, Expr: yyDollar[2].expr} } case 467: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2452 +//line sql.y:2450 { // This rule prevents the usage of INTERVAL // as a function. If support is needed for that, @@ -6334,313 +6332,313 @@ yydefault: } case 472: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2470 +//line sql.y:2468 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Exprs: yyDollar[3].selectExprs} } case 473: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2474 +//line sql.y:2472 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Distinct: true, Exprs: yyDollar[4].selectExprs} } case 474: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2478 +//line sql.y:2476 { yyVAL.expr = &FuncExpr{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].colIdent, Exprs: yyDollar[5].selectExprs} } case 475: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2488 +//line sql.y:2486 { yyVAL.expr = &FuncExpr{Name: NewColIdent("left"), Exprs: yyDollar[3].selectExprs} } case 476: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2492 +//line sql.y:2490 { yyVAL.expr = &FuncExpr{Name: NewColIdent("right"), Exprs: yyDollar[3].selectExprs} } case 477: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2496 +//line sql.y:2494 { yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } case 478: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2500 +//line sql.y:2498 { yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } case 479: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2504 +//line sql.y:2502 { yyVAL.expr = &ConvertUsingExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].str} } case 480: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2508 +//line sql.y:2506 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } case 481: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2512 +//line sql.y:2510 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } case 482: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2516 +//line sql.y:2514 { yyVAL.expr = &SubstrExpr{StrVal: NewStrVal(yyDollar[3].bytes), From: yyDollar[5].expr, To: yyDollar[7].expr} } case 483: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2520 +//line sql.y:2518 { yyVAL.expr = &SubstrExpr{StrVal: NewStrVal(yyDollar[3].bytes), From: yyDollar[5].expr, To: yyDollar[7].expr} } case 484: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:2524 +//line sql.y:2522 { yyVAL.expr = &MatchExpr{Columns: yyDollar[3].selectExprs, Expr: yyDollar[7].expr, Option: yyDollar[8].str} } case 485: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:2528 +//line sql.y:2526 { yyVAL.expr = &GroupConcatExpr{Distinct: yyDollar[3].str, Exprs: yyDollar[4].selectExprs, OrderBy: yyDollar[5].orderBy, Separator: yyDollar[6].str} } case 486: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2532 +//line sql.y:2530 { yyVAL.expr = &CaseExpr{Expr: yyDollar[2].expr, Whens: yyDollar[3].whens, Else: yyDollar[4].expr} } case 487: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2536 +//line sql.y:2534 { yyVAL.expr = &ValuesFuncExpr{Name: yyDollar[3].colName} } case 488: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2546 +//line sql.y:2544 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_timestamp")} } case 489: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2550 +//line sql.y:2548 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_timestamp")} } case 490: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2554 +//line sql.y:2552 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_time")} } case 491: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2559 +//line sql.y:2557 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_date")} } case 492: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2564 +//line sql.y:2562 { yyVAL.expr = &FuncExpr{Name: NewColIdent("localtime")} } case 493: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2569 +//line sql.y:2567 { yyVAL.expr = &FuncExpr{Name: NewColIdent("localtimestamp")} } case 494: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2575 +//line sql.y:2573 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_date")} } case 495: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2580 +//line sql.y:2578 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_time")} } case 496: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2585 +//line sql.y:2583 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_timestamp"), Fsp: yyDollar[2].expr} } case 497: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2589 +//line sql.y:2587 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_timestamp"), Fsp: yyDollar[2].expr} } case 498: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2593 +//line sql.y:2591 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_time"), Fsp: yyDollar[2].expr} } case 499: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2598 +//line sql.y:2596 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtime"), Fsp: yyDollar[2].expr} } case 500: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2603 +//line sql.y:2601 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtimestamp"), Fsp: yyDollar[2].expr} } case 501: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2608 +//line sql.y:2606 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_time"), Fsp: yyDollar[2].expr} } case 502: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2612 +//line sql.y:2610 { yyVAL.expr = &TimestampFuncExpr{Name: string("timestampadd"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} } case 503: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2616 +//line sql.y:2614 { yyVAL.expr = &TimestampFuncExpr{Name: string("timestampdiff"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} } case 506: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2626 +//line sql.y:2624 { yyVAL.expr = yyDollar[2].expr } case 507: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2636 +//line sql.y:2634 { yyVAL.expr = &FuncExpr{Name: NewColIdent("if"), Exprs: yyDollar[3].selectExprs} } case 508: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2640 +//line sql.y:2638 { yyVAL.expr = &FuncExpr{Name: NewColIdent("database"), Exprs: yyDollar[3].selectExprs} } case 509: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2644 +//line sql.y:2642 { yyVAL.expr = &FuncExpr{Name: NewColIdent("mod"), Exprs: yyDollar[3].selectExprs} } case 510: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2648 +//line sql.y:2646 { yyVAL.expr = &FuncExpr{Name: NewColIdent("replace"), Exprs: yyDollar[3].selectExprs} } case 511: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2652 +//line sql.y:2650 { yyVAL.expr = &FuncExpr{Name: NewColIdent("substr"), Exprs: yyDollar[3].selectExprs} } case 512: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2656 +//line sql.y:2654 { yyVAL.expr = &FuncExpr{Name: NewColIdent("substr"), Exprs: yyDollar[3].selectExprs} } case 513: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2662 +//line sql.y:2660 { yyVAL.str = "" } case 514: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2666 +//line sql.y:2664 { yyVAL.str = BooleanModeStr } case 515: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2670 +//line sql.y:2668 { yyVAL.str = NaturalLanguageModeStr } case 516: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:2674 +//line sql.y:2672 { yyVAL.str = NaturalLanguageModeWithQueryExpansionStr } case 517: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2678 +//line sql.y:2676 { yyVAL.str = QueryExpansionStr } case 518: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2684 +//line sql.y:2682 { yyVAL.str = string(yyDollar[1].bytes) } case 519: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2688 +//line sql.y:2686 { yyVAL.str = string(yyDollar[1].bytes) } case 520: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2694 +//line sql.y:2692 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } case 521: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2698 +//line sql.y:2696 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal, Charset: yyDollar[3].str, Operator: CharacterSetStr} } case 522: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2702 +//line sql.y:2700 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal, Charset: string(yyDollar[3].bytes)} } case 523: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2706 +//line sql.y:2704 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 524: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2710 +//line sql.y:2708 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } case 525: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2714 +//line sql.y:2712 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} yyVAL.convertType.Length = yyDollar[2].LengthScaleOption.Length @@ -6648,169 +6646,169 @@ yydefault: } case 526: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2720 +//line sql.y:2718 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 527: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2724 +//line sql.y:2722 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } case 528: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2728 +//line sql.y:2726 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 529: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2732 +//line sql.y:2730 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 530: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2736 +//line sql.y:2734 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } case 531: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2740 +//line sql.y:2738 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 532: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2744 +//line sql.y:2742 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 533: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2749 +//line sql.y:2747 { yyVAL.expr = nil } case 534: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2753 +//line sql.y:2751 { yyVAL.expr = yyDollar[1].expr } case 535: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2758 +//line sql.y:2756 { yyVAL.str = string("") } case 536: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2762 +//line sql.y:2760 { yyVAL.str = " separator '" + string(yyDollar[2].bytes) + "'" } case 537: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2768 +//line sql.y:2766 { yyVAL.whens = []*When{yyDollar[1].when} } case 538: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2772 +//line sql.y:2770 { yyVAL.whens = append(yyDollar[1].whens, yyDollar[2].when) } case 539: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2778 +//line sql.y:2776 { yyVAL.when = &When{Cond: yyDollar[2].expr, Val: yyDollar[4].expr} } case 540: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2783 +//line sql.y:2781 { yyVAL.expr = nil } case 541: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2787 +//line sql.y:2785 { yyVAL.expr = yyDollar[2].expr } case 542: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2793 +//line sql.y:2791 { yyVAL.colName = &ColName{Name: yyDollar[1].colIdent} } case 543: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2797 +//line sql.y:2795 { yyVAL.colName = &ColName{Qualifier: TableName{Name: yyDollar[1].tableIdent}, Name: yyDollar[3].colIdent} } case 544: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2801 +//line sql.y:2799 { yyVAL.colName = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}, Name: yyDollar[5].colIdent} } case 545: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2807 +//line sql.y:2805 { yyVAL.expr = NewStrVal(yyDollar[1].bytes) } case 546: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2811 +//line sql.y:2809 { yyVAL.expr = NewHexVal(yyDollar[1].bytes) } case 547: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2815 +//line sql.y:2813 { yyVAL.expr = NewBitVal(yyDollar[1].bytes) } case 548: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2819 +//line sql.y:2817 { yyVAL.expr = NewIntVal(yyDollar[1].bytes) } case 549: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2823 +//line sql.y:2821 { yyVAL.expr = NewFloatVal(yyDollar[1].bytes) } case 550: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2827 +//line sql.y:2825 { yyVAL.expr = NewHexNum(yyDollar[1].bytes) } case 551: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2831 +//line sql.y:2829 { yyVAL.expr = NewValArg(yyDollar[1].bytes) } case 552: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2835 +//line sql.y:2833 { yyVAL.expr = &NullVal{} } case 553: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2841 +//line sql.y:2839 { // TODO(sougou): Deprecate this construct. if yyDollar[1].colIdent.Lowered() != "value" { @@ -6821,237 +6819,237 @@ yydefault: } case 554: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2850 +//line sql.y:2848 { yyVAL.expr = NewIntVal(yyDollar[1].bytes) } case 555: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2854 +//line sql.y:2852 { yyVAL.expr = NewValArg(yyDollar[1].bytes) } case 556: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2859 +//line sql.y:2857 { yyVAL.exprs = nil } case 557: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2863 +//line sql.y:2861 { yyVAL.exprs = yyDollar[3].exprs } case 558: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2868 +//line sql.y:2866 { yyVAL.expr = nil } case 559: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2872 +//line sql.y:2870 { yyVAL.expr = yyDollar[2].expr } case 560: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2877 +//line sql.y:2875 { yyVAL.orderBy = nil } case 561: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2881 +//line sql.y:2879 { yyVAL.orderBy = yyDollar[3].orderBy } case 562: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2887 +//line sql.y:2885 { yyVAL.orderBy = OrderBy{yyDollar[1].order} } case 563: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2891 +//line sql.y:2889 { yyVAL.orderBy = append(yyDollar[1].orderBy, yyDollar[3].order) } case 564: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2897 +//line sql.y:2895 { yyVAL.order = &Order{Expr: yyDollar[1].expr, Direction: yyDollar[2].str} } case 565: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2902 +//line sql.y:2900 { yyVAL.str = AscScr } case 566: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2906 +//line sql.y:2904 { yyVAL.str = AscScr } case 567: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2910 +//line sql.y:2908 { yyVAL.str = DescScr } case 568: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2915 +//line sql.y:2913 { yyVAL.limit = nil } case 569: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2919 +//line sql.y:2917 { yyVAL.limit = &Limit{Rowcount: yyDollar[2].expr} } case 570: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2923 +//line sql.y:2921 { yyVAL.limit = &Limit{Offset: yyDollar[2].expr, Rowcount: yyDollar[4].expr} } case 571: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2927 +//line sql.y:2925 { yyVAL.limit = &Limit{Offset: yyDollar[4].expr, Rowcount: yyDollar[2].expr} } case 572: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2932 +//line sql.y:2930 { yyVAL.str = "" } case 573: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2936 +//line sql.y:2934 { yyVAL.str = ForUpdateStr } case 574: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2940 +//line sql.y:2938 { yyVAL.str = ShareModeStr } case 575: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2953 +//line sql.y:2951 { yyVAL.ins = &Insert{Rows: yyDollar[2].values} } case 576: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2957 +//line sql.y:2955 { yyVAL.ins = &Insert{Rows: yyDollar[1].selStmt} } case 577: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2961 +//line sql.y:2959 { // Drop the redundant parenthesis. yyVAL.ins = &Insert{Rows: yyDollar[2].selStmt} } case 578: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2966 +//line sql.y:2964 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].values} } case 579: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2970 +//line sql.y:2968 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[4].selStmt} } case 580: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2974 +//line sql.y:2972 { // Drop the redundant parenthesis. yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].selStmt} } case 581: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2981 +//line sql.y:2979 { yyVAL.columns = Columns{yyDollar[1].colIdent} } case 582: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2985 +//line sql.y:2983 { yyVAL.columns = Columns{yyDollar[3].colIdent} } case 583: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2989 +//line sql.y:2987 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } case 584: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2993 +//line sql.y:2991 { yyVAL.columns = append(yyVAL.columns, yyDollar[5].colIdent) } case 585: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2998 +//line sql.y:2996 { yyVAL.updateExprs = nil } case 586: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3002 +//line sql.y:3000 { yyVAL.updateExprs = yyDollar[5].updateExprs } case 587: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3008 +//line sql.y:3006 { yyVAL.values = Values{yyDollar[1].valTuple} } case 588: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3012 +//line sql.y:3010 { yyVAL.values = append(yyDollar[1].values, yyDollar[3].valTuple) } case 589: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3018 +//line sql.y:3016 { yyVAL.valTuple = yyDollar[1].valTuple } case 590: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3022 +//line sql.y:3020 { yyVAL.valTuple = ValTuple{} } case 591: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3028 +//line sql.y:3026 { yyVAL.valTuple = ValTuple(yyDollar[2].exprs) } case 592: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3034 +//line sql.y:3032 { if len(yyDollar[1].valTuple) == 1 { yyVAL.expr = &ParenExpr{yyDollar[1].valTuple[0]} @@ -7061,277 +7059,277 @@ yydefault: } case 593: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3044 +//line sql.y:3042 { yyVAL.updateExprs = UpdateExprs{yyDollar[1].updateExpr} } case 594: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3048 +//line sql.y:3046 { yyVAL.updateExprs = append(yyDollar[1].updateExprs, yyDollar[3].updateExpr) } case 595: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3054 +//line sql.y:3052 { yyVAL.updateExpr = &UpdateExpr{Name: yyDollar[1].colName, Expr: yyDollar[3].expr} } case 596: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3060 +//line sql.y:3058 { yyVAL.setExprs = SetExprs{yyDollar[1].setExpr} } case 597: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3064 +//line sql.y:3062 { yyVAL.setExprs = append(yyDollar[1].setExprs, yyDollar[3].setExpr) } case 598: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3070 +//line sql.y:3068 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Expr: NewStrVal([]byte("on"))} } case 599: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3074 +//line sql.y:3072 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Expr: NewStrVal([]byte("off"))} } case 600: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3078 +//line sql.y:3076 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Expr: yyDollar[3].expr} } case 601: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3082 +//line sql.y:3080 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(string(yyDollar[1].bytes)), Expr: yyDollar[2].expr} } case 603: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3089 +//line sql.y:3087 { yyVAL.bytes = []byte("charset") } case 605: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3096 +//line sql.y:3094 { yyVAL.expr = NewStrVal([]byte(yyDollar[1].colIdent.String())) } case 606: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3100 +//line sql.y:3098 { yyVAL.expr = NewStrVal(yyDollar[1].bytes) } case 607: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3104 +//line sql.y:3102 { yyVAL.expr = &Default{} } case 610: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3113 +//line sql.y:3111 { yyVAL.byt = 0 } case 611: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3115 +//line sql.y:3113 { yyVAL.byt = 1 } case 612: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3118 +//line sql.y:3116 { yyVAL.empty = struct{}{} } case 613: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3120 +//line sql.y:3118 { yyVAL.empty = struct{}{} } case 614: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3123 +//line sql.y:3121 { yyVAL.str = "" } case 615: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3125 +//line sql.y:3123 { yyVAL.str = IgnoreStr } case 616: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3129 +//line sql.y:3127 { yyVAL.empty = struct{}{} } case 617: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3131 +//line sql.y:3129 { yyVAL.empty = struct{}{} } case 618: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3133 +//line sql.y:3131 { yyVAL.empty = struct{}{} } case 619: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3135 +//line sql.y:3133 { yyVAL.empty = struct{}{} } case 620: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3137 +//line sql.y:3135 { yyVAL.empty = struct{}{} } case 621: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3139 +//line sql.y:3137 { yyVAL.empty = struct{}{} } case 622: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3141 +//line sql.y:3139 { yyVAL.empty = struct{}{} } case 623: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3143 +//line sql.y:3141 { yyVAL.empty = struct{}{} } case 624: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3145 +//line sql.y:3143 { yyVAL.empty = struct{}{} } case 625: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3147 +//line sql.y:3145 { yyVAL.empty = struct{}{} } case 626: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3150 +//line sql.y:3148 { yyVAL.empty = struct{}{} } case 627: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3152 +//line sql.y:3150 { yyVAL.empty = struct{}{} } case 628: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3154 +//line sql.y:3152 { yyVAL.empty = struct{}{} } case 629: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3158 +//line sql.y:3156 { yyVAL.empty = struct{}{} } case 630: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3160 +//line sql.y:3158 { yyVAL.empty = struct{}{} } case 631: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3163 +//line sql.y:3161 { yyVAL.empty = struct{}{} } case 632: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3165 +//line sql.y:3163 { yyVAL.empty = struct{}{} } case 633: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3167 +//line sql.y:3165 { yyVAL.empty = struct{}{} } case 634: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3170 +//line sql.y:3168 { yyVAL.colIdent = ColIdent{} } case 635: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3172 +//line sql.y:3170 { yyVAL.colIdent = yyDollar[2].colIdent } case 636: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3176 +//line sql.y:3174 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } case 637: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3180 +//line sql.y:3178 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } case 639: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3187 +//line sql.y:3185 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } case 640: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3193 +//line sql.y:3191 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } case 641: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3197 +//line sql.y:3195 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } case 643: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3204 +//line sql.y:3202 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } case 930: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3516 +//line sql.y:3514 { if incNesting(yylex) { yylex.Error("max nesting level reached") @@ -7340,31 +7338,31 @@ yydefault: } case 931: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3525 +//line sql.y:3523 { decNesting(yylex) } case 932: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3530 +//line sql.y:3528 { skipToEnd(yylex) } case 933: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3535 +//line sql.y:3533 { skipToEnd(yylex) } case 934: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3539 +//line sql.y:3537 { skipToEnd(yylex) } case 935: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3543 +//line sql.y:3541 { skipToEnd(yylex) } diff --git a/go/vt/sqlparser/sql.y b/go/vt/sqlparser/sql.y index 10b363b3065..c2333591836 100644 --- a/go/vt/sqlparser/sql.y +++ b/go/vt/sqlparser/sql.y @@ -1583,9 +1583,7 @@ show_statement: } | SHOW COLLATION WHERE expression { - // Cannot dereference $4 directly, or else the parser stackcannot be pooled. See yyParsePooled - showCollationFilterOpt := $4 - $$ = &Show{Type: string($2), ShowCollationFilterOpt: &showCollationFilterOpt} + $$ = &Show{Type: string($2), ShowCollationFilterOpt: $4} } | SHOW VITESS_METADATA VARIABLES like_opt { diff --git a/go/vt/vtgate/planbuilder/expr.go b/go/vt/vtgate/planbuilder/expr.go index 2e4bd4baeaa..0aa8bf59a45 100644 --- a/go/vt/vtgate/planbuilder/expr.go +++ b/go/vt/vtgate/planbuilder/expr.go @@ -19,7 +19,9 @@ package planbuilder import ( "bytes" "errors" - "fmt" + + "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/engine" @@ -97,12 +99,14 @@ func (pb *primitiveBuilder) findOrigin(expr sqlparser.Expr) (pullouts []*pullout // pulled out. constructsMap := make(map[*sqlparser.Subquery]sqlparser.Expr) - err = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + var failure error + sqlparser.VisitAll(expr, func(node sqlparser.SQLNode) bool { switch node := node.(type) { case *sqlparser.ColName: newOrigin, isLocal, err := pb.st.Find(node) if err != nil { - return false, err + failure = err + return false } if isLocal && newOrigin.Order() > highestOrigin.Order() { highestOrigin = newOrigin @@ -120,14 +124,17 @@ func (pb *primitiveBuilder) findOrigin(expr sqlparser.Expr) (pullouts []*pullout switch stmt := node.Select.(type) { case *sqlparser.Select: if err := spb.processSelect(stmt, pb.st); err != nil { - return false, err + failure = err + return false } case *sqlparser.Union: if err := spb.processUnion(stmt, pb.st); err != nil { - return false, err + failure = err + return false } default: - return false, fmt.Errorf("BUG: unexpected SELECT type: %T", node) + failure = vterrors.Errorf(vtrpc.Code_INTERNAL, "BUG: unexpected SELECT type: %T", node) + return false } sqi := subqueryInfo{ ast: node, @@ -149,21 +156,22 @@ func (pb *primitiveBuilder) findOrigin(expr sqlparser.Expr) (pullouts []*pullout } } subqueries = append(subqueries, sqi) - return false, nil + return false case *sqlparser.FuncExpr: switch { // If it's last_insert_id, ensure it's a single unsharded route. case node.Name.EqualString("last_insert_id"): if rb, isRoute := pb.bldr.(*route); !isRoute || !rb.removeShardedOptions() { - return false, errors.New("unsupported: LAST_INSERT_ID is only allowed for unsharded keyspaces") + failure = vterrors.New(vtrpc.Code_INVALID_ARGUMENT, "unsupported: LAST_INSERT_ID is only allowed for unsharded keyspaces") + return false } } - return true, nil + return true } - return true, nil - }, expr) - if err != nil { - return nil, nil, nil, err + return true + }) + if failure != nil { + return nil, nil, nil, failure } highestRoute, _ := highestOrigin.(*route) @@ -230,13 +238,13 @@ func (pb *primitiveBuilder) findOrigin(expr sqlparser.Expr) (pullouts []*pullout func hasSubquery(node sqlparser.SQLNode) bool { has := false - _ = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + sqlparser.VisitAll(node, func(node sqlparser.SQLNode) bool { if _, ok := node.(*sqlparser.Subquery); ok { has = true - return false, errors.New("dummy") + return false } - return true, nil - }, node) + return true + }) return has } @@ -252,54 +260,54 @@ func (pb *primitiveBuilder) finalizeUnshardedDMLSubqueries(nodes ...sqlparser.SQ for _, node := range nodes { samePlan := true inSubQuery := false - _ = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + sqlparser.VisitAll(node, func(node sqlparser.SQLNode) bool { switch nodeType := node.(type) { case *sqlparser.Subquery, *sqlparser.Insert: inSubQuery = true - return true, nil + return true case *sqlparser.Select: if !inSubQuery { - return true, nil + return true } spb := newPrimitiveBuilder(pb.vschema, pb.jt) if err := spb.processSelect(nodeType, pb.st); err != nil { samePlan = false - return false, err + return false } innerRoute, ok := spb.bldr.(*route) if !ok { samePlan = false - return false, errors.New("dummy") + return false } if !innerRoute.removeOptionsWithUnmatchedKeyspace(keyspace) { samePlan = false - return false, errors.New("dummy") + return false } for _, sub := range innerRoute.routeOptions[0].substitutions { *sub.oldExpr = *sub.newExpr } case *sqlparser.Union: if !inSubQuery { - return true, nil + return true } spb := newPrimitiveBuilder(pb.vschema, pb.jt) if err := spb.processUnion(nodeType, pb.st); err != nil { samePlan = false - return false, err + return false } innerRoute, ok := spb.bldr.(*route) if !ok { samePlan = false - return false, errors.New("dummy") + return false } if !innerRoute.removeOptionsWithUnmatchedKeyspace(keyspace) { samePlan = false - return false, errors.New("dummy") + return false } } - return true, nil - }, node) + return true + }) if !samePlan { return false } diff --git a/go/vt/vtgate/planbuilder/join.go b/go/vt/vtgate/planbuilder/join.go index 6ec4abffce4..ff8ad7551fd 100644 --- a/go/vt/vtgate/planbuilder/join.go +++ b/go/vt/vtgate/planbuilder/join.go @@ -235,18 +235,21 @@ func (jb *join) PushOrderBy(orderBy sqlparser.OrderBy) (builder, error) { } else { // Analyze column references within the expression to make sure they all // go to the left. - err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + var err error + sqlparser.VisitAll(order.Expr, func(node sqlparser.SQLNode) bool { switch node := node.(type) { case *sqlparser.ColName: if node.Metadata.(*column).Origin().Order() > jb.Left.Order() { - return false, errors.New("unsupported: order by spans across shards") + err = errors.New("unsupported: order by spans across shards") + return false } case *sqlparser.Subquery: // Unreachable because ResolveSymbols perfoms this check up above. - return false, errors.New("unsupported: order by has subquery") + err = errors.New("unsupported: order by has subquery") + return false } - return true, nil - }, order.Expr) + return true + }) if err != nil { return newMemorySort(jb, orderBy) } diff --git a/go/vt/vtgate/planbuilder/ordered_aggregate.go b/go/vt/vtgate/planbuilder/ordered_aggregate.go index d7c76dd0f5a..8bebb66a46f 100644 --- a/go/vt/vtgate/planbuilder/ordered_aggregate.go +++ b/go/vt/vtgate/planbuilder/ordered_aggregate.go @@ -141,22 +141,22 @@ func (pb *primitiveBuilder) checkAggregates(sel *sqlparser.Select) error { func nodeHasAggregates(node sqlparser.SQLNode) bool { hasAggregates := false - _ = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + sqlparser.VisitAll(node, func(node sqlparser.SQLNode) bool { switch node := node.(type) { case *sqlparser.FuncExpr: if node.IsAggregate() { hasAggregates = true - return false, errors.New("unused error") + return false } case *sqlparser.GroupConcatExpr: hasAggregates = true - return false, errors.New("unused error") + return false case *sqlparser.Subquery: // Subqueries are analyzed by themselves. - return false, nil + return false } - return true, nil - }, node) + return true + }) return hasAggregates } diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go index 1f58eadbda8..daafeb9f3b8 100644 --- a/go/vt/vtgate/planbuilder/route.go +++ b/go/vt/vtgate/planbuilder/route.go @@ -273,9 +273,10 @@ func (rb *route) Wireup(bldr builder, jt *jointab) error { } // Fix up the AST. - _ = sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) { + sqlparser.VisitAll(rb.Select, func(node sqlparser.SQLNode) bool { switch node := node.(type) { case *sqlparser.Select: + // If empty SELECT, make it SELECT 1 if len(node.SelectExprs) == 0 { node.SelectExprs = sqlparser.SelectExprs([]sqlparser.SelectExpr{ &sqlparser.AliasedExpr{ @@ -284,14 +285,15 @@ func (rb *route) Wireup(bldr builder, jt *jointab) error { }) } case *sqlparser.ComparisonExpr: + // 12 = column => column = 12 if node.Operator == sqlparser.EqualStr { if ro.exprIsValue(node.Left) && !ro.exprIsValue(node.Right) { node.Left, node.Right = node.Right, node.Left } } } - return true, nil - }, rb.Select) + return true + }) // Substitute table names for _, sub := range ro.substitutions { diff --git a/go/vt/vtgate/planbuilder/symtab.go b/go/vt/vtgate/planbuilder/symtab.go index 654245c3187..f85db00596f 100644 --- a/go/vt/vtgate/planbuilder/symtab.go +++ b/go/vt/vtgate/planbuilder/symtab.go @@ -433,17 +433,21 @@ func BuildColName(rcs []*resultColumn, index int) (*sqlparser.ColName, error) { // If a symbol cannot be resolved or if the expression contains // a subquery, an error is returned. func (st *symtab) ResolveSymbols(node sqlparser.SQLNode) error { - return sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + var failure error + sqlparser.VisitAll(node, func(node sqlparser.SQLNode) bool { switch node := node.(type) { case *sqlparser.ColName: if _, _, err := st.Find(node); err != nil { - return false, err + failure = err + return false } case *sqlparser.Subquery: - return false, errors.New("unsupported: subqueries disallowed in GROUP or ORDER BY") + failure = errors.New("unsupported: subqueries disallowed in GROUP or ORDER BY") + return false } - return true, nil - }, node) + return true + }) + return failure } // table is part of symtab. diff --git a/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go b/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go index 95104a0a944..27ba49ca1a1 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go +++ b/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go @@ -344,23 +344,27 @@ func (tpb *tablePlanBuilder) analyzeExpr(selExpr sqlparser.SelectExpr) (*colExpr return cexpr, nil } } - err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + var err error + sqlparser.VisitAll(aliased.Expr, func(node sqlparser.SQLNode) bool { switch node := node.(type) { case *sqlparser.ColName: if !node.Qualifier.IsEmpty() { - return false, fmt.Errorf("unsupported qualifier for column: %v", sqlparser.String(node)) + err = fmt.Errorf("unsupported qualifier for column: %v", sqlparser.String(node)) + return false } tpb.addCol(node.Name) cexpr.references[node.Name.Lowered()] = true case *sqlparser.Subquery: - return false, fmt.Errorf("unsupported subquery: %v", sqlparser.String(node)) + err = fmt.Errorf("unsupported subquery: %v", sqlparser.String(node)) + return false case *sqlparser.FuncExpr: if node.IsAggregate() { - return false, fmt.Errorf("unexpected: %v", sqlparser.String(node)) + err = fmt.Errorf("unexpected: %v", sqlparser.String(node)) + return false } } - return true, nil - }, aliased.Expr) + return true + }) if err != nil { return nil, err } diff --git a/go/vt/vttablet/tabletserver/planbuilder/permission.go b/go/vt/vttablet/tabletserver/planbuilder/permission.go index 5fe98438d95..d886cdbb53c 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/permission.go +++ b/go/vt/vttablet/tabletserver/planbuilder/permission.go @@ -64,15 +64,15 @@ func BuildPermissions(stmt sqlparser.Statement) []Permission { } func buildSubqueryPermissions(stmt sqlparser.Statement, role tableacl.Role, permissions []Permission) []Permission { - _ = sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) { + sqlparser.VisitAll(stmt, func(node sqlparser.SQLNode) bool { switch node := node.(type) { case *sqlparser.Select: permissions = buildTableExprsPermissions(node.From, role, permissions) case sqlparser.TableExprs: - return false, nil + return false } - return true, nil - }, stmt) + return true + }) return permissions } diff --git a/go/vt/vttablet/tabletserver/planbuilder/plan.go b/go/vt/vttablet/tabletserver/planbuilder/plan.go index 87e119f3c52..199563b24e5 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/plan.go +++ b/go/vt/vttablet/tabletserver/planbuilder/plan.go @@ -349,15 +349,18 @@ func BuildMessageStreaming(name string, tables map[string]*schema.Table) (*Plan, // a call to GET_LOCK(), which is unsafe with server-side connection pooling. // For more background, see https://github.com/vitessio/vitess/issues/3631. func checkForPoolingUnsafeConstructs(expr sqlparser.SQLNode) error { - return sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + var failure error + sqlparser.VisitAll(expr, func(node sqlparser.SQLNode) bool { if f, ok := node.(*sqlparser.FuncExpr); ok { if f.Name.Lowered() == "get_lock" { - return false, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "get_lock() not allowed") + failure = vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "get_lock() not allowed") + return false } } // TODO: This could be smarter about not walking down parts of the AST that can't contain // function calls. - return true, nil - }, expr) + return true + }) + return failure }