github.com/dolthub/go-mysql-server@v0.18.0/sql/plan/truncate.go (about) 1 // Copyright 2020-2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package plan 16 17 import ( 18 "gopkg.in/src-d/go-errors.v1" 19 20 "github.com/dolthub/go-mysql-server/sql/types" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 ) 24 25 var ErrTruncateNotSupported = errors.NewKind("table doesn't support TRUNCATE") 26 27 // Truncate is a node describing the deletion of all rows from some table. 28 type Truncate struct { 29 db string 30 UnaryNode 31 } 32 33 var _ sql.Node = (*Truncate)(nil) 34 var _ sql.DebugStringer = (*Truncate)(nil) 35 var _ sql.CollationCoercible = (*Truncate)(nil) 36 37 // NewTruncate creates a Truncate node. 38 func NewTruncate(db string, table sql.Node) *Truncate { 39 return &Truncate{ 40 db: db, 41 UnaryNode: UnaryNode{table}, 42 } 43 } 44 45 func GetTruncatable(node sql.Node) (sql.TruncateableTable, error) { 46 switch node := node.(type) { 47 case sql.TruncateableTable: 48 return node, nil 49 case *IndexedTableAccess: 50 return GetTruncatable(node.TableNode) 51 case *ResolvedTable: 52 return getTruncatableTable(node.Table) 53 case sql.TableWrapper: 54 return getTruncatableTable(node.Underlying()) 55 } 56 for _, child := range node.Children() { 57 truncater, _ := GetTruncatable(child) 58 if truncater != nil { 59 return truncater, nil 60 } 61 } 62 return nil, ErrTruncateNotSupported.New() 63 } 64 65 func getTruncatableTable(t sql.Table) (sql.TruncateableTable, error) { 66 switch t := t.(type) { 67 case sql.TruncateableTable: 68 return t, nil 69 case sql.TableWrapper: 70 return getTruncatableTable(t.Underlying()) 71 default: 72 return nil, ErrTruncateNotSupported.New() 73 } 74 } 75 76 // DatabaseName returns the name of the database that this operation is being performed in. 77 func (p *Truncate) DatabaseName() string { 78 return p.db 79 } 80 81 // Schema implements the Node interface. 82 func (p *Truncate) Schema() sql.Schema { 83 return types.OkResultSchema 84 } 85 86 // WithChildren implements the Node interface. 87 func (p *Truncate) WithChildren(children ...sql.Node) (sql.Node, error) { 88 if len(children) != 1 { 89 return nil, sql.ErrInvalidChildrenNumber.New(p, len(children), 1) 90 } 91 nt := *p 92 nt.UnaryNode = UnaryNode{children[0]} 93 return &nt, nil 94 } 95 96 // CheckPrivileges implements the interface sql.Node. 97 func (p *Truncate) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 98 subject := sql.PrivilegeCheckSubject{ 99 Database: p.db, 100 Table: getTableName(p.Child), 101 } 102 103 return opChecker.UserHasPrivileges(ctx, 104 sql.NewPrivilegedOperation(subject, sql.PrivilegeType_Drop)) 105 } 106 107 // CollationCoercibility implements the interface sql.CollationCoercible. 108 func (*Truncate) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 109 return sql.Collation_binary, 7 110 } 111 112 func (*Truncate) IsReadOnly() bool { 113 return false 114 } 115 116 // String implements the Node interface. 117 func (p Truncate) String() string { 118 pr := sql.NewTreePrinter() 119 _ = pr.WriteNode("Truncate") 120 _ = pr.WriteChildren(p.Child.String()) 121 return pr.String() 122 } 123 124 // DebugString implements the DebugStringer interface. 125 func (p Truncate) DebugString() string { 126 pr := sql.NewTreePrinter() 127 _ = pr.WriteNode("Truncate") 128 _ = pr.WriteChildren(sql.DebugString(p.Child)) 129 return pr.String() 130 }