// writeDescriptor takes a Table or Database descriptor and writes it // if needed, incrementing the descriptor counter. func (p *planner) writeDescriptor(plainKey descriptorKey, descriptor descriptorProto, ifNotExists bool) error { key := plainKey.Key() // Check whether key exists. gr, err := p.txn.Get(key) if err != nil { return err } if gr.Exists() { if ifNotExists { // Noop. return nil } // Key exists, but we don't want it to: error out. return fmt.Errorf("%s %q already exists", descriptor.TypeName(), plainKey.Name()) } // Increment unique descriptor counter. if ir, err := p.txn.Inc(keys.DescIDGenerator, 1); err == nil { descriptor.SetID(structured.ID(ir.ValueInt() - 1)) } else { return err } // TODO(pmattis): The error currently returned below is likely going to be // difficult to interpret. // TODO(pmattis): Need to handle if-not-exists here as well. descKey := structured.MakeDescMetadataKey(descriptor.GetID()) b := client.Batch{} b.CPut(key, descKey, nil) b.CPut(descKey, descriptor, nil) return p.txn.Run(&b) }
// RenameDatabase renames the database. // Privileges: security.RootUser user. // Notes: postgres requires superuser, db owner, or "CREATEDB". // mysql >= 5.1.23 does not allow database renames. func (p *planner) RenameDatabase(n *parser.RenameDatabase) (planNode, error) { if n.Name == "" || n.NewName == "" { return nil, errEmptyDatabaseName } if p.session.User != security.RootUser { return nil, fmt.Errorf("only %s is allowed to rename databases", security.RootUser) } dbDesc, err := p.getDatabaseDesc(string(n.Name)) if err != nil { return nil, err } if dbDesc == nil { return nil, databaseDoesNotExistError(string(n.Name)) } if n.Name == n.NewName { // Noop. return &emptyNode{}, nil } // Now update the nameMetadataKey and the descriptor. descKey := sqlbase.MakeDescMetadataKey(dbDesc.GetID()) dbDesc.SetName(string(n.NewName)) if err := dbDesc.Validate(); err != nil { return nil, err } newKey := databaseKey{string(n.NewName)}.Key() oldKey := databaseKey{string(n.Name)}.Key() descID := dbDesc.GetID() descDesc := sqlbase.WrapDescriptor(dbDesc) b := client.Batch{} b.CPut(newKey, descID, nil) b.Put(descKey, descDesc) b.Del(oldKey) if err := p.txn.Run(&b); err != nil { if _, ok := err.(*roachpb.ConditionFailedError); ok { return nil, fmt.Errorf("the new database name %q already exists", string(n.NewName)) } return nil, err } p.setTestingVerifyMetadata(func(systemConfig config.SystemConfig) error { if err := expectDescriptorID(systemConfig, newKey, descID); err != nil { return err } if err := expectDescriptor(systemConfig, descKey, descDesc); err != nil { return err } return expectDeleted(systemConfig, oldKey) }) return &emptyNode{}, nil }
func (p *planner) makeBackfillBatch(tableName *parser.QualifiedName, tableDesc *TableDescriptor, indexDescs ...IndexDescriptor) (client.Batch, error) { b := client.Batch{} // Get all the rows affected. // TODO(vivek): Avoid going through Select. // TODO(tamird): Support partial indexes? row, err := p.Select(&parser.Select{ Exprs: parser.SelectExprs{parser.StarSelectExpr()}, From: parser.TableExprs{&parser.AliasedTableExpr{Expr: tableName}}, }) if err != nil { return b, 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 row.Columns() { c, err := tableDesc.FindColumnByName(name) if err != nil { return b, err } colIDtoRowIndex[c.ID] = i } // 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 row.Next() { rowVals := row.Values() for _, indexDesc := range indexDescs { secondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, []IndexDescriptor{indexDesc}, colIDtoRowIndex, rowVals) if err != nil { return b, 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 b, row.Err() }
// createDescriptor implements the DescriptorAccessor interface. func (p *planner) createDescriptor(plainKey sqlbase.DescriptorKey, descriptor sqlbase.DescriptorProto, ifNotExists bool) (bool, error) { idKey := plainKey.Key() // Check whether idKey exists. gr, err := p.txn.Get(idKey) if err != nil { return false, err } if gr.Exists() { if ifNotExists { // Noop. return false, nil } // Key exists, but we don't want it to: error out. return false, fmt.Errorf("%s %q already exists", descriptor.TypeName(), plainKey.Name()) } // Increment unique descriptor counter. if ir, err := p.txn.Inc(keys.DescIDGenerator, 1); err == nil { descriptor.SetID(sqlbase.ID(ir.ValueInt() - 1)) } else { return false, err } // TODO(pmattis): The error currently returned below is likely going to be // difficult to interpret. // // TODO(pmattis): Need to handle if-not-exists here as well. // // TODO(pmattis): This is writing the namespace and descriptor table entries, // but not going through the normal INSERT logic and not performing a precise // mimicry. In particular, we're only writing a single key per table, while // perfect mimicry would involve writing a sentinel key for each row as well. descKey := sqlbase.MakeDescMetadataKey(descriptor.GetID()) b := client.Batch{} descID := descriptor.GetID() descDesc := sqlbase.WrapDescriptor(descriptor) if log.V(2) { log.Infof("CPut %s -> %d", idKey, descID) log.Infof("CPut %s -> %s", descKey, descDesc) } b.CPut(idKey, descID, nil) b.CPut(descKey, descDesc, nil) p.setTestingVerifyMetadata(func(systemConfig config.SystemConfig) error { if err := expectDescriptorID(systemConfig, idKey, descID); err != nil { return err } return expectDescriptor(systemConfig, descKey, descDesc) }) return true, p.txn.Run(&b) }
// updateRangeDescriptor adds a ConditionalPut on the range descriptor. The // conditional put verifies that changes to the range descriptor are made in a // well-defined order, preventing a scenario where a wayward replica which is // no longer part of the original Raft group comes back online to form a // splinter group with a node which was also a former replica, and hijacks the // range descriptor. This is a last line of defense; other mechanisms should // prevent rogue replicas from getting this far (see #768). func updateRangeDescriptor(b *client.Batch, descKey proto.Key, oldDesc, newDesc *proto.RangeDescriptor) error { var oldValue []byte if oldDesc != nil { var err error if oldValue, err = gogoproto.Marshal(oldDesc); err != nil { return err } } newValue, err := gogoproto.Marshal(newDesc) if err != nil { return err } b.CPut(descKey, newValue, oldValue) return nil }
// RenameDatabase renames the database. // Privileges: "root" user. // Notes: postgres requires superuser, db owner, or "CREATEDB". // mysql >= 5.1.23 does not allow database renames. func (p *planner) RenameDatabase(n *parser.RenameDatabase) (planNode, error) { if n.Name == "" || n.NewName == "" { return nil, errEmptyDatabaseName } if p.user != security.RootUser { return nil, fmt.Errorf("only %s is allowed to rename databases", security.RootUser) } dbDesc, err := p.getDatabaseDesc(string(n.Name)) if err != nil { return nil, err } if n.Name == n.NewName { // Noop. return &valuesNode{}, nil } // Now update the nameMetadataKey and the descriptor. descKey := MakeDescMetadataKey(dbDesc.GetID()) dbDesc.SetName(string(n.NewName)) if err := dbDesc.Validate(); err != nil { return nil, err } b := client.Batch{} b.CPut(databaseKey{string(n.NewName)}.Key(), dbDesc.GetID(), nil) b.Put(descKey, dbDesc) b.Del(databaseKey{string(n.Name)}.Key()) // Mark transaction as operating on the system DB. p.txn.SetSystemDBTrigger() if err := p.txn.Run(&b); err != nil { if _, ok := err.(*proto.ConditionFailedError); ok { return nil, fmt.Errorf("the new database name %q already exists", string(n.NewName)) } return nil, err } return &valuesNode{}, nil }
// createDescriptor takes a Table or Database descriptor and creates it // if needed, incrementing the descriptor counter. func (p *planner) createDescriptor(plainKey descriptorKey, descriptor descriptorProto, ifNotExists bool) error { key := plainKey.Key() // Check whether key exists. gr, err := p.txn.Get(key) if err != nil { return err } if gr.Exists() { if ifNotExists { // Noop. return nil } // Key exists, but we don't want it to: error out. return fmt.Errorf("%s %q already exists", descriptor.TypeName(), plainKey.Name()) } // Increment unique descriptor counter. if ir, err := p.txn.Inc(keys.DescIDGenerator, 1); err == nil { descriptor.SetID(ID(ir.ValueInt() - 1)) } else { return err } // TODO(pmattis): The error currently returned below is likely going to be // difficult to interpret. // // TODO(pmattis): Need to handle if-not-exists here as well. // // TODO(pmattis): This is writing the namespace and descriptor table entries, // but not going through the normal INSERT logic and not performing a precise // mimicry. In particular, we're only writing a single key per table, while // perfect mimicry would involve writing a sentinel key for each row as well. descKey := MakeDescMetadataKey(descriptor.GetID()) b := client.Batch{} b.CPut(key, descriptor.GetID(), nil) b.CPut(descKey, wrapDescriptor(descriptor), nil) return p.txn.Run(&b) }
// Update updates columns for a selection of rows from a table. // Privileges: UPDATE and SELECT on table. We currently always use a select statement. // Notes: postgres requires UPDATE. Requires SELECT with WHERE clause with table. // mysql requires UPDATE. Also requires SELECT with WHERE clause with table. func (p *planner) Update(n *parser.Update) (planNode, error) { tableDesc, err := p.getAliasedTableDesc(n.Table) if err != nil { return nil, err } if err := p.checkPrivilege(tableDesc, privilege.UPDATE); err != nil { return nil, err } // Determine which columns we're inserting into. var names parser.QualifiedNames for _, expr := range n.Exprs { names = append(names, expr.Name) } cols, err := p.processColumns(tableDesc, names) if err != nil { return nil, err } // Set of columns being updated colIDSet := map[ColumnID]struct{}{} for _, c := range cols { colIDSet[c.ID] = struct{}{} } // Don't allow updating any column that is part of the primary key. for i, id := range tableDesc.PrimaryIndex.ColumnIDs { if _, ok := colIDSet[id]; ok { return nil, fmt.Errorf("primary key column %q cannot be updated", tableDesc.PrimaryIndex.ColumnNames[i]) } } // Generate the list of select targets. We need to select all of the columns // plus we select all of the update expressions in case those expressions // reference columns (e.g. "UPDATE t SET v = v + 1"). targets := make(parser.SelectExprs, 0, len(n.Exprs)+1) targets = append(targets, parser.StarSelectExpr()) for _, expr := range n.Exprs { targets = append(targets, parser.SelectExpr{Expr: expr.Expr}) } // Query the rows that need updating. rows, err := p.Select(&parser.Select{ Exprs: targets, 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, col := range tableDesc.Columns { colIDtoRowIndex[col.ID] = i } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) // Secondary indexes needing updating. var indexes []IndexDescriptor for _, index := range tableDesc.Indexes { for _, id := range index.ColumnIDs { if _, ok := colIDSet[id]; ok { indexes = append(indexes, index) break } } } // Update all the rows. var b client.Batch for rows.Next() { rowVals := rows.Values() primaryIndexKey, _, err := encodeIndexKey( primaryIndex.ColumnIDs, colIDtoRowIndex, rowVals, primaryIndexKeyPrefix) if err != nil { return nil, err } // Compute the current secondary index key:value pairs for this row. secondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, indexes, colIDtoRowIndex, rowVals) if err != nil { return nil, err } // Our updated value expressions occur immediately after the plain // columns in the output. newVals := rowVals[len(tableDesc.Columns):] // Update the row values. for i, col := range cols { val := newVals[i] if !col.Nullable && val == parser.DNull { return nil, fmt.Errorf("null value in column %q violates not-null constraint", col.Name) } rowVals[colIDtoRowIndex[col.ID]] = val } // Compute the new secondary index key:value pairs for this row. newSecondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, indexes, colIDtoRowIndex, rowVals) if err != nil { return nil, err } // Update secondary indexes. for i, newSecondaryIndexEntry := range newSecondaryIndexEntries { secondaryIndexEntry := secondaryIndexEntries[i] if !bytes.Equal(newSecondaryIndexEntry.key, secondaryIndexEntry.key) { if log.V(2) { log.Infof("CPut %q -> %v", newSecondaryIndexEntry.key, newSecondaryIndexEntry.value) } b.CPut(newSecondaryIndexEntry.key, newSecondaryIndexEntry.value, nil) if log.V(2) { log.Infof("Del %q", secondaryIndexEntry.key) } b.Del(secondaryIndexEntry.key) } } // Add the new values. for i, val := range newVals { col := cols[i] primitive, err := convertDatum(col, val) if err != nil { return nil, err } key := MakeColumnKey(col.ID, primaryIndexKey) if primitive != nil { // We only output non-NULL values. Non-existent column keys are // considered NULL during scanning and the row sentinel ensures we know // the row exists. if log.V(2) { log.Infof("Put %q -> %v", key, val) } b.Put(key, primitive) } else { // The column might have already existed but is being set to NULL, so // delete it. if log.V(2) { log.Infof("Del %q", key) } b.Del(key) } } } if err := rows.Err(); err != nil { return nil, err } if err := p.txn.Run(&b); err != nil { return nil, convertBatchError(tableDesc, b, err) } // TODO(tamird/pmattis): return the number of affected rows. return &valuesNode{}, nil }
// updateRow adds to the batch the kv operations necessary to update a table row // with the given values. // // The row corresponding to oldValues is updated with the ones in updateValues. // Note that updateValues only contains the ones that are changing. // // The return value is only good until the next call to UpdateRow. func (ru *rowUpdater) updateRow( b *client.Batch, oldValues []parser.Datum, updateValues []parser.Datum, ) ([]parser.Datum, error) { if len(oldValues) != len(ru.fetchCols) { return nil, util.Errorf("got %d values but expected %d", len(oldValues), len(ru.fetchCols)) } if len(updateValues) != len(ru.updateCols) { return nil, util.Errorf("got %d values but expected %d", len(updateValues), len(ru.updateCols)) } primaryIndexKey, secondaryIndexEntries, err := ru.helper.encodeIndexes(ru.fetchColIDtoRowIndex, oldValues) if err != nil { return nil, err } // Check that the new value types match the column types. This needs to // happen before index encoding because certain datum types (i.e. tuple) // cannot be used as index values. for i, val := range updateValues { if ru.marshalled[i], err = sqlbase.MarshalColumnValue(ru.updateCols[i], val); err != nil { return nil, err } } // Update the row values. copy(ru.newValues, oldValues) for i, updateCol := range ru.updateCols { ru.newValues[ru.fetchColIDtoRowIndex[updateCol.ID]] = updateValues[i] } newPrimaryIndexKey := primaryIndexKey rowPrimaryKeyChanged := false var newSecondaryIndexEntries []sqlbase.IndexEntry if ru.primaryKeyColChange { newPrimaryIndexKey, newSecondaryIndexEntries, err = ru.helper.encodeIndexes(ru.fetchColIDtoRowIndex, ru.newValues) if err != nil { return nil, err } rowPrimaryKeyChanged = !bytes.Equal(primaryIndexKey, newPrimaryIndexKey) } else { newSecondaryIndexEntries, err = sqlbase.EncodeSecondaryIndexes( ru.helper.tableDesc.ID, ru.helper.indexes, ru.fetchColIDtoRowIndex, ru.newValues) if err != nil { return nil, err } } if rowPrimaryKeyChanged { err := ru.rd.deleteRow(b, oldValues) if err != nil { return nil, err } err = ru.ri.insertRow(b, ru.newValues) return ru.newValues, err } // Update secondary indexes. for i, newSecondaryIndexEntry := range newSecondaryIndexEntries { secondaryIndexEntry := secondaryIndexEntries[i] secondaryKeyChanged := !bytes.Equal(newSecondaryIndexEntry.Key, secondaryIndexEntry.Key) if secondaryKeyChanged { if log.V(2) { log.Infof("Del %s", secondaryIndexEntry.Key) } b.Del(secondaryIndexEntry.Key) // Do not update Indexes in the DELETE_ONLY state. if _, ok := ru.deleteOnlyIndex[i]; !ok { if log.V(2) { log.Infof("CPut %s -> %v", newSecondaryIndexEntry.Key, newSecondaryIndexEntry.Value) } b.CPut(newSecondaryIndexEntry.Key, newSecondaryIndexEntry.Value, nil) } } } // Add the new values. for i, val := range updateValues { col := ru.updateCols[i] if ru.helper.columnInPK(col.ID) { // Skip primary key columns as their values are encoded in the row // sentinel key which is guaranteed to exist for as long as the row // exists. continue } ru.key = keys.MakeColumnKey(newPrimaryIndexKey, uint32(col.ID)) if ru.marshalled[i].RawBytes != nil { // We only output non-NULL values. Non-existent column keys are // considered NULL during scanning and the row sentinel ensures we know // the row exists. if log.V(2) { log.Infof("Put %s -> %v", ru.key, val) } b.Put(&ru.key, &ru.marshalled[i]) } else { // The column might have already existed but is being set to NULL, so // delete it. if log.V(2) { log.Infof("Del %s", ru.key) } b.Del(&ru.key) } ru.key = nil } return ru.newValues, nil }
// insertRow adds to the batch the kv operations necessary to insert a table row // with the given values. func (ri *rowInserter) insertRow(b *client.Batch, values []parser.Datum) error { if len(values) != len(ri.insertCols) { return util.Errorf("got %d values but expected %d", len(values), len(ri.insertCols)) } // Encode the values to the expected column type. This needs to // happen before index encoding because certain datum types (i.e. tuple) // cannot be used as index values. for i, val := range values { // Make sure the value can be written to the column before proceeding. var err error if ri.marshalled[i], err = sqlbase.MarshalColumnValue(ri.insertCols[i], val); err != nil { return err } } primaryIndexKey, secondaryIndexEntries, err := ri.helper.encodeIndexes(ri.insertColIDtoRowIndex, values) if err != nil { return err } // Write the row sentinel. We want to write the sentinel first in case // we are trying to insert a duplicate primary key: if we write the // secondary indexes first, we may get an error that looks like a // uniqueness violation on a non-unique index. ri.key = keys.MakeNonColumnKey(primaryIndexKey) if log.V(2) { log.Infof("CPut %s -> NULL", ri.key) } // Each sentinel value needs a distinct RawBytes field as the computed // checksum includes the key the value is associated with. ri.sentinelValue.SetBytes([]byte{}) b.CPut(&ri.key, &ri.sentinelValue, nil) ri.key = nil for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("CPut %s -> %v", secondaryIndexEntry.Key, secondaryIndexEntry.Value) } ri.key = secondaryIndexEntry.Key b.CPut(&ri.key, secondaryIndexEntry.Value, nil) } ri.key = nil // Write the row columns. for i, val := range values { col := ri.insertCols[i] if ri.helper.columnInPK(col.ID) { // Skip primary key columns as their values are encoded in the row // sentinel key which is guaranteed to exist for as long as the row // exists. continue } if ri.marshalled[i].RawBytes != nil { // We only output non-NULL values. Non-existent column keys are // considered NULL during scanning and the row sentinel ensures we know // the row exists. ri.key = keys.MakeColumnKey(primaryIndexKey, uint32(col.ID)) if log.V(2) { log.Infof("CPut %s -> %v", ri.key, val) } b.CPut(&ri.key, &ri.marshalled[i], nil) ri.key = nil } } return 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 }
// Insert inserts rows into the database. // Privileges: INSERT on table // Notes: postgres requires INSERT. No "on duplicate key update" option. // mysql requires INSERT. Also requires UPDATE on "ON DUPLICATE KEY UPDATE". func (p *planner) Insert(n *parser.Insert) (planNode, error) { tableDesc, err := p.getTableDesc(n.Table) if err != nil { return nil, err } if err := p.checkPrivilege(tableDesc, privilege.INSERT); err != nil { return nil, err } // Determine which columns we're inserting into. cols, err := p.processColumns(tableDesc, n.Columns) 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, c := range cols { colIDtoRowIndex[c.ID] = i } // Verify we have at least the columns that are part of the primary key. primaryKeyCols := map[ColumnID]struct{}{} for i, id := range tableDesc.PrimaryIndex.ColumnIDs { if _, ok := colIDtoRowIndex[id]; !ok { return nil, fmt.Errorf("missing %q primary key column", tableDesc.PrimaryIndex.ColumnNames[i]) } primaryKeyCols[id] = struct{}{} } // Transform the values into a rows object. This expands SELECT statements or // generates rows from the values contained within the query. rows, err := p.makePlan(n.Rows) if err != nil { return nil, err } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) b := client.Batch{} for rows.Next() { values := rows.Values() for range cols[len(values):] { values = append(values, parser.DNull) } for _, col := range tableDesc.Columns { if !col.Nullable { if i, ok := colIDtoRowIndex[col.ID]; !ok || values[i] == parser.DNull { return nil, fmt.Errorf("null value in column %q violates not-null constraint", col.Name) } } } primaryIndexKey, _, err := encodeIndexKey( primaryIndex.ColumnIDs, colIDtoRowIndex, values, primaryIndexKeyPrefix) if err != nil { return nil, err } // Write 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("CPut %q -> %v", secondaryIndexEntry.key, secondaryIndexEntry.value) } b.CPut(secondaryIndexEntry.key, secondaryIndexEntry.value, nil) } // Write the row sentinel. if log.V(2) { log.Infof("CPut %q -> NULL", primaryIndexKey) } b.CPut(primaryIndexKey, nil, nil) // Write the row columns. for i, val := range values { col := cols[i] // Make sure the value can be written to the column before proceeding. primitive, err := convertDatum(col, val) if err != nil { return nil, err } if _, ok := primaryKeyCols[col.ID]; ok { // Skip primary key columns as their values are encoded in the row // sentinel key which is guaranteed to exist for as long as the row // exists. continue } if primitive != nil { // We only output non-NULL values. Non-existent column keys are // considered NULL during scanning and the row sentinel ensures we know // the row exists. key := MakeColumnKey(col.ID, primaryIndexKey) if log.V(2) { log.Infof("CPut %q -> %v", key, primitive) } b.CPut(key, primitive, nil) } } } if err := rows.Err(); err != nil { return nil, err } if err := p.txn.Run(&b); err != nil { if tErr, ok := err.(*proto.ConditionFailedError); ok { return nil, util.Errorf("duplicate key value %q violates unique constraint %s", tErr.ActualValue.Bytes, "TODO(tamird)") } return nil, err } // TODO(tamird/pmattis): return the number of affected rows return &valuesNode{}, nil }
// Insert inserts rows into the database. // Privileges: WRITE on table // Notes: postgres requires INSERT. No "on duplicate key update" option. // mysql requires INSERT. Also requires UPDATE on "ON DUPLICATE KEY UPDATE". func (p *planner) Insert(n *parser.Insert) (planNode, error) { tableDesc, err := p.getTableDesc(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) } // Determine which columns we're inserting into. cols, err := p.processColumns(tableDesc, n.Columns) 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, c := range cols { colIDtoRowIndex[c.ID] = i } // Verify we have at least the columns that are part of the primary key. for i, id := range tableDesc.PrimaryIndex.ColumnIDs { if _, ok := colIDtoRowIndex[id]; !ok { return nil, fmt.Errorf("missing %q primary key column", tableDesc.PrimaryIndex.ColumnNames[i]) } } // Transform the values into a rows object. This expands SELECT statements or // generates rows from the values contained within the query. rows, err := p.makePlan(n.Rows) if err != nil { return nil, err } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := encodeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) b := client.Batch{} for rows.Next() { values := rows.Values() if len(values) != len(cols) { return nil, fmt.Errorf("invalid values for columns: %d != %d", len(values), len(cols)) } primaryIndexKeySuffix, _, err := encodeIndexKey(primaryIndex.ColumnIDs, colIDtoRowIndex, values, nil) if err != nil { return nil, err } primaryIndexKey := bytes.Join([][]byte{primaryIndexKeyPrefix, primaryIndexKeySuffix}, nil) // Write 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("CPut %q -> %v", secondaryIndexEntry.key, secondaryIndexEntry.value) } b.CPut(secondaryIndexEntry.key, secondaryIndexEntry.value, nil) } // Write the row. for i, val := range values { key := encodeColumnKey(cols[i], primaryIndexKey) if log.V(2) { log.Infof("CPut %q -> %v", key, val) } v, err := prepareVal(cols[i], val) if err != nil { return nil, err } b.CPut(key, v, nil) } } if err := rows.Err(); err != nil { return nil, err } if err := p.db.Run(&b); err != nil { if tErr, ok := err.(*proto.ConditionFailedError); ok { return nil, fmt.Errorf("duplicate key value %q violates unique constraint %s", tErr.ActualValue.Bytes, "TODO(tamird)") } return nil, err } // TODO(tamird/pmattis): return the number of affected rows return &valuesNode{}, nil }
// RenameTable renames the table. // Privileges: WRITE on database. // Notes: postgres requires the table owner. // mysql requires ALTER, DROP on the original table, and CREATE, INSERT // on the new table (and does not copy privileges over). func (p *planner) RenameTable(n *parser.RenameTable) (planNode, error) { if n.NewName == "" { return nil, errEmptyTableName } if err := n.Name.NormalizeTableName(p.session.Database); err != nil { return nil, err } if n.Name.Table() == string(n.NewName) { // Noop. return &valuesNode{}, nil } dbDesc, err := p.getDatabaseDesc(n.Name.Database()) if err != nil { return nil, err } tbKey := tableKey{dbDesc.ID, string(n.Name.Table())}.Key() // Check if table exists. gr, err := p.txn.Get(tbKey) if err != nil { return nil, err } if !gr.Exists() { if n.IfExists { // Noop. return &valuesNode{}, nil } // Key does not exist, but we want it to: error out. return nil, fmt.Errorf("table %q does not exist", n.Name.Table()) } if err := p.checkPrivilege(dbDesc, privilege.WRITE); err != nil { return nil, err } tableDesc, err := p.getTableDesc(n.Name) if err != nil { return nil, err } tableDesc.SetName(string(n.NewName)) newTbKey := tableKey{dbDesc.ID, string(n.NewName)}.Key() descKey := MakeDescMetadataKey(tableDesc.GetID()) b := client.Batch{} b.Put(descKey, tableDesc) b.CPut(newTbKey, descKey, nil) b.Del(tbKey) if err := p.txn.Run(&b); err != nil { if _, ok := err.(*proto.ConditionFailedError); ok { return nil, fmt.Errorf("table name %q already exists", n.NewName) } return nil, err } return &valuesNode{}, nil }
// RenameTable renames the table. // Privileges: DROP on source table, CREATE on destination database. // Notes: postgres requires the table owner. // mysql requires ALTER, DROP on the original table, and CREATE, INSERT // on the new table (and does not copy privileges over). func (p *planner) RenameTable(n *parser.RenameTable) (planNode, *roachpb.Error) { if err := n.NewName.NormalizeTableName(p.session.Database); err != nil { return nil, roachpb.NewError(err) } if n.NewName.Table() == "" { return nil, roachpb.NewError(errEmptyTableName) } if err := n.Name.NormalizeTableName(p.session.Database); err != nil { return nil, roachpb.NewError(err) } dbDesc, pErr := p.getDatabaseDesc(n.Name.Database()) if pErr != nil { return nil, pErr } tbKey := tableKey{dbDesc.ID, n.Name.Table()}.Key() // Check if table exists. gr, pErr := p.txn.Get(tbKey) if pErr != nil { return nil, pErr } if !gr.Exists() { if n.IfExists { // Noop. return &valuesNode{}, nil } // Key does not exist, but we want it to: error out. return nil, roachpb.NewUErrorf("table %q does not exist", n.Name.Table()) } targetDbDesc, pErr := p.getDatabaseDesc(n.NewName.Database()) if pErr != nil { return nil, pErr } if pErr := p.checkPrivilege(targetDbDesc, privilege.CREATE); pErr != nil { return nil, pErr } if n.Name.Database() == n.NewName.Database() && n.Name.Table() == n.NewName.Table() { // Noop. return &valuesNode{}, nil } tableDesc, pErr := p.getTableDesc(n.Name) if pErr != nil { return nil, pErr } if pErr := p.checkPrivilege(tableDesc, privilege.DROP); pErr != nil { return nil, pErr } tableDesc.SetName(n.NewName.Table()) tableDesc.ParentID = targetDbDesc.ID descKey := MakeDescMetadataKey(tableDesc.GetID()) newTbKey := tableKey{targetDbDesc.ID, n.NewName.Table()}.Key() if err := tableDesc.Validate(); err != nil { return nil, roachpb.NewError(err) } descID := tableDesc.GetID() descDesc := wrapDescriptor(tableDesc) b := client.Batch{} b.Put(descKey, descDesc) b.CPut(newTbKey, descID, nil) b.Del(tbKey) if pErr := p.txn.Run(&b); pErr != nil { if _, ok := pErr.GoError().(*roachpb.ConditionFailedError); ok { return nil, roachpb.NewUErrorf("table name %q already exists", n.NewName.Table()) } return nil, pErr } p.testingVerifyMetadata = func(systemConfig config.SystemConfig) error { if err := expectDescriptorID(systemConfig, newTbKey, descID); err != nil { return err } if err := expectDescriptor(systemConfig, descKey, descDesc); err != nil { return err } return expectDeleted(systemConfig, tbKey) } return &valuesNode{}, nil }
// Insert inserts rows into the database. // Privileges: INSERT on table // Notes: postgres requires INSERT. No "on duplicate key update" option. // mysql requires INSERT. Also requires UPDATE on "ON DUPLICATE KEY UPDATE". func (p *planner) Insert(n *parser.Insert) (planNode, error) { // TODO(marcb): We can't use the cached descriptor here because a recent // update of the schema (e.g. the addition of an index) might not be // reflected in the cached version (yet). Perhaps schema modification // routines such as CREATE INDEX should not return until the schema change // has been pushed everywhere. tableDesc, err := p.getTableLease(n.Table) if err != nil { return nil, err } if err := p.checkPrivilege(tableDesc, privilege.INSERT); err != nil { return nil, err } // Determine which columns we're inserting into. cols, err := p.processColumns(tableDesc, n.Columns) 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, c := range cols { colIDtoRowIndex[c.ID] = i } // Add any column not already present that has a DEFAULT expression. for _, col := range tableDesc.Columns { if _, ok := colIDtoRowIndex[col.ID]; ok { continue } if col.DefaultExpr != nil { colIDtoRowIndex[col.ID] = len(cols) cols = append(cols, col) } } // Verify we have at least the columns that are part of the primary key. primaryKeyCols := map[ColumnID]struct{}{} for i, id := range tableDesc.PrimaryIndex.ColumnIDs { if _, ok := colIDtoRowIndex[id]; !ok { return nil, fmt.Errorf("missing %q primary key column", tableDesc.PrimaryIndex.ColumnNames[i]) } primaryKeyCols[id] = struct{}{} } // Construct the default expressions. The returned slice will be nil if no // column in the table has a default expression. defaultExprs, err := p.makeDefaultExprs(cols) if err != nil { return nil, err } // Replace any DEFAULT markers with the corresponding default expressions. if n.Rows, err = p.fillDefaults(defaultExprs, cols, n.Rows); err != nil { return nil, err } // Transform the values into a rows object. This expands SELECT statements or // generates rows from the values contained within the query. rows, err := p.makePlan(n.Rows) if err != nil { return nil, err } if expressions, columns := len(rows.Columns()), len(cols); expressions > columns { return nil, fmt.Errorf("INSERT has more expressions than target columns: %d/%d", expressions, columns) } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) marshalled := make([]interface{}, len(cols)) b := client.Batch{} result := &valuesNode{} for rows.Next() { rowVals := rows.Values() result.rows = append(result.rows, parser.DTuple(nil)) // The values for the row may be shorter than the number of columns being // inserted into. Generate default values for those columns using the // default expressions. for i := len(rowVals); i < len(cols); i++ { if defaultExprs == nil { rowVals = append(rowVals, parser.DNull) continue } d, err := defaultExprs[i].Eval(p.evalCtx) if err != nil { return nil, err } rowVals = append(rowVals, d) } // Check to see if NULL is being inserted into any non-nullable column. for _, col := range tableDesc.Columns { if !col.Nullable { if i, ok := colIDtoRowIndex[col.ID]; !ok || rowVals[i] == parser.DNull { return nil, fmt.Errorf("null value in column %q violates not-null constraint", col.Name) } } } // Check that the row value types match the column types. This needs to // happen before index encoding because certain datum types (i.e. tuple) // cannot be used as index values. for i, val := range rowVals { // Make sure the value can be written to the column before proceeding. var err error if marshalled[i], err = marshalColumnValue(cols[i], val); err != nil { return nil, err } } primaryIndexKey, _, err := encodeIndexKey( primaryIndex.ColumnIDs, colIDtoRowIndex, rowVals, primaryIndexKeyPrefix) if err != nil { return nil, err } // Write 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("CPut %s -> %v", prettyKey(secondaryIndexEntry.key, 0), secondaryIndexEntry.value) } b.CPut(secondaryIndexEntry.key, secondaryIndexEntry.value, nil) } // Write the row sentinel. if log.V(2) { log.Infof("CPut %s -> NULL", prettyKey(primaryIndexKey, 0)) } b.CPut(primaryIndexKey, nil, nil) // Write the row columns. for i, val := range rowVals { col := cols[i] if _, ok := primaryKeyCols[col.ID]; ok { // Skip primary key columns as their values are encoded in the row // sentinel key which is guaranteed to exist for as long as the row // exists. continue } if marshalled[i] != nil { // We only output non-NULL values. Non-existent column keys are // considered NULL during scanning and the row sentinel ensures we know // the row exists. key := MakeColumnKey(col.ID, primaryIndexKey) if log.V(2) { log.Infof("CPut %s -> %v", prettyKey(key, 0), val) } b.CPut(key, marshalled[i], nil) } } } 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, convertBatchError(tableDesc, b, err) } return result, nil }
// Update updates columns for a selection of rows from a table. // Privileges: UPDATE and SELECT on table. We currently always use a select statement. // Notes: postgres requires UPDATE. Requires SELECT with WHERE clause with table. // mysql requires UPDATE. Also requires SELECT with WHERE clause with table. func (p *planner) Update(n *parser.Update) (planNode, *roachpb.Error) { tableDesc, pErr := p.getAliasedTableLease(n.Table) if pErr != nil { return nil, pErr } if err := p.checkPrivilege(tableDesc, privilege.UPDATE); err != nil { return nil, roachpb.NewError(err) } // Determine which columns we're inserting into. var names parser.QualifiedNames for _, expr := range n.Exprs { var epErr *roachpb.Error expr.Expr, epErr = p.expandSubqueries(expr.Expr, len(expr.Names)) if epErr != nil { return nil, epErr } if expr.Tuple { // TODO(pmattis): The distinction between Tuple and DTuple here is // irritating. We'll see a DTuple if the expression was a subquery that // has been evaluated. We'll see a Tuple in other cases. n := 0 switch t := expr.Expr.(type) { case parser.Tuple: n = len(t) case parser.DTuple: n = len(t) default: return nil, roachpb.NewErrorf("unsupported tuple assignment: %T", expr.Expr) } if len(expr.Names) != n { return nil, roachpb.NewUErrorf("number of columns (%d) does not match number of values (%d)", len(expr.Names), n) } } names = append(names, expr.Names...) } cols, err := p.processColumns(tableDesc, names) if err != nil { return nil, roachpb.NewError(err) } // Set of columns being updated colIDSet := map[ColumnID]struct{}{} for _, c := range cols { colIDSet[c.ID] = struct{}{} } // Don't allow updating any column that is part of the primary key. for i, id := range tableDesc.PrimaryIndex.ColumnIDs { if _, ok := colIDSet[id]; ok { return nil, roachpb.NewUErrorf("primary key column %q cannot be updated", tableDesc.PrimaryIndex.ColumnNames[i]) } } defaultExprs, err := p.makeDefaultExprs(cols) if err != nil { return nil, roachpb.NewError(err) } // Generate the list of select targets. We need to select all of the columns // plus we select all of the update expressions in case those expressions // reference columns (e.g. "UPDATE t SET v = v + 1"). Note that we flatten // expressions for tuple assignments just as we flattened the column names // above. So "UPDATE t SET (a, b) = (1, 2)" translates into select targets of // "*, 1, 2", not "*, (1, 2)". targets := tableDesc.allColumnsSelector() i := 0 for _, expr := range n.Exprs { if expr.Tuple { switch t := expr.Expr.(type) { case parser.Tuple: for _, e := range t { e = fillDefault(e, i, defaultExprs) targets = append(targets, parser.SelectExpr{Expr: e}) i++ } case parser.DTuple: for _, e := range t { targets = append(targets, parser.SelectExpr{Expr: e}) i++ } } } else { e := fillDefault(expr.Expr, i, defaultExprs) targets = append(targets, parser.SelectExpr{Expr: e}) i++ } } // Query the rows that need updating. rows, pErr := p.Select(&parser.Select{ Exprs: targets, From: parser.TableExprs{n.Table}, Where: n.Where, }) if pErr != nil { return nil, pErr } // ValArgs have their types populated in the above Select if they are part // of an expression ("SET a = 2 + $1") in the type check step where those // types are inferred. For the simpler case ("SET a = $1"), populate them // using marshalColumnValue. This step also verifies that the expression // types match the column types. if p.prepareOnly { i := 0 f := func(expr parser.Expr) *roachpb.Error { idx := i i++ // DefaultVal doesn't implement TypeCheck if _, ok := expr.(parser.DefaultVal); ok { return nil } d, err := expr.TypeCheck(p.evalCtx.Args) if err != nil { return roachpb.NewError(err) } if _, err := marshalColumnValue(cols[idx], d, p.evalCtx.Args); err != nil { return roachpb.NewError(err) } return nil } for _, expr := range n.Exprs { if expr.Tuple { switch t := expr.Expr.(type) { case parser.Tuple: for _, e := range t { if err := f(e); err != nil { return nil, err } } case parser.DTuple: for _, e := range t { if err := f(e); err != nil { return nil, err } } } } else { if err := f(expr.Expr); err != nil { return nil, err } } } return nil, nil } // Construct a map from column ID to the index the value appears at within a // row. colIDtoRowIndex := map[ColumnID]int{} for i, col := range tableDesc.Columns { colIDtoRowIndex[col.ID] = i } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) // Secondary indexes needing updating. needsUpdate := func(index IndexDescriptor) bool { for _, id := range index.ColumnIDs { if _, ok := colIDSet[id]; ok { return true } } return false } indexes := make([]IndexDescriptor, 0, len(tableDesc.Indexes)+len(tableDesc.Mutations)) var deleteOnlyIndex map[int]struct{} for _, index := range tableDesc.Indexes { if needsUpdate(index) { indexes = append(indexes, index) } } for _, m := range tableDesc.Mutations { if index := m.GetIndex(); index != nil { if needsUpdate(*index) { indexes = append(indexes, *index) switch m.State { case DescriptorMutation_DELETE_ONLY: if deleteOnlyIndex == nil { // Allocate at most once. deleteOnlyIndex = make(map[int]struct{}, len(tableDesc.Mutations)) } deleteOnlyIndex[len(indexes)-1] = struct{}{} case DescriptorMutation_WRITE_ONLY: } } } } marshalled := make([]interface{}, len(cols)) 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) } // Compute the current secondary index key:value pairs for this row. secondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, indexes, colIDtoRowIndex, rowVals) if err != nil { return nil, roachpb.NewError(err) } // Our updated value expressions occur immediately after the plain // columns in the output. newVals := rowVals[len(tableDesc.Columns):] // Update the row values. for i, col := range cols { val := newVals[i] if !col.Nullable && val == parser.DNull { return nil, roachpb.NewUErrorf("null value in column %q violates not-null constraint", col.Name) } rowVals[colIDtoRowIndex[col.ID]] = val } // Check that the new value types match the column types. This needs to // happen before index encoding because certain datum types (i.e. tuple) // cannot be used as index values. for i, val := range newVals { var mErr error if marshalled[i], mErr = marshalColumnValue(cols[i], val, p.evalCtx.Args); mErr != nil { return nil, roachpb.NewError(mErr) } } // Compute the new secondary index key:value pairs for this row. newSecondaryIndexEntries, eErr := encodeSecondaryIndexes( tableDesc.ID, indexes, colIDtoRowIndex, rowVals) if eErr != nil { return nil, roachpb.NewError(eErr) } // Update secondary indexes. for i, newSecondaryIndexEntry := range newSecondaryIndexEntries { secondaryIndexEntry := secondaryIndexEntries[i] if !bytes.Equal(newSecondaryIndexEntry.key, secondaryIndexEntry.key) { // Do not update Indexes in the DELETE_ONLY state. if _, ok := deleteOnlyIndex[i]; !ok { if log.V(2) { log.Infof("CPut %s -> %v", newSecondaryIndexEntry.key, newSecondaryIndexEntry.value) } b.CPut(newSecondaryIndexEntry.key, newSecondaryIndexEntry.value, nil) } if log.V(2) { log.Infof("Del %s", secondaryIndexEntry.key) } b.Del(secondaryIndexEntry.key) } } // Add the new values. for i, val := range newVals { col := cols[i] key := keys.MakeColumnKey(primaryIndexKey, uint32(col.ID)) if marshalled[i] != nil { // We only output non-NULL values. Non-existent column keys are // considered NULL during scanning and the row sentinel ensures we know // the row exists. if log.V(2) { log.Infof("Put %s -> %v", key, val) } b.Put(key, marshalled[i]) } else { // The column might have already existed but is being set to NULL, so // delete it. if log.V(2) { log.Infof("Del %s", key) } b.Del(key) } } } if pErr := rows.PErr(); pErr != nil { return nil, pErr } if pErr := p.txn.Run(&b); pErr != nil { return nil, convertBatchError(tableDesc, b, pErr) } return result, nil }
// CreateIndex creates an index. // Privileges: CREATE on table. // notes: postgres requires CREATE on the table. // mysql requires ALTER, CREATE, INSERT on the table. func (p *planner) CreateIndex(n *parser.CreateIndex) (planNode, error) { tableDesc, err := p.getTableDesc(n.Table) if err != nil { return nil, err } if _, err := tableDesc.FindIndexByName(string(n.Name)); err == nil { if n.IfNotExists { // Noop. return &valuesNode{}, nil } return nil, fmt.Errorf("index %q already exists", string(n.Name)) } if err := p.checkPrivilege(tableDesc, privilege.CREATE); err != nil { return nil, err } index := IndexDescriptor{ Name: string(n.Name), Unique: n.Unique, ColumnNames: n.Columns, } tableDesc.Indexes = append(tableDesc.Indexes, index) if err := tableDesc.AllocateIDs(); err != nil { return nil, err } // `index` changed on us when we called `tableDesc.AllocateIDs()`. index = tableDesc.Indexes[len(tableDesc.Indexes)-1] // Get all the rows affected. // TODO(vivek): Avoid going through Select. // TODO(tamird): Support partial indexes? row, err := p.Select(&parser.Select{ Exprs: parser.SelectExprs{parser.StarSelectExpr()}, From: parser.TableExprs{&parser.AliasedTableExpr{Expr: n.Table}}, }) 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 row.Columns() { c, err := tableDesc.FindColumnByName(name) if err != nil { return nil, err } colIDtoRowIndex[c.ID] = i } // 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. var b client.Batch b.Put(MakeDescMetadataKey(tableDesc.GetID()), tableDesc) for row.Next() { rowVals := row.Values() secondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, []IndexDescriptor{index}, colIDtoRowIndex, rowVals) if err != nil { return nil, err } for _, secondaryIndexEntry := range secondaryIndexEntries { if log.V(2) { log.Infof("CPut %q -> %v", secondaryIndexEntry.key, secondaryIndexEntry.value) } b.CPut(secondaryIndexEntry.key, secondaryIndexEntry.value, nil) } } if err := row.Err(); err != nil { return nil, err } if err := p.txn.Run(&b); err != nil { if tErr, ok := err.(*proto.ConditionFailedError); ok { return nil, fmt.Errorf("duplicate key value %q violates unique constraint %s", tErr.ActualValue.Bytes, "TODO(tamird)") } return nil, err } return &valuesNode{}, nil }
// RenameTable renames the table. // Privileges: DROP on source table, CREATE on destination database. // Notes: postgres requires the table owner. // mysql requires ALTER, DROP on the original table, and CREATE, INSERT // on the new table (and does not copy privileges over). func (p *planner) RenameTable(n *parser.RenameTable) (planNode, error) { if err := n.NewName.NormalizeTableName(p.session.Database); err != nil { return nil, err } if n.NewName.Table() == "" { return nil, errEmptyTableName } if err := n.Name.NormalizeTableName(p.session.Database); err != nil { return nil, err } dbDesc, err := p.getDatabaseDesc(n.Name.Database()) if err != nil { return nil, err } if dbDesc == nil { return nil, sqlbase.NewUndefinedDatabaseError(n.Name.Database()) } tbKey := tableKey{dbDesc.ID, n.Name.Table()}.Key() // Check if table exists. gr, err := p.txn.Get(tbKey) if err != nil { return nil, err } if !gr.Exists() { if n.IfExists { // Noop. return &emptyNode{}, nil } // Key does not exist, but we want it to: error out. return nil, fmt.Errorf("table %q does not exist", n.Name.Table()) } targetDbDesc, err := p.getDatabaseDesc(n.NewName.Database()) if err != nil { return nil, err } if targetDbDesc == nil { return nil, sqlbase.NewUndefinedDatabaseError(n.NewName.Database()) } if err := p.checkPrivilege(targetDbDesc, privilege.CREATE); err != nil { return nil, err } if n.Name.Database() == n.NewName.Database() && n.Name.Table() == n.NewName.Table() { // Noop. return &emptyNode{}, nil } tableDesc, err := p.getTableDesc(n.Name) if err != nil { return nil, err } if tableDesc == nil || tableDesc.State != sqlbase.TableDescriptor_PUBLIC { return nil, sqlbase.NewUndefinedTableError(n.Name.String()) } if err := p.checkPrivilege(tableDesc, privilege.DROP); err != nil { return nil, err } tableDesc.SetName(n.NewName.Table()) tableDesc.ParentID = targetDbDesc.ID descKey := sqlbase.MakeDescMetadataKey(tableDesc.GetID()) newTbKey := tableKey{targetDbDesc.ID, n.NewName.Table()}.Key() if err := tableDesc.Validate(); err != nil { return nil, err } descID := tableDesc.GetID() descDesc := sqlbase.WrapDescriptor(tableDesc) if err := tableDesc.SetUpVersion(); err != nil { return nil, err } renameDetails := sqlbase.TableDescriptor_RenameInfo{ OldParentID: uint32(dbDesc.ID), OldName: n.Name.Table()} tableDesc.Renames = append(tableDesc.Renames, renameDetails) if err := p.writeTableDesc(tableDesc); err != nil { return nil, err } // We update the descriptor to the new name, but also leave the mapping of the // old name to the id, so that the name is not reused until the schema changer // has made sure it's not in use any more. b := client.Batch{} b.Put(descKey, descDesc) b.CPut(newTbKey, descID, nil) if err := p.txn.Run(&b); err != nil { if _, ok := err.(*roachpb.ConditionFailedError); ok { return nil, fmt.Errorf("table name %q already exists", n.NewName.Table()) } return nil, err } p.notifySchemaChange(tableDesc.ID, sqlbase.InvalidMutationID) p.setTestingVerifyMetadata(func(systemConfig config.SystemConfig) error { if err := expectDescriptorID(systemConfig, newTbKey, descID); err != nil { return err } if err := expectDescriptor(systemConfig, descKey, descDesc); err != nil { return err } return nil }) return &emptyNode{}, nil }
// Insert inserts rows into the database. // Privileges: INSERT on table // Notes: postgres requires INSERT. No "on duplicate key update" option. // mysql requires INSERT. Also requires UPDATE on "ON DUPLICATE KEY UPDATE". func (p *planner) Insert(n *parser.Insert) (planNode, error) { tableDesc, err := p.getTableDesc(n.Table) if err != nil { return nil, err } if err := p.checkPrivilege(tableDesc, privilege.INSERT); err != nil { return nil, err } // Determine which columns we're inserting into. cols, err := p.processColumns(tableDesc, n.Columns) 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, c := range cols { colIDtoRowIndex[c.ID] = i } // Add any column not already present that has a DEFAULT expression. for _, col := range tableDesc.Columns { if _, ok := colIDtoRowIndex[col.ID]; ok { continue } if col.DefaultExpr != nil { colIDtoRowIndex[col.ID] = len(cols) cols = append(cols, col) } } // Verify we have at least the columns that are part of the primary key. primaryKeyCols := map[ColumnID]struct{}{} for i, id := range tableDesc.PrimaryIndex.ColumnIDs { if _, ok := colIDtoRowIndex[id]; !ok { return nil, fmt.Errorf("missing %q primary key column", tableDesc.PrimaryIndex.ColumnNames[i]) } primaryKeyCols[id] = struct{}{} } // Construct the default expressions. The returned slice will be nil if no // column in the table has a default expression. defaultExprs, err := p.makeDefaultExprs(cols) if err != nil { return nil, err } // Replace any DEFAULT markers with the corresponding default expressions. if n.Rows, err = p.fillDefaults(defaultExprs, cols, n.Rows); err != nil { return nil, err } // Transform the values into a rows object. This expands SELECT statements or // generates rows from the values contained within the query. rows, err := p.makePlan(n.Rows) if err != nil { return nil, err } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) var b client.Batch for rows.Next() { rowVals := rows.Values() // The values for the row may be shorter than the number of columns being // inserted into. Generate default values for those columns using the // default expressions. for i := len(rowVals); i < len(cols); i++ { if defaultExprs == nil { rowVals = append(rowVals, parser.DNull) continue } d, err := p.evalCtx.EvalExpr(defaultExprs[i]) if err != nil { return nil, err } rowVals = append(rowVals, d) } // Check to see if NULL is being inserted into any non-nullable column. for _, col := range tableDesc.Columns { if !col.Nullable { if i, ok := colIDtoRowIndex[col.ID]; !ok || rowVals[i] == parser.DNull { return nil, fmt.Errorf("null value in column %q violates not-null constraint", col.Name) } } } primaryIndexKey, _, err := encodeIndexKey( primaryIndex.ColumnIDs, colIDtoRowIndex, rowVals, primaryIndexKeyPrefix) if err != nil { return nil, err } // Write 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("CPut %q -> %v", secondaryIndexEntry.key, secondaryIndexEntry.value) } b.CPut(secondaryIndexEntry.key, secondaryIndexEntry.value, nil) } // Write the row sentinel. if log.V(2) { log.Infof("CPut %q -> NULL", primaryIndexKey) } b.CPut(primaryIndexKey, nil, nil) // Write the row columns. for i, val := range rowVals { col := cols[i] // Make sure the value can be written to the column before proceeding. marshalled, err := marshalColumnValue(col, val) if err != nil { return nil, err } if _, ok := primaryKeyCols[col.ID]; ok { // Skip primary key columns as their values are encoded in the row // sentinel key which is guaranteed to exist for as long as the row // exists. continue } if marshalled != nil { // We only output non-NULL values. Non-existent column keys are // considered NULL during scanning and the row sentinel ensures we know // the row exists. key := MakeColumnKey(col.ID, primaryIndexKey) if log.V(2) { log.Infof("CPut %q -> %v", key, val) } b.CPut(key, marshalled, nil) } } } 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 pErr := p.txn.Run(&b); pErr != nil { return nil, convertBatchError(tableDesc, b, pErr) } // TODO(tamird/pmattis): return the number of affected rows return &valuesNode{}, 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 }
// insertCPutFn is used by insertRow when conflicts should be respected. // logValue is used for pretty printing. func insertCPutFn(b *client.Batch, key *roachpb.Key, value interface{}, logValue interface{}) { if log.V(2) { log.InfofDepth(1, "CPut %s -> %v", *key, logValue) } b.CPut(key, value, nil) }
// Update updates columns for a selection of rows from a table. // Privileges: WRITE and READ on table. We currently always use a select statement. // Notes: postgres requires UPDATE. Requires SELECT with WHERE clause with table. // mysql requires UPDATE. Also requires SELECT with WHERE clause with table. func (p *planner) Update(n *parser.Update) (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) } // Determine which columns we're inserting into. var names parser.QualifiedNames for _, expr := range n.Exprs { names = append(names, expr.Name) } cols, err := p.processColumns(tableDesc, names) if err != nil { return nil, err } // Set of columns being updated colIDSet := map[structured.ColumnID]struct{}{} for _, c := range cols { colIDSet[c.ID] = struct{}{} } // Don't allow updating any column that is part of the primary key. for i, id := range tableDesc.PrimaryIndex.ColumnIDs { if _, ok := colIDSet[id]; ok { return nil, fmt.Errorf("primary key column %q cannot be updated", tableDesc.PrimaryIndex.ColumnNames[i]) } } // Query the rows that need updating. // TODO(vivek): Avoid going through Select. row, 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[structured.ColumnID]int{} for i, name := range row.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) // Evaluate all the column value expressions. vals := make([]parser.Datum, 0, 10) for _, expr := range n.Exprs { val, err := parser.EvalExpr(expr.Expr) if err != nil { return nil, err } vals = append(vals, val) } // Secondary indexes needing updating. var indexes []structured.IndexDescriptor for _, index := range tableDesc.Indexes { for _, id := range index.ColumnIDs { if _, ok := colIDSet[id]; ok { indexes = append(indexes, index) break } } } // Update all the rows. b := client.Batch{} for row.Next() { rowVals := row.Values() primaryIndexKeySuffix, _, err := encodeIndexKey(primaryIndex.ColumnIDs, colIDtoRowIndex, rowVals, nil) if err != nil { return nil, err } primaryIndexKey := bytes.Join([][]byte{primaryIndexKeyPrefix, primaryIndexKeySuffix}, nil) // Compute the current secondary index key:value pairs for this row. secondaryIndexEntries, err := encodeSecondaryIndexes(tableDesc.ID, indexes, colIDtoRowIndex, rowVals, primaryIndexKeySuffix) if err != nil { return nil, err } // Compute the new secondary index key:value pairs for this row. // // Update the row values. for i, col := range cols { val := vals[i] if !col.Nullable && val == parser.DNull { return nil, fmt.Errorf("null value in column %q violates not-null constraint", col.Name) } rowVals[colIDtoRowIndex[col.ID]] = val } newSecondaryIndexEntries, err := encodeSecondaryIndexes(tableDesc.ID, indexes, colIDtoRowIndex, rowVals, primaryIndexKeySuffix) if err != nil { return nil, err } // Update secondary indexes. for i, newSecondaryIndexEntry := range newSecondaryIndexEntries { secondaryIndexEntry := secondaryIndexEntries[i] if !bytes.Equal(newSecondaryIndexEntry.key, secondaryIndexEntry.key) { if log.V(2) { log.Infof("CPut %q -> %v", newSecondaryIndexEntry.key, newSecondaryIndexEntry.value) } b.CPut(newSecondaryIndexEntry.key, newSecondaryIndexEntry.value, nil) if log.V(2) { log.Infof("Del %q", secondaryIndexEntry.key) } b.Del(secondaryIndexEntry.key) } } // Add the new values. for i, val := range vals { col := cols[i] primitive, err := convertDatum(col, val) if err != nil { return nil, err } key := structured.MakeColumnKey(col.ID, primaryIndexKey) if primitive != nil { // We only output non-NULL values. Non-existent column keys are // considered NULL during scanning and the row sentinel ensures we know // the row exists. if log.V(2) { log.Infof("Put %q -> %v", key, val) } b.Put(key, primitive) } else { // The column might have already existed but is being set to NULL, so // delete it. if log.V(2) { log.Infof("Del %q", key) } b.Del(key) } } } if err := row.Err(); err != nil { return nil, err } if err := p.txn.Run(&b); err != nil { if tErr, ok := err.(*proto.ConditionFailedError); ok { return nil, fmt.Errorf("duplicate key value %q violates unique constraint %s", tErr.ActualValue.Bytes, "TODO(tamird)") } return nil, err } // TODO(tamird/pmattis): return the number of affected rows. return &valuesNode{}, nil }
// Update updates columns for a selection of rows from a table. // Privileges: UPDATE and SELECT on table. We currently always use a select statement. // Notes: postgres requires UPDATE. Requires SELECT with WHERE clause with table. // mysql requires UPDATE. Also requires SELECT with WHERE clause with table. func (p *planner) Update(n *parser.Update) (planNode, error) { tableDesc, err := p.getAliasedTableDesc(n.Table) if err != nil { return nil, err } if err := p.checkPrivilege(tableDesc, privilege.UPDATE); err != nil { return nil, err } // Determine which columns we're inserting into. var names parser.QualifiedNames for _, expr := range n.Exprs { var err error expr.Expr, err = p.expandSubqueries(expr.Expr, len(expr.Names)) if err != nil { return nil, err } if expr.Tuple { // TODO(pmattis): The distinction between Tuple and DTuple here is // irritating. We'll see a DTuple if the expression was a subquery that // has been evaluated. We'll see a Tuple in other cases. n := 0 switch t := expr.Expr.(type) { case parser.Tuple: n = len(t) case parser.DTuple: n = len(t) default: return nil, util.Errorf("unsupported tuple assignment: %T", expr.Expr) } if len(expr.Names) != n { return nil, fmt.Errorf("number of columns (%d) does not match number of values (%d)", len(expr.Names), n) } } names = append(names, expr.Names...) } cols, err := p.processColumns(tableDesc, names) if err != nil { return nil, err } // Set of columns being updated colIDSet := map[ColumnID]struct{}{} for _, c := range cols { colIDSet[c.ID] = struct{}{} } // Don't allow updating any column that is part of the primary key. for i, id := range tableDesc.PrimaryIndex.ColumnIDs { if _, ok := colIDSet[id]; ok { return nil, fmt.Errorf("primary key column %q cannot be updated", tableDesc.PrimaryIndex.ColumnNames[i]) } } defaultExprs, err := p.makeDefaultExprs(cols) if err != nil { return nil, err } // Generate the list of select targets. We need to select all of the columns // plus we select all of the update expressions in case those expressions // reference columns (e.g. "UPDATE t SET v = v + 1"). Note that we flatten // expressions for tuple assignments just as we flattened the column names // above. So "UPDATE t SET (a, b) = (1, 2)" translates into select targets of // "*, 1, 2", not "*, (1, 2)". targets := make(parser.SelectExprs, 0, len(n.Exprs)+1) targets = append(targets, parser.StarSelectExpr()) for _, expr := range n.Exprs { if expr.Tuple { switch t := expr.Expr.(type) { case parser.Tuple: for i, e := range t { e, err := fillDefault(e, i, defaultExprs) if err != nil { return nil, err } targets = append(targets, parser.SelectExpr{Expr: e}) } case parser.DTuple: for _, e := range t { targets = append(targets, parser.SelectExpr{Expr: e}) } } } else { e, err := fillDefault(expr.Expr, 0, defaultExprs) if err != nil { return nil, err } targets = append(targets, parser.SelectExpr{Expr: e}) } } // Query the rows that need updating. rows, err := p.Select(&parser.Select{ Exprs: targets, 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, col := range tableDesc.Columns { colIDtoRowIndex[col.ID] = i } primaryIndex := tableDesc.PrimaryIndex primaryIndexKeyPrefix := MakeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) // Secondary indexes needing updating. var indexes []IndexDescriptor for _, index := range tableDesc.Indexes { for _, id := range index.ColumnIDs { if _, ok := colIDSet[id]; ok { indexes = append(indexes, index) break } } } marshalled := make([]interface{}, len(cols)) // Update all the rows. var b client.Batch for rows.Next() { rowVals := rows.Values() primaryIndexKey, _, err := encodeIndexKey( primaryIndex.ColumnIDs, colIDtoRowIndex, rowVals, primaryIndexKeyPrefix) if err != nil { return nil, err } // Compute the current secondary index key:value pairs for this row. secondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, indexes, colIDtoRowIndex, rowVals) if err != nil { return nil, err } // Our updated value expressions occur immediately after the plain // columns in the output. newVals := rowVals[len(tableDesc.Columns):] // Update the row values. for i, col := range cols { val := newVals[i] if !col.Nullable && val == parser.DNull { return nil, fmt.Errorf("null value in column %q violates not-null constraint", col.Name) } rowVals[colIDtoRowIndex[col.ID]] = val } // Check that the new value types match the column types. This needs to // happen before index encoding because certain datum types (i.e. tuple) // cannot be used as index values. for i, val := range newVals { var err error if marshalled[i], err = marshalColumnValue(cols[i], val); err != nil { return nil, err } } // Compute the new secondary index key:value pairs for this row. newSecondaryIndexEntries, err := encodeSecondaryIndexes( tableDesc.ID, indexes, colIDtoRowIndex, rowVals) if err != nil { return nil, err } // Update secondary indexes. for i, newSecondaryIndexEntry := range newSecondaryIndexEntries { secondaryIndexEntry := secondaryIndexEntries[i] if !bytes.Equal(newSecondaryIndexEntry.key, secondaryIndexEntry.key) { if log.V(2) { log.Infof("CPut %q -> %v", newSecondaryIndexEntry.key, newSecondaryIndexEntry.value) } b.CPut(newSecondaryIndexEntry.key, newSecondaryIndexEntry.value, nil) if log.V(2) { log.Infof("Del %q", secondaryIndexEntry.key) } b.Del(secondaryIndexEntry.key) } } // Add the new values. for i, val := range newVals { col := cols[i] key := MakeColumnKey(col.ID, primaryIndexKey) if marshalled[i] != nil { // We only output non-NULL values. Non-existent column keys are // considered NULL during scanning and the row sentinel ensures we know // the row exists. if log.V(2) { log.Infof("Put %q -> %v", key, val) } b.Put(key, marshalled[i]) } else { // The column might have already existed but is being set to NULL, so // delete it. if log.V(2) { log.Infof("Del %q", key) } b.Del(key) } } } if err := rows.Err(); err != nil { return nil, err } if err := p.txn.Run(&b); err != nil { return nil, convertBatchError(tableDesc, b, err) } // TODO(tamird/pmattis): return the number of affected rows. return &valuesNode{}, nil }
// RenameTable renames the table. // Privileges: DROP on source table, CREATE on destination database. // Notes: postgres requires the table owner. // mysql requires ALTER, DROP on the original table, and CREATE, INSERT // on the new table (and does not copy privileges over). func (p *planner) RenameTable(n *parser.RenameTable) (planNode, error) { if err := n.NewName.NormalizeTableName(p.session.Database); err != nil { return nil, err } if n.NewName.Table() == "" { return nil, errEmptyTableName } if err := n.Name.NormalizeTableName(p.session.Database); err != nil { return nil, err } dbDesc, err := p.getDatabaseDesc(n.Name.Database()) if err != nil { return nil, err } tbKey := tableKey{dbDesc.ID, n.Name.Table()}.Key() // Check if table exists. gr, err := p.txn.Get(tbKey) if err != nil { return nil, err } if !gr.Exists() { if n.IfExists { // Noop. return &valuesNode{}, nil } // Key does not exist, but we want it to: error out. return nil, fmt.Errorf("table %q does not exist", n.Name.Table()) } targetDbDesc, err := p.getDatabaseDesc(n.NewName.Database()) if err != nil { return nil, err } if err := p.checkPrivilege(targetDbDesc, privilege.CREATE); err != nil { return nil, err } if n.Name.Database() == n.NewName.Database() && n.Name.Table() == n.NewName.Table() { // Noop. return &valuesNode{}, nil } tableDesc, err := p.getTableDesc(n.Name) if err != nil { return nil, err } if err := p.checkPrivilege(tableDesc, privilege.DROP); err != nil { return nil, err } tableDesc.SetName(n.NewName.Table()) tableDesc.ParentID = targetDbDesc.ID newTbKey := tableKey{targetDbDesc.ID, n.NewName.Table()}.Key() descKey := MakeDescMetadataKey(tableDesc.GetID()) if err := tableDesc.Validate(); err != nil { return nil, err } b := client.Batch{} b.Put(descKey, tableDesc) b.CPut(newTbKey, tableDesc.GetID(), nil) b.Del(tbKey) // Mark transaction as operating on the system DB. p.txn.SetSystemDBTrigger() if err := p.txn.Run(&b); err != nil { if _, ok := err.(*proto.ConditionFailedError); ok { return nil, fmt.Errorf("table name %q already exists", n.NewName.Table()) } return nil, err } return &valuesNode{}, nil }
// Insert inserts rows into the database. func (p *planner) Insert(n *parser.Insert) (planNode, error) { tableDesc, err := p.getTableDesc(n.Table) if err != nil { return nil, err } // Determine which columns we're inserting into. cols, err := p.processColumns(tableDesc, n.Columns) if err != nil { return nil, err } // Construct a map from column ID to the index the value appears at within a // row. colMap := map[uint32]int{} for i, c := range cols { colMap[c.ID] = i } // Verify we have at least the columns that are part of the primary key. for i, id := range tableDesc.Indexes[0].ColumnIDs { if _, ok := colMap[id]; !ok { return nil, fmt.Errorf("missing \"%s\" primary key column", tableDesc.Indexes[0].ColumnNames[i]) } } // Transform the values into a rows object. This expands SELECT statements or // generates rows from the values contained within the query. rows, err := p.makePlan(n.Rows) if err != nil { return nil, err } primaryIndex := tableDesc.Indexes[0] primaryIndexKeyPrefix := encodeIndexKeyPrefix(tableDesc.ID, primaryIndex.ID) b := client.Batch{} for rows.Next() { values := rows.Values() if len(values) != len(cols) { return nil, fmt.Errorf("invalid values for columns: %d != %d", len(values), len(cols)) } primaryIndexKeySuffix, err := encodeIndexKey(primaryIndex, colMap, values, nil) if err != nil { return nil, err } primaryIndexKey := bytes.Join([][]byte{primaryIndexKeyPrefix, primaryIndexKeySuffix}, nil) // Write 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("CPut %q -> %v", secondaryIndexEntry.key, secondaryIndexEntry.value) } b.CPut(secondaryIndexEntry.key, secondaryIndexEntry.value, nil) } // Write the row. for i, val := range values { key := encodeColumnKey(cols[i], primaryIndexKey) if log.V(2) { log.Infof("CPut %q -> %v", key, val) } // TODO(pmattis): Need to convert the value type to the column type. switch t := val.(type) { case parser.DBool: b.CPut(key, bool(t), nil) case parser.DInt: b.CPut(key, int64(t), nil) case parser.DFloat: b.CPut(key, float64(t), nil) case parser.DString: b.CPut(key, string(t), nil) } } } if err := rows.Err(); err != nil { return nil, err } if err := p.db.Run(&b); err != nil { if tErr, ok := err.(*proto.ConditionFailedError); ok { return nil, fmt.Errorf("duplicate key value %q violates unique constraint %s", tErr.ActualValue.Bytes, "TODO(tamird)") } return nil, err } // TODO(tamird/pmattis): return the number of affected rows return &valuesNode{}, nil }