github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/writer/prolly_index_writer.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 writer
    16  
    17  import (
    18  	"context"
    19  	"io"
    20  	"strings"
    21  
    22  	"github.com/dolthub/go-mysql-server/sql"
    23  
    24  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
    25  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdb/durable"
    26  	"github.com/dolthub/dolt/go/libraries/doltcore/schema"
    27  	"github.com/dolthub/dolt/go/store/prolly"
    28  	"github.com/dolthub/dolt/go/store/prolly/tree"
    29  	"github.com/dolthub/dolt/go/store/val"
    30  )
    31  
    32  func getPrimaryProllyWriter(ctx context.Context, t *doltdb.Table, sqlSch sql.Schema, sch schema.Schema) (prollyIndexWriter, error) {
    33  	idx, err := t.GetRowData(ctx)
    34  	if err != nil {
    35  		return prollyIndexWriter{}, err
    36  	}
    37  
    38  	m := durable.ProllyMapFromIndex(idx)
    39  
    40  	keyDesc, valDesc := m.Descriptors()
    41  	keyMap, valMap := ordinalMappingsFromSchema(sqlSch, sch)
    42  
    43  	return prollyIndexWriter{
    44  		mut:    m.Mutate(),
    45  		keyBld: val.NewTupleBuilder(keyDesc),
    46  		keyMap: keyMap,
    47  		valBld: val.NewTupleBuilder(valDesc),
    48  		valMap: valMap,
    49  	}, nil
    50  }
    51  
    52  func getPrimaryKeylessProllyWriter(ctx context.Context, t *doltdb.Table, sqlSch sql.Schema, sch schema.Schema) (prollyKeylessWriter, error) {
    53  	idx, err := t.GetRowData(ctx)
    54  	if err != nil {
    55  		return prollyKeylessWriter{}, err
    56  	}
    57  
    58  	m := durable.ProllyMapFromIndex(idx)
    59  
    60  	keyDesc, valDesc := m.Descriptors()
    61  	_, valMap := ordinalMappingsFromSchema(sqlSch, sch)
    62  
    63  	return prollyKeylessWriter{
    64  		mut:    m.Mutate(),
    65  		keyBld: val.NewTupleBuilder(keyDesc),
    66  		valBld: val.NewTupleBuilder(valDesc),
    67  		valMap: valMap,
    68  	}, nil
    69  }
    70  
    71  type indexWriter interface {
    72  	Name() string
    73  	Map(ctx context.Context) (prolly.Map, error)
    74  	ValidateKeyViolations(ctx context.Context, sqlRow sql.Row) error
    75  	Insert(ctx context.Context, sqlRow sql.Row) error
    76  	Delete(ctx context.Context, sqlRow sql.Row) error
    77  	Update(ctx context.Context, oldRow sql.Row, newRow sql.Row) error
    78  	Commit(ctx context.Context) error
    79  	Discard(ctx context.Context) error
    80  	HasEdits(ctx context.Context) bool
    81  	IterRange(ctx context.Context, rng prolly.Range) (prolly.MapIter, error)
    82  }
    83  
    84  type primaryIndexErrBuilder interface {
    85  	errForSecondaryUniqueKeyError(ctx context.Context, err secondaryUniqueKeyError) error
    86  }
    87  
    88  type prollyIndexWriter struct {
    89  	mut *prolly.MutableMap
    90  
    91  	keyBld *val.TupleBuilder
    92  	keyMap val.OrdinalMapping
    93  
    94  	valBld *val.TupleBuilder
    95  	valMap val.OrdinalMapping
    96  }
    97  
    98  var _ indexWriter = prollyIndexWriter{}
    99  var _ primaryIndexErrBuilder = prollyIndexWriter{}
   100  
   101  func (m prollyIndexWriter) Name() string {
   102  	// primary indexes don't have a name
   103  	return ""
   104  }
   105  
   106  func (m prollyIndexWriter) Map(ctx context.Context) (prolly.Map, error) {
   107  	return m.mut.Map(ctx)
   108  }
   109  
   110  func (m prollyIndexWriter) keyFromRow(ctx context.Context, sqlRow sql.Row) (val.Tuple, error) {
   111  	for to := range m.keyMap {
   112  		from := m.keyMap.MapOrdinal(to)
   113  		if err := tree.PutField(ctx, m.mut.NodeStore(), m.keyBld, to, sqlRow[from]); err != nil {
   114  			return nil, err
   115  		}
   116  	}
   117  	return m.keyBld.BuildPermissive(sharePool), nil
   118  }
   119  
   120  func (m prollyIndexWriter) ValidateKeyViolations(ctx context.Context, sqlRow sql.Row) error {
   121  	k, err := m.keyFromRow(ctx, sqlRow)
   122  	if err != nil {
   123  		return err
   124  	}
   125  
   126  	ok, err := m.mut.Has(ctx, k)
   127  	if err != nil {
   128  		return err
   129  	} else if ok {
   130  		keyStr := FormatKeyForUniqKeyErr(k, m.keyBld.Desc)
   131  		return m.uniqueKeyError(ctx, keyStr, k, true)
   132  	}
   133  	return nil
   134  }
   135  
   136  func (m prollyIndexWriter) Insert(ctx context.Context, sqlRow sql.Row) error {
   137  	k, err := m.keyFromRow(ctx, sqlRow)
   138  	if err != nil {
   139  		return err
   140  	}
   141  
   142  	for to := range m.valMap {
   143  		from := m.valMap.MapOrdinal(to)
   144  		if err := tree.PutField(ctx, m.mut.NodeStore(), m.valBld, to, sqlRow[from]); err != nil {
   145  			return err
   146  		}
   147  	}
   148  	v := m.valBld.Build(sharePool)
   149  
   150  	return m.mut.Put(ctx, k, v)
   151  }
   152  
   153  func (m prollyIndexWriter) Delete(ctx context.Context, sqlRow sql.Row) error {
   154  	k, err := m.keyFromRow(ctx, sqlRow)
   155  	if err != nil {
   156  		return err
   157  	}
   158  
   159  	return m.mut.Delete(ctx, k)
   160  }
   161  
   162  func (m prollyIndexWriter) Update(ctx context.Context, oldRow sql.Row, newRow sql.Row) error {
   163  	oldKey, err := m.keyFromRow(ctx, oldRow)
   164  	if err != nil {
   165  		return err
   166  	}
   167  
   168  	// If the old row is empty, there is nothing to delete.
   169  	// This can happen when updating a row in a conflict table if the row did not exist on one branch.
   170  	if oldKey.Count() != 0 {
   171  		// todo(andy): we can skip building, deleting |oldKey|
   172  		//  if we know the key fields are unchanged
   173  		if err := m.mut.Delete(ctx, oldKey); err != nil {
   174  			return err
   175  		}
   176  	}
   177  
   178  	newKey, err := m.keyFromRow(ctx, newRow)
   179  	if err != nil {
   180  		return err
   181  	}
   182  
   183  	ok, err := m.mut.Has(ctx, newKey)
   184  	if err != nil {
   185  		return err
   186  	} else if ok {
   187  		keyStr := FormatKeyForUniqKeyErr(newKey, m.keyBld.Desc)
   188  		return m.uniqueKeyError(ctx, keyStr, newKey, true)
   189  	}
   190  
   191  	for to := range m.valMap {
   192  		from := m.valMap.MapOrdinal(to)
   193  		if err = tree.PutField(ctx, m.mut.NodeStore(), m.valBld, to, newRow[from]); err != nil {
   194  			return err
   195  		}
   196  	}
   197  	v := m.valBld.Build(sharePool)
   198  
   199  	return m.mut.Put(ctx, newKey, v)
   200  }
   201  
   202  func (m prollyIndexWriter) Commit(ctx context.Context) error {
   203  	return m.mut.Checkpoint(ctx)
   204  }
   205  
   206  func (m prollyIndexWriter) Discard(ctx context.Context) error {
   207  	m.mut.Revert(ctx)
   208  	return nil
   209  }
   210  
   211  func (m prollyIndexWriter) HasEdits(ctx context.Context) bool {
   212  	return m.mut.HasEdits()
   213  }
   214  
   215  func (m prollyIndexWriter) IterRange(ctx context.Context, rng prolly.Range) (prolly.MapIter, error) {
   216  	return m.mut.IterRange(ctx, rng)
   217  }
   218  
   219  func (m prollyIndexWriter) errForSecondaryUniqueKeyError(ctx context.Context, err secondaryUniqueKeyError) error {
   220  	return m.uniqueKeyError(ctx, err.keyStr, err.existingKey, false)
   221  }
   222  
   223  // uniqueKeyError builds a sql.UniqueKeyError. It fetches the existing row using
   224  // |key| and passes it as the |existing| row.
   225  func (m prollyIndexWriter) uniqueKeyError(ctx context.Context, keyStr string, key val.Tuple, isPk bool) error {
   226  	existing := make(sql.Row, len(m.keyMap)+len(m.valMap))
   227  
   228  	_ = m.mut.Get(ctx, key, func(key, value val.Tuple) (err error) {
   229  		kd := m.keyBld.Desc
   230  		for from := range m.keyMap {
   231  			to := m.keyMap.MapOrdinal(from)
   232  			if existing[to], err = tree.GetField(ctx, kd, from, key, m.mut.NodeStore()); err != nil {
   233  				return err
   234  			}
   235  		}
   236  
   237  		vd := m.valBld.Desc
   238  		for from := range m.valMap {
   239  			to := m.valMap.MapOrdinal(from)
   240  			if existing[to], err = tree.GetField(ctx, vd, from, value, m.mut.NodeStore()); err != nil {
   241  				return err
   242  			}
   243  		}
   244  		return
   245  	})
   246  
   247  	return sql.NewUniqueKeyErr(keyStr, isPk, existing)
   248  }
   249  
   250  type prollySecondaryIndexWriter struct {
   251  	name          string
   252  	mut           *prolly.MutableMap
   253  	unique        bool
   254  	prefixLengths []uint16
   255  
   256  	// number of indexed cols
   257  	idxCols int
   258  
   259  	// keyMap is a mapping from sql.Row fields to
   260  	// key fields of this secondary index
   261  	keyMap val.OrdinalMapping
   262  	// keyBld builds key tuples for the secondary index
   263  	keyBld *val.TupleBuilder
   264  
   265  	// pkMap is a mapping from secondary index keys to
   266  	// primary key clustered index keys
   267  	pkMap val.OrdinalMapping
   268  	// pkBld builds key tuples for primary key index
   269  	pkBld *val.TupleBuilder
   270  }
   271  
   272  var _ indexWriter = prollySecondaryIndexWriter{}
   273  
   274  func (m prollySecondaryIndexWriter) Name() string {
   275  	return m.name
   276  }
   277  
   278  func (m prollySecondaryIndexWriter) Map(ctx context.Context) (prolly.Map, error) {
   279  	return m.mut.Map(ctx)
   280  }
   281  
   282  func (m prollySecondaryIndexWriter) ValidateKeyViolations(ctx context.Context, sqlRow sql.Row) error {
   283  	if m.unique {
   284  		if err := m.checkForUniqueKeyErr(ctx, sqlRow); err != nil {
   285  			return err
   286  		}
   287  	}
   288  	return nil
   289  }
   290  
   291  // trimKeyPart will trim entry into the sql.Row depending on the prefixLengths
   292  func (m prollySecondaryIndexWriter) trimKeyPart(to int, keyPart interface{}) interface{} {
   293  	var prefixLength uint16
   294  	if len(m.prefixLengths) > to {
   295  		prefixLength = m.prefixLengths[to]
   296  	}
   297  	return val.TrimValueToPrefixLength(keyPart, prefixLength)
   298  }
   299  
   300  func (m prollySecondaryIndexWriter) keyFromRow(ctx context.Context, sqlRow sql.Row) (val.Tuple, error) {
   301  	for to := range m.keyMap {
   302  		from := m.keyMap.MapOrdinal(to)
   303  		keyPart := m.trimKeyPart(to, sqlRow[from])
   304  		if err := tree.PutField(ctx, m.mut.NodeStore(), m.keyBld, to, keyPart); err != nil {
   305  			return nil, err
   306  		}
   307  	}
   308  	return m.keyBld.Build(sharePool), nil
   309  }
   310  
   311  func (m prollySecondaryIndexWriter) Insert(ctx context.Context, sqlRow sql.Row) error {
   312  	k, err := m.keyFromRow(ctx, sqlRow)
   313  	if err != nil {
   314  		return err
   315  	}
   316  	return m.mut.Put(ctx, k, val.EmptyTuple)
   317  }
   318  
   319  func (m prollySecondaryIndexWriter) checkForUniqueKeyErr(ctx context.Context, sqlRow sql.Row) error {
   320  	ns := m.mut.NodeStore()
   321  	for to := range m.keyMap[:m.idxCols] {
   322  		from := m.keyMap.MapOrdinal(to)
   323  		if sqlRow[from] == nil {
   324  			// NULL is incomparable and cannot
   325  			// trigger a UNIQUE KEY violation
   326  			m.keyBld.Recycle()
   327  			return nil
   328  		}
   329  		keyPart := m.trimKeyPart(to, sqlRow[from])
   330  		if err := tree.PutField(ctx, ns, m.keyBld, to, keyPart); err != nil {
   331  			return err
   332  		}
   333  	}
   334  
   335  	// build a val.Tuple containing only fields for the unique column prefix
   336  	key := m.keyBld.BuildPrefix(ns.Pool(), m.idxCols)
   337  	desc := m.keyBld.Desc.PrefixDesc(m.idxCols)
   338  	rng := prolly.PrefixRange(key, desc)
   339  	iter, err := m.mut.IterRange(ctx, rng)
   340  	if err != nil {
   341  		return err
   342  	}
   343  
   344  	idxKey, _, err := iter.Next(ctx)
   345  	if err == io.EOF {
   346  		return nil // no violation
   347  	} else if err != nil {
   348  		return err
   349  	}
   350  
   351  	// |prefix| collides with an existing key
   352  	idxDesc := m.keyBld.Desc
   353  	for to := range m.pkMap {
   354  		from := m.pkMap.MapOrdinal(to)
   355  		m.pkBld.PutRaw(to, idxDesc.GetField(from, idxKey))
   356  	}
   357  	existingPK := m.pkBld.Build(sharePool)
   358  
   359  	return secondaryUniqueKeyError{
   360  		keyStr:      FormatKeyForUniqKeyErr(key, desc),
   361  		existingKey: existingPK,
   362  	}
   363  }
   364  
   365  func (m prollySecondaryIndexWriter) Delete(ctx context.Context, sqlRow sql.Row) error {
   366  	k := m.keyBld.Build(sharePool)
   367  	k, err := m.keyFromRow(ctx, sqlRow)
   368  	if err != nil {
   369  		return err
   370  	}
   371  	return m.mut.Delete(ctx, k)
   372  }
   373  
   374  func (m prollySecondaryIndexWriter) Update(ctx context.Context, oldRow sql.Row, newRow sql.Row) error {
   375  	oldKey, err := m.keyFromRow(ctx, oldRow)
   376  	if err != nil {
   377  		return err
   378  	}
   379  
   380  	// todo(andy): we can skip building, deleting |oldKey|
   381  	//  if we know the key fields are unchanged
   382  	if err := m.mut.Delete(ctx, oldKey); err != nil {
   383  		return err
   384  	}
   385  
   386  	if m.unique {
   387  		if err := m.checkForUniqueKeyErr(ctx, newRow); err != nil {
   388  			return err
   389  		}
   390  	}
   391  
   392  	newKey, err := m.keyFromRow(ctx, newRow)
   393  	if err != nil {
   394  		return err
   395  	}
   396  	return m.mut.Put(ctx, newKey, val.EmptyTuple)
   397  }
   398  
   399  func (m prollySecondaryIndexWriter) Commit(ctx context.Context) error {
   400  	return m.mut.Checkpoint(ctx)
   401  }
   402  
   403  func (m prollySecondaryIndexWriter) Discard(ctx context.Context) error {
   404  	m.mut.Revert(ctx)
   405  	return nil
   406  }
   407  
   408  func (m prollySecondaryIndexWriter) HasEdits(ctx context.Context) bool {
   409  	return m.mut.HasEdits()
   410  }
   411  
   412  func (m prollySecondaryIndexWriter) IterRange(ctx context.Context, rng prolly.Range) (prolly.MapIter, error) {
   413  	return m.mut.IterRange(ctx, rng)
   414  }
   415  
   416  // FormatKeyForUniqKeyErr formats the given tuple |key| using |d|. The resulting
   417  // string is suitable for use in a sql.UniqueKeyError
   418  func FormatKeyForUniqKeyErr(key val.Tuple, d val.TupleDesc) string {
   419  	var sb strings.Builder
   420  	sb.WriteString("[")
   421  	seenOne := false
   422  	for i := range d.Types {
   423  		if seenOne {
   424  			sb.WriteString(",")
   425  		}
   426  		seenOne = true
   427  		sb.WriteString(d.FormatValue(i, key.GetField(i)))
   428  	}
   429  	sb.WriteString("]")
   430  	return sb.String()
   431  }