// upsertRowPKs returns the primary keys of any rows with potential upsert // conflicts. func (tu *tableUpserter) upsertRowPKs(ctx context.Context) ([]roachpb.Key, error) { upsertRowPKs := make([]roachpb.Key, len(tu.insertRows)) if tu.conflictIndex.ID == tu.tableDesc.PrimaryIndex.ID { // If the conflict index is the primary index, we can compute them directly. // In this case, the slice will be filled, but not all rows will have // conflicts. for i, insertRow := range tu.insertRows { upsertRowPK, _, err := sqlbase.EncodeIndexKey( tu.tableDesc, &tu.conflictIndex, tu.ri.InsertColIDtoRowIndex, insertRow, tu.indexKeyPrefix) if err != nil { return nil, err } upsertRowPKs[i] = upsertRowPK } return upsertRowPKs, nil } // Otherwise, compute the keys for the conflict index and look them up. The // primary keys can be constructed from the entries that come back. In this // case, some spots in the slice will be nil (indicating no conflict) and the // others will be conflicting rows. b := tu.txn.NewBatch() for _, insertRow := range tu.insertRows { entry, err := sqlbase.EncodeSecondaryIndex( tu.tableDesc, &tu.conflictIndex, tu.ri.InsertColIDtoRowIndex, insertRow) if err != nil { return nil, err } if log.V(2) { log.Infof(ctx, "Get %s\n", entry.Key) } b.Get(entry.Key) } if err := tu.txn.Run(b); err != nil { return nil, err } for i, result := range b.Results { // if len(result.Rows) == 0, then no conflict for this row, so leave // upsertRowPKs[i] as nil. if len(result.Rows) == 1 { if result.Rows[0].Value == nil { upsertRowPKs[i] = nil } else { upsertRowPK, err := sqlbase.ExtractIndexKey(&tu.a, tu.tableDesc, result.Rows[0]) if err != nil { return nil, err } upsertRowPKs[i] = upsertRowPK } } else if len(result.Rows) > 1 { panic(fmt.Errorf( "Expected <= 1 but got %d conflicts for row %s", len(result.Rows), tu.insertRows[i])) } } return upsertRowPKs, nil }
// deleteIndexRow adds to the batch the kv operations necessary to delete a // table row from the given index. func (rd *rowDeleter) deleteIndexRow( ctx context.Context, b *client.Batch, idx *sqlbase.IndexDescriptor, values []parser.Datum, ) error { if err := rd.fks.checkAll(values); err != nil { return err } secondaryIndexEntry, err := sqlbase.EncodeSecondaryIndex( rd.helper.tableDesc, idx, rd.fetchColIDtoRowIndex, values) if err != nil { return err } if log.V(2) { log.Infof(ctx, "Del %s", secondaryIndexEntry.Key) } b.Del(secondaryIndexEntry.Key) return nil }