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 }