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 }