// deleteRow adds to the batch the kv operations necessary to delete a table row // with the given values. func (rd *rowDeleter) deleteRow(b *client.Batch, values []parser.Datum) error { if err := rd.fks.checkAll(values); err != nil { return err } primaryIndexKey, secondaryIndexEntries, err := rd.helper.encodeIndexes(rd.fetchColIDtoRowIndex, values) if err != nil { return err } for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("Del %s", secondaryIndexEntry.Key) } b.Del(secondaryIndexEntry.Key) } // Delete the row. rd.startKey = roachpb.Key(primaryIndexKey) rd.endKey = rd.startKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %s - %s", rd.startKey, rd.endKey) } b.DelRange(&rd.startKey, &rd.endKey, false) rd.startKey, rd.endKey = nil, nil return nil }
// Truncate deletes all rows from a table. // Privileges: WRITE on table. // Notes: postgres requires TRUNCATE. // mysql requires DROP (for mysql >= 5.1.16, DELETE before that). func (p *planner) Truncate(n *parser.Truncate) (planNode, error) { b := client.Batch{} for _, tableQualifiedName := range n.Tables { tableDesc, err := p.getTableDesc(tableQualifiedName) if err != nil { return nil, err } if err := p.checkPrivilege(tableDesc, privilege.WRITE); err != nil { return nil, err } tablePrefix := MakeTablePrefix(tableDesc.ID) // Delete rows and indexes starting with the table's prefix. tableStartKey := proto.Key(tablePrefix) tableEndKey := tableStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %q - %q", tableStartKey, tableEndKey) } b.DelRange(tableStartKey, tableEndKey) } if err := p.txn.Run(&b); err != nil { return nil, err } // TODO(tamird/pmattis): return the number of affected rows return &valuesNode{}, nil }
// Truncate deletes all rows from a table. // Privileges: WRITE on table. // Notes: postgres requires TRUNCATE. // mysql requires DROP (for mysql >= 5.1.16, DELETE before that). func (p *planner) Truncate(n *parser.Truncate) (planNode, error) { b := client.Batch{} for _, tableQualifiedName := range n.Tables { tableDesc, err := p.getTableDesc(tableQualifiedName) if err != nil { return nil, err } if !tableDesc.HasPrivilege(p.user, parser.PrivilegeWrite) { return nil, fmt.Errorf("user %s does not have %s privilege on table %s", p.user, parser.PrivilegeWrite, tableDesc.Name) } tablePrefix := encodeTablePrefix(tableDesc.ID) // Delete rows and indexes starting with the table's prefix. tableStartKey := proto.Key(tablePrefix) tableEndKey := tableStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %q - %q", tableStartKey, tableEndKey) } b.DelRange(tableStartKey, tableEndKey) } if err := p.db.Run(&b); err != nil { return nil, err } // TODO(tamird/pmattis): return the number of affected rows return &valuesNode{}, nil }
// Truncate deletes all rows from a table. // Privileges: DROP on table. // Notes: postgres requires TRUNCATE. // mysql requires DROP (for mysql >= 5.1.16, DELETE before that). func (p *planner) Truncate(n *parser.Truncate) (planNode, *roachpb.Error) { b := client.Batch{} for _, tableQualifiedName := range n.Tables { tableDesc, pErr := p.getTableLease(tableQualifiedName) if pErr != nil { return nil, pErr } if err := p.checkPrivilege(&tableDesc, privilege.DROP); err != nil { return nil, roachpb.NewError(err) } tablePrefix := keys.MakeTablePrefix(uint32(tableDesc.ID)) // Delete rows and indexes starting with the table's prefix. tableStartKey := roachpb.Key(tablePrefix) tableEndKey := tableStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %s - %s", tableStartKey, tableEndKey) } b.DelRange(tableStartKey, tableEndKey, false) } if pErr := p.txn.Run(&b); pErr != nil { return nil, pErr } return &emptyNode{}, nil }
// Truncate deletes all rows from a table. // Privileges: DROP on table. // Notes: postgres requires TRUNCATE. // mysql requires DROP (for mysql >= 5.1.16, DELETE before that). func (p *planner) Truncate(n *parser.Truncate) (planNode, error) { b := client.Batch{} for _, tableQualifiedName := range n.Tables { tableDesc, err := p.getTableDesc(tableQualifiedName) if err != nil { return nil, err } if err := p.checkPrivilege(tableDesc, privilege.DROP); err != nil { return nil, err } tablePrefix := keys.MakeTablePrefix(uint32(tableDesc.ID)) // Delete rows and indexes starting with the table's prefix. tableStartKey := proto.Key(tablePrefix) tableEndKey := tableStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %s - %s", prettyKey(tableStartKey, 0), prettyKey(tableEndKey, 0)) } b.DelRange(tableStartKey, tableEndKey) } if err := p.txn.Run(&b); err != nil { return nil, err } return &valuesNode{}, nil }
// Delete deletes rows from a table. func (p *planner) Delete(n *parser.Delete) (planNode, error) { tableDesc, err := p.getAliasedTableDesc(n.Table) if err != nil { return nil, err } // TODO(tamird,pmattis): avoid going through Select to avoid encoding // and decoding keys. Also, avoiding Select may provide more // convenient access to index keys which we are not currently // deleting. node, err := p.Select(&parser.Select{ Exprs: parser.SelectExprs{ &parser.StarExpr{TableName: parser.QualifiedName{tableDesc.Name}}, }, From: parser.TableExprs{n.Table}, Where: n.Where, }) if err != nil { return nil, err } colMap := map[uint32]int{} for i, name := range node.Columns() { c, err := tableDesc.FindColumnByName(name) if err != nil { return nil, err } colMap[c.ID] = i } index := tableDesc.Indexes[0] indexKey := encodeIndexKeyPrefix(tableDesc.ID, index.ID) b := client.Batch{} for node.Next() { if err := node.Err(); err != nil { return nil, err } // TODO(tamird/pmattis): delete the secondary indexes too primaryKey, err := encodeIndexKey(index, colMap, node.Values(), indexKey) if err != nil { return nil, err } rowStartKey := proto.Key(primaryKey) b.DelRange(rowStartKey, rowStartKey.PrefixEnd()) } if err := p.db.Run(&b); err != nil { return nil, err } // TODO(tamird/pmattis): return the number of affected rows return &valuesNode{}, nil }
// truncateTable truncates the data of a table. // It deletes a range of data for the table, which includes the PK and all // indexes. func truncateTable(tableDesc *sqlbase.TableDescriptor, txn *client.Txn) error { tablePrefix := keys.MakeTablePrefix(uint32(tableDesc.ID)) // Delete rows and indexes starting with the table's prefix. tableStartKey := roachpb.Key(tablePrefix) tableEndKey := tableStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %s - %s", tableStartKey, tableEndKey) } b := client.Batch{} b.DelRange(tableStartKey, tableEndKey, false) return txn.Run(&b) }
// Delete deletes rows from a table. func (p *planner) Delete(n *parser.Delete) (planNode, error) { tableDesc, err := p.getAliasedTableDesc(n.Table) if err != nil { return nil, err } // TODO(tamird,pmattis): avoid going through Select to avoid encoding // and decoding keys. Also, avoiding Select may provide more // convenient access to index keys which we are not currently // deleting. node, err := p.Select(&parser.Select{ Exprs: parser.SelectExprs{ &parser.StarExpr{TableName: parser.QualifiedName{tableDesc.Name}}, }, From: parser.TableExprs{n.Table}, Where: n.Where, }) if err != nil { return nil, err } colMap := map[uint32]int{} for i, name := range node.Columns() { c, err := tableDesc.FindColumnByName(name) if err != nil { return nil, err } colMap[c.ID] = i } primaryIndex := tableDesc.Indexes[0] primaryIndexKeyPrefix := encodeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) b := client.Batch{} for node.Next() { if err := node.Err(); err != nil { return nil, err } values := node.Values() primaryIndexKeySuffix, err := encodeIndexKey(primaryIndex, colMap, values, nil) if err != nil { return nil, err } primaryIndexKey := bytes.Join([][]byte{primaryIndexKeyPrefix, primaryIndexKeySuffix}, nil) // Delete the secondary indexes. secondaryIndexEntries, err := encodeSecondaryIndexes(tableDesc, colMap, values, primaryIndexKeySuffix) if err != nil { return nil, err } for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("Del %q", secondaryIndexEntry.key) } b.Del(secondaryIndexEntry.key) } // Delete the row. rowStartKey := proto.Key(primaryIndexKey) rowEndKey := rowStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %q - %q", rowStartKey, rowEndKey) } b.DelRange(rowStartKey, rowEndKey) } if err := p.db.Run(&b); err != nil { return nil, err } // TODO(tamird/pmattis): return the number of affected rows return &valuesNode{}, nil }
// Delete deletes rows from a table. // Privileges: DELETE and SELECT on table. We currently always use a SELECT statement. // Notes: postgres requires DELETE. Also requires SELECT for "USING" and "WHERE" with tables. // mysql requires DELETE. Also requires SELECT if a table is used in the "WHERE" clause. func (p *planner) Delete(n *parser.Delete) (planNode, *roachpb.Error) { tableDesc, pErr := p.getAliasedTableLease(n.Table) if pErr != nil { return nil, pErr } if err := p.checkPrivilege(tableDesc, privilege.DELETE); err != nil { return nil, roachpb.NewError(err) } // TODO(tamird,pmattis): avoid going through Select to avoid encoding // and decoding keys. rows, pErr := p.Select(&parser.Select{ Exprs: tableDesc.allColumnsSelector(), From: parser.TableExprs{n.Table}, Where: n.Where, }) if pErr != nil { return nil, pErr } if p.prepareOnly { return nil, nil } // Construct a map from column ID to the index the value appears at within a // row. colIDtoRowIndex, err := makeColIDtoRowIndex(rows, tableDesc) if err != nil { return nil, roachpb.NewError(err) } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) b := client.Batch{} result := &valuesNode{} for rows.Next() { rowVals := rows.Values() result.rows = append(result.rows, parser.DTuple(nil)) primaryIndexKey, _, err := encodeIndexKey( &primaryIndex, colIDtoRowIndex, rowVals, primaryIndexKeyPrefix) if err != nil { return nil, roachpb.NewError(err) } // Delete the secondary indexes. indexes := tableDesc.Indexes // Also include all the indexes under mutation; mutation state is // irrelevant for deletions. for _, m := range tableDesc.Mutations { if index := m.GetIndex(); index != nil { indexes = append(indexes, *index) } } secondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, indexes, colIDtoRowIndex, rowVals) if err != nil { return nil, roachpb.NewError(err) } for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("Del %s", secondaryIndexEntry.key) } b.Del(secondaryIndexEntry.key) } // Delete the row. rowStartKey := roachpb.Key(primaryIndexKey) rowEndKey := rowStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %s - %s", rowStartKey, rowEndKey) } b.DelRange(rowStartKey, rowEndKey) } if pErr := rows.PErr(); pErr != nil { return nil, pErr } if isSystemConfigID(tableDesc.GetID()) { // Mark transaction as operating on the system DB. p.txn.SetSystemConfigTrigger() } if pErr := p.txn.Run(&b); pErr != nil { return nil, pErr } return result, nil }
func (p *planner) backfillBatch(b *client.Batch, tableName *parser.QualifiedName, oldTableDesc, newTableDesc *TableDescriptor) error { table := &parser.AliasedTableExpr{Expr: tableName} var droppedColumnDescs []ColumnDescriptor var droppedIndexDescs []IndexDescriptor var newIndexDescs []IndexDescriptor for _, m := range oldTableDesc.Mutations { switch m.Direction { case DescriptorMutation_ADD: switch t := m.Descriptor_.(type) { case *DescriptorMutation_Column: // TODO(vivek): Add column to new columns and use it // to fill in default values. case *DescriptorMutation_Index: newIndexDescs = append(newIndexDescs, *t.Index) } case DescriptorMutation_DROP: switch t := m.Descriptor_.(type) { case *DescriptorMutation_Column: droppedColumnDescs = append(droppedColumnDescs, *t.Column) case *DescriptorMutation_Index: droppedIndexDescs = append(droppedIndexDescs, *t.Index) } } } if len(droppedColumnDescs) > 0 { var updateExprs parser.UpdateExprs for _, droppedColumnDesc := range droppedColumnDescs { updateExprs = append(updateExprs, &parser.UpdateExpr{ Names: parser.QualifiedNames{&parser.QualifiedName{Base: parser.Name(droppedColumnDesc.Name)}}, Expr: parser.DNull, }) } // Run `UPDATE <table> SET col1 = NULL, col2 = NULL, ...` to clear // the data stored in the columns being dropped. if _, err := p.Update(&parser.Update{ Table: table, Exprs: updateExprs, }); err != nil { return err } } for _, indexDescriptor := range droppedIndexDescs { indexPrefix := MakeIndexKeyPrefix(newTableDesc.ID, indexDescriptor.ID) // Delete the index. indexStartKey := roachpb.Key(indexPrefix) indexEndKey := indexStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %s - %s", prettyKey(indexStartKey, 0), prettyKey(indexEndKey, 0)) } b.DelRange(indexStartKey, indexEndKey) } if len(newIndexDescs) > 0 { // Get all the rows affected. // TODO(vivek): Avoid going through Select. // TODO(tamird): Support partial indexes? rows, err := p.Select(&parser.Select{ Exprs: parser.SelectExprs{parser.StarSelectExpr()}, From: parser.TableExprs{table}, }) if err != nil { return err } // Construct a map from column ID to the index the value appears at within a // row. colIDtoRowIndex, err := makeColIDtoRowIndex(rows, oldTableDesc) if err != nil { return err } // TODO(tamird): This will fall down in production use. We need to do // something better (see #2036). In particular, this implementation // has the following problems: // - Very large tables will generate an enormous batch here. This // isn't really a problem in itself except that it will exacerbate // the other issue: // - Any non-quiescent table that this runs against will end up with // an inconsistent index. This is because as inserts/updates continue // to roll in behind this operation's read front, the written index // will become incomplete/stale before it's written. for rows.Next() { rowVals := rows.Values() for _, newIndexDesc := range newIndexDescs { secondaryIndexEntries, err := encodeSecondaryIndexes( oldTableDesc.ID, []IndexDescriptor{newIndexDesc}, colIDtoRowIndex, rowVals) if err != nil { return err } for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("CPut %s -> %v", prettyKey(secondaryIndexEntry.key, 0), secondaryIndexEntry.value) } b.CPut(secondaryIndexEntry.key, secondaryIndexEntry.value, nil) } } } return rows.Err() } return nil }
// Delete deletes rows from a table. // Privileges: WRITE and READ on table. We currently always use a SELECT statement. // Notes: postgres requires DELETE. Also requires SELECT for "USING" and "WHERE" with tables. // mysql requires DELETE. Also requires SELECT if a table is used in the "WHERE" clause. func (p *planner) Delete(n *parser.Delete) (planNode, error) { tableDesc, err := p.getAliasedTableDesc(n.Table) if err != nil { return nil, err } if !tableDesc.HasPrivilege(p.user, parser.PrivilegeWrite) { return nil, fmt.Errorf("user %s does not have %s privilege on table %s", p.user, parser.PrivilegeWrite, tableDesc.Name) } // TODO(tamird,pmattis): avoid going through Select to avoid encoding // and decoding keys. Also, avoiding Select may provide more // convenient access to index keys which we are not currently // deleting. node, err := p.Select(&parser.Select{ Exprs: parser.SelectExprs{ &parser.StarExpr{TableName: &parser.QualifiedName{Base: parser.Name(tableDesc.Name)}}, }, From: parser.TableExprs{n.Table}, Where: n.Where, }) if err != nil { return nil, err } // Construct a map from column ID to the index the value appears at within a // row. colIDtoRowIndex := map[structured.ID]int{} for i, name := range node.Columns() { c, err := tableDesc.FindColumnByName(name) if err != nil { return nil, err } colIDtoRowIndex[c.ID] = i } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := structured.MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) b := client.Batch{} for node.Next() { if err := node.Err(); err != nil { return nil, err } values := node.Values() primaryIndexKeySuffix, _, err := encodeIndexKey(primaryIndex.ColumnIDs, colIDtoRowIndex, values, nil) if err != nil { return nil, err } primaryIndexKey := bytes.Join([][]byte{primaryIndexKeyPrefix, primaryIndexKeySuffix}, nil) // Delete the secondary indexes. secondaryIndexEntries, err := encodeSecondaryIndexes(tableDesc.ID, tableDesc.Indexes, colIDtoRowIndex, values, primaryIndexKeySuffix) if err != nil { return nil, err } for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("Del %q", secondaryIndexEntry.key) } b.Del(secondaryIndexEntry.key) } // Delete the row. rowStartKey := proto.Key(primaryIndexKey) rowEndKey := rowStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %q - %q", rowStartKey, rowEndKey) } b.DelRange(rowStartKey, rowEndKey) } if err := p.db.Run(&b); err != nil { return nil, err } // TODO(tamird/pmattis): return the number of affected rows return &valuesNode{}, nil }
func (p *planner) backfillBatch(b *client.Batch, oldTableDesc *TableDescriptor, mutationID MutationID) *roachpb.Error { var droppedColumnDescs []ColumnDescriptor var droppedIndexDescs []IndexDescriptor var newIndexDescs []IndexDescriptor // Collect the elements that are part of the mutation. for _, m := range oldTableDesc.Mutations { if m.MutationID != mutationID { // Mutations are applied in a FIFO order. Only apply the first set of // mutations if they have the mutation ID we're looking for. break } switch m.Direction { case DescriptorMutation_ADD: switch t := m.Descriptor_.(type) { case *DescriptorMutation_Column: // TODO(vivek): Add column to new columns and use it // to fill in default values. case *DescriptorMutation_Index: newIndexDescs = append(newIndexDescs, *t.Index) } case DescriptorMutation_DROP: switch t := m.Descriptor_.(type) { case *DescriptorMutation_Column: droppedColumnDescs = append(droppedColumnDescs, *t.Column) case *DescriptorMutation_Index: droppedIndexDescs = append(droppedIndexDescs, *t.Index) } } } // TODO(vivek): Break these backfill operations into chunks. All of them // will fail on big tables (see #3274). // Delete the entire dropped columns. // This used to use SQL UPDATE in the past to update the dropped // column to NULL; but a column in the process of being // dropped is placed in the table descriptor mutations, and // a SQL UPDATE of a column in mutations will fail. if len(droppedColumnDescs) > 0 { // Run a scan across the table using the primary key. start := roachpb.Key(MakeIndexKeyPrefix(oldTableDesc.ID, oldTableDesc.PrimaryIndex.ID)) // Use a different batch to perform the scan. batch := &client.Batch{} batch.Scan(start, start.PrefixEnd(), 0) if pErr := p.txn.Run(batch); pErr != nil { return pErr } for _, result := range batch.Results { var sentinelKey roachpb.Key for _, kv := range result.Rows { if sentinelKey == nil || !bytes.HasPrefix(kv.Key, sentinelKey) { // Sentinel keys have a 0 suffix indicating 0 bytes of column // ID. Strip off that suffix to determine the prefix shared with the // other keys for the row. sentinelKey = stripColumnIDLength(kv.Key) for _, columnDesc := range droppedColumnDescs { // Delete the dropped column. colKey := keys.MakeColumnKey(sentinelKey, uint32(columnDesc.ID)) if log.V(2) { log.Infof("Del %s", colKey) } b.Del(colKey) } } } } } for _, indexDescriptor := range droppedIndexDescs { indexPrefix := MakeIndexKeyPrefix(oldTableDesc.ID, indexDescriptor.ID) // Delete the index. indexStartKey := roachpb.Key(indexPrefix) indexEndKey := indexStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %s - %s", indexStartKey, indexEndKey) } b.DelRange(indexStartKey, indexEndKey) } if len(newIndexDescs) > 0 { // Get all the rows affected. // TODO(vivek): Avoid going through Select. // TODO(tamird): Support partial indexes? // Use a scanNode with SELECT to pass in a TableDescriptor // to the SELECT without needing to use a parser.QualifiedName, // because we want to run schema changes from a gossip feed of // table IDs. scan := &scanNode{ planner: p, txn: p.txn, desc: oldTableDesc, } scan.initDescDefaults() rows, pErr := p.selectIndex(&selectNode{}, scan, nil, false) if pErr != nil { return pErr } // Construct a map from column ID to the index the value appears at within a // row. colIDtoRowIndex, pErr := makeColIDtoRowIndex(rows, oldTableDesc) if pErr != nil { return pErr } for rows.Next() { rowVals := rows.Values() for _, newIndexDesc := range newIndexDescs { secondaryIndexEntries, pErr := encodeSecondaryIndexes( oldTableDesc.ID, []IndexDescriptor{newIndexDesc}, colIDtoRowIndex, rowVals) if pErr != nil { return pErr } for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("CPut %s -> %v", secondaryIndexEntry.key, secondaryIndexEntry.value) } b.CPut(secondaryIndexEntry.key, secondaryIndexEntry.value, nil) } } } return rows.PErr() } return nil }
func (p *planner) backfillBatch(b *client.Batch, oldTableDesc, newTableDesc *TableDescriptor) error { var droppedColumnDescs []ColumnDescriptor var droppedIndexDescs []IndexDescriptor var newIndexDescs []IndexDescriptor for _, m := range oldTableDesc.Mutations { switch m.Direction { case DescriptorMutation_ADD: switch t := m.Descriptor_.(type) { case *DescriptorMutation_Column: // TODO(vivek): Add column to new columns and use it // to fill in default values. case *DescriptorMutation_Index: newIndexDescs = append(newIndexDescs, *t.Index) } case DescriptorMutation_DROP: switch t := m.Descriptor_.(type) { case *DescriptorMutation_Column: droppedColumnDescs = append(droppedColumnDescs, *t.Column) case *DescriptorMutation_Index: droppedIndexDescs = append(droppedIndexDescs, *t.Index) } } } // TODO(vivek): Break these backfill operations into chunks. All of them // will fail on big tables. // Delete the entire dropped columns. // This used to use SQL UPDATE in the past to update the dropped // column to NULL; but a column in the process of being // dropped is placed in the table descriptor mutations, and // a SQL UPDATE of a column in mutations will fail. if len(droppedColumnDescs) > 0 { // Run a scan across the table using the primary key. start := roachpb.Key(MakeIndexKeyPrefix(newTableDesc.ID, newTableDesc.PrimaryIndex.ID)) // Use a different batch to perform the scan. batch := &client.Batch{} batch.Scan(start, start.PrefixEnd(), 0) if err := p.txn.Run(batch); err != nil { return err } for _, result := range batch.Results { var sentinelKey roachpb.Key for _, kv := range result.Rows { if sentinelKey == nil || !bytes.HasPrefix(kv.Key, sentinelKey) { // Sentinel keys have a 0 suffix indicating 0 bytes of column // ID. Strip off that suffix to determine the prefix shared with the // other keys for the row. sentinelKey = stripColumnIDLength(kv.Key) for _, columnDesc := range droppedColumnDescs { // Delete the dropped column. colKey := keys.MakeColumnKey(sentinelKey, uint32(columnDesc.ID)) if log.V(2) { log.Infof("Del %s", colKey) } b.Del(colKey) } } } } } for _, indexDescriptor := range droppedIndexDescs { indexPrefix := MakeIndexKeyPrefix(newTableDesc.ID, indexDescriptor.ID) // Delete the index. indexStartKey := roachpb.Key(indexPrefix) indexEndKey := indexStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %s - %s", indexStartKey, indexEndKey) } b.DelRange(indexStartKey, indexEndKey) } if len(newIndexDescs) > 0 { // Get all the rows affected. // TODO(vivek): Avoid going through Select. // TODO(tamird): Support partial indexes? // Use a scanNode with SELECT to pass in a TableDescriptor // to the SELECT without needing to use a parser.QualifiedName, // because we want to run schema changes from a gossip feed of // table IDs. scan := &scanNode{ planner: p, txn: p.txn, desc: oldTableDesc, } scan.initDescDefaults() rows, err := p.selectWithScan(scan, &parser.Select{Exprs: oldTableDesc.allColumnsSelector()}) if err != nil { return err } // Construct a map from column ID to the index the value appears at within a // row. colIDtoRowIndex, err := makeColIDtoRowIndex(rows, oldTableDesc) if err != nil { return err } // TODO(tamird): This will fall down in production use. We need to do // something better (see #2036). In particular, this implementation // has the following problems: // - Very large tables will generate an enormous batch here. This // isn't really a problem in itself except that it will exacerbate // the other issue: // - Any non-quiescent table that this runs against will end up with // an inconsistent index. This is because as inserts/updates continue // to roll in behind this operation's read front, the written index // will become incomplete/stale before it's written. for rows.Next() { rowVals := rows.Values() for _, newIndexDesc := range newIndexDescs { secondaryIndexEntries, err := encodeSecondaryIndexes( oldTableDesc.ID, []IndexDescriptor{newIndexDesc}, colIDtoRowIndex, rowVals) if err != nil { return err } for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("CPut %s -> %v", secondaryIndexEntry.key, secondaryIndexEntry.value) } b.CPut(secondaryIndexEntry.key, secondaryIndexEntry.value, nil) } } } return rows.Err() } return nil }
// DropIndex drops an index. // Privileges: CREATE on table. // Notes: postgres allows only the index owner to DROP an index. // mysql requires the INDEX privilege on the table. func (p *planner) DropIndex(n *parser.DropIndex) (planNode, error) { var b client.Batch for _, indexQualifiedName := range n.Names { if err := indexQualifiedName.NormalizeTableName(p.session.Database); err != nil { return nil, err } tableDesc, err := p.getTableDesc(indexQualifiedName) if err != nil { return nil, err } idxName := indexQualifiedName.Index() idx, err := tableDesc.FindIndexByName(idxName) if err != nil { if n.IfExists { // Noop. return &valuesNode{}, nil } // Index does not exist, but we want it to: error out. return nil, fmt.Errorf("index %q does not exist", idxName) } if err := p.checkPrivilege(tableDesc, privilege.CREATE); err != nil { return nil, err } indexPrefix := MakeIndexKeyPrefix(tableDesc.ID, idx.ID) // Delete the index. indexStartKey := proto.Key(indexPrefix) indexEndKey := indexStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %q - %q", indexStartKey, indexEndKey) } b.DelRange(indexStartKey, indexEndKey) found := false for i := range tableDesc.Indexes { if &tableDesc.Indexes[i] == idx { tableDesc.Indexes = append(tableDesc.Indexes[:i], tableDesc.Indexes[i+1:]...) found = true break } } if !found { return nil, util.Errorf("index %s not found in %s", idx, tableDesc) } descKey := MakeDescMetadataKey(tableDesc.GetID()) if err := tableDesc.Validate(); err != nil { return nil, err } if err := p.txn.Put(descKey, tableDesc); err != nil { return nil, err } // Mark transaction as operating on the system DB. p.txn.SetSystemDBTrigger() } if err := p.txn.Run(&b).GoError(); err != nil { return nil, err } return &valuesNode{}, nil }
// Delete deletes rows from a table. // Privileges: DELETE and SELECT on table. We currently always use a SELECT statement. // Notes: postgres requires DELETE. Also requires SELECT for "USING" and "WHERE" with tables. // mysql requires DELETE. Also requires SELECT if a table is used in the "WHERE" clause. func (p *planner) Delete(n *parser.Delete) (planNode, error) { tableDesc, err := p.getAliasedTableDesc(n.Table, false /* !allowCache */) if err != nil { return nil, err } if err := p.checkPrivilege(tableDesc, privilege.DELETE); err != nil { return nil, err } // TODO(tamird,pmattis): avoid going through Select to avoid encoding // and decoding keys. Also, avoiding Select may provide more // convenient access to index keys which we are not currently // deleting. rows, err := p.Select(&parser.Select{ Exprs: parser.SelectExprs{parser.StarSelectExpr()}, From: parser.TableExprs{n.Table}, Where: n.Where, }) if err != nil { return nil, err } // Construct a map from column ID to the index the value appears at within a // row. colIDtoRowIndex := map[ColumnID]int{} for i, name := range rows.Columns() { c, err := tableDesc.FindColumnByName(name) if err != nil { return nil, err } colIDtoRowIndex[c.ID] = i } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) b := client.Batch{} result := &valuesNode{} for rows.Next() { rowVals := rows.Values() result.rows = append(result.rows, parser.DTuple(nil)) primaryIndexKey, _, err := encodeIndexKey( primaryIndex.ColumnIDs, colIDtoRowIndex, rowVals, primaryIndexKeyPrefix) if err != nil { return nil, err } // Delete the secondary indexes. secondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, tableDesc.Indexes, colIDtoRowIndex, rowVals) if err != nil { return nil, err } for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("Del %s", prettyKey(secondaryIndexEntry.key, 0)) } b.Del(secondaryIndexEntry.key) } // Delete the row. rowStartKey := roachpb.Key(primaryIndexKey) rowEndKey := rowStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %s - %s", prettyKey(rowStartKey, 0), prettyKey(rowEndKey, 0)) } b.DelRange(rowStartKey, rowEndKey) } if err := rows.Err(); err != nil { return nil, err } if err := p.txn.Run(&b); err != nil { return nil, err } return result, nil }
// Delete deletes rows from a table. // Privileges: DELETE and SELECT on table. We currently always use a SELECT statement. // Notes: postgres requires DELETE. Also requires SELECT for "USING" and "WHERE" with tables. // mysql requires DELETE. Also requires SELECT if a table is used in the "WHERE" clause. func (p *planner) Delete(n *parser.Delete) (planNode, error) { tableDesc, err := p.getAliasedTableDesc(n.Table) if err != nil { return nil, err } if err := p.checkPrivilege(tableDesc, privilege.DELETE); err != nil { return nil, err } // TODO(tamird,pmattis): avoid going through Select to avoid encoding // and decoding keys. Also, avoiding Select may provide more // convenient access to index keys which we are not currently // deleting. node, err := p.Select(&parser.Select{ Exprs: parser.SelectExprs{parser.StarSelectExpr()}, From: parser.TableExprs{n.Table}, Where: n.Where, }) if err != nil { return nil, err } // Construct a map from column ID to the index the value appears at within a // row. colIDtoRowIndex := map[ColumnID]int{} for i, name := range node.Columns() { c, err := tableDesc.FindColumnByName(name) if err != nil { return nil, err } colIDtoRowIndex[c.ID] = i } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) b := client.Batch{} for node.Next() { values := node.Values() primaryIndexKey, _, err := encodeIndexKey( primaryIndex.ColumnIDs, colIDtoRowIndex, values, primaryIndexKeyPrefix) if err != nil { return nil, err } // Delete the secondary indexes. secondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, tableDesc.Indexes, colIDtoRowIndex, values) if err != nil { return nil, err } for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("Del %q", secondaryIndexEntry.key) } b.Del(secondaryIndexEntry.key) } // Delete the row. rowStartKey := proto.Key(primaryIndexKey) rowEndKey := rowStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %q - %q", rowStartKey, rowEndKey) } b.DelRange(rowStartKey, rowEndKey) } if err := node.Err(); err != nil { return nil, err } if err := p.txn.Run(&b).GoError(); err != nil { return nil, err } // TODO(tamird/pmattis): return the number of affected rows return &valuesNode{}, nil }
// Delete deletes rows from a table. // Privileges: DELETE and SELECT on table. We currently always use a SELECT statement. // Notes: postgres requires DELETE. Also requires SELECT for "USING" and "WHERE" with tables. // mysql requires DELETE. Also requires SELECT if a table is used in the "WHERE" clause. func (p *planner) Delete(n *parser.Delete) (planNode, error) { tableDesc, err := p.getAliasedTableDesc(n.Table, false /* !allowCache */) if err != nil { return nil, err } if err := p.checkPrivilege(tableDesc, privilege.DELETE); err != nil { return nil, err } // TODO(tamird,pmattis): avoid going through Select to avoid encoding // and decoding keys. rows, err := p.Select(&parser.Select{ Exprs: parser.SelectExprs{parser.StarSelectExpr()}, From: parser.TableExprs{n.Table}, Where: n.Where, }) if err != nil { return nil, err } // Construct a map from column ID to the index the value appears at within a // row. colIDtoRowIndex, err := makeColIDtoRowIndex(rows, tableDesc) if err != nil { return nil, err } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) b := client.Batch{} result := &valuesNode{} for rows.Next() { rowVals := rows.Values() result.rows = append(result.rows, parser.DTuple(nil)) primaryIndexKey, _, err := encodeIndexKey( primaryIndex.ColumnIDs, colIDtoRowIndex, rowVals, primaryIndexKeyPrefix) if err != nil { return nil, err } // Delete the secondary indexes. secondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, tableDesc.Indexes, colIDtoRowIndex, rowVals) if err != nil { return nil, err } for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("Del %s", prettyKey(secondaryIndexEntry.key, 0)) } b.Del(secondaryIndexEntry.key) } // Delete the row. rowStartKey := roachpb.Key(primaryIndexKey) rowEndKey := rowStartKey.PrefixEnd() if log.V(2) { log.Infof("DelRange %s - %s", prettyKey(rowStartKey, 0), prettyKey(rowEndKey, 0)) } b.DelRange(rowStartKey, rowEndKey) } if err := rows.Err(); err != nil { return nil, err } if IsSystemID(tableDesc.GetID()) { // Mark transaction as operating on the system DB. p.txn.SetSystemDBTrigger() } if err := p.txn.Run(&b); err != nil { return nil, err } return result, nil }