DeletePrefix is used to delete an entire subtree based on a prefix. The given index must be a prefix index, and will be used to perform a scan and enumerate the set of objects to delete. These will be removed from all other indexes, and then a special prefix operation will delete the objects from th
(table string, prefix_index string, prefix string)
| 382 | // These will be removed from all other indexes, and then a special prefix operation will delete the objects from the given index in an efficient subtree delete operation. |
| 383 | // This is useful when you have a very large number of objects indexed by the given index, along with a much smaller number of entries in the other indexes for those objects. |
| 384 | func (txn *Txn) DeletePrefix(table string, prefix_index string, prefix string) (bool, error) { |
| 385 | if !txn.write { |
| 386 | return false, fmt.Errorf("cannot delete in read-only transaction") |
| 387 | } |
| 388 | |
| 389 | if !strings.HasSuffix(prefix_index, "_prefix") { |
| 390 | return false, fmt.Errorf("Index name for DeletePrefix must be a prefix index, Got %v ", prefix_index) |
| 391 | } |
| 392 | |
| 393 | deletePrefixIndex := strings.TrimSuffix(prefix_index, "_prefix") |
| 394 | |
| 395 | // Get an iterator over all of the keys with the given prefix. |
| 396 | entries, err := txn.Get(table, prefix_index, prefix) |
| 397 | if err != nil { |
| 398 | return false, fmt.Errorf("failed kvs lookup: %s", err) |
| 399 | } |
| 400 | // Get the table schema |
| 401 | tableSchema, ok := txn.db.schema.Tables[table] |
| 402 | if !ok { |
| 403 | return false, fmt.Errorf("invalid table '%s'", table) |
| 404 | } |
| 405 | |
| 406 | foundAny := false |
| 407 | for entry := entries.Next(); entry != nil; entry = entries.Next() { |
| 408 | if !foundAny { |
| 409 | foundAny = true |
| 410 | } |
| 411 | // Get the primary ID of the object |
| 412 | idSchema := tableSchema.Indexes[id] |
| 413 | idIndexer := idSchema.Indexer.(SingleIndexer) |
| 414 | ok, idVal, err := idIndexer.FromObject(entry) |
| 415 | if err != nil { |
| 416 | return false, fmt.Errorf("failed to build primary index: %v", err) |
| 417 | } |
| 418 | if !ok { |
| 419 | return false, fmt.Errorf("object missing primary index") |
| 420 | } |
| 421 | if txn.changes != nil { |
| 422 | // Record the deletion |
| 423 | idTxn := txn.writableIndex(table, id) |
| 424 | existing, ok := idTxn.Get(idVal) |
| 425 | if ok { |
| 426 | txn.changes = append(txn.changes, Change{ |
| 427 | Table: table, |
| 428 | Before: existing, |
| 429 | After: nil, // Now nil indicates deletion |
| 430 | primaryKey: idVal, |
| 431 | }) |
| 432 | } |
| 433 | } |
| 434 | // Remove the object from all the indexes except the given prefix index |
| 435 | for name, indexSchema := range tableSchema.Indexes { |
| 436 | if name == deletePrefixIndex { |
| 437 | continue |
| 438 | } |
| 439 | indexTxn := txn.writableIndex(table, name) |
| 440 | |
| 441 | // Handle the update by deleting from the index first |