410 lines
8.1 KiB
Go
410 lines
8.1 KiB
Go
// Copyright 2015 PingCAP, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package ast
|
|
|
|
import (
|
|
"github.com/pingcap/tidb/model"
|
|
)
|
|
|
|
var (
|
|
_ DMLNode = &InsertStmt{}
|
|
_ DMLNode = &DeleteStmt{}
|
|
_ DMLNode = &UpdateStmt{}
|
|
_ DMLNode = &SelectStmt{}
|
|
_ Node = &Join{}
|
|
_ Node = &Union{}
|
|
_ Node = &TableRef{}
|
|
_ Node = &TableSource{}
|
|
_ Node = &Assignment{}
|
|
)
|
|
|
|
// JoinType is join type, including cross/left/right/full.
|
|
type JoinType int
|
|
|
|
const (
|
|
// CrossJoin is cross join type.
|
|
CrossJoin JoinType = iota + 1
|
|
// LeftJoin is left Join type.
|
|
LeftJoin
|
|
// RightJoin is right Join type.
|
|
RightJoin
|
|
)
|
|
|
|
// Join represents table join.
|
|
type Join struct {
|
|
node
|
|
|
|
// Left table can be TableSource or JoinNode.
|
|
Left Node
|
|
// Right table can be TableSource or JoinNode or nil.
|
|
Right Node
|
|
// Tp represents join type.
|
|
Tp JoinType
|
|
}
|
|
|
|
// Accept implements Node Accept interface.
|
|
func (j *Join) Accept(v Visitor) (Node, bool) {
|
|
if !v.Enter(j) {
|
|
return j, false
|
|
}
|
|
node, ok := j.Left.Accept(v)
|
|
if !ok {
|
|
return j, false
|
|
}
|
|
j.Left = node
|
|
if j.Right != nil {
|
|
node, ok = j.Right.Accept(v)
|
|
if !ok {
|
|
return j, false
|
|
}
|
|
j.Right = node
|
|
}
|
|
return v.Leave(j)
|
|
}
|
|
|
|
// TableRef represents a reference to actual table.
|
|
type TableRef struct {
|
|
node
|
|
|
|
Schema model.CIStr
|
|
Name model.CIStr
|
|
}
|
|
|
|
// Accept implements Node Accept interface.
|
|
func (tr *TableRef) Accept(v Visitor) (Node, bool) {
|
|
if !v.Enter(tr) {
|
|
return tr, false
|
|
}
|
|
return v.Leave(tr)
|
|
}
|
|
|
|
// TableSource represents table source with a name.
|
|
type TableSource struct {
|
|
node
|
|
|
|
// Source is the source of the data, can be a TableRef,
|
|
// a SubQuery, or a JoinNode.
|
|
Source Node
|
|
|
|
// Name is the alias name of the table source.
|
|
Name string
|
|
}
|
|
|
|
// Accept implements Node Accept interface.
|
|
func (ts *TableSource) Accept(v Visitor) (Node, bool) {
|
|
if !v.Enter(ts) {
|
|
return ts, false
|
|
}
|
|
node, ok := ts.Source.Accept(v)
|
|
if !ok {
|
|
return ts, false
|
|
}
|
|
ts.Source = node
|
|
return v.Leave(ts)
|
|
}
|
|
|
|
// Union represents union select statement.
|
|
type Union struct {
|
|
node
|
|
|
|
Select *SelectStmt
|
|
}
|
|
|
|
// Accept implements Node Accept interface.
|
|
func (u *Union) Accept(v Visitor) (Node, bool) {
|
|
if !v.Enter(u) {
|
|
return u, false
|
|
}
|
|
node, ok := u.Select.Accept(v)
|
|
if !ok {
|
|
return u, false
|
|
}
|
|
u.Select = node.(*SelectStmt)
|
|
return v.Leave(u)
|
|
}
|
|
|
|
// SelectLockType is the lock type for SelectStmt.
|
|
type SelectLockType int
|
|
|
|
// Select lock types.
|
|
const (
|
|
SelectLockNone SelectLockType = iota
|
|
SelectLockForUpdate
|
|
SelectLockInShareMode
|
|
)
|
|
|
|
// SelectStmt represents the select query node.
|
|
type SelectStmt struct {
|
|
dmlNode
|
|
|
|
// Distinct represents if the select has distinct option.
|
|
Distinct bool
|
|
// Fields is the select expression list.
|
|
Fields []ExprNode
|
|
// From is the from clause of the query.
|
|
From *Join
|
|
// Where is the where clause in select statement.
|
|
Where ExprNode
|
|
// GroupBy is the group by expression list.
|
|
GroupBy []ExprNode
|
|
// Having is the having condition.
|
|
Having ExprNode
|
|
// OrderBy is the odering expression list.
|
|
OrderBy []ExprNode
|
|
// Offset is the offset value.
|
|
Offset int
|
|
// Limit is the limit value.
|
|
Limit int
|
|
// Lock is the lock type
|
|
LockTp SelectLockType
|
|
// Unions is the union select statement.
|
|
Unions []*Union
|
|
}
|
|
|
|
// Accept implements Node Accept interface.
|
|
func (sn *SelectStmt) Accept(v Visitor) (Node, bool) {
|
|
if !v.Enter(sn) {
|
|
return sn, false
|
|
}
|
|
for i, val := range sn.Fields {
|
|
node, ok := val.Accept(v)
|
|
if !ok {
|
|
return sn, false
|
|
}
|
|
sn.Fields[i] = node.(ExprNode)
|
|
}
|
|
if sn.From != nil {
|
|
node, ok := sn.From.Accept(v)
|
|
if !ok {
|
|
return sn, false
|
|
}
|
|
sn.From = node.(*Join)
|
|
}
|
|
|
|
if sn.Where != nil {
|
|
node, ok := sn.Where.Accept(v)
|
|
if !ok {
|
|
return sn, false
|
|
}
|
|
sn.Where = node.(ExprNode)
|
|
}
|
|
|
|
for i, val := range sn.GroupBy {
|
|
node, ok := val.Accept(v)
|
|
if !ok {
|
|
return sn, false
|
|
}
|
|
sn.GroupBy[i] = node.(ExprNode)
|
|
}
|
|
if sn.Having != nil {
|
|
node, ok := sn.Having.Accept(v)
|
|
if !ok {
|
|
return sn, false
|
|
}
|
|
sn.Having = node.(ExprNode)
|
|
}
|
|
|
|
for i, val := range sn.OrderBy {
|
|
node, ok := val.Accept(v)
|
|
if !ok {
|
|
return sn, false
|
|
}
|
|
sn.OrderBy[i] = node.(ExprNode)
|
|
}
|
|
|
|
for i, val := range sn.Unions {
|
|
node, ok := val.Accept(v)
|
|
if !ok {
|
|
return sn, false
|
|
}
|
|
sn.Unions[i] = node.(*Union)
|
|
}
|
|
return v.Leave(sn)
|
|
}
|
|
|
|
// Assignment is the expression for assignment, like a = 1.
|
|
type Assignment struct {
|
|
node
|
|
// Column is the column reference to be assigned.
|
|
Column *ColumnRefExpr
|
|
// Expr is the expression assigning to ColName.
|
|
Expr ExprNode
|
|
}
|
|
|
|
// Accept implements Node Accept interface.
|
|
func (as *Assignment) Accept(v Visitor) (Node, bool) {
|
|
if !v.Enter(as) {
|
|
return as, false
|
|
}
|
|
node, ok := as.Column.Accept(v)
|
|
if !ok {
|
|
return as, false
|
|
}
|
|
as.Column = node.(*ColumnRefExpr)
|
|
node, ok = as.Expr.Accept(v)
|
|
if !ok {
|
|
return as, false
|
|
}
|
|
as.Expr = node.(ExprNode)
|
|
return v.Leave(as)
|
|
}
|
|
|
|
// InsertStmt is a statement to insert new rows into an existing table.
|
|
// See: https://dev.mysql.com/doc/refman/5.7/en/insert.html
|
|
type InsertStmt struct {
|
|
dmlNode
|
|
|
|
Columns []*ColumnRefExpr
|
|
Lists [][]ExprNode
|
|
Table *TableRef
|
|
Setlist []*Assignment
|
|
Priority int
|
|
OnDuplicate []*Assignment
|
|
}
|
|
|
|
// Accept implements Node Accept interface.
|
|
func (in *InsertStmt) Accept(v Visitor) (Node, bool) {
|
|
if !v.Enter(in) {
|
|
return in, false
|
|
}
|
|
for i, val := range in.Columns {
|
|
node, ok := val.Accept(v)
|
|
if !ok {
|
|
return in, false
|
|
}
|
|
in.Columns[i] = node.(*ColumnRefExpr)
|
|
}
|
|
for i, list := range in.Lists {
|
|
for j, val := range list {
|
|
node, ok := val.Accept(v)
|
|
if !ok {
|
|
return in, false
|
|
}
|
|
in.Lists[i][j] = node.(ExprNode)
|
|
}
|
|
}
|
|
for i, val := range in.Setlist {
|
|
node, ok := val.Accept(v)
|
|
if !ok {
|
|
return in, false
|
|
}
|
|
in.Setlist[i] = node.(*Assignment)
|
|
}
|
|
for i, val := range in.OnDuplicate {
|
|
node, ok := val.Accept(v)
|
|
if !ok {
|
|
return in, false
|
|
}
|
|
in.OnDuplicate[i] = node.(*Assignment)
|
|
}
|
|
return v.Leave(in)
|
|
}
|
|
|
|
// DeleteStmt is a statement to delete rows from table.
|
|
// See: https://dev.mysql.com/doc/refman/5.7/en/delete.html
|
|
type DeleteStmt struct {
|
|
dmlNode
|
|
|
|
Tables []*TableRef
|
|
Where ExprNode
|
|
Order []ExprNode
|
|
Limit int
|
|
LowPriority bool
|
|
Ignore bool
|
|
Quick bool
|
|
MultiTable bool
|
|
BeforeFrom bool
|
|
}
|
|
|
|
// Accept implements Node Accept interface.
|
|
func (de *DeleteStmt) Accept(v Visitor) (Node, bool) {
|
|
if !v.Enter(de) {
|
|
return de, false
|
|
}
|
|
for i, val := range de.Tables {
|
|
node, ok := val.Accept(v)
|
|
if !ok {
|
|
return de, false
|
|
}
|
|
de.Tables[i] = node.(*TableRef)
|
|
}
|
|
|
|
if de.Where != nil {
|
|
node, ok := de.Where.Accept(v)
|
|
if !ok {
|
|
return de, false
|
|
}
|
|
de.Where = node.(ExprNode)
|
|
}
|
|
|
|
for i, val := range de.Order {
|
|
node, ok := val.Accept(v)
|
|
if !ok {
|
|
return de, false
|
|
}
|
|
de.Order[i] = node.(ExprNode)
|
|
}
|
|
return v.Leave(de)
|
|
}
|
|
|
|
// UpdateStmt is a statement to update columns of existing rows in tables with new values.
|
|
// See: https://dev.mysql.com/doc/refman/5.7/en/update.html
|
|
type UpdateStmt struct {
|
|
dmlNode
|
|
|
|
TableRefs *Join
|
|
List []*Assignment
|
|
Where ExprNode
|
|
Order []ExprNode
|
|
Limit int
|
|
LowPriority bool
|
|
Ignore bool
|
|
MultipleTable bool
|
|
}
|
|
|
|
// Accept implements Node Accept interface.
|
|
func (up *UpdateStmt) Accept(v Visitor) (Node, bool) {
|
|
if !v.Enter(up) {
|
|
return up, false
|
|
}
|
|
node, ok := up.TableRefs.Accept(v)
|
|
if !ok {
|
|
return up, false
|
|
}
|
|
up.TableRefs = node.(*Join)
|
|
for i, val := range up.List {
|
|
node, ok = val.Accept(v)
|
|
if !ok {
|
|
return up, false
|
|
}
|
|
up.List[i] = node.(*Assignment)
|
|
}
|
|
if up.Where != nil {
|
|
node, ok = up.Where.Accept(v)
|
|
if !ok {
|
|
return up, false
|
|
}
|
|
up.Where = node.(ExprNode)
|
|
}
|
|
|
|
for i, val := range up.Order {
|
|
node, ok = val.Accept(v)
|
|
if !ok {
|
|
return up, false
|
|
}
|
|
up.Order[i] = node.(ExprNode)
|
|
}
|
|
return v.Leave(up)
|
|
}
|