// Future home of the asynchronous schema changer that picks up // queued schema changes and processes them. // // applyMutations applies the queued mutations for a table. func (p *planner) applyMutations(tableDesc *TableDescriptor) error { if len(tableDesc.Mutations) == 0 { return nil } newTableDesc := proto.Clone(tableDesc).(*TableDescriptor) p.applyUpVersion(newTableDesc) // Make all mutations active. for _, mutation := range newTableDesc.Mutations { newTableDesc.makeMutationComplete(mutation) } newTableDesc.Mutations = nil if err := newTableDesc.Validate(); err != nil { return err } b := client.Batch{} if err := p.backfillBatch(&b, tableDesc, newTableDesc); err != nil { return err } b.Put(MakeDescMetadataKey(newTableDesc.GetID()), wrapDescriptor(newTableDesc)) if err := p.txn.Run(&b); err != nil { return convertBatchError(newTableDesc, b, err) } p.notifyCompletedSchemaChange(newTableDesc.ID) return nil }
// 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) }
func runPut(cmd *cobra.Command, args []string) { if len(args) == 0 || len(args)%2 == 1 { cmd.Usage() return } count := len(args) / 2 keys := make([]string, 0, count) values := make([]string, 0, count) for i := 0; i < len(args); i += 2 { keys = append(keys, unquoteArg(args[i], true /* disallow system keys */)) values = append(values, unquoteArg(args[i+1], false)) } kvDB := makeDBClient() if kvDB == nil { return } var b client.Batch for i := 0; i < count; i++ { b.Put(keys[i], values[i]) } if err := kvDB.Run(&b); err != nil { fmt.Fprintf(osStderr, "put failed: %s\n", err) osExit(1) return } }
// 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 }
// 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 !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 }
// Future home of the aysynchronous schema changer that picks up // queued schema changes and processes them. // // applyMutations applies the queued mutations for a table. // TODO(vivek): Eliminate the need to pass in tableName. func (p *planner) applyMutations(tableDesc *TableDescriptor, tableName *parser.QualifiedName) error { if len(tableDesc.Mutations) == 0 { return nil } newTableDesc := proto.Clone(tableDesc).(*TableDescriptor) // Make all mutations active. for _, mutation := range newTableDesc.Mutations { newTableDesc.makeMutationComplete(mutation) } newTableDesc.Mutations = nil if err := newTableDesc.Validate(); err != nil { return err } b := client.Batch{} if err := p.backfillBatch(&b, tableName, tableDesc, newTableDesc); err != nil { return err } // TODO(pmattis): This is a hack. Remove when schema change operations work // properly. p.hackNoteSchemaChange(newTableDesc) b.Put(MakeDescMetadataKey(newTableDesc.GetID()), wrapDescriptor(newTableDesc)) if err := p.txn.Run(&b); err != nil { return convertBatchError(newTableDesc, b, err) } return nil }
// StoreData writes the supplied time series data to the cockroach server. // Stored data will be sampled at the supplied resolution. func (db *DB) StoreData(r Resolution, data []tspb.TimeSeriesData) error { var kvs []roachpb.KeyValue // Process data collection: data is converted to internal format, and a key // is generated for each internal message. for _, d := range data { idatas, err := d.ToInternal(r.KeyDuration(), r.SampleDuration()) if err != nil { return err } for _, idata := range idatas { var value roachpb.Value if err := value.SetProto(&idata); err != nil { return err } kvs = append(kvs, roachpb.KeyValue{ Key: MakeDataKey(d.Name, d.Source, r, idata.StartTimestampNanos), Value: value, }) } } // Send the individual internal merge requests. b := client.Batch{} for _, kv := range kvs { b.AddRawRequest(&roachpb.MergeRequest{ Span: roachpb.Span{ Key: kv.Key, }, Value: kv.Value, }) } return db.db.Run(&b) }
// 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 }
// 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 }
func runDel(cmd *cobra.Command, args []string) { if len(args) == 0 { cmd.Usage() return } count := len(args) keys := make([]string, 0, count) for i := 0; i < count; i++ { keys = append(keys, unquoteArg(args[i], true /* disallow system keys */)) } kvDB := makeDBClient() if kvDB == nil { return } var b client.Batch for i := 0; i < count; i++ { b.Del(keys[i]) } if err := kvDB.Run(&b); err != nil { fmt.Fprintf(osStderr, "delete failed: %s\n", err) osExit(1) return } }
func runPut(cmd *cobra.Command, args []string) { if len(args) == 0 || len(args)%2 == 1 { cmd.Usage() return } var b client.Batch for i := 0; i < len(args); i += 2 { b.Put( unquoteArg(args[i], true /* disallow system keys */), unquoteArg(args[i+1], false), ) } kvDB := makeDBClient() if kvDB == nil { return } if err := kvDB.Run(&b); err != nil { fmt.Fprintf(osStderr, "put failed: %s\n", err) osExit(1) return } }
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() }
// 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 }
// 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) }
// flush writes all dirty nodes and the tree to the transaction. func (tc *treeContext) flush(b *client.Batch) error { if tc.dirty { b.Put(keys.RangeTreeRoot, tc.tree) } for _, cachedNode := range tc.nodes { if cachedNode.dirty { b.Put(keys.RangeTreeNodeKey(cachedNode.node.Key), cachedNode.node) } } return nil }
// CreateIndex creates an index. // Privileges: CREATE on table. // notes: postgres requires CREATE on the table. // mysql requires INDEX 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 } indexDesc := IndexDescriptor{ Name: string(n.Name), Unique: n.Unique, ColumnNames: n.Columns, StoreColumnNames: n.Storing, } newTableDesc := proto.Clone(tableDesc).(*TableDescriptor) if err := newTableDesc.AddIndex(indexDesc, false); err != nil { return nil, err } if err := newTableDesc.AllocateIDs(); err != nil { return nil, err } b := client.Batch{} if err := p.backfillBatch(&b, n.Table, tableDesc, newTableDesc); err != nil { return nil, err } // TODO(pmattis): This is a hack. Remove when schema change operations work // properly. p.hackNoteSchemaChange(newTableDesc) b.Put(MakeDescMetadataKey(newTableDesc.GetID()), wrapDescriptor(newTableDesc)) if err := p.txn.Run(&b); err != nil { return nil, convertBatchError(newTableDesc, b, err) } 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) }
// 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 }
// 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) { 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 } if err := p.checkPrivilege(tableDesc, privilege.CREATE); err != nil { return nil, err } newTableDesc := proto.Clone(tableDesc).(*TableDescriptor) idxName := indexQualifiedName.Index() i, err := newTableDesc.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, err } newTableDesc.Indexes = append(newTableDesc.Indexes[:i], newTableDesc.Indexes[i+1:]...) if err := p.backfillBatch(&b, indexQualifiedName, tableDesc, newTableDesc); err != nil { return nil, err } if err := newTableDesc.Validate(); err != nil { return nil, err } descKey := MakeDescMetadataKey(newTableDesc.GetID()) b.Put(descKey, wrapDescriptor(newTableDesc)) } if err := p.txn.Run(&b); err != nil { return nil, err } return &valuesNode{}, nil }
func runDel(cmd *cobra.Command, args []string) { if len(args) == 0 { mustUsage(cmd) return } var b client.Batch for _, arg := range args { b.Del(unquoteArg(arg, true /* disallow system keys */)) } kvDB, stopper := makeDBClient() defer stopper.Stop() if err := kvDB.Run(&b); err != nil { panicf("delete failed: %s", err) } }
// 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 convertBatchError(tableDesc *sqlbase.TableDescriptor, b *client.Batch) error { origPErr := b.MustPErr() if origPErr.Index == nil { return origPErr.GoError() } index := origPErr.Index.Index if index >= int32(len(b.Results)) { panic(fmt.Sprintf("index %d outside of results: %+v", index, b.Results)) } result := b.Results[index] var alloc sqlbase.DatumAlloc if _, ok := origPErr.GetDetail().(*roachpb.ConditionFailedError); ok { for _, row := range result.Rows { indexID, key, err := sqlbase.DecodeIndexKeyPrefix(tableDesc, row.Key) if err != nil { return err } index, err := tableDesc.FindIndexByID(indexID) if err != nil { return err } valTypes, err := sqlbase.MakeKeyVals(tableDesc, index.ColumnIDs) if err != nil { return err } dirs := make([]encoding.Direction, 0, len(index.ColumnIDs)) for _, dir := range index.ColumnDirections { convertedDir, err := dir.ToEncodingDirection() if err != nil { return err } dirs = append(dirs, convertedDir) } vals := make([]parser.Datum, len(valTypes)) if _, err := sqlbase.DecodeKeyVals(&alloc, valTypes, vals, dirs, key); err != nil { return err } return sqlbase.NewUniquenessConstraintViolationError(index, vals) } } return origPErr.GoError() }
func runDel(cmd *cobra.Command, args []string) { if len(args) == 0 { cmd.Usage() return } var b client.Batch for _, arg := range args { b.Del(unquoteArg(arg, true /* disallow system keys */)) } kvDB, stopper := makeDBClient() defer stopper.Stop() if err := kvDB.Run(&b); err != nil { fmt.Fprintf(osStderr, "delete failed: %s\n", err) osExit(1) return } }
// 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) }
func runPut(cmd *cobra.Command, args []string) { if len(args) == 0 || len(args)%2 == 1 { mustUsage(cmd) return } var b client.Batch for i := 0; i < len(args); i += 2 { b.Put( unquoteArg(args[i], true /* disallow system keys */), unquoteArg(args[i+1], false), ) } kvDB, stopper := makeDBClient() defer stopper.Stop() if err := kvDB.Run(&b); err != nil { panicf("put failed: %s", err) } }
// TestAuthentication tests authentication for the KV endpoint. func TestAuthentication(t *testing.T) { defer leaktest.AfterTest(t)() s := server.StartTestServer(t) defer s.Stop() var b1 client.Batch b1.Put("a", "b") // Create a node user client and call Run() on it which lets us build our own // request, specifying the user. db1 := createTestClientForUser(t, s.Stopper(), s.ServingAddr(), security.NodeUser) if err := db1.Run(&b1); err != nil { t.Fatal(err) } var b2 client.Batch b2.Put("c", "d") // Try again, but this time with certs for a non-node user (even the root // user has no KV permissions). db2 := createTestClientForUser(t, s.Stopper(), s.ServingAddr(), security.RootUser) if err := db2.Run(&b2); !testutils.IsError(err, "is not allowed") { t.Fatal(err) } }
// flush writes all dirty nodes and the tree to the transaction. func (tc *treeContext) flush(b *client.Batch) { if tc.dirty { b.Put(keys.RangeTreeRoot, tc.tree) } for key, cachedNode := range tc.nodes { if cachedNode.dirty { if cachedNode.node == nil { b.Del(keys.RangeTreeNodeKey(roachpb.RKey(key))) } else { b.Put(keys.RangeTreeNodeKey(roachpb.RKey(key)), cachedNode.node) } } } }
// 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 }
// 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 }