github.com/dolthub/go-mysql-server@v0.18.0/sql/in_mem_table/multimapeditors.go (about) 1 // Copyright 2023 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 in_mem_table 16 17 import ( 18 "errors" 19 20 "github.com/dolthub/go-mysql-server/sql" 21 ) 22 23 // Given operations for converting an IndexedSet entry into a sql.Row, these 24 // editors converted and IndexedSet into a table editor. 25 // 26 // These editors treat the first first Keyer in the IndexedSet as a primary 27 // key. It is an internal coding error if other operations on the IndexedSet 28 // result in multiple entries for a single key for entries keyed by the first 29 // keyer. 30 31 type ValueOps[V any] struct { 32 ToRow func(*sql.Context, V) (sql.Row, error) 33 FromRow func(*sql.Context, sql.Row) (V, error) 34 UpdateWithRow func(*sql.Context, sql.Row, V) (V, error) 35 } 36 37 func Insert[V any](ctx *sql.Context, ops *ValueOps[V], is IndexedSet[V], row sql.Row) error { 38 e, err := ops.FromRow(ctx, row) 39 if err != nil { 40 return err 41 } 42 ek := is.Keyers[0].GetKey(e) 43 if es := is.GetMany(is.Keyers[0], ek); len(es) != 0 { 44 return sql.ErrPrimaryKeyViolation.New() 45 } 46 is.Put(e) 47 return nil 48 } 49 50 func Delete[V any](ctx *sql.Context, ops *ValueOps[V], is IndexedSet[V], row sql.Row) error { 51 e, err := ops.FromRow(ctx, row) 52 if err != nil { 53 return err 54 } 55 ek := is.Keyers[0].GetKey(e) 56 is.RemoveMany(is.Keyers[0], ek) 57 return nil 58 } 59 60 func Update[V any](ctx *sql.Context, ops *ValueOps[V], is IndexedSet[V], old, new sql.Row) error { 61 e, err := ops.FromRow(ctx, old) 62 if err != nil { 63 return err 64 } 65 ek := is.Keyers[0].GetKey(e) 66 es := is.GetMany(is.Keyers[0], ek) 67 if len(es) == 1 { 68 old := e 69 e := es[0] 70 e, err = ops.UpdateWithRow(ctx, new, e) 71 if err != nil { 72 return err 73 } 74 is.Remove(old) 75 is.Put(e) 76 } else { 77 e, err = ops.FromRow(ctx, new) 78 if err != nil { 79 return err 80 } 81 for _, old := range es { 82 is.Remove(old) 83 } 84 is.Put(e) 85 } 86 return nil 87 } 88 89 var _ sql.TableEditor = (*IndexedSetTableEditor[string])(nil) 90 91 type IndexedSetTableEditor[V any] struct { 92 Set IndexedSet[V] 93 Ops ValueOps[V] 94 } 95 96 func (e *IndexedSetTableEditor[V]) StatementBegin(ctx *sql.Context) { 97 } 98 99 func (e *IndexedSetTableEditor[V]) DiscardChanges(ctx *sql.Context, cause error) error { 100 return nil 101 } 102 103 func (e *IndexedSetTableEditor[V]) StatementComplete(ctx *sql.Context) error { 104 return nil 105 } 106 107 func (e *IndexedSetTableEditor[V]) Close(ctx *sql.Context) error { 108 return nil 109 } 110 111 func (e *IndexedSetTableEditor[V]) Insert(ctx *sql.Context, row sql.Row) error { 112 return Insert[V](ctx, &e.Ops, e.Set, row) 113 } 114 115 func (e *IndexedSetTableEditor[V]) Delete(ctx *sql.Context, row sql.Row) error { 116 return Delete[V](ctx, &e.Ops, e.Set, row) 117 } 118 119 func (e *IndexedSetTableEditor[V]) Update(ctx *sql.Context, old, new sql.Row) error { 120 return Update[V](ctx, &e.Ops, e.Set, old, new) 121 } 122 123 type MultiValueOps[V any] struct { 124 ToRows func(*sql.Context, V) ([]sql.Row, error) 125 FromRow func(*sql.Context, sql.Row) (V, error) 126 AddRow func(*sql.Context, sql.Row, V) (V, error) 127 DeleteRow func(*sql.Context, sql.Row, V) (V, error) 128 } 129 130 var ErrEntryNotFound = errors.New("cannot insert row; matching entry not found") 131 132 func MultiInsert[V any](ctx *sql.Context, ops *MultiValueOps[V], is IndexedSet[V], row sql.Row) error { 133 e, err := ops.FromRow(ctx, row) 134 if err != nil { 135 return err 136 } 137 ek := is.Keyers[0].GetKey(e) 138 es := is.GetMany(is.Keyers[0], ek) 139 if len(es) != 1 { 140 return ErrEntryNotFound 141 } 142 newE, err := ops.AddRow(ctx, row, es[0]) 143 if err != nil { 144 return err 145 } 146 is.Remove(es[0]) 147 is.Put(newE) 148 return nil 149 } 150 151 func MultiDelete[V any](ctx *sql.Context, ops *MultiValueOps[V], is IndexedSet[V], row sql.Row) error { 152 e, err := ops.FromRow(ctx, row) 153 if err != nil { 154 return err 155 } 156 ek := is.Keyers[0].GetKey(e) 157 es := is.GetMany(is.Keyers[0], ek) 158 if len(es) != 1 { 159 return ErrEntryNotFound 160 } 161 newE, err := ops.DeleteRow(ctx, row, es[0]) 162 if err != nil { 163 return err 164 } 165 is.Remove(es[0]) 166 is.Put(newE) 167 return nil 168 } 169 170 func MultiUpdate[V any](ctx *sql.Context, ops *MultiValueOps[V], is IndexedSet[V], old, new sql.Row) error { 171 err := MultiDelete[V](ctx, ops, is, old) 172 if err != nil { 173 return err 174 } 175 return MultiInsert(ctx, ops, is, new) 176 } 177 178 var _ sql.TableEditor = (*MultiIndexedSetTableEditor[string])(nil) 179 180 type MultiIndexedSetTableEditor[V any] struct { 181 Set IndexedSet[V] 182 Ops MultiValueOps[V] 183 } 184 185 func (e *MultiIndexedSetTableEditor[V]) StatementBegin(ctx *sql.Context) { 186 } 187 188 func (e *MultiIndexedSetTableEditor[V]) DiscardChanges(ctx *sql.Context, cause error) error { 189 return nil 190 } 191 192 func (e *MultiIndexedSetTableEditor[V]) StatementComplete(ctx *sql.Context) error { 193 return nil 194 } 195 196 func (e *MultiIndexedSetTableEditor[V]) Close(ctx *sql.Context) error { 197 return nil 198 } 199 200 func (e *MultiIndexedSetTableEditor[V]) Insert(ctx *sql.Context, row sql.Row) error { 201 return MultiInsert[V](ctx, &e.Ops, e.Set, row) 202 } 203 204 func (e *MultiIndexedSetTableEditor[V]) Delete(ctx *sql.Context, row sql.Row) error { 205 return MultiDelete[V](ctx, &e.Ops, e.Set, row) 206 } 207 208 func (e *MultiIndexedSetTableEditor[V]) Update(ctx *sql.Context, old, new sql.Row) error { 209 return MultiUpdate[V](ctx, &e.Ops, e.Set, old, new) 210 }