func (conn *vtgateConn) StreamExecuteKeyspaceIds(ctx context.Context, query string, keyspace string, keyspaceIds []key.KeyspaceId, bindVars map[string]interface{}, tabletType topo.TabletType) (<-chan *mproto.QueryResult, vtgateconn.ErrFunc, error) { req := &pb.StreamExecuteKeyspaceIdsRequest{ Query: tproto.BoundQueryToProto3(query, bindVars), Keyspace: keyspace, KeyspaceIds: key.KeyspaceIdsToProto(keyspaceIds), TabletType: topo.TabletTypeToProto(tabletType), } stream, err := conn.c.StreamExecuteKeyspaceIds(ctx, req) if err != nil { return nil, nil, err } sr := make(chan *mproto.QueryResult, 10) var finalError error go func() { for { ser, err := stream.Recv() if err != nil { if err != io.EOF { finalError = err } close(sr) return } if ser.Error != nil { finalError = vterrors.FromVtRPCError(ser.Error) close(sr) return } sr <- mproto.Proto3ToQueryResult(ser.Result) } }() return sr, func() error { return finalError }, nil }
// StreamExecuteKeyspaceIds2 is the RPC version of // vtgateservice.VTGateService method func (vtg *VTGate) StreamExecuteKeyspaceIds2(ctx context.Context, request *proto.KeyspaceIdQuery, sendReply func(interface{}) error) (err error) { defer vtg.server.HandlePanic(&err) ctx = callerid.NewContext(ctx, callerid.GoRPCEffectiveCallerID(request.CallerID), callerid.NewImmediateCallerID("gorpc client")) vtgErr := vtg.server.StreamExecuteKeyspaceIds(ctx, request.Sql, request.BindVariables, request.Keyspace, key.KeyspaceIdsToProto(request.KeyspaceIds), topo.TabletTypeToProto(request.TabletType), func(value *proto.QueryResult) error { return sendReply(value) }) if vtgErr == nil { return nil } if *vtgate.RPCErrorOnlyInReply { // If there was an app error, send a QueryResult back with it. qr := new(proto.QueryResult) vtgate.AddVtGateErrorToQueryResult(vtgErr, qr) // Sending back errors this way is not backwards compatible. If a (new) server sends an additional // QueryResult with an error, and the (old) client doesn't know how to read it, it will cause // problems where the client will get out of sync with the number of QueryResults sent. // That's why this the error is only sent this way when the --rpc_errors_only_in_reply flag is set // (signalling that all clients are able to handle new-style errors). return sendReply(qr) } return vtgErr }
// BoundKeyspaceIdQueriesToProto transforms a list of BoundKeyspaceIdQuery to proto3 func BoundKeyspaceIdQueriesToProto(bsq []BoundKeyspaceIdQuery) []*pb.BoundKeyspaceIdQuery { if len(bsq) == 0 { return nil } result := make([]*pb.BoundKeyspaceIdQuery, len(bsq)) for i, q := range bsq { result[i] = &pb.BoundKeyspaceIdQuery{ Query: tproto.BoundQueryToProto3(q.Sql, q.BindVariables), Keyspace: q.Keyspace, KeyspaceIds: key.KeyspaceIdsToProto(q.KeyspaceIds), } } return result }
// StreamExecuteKeyspaceIds is the RPC version of // vtgateservice.VTGateService method func (vtg *VTGate) StreamExecuteKeyspaceIds(ctx context.Context, request *proto.KeyspaceIdQuery, sendReply func(interface{}) error) (err error) { defer vtg.server.HandlePanic(&err) ctx = callerid.NewContext(ctx, callerid.GoRPCEffectiveCallerID(request.CallerID), callerid.NewImmediateCallerID("gorpc client")) return vtg.server.StreamExecuteKeyspaceIds(ctx, request.Sql, request.BindVariables, request.Keyspace, key.KeyspaceIdsToProto(request.KeyspaceIds), topo.TabletTypeToProto(request.TabletType), func(value *proto.QueryResult) error { return sendReply(value) }) }
// BoundKeyspaceIdQueriesToProto transforms a list of BoundKeyspaceIdQuery to proto3 func BoundKeyspaceIdQueriesToProto(bsq []BoundKeyspaceIdQuery) ([]*pb.BoundKeyspaceIdQuery, error) { if len(bsq) == 0 { return nil, nil } result := make([]*pb.BoundKeyspaceIdQuery, len(bsq)) for i, q := range bsq { qq, err := tproto.BoundQueryToProto3(q.Sql, q.BindVariables) if err != nil { return nil, err } result[i] = &pb.BoundKeyspaceIdQuery{ Query: qq, Keyspace: q.Keyspace, KeyspaceIds: key.KeyspaceIdsToProto(q.KeyspaceIds), } } return result, nil }
// ExecuteKeyspaceIds is the RPC version of vtgateservice.VTGateService method func (vtg *VTGate) ExecuteKeyspaceIds(ctx context.Context, request *proto.KeyspaceIdQuery, reply *proto.QueryResult) (err error) { defer vtg.server.HandlePanic(&err) ctx, cancel := context.WithDeadline(ctx, time.Now().Add(*rpcTimeout)) defer cancel() ctx = callerid.NewContext(ctx, callerid.GoRPCEffectiveCallerID(request.CallerID), callerid.NewImmediateCallerID("gorpc client")) vtgErr := vtg.server.ExecuteKeyspaceIds(ctx, request.Sql, request.BindVariables, request.Keyspace, key.KeyspaceIdsToProto(request.KeyspaceIds), topo.TabletTypeToProto(request.TabletType), request.Session, request.NotInTransaction, reply) vtgate.AddVtGateError(vtgErr, &reply.Err) return nil }
func (conn *vtgateConn) ExecuteKeyspaceIds(ctx context.Context, query string, keyspace string, keyspaceIds []key.KeyspaceId, bindVars map[string]interface{}, tabletType topo.TabletType, notInTransaction bool, session interface{}) (*mproto.QueryResult, interface{}, error) { var s *pb.Session if session != nil { s = session.(*pb.Session) } request := &pb.ExecuteKeyspaceIdsRequest{ Session: s, Query: tproto.BoundQueryToProto3(query, bindVars), Keyspace: keyspace, KeyspaceIds: key.KeyspaceIdsToProto(keyspaceIds), TabletType: topo.TabletTypeToProto(tabletType), NotInTransaction: notInTransaction, } response, err := conn.c.ExecuteKeyspaceIds(ctx, request) if err != nil { return nil, session, err } if response.Error != nil { return nil, response.Session, vterrors.FromVtRPCError(response.Error) } return mproto.Proto3ToQueryResult(response.Result), response.Session, nil }
// StreamExecuteKeyspaceIds2 is the RPC version of // vtgateservice.VTGateService method func (vtg *VTGate) StreamExecuteKeyspaceIds2(ctx context.Context, request *proto.KeyspaceIdQuery, sendReply func(interface{}) error) (err error) { defer vtg.server.HandlePanic(&err) ctx = callerid.NewContext(ctx, callerid.GoRPCEffectiveCallerID(request.CallerID), callerid.NewImmediateCallerID("gorpc client")) vtgErr := vtg.server.StreamExecuteKeyspaceIds(ctx, request.Sql, request.BindVariables, request.Keyspace, key.KeyspaceIdsToProto(request.KeyspaceIds), topo.TabletTypeToProto(request.TabletType), func(value *proto.QueryResult) error { return sendReply(value) }) if vtgErr == nil { return nil } // If there was an app error, send a QueryResult back with it. qr := new(proto.QueryResult) vtgate.AddVtGateError(vtgErr, &qr.Err) return sendReply(qr) }
func boundKeyspaceIDQueriesToBoundShardQueries(ctx context.Context, topoServ SrvTopoServer, cell string, tabletType pb.TabletType, idQueries []proto.BoundKeyspaceIdQuery) ([]proto.BoundShardQuery, error) { shardQueries := make([]proto.BoundShardQuery, len(idQueries)) for i, idQuery := range idQueries { keyspace, shards, err := mapKeyspaceIdsToShards(ctx, topoServ, cell, idQuery.Keyspace, tabletType, key.KeyspaceIdsToProto(idQuery.KeyspaceIds)) if err != nil { return nil, err } shardQueries[i] = proto.BoundShardQuery{ Sql: idQuery.Sql, BindVariables: idQuery.BindVariables, Keyspace: keyspace, Shards: shards, } } return shardQueries, nil }