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 }