func (conn *vtgateConn) StreamExecuteKeyspaceIds(ctx context.Context, query string, keyspace string, keyspaceIds [][]byte, bindVars map[string]interface{}, tabletType pbt.TabletType) (<-chan *mproto.QueryResult, vtgateconn.ErrFunc, error) { req := &pb.StreamExecuteKeyspaceIdsRequest{ CallerId: callerid.EffectiveCallerIDFromContext(ctx), Query: tproto.BoundQueryToProto3(query, bindVars), Keyspace: keyspace, KeyspaceIds: keyspaceIds, TabletType: tabletType, } stream, err := conn.c.StreamExecuteKeyspaceIds(ctx, req) if err != nil { return nil, nil, vterrors.FromGRPCError(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 = vterrors.FromGRPCError(err) } close(sr) return } sr <- mproto.Proto3ToQueryResult(ser.Result) } }() return sr, func() error { return finalError }, nil }
func sendStreamResults(c *rpcplus.Call, sr chan streamResult) (<-chan *mproto.QueryResult, vtgateconn.ErrFunc, error) { srout := make(chan *mproto.QueryResult, 1) var err error go func() { defer close(srout) for r := range sr { // nil != nil vtErr := vterrors.FromVtRPCError(r.err) if vtErr != nil { err = vtErr continue } // If we get a QueryResult with an RPCError, that was an extra QueryResult sent by // the server specifically to indicate an error, and we shouldn't surface it to clients. srout <- mproto.Proto3ToQueryResult(r.qr) } }() // errFunc will return either an RPC-layer error or an application error, if one exists. // It will only return the most recent application error (i.e, from the QueryResult that // most recently contained an error). It will prioritize an RPC-layer error over an apperror, // if both exist. errFunc := func() error { if c.Error != nil { return c.Error } return err } return srout, errFunc, nil }
func (conn *vtgateConn) StreamExecute(ctx context.Context, query string, bindVars map[string]interface{}, tabletType pbt.TabletType) (<-chan *mproto.QueryResult, vtgateconn.ErrFunc, error) { req := &pb.StreamExecuteRequest{ CallerId: callerid.EffectiveCallerIDFromContext(ctx), Query: tproto.BoundQueryToProto3(query, bindVars), TabletType: tabletType, } stream, err := conn.c.StreamExecute(ctx, req) if err != nil { return nil, nil, vterrors.FromGRPCError(err) } sr := make(chan *mproto.QueryResult, 10) // TODO(aaijazi): I'm pretty sure ther error handling going on down here is overkill now... 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 }
func (conn *vtgateConn) ExecuteShards(ctx context.Context, query string, keyspace string, shards []string, bindVars map[string]interface{}, tabletType pbt.TabletType, notInTransaction bool, session interface{}) (*mproto.QueryResult, interface{}, error) { var s *pb.Session if session != nil { s = session.(*pb.Session) } q, err := tproto.BoundQueryToProto3(query, bindVars) if err != nil { return nil, session, err } request := &pb.ExecuteShardsRequest{ CallerId: callerid.EffectiveCallerIDFromContext(ctx), Session: s, Query: q, Keyspace: keyspace, Shards: shards, TabletType: tabletType, NotInTransaction: notInTransaction, } response, err := conn.c.ExecuteShards(ctx, request) if err != nil { return nil, session, vterrors.FromGRPCError(err) } if response.Error != nil { return nil, response.Session, vterrors.FromVtRPCError(response.Error) } return mproto.Proto3ToQueryResult(response.Result), response.Session, nil }
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 }
func sendStreamResults(c *rpcplus.Call, sr chan *qpb.QueryResult) (<-chan *mproto.QueryResult, vtgateconn.ErrFunc, error) { srout := make(chan *mproto.QueryResult, 1) go func() { defer close(srout) for r := range sr { srout <- mproto.Proto3ToQueryResult(r) } }() errFunc := func() error { return vterrors.FromJSONError(c.Error) } return srout, errFunc, nil }
// ExecuteFetchAsApp is part of the tmclient.TabletManagerClient interface func (client *Client) ExecuteFetchAsApp(ctx context.Context, tablet *topo.TabletInfo, query string, maxRows int, wantFields bool) (*mproto.QueryResult, error) { cc, c, err := client.dial(ctx, tablet) if err != nil { return nil, err } defer cc.Close() response, err := c.ExecuteFetchAsApp(ctx, &pb.ExecuteFetchAsAppRequest{ Query: query, MaxRows: uint64(maxRows), WantFields: wantFields, }) if err != nil { return nil, err } return mproto.Proto3ToQueryResult(response.Result), nil }
// ExecuteFetchAsDba is part of the tmclient.TabletManagerClient interface func (client *Client) ExecuteFetchAsDba(ctx context.Context, tablet *topo.TabletInfo, query string, maxRows int, wantFields, disableBinlogs, reloadSchema bool) (*mproto.QueryResult, error) { cc, c, err := client.dial(ctx, tablet) if err != nil { return nil, err } defer cc.Close() response, err := c.ExecuteFetchAsDba(ctx, &pb.ExecuteFetchAsDbaRequest{ Query: query, DbName: tablet.DbName(), MaxRows: uint64(maxRows), WantFields: wantFields, DisableBinlogs: disableBinlogs, ReloadSchema: reloadSchema, }) if err != nil { return nil, err } return mproto.Proto3ToQueryResult(response.Result), nil }
func (conn *vtgateConn) Execute(ctx context.Context, query string, 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.ExecuteRequest{ Session: s, Query: tproto.BoundQueryToProto3(query, bindVars), TabletType: topo.TabletTypeToProto(tabletType), NotInTransaction: notInTransaction, } response, err := conn.c.Execute(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 }
// Execute sends the query to VTTablet. func (conn *gRPCQueryClient) Execute(ctx context.Context, query string, bindVars map[string]interface{}, transactionID int64) (*mproto.QueryResult, error) { conn.mu.RLock() defer conn.mu.RUnlock() if conn.cc == nil { return nil, tabletconn.ConnClosed } req := &pb.ExecuteRequest{ Query: tproto.BoundQueryToProto3(query, bindVars), TransactionId: transactionID, SessionId: conn.sessionID, } er, err := conn.c.Execute(ctx, req) if err != nil { return nil, tabletErrorFromGRPC(err) } if er.Error != nil { return nil, tabletErrorFromRPCError(er.Error) } return mproto.Proto3ToQueryResult(er.Result), nil }
func (conn *vtgateConn) Execute(ctx context.Context, query string, bindVars map[string]interface{}, tabletType topopb.TabletType, notInTransaction bool, session interface{}) (*mproto.QueryResult, interface{}, error) { var s *pb.Session if session != nil { s = session.(*pb.Session) } request := &pb.ExecuteRequest{ CallerId: callerid.EffectiveCallerIDFromContext(ctx), Query: tproto.BoundQueryToProto3(query, bindVars), TabletType: tabletType, Session: s, NotInTransaction: notInTransaction, } response := &pb.ExecuteResponse{} if err := conn.rpcConn.Call(ctx, "VTGateP3.Execute", request, response); err != nil { return nil, response.Session, err } if err := vterrors.FromVtRPCError(response.Error); err != nil { return nil, response.Session, err } return mproto.Proto3ToQueryResult(response.Result), response.Session, nil }
// StreamExecute starts a streaming query to VTTablet. func (conn *gRPCQueryClient) StreamExecute(ctx context.Context, query string, bindVars map[string]interface{}, transactionID int64) (<-chan *mproto.QueryResult, tabletconn.ErrFunc, error) { conn.mu.RLock() defer conn.mu.RUnlock() if conn.cc == nil { return nil, nil, tabletconn.ConnClosed } req := &pb.StreamExecuteRequest{ Query: tproto.BoundQueryToProto3(query, bindVars), SessionId: conn.sessionID, } stream, err := conn.c.StreamExecute(ctx, req) if err != nil { return nil, nil, tabletErrorFromGRPC(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 = tabletErrorFromGRPC(err) } close(sr) return } if ser.Error != nil { finalError = tabletErrorFromRPCError(ser.Error) close(sr) return } sr <- mproto.Proto3ToQueryResult(ser.Result) } }() return sr, func() error { return finalError }, nil }
func (conn *vtgateConn) ExecuteKeyRanges(ctx context.Context, query string, keyspace string, keyRanges []key.KeyRange, 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.ExecuteKeyRangesRequest{ CallerId: callerid.EffectiveCallerIDFromContext(ctx), Session: s, Query: tproto.BoundQueryToProto3(query, bindVars), Keyspace: keyspace, KeyRanges: key.KeyRangesToProto(keyRanges), TabletType: topo.TabletTypeToProto(tabletType), NotInTransaction: notInTransaction, } response, err := conn.c.ExecuteKeyRanges(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 }
func (conn *vtgateConn) ExecuteEntityIds(ctx context.Context, query string, keyspace string, entityColumnName string, entityKeyspaceIDs []*pb.ExecuteEntityIdsRequest_EntityId, bindVars map[string]interface{}, tabletType topopb.TabletType, notInTransaction bool, session interface{}) (*mproto.QueryResult, interface{}, error) { var s *pb.Session if session != nil { s = session.(*pb.Session) } request := &pb.ExecuteEntityIdsRequest{ CallerId: callerid.EffectiveCallerIDFromContext(ctx), Session: s, Query: tproto.BoundQueryToProto3(query, bindVars), Keyspace: keyspace, EntityColumnName: entityColumnName, EntityKeyspaceIds: entityKeyspaceIDs, TabletType: tabletType, NotInTransaction: notInTransaction, } response := &pb.ExecuteEntityIdsResponse{} if err := conn.rpcConn.Call(ctx, "VTGateP3.ExecuteEntityIds", request, response); err != nil { return nil, session, vterrors.FromJSONError(err) } if response.Error != nil { return nil, response.Session, vterrors.FromVtRPCError(response.Error) } return mproto.Proto3ToQueryResult(response.Result), response.Session, nil }