// RunWithResponse is a version of Run that returns the BatchResponse. func (txn *Txn) RunWithResponse(b *Batch) (*roachpb.BatchResponse, *roachpb.Error) { tracer.AnnotateTrace() defer tracer.AnnotateTrace() if pErr := b.prepare(); pErr != nil { return nil, pErr } return sendAndFill(txn.send, b) }
func (n *scanNode) Next() bool { tracer.AnnotateTrace() if n.pErr != nil { return false } if n.kvs == nil { if !n.initScan() { return false } } // All of the columns for a particular row will be grouped together. We loop // over the key/value pairs and decode the key to extract the columns encoded // within the key and the column ID. We use the column ID to lookup the // column and decode the value. All of these values go into a map keyed by // column name. When the index key changes we output a row containing the // current values. for { if n.maybeOutputRow() { return n.pErr == nil } if n.kvIndex == len(n.kvs) { return false } if !n.processKV(n.kvs[n.kvIndex]) { return false } n.kvIndex++ } }
func (c *v3Conn) executeStatements(stmts string, params []parser.Datum, formatCodes []formatCode, sendDescription bool) error { tracer.AnnotateTrace() c.session.Database = c.opts.database // TODO(dt): this is a clumsy check better left to the actual parser. #3852 if len(strings.TrimSpace(stmts)) == 0 { // Skip executor and just send EmptyQueryResponse. c.writeBuf.initMsg(serverMsgEmptyQuery) return c.writeBuf.finishMsg(c.wr) } resp, _, err := c.executor.ExecuteStatements(c.opts.user, c.session, stmts, params) if err != nil { return c.sendError(err.Error()) } c.session.Reset() if err := c.session.Unmarshal(resp.Session); err != nil { return err } c.opts.database = c.session.Database return c.sendResponse(resp, formatCodes, sendDescription) }
// send runs the specified calls synchronously in a single batch and returns // any errors. Returns a nil response for empty input (no requests). func (db *DB) send(reqs ...roachpb.Request) (*roachpb.BatchResponse, *roachpb.Error) { if len(reqs) == 0 { return nil, nil } ba := roachpb.BatchRequest{} ba.Add(reqs...) if ba.UserPriority == 0 && db.userPriority != 1 { ba.UserPriority = db.userPriority } tracer.AnnotateTrace() br, pErr := db.sender.Send(context.TODO(), ba) if pErr != nil { if log.V(1) { log.Infof("failed batch: %s", pErr) } return nil, pErr } return br, nil }
// Send implements the batch.Sender interface. It subdivides // the Batch into batches admissible for sending (preventing certain // illegal mixtures of requests), executes each individual part // (which may span multiple ranges), and recombines the response. // When the request spans ranges, it is split up and the corresponding // ranges queried serially, in ascending order. // In particular, the first write in a transaction may not be part of the first // request sent. This is relevant since the first write is a BeginTransaction // request, thus opening up a window of time during which there may be intents // of a transaction, but no entry. Pushing such a transaction will succeed, and // may lead to the transaction being aborted early. func (ds *DistSender) Send(ctx context.Context, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) { tracer.AnnotateTrace() // In the event that timestamp isn't set and read consistency isn't // required, set the timestamp using the local clock. if ba.ReadConsistency == roachpb.INCONSISTENT && ba.Timestamp.Equal(roachpb.ZeroTimestamp) { ba.Timestamp = ds.clock.Now() } if ba.Txn != nil && len(ba.Txn.CertainNodes.Nodes) == 0 { // Ensure the local NodeID is marked as free from clock offset; // the transaction's timestamp was taken off the local clock. if nDesc := ds.getNodeDescriptor(); nDesc != nil { // TODO(tschottdorf): bad style to assume that ba.Txn is ours. // No race here, but should have a better way of doing this. // TODO(tschottdorf): future refactoring should move this to txn // creation in TxnCoordSender, which is currently unaware of the // NodeID (and wraps *DistSender through client.Sender since it // also needs test compatibility with *LocalSender). ba.Txn.CertainNodes.Add(nDesc.NodeID) } } if len(ba.Requests) < 1 { panic("empty batch") } var rplChunks []*roachpb.BatchResponse parts := ba.Split(false /* don't split ET */) for len(parts) > 0 { part := parts[0] ba.Requests = part rpl, pErr, shouldSplitET := ds.sendChunk(ctx, ba) if shouldSplitET { // If we tried to send a single round-trip EndTransaction but // it looks like it's going to hit multiple ranges, split it // here and try again. if len(parts) != 1 { panic("EndTransaction not in last chunk of batch") } parts = ba.Split(true /* split ET */) if len(parts) != 2 { panic("split of final EndTransaction chunk resulted in != 2 parts") } continue } if pErr != nil { return nil, pErr } // Propagate transaction from last reply to next request. The final // update is taken and put into the response's main header. ba.Txn.Update(rpl.Header().Txn) rplChunks = append(rplChunks, rpl) parts = parts[1:] } reply := rplChunks[0] for _, rpl := range rplChunks[1:] { reply.Responses = append(reply.Responses, rpl.Responses...) } *reply.Header() = rplChunks[len(rplChunks)-1].BatchResponse_Header return reply, nil }
// sendRPC sends one or more RPCs to replicas from the supplied roachpb.Replica // slice. First, replicas which have gossiped addresses are corralled (and // rearranged depending on proximity and whether the request needs to go to a // leader) and then sent via rpc.Send, with requirement that one RPC to a // server must succeed. Returns an RPC error if the request could not be sent. // Note that the reply may contain a higher level error and must be checked in // addition to the RPC error. func (ds *DistSender) sendRPC(trace *tracer.Trace, rangeID roachpb.RangeID, replicas replicaSlice, order rpc.OrderingPolicy, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) { if len(replicas) == 0 { return nil, roachpb.NewError(noNodeAddrsAvailError{}) } // Build a slice of replica addresses. addrs := make([]net.Addr, 0, len(replicas)) replicaMap := make(map[string]*roachpb.ReplicaDescriptor, len(replicas)) for i := range replicas { addr := replicas[i].NodeDesc.Address addrs = append(addrs, addr) replicaMap[addr.String()] = &replicas[i].ReplicaDescriptor } // TODO(pmattis): This needs to be tested. If it isn't set we'll // still route the request appropriately by key, but won't receive // RangeNotFoundErrors. ba.RangeID = rangeID // Set RPC opts with stipulation that one of N RPCs must succeed. rpcOpts := rpc.Options{ Ordering: order, SendNextTimeout: defaultSendNextTimeout, Timeout: rpc.DefaultRPCTimeout, Trace: trace, } // getArgs clones the arguments on demand for all but the first replica. firstArgs := true getArgs := func(addr net.Addr) proto.Message { var a *roachpb.BatchRequest // Use the supplied args proto if this is our first address. if firstArgs { firstArgs = false a = &ba } else { // Otherwise, copy the args value and set the replica in the header. a = proto.Clone(&ba).(*roachpb.BatchRequest) } if addr != nil { // TODO(tschottdorf): see len(replicas) above. a.Replica = *replicaMap[addr.String()] } return a } // RPCs are sent asynchronously and there is no synchronized access to // the reply object, so we don't pass itself to RPCSend. // Otherwise there maybe a race case: // If the RPC call times out using our original reply object, // we must not use it any more; the rpc call might still return // and just write to it at any time. // args.CreateReply() should be cheaper than proto.Clone which use reflect. getReply := func() proto.Message { return &roachpb.BatchResponse{} } tracer.AnnotateTrace() defer tracer.AnnotateTrace() const method = "Node.Batch" reply, err := ds.rpcSend(rpcOpts, method, addrs, getArgs, getReply, ds.rpcContext) if err != nil { return nil, roachpb.NewError(err) } return reply.(*roachpb.BatchResponse), nil }
// makePlan creates the query plan for a single SQL statement. The returned // plan needs to be iterated over using planNode.Next() and planNode.Values() // in order to retrieve matching rows. If autoCommit is true, the plan is // allowed (but not required) to commit the transaction along with other KV // operations. // // Note: The autoCommit parameter enables operations to enable the 1PC // optimization. This is a bit hackish/preliminary at present. func (p *planner) makePlan(stmt parser.Statement, autoCommit bool) (planNode, *roachpb.Error) { tracer.AnnotateTrace() // This will set the system DB trigger for transactions containing // DDL statements that have no effect, such as // `BEGIN; INSERT INTO ...; CREATE TABLE IF NOT EXISTS ...; COMMIT;` // where the table already exists. This will generate some false // refreshes, but that's expected to be quite rare in practice. if stmt.StatementType() == parser.DDL { p.txn.SetSystemConfigTrigger() } switch n := stmt.(type) { case *parser.AlterTable: return p.AlterTable(n) case *parser.BeginTransaction: return p.BeginTransaction(n) case *parser.CommitTransaction: return p.CommitTransaction(n) case *parser.CreateDatabase: return p.CreateDatabase(n) case *parser.CreateIndex: return p.CreateIndex(n) case *parser.CreateTable: return p.CreateTable(n) case *parser.Delete: return p.Delete(n) case *parser.DropDatabase: return p.DropDatabase(n) case *parser.DropIndex: return p.DropIndex(n) case *parser.DropTable: return p.DropTable(n) case *parser.Explain: return p.Explain(n) case *parser.Grant: return p.Grant(n) case *parser.Insert: return p.Insert(n, autoCommit) case *parser.ParenSelect: return p.makePlan(n.Select, autoCommit) case *parser.RenameColumn: return p.RenameColumn(n) case *parser.RenameDatabase: return p.RenameDatabase(n) case *parser.RenameIndex: return p.RenameIndex(n) case *parser.RenameTable: return p.RenameTable(n) case *parser.Revoke: return p.Revoke(n) case *parser.RollbackTransaction: return p.RollbackTransaction(n) case *parser.Select: return p.Select(n) case *parser.Set: return p.Set(n) case *parser.SetTimeZone: return p.SetTimeZone(n) case *parser.SetTransaction: return p.SetTransaction(n) case *parser.Show: return p.Show(n) case *parser.ShowColumns: return p.ShowColumns(n) case *parser.ShowDatabases: return p.ShowDatabases(n) case *parser.ShowGrants: return p.ShowGrants(n) case *parser.ShowIndex: return p.ShowIndex(n) case *parser.ShowTables: return p.ShowTables(n) case *parser.Truncate: return p.Truncate(n) case *parser.Update: return p.Update(n) case parser.Values: return p.Values(n) default: return nil, roachpb.NewErrorf("unknown statement type: %T", stmt) } }