예제 #1
0
파일: conn.go 프로젝트: haoqoo/vitess
// StreamExecute2 starts a streaming query to VTTablet. This differs from StreamExecute in that
// it expects errors to be returned as part of the StreamExecute results.
func (conn *TabletBson) StreamExecute2(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.rpcClient == nil {
		return nil, nil, tabletconn.ConnClosed
	}

	req := &tproto.StreamExecuteRequest{
		Target:            conn.target,
		EffectiveCallerID: getEffectiveCallerID(ctx),
		ImmediateCallerID: getImmediateCallerID(ctx),
		Query: &tproto.Query{
			Sql:           query,
			BindVariables: bindVars,
			TransactionId: transactionID,
			SessionId:     conn.sessionID,
		},
	}
	// Use QueryResult instead of StreamExecuteResult for now, due to backwards compatability reasons.
	// It'll be easuer to migrate all end-points to using StreamExecuteResult instead of
	// maintaining a mixture of QueryResult and StreamExecuteResult channel returns.
	sr := make(chan *mproto.QueryResult, 10)
	c := conn.rpcClient.StreamGo("SqlQuery.StreamExecute2", req, sr)
	firstResult, ok := <-sr
	if !ok {
		return nil, nil, tabletError(c.Error)
	}
	// SqlQuery.StreamExecute might return an application error inside the QueryResult
	vtErr := vterrors.FromRPCError(firstResult.Err)
	if vtErr != nil {
		return nil, nil, tabletError(vtErr)
	}
	srout := make(chan *mproto.QueryResult, 1)
	go func() {
		defer close(srout)
		srout <- firstResult
		for r := range sr {
			vtErr = vterrors.FromRPCError(r.Err)
			// 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.
			if vtErr == nil {
				srout <- r
			}
		}
	}()
	// 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 {
		rpcErr := tabletError(c.Error)
		if rpcErr != nil {
			return rpcErr
		}
		return tabletError(vtErr)
	}
	return srout, errFunc, nil
}
예제 #2
0
파일: conn.go 프로젝트: pranjal5215/vitess
// StreamExecute starts a streaming query to VTTablet.
func (conn *TabletBson) 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.rpcClient == nil {
		return nil, nil, tabletconn.ConnClosed
	}

	req := &tproto.Query{
		Sql:           query,
		BindVariables: bindVars,
		TransactionId: transactionID,
		SessionId:     conn.sessionID,
	}
	sr := make(chan *mproto.QueryResult, 10)
	c := conn.rpcClient.StreamGo("SqlQuery.StreamExecute", req, sr)
	firstResult, ok := <-sr
	if !ok {
		return nil, nil, tabletError(c.Error)
	}
	// SqlQuery.StreamExecute might return an application error inside the QueryResult
	vtErr := vterrors.FromRPCError(firstResult.Err)
	if vtErr != nil {
		return nil, nil, tabletError(vtErr)
	}
	srout := make(chan *mproto.QueryResult, 1)
	go func() {
		defer close(srout)
		srout <- firstResult
		for r := range sr {
			vtErr = vterrors.FromRPCError(r.Err)
			// 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.
			if vtErr == nil {
				srout <- r
			}
		}
	}()
	// 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 {
		rpcErr := tabletError(c.Error)
		if rpcErr != nil {
			return rpcErr
		}
		return tabletError(vtErr)
	}
	return srout, errFunc, nil
}
예제 #3
0
파일: conn.go 프로젝트: kissthink/vitess
func (conn *vtgateConn) ExecuteBatchShard(ctx context.Context, queries []tproto.BoundQuery, keyspace string, shards []string, tabletType topo.TabletType, notInTransaction bool, session interface{}) ([]mproto.QueryResult, interface{}, error) {
	var s *proto.Session
	if session != nil {
		s = session.(*proto.Session)
	}
	request := proto.BatchQueryShard{
		Queries:          queries,
		Keyspace:         keyspace,
		Shards:           shards,
		TabletType:       tabletType,
		Session:          s,
		NotInTransaction: notInTransaction,
	}
	var result proto.QueryResultList
	if err := conn.rpcConn.Call(ctx, "VTGate.ExecuteBatchShard", request, &result); err != nil {
		return nil, session, err
	}
	if result.Error != "" {
		return nil, result.Session, errors.New(result.Error)
	}
	if err := vterrors.FromRPCError(result.Err); err != nil {
		return nil, result.Session, err
	}
	return result.List, result.Session, nil
}
예제 #4
0
파일: conn.go 프로젝트: afrolovskiy/vitess
// DialTablet creates and initializes TabletBson.
func DialTablet(ctx context.Context, endPoint *pbt.EndPoint, keyspace, shard string, timeout time.Duration) (tabletconn.TabletConn, error) {
	addr := netutil.JoinHostPort(endPoint.Host, endPoint.PortMap["vt"])
	conn := &TabletBson{endPoint: endPoint}
	var err error
	if *tabletBsonUsername != "" {
		conn.rpcClient, err = bsonrpc.DialAuthHTTP("tcp", addr, *tabletBsonUsername, *tabletBsonPassword, timeout)
	} else {
		conn.rpcClient, err = bsonrpc.DialHTTP("tcp", addr, timeout)
	}
	if err != nil {
		return nil, tabletError(err)
	}

	if keyspace != "" || shard != "" {
		var sessionInfo tproto.SessionInfo
		if err = conn.rpcClient.Call(ctx, "SqlQuery.GetSessionId", tproto.SessionParams{Keyspace: keyspace, Shard: shard}, &sessionInfo); err != nil {
			conn.rpcClient.Close()
			return nil, tabletError(err)
		}
		// SqlQuery.GetSessionId might return an application error inside the SessionInfo
		if err = vterrors.FromRPCError(sessionInfo.Err); err != nil {
			conn.rpcClient.Close()
			return nil, tabletError(err)
		}
		conn.sessionID = sessionInfo.SessionId
	}
	return conn, nil
}
예제 #5
0
파일: conn.go 프로젝트: haoqoo/vitess
// Rollback2 should not be used for anything except tests for now;
// it will eventually replace the existing Rollback.
// Rollback2 rolls back the ongoing transaction.
func (conn *TabletBson) Rollback2(ctx context.Context, transactionID int64) error {
	conn.mu.RLock()
	defer conn.mu.RUnlock()
	if conn.rpcClient == nil {
		return tabletconn.ConnClosed
	}

	rollbackRequest := &tproto.RollbackRequest{
		Target:            conn.target,
		EffectiveCallerID: getEffectiveCallerID(ctx),
		ImmediateCallerID: getImmediateCallerID(ctx),
		SessionId:         conn.sessionID,
		TransactionId:     transactionID,
	}
	rollbackResponse := new(tproto.RollbackResponse)
	action := func() error {
		err := conn.rpcClient.Call(ctx, "SqlQuery.Rollback2", rollbackRequest, rollbackResponse)
		if err != nil {
			return err
		}
		// SqlQuery.Rollback might return an application error inside the ErrorOnly
		return vterrors.FromRPCError(rollbackResponse.Err)
	}
	err := conn.withTimeout(ctx, action)
	return tabletError(err)
}
예제 #6
0
파일: conn.go 프로젝트: haoqoo/vitess
// Begin2 should not be used for anything except tests for now;
// it will eventually replace the existing Begin.
// Begin2 starts a transaction.
func (conn *TabletBson) Begin2(ctx context.Context) (transactionID int64, err error) {
	conn.mu.RLock()
	defer conn.mu.RUnlock()
	if conn.rpcClient == nil {
		return 0, tabletconn.ConnClosed
	}

	beginRequest := &tproto.BeginRequest{
		Target:            conn.target,
		EffectiveCallerID: getEffectiveCallerID(ctx),
		ImmediateCallerID: getImmediateCallerID(ctx),
		SessionId:         conn.sessionID,
	}
	beginResponse := new(tproto.BeginResponse)
	action := func() error {
		err := conn.rpcClient.Call(ctx, "SqlQuery.Begin2", beginRequest, beginResponse)
		if err != nil {
			return err
		}
		// SqlQuery.Begin might return an application error inside the TransactionInfo
		return vterrors.FromRPCError(beginResponse.Err)
	}
	err = conn.withTimeout(ctx, action)
	return beginResponse.TransactionId, tabletError(err)
}
예제 #7
0
파일: conn.go 프로젝트: haoqoo/vitess
// ExecuteBatch2 should not be used now other than in tests.
// It is the CallerID enabled version of ExecuteBatch
// ExecuteBatch2 sends a batch query to VTTablet
func (conn *TabletBson) ExecuteBatch2(ctx context.Context, queries []tproto.BoundQuery, asTransaction bool, transactionID int64) (*tproto.QueryResultList, error) {
	conn.mu.RLock()
	defer conn.mu.RUnlock()
	if conn.rpcClient == nil {
		return nil, tabletconn.ConnClosed
	}

	req := tproto.ExecuteBatchRequest{
		Target:            conn.target,
		EffectiveCallerID: getEffectiveCallerID(ctx),
		ImmediateCallerID: getImmediateCallerID(ctx),
		QueryBatch: tproto.QueryList{
			Queries:       queries,
			AsTransaction: asTransaction,
			TransactionId: transactionID,
			SessionId:     conn.sessionID,
		},
		//TODO::Add CallerID information after it is passed down by context
	}
	qrs := new(tproto.QueryResultList)
	action := func() error {
		err := conn.rpcClient.Call(ctx, "SqlQuery.ExecuteBatch2", req, qrs)
		if err != nil {
			return err
		}
		// SqlQuery.ExecuteBatch might return an application error inside the QueryResultList
		return vterrors.FromRPCError(qrs.Err)
	}
	if err := conn.withTimeout(ctx, action); err != nil {
		return nil, tabletError(err)
	}
	return qrs, nil
}
예제 #8
0
파일: conn.go 프로젝트: haoqoo/vitess
// Execute2 should not be used now other than in tests.
// It is the CallerID enabled version of Execute
// Execute2 sends to query to VTTablet
func (conn *TabletBson) Execute2(ctx context.Context, query string, bindVars map[string]interface{}, transactionID int64) (*mproto.QueryResult, error) {
	conn.mu.RLock()
	defer conn.mu.RUnlock()
	if conn.rpcClient == nil {
		return nil, tabletconn.ConnClosed
	}

	req := &tproto.ExecuteRequest{
		Target:            conn.target,
		EffectiveCallerID: getEffectiveCallerID(ctx),
		ImmediateCallerID: getImmediateCallerID(ctx),
		QueryRequest: tproto.Query{
			Sql:           query,
			BindVariables: bindVars,
			TransactionId: transactionID,
			SessionId:     conn.sessionID,
		},
		// TODO::Fill in EffectiveCallerID and ImmediateCallerID
	}
	qr := new(mproto.QueryResult)
	action := func() error {
		err := conn.rpcClient.Call(ctx, "SqlQuery.Execute2", req, qr)
		if err != nil {
			return err
		}
		// SqlQuery.Execute2 might return an application error inside the QueryRequest
		return vterrors.FromRPCError(qr.Err)
	}
	if err := conn.withTimeout(ctx, action); err != nil {
		return nil, tabletError(err)
	}
	return qr, nil
}
예제 #9
0
파일: conn.go 프로젝트: BobbWu/vitess
func (conn *vtgateConn) ExecuteEntityIds(ctx context.Context, query string, keyspace string, entityColumnName string, entityKeyspaceIDs []*vtgatepb.ExecuteEntityIdsRequest_EntityId, bindVars map[string]interface{}, tabletType topodatapb.TabletType, notInTransaction bool, session interface{}) (*sqltypes.Result, interface{}, error) {
	s := sessionToRPC(session)
	request := gorpcvtgatecommon.EntityIdsQuery{
		CallerID:          getEffectiveCallerID(ctx),
		Sql:               query,
		BindVariables:     bindVars,
		Keyspace:          keyspace,
		EntityColumnName:  entityColumnName,
		EntityKeyspaceIDs: gorpcvtgatecommon.ProtoToEntityIds(entityKeyspaceIDs),
		TabletType:        tabletType,
		Session:           s,
		NotInTransaction:  notInTransaction,
	}
	var result gorpcvtgatecommon.QueryResult
	if err := conn.rpcConn.Call(ctx, "VTGate.ExecuteEntityIds", request, &result); err != nil {
		return nil, session, err
	}
	if err := vterrors.FromRPCError(result.Err); err != nil {
		return nil, sessionFromRPC(result.Session), err
	}
	if result.Result != nil {
		result.Result.Repair(result.Result.Fields)
	}
	return result.Result, sessionFromRPC(result.Session), nil
}
예제 #10
0
파일: conn.go 프로젝트: pranjal5215/vitess
// Execute sends the query to VTTablet.
func (conn *TabletBson) Execute(ctx context.Context, query string, bindVars map[string]interface{}, transactionID int64) (*mproto.QueryResult, error) {
	conn.mu.RLock()
	defer conn.mu.RUnlock()
	if conn.rpcClient == nil {
		return nil, tabletconn.ConnClosed
	}

	req := &tproto.Query{
		Sql:           query,
		BindVariables: bindVars,
		TransactionId: transactionID,
		SessionId:     conn.sessionID,
	}
	qr := new(mproto.QueryResult)
	action := func() error {
		err := conn.rpcClient.Call(ctx, "SqlQuery.Execute", req, qr)
		if err != nil {
			return err
		}
		// SqlQuery.Execute might return an application error inside the QueryResult
		return vterrors.FromRPCError(qr.Err)
	}
	if err := conn.withTimeout(ctx, action); err != nil {
		return nil, tabletError(err)
	}
	return qr, nil
}
예제 #11
0
파일: conn.go 프로젝트: BobbWu/vitess
func sendStreamResults(c *rpcplus.Call, sr chan *gorpcvtgatecommon.QueryResult) (<-chan *sqltypes.Result, vtgateconn.ErrFunc, error) {
	srout := make(chan *sqltypes.Result, 1)
	var vtErr error
	go func() {
		defer close(srout)
		var fields []*querypb.Field
		for r := range sr {
			vtErr = vterrors.FromRPCError(r.Err)
			// 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.
			if vtErr == nil {
				if fields == nil {
					// first packet, we remember the fields
					fields = r.Result.Fields
				} else {
					// next packet, fix the result
					r.Result.Repair(fields)
				}
				srout <- r.Result
			}
		}
	}()
	// 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 vtErr
	}
	return srout, errFunc, nil
}
예제 #12
0
파일: conn.go 프로젝트: pranjal5215/vitess
// ExecuteBatch sends a batch query to VTTablet.
func (conn *TabletBson) ExecuteBatch(ctx context.Context, queries []tproto.BoundQuery, transactionID int64) (*tproto.QueryResultList, error) {
	conn.mu.RLock()
	defer conn.mu.RUnlock()
	if conn.rpcClient == nil {
		return nil, tabletconn.ConnClosed
	}

	req := tproto.QueryList{
		Queries:       queries,
		TransactionId: transactionID,
		SessionId:     conn.sessionID,
	}
	qrs := new(tproto.QueryResultList)
	action := func() error {
		err := conn.rpcClient.Call(ctx, "SqlQuery.ExecuteBatch", req, qrs)
		if err != nil {
			return err
		}
		// SqlQuery.ExecuteBatch might return an application error inside the QueryResultList
		return vterrors.FromRPCError(qrs.Err)
	}
	if err := conn.withTimeout(ctx, action); err != nil {
		return nil, tabletError(err)
	}
	return qrs, nil
}
예제 #13
0
파일: conn.go 프로젝트: pranjal5215/vitess
// SplitQuery is the stub for SqlQuery.SplitQuery RPC
func (conn *TabletBson) SplitQuery(ctx context.Context, query tproto.BoundQuery, splitCount int) (queries []tproto.QuerySplit, err error) {
	conn.mu.RLock()
	defer conn.mu.RUnlock()
	if conn.rpcClient == nil {
		err = tabletconn.ConnClosed
		return
	}
	req := &tproto.SplitQueryRequest{
		Query:      query,
		SplitCount: splitCount,
		SessionID:  conn.sessionID,
	}
	reply := new(tproto.SplitQueryResult)
	action := func() error {
		err := conn.rpcClient.Call(ctx, "SqlQuery.SplitQuery", req, reply)
		if err != nil {
			return err
		}
		// SqlQuery.SplitQuery might return an application error inside the SplitQueryRequest
		return vterrors.FromRPCError(reply.Err)
	}
	if err := conn.withTimeout(ctx, action); err != nil {
		return nil, tabletError(err)
	}
	return reply.Queries, nil
}
예제 #14
0
파일: conn.go 프로젝트: BobbWu/vitess
func (conn *vtgateConn) ExecuteBatchKeyspaceIds(ctx context.Context, queries []*vtgatepb.BoundKeyspaceIdQuery, tabletType topodatapb.TabletType, asTransaction bool, session interface{}) ([]sqltypes.Result, interface{}, error) {
	s := sessionToRPC(session)
	qs, err := gorpcvtgatecommon.ProtoToBoundKeyspaceIdQueries(queries)
	if err != nil {
		return nil, session, err
	}
	request := gorpcvtgatecommon.KeyspaceIdBatchQuery{
		CallerID:      getEffectiveCallerID(ctx),
		Queries:       qs,
		TabletType:    tabletType,
		AsTransaction: asTransaction,
		Session:       s,
	}
	var result gorpcvtgatecommon.QueryResultList
	if err := conn.rpcConn.Call(ctx, "VTGate.ExecuteBatchKeyspaceIds", request, &result); err != nil {
		return nil, session, err
	}
	if err := vterrors.FromRPCError(result.Err); err != nil {
		return nil, sessionFromRPC(result.Session), err
	}
	for _, r := range result.List {
		r.Repair(r.Fields)
	}
	return result.List, sessionFromRPC(result.Session), nil
}
예제 #15
0
파일: conn.go 프로젝트: pranjal5215/vitess
// DialTablet creates and initializes TabletBson.
func DialTablet(ctx context.Context, endPoint topo.EndPoint, keyspace, shard string, timeout time.Duration) (tabletconn.TabletConn, error) {
	var addr string
	var config *tls.Config
	if *tabletBsonEncrypted {
		addr = netutil.JoinHostPort(endPoint.Host, endPoint.NamedPortMap["vts"])
		config = &tls.Config{}
		config.InsecureSkipVerify = true
	} else {
		addr = netutil.JoinHostPort(endPoint.Host, endPoint.NamedPortMap["vt"])
	}

	conn := &TabletBson{endPoint: endPoint}
	var err error
	if *tabletBsonUsername != "" {
		conn.rpcClient, err = bsonrpc.DialAuthHTTP("tcp", addr, *tabletBsonUsername, *tabletBsonPassword, timeout, config)
	} else {
		conn.rpcClient, err = bsonrpc.DialHTTP("tcp", addr, timeout, config)
	}
	if err != nil {
		return nil, tabletError(err)
	}

	var sessionInfo tproto.SessionInfo
	if err = conn.rpcClient.Call(ctx, "SqlQuery.GetSessionId", tproto.SessionParams{Keyspace: keyspace, Shard: shard}, &sessionInfo); err != nil {
		conn.rpcClient.Close()
		return nil, tabletError(err)
	}
	// SqlQuery.GetSessionId might return an application error inside the SessionInfo
	if err = vterrors.FromRPCError(sessionInfo.Err); err != nil {
		conn.rpcClient.Close()
		return nil, tabletError(err)
	}
	conn.sessionID = sessionInfo.SessionId
	return conn, nil
}
예제 #16
0
파일: conn.go 프로젝트: richarwu/vitess
func (conn *vtgateConn) ExecuteEntityIds(ctx context.Context, query string, keyspace string, entityColumnName string, entityKeyspaceIDs []*pbg.ExecuteEntityIdsRequest_EntityId, bindVars map[string]interface{}, tabletType pb.TabletType, notInTransaction bool, session interface{}) (*mproto.QueryResult, interface{}, error) {
	var s *proto.Session
	if session != nil {
		s = session.(*proto.Session)
	}
	request := proto.EntityIdsQuery{
		CallerID:          getEffectiveCallerID(ctx),
		Sql:               query,
		BindVariables:     bindVars,
		Keyspace:          keyspace,
		EntityColumnName:  entityColumnName,
		EntityKeyspaceIDs: proto.ProtoToEntityIds(entityKeyspaceIDs),
		TabletType:        topo.ProtoToTabletType(tabletType),
		Session:           s,
		NotInTransaction:  notInTransaction,
	}
	var result proto.QueryResult
	if err := conn.rpcConn.Call(ctx, "VTGate.ExecuteEntityIds", request, &result); err != nil {
		return nil, session, err
	}
	if err := vterrors.FromRPCError(result.Err); err != nil {
		return nil, result.Session, err
	}
	return result.Result, result.Session, nil
}
예제 #17
0
파일: conn.go 프로젝트: kissthink/vitess
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 *proto.Session
	if session != nil {
		s = session.(*proto.Session)
	}
	request := proto.KeyspaceIdQuery{
		Sql:              query,
		BindVariables:    bindVars,
		Keyspace:         keyspace,
		KeyspaceIds:      keyspaceIds,
		TabletType:       tabletType,
		Session:          s,
		NotInTransaction: notInTransaction,
	}
	var result proto.QueryResult
	if err := conn.rpcConn.Call(ctx, "VTGate.ExecuteKeyspaceIds", request, &result); err != nil {
		return nil, session, err
	}
	if result.Error != "" {
		return nil, result.Session, errors.New(result.Error)
	}
	if err := vterrors.FromRPCError(result.Err); err != nil {
		return nil, result.Session, err
	}
	return result.Result, result.Session, nil
}
예제 #18
0
파일: conn.go 프로젝트: payintel/vitess
func (conn *vtgateConn) ExecuteShards(ctx context.Context, query string, keyspace string, shards []string, bindVars map[string]interface{}, tabletType pb.TabletType, notInTransaction bool, session interface{}) (*mproto.QueryResult, interface{}, error) {
	var s *proto.Session
	if session != nil {
		s = session.(*proto.Session)
	}
	request := proto.QueryShard{
		CallerID:         getEffectiveCallerID(ctx),
		Sql:              query,
		BindVariables:    bindVars,
		Keyspace:         keyspace,
		Shards:           shards,
		TabletType:       topo.ProtoToTabletType(tabletType),
		Session:          s,
		NotInTransaction: notInTransaction,
	}
	var result proto.QueryResult
	if err := conn.rpcConn.Call(ctx, "VTGate.ExecuteShard", request, &result); err != nil {
		return nil, session, err
	}
	if result.Error != "" {
		return nil, result.Session, errors.New(result.Error)
	}
	if err := vterrors.FromRPCError(result.Err); err != nil {
		return nil, result.Session, err
	}
	return result.Result, result.Session, nil
}
예제 #19
0
파일: conn.go 프로젝트: payintel/vitess
func sendStreamResults(c *rpcplus.Call, sr chan *proto.QueryResult) (<-chan *mproto.QueryResult, vtgateconn.ErrFunc, error) {
	srout := make(chan *mproto.QueryResult, 1)
	var vtErr error
	go func() {
		defer close(srout)
		for r := range sr {
			vtErr = vterrors.FromRPCError(r.Err)
			// 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.
			if vtErr == nil {
				srout <- r.Result
			}
		}
	}()
	// 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 vtErr
	}
	return srout, errFunc, nil
}
예제 #20
0
파일: conn.go 프로젝트: kissthink/vitess
func (conn *vtgateConn) Rollback2(ctx context.Context, session interface{}) error {
	s := session.(*proto.Session)
	request := &proto.RollbackRequest{
		Session: s,
	}
	reply := new(proto.RollbackResponse)
	if err := conn.rpcConn.Call(ctx, "VTGate.Rollback2", request, reply); err != nil {
		return err
	}
	return vterrors.FromRPCError(reply.Err)
}
예제 #21
0
파일: conn.go 프로젝트: BobbWu/vitess
func (conn *vtgateConn) Rollback2(ctx context.Context, session interface{}) error {
	s := sessionToRPC(session)
	request := &gorpcvtgatecommon.RollbackRequest{
		CallerID: getEffectiveCallerID(ctx),
		Session:  s,
	}
	reply := new(gorpcvtgatecommon.RollbackResponse)
	if err := conn.rpcConn.Call(ctx, "VTGate.Rollback2", request, reply); err != nil {
		return err
	}
	return vterrors.FromRPCError(reply.Err)
}
예제 #22
0
파일: conn.go 프로젝트: payintel/vitess
func (conn *vtgateConn) Commit2(ctx context.Context, session interface{}) error {
	s := session.(*proto.Session)
	request := &proto.CommitRequest{
		CallerID: getEffectiveCallerID(ctx),
		Session:  s,
	}
	reply := new(proto.CommitResponse)
	if err := conn.rpcConn.Call(ctx, "VTGate.Commit2", request, reply); err != nil {
		return err
	}
	return vterrors.FromRPCError(reply.Err)
}
예제 #23
0
파일: conn.go 프로젝트: kissthink/vitess
func (conn *vtgateConn) SplitQuery(ctx context.Context, keyspace string, query tproto.BoundQuery, splitCount int) ([]proto.SplitQueryPart, error) {
	request := &proto.SplitQueryRequest{
		Keyspace:   keyspace,
		Query:      query,
		SplitCount: splitCount,
	}
	result := &proto.SplitQueryResult{}
	if err := conn.rpcConn.Call(ctx, "VTGate.SplitQuery", request, result); err != nil {
		return nil, err
	}
	if err := vterrors.FromRPCError(result.Err); err != nil {
		return nil, err
	}
	return result.Splits, nil
}
예제 #24
0
파일: conn.go 프로젝트: kissthink/vitess
func (conn *vtgateConn) Begin2(ctx context.Context) (interface{}, error) {
	request := new(proto.BeginRequest)
	reply := new(proto.BeginResponse)
	if err := conn.rpcConn.Call(ctx, "VTGate.Begin2", request, reply); err != nil {
		return nil, err
	}
	if err := vterrors.FromRPCError(reply.Err); err != nil {
		return nil, err
	}
	// Return a non-nil pointer
	session := &proto.Session{}
	if reply.Session != nil {
		session = reply.Session
	}
	return session, nil
}
예제 #25
0
파일: conn.go 프로젝트: c3p0hz/vitess
func (conn *vtgateConn) ExecuteBatchKeyspaceIds(ctx context.Context, queries []proto.BoundKeyspaceIdQuery, tabletType pb.TabletType, asTransaction bool, session interface{}) ([]sqltypes.Result, interface{}, error) {
	s := sessionToRPC(session)
	request := proto.KeyspaceIdBatchQuery{
		CallerID:      getEffectiveCallerID(ctx),
		Queries:       queries,
		TabletType:    tabletType,
		AsTransaction: asTransaction,
		Session:       s,
	}
	var result proto.QueryResultList
	if err := conn.rpcConn.Call(ctx, "VTGate.ExecuteBatchKeyspaceIds", request, &result); err != nil {
		return nil, session, err
	}
	if err := vterrors.FromRPCError(result.Err); err != nil {
		return nil, sessionFromRPC(result.Session), err
	}
	return result.List, sessionFromRPC(result.Session), nil
}
예제 #26
0
파일: conn.go 프로젝트: BobbWu/vitess
func (conn *vtgateConn) Begin2(ctx context.Context) (interface{}, error) {
	request := &gorpcvtgatecommon.BeginRequest{
		CallerID: getEffectiveCallerID(ctx),
	}
	reply := new(gorpcvtgatecommon.BeginResponse)
	if err := conn.rpcConn.Call(ctx, "VTGate.Begin2", request, reply); err != nil {
		return nil, err
	}
	if err := vterrors.FromRPCError(reply.Err); err != nil {
		return nil, err
	}
	// Return a non-nil pointer
	session := &vtgatepb.Session{}
	if reply.Session != nil {
		session = reply.Session
	}
	return session, nil
}
예제 #27
0
파일: conn.go 프로젝트: c3p0hz/vitess
func (conn *vtgateConn) Execute(ctx context.Context, query string, bindVars map[string]interface{}, tabletType pb.TabletType, notInTransaction bool, session interface{}) (*sqltypes.Result, interface{}, error) {
	s := sessionToRPC(session)
	request := proto.Query{
		CallerID:         getEffectiveCallerID(ctx),
		Sql:              query,
		BindVariables:    bindVars,
		TabletType:       tabletType,
		Session:          s,
		NotInTransaction: notInTransaction,
	}
	var result proto.QueryResult
	if err := conn.rpcConn.Call(ctx, "VTGate.Execute", request, &result); err != nil {
		return nil, session, err
	}
	if err := vterrors.FromRPCError(result.Err); err != nil {
		return nil, sessionFromRPC(result.Session), err
	}
	return result.Result, sessionFromRPC(result.Session), nil
}
예제 #28
0
파일: conn.go 프로젝트: payintel/vitess
func (conn *vtgateConn) SplitQuery(ctx context.Context, keyspace string, query string, bindVars map[string]interface{}, splitColumn string, splitCount int) ([]proto.SplitQueryPart, error) {
	request := &proto.SplitQueryRequest{
		CallerID: getEffectiveCallerID(ctx),
		Keyspace: keyspace,
		Query: tproto.BoundQuery{
			Sql:           query,
			BindVariables: bindVars,
		},
		SplitColumn: splitColumn,
		SplitCount:  splitCount,
	}
	result := &proto.SplitQueryResult{}
	if err := conn.rpcConn.Call(ctx, "VTGate.SplitQuery", request, result); err != nil {
		return nil, err
	}
	if err := vterrors.FromRPCError(result.Err); err != nil {
		return nil, err
	}
	return result.Splits, nil
}
예제 #29
0
파일: conn.go 프로젝트: richarwu/vitess
func (conn *vtgateConn) ExecuteBatchShards(ctx context.Context, queries []proto.BoundShardQuery, tabletType pb.TabletType, asTransaction bool, session interface{}) ([]mproto.QueryResult, interface{}, error) {
	var s *proto.Session
	if session != nil {
		s = session.(*proto.Session)
	}
	request := proto.BatchQueryShard{
		CallerID:      getEffectiveCallerID(ctx),
		Queries:       queries,
		TabletType:    topo.ProtoToTabletType(tabletType),
		AsTransaction: asTransaction,
		Session:       s,
	}
	var result proto.QueryResultList
	if err := conn.rpcConn.Call(ctx, "VTGate.ExecuteBatchShard", request, &result); err != nil {
		return nil, session, err
	}
	if err := vterrors.FromRPCError(result.Err); err != nil {
		return nil, result.Session, err
	}
	return result.List, result.Session, nil
}
예제 #30
0
파일: conn.go 프로젝트: pranjal5215/vitess
// Begin starts a transaction.
func (conn *TabletBson) Begin(ctx context.Context) (transactionID int64, err error) {
	conn.mu.RLock()
	defer conn.mu.RUnlock()
	if conn.rpcClient == nil {
		return 0, tabletconn.ConnClosed
	}

	req := &tproto.Session{
		SessionId: conn.sessionID,
	}
	var txInfo tproto.TransactionInfo
	action := func() error {
		err := conn.rpcClient.Call(ctx, "SqlQuery.Begin", req, &txInfo)
		if err != nil {
			return err
		}
		// SqlQuery.Begin might return an application error inside the TransactionInfo
		return vterrors.FromRPCError(txInfo.Err)
	}
	err = conn.withTimeout(ctx, action)
	return txInfo.TransactionId, tabletError(err)
}