github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/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  // 			Uint(schema.KeylessRowIdTag),
    36  //          UUID(hash.Of(tag1, val1, ..., tagN, valN))
    37  //      )
    38  // val: Tuple(
    39  // 			Uint(schema.KeylessRowCardinalityTag),
    40  //          Uint(cardinality),
    41  //          Uint(tag1), Value(val1),
    42  //            ...
    43  //          Uint(tagN), Value(valN)
    44  //      )
    45  type keylessRow struct {
    46  	key types.Tuple
    47  	val types.Tuple
    48  }
    49  
    50  var _ Row = keylessRow{}
    51  
    52  func KeylessRow(nbf *types.NomsBinFormat, vals ...types.Value) (Row, error) {
    53  	return keylessRowWithCardinality(nbf, 1, vals...)
    54  }
    55  
    56  func KeylessRowsFromTuples(key, val types.Tuple) (Row, uint64, error) {
    57  	c, err := val.Get(1)
    58  	if err != nil {
    59  		return nil, 0, err
    60  	}
    61  
    62  	card := uint64(c.(types.Uint))
    63  	r := keylessRow{
    64  		key: key,
    65  		val: val,
    66  	}
    67  
    68  	return r, card, err
    69  }
    70  
    71  func keylessRowFromTaggedValued(nbf *types.NomsBinFormat, sch schema.Schema, tv TaggedValues) (Row, error) {
    72  	vals := make([]types.Value, len(tv)*2)
    73  	i := 0
    74  
    75  	err := sch.GetAllCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
    76  		v, ok := tv[tag]
    77  		if ok && v.Kind() != types.NullKind {
    78  			vals[i] = types.Uint(tag)
    79  			vals[i+1] = v
    80  			i += 2
    81  		}
    82  		return
    83  	})
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	return keylessRowWithCardinality(nbf, 1, vals[:i]...)
    89  }
    90  
    91  func keylessRowWithCardinality(nbf *types.NomsBinFormat, card uint64, vals ...types.Value) (Row, error) {
    92  	id, err := types.UUIDHashedFromValues(nbf, vals...) // don't hash cardinality
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  	idTag := types.Uint(schema.KeylessRowIdTag)
    97  
    98  	kt, err := types.NewTuple(nbf, idTag, id)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	prefix := []types.Value{
   104  		types.Uint(schema.KeylessRowCardinalityTag),
   105  		types.Uint(card),
   106  	}
   107  	vals = append(prefix, vals...)
   108  
   109  	vt, err := types.NewTuple(nbf, vals...)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  
   114  	return keylessRow{
   115  		key: kt,
   116  		val: vt,
   117  	}, nil
   118  }
   119  
   120  func (r keylessRow) NomsMapKey(sch schema.Schema) types.LesserValuable {
   121  	return r.key
   122  }
   123  
   124  func (r keylessRow) NomsMapValue(sch schema.Schema) types.Valuable {
   125  	return r.val
   126  }
   127  
   128  func (r keylessRow) IterCols(cb func(tag uint64, val types.Value) (stop bool, err error)) (bool, error) {
   129  	iter, err := r.val.IteratorAt(KeylessFirstValIdx) // skip cardinality tag & val
   130  	if err != nil {
   131  		return false, err
   132  	}
   133  
   134  	for {
   135  		_, v, err := iter.Next()
   136  		if err != nil {
   137  			return false, err
   138  		}
   139  		if v == nil {
   140  			break
   141  		}
   142  
   143  		tag, ok := v.(types.Uint)
   144  		if !ok {
   145  			return false, fmt.Errorf("expected tag types.Uint, got %v", v)
   146  		}
   147  
   148  		_, v, err = iter.Next()
   149  		if err != nil {
   150  			return false, err
   151  		}
   152  
   153  		stop, err := cb(uint64(tag), v)
   154  		if err != nil {
   155  			return false, nil
   156  		}
   157  		if stop {
   158  			return stop, nil
   159  		}
   160  	}
   161  
   162  	return true, nil
   163  }
   164  
   165  func (r keylessRow) IterSchema(sch schema.Schema, cb func(tag uint64, val types.Value) (stop bool, err error)) (bool, error) {
   166  	iter, err := r.val.IteratorAt(KeylessFirstValIdx) // skip cardinality tag & val
   167  	if err != nil {
   168  		return false, err
   169  	}
   170  
   171  	tags := sch.GetAllCols().Tags
   172  	vals := make([]types.Value, len(tags))
   173  
   174  	for {
   175  		_, v, err := iter.Next()
   176  		if err != nil {
   177  			return false, err
   178  		}
   179  		if v == nil {
   180  			break
   181  		}
   182  
   183  		tag, ok := v.(types.Uint)
   184  		if !ok {
   185  			return false, fmt.Errorf("expected tag types.Uint, got %v", v)
   186  		}
   187  
   188  		idx := sch.GetAllCols().TagToIdx[uint64(tag)]
   189  		_, vals[idx], err = iter.Next()
   190  		if err != nil {
   191  			return false, err
   192  		}
   193  	}
   194  
   195  	for idx, tag := range tags {
   196  		stop, err := cb(tag, vals[idx])
   197  		if err != nil {
   198  			return false, err
   199  		}
   200  		if stop {
   201  			return stop, nil
   202  		}
   203  	}
   204  
   205  	return true, nil
   206  }
   207  
   208  func (r keylessRow) GetColVal(tag uint64) (val types.Value, ok bool) {
   209  	_, _ = r.IterCols(func(t uint64, v types.Value) (stop bool, err error) {
   210  		if tag == t {
   211  			val = v
   212  			ok, stop = true, true
   213  		}
   214  		return
   215  	})
   216  	return val, ok
   217  }
   218  
   219  func (r keylessRow) SetColVal(updateTag uint64, updateVal types.Value, sch schema.Schema) (Row, error) {
   220  	iter, err := r.val.IteratorAt(KeylessCardinalityValIdx) // skip cardinality tag
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  	_, c, err := iter.Next()
   225  	if err != nil {
   226  		return nil, err
   227  	}
   228  	card := uint64(c.(types.Uint))
   229  
   230  	i := 0
   231  	vals := make([]types.Value, sch.GetAllCols().Size()*2)
   232  
   233  	_, err = r.IterSchema(sch, func(tag uint64, val types.Value) (stop bool, err error) {
   234  		if tag == updateTag {
   235  			val = updateVal
   236  		}
   237  
   238  		if val != nil {
   239  			vals[i] = types.Uint(tag)
   240  			vals[i+1] = val
   241  			i += 2
   242  		}
   243  
   244  		return
   245  	})
   246  
   247  	if err != nil {
   248  		return nil, err
   249  	}
   250  
   251  	return keylessRowWithCardinality(r.val.Format(), card, vals[:i]...)
   252  }
   253  
   254  // TaggedValues implements the Row interface.
   255  func (r keylessRow) TaggedValues() (TaggedValues, error) {
   256  	tv := make(TaggedValues)
   257  	_, err := r.IterCols(func(tag uint64, val types.Value) (stop bool, err error) {
   258  		tv[tag] = val
   259  		return false, nil
   260  	})
   261  	return tv, err
   262  }
   263  
   264  func (r keylessRow) Format() *types.NomsBinFormat {
   265  	return r.val.Format()
   266  }