Skip to content

Commit

Permalink
[parser] ast, parser: extract create view parameters to CreateViewStmt (
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewDi authored and xhebox committed Oct 8, 2021
1 parent f6c2050 commit e055c29
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 28 deletions.
31 changes: 25 additions & 6 deletions parser/ast/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package ast

import (
"github.com/pingcap/parser/auth"
"github.com/pingcap/parser/model"
"github.com/pingcap/parser/types"
)
Expand Down Expand Up @@ -552,16 +553,34 @@ func (n *TableToTable) Accept(v Visitor) (Node, bool) {
type CreateViewStmt struct {
ddlNode

OrReplace bool
ViewName *TableName
Cols []model.CIStr
Select StmtNode
OrReplace bool
ViewName *TableName
Cols []model.CIStr
Select StmtNode
Algorithm model.ViewAlgorithm
Definer *auth.UserIdentity
Security model.ViewSecurity
CheckOption model.ViewCheckOption
}

// Accept implements Node Accept interface.
func (n *CreateViewStmt) Accept(v Visitor) (Node, bool) {
// TODO: implement the details.
return n, true
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*CreateViewStmt)
node, ok := n.ViewName.Accept(v)
if !ok {
return n, false
}
n.ViewName = node.(*TableName)
selnode, ok := n.Select.Accept(v)
if !ok {
return n, false
}
n.Select = selnode.(*SelectStmt)
return v.Leave(n)
}

// CreateIndexStmt is a statement to create an index.
Expand Down
2 changes: 2 additions & 0 deletions parser/model/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const (
ActionRenameIndex ActionType = 18
ActionAddTablePartition ActionType = 19
ActionDropTablePartition ActionType = 20
ActionCreateView ActionType = 21
)

// AddIndexStr is a string related to the operation of "add index".
Expand All @@ -76,6 +77,7 @@ var actionMap = map[ActionType]string{
ActionRenameIndex: "rename index",
ActionAddTablePartition: "add partition",
ActionDropTablePartition: "drop table partition",
ActionCreateView: "create view",
}

// String return current ddl action in string
Expand Down
81 changes: 81 additions & 0 deletions parser/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"time"

"github.com/pingcap/errors"
"github.com/pingcap/parser/auth"
"github.com/pingcap/parser/mysql"
"github.com/pingcap/parser/types"
"github.com/pingcap/tipb/go-tipb"
Expand Down Expand Up @@ -169,6 +170,8 @@ type TableInfo struct {
Partition *PartitionInfo `json:"partition"`

Compression string `json:"compression"`

View *ViewInfo `json:"view"`
}

// GetPartitionInfo returns the partition information.
Expand Down Expand Up @@ -287,6 +290,84 @@ func (t *TableInfo) ColumnIsInIndex(c *ColumnInfo) bool {
return false
}

// IsView checks if tableinfo is a view
func (t *TableInfo) IsView() bool {
return t.View != nil
}

// ViewAlgorithm is VIEW's SQL AlGORITHM characteristic.
// See https://dev.mysql.com/doc/refman/5.7/en/view-algorithms.html
type ViewAlgorithm int

const (
AlgorithmUndefined ViewAlgorithm = iota
AlgorithmMerge
AlgorithmTemptable
)

func (v *ViewAlgorithm) String() string {
switch *v {
case AlgorithmMerge:
return "MERGE"
case AlgorithmTemptable:
return "TEMPTABLE"
case AlgorithmUndefined:
return "UNDEFINED"
default:
return "UNDEFINED"
}
}

// ViewSecurity is VIEW's SQL SECURITY characteristic.
// See https://dev.mysql.com/doc/refman/5.7/en/create-view.html
type ViewSecurity int

const (
SecurityDefiner ViewSecurity = iota
SecurityInvoker
)

func (v *ViewSecurity) String() string {
switch *v {
case SecurityInvoker:
return "INVOKER"
case SecurityDefiner:
return "DEFINER"
default:
return "DEFINER"
}
}

// ViewCheckOption is VIEW's WITH CHECK OPTION clause part.
// See https://dev.mysql.com/doc/refman/5.7/en/view-check-option.html
type ViewCheckOption int

const (
CheckOptionLocal ViewCheckOption = iota
CheckOptionCascaded
)

func (v *ViewCheckOption) String() string {
switch *v {
case CheckOptionLocal:
return "LOCAL"
case CheckOptionCascaded:
return "CASCADED"
default:
return "CASCADED"
}
}

// ViewInfo provides meta data describing a DB view.
type ViewInfo struct {
Algorithm ViewAlgorithm `json:"view_algorithm"`
Definer *auth.UserIdentity `json:"view_definer"`
Security ViewSecurity `json:"view_security"`
SelectStmt string `json:"view_select"`
CheckOption ViewCheckOption `json:"view_checkoption"`
Cols []CIStr `json:"view_cols"`
}

// PartitionType is the type for PartitionInfo
type PartitionType int

Expand Down
32 changes: 21 additions & 11 deletions parser/parser.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 21 additions & 11 deletions parser/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -2132,15 +2132,25 @@ CreateViewStmt:
{
startOffset := parser.startOffset(&yyS[yypt-1])
selStmt := $10.(*ast.SelectStmt)
selStmt.SetText(string(parser.src[startOffset:]))
selStmt.SetText(strings.TrimSpace(parser.src[startOffset:]))
x := &ast.CreateViewStmt {
OrReplace: $2.(bool),
ViewName: $7.(*ast.TableName),
Select: selStmt,
Algorithm: $3.(model.ViewAlgorithm),
Definer: $4.(*auth.UserIdentity),
Security: $5.(model.ViewSecurity),
}
if $8 != nil{
x.Cols = $8.([]model.CIStr)
}
if $11 !=nil {
x.CheckOption = $11.(model.ViewCheckOption)
endOffset := parser.startOffset(&yyS[yypt])
selStmt.SetText(strings.TrimSpace(parser.src[startOffset:endOffset]))
} else {
x.CheckOption = model.CheckOptionCascaded
}
$$ = x
}

Expand All @@ -2156,25 +2166,25 @@ OrReplace:
ViewAlgorithm:
/* EMPTY */
{
$$ = "UNDEFINED"
$$ = model.AlgorithmUndefined
}
| "ALGORITHM" "=" "UNDEFINED"
{
$$ = strings.ToUpper($3)
$$ = model.AlgorithmUndefined
}
| "ALGORITHM" "=" "MERGE"
{
$$ = strings.ToUpper($3)
$$ = model.AlgorithmMerge
}
| "ALGORITHM" "=" "TEMPTABLE"
{
$$ = strings.ToUpper($3)
$$ = model.AlgorithmTemptable
}

ViewDefiner:
/* EMPTY */
{
$$ = nil
$$ = &auth.UserIdentity{CurrentUser: true}
}
| "DEFINER" "=" Username
{
Expand All @@ -2184,15 +2194,15 @@ ViewDefiner:
ViewSQLSecurity:
/* EMPTY */
{
$$ = "DEFINER"
$$ = model.SecurityDefiner
}
| "SQL" "SECURITY" "DEFINER"
{
$$ = $3
$$ = model.SecurityDefiner
}
| "SQL" "SECURITY" "INVOKER"
{
$$ = $3
$$ = model.SecurityInvoker
}

ViewName:
Expand Down Expand Up @@ -2228,11 +2238,11 @@ ViewCheckOption:
}
| "WITH" "CASCADED" "CHECK" "OPTION"
{
$$ = $2
$$ = model.CheckOptionCascaded
}
| "WITH" "LOCAL" "CHECK" "OPTION"
{
$$ = $2
$$ = model.CheckOptionLocal
}

/******************************************************************
Expand Down
25 changes: 25 additions & 0 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/pingcap/errors"
"github.com/pingcap/parser/ast"
"github.com/pingcap/parser/charset"
"github.com/pingcap/parser/model"
"github.com/pingcap/parser/mysql"
"github.com/pingcap/parser/terror"
_ "github.com/pingcap/tidb/types/parser_driver"
Expand Down Expand Up @@ -2239,7 +2240,31 @@ func (s *testParserSuite) TestView(c *C) {
c.Assert(err, IsNil)
v, ok := sms[0].(*ast.CreateViewStmt)
c.Assert(ok, IsTrue)
c.Assert(v.Algorithm, Equals, model.AlgorithmUndefined)
c.Assert(v.Select.Text(), Equals, "select * from t")
c.Assert(v.Security, Equals, model.SecurityDefiner)
c.Assert(v.CheckOption, Equals, model.CheckOptionCascaded)

src := `CREATE OR REPLACE ALGORITHM = UNDEFINED DEFINER = root@localhost
SQL SECURITY DEFINER
VIEW V(a,b,c) AS select c,d,e from t
WITH CASCADED CHECK OPTION;`

var st ast.StmtNode
st, err = p.ParseOneStmt(src, "", "")
c.Assert(err, IsNil)
v, ok = st.(*ast.CreateViewStmt)
c.Assert(ok, IsTrue)
c.Assert(v.OrReplace, IsTrue)
c.Assert(v.Algorithm, Equals, model.AlgorithmUndefined)
c.Assert(v.Definer.Username, Equals, "root")
c.Assert(v.Definer.Hostname, Equals, "localhost")
c.Assert(v.Cols[0], Equals, model.CIStr{"a", "a"})
c.Assert(v.Cols[1], Equals, model.CIStr{"b", "b"})
c.Assert(v.Cols[2], Equals, model.CIStr{"c", "c"})
c.Assert(v.Select.Text(), Equals, "select c,d,e from t")
c.Assert(v.Security, Equals, model.SecurityDefiner)
c.Assert(v.CheckOption, Equals, model.CheckOptionCascaded)
}

func (s *testParserSuite) TestTimestampDiffUnit(c *C) {
Expand Down

0 comments on commit e055c29

Please sign in to comment.