github.com/dolthub/go-mysql-server@v0.18.0/sql/plan/foreign_key_handler.go (about) 1 // Copyright 2022 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 "github.com/dolthub/go-mysql-server/sql" 21 ) 22 23 // ForeignKeyHandler handles all referencing and cascading operations that would need to be executed for an operation 24 // on a table. 25 type ForeignKeyHandler struct { 26 Table sql.ForeignKeyTable 27 Sch sql.Schema 28 OriginalNode sql.Node 29 Editor *ForeignKeyEditor 30 AllUpdaters []sql.ForeignKeyEditor 31 } 32 33 var _ sql.Node = (*ForeignKeyHandler)(nil) 34 var _ sql.CollationCoercible = (*ForeignKeyHandler)(nil) 35 var _ sql.Table = (*ForeignKeyHandler)(nil) 36 var _ sql.InsertableTable = (*ForeignKeyHandler)(nil) 37 var _ sql.ReplaceableTable = (*ForeignKeyHandler)(nil) 38 var _ sql.UpdatableTable = (*ForeignKeyHandler)(nil) 39 var _ sql.DeletableTable = (*ForeignKeyHandler)(nil) 40 var _ sql.TableEditor = (*ForeignKeyHandler)(nil) 41 var _ sql.RowInserter = (*ForeignKeyHandler)(nil) 42 var _ sql.RowUpdater = (*ForeignKeyHandler)(nil) 43 var _ sql.RowDeleter = (*ForeignKeyHandler)(nil) 44 45 // Resolved implements the interface sql.Node. 46 func (n *ForeignKeyHandler) Resolved() bool { 47 return n.OriginalNode.Resolved() && n.Editor.IsInitialized(make(map[*ForeignKeyEditor]struct{})) 48 } 49 50 // String implements the interface sql.Node. 51 func (n *ForeignKeyHandler) String() string { 52 return n.OriginalNode.String() 53 } 54 55 func (n *ForeignKeyHandler) DebugString() string { 56 return sql.DebugString(n.OriginalNode) 57 } 58 59 // Schema implements the interface sql.Node. 60 func (n *ForeignKeyHandler) Schema() sql.Schema { 61 return n.OriginalNode.Schema() 62 } 63 64 func (n *ForeignKeyHandler) IsReadOnly() bool { 65 // false? 66 return n.OriginalNode.IsReadOnly() 67 } 68 69 // Collation implements the interface sql.Node. 70 func (n *ForeignKeyHandler) Collation() sql.CollationID { 71 originalTable, ok := n.OriginalNode.(sql.Table) 72 if !ok { 73 return sql.Collation_Default 74 } 75 return originalTable.Collation() 76 } 77 78 // Children implements the interface sql.Node. 79 func (n *ForeignKeyHandler) Children() []sql.Node { 80 return []sql.Node{n.OriginalNode} 81 } 82 83 // WithChildren implements the interface sql.Node. 84 func (n *ForeignKeyHandler) WithChildren(children ...sql.Node) (sql.Node, error) { 85 if len(children) != 1 { 86 return nil, sql.ErrInvalidChildrenNumber.New(n, len(children), 1) 87 } 88 nn := *n 89 nn.OriginalNode = children[0] 90 return &nn, nil 91 } 92 93 // CheckPrivileges implements the interface sql.Node. 94 func (n *ForeignKeyHandler) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 95 return n.OriginalNode.CheckPrivileges(ctx, opChecker) 96 } 97 98 // CollationCoercibility implements the interface sql.CollationCoercible. 99 func (*ForeignKeyHandler) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 100 return sql.Collation_binary, 7 101 } 102 103 // Name implements the interface sql.Table. 104 func (n *ForeignKeyHandler) Name() string { 105 return n.Table.Name() 106 } 107 108 // Partitions implements the interface sql.Table. 109 func (n *ForeignKeyHandler) Partitions(ctx *sql.Context) (sql.PartitionIter, error) { 110 originalTable, ok := n.OriginalNode.(sql.Table) 111 if !ok { 112 return nil, fmt.Errorf("cannot partition foreign key handler due to the original node not being a table") 113 } 114 return originalTable.Partitions(ctx) 115 } 116 117 // PartitionRows implements the interface sql.Table. 118 func (n *ForeignKeyHandler) PartitionRows(ctx *sql.Context, partition sql.Partition) (sql.RowIter, error) { 119 originalTable, ok := n.OriginalNode.(sql.Table) 120 if !ok { 121 return nil, fmt.Errorf("cannot partition rows on foreign key handler due to the original node not being a table") 122 } 123 return originalTable.PartitionRows(ctx, partition) 124 } 125 126 // Inserter implements the interface sql.InsertableTable. 127 func (n *ForeignKeyHandler) Inserter(context *sql.Context) sql.RowInserter { 128 return n 129 } 130 131 // Replacer implements the interface sql.ReplaceableTable. 132 func (n *ForeignKeyHandler) Replacer(ctx *sql.Context) sql.RowReplacer { 133 return n 134 } 135 136 // Updater implements the interface sql.UpdatableTable. 137 func (n *ForeignKeyHandler) Updater(ctx *sql.Context) sql.RowUpdater { 138 return n 139 } 140 141 // Deleter implements the interface sql.DeletableTable. 142 func (n *ForeignKeyHandler) Deleter(context *sql.Context) sql.RowDeleter { 143 return n 144 } 145 146 // StatementBegin implements the interface sql.TableEditor. 147 func (n *ForeignKeyHandler) StatementBegin(ctx *sql.Context) { 148 for _, updater := range n.AllUpdaters { 149 updater.StatementBegin(ctx) 150 } 151 } 152 153 // DiscardChanges implements the interface sql.TableEditor. 154 func (n *ForeignKeyHandler) DiscardChanges(ctx *sql.Context, errorEncountered error) error { 155 var err error 156 for _, updater := range n.AllUpdaters { 157 nErr := updater.DiscardChanges(ctx, errorEncountered) 158 if err == nil { 159 err = nErr 160 } 161 } 162 return err 163 } 164 165 // StatementComplete implements the interface sql.TableEditor. 166 func (n *ForeignKeyHandler) StatementComplete(ctx *sql.Context) error { 167 var err error 168 for _, updater := range n.AllUpdaters { 169 nErr := updater.StatementComplete(ctx) 170 if err == nil { 171 err = nErr 172 } 173 } 174 return err 175 } 176 177 // Insert implements the interface sql.RowInserter. 178 func (n *ForeignKeyHandler) Insert(ctx *sql.Context, row sql.Row) error { 179 for _, reference := range n.Editor.References { 180 if err := reference.CheckReference(ctx, row); err != nil { 181 return err 182 } 183 } 184 return n.Editor.Editor.Insert(ctx, row) 185 } 186 187 // Update implements the interface sql.RowUpdater. 188 func (n *ForeignKeyHandler) Update(ctx *sql.Context, old sql.Row, new sql.Row) error { 189 return n.Editor.Update(ctx, old, new, 1) 190 } 191 192 // Delete implements the interface sql.RowDeleter. 193 func (n *ForeignKeyHandler) Delete(ctx *sql.Context, row sql.Row) error { 194 return n.Editor.Delete(ctx, row, 1) 195 } 196 197 // Close implements the interface sql.Closer. 198 func (n *ForeignKeyHandler) Close(ctx *sql.Context) error { 199 var err error 200 for _, updater := range n.AllUpdaters { 201 nErr := updater.Close(ctx) 202 if err == nil { 203 err = nErr 204 } 205 } 206 return err 207 }