// makeRowDeleter creates a rowDeleter for the given table. // // The returned rowDeleter contains a fetchCols field that defines the // expectation of which values are passed as values to deleteRow. Any column // passed in requestedCols will be included in fetchCols. func makeRowDeleter( txn *client.Txn, tableDesc *sqlbase.TableDescriptor, fkTables tableLookupsByID, requestedCols []sqlbase.ColumnDescriptor, checkFKs bool, ) (rowDeleter, error) { indexes := tableDesc.Indexes for _, m := range tableDesc.Mutations { if index := m.GetIndex(); index != nil { indexes = append(indexes, *index) } } fetchCols := requestedCols[:len(requestedCols):len(requestedCols)] fetchColIDtoRowIndex := colIDtoRowIndexFromCols(fetchCols) maybeAddCol := func(colID sqlbase.ColumnID) error { if _, ok := fetchColIDtoRowIndex[colID]; !ok { col, err := tableDesc.FindColumnByID(colID) if err != nil { return err } fetchColIDtoRowIndex[col.ID] = len(fetchCols) fetchCols = append(fetchCols, *col) } return nil } for _, colID := range tableDesc.PrimaryIndex.ColumnIDs { if err := maybeAddCol(colID); err != nil { return rowDeleter{}, err } } for _, index := range indexes { for _, colID := range index.ColumnIDs { if err := maybeAddCol(colID); err != nil { return rowDeleter{}, err } } } rd := rowDeleter{ helper: rowHelper{tableDesc: tableDesc, indexes: indexes}, fetchCols: fetchCols, fetchColIDtoRowIndex: fetchColIDtoRowIndex, } if checkFKs { var err error if rd.fks, err = makeFKDeleteHelper(txn, *tableDesc, fkTables, fetchColIDtoRowIndex); err != nil { return rowDeleter{}, err } } return rd, nil }
// makeRowUpdater creates a rowUpdater for the given table. // // updateCols are the columns being updated and correspond to the updateValues // that will be passed to updateRow. // // The returned rowUpdater contains a fetchCols field that defines the // expectation of which values are passed as oldValues to updateRow. Any column // passed in requestedCols will be included in fetchCols. func makeRowUpdater( txn *client.Txn, tableDesc *sqlbase.TableDescriptor, fkTables tableLookupsByID, updateCols []sqlbase.ColumnDescriptor, requestedCols []sqlbase.ColumnDescriptor, updateType rowUpdaterType, ) (rowUpdater, error) { updateColIDtoRowIndex := colIDtoRowIndexFromCols(updateCols) primaryIndexCols := make(map[sqlbase.ColumnID]struct{}, len(tableDesc.PrimaryIndex.ColumnIDs)) for _, colID := range tableDesc.PrimaryIndex.ColumnIDs { primaryIndexCols[colID] = struct{}{} } var primaryKeyColChange bool for _, c := range updateCols { if _, ok := primaryIndexCols[c.ID]; ok { primaryKeyColChange = true break } } // Secondary indexes needing updating. needsUpdate := func(index sqlbase.IndexDescriptor) bool { if updateType == rowUpdaterOnlyColumns { // Only update columns. return false } // If the primary key changed, we need to update all of them. if primaryKeyColChange { return true } for _, id := range index.ColumnIDs { if _, ok := updateColIDtoRowIndex[id]; ok { return true } } return false } indexes := make([]sqlbase.IndexDescriptor, 0, len(tableDesc.Indexes)+len(tableDesc.Mutations)) for _, index := range tableDesc.Indexes { if needsUpdate(index) { indexes = append(indexes, index) } } var deleteOnlyIndex map[int]struct{} for _, m := range tableDesc.Mutations { if index := m.GetIndex(); index != nil { if needsUpdate(*index) { indexes = append(indexes, *index) switch m.State { case sqlbase.DescriptorMutation_DELETE_ONLY: if deleteOnlyIndex == nil { // Allocate at most once. deleteOnlyIndex = make(map[int]struct{}, len(tableDesc.Mutations)) } deleteOnlyIndex[len(indexes)-1] = struct{}{} case sqlbase.DescriptorMutation_WRITE_ONLY: } } } } ru := rowUpdater{ helper: rowHelper{tableDesc: tableDesc, indexes: indexes}, updateCols: updateCols, updateColIDtoRowIndex: updateColIDtoRowIndex, deleteOnlyIndex: deleteOnlyIndex, primaryKeyColChange: primaryKeyColChange, marshalled: make([]roachpb.Value, len(updateCols)), newValues: make([]parser.Datum, len(tableDesc.Columns)+len(tableDesc.Mutations)), } if primaryKeyColChange { // These fields are only used when the primary key is changing. var err error // When changing the primary key, we delete the old values and reinsert // them, so request them all. if ru.rd, err = makeRowDeleter(txn, tableDesc, fkTables, tableDesc.Columns, skipFKs); err != nil { return rowUpdater{}, err } ru.fetchCols = ru.rd.fetchCols ru.fetchColIDtoRowIndex = colIDtoRowIndexFromCols(ru.fetchCols) if ru.ri, err = MakeRowInserter(txn, tableDesc, fkTables, tableDesc.Columns, skipFKs); err != nil { return rowUpdater{}, err } } else { ru.fetchCols = requestedCols[:len(requestedCols):len(requestedCols)] ru.fetchColIDtoRowIndex = colIDtoRowIndexFromCols(ru.fetchCols) maybeAddCol := func(colID sqlbase.ColumnID) error { if _, ok := ru.fetchColIDtoRowIndex[colID]; !ok { col, err := tableDesc.FindColumnByID(colID) if err != nil { return err } ru.fetchColIDtoRowIndex[col.ID] = len(ru.fetchCols) ru.fetchCols = append(ru.fetchCols, *col) } return nil } for _, colID := range tableDesc.PrimaryIndex.ColumnIDs { if err := maybeAddCol(colID); err != nil { return rowUpdater{}, err } } for _, fam := range tableDesc.Families { familyBeingUpdated := false for _, colID := range fam.ColumnIDs { if _, ok := ru.updateColIDtoRowIndex[colID]; ok { familyBeingUpdated = true break } } if familyBeingUpdated { for _, colID := range fam.ColumnIDs { if err := maybeAddCol(colID); err != nil { return rowUpdater{}, err } } } } for _, index := range indexes { for _, colID := range index.ColumnIDs { if err := maybeAddCol(colID); err != nil { return rowUpdater{}, err } } } } var err error if ru.fks, err = makeFKUpdateHelper(txn, *tableDesc, fkTables, ru.fetchColIDtoRowIndex); err != nil { return rowUpdater{}, err } return ru, nil }