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  }