github.com/dolthub/go-mysql-server@v0.18.0/sql/plan/show_create_table.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 "fmt" 19 20 "gopkg.in/src-d/go-errors.v1" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 "github.com/dolthub/go-mysql-server/sql/transform" 24 "github.com/dolthub/go-mysql-server/sql/types" 25 ) 26 27 var ErrNotView = errors.NewKind("'%' is not VIEW") 28 29 // ShowCreateTable is a node that shows the CREATE TABLE statement for a table. 30 type ShowCreateTable struct { 31 *UnaryNode 32 IsView bool 33 Indexes []sql.Index 34 checks sql.CheckConstraints 35 targetSchema sql.Schema 36 PrimaryKeySchema sql.PrimaryKeySchema 37 asOf sql.Expression 38 } 39 40 var _ sql.Node = (*ShowCreateTable)(nil) 41 var _ sql.Expressioner = (*ShowCreateTable)(nil) 42 var _ sql.SchemaTarget = (*ShowCreateTable)(nil) 43 var _ sql.CheckConstraintNode = (*ShowCreateTable)(nil) 44 var _ sql.CollationCoercible = (*ShowCreateTable)(nil) 45 var _ Versionable = (*ShowCreateTable)(nil) 46 47 // NewShowCreateTable creates a new ShowCreateTable node. 48 func NewShowCreateTable(table sql.Node, isView bool) *ShowCreateTable { 49 return NewShowCreateTableWithAsOf(table, isView, nil) 50 } 51 52 // NewShowCreateTableWithAsOf creates a new ShowCreateTable node for a specific version of a table. 53 func NewShowCreateTableWithAsOf(table sql.Node, isView bool, asOf sql.Expression) *ShowCreateTable { 54 return &ShowCreateTable{ 55 UnaryNode: &UnaryNode{table}, 56 IsView: isView, 57 asOf: asOf, 58 } 59 } 60 61 func (sc *ShowCreateTable) Checks() sql.CheckConstraints { 62 return sc.checks 63 } 64 65 func (sc *ShowCreateTable) WithChecks(checks sql.CheckConstraints) sql.Node { 66 ret := *sc 67 ret.checks = checks 68 return &ret 69 } 70 71 // Resolved implements the Resolvable interface. 72 func (sc *ShowCreateTable) Resolved() bool { 73 return sc.Child.Resolved() && sc.targetSchema.Resolved() 74 } 75 76 func (sc *ShowCreateTable) IsReadOnly() bool { 77 return true 78 } 79 80 func (sc ShowCreateTable) WithChildren(children ...sql.Node) (sql.Node, error) { 81 if len(children) != 1 { 82 return nil, sql.ErrInvalidChildrenNumber.New(1, len(children)) 83 } 84 child := children[0] 85 86 switch child.(type) { 87 case *SubqueryAlias, *ResolvedTable, sql.UnresolvedTable: 88 default: 89 return nil, sql.ErrInvalidChildType.New(sc, child, (*SubqueryAlias)(nil)) 90 } 91 92 sc.Child = child 93 return &sc, nil 94 } 95 96 // CheckPrivileges implements the interface sql.Node. 97 func (sc *ShowCreateTable) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 98 // The table won't be visible during the resolution step if the user doesn't have the correct privileges 99 return true 100 } 101 102 // CollationCoercibility implements the interface sql.CollationCoercible. 103 func (*ShowCreateTable) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 104 return sql.Collation_binary, 7 105 } 106 107 func (sc ShowCreateTable) WithTargetSchema(schema sql.Schema) (sql.Node, error) { 108 sc.targetSchema = schema 109 return &sc, nil 110 } 111 112 func (sc *ShowCreateTable) TargetSchema() sql.Schema { 113 return sc.targetSchema 114 } 115 116 func (sc ShowCreateTable) WithPrimaryKeySchema(schema sql.PrimaryKeySchema) (sql.Node, error) { 117 sc.PrimaryKeySchema = schema 118 return &sc, nil 119 } 120 121 func (sc *ShowCreateTable) Expressions() []sql.Expression { 122 return transform.WrappedColumnDefaults(sc.targetSchema) 123 } 124 125 func (sc ShowCreateTable) WithExpressions(exprs ...sql.Expression) (sql.Node, error) { 126 if len(exprs) != len(sc.targetSchema) { 127 return nil, sql.ErrInvalidChildrenNumber.New(sc, len(exprs), len(sc.targetSchema)) 128 } 129 130 sch, err := transform.SchemaWithDefaults(sc.targetSchema, exprs) 131 if err != nil { 132 return nil, err 133 } 134 135 sc.targetSchema = sch 136 return &sc, nil 137 } 138 139 // Schema implements the Node interface. 140 func (sc *ShowCreateTable) Schema() sql.Schema { 141 switch sc.Child.(type) { 142 case *SubqueryAlias: 143 return sql.Schema{ 144 &sql.Column{Name: "View", Type: types.LongText, Nullable: false}, 145 &sql.Column{Name: "Create View", Type: types.LongText, Nullable: false}, 146 &sql.Column{Name: "character_set_client", Type: types.LongText, Nullable: false}, 147 &sql.Column{Name: "collation_connection", Type: types.LongText, Nullable: false}, 148 } 149 case *ResolvedTable, sql.UnresolvedTable: 150 return sql.Schema{ 151 &sql.Column{Name: "Table", Type: types.LongText, Nullable: false}, 152 &sql.Column{Name: "Create Table", Type: types.LongText, Nullable: false}, 153 } 154 default: 155 panic(fmt.Sprintf("unexpected type %T", sc.Child)) 156 } 157 } 158 159 // GetTargetSchema returns the final resolved target schema of show create table. 160 func (sc *ShowCreateTable) GetTargetSchema() sql.Schema { 161 return sc.targetSchema 162 } 163 164 // WithAsOf implements the Versionable interface. 165 func (sc *ShowCreateTable) WithAsOf(asOf sql.Expression) (sql.Node, error) { 166 nsc := *sc 167 nsc.asOf = asOf 168 return &nsc, nil 169 } 170 171 // AsOf implements the Versionable interface. 172 func (sc *ShowCreateTable) AsOf() sql.Expression { 173 return sc.asOf 174 } 175 176 // String implements the fmt.Stringer interface. 177 func (sc *ShowCreateTable) String() string { 178 t := "TABLE" 179 if sc.IsView { 180 t = "VIEW" 181 } 182 183 name := "" 184 if nameable, ok := sc.Child.(sql.Nameable); ok { 185 name = nameable.Name() 186 } 187 188 asOfClause := "" 189 if sc.asOf != nil { 190 asOfClause = fmt.Sprintf("as of %v", sc.asOf) 191 } 192 193 return fmt.Sprintf("SHOW CREATE %s %s %s", t, name, asOfClause) 194 }