github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/row/keyless_row.go (about)

     1  // Copyright 2020 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 row
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"github.com/dolthub/dolt/go/libraries/doltcore/schema"
    21  	"github.com/dolthub/dolt/go/store/types"
    22  )
    23  
    24  const (
    25  	KeylessCardinalityTagIdx = uint64(0)
    26  	KeylessCardinalityValIdx = uint64(1)
    27  	KeylessFirstValIdx       = uint64(2)
    28  )
    29  
    30  var ErrZeroCardinality = fmt.Errorf("read row with zero cardinality")
    31  
    32  // keylessRow is a Row without PRIMARY_KEY fields
    33  //
    34  // key: Tuple(
    35  //
    36  //				Uint(schema.KeylessRowIdTag),
    37  //	         UUID(hash.Of(tag1, val1, ..., tagN, valN))
    38  //	     )
    39  //
    40  // val: Tuple(
    41  //
    42  //				Uint(schema.KeylessRowCardinalityTag),
    43  //	         Uint(cardinality),
    44  //	         Uint(tag1), Value(val1),
    45  //	           ...
    46  //	         Uint(tagN), Value(valN)
    47  //	     )
    48  type keylessRow struct {
    49  	key types.Tuple
    50  	val types.Tuple
    51  }
    52  
    53  var _ Row = keylessRow{}
    54  
    55  func KeylessRow(nbf *types.NomsBinFormat, vals ...types.Value) (Row, error) {
    56  	return keylessRowWithCardinality(nbf, 1, vals...)
    57  }
    58  
    59  func KeylessRowsFromTuples(key, val types.Tuple) (Row, uint64, error) {
    60  	c, err := val.Get(1)
    61  	if err != nil {
    62  		return nil, 0, err
    63  	}
    64  
    65  	card := uint64(c.(types.Uint))
    66  	r := keylessRow{
    67  		key: key,
    68  		val: val,
    69  	}
    70  
    71  	return r, card, err
    72  }
    73  
    74  func keylessRowFromTaggedValued(nbf *types.NomsBinFormat, sch schema.Schema, tv TaggedValues) (Row, error) {
    75  	vals := make([]types.Value, len(tv)*2)
    76  	i := 0
    77  
    78  	err := sch.GetAllCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
    79  		v, ok := tv[tag]
    80  		if ok && v.Kind() != types.NullKind {
    81  			vals[i] = types.Uint(tag)
    82  			vals[i+1] = v
    83  			i += 2
    84  		}
    85  		return
    86  	})
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  
    91  	return keylessRowWithCardinality(nbf, 1, vals[:i]...)
    92  }
    93  
    94  func keylessRowWithCardinality(nbf *types.NomsBinFormat, card uint64, vals ...types.Value) (Row, error) {
    95  	id, err := types.UUIDHashedFromValues(nbf, vals...) // don't hash cardinality
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	idTag := types.Uint(schema.KeylessRowIdTag)
   100  
   101  	kt, err := types.NewTuple(nbf, idTag, id)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	prefix := []types.Value{
   107  		types.Uint(schema.KeylessRowCardinalityTag),
   108  		types.Uint(card),
   109  	}
   110  	vals = append(prefix, vals...)
   111  
   112  	vt, err := types.NewTuple(nbf, vals...)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	return keylessRow{
   118  		key: kt,
   119  		val: vt,
   120  	}, nil
   121  }
   122  
   123  func (r keylessRow) NomsMapKey(sch schema.Schema) types.LesserValuable {
   124  	return r.key
   125  }
   126  
   127  func (r keylessRow) NomsMapValue(sch schema.Schema) types.Valuable {
   128  	return r.val
   129  }
   130  
   131  func (r keylessRow) NomsMapKeyTuple(sch schema.Schema, tf *types.TupleFactory) (types.Tuple, error) {
   132  	return r.key, nil
   133  }
   134  
   135  func (r keylessRow) NomsMapValueTuple(sch schema.Schema, tf *types.TupleFactory) (types.Tuple, error) {
   136  	return r.val, nil
   137  }
   138  
   139  func (r keylessRow) IterCols(cb func(tag uint64, val types.Value) (stop bool, err error)) (bool, error) {
   140  	iter, err := r.val.IteratorAt(KeylessFirstValIdx) // skip cardinality tag & val
   141  	if err != nil {
   142  		return false, err
   143  	}
   144  
   145  	for {
   146  		_, v, err := iter.Next()
   147  		if err != nil {
   148  			return false, err
   149  		}
   150  		if v == nil {
   151  			break
   152  		}
   153  
   154  		tag, ok := v.(types.Uint)
   155  		if !ok {
   156  			return false, fmt.Errorf("expected tag types.Uint, got %v", v)
   157  		}
   158  
   159  		_, v, err = iter.Next()
   160  		if err != nil {
   161  			return false, err
   162  		}
   163  
   164  		stop, err := cb(uint64(tag), v)
   165  		if err != nil {
   166  			return false, nil
   167  		}
   168  		if stop {
   169  			return stop, nil
   170  		}
   171  	}
   172  
   173  	return true, nil
   174  }
   175  
   176  func (r keylessRow) IterSchema(sch schema.Schema, cb func(tag uint64, val types.Value) (stop bool, err error)) (bool, error) {
   177  	iter, err := r.val.IteratorAt(KeylessFirstValIdx) // skip cardinality tag & val
   178  	if err != nil {
   179  		return false, err
   180  	}
   181  
   182  	tags := sch.GetAllCols().Tags
   183  	vals := make([]types.Value, len(tags))
   184  
   185  	for {
   186  		_, v, err := iter.Next()
   187  		if err != nil {
   188  			return false, err
   189  		}
   190  		if v == nil {
   191  			break
   192  		}
   193  
   194  		tag, ok := v.(types.Uint)
   195  		if !ok {
   196  			return false, fmt.Errorf("expected tag types.Uint, got %v", v)
   197  		}
   198  
   199  		idx := sch.GetAllCols().TagToIdx[uint64(tag)]
   200  		_, vals[idx], err = iter.Next()
   201  		if err != nil {
   202  			return false, err
   203  		}
   204  	}
   205  
   206  	for idx, tag := range tags {
   207  		stop, err := cb(tag, vals[idx])
   208  		if err != nil {
   209  			return false, err
   210  		}
   211  		if stop {
   212  			return stop, nil
   213  		}
   214  	}
   215  
   216  	return true, nil
   217  }
   218  
   219  func (r keylessRow) GetColVal(tag uint64) (val types.Value, ok bool) {
   220  	_, _ = r.IterCols(func(t uint64, v types.Value) (stop bool, err error) {
   221  		if tag == t {
   222  			val = v
   223  			ok, stop = true, true
   224  		}
   225  		return
   226  	})
   227  	return val, ok
   228  }
   229  
   230  func (r keylessRow) SetColVal(updateTag uint64, updateVal types.Value, sch schema.Schema) (Row, error) {
   231  	iter, err := r.val.IteratorAt(KeylessCardinalityValIdx) // skip cardinality tag
   232  	if err != nil {
   233  		return nil, err
   234  	}
   235  	_, c, err := iter.Next()
   236  	if err != nil {
   237  		return nil, err
   238  	}
   239  	card := uint64(c.(types.Uint))
   240  
   241  	i := 0
   242  	vals := make([]types.Value, sch.GetAllCols().Size()*2)
   243  
   244  	_, err = r.IterSchema(sch, func(tag uint64, val types.Value) (stop bool, err error) {
   245  		if tag == updateTag {
   246  			val = updateVal
   247  		}
   248  
   249  		if val != nil {
   250  			vals[i] = types.Uint(tag)
   251  			vals[i+1] = val
   252  			i += 2
   253  		}
   254  
   255  		return
   256  	})
   257  
   258  	if err != nil {
   259  		return nil, err
   260  	}
   261  
   262  	return keylessRowWithCardinality(r.val.Format(), card, vals[:i]...)
   263  }
   264  
   265  // TaggedValues implements the Row interface.
   266  func (r keylessRow) TaggedValues() (TaggedValues, error) {
   267  	tv := make(TaggedValues)
   268  	_, err := r.IterCols(func(tag uint64, val types.Value) (stop bool, err error) {
   269  		tv[tag] = val
   270  		return false, nil
   271  	})
   272  	return tv, err
   273  }
   274  
   275  func (r keylessRow) Format() *types.NomsBinFormat {
   276  	return r.val.Format()
   277  }
   278  
   279  // ReduceToIndexKeys creates a full key, a partial key, and a cardinality value from the given row
   280  // (first tuple being the full key). Please refer to the note in the index editor for more information
   281  // regarding partial keys.
   282  func (r keylessRow) ReduceToIndexKeys(idx schema.Index, tf *types.TupleFactory) (types.Tuple, types.Tuple, types.Tuple, error) {
   283  	vals := make([]types.Value, 0, len(idx.AllTags())*2)
   284  	for _, tag := range idx.AllTags() {
   285  		val, ok := r.GetColVal(tag)
   286  		if !ok {
   287  			val = types.NullValue
   288  		}
   289  		vals = append(vals, types.Uint(tag), val)
   290  	}
   291  	hashTag, err := r.key.Get(0)
   292  	if err != nil {
   293  		return types.Tuple{}, types.Tuple{}, types.Tuple{}, err
   294  	}
   295  	hashVal, err := r.key.Get(1)
   296  	if err != nil {
   297  		return types.Tuple{}, types.Tuple{}, types.Tuple{}, err
   298  	}
   299  
   300  	cardTag, err := r.val.Get(0)
   301  	if err != nil {
   302  		return types.Tuple{}, types.Tuple{}, types.Tuple{}, err
   303  	}
   304  	cardVal, err := r.val.Get(1)
   305  	if err != nil {
   306  		return types.Tuple{}, types.Tuple{}, types.Tuple{}, err
   307  	}
   308  
   309  	var fullKey types.Tuple
   310  	var partialKey types.Tuple
   311  	var keyValue types.Tuple
   312  
   313  	if tf == nil {
   314  		keyValue, err = types.NewTuple(r.Format(), cardTag, cardVal)
   315  		if err != nil {
   316  			return types.Tuple{}, types.Tuple{}, types.Tuple{}, err
   317  		}
   318  
   319  		vals = append(vals, hashTag, hashVal)
   320  		fullKey, err = types.NewTuple(r.Format(), vals...)
   321  		if err != nil {
   322  			return types.Tuple{}, types.Tuple{}, types.Tuple{}, err
   323  		}
   324  
   325  		partialKey, err = types.NewTuple(r.Format(), vals[:idx.Count()*2]...)
   326  		if err != nil {
   327  			return types.Tuple{}, types.Tuple{}, types.Tuple{}, err
   328  		}
   329  	} else {
   330  		keyValue, err = tf.Create(cardTag, cardVal)
   331  		if err != nil {
   332  			return types.Tuple{}, types.Tuple{}, types.Tuple{}, err
   333  		}
   334  
   335  		vals = append(vals, hashTag, hashVal)
   336  		fullKey, err = tf.Create(vals...)
   337  		if err != nil {
   338  			return types.Tuple{}, types.Tuple{}, types.Tuple{}, err
   339  		}
   340  
   341  		partialKey, err = tf.Create(vals[:idx.Count()*2]...)
   342  		if err != nil {
   343  			return types.Tuple{}, types.Tuple{}, types.Tuple{}, err
   344  		}
   345  	}
   346  
   347  	return fullKey, partialKey, keyValue, nil
   348  }