Exemple #1
0
func testUpdateStream(t *testing.T, conn tabletconn.TabletConn, f *FakeQueryService) {
	t.Log("testUpdateStream")
	ctx := context.Background()
	ctx = callerid.NewContext(ctx, TestCallerID, TestVTGateCallerID)
	stream, err := conn.UpdateStream(ctx, TestTarget, UpdateStreamPosition, UpdateStreamTimestamp)
	if err != nil {
		t.Fatalf("UpdateStream failed: %v", err)
	}
	qr, err := stream.Recv()
	if err != nil {
		t.Fatalf("UpdateStream failed: cannot read result1: %v", err)
	}
	if !reflect.DeepEqual(*qr, UpdateStreamStreamEvent1) {
		t.Errorf("Unexpected result1 from UpdateStream: got %v wanted %v", qr, UpdateStreamStreamEvent1)
	}
	qr, err = stream.Recv()
	if err != nil {
		t.Fatalf("UpdateStream failed: cannot read result2: %v", err)
	}
	if !reflect.DeepEqual(*qr, UpdateStreamStreamEvent2) {
		t.Errorf("Unexpected result2 from UpdateStream: got %v wanted %v", qr, UpdateStreamStreamEvent2)
	}
	qr, err = stream.Recv()
	if err != io.EOF {
		t.Fatalf("UpdateStream errFunc failed: %v", err)
	}
}
Exemple #2
0
// SplitQuery is the RPC version of vtgateservice.VTGateService method
func (vtg *VTGate) SplitQuery(ctx context.Context, request *vtgatepb.SplitQueryRequest) (response *vtgatepb.SplitQueryResponse, err error) {

	defer vtg.server.HandlePanic(&err)
	ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx),
		request.CallerId,
		callerid.NewImmediateCallerID("grpc client"))
	bv, err := querytypes.Proto3ToBindVariables(request.Query.BindVariables)
	if err != nil {
		return nil, vterrors.ToGRPCError(err)
	}
	splits, vtgErr := vtgateservice.CallCorrectSplitQuery(
		vtg.server,
		request.UseSplitQueryV2,
		ctx,
		request.Keyspace,
		string(request.Query.Sql),
		bv,
		request.SplitColumn,
		request.SplitCount,
		request.NumRowsPerQueryPart,
		request.Algorithm)
	if vtgErr != nil {
		return nil, vterrors.ToGRPCError(vtgErr)
	}
	return &vtgatepb.SplitQueryResponse{
		Splits: splits,
	}, nil
}
Exemple #3
0
func testUpdateStreamError(t *testing.T, conn tabletconn.TabletConn, f *FakeQueryService) {
	t.Log("testUpdateStreamError")
	f.HasError = true
	testErrorHelper(t, f, "UpdateStream", func(ctx context.Context) error {
		f.ErrorWait = make(chan struct{})
		ctx = callerid.NewContext(ctx, TestCallerID, TestVTGateCallerID)
		stream, err := conn.UpdateStream(ctx, TestTarget, UpdateStreamPosition, UpdateStreamTimestamp)
		if err != nil {
			t.Fatalf("UpdateStream failed: %v", err)
		}
		qr, err := stream.Recv()
		if err != nil {
			t.Fatalf("UpdateStream failed: cannot read result1: %v", err)
		}
		if !reflect.DeepEqual(*qr, UpdateStreamStreamEvent1) {
			t.Errorf("Unexpected result1 from UpdateStream: got %v wanted %v", qr, UpdateStreamStreamEvent1)
		}
		// signal to the server that the first result has been received
		close(f.ErrorWait)
		// After 1 result, we expect to get an error (no more results).
		qr, err = stream.Recv()
		if err == nil {
			t.Fatalf("UpdateStream channel wasn't closed")
		}
		return err
	})
	f.HasError = false
}
Exemple #4
0
// ExecuteBatch is part of the queryservice.QueryServer interface
func (q *query) ExecuteBatch(ctx context.Context, request *pb.ExecuteBatchRequest) (response *pb.ExecuteBatchResponse, err error) {
	defer q.server.HandlePanic(&err)
	ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx),
		request.EffectiveCallerId,
		request.ImmediateCallerId,
	)
	reply := new(proto.QueryResultList)
	bql, err := proto.Proto3ToBoundQueryList(request.Queries)
	if err != nil {
		return nil, tabletserver.ToGRPCError(err)
	}
	if err := q.server.ExecuteBatch(ctx, request.Target, &proto.QueryList{
		Queries:       bql,
		SessionId:     request.SessionId,
		AsTransaction: request.AsTransaction,
		TransactionId: request.TransactionId,
	}, reply); err != nil {
		return nil, tabletserver.ToGRPCError(err)
	}
	results, err := proto.QueryResultListToProto3(reply.List)
	if err != nil {
		return nil, tabletserver.ToGRPCError(err)
	}
	return &pb.ExecuteBatchResponse{Results: results}, nil
}
Exemple #5
0
// ExecuteEntityIds is the RPC version of vtgateservice.VTGateService method
func (vtg *VTGateP3) ExecuteEntityIds(ctx context.Context, request *pb.ExecuteEntityIdsRequest, response *pb.ExecuteEntityIdsResponse) (err error) {
	defer vtg.server.HandlePanic(&err)
	ctx, cancel := context.WithDeadline(ctx, time.Now().Add(*rpcTimeout))
	defer cancel()
	ctx = callerid.NewContext(ctx,
		request.CallerId,
		callerid.NewImmediateCallerID("bsonp3 client"))
	reply := new(proto.QueryResult)
	executeErr := vtg.server.ExecuteEntityIds(ctx,
		string(request.Query.Sql),
		tproto.Proto3ToBindVariables(request.Query.BindVariables),
		request.Keyspace,
		request.EntityColumnName,
		request.EntityKeyspaceIds,
		request.TabletType,
		proto.ProtoToSession(request.Session),
		request.NotInTransaction,
		reply)
	if executeErr == nil {
		response.Error = vtgate.RPCErrorToVtRPCError(reply.Err)
		response.Result = mproto.QueryResultToProto3(reply.Result)
		response.Session = proto.SessionToProto(reply.Session)
	}
	return vterrors.ToJSONError(executeErr)
}
Exemple #6
0
// StreamExecute is part of the queryservice.QueryServer interface
func (q *query) StreamExecute(request *pb.StreamExecuteRequest, stream pbs.Query_StreamExecuteServer) (err error) {
	defer q.server.HandlePanic(&err)
	ctx := callerid.NewContext(callinfo.GRPCCallInfo(stream.Context()),
		request.EffectiveCallerId,
		request.ImmediateCallerId,
	)
	bv, err := proto.Proto3ToBindVariables(request.Query.BindVariables)
	if err != nil {
		return tabletserver.ToGRPCError(err)
	}
	if err := q.server.StreamExecute(ctx, request.Target, &proto.Query{
		Sql:           request.Query.Sql,
		BindVariables: bv,
		SessionId:     request.SessionId,
	}, func(reply *mproto.QueryResult) error {
		result, err := mproto.QueryResultToProto3(reply)
		if err != nil {
			return err
		}
		return stream.Send(&pb.StreamExecuteResponse{Result: result})
	}); err != nil {
		return tabletserver.ToGRPCError(err)
	}
	return nil
}
Exemple #7
0
// StreamExecuteKeyRanges2 is the RPC version of
// vtgateservice.VTGateService method
func (vtg *VTGateP3) StreamExecuteKeyRanges2(ctx context.Context, request *pb.StreamExecuteKeyRangesRequest, sendReply func(interface{}) error) (err error) {
	defer vtg.server.HandlePanic(&err)
	ctx = callerid.NewContext(ctx,
		request.CallerId,
		callerid.NewImmediateCallerID("gorpc client"))
	vtgErr := vtg.server.StreamExecuteKeyRanges(ctx,
		string(request.Query.Sql),
		tproto.Proto3ToBindVariables(request.Query.BindVariables),
		request.Keyspace,
		request.KeyRanges,
		request.TabletType,
		func(reply *proto.QueryResult) error {
			return sendReply(&pb.StreamExecuteKeyRangesResponse{
				Error:  vtgate.VtGateErrorToVtRPCError(nil, reply.Error),
				Result: mproto.QueryResultToProto3(reply.Result),
			})
		})
	if vtgErr == nil {
		return nil
	}
	if *vtgate.RPCErrorOnlyInReply {
		// If there was an app error, send a QueryResult back with it.
		// 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(&pb.StreamExecuteKeyRangesResponse{
			Error: vtgate.VtGateErrorToVtRPCError(vtgErr, ""),
		})
	}
	return vtgErr
}
Exemple #8
0
// ExecuteKeyspaceIds is the RPC version of vtgateservice.VTGateService method
func (vtg *VTGate) ExecuteKeyspaceIds(ctx context.Context, request *pb.ExecuteKeyspaceIdsRequest) (response *pb.ExecuteKeyspaceIdsResponse, err error) {
	defer vtg.server.HandlePanic(&err)
	ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx),
		request.CallerId,
		callerid.NewImmediateCallerID("grpc client"))
	reply := new(proto.QueryResult)
	bv, err := tproto.Proto3ToBindVariables(request.Query.BindVariables)
	if err != nil {
		return nil, vterrors.ToGRPCError(err)
	}
	executeErr := vtg.server.ExecuteKeyspaceIds(ctx,
		string(request.Query.Sql),
		bv,
		request.Keyspace,
		request.KeyspaceIds,
		request.TabletType,
		request.Session,
		request.NotInTransaction,
		reply)
	response = &pb.ExecuteKeyspaceIdsResponse{
		Error: vtgate.RPCErrorToVtRPCError(reply.Err),
	}
	if executeErr != nil {
		return nil, vterrors.ToGRPCError(executeErr)
	}
	response.Result = sqltypes.ResultToProto3(reply.Result)
	response.Session = reply.Session
	return response, nil
}
Exemple #9
0
// SplitQuery is part of the queryservice.QueryServer interface
func (q *query) SplitQuery(ctx context.Context, request *pb.SplitQueryRequest) (response *pb.SplitQueryResponse, err error) {
	defer q.server.HandlePanic(&err)
	ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx),
		request.EffectiveCallerId,
		request.ImmediateCallerId,
	)
	reply := &proto.SplitQueryResult{}
	bq, err := proto.Proto3ToBoundQuery(request.Query)
	if err != nil {
		return nil, tabletserver.ToGRPCError(err)
	}
	if err := q.server.SplitQuery(ctx, request.Target, &proto.SplitQueryRequest{
		Query:       *bq,
		SplitColumn: request.SplitColumn,
		SplitCount:  int(request.SplitCount),
		SessionID:   request.SessionId,
	}, reply); err != nil {
		return nil, tabletserver.ToGRPCError(err)
	}
	qs, err := proto.QuerySplitsToProto3(reply.Queries)
	if err != nil {
		return nil, tabletserver.ToGRPCError(err)
	}
	return &pb.SplitQueryResponse{Queries: qs}, nil
}
Exemple #10
0
// StreamExecuteKeyRanges2 is the RPC version of
// vtgateservice.VTGateService method
func (vtg *VTGate) StreamExecuteKeyRanges2(ctx context.Context, request *gorpcvtgatecommon.KeyRangeQuery, 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.StreamExecuteKeyRanges(ctx,
		request.Sql,
		request.BindVariables,
		request.Keyspace,
		request.KeyRanges,
		request.TabletType,
		func(value *sqltypes.Result) error {
			return sendReply(&gorpcvtgatecommon.QueryResult{
				Result: value,
			})
		})
	if vtgErr == nil {
		return nil
	}

	// If there was an app error, send a QueryResult back with it.
	return sendReply(&gorpcvtgatecommon.QueryResult{
		Err: vterrors.RPCErrFromVtError(vtgErr),
	})
}
Exemple #11
0
func testStreamExecuteError(t *testing.T, conn tabletconn.TabletConn, fake *FakeQueryService) {
	ctx := context.Background()
	ctx = callerid.NewContext(ctx, testCallerID, testVTGateCallerID)
	stream, errFunc, err := conn.StreamExecute(ctx, streamExecuteQuery, streamExecuteBindVars, streamExecuteTransactionID)
	if err != nil {
		t.Fatalf("StreamExecute failed: %v", err)
	}
	qr, ok := <-stream
	if !ok {
		t.Fatalf("StreamExecute failed: cannot read result1")
	}
	if len(qr.Rows) == 0 {
		qr.Rows = nil
	}
	if !reflect.DeepEqual(*qr, streamExecuteQueryResult1) {
		t.Errorf("Unexpected result1 from StreamExecute: got %v wanted %v", qr, streamExecuteQueryResult1)
	}
	// signal to the server that the first result has been received
	close(fake.errorWait)
	// After 1 result, we expect to get an error (no more results).
	qr, ok = <-stream
	if ok {
		t.Fatalf("StreamExecute channel wasn't closed")
	}
	err = errFunc()
	verifyError(t, err, "StreamExecute")
}
Exemple #12
0
// Execute is part of the queryservice.QueryServer interface
func (q *query) Execute(ctx context.Context, request *pb.ExecuteRequest) (response *pb.ExecuteResponse, err error) {
	defer q.server.HandlePanic(&err)
	ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx),
		request.EffectiveCallerId,
		request.ImmediateCallerId,
	)
	reply := new(mproto.QueryResult)
	bv, err := proto.Proto3ToBindVariables(request.Query.BindVariables)
	if err != nil {
		return nil, tabletserver.ToGRPCError(err)
	}
	if err := q.server.Execute(ctx, request.Target, &proto.Query{
		Sql:           request.Query.Sql,
		BindVariables: bv,
		SessionId:     request.SessionId,
		TransactionId: request.TransactionId,
	}, reply); err != nil {
		return nil, tabletserver.ToGRPCError(err)
	}
	result, err := mproto.QueryResultToProto3(reply)
	if err != nil {
		return nil, tabletserver.ToGRPCError(err)
	}
	return &pb.ExecuteResponse{Result: result}, nil
}
Exemple #13
0
// ExecuteBatchShards is the RPC version of vtgateservice.VTGateService method
func (vtg *VTGate) ExecuteBatchShards(ctx context.Context, request *pb.ExecuteBatchShardsRequest) (response *pb.ExecuteBatchShardsResponse, err error) {
	defer vtg.server.HandlePanic(&err)
	ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx),
		request.CallerId,
		callerid.NewImmediateCallerID("grpc client"))
	reply := new(proto.QueryResultList)
	executeErr := vtg.server.ExecuteBatchShards(ctx,
		proto.ProtoToBoundShardQueries(request.Queries),
		request.TabletType,
		request.AsTransaction,
		proto.ProtoToSession(request.Session),
		reply)
	response = &pb.ExecuteBatchShardsResponse{
		Error: vtgate.VtGateErrorToVtRPCError(executeErr, reply.Error),
	}
	if executeErr == nil {
		response.Results = tproto.QueryResultListToProto3(reply.List)
		response.Session = proto.SessionToProto(reply.Session)
		return response, nil
	}
	if *vtgate.RPCErrorOnlyInReply {
		return response, nil
	}
	return nil, executeErr
}
Exemple #14
0
func testStreamExecute(t *testing.T, conn tabletconn.TabletConn, f *FakeQueryService) {
	t.Log("testStreamExecute")
	ctx := context.Background()
	ctx = callerid.NewContext(ctx, TestCallerID, TestVTGateCallerID)
	stream, err := conn.StreamExecute(ctx, TestTarget, StreamExecuteQuery, StreamExecuteBindVars)
	if err != nil {
		t.Fatalf("StreamExecute failed: %v", err)
	}
	qr, err := stream.Recv()
	if err != nil {
		t.Fatalf("StreamExecute failed: cannot read result1: %v", err)
	}
	if len(qr.Rows) == 0 {
		qr.Rows = nil
	}
	if !reflect.DeepEqual(*qr, StreamExecuteQueryResult1) {
		t.Errorf("Unexpected result1 from StreamExecute: got %v wanted %v", qr, StreamExecuteQueryResult1)
	}
	qr, err = stream.Recv()
	if err != nil {
		t.Fatalf("StreamExecute failed: cannot read result2: %v", err)
	}
	if len(qr.Fields) == 0 {
		qr.Fields = nil
	}
	if !reflect.DeepEqual(*qr, StreamExecuteQueryResult2) {
		t.Errorf("Unexpected result2 from StreamExecute: got %v wanted %v", qr, StreamExecuteQueryResult2)
	}
	qr, err = stream.Recv()
	if err != io.EOF {
		t.Fatalf("StreamExecute errFunc failed: %v", err)
	}
}
Exemple #15
0
func testStreamExecuteError(t *testing.T, conn tabletconn.TabletConn, f *FakeQueryService) {
	t.Log("testStreamExecuteError")
	f.HasError = true
	testErrorHelper(t, f, "StreamExecute", func(ctx context.Context) error {
		f.ErrorWait = make(chan struct{})
		ctx = callerid.NewContext(ctx, TestCallerID, TestVTGateCallerID)
		stream, err := conn.StreamExecute(ctx, TestTarget, StreamExecuteQuery, StreamExecuteBindVars)
		if err != nil {
			t.Fatalf("StreamExecute failed: %v", err)
		}
		qr, err := stream.Recv()
		if err != nil {
			t.Fatalf("StreamExecute failed: cannot read result1: %v", err)
		}
		if len(qr.Rows) == 0 {
			qr.Rows = nil
		}
		if !reflect.DeepEqual(*qr, StreamExecuteQueryResult1) {
			t.Errorf("Unexpected result1 from StreamExecute: got %v wanted %v", qr, StreamExecuteQueryResult1)
		}
		// signal to the server that the first result has been received
		close(f.ErrorWait)
		// After 1 result, we expect to get an error (no more results).
		qr, err = stream.Recv()
		if err == nil {
			t.Fatalf("StreamExecute channel wasn't closed")
		}
		return err
	})
	f.HasError = false
}
Exemple #16
0
// StreamExecute is part of the queryservice.QueryServer interface
func (q *query) StreamExecute(request *pb.StreamExecuteRequest, stream pbs.Query_StreamExecuteServer) (err error) {
	defer q.server.HandlePanic(&err)
	ctx := callerid.NewContext(callinfo.GRPCCallInfo(stream.Context()),
		request.GetEffectiveCallerId(),
		request.GetImmediateCallerId(),
	)
	seErr := q.server.StreamExecute(ctx, &proto.Query{
		Sql:           string(request.Query.Sql),
		BindVariables: proto.Proto3ToBindVariables(request.Query.BindVariables),
		SessionId:     request.SessionId,
	}, func(reply *mproto.QueryResult) error {
		return stream.Send(&pb.StreamExecuteResponse{
			Result: mproto.QueryResultToProto3(reply),
		})
	})
	if seErr != nil {
		response := &pb.StreamExecuteResponse{
			Error: tabletserver.TabletErrorToRPCError(seErr),
		}
		if err := stream.Send(response); err != nil {
			return err
		}
	}
	return nil
}
Exemple #17
0
// StreamExecuteKeyRanges2 is the RPC version of
// vtgateservice.VTGateService method
func (vtg *VTGate) StreamExecuteKeyRanges2(ctx context.Context, request *proto.KeyRangeQuery, 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.StreamExecuteKeyRanges(ctx,
		request.Sql,
		request.BindVariables,
		request.Keyspace,
		key.KeyRangesToProto(request.KeyRanges),
		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
}
Exemple #18
0
// SplitQuery is part of the queryservice.QueryServer interface
func (q *query) SplitQuery(ctx context.Context, request *querypb.SplitQueryRequest) (response *querypb.SplitQueryResponse, err error) {
	defer q.server.HandlePanic(&err)
	ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx),
		request.EffectiveCallerId,
		request.ImmediateCallerId,
	)

	bq, err := querytypes.Proto3ToBoundQuery(request.Query)
	if err != nil {
		return nil, vterrors.ToGRPCError(err)
	}
	splits := []querytypes.QuerySplit{}
	splits, err = queryservice.CallCorrectSplitQuery(
		q.server,
		request.UseSplitQueryV2,
		ctx,
		request.Target,
		bq.Sql,
		bq.BindVariables,
		request.SplitColumn,
		request.SplitCount,
		request.NumRowsPerQueryPart,
		request.Algorithm)
	if err != nil {
		return nil, vterrors.ToGRPCError(err)
	}
	qs, err := querytypes.QuerySplitsToProto3(splits)
	if err != nil {
		return nil, vterrors.ToGRPCError(err)
	}
	return &querypb.SplitQueryResponse{Queries: qs}, nil
}
Exemple #19
0
// BeginExecuteBatch is part of the queryservice.QueryServer interface
func (q *query) BeginExecuteBatch(ctx context.Context, request *querypb.BeginExecuteBatchRequest) (response *querypb.BeginExecuteBatchResponse, err error) {
	defer q.server.HandlePanic(&err)
	ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx),
		request.EffectiveCallerId,
		request.ImmediateCallerId,
	)
	bql, err := querytypes.Proto3ToBoundQueryList(request.Queries)
	if err != nil {
		return nil, vterrors.ToGRPCError(err)
	}

	results, transactionID, err := q.server.BeginExecuteBatch(ctx, request.Target, bql, request.AsTransaction, request.Options)
	if err != nil {
		// if we have a valid transactionID, return the error in-band
		if transactionID != 0 {
			return &querypb.BeginExecuteBatchResponse{
				Error:         vterrors.VtRPCErrorFromVtError(err),
				TransactionId: transactionID,
			}, nil
		}
		return nil, vterrors.ToGRPCError(err)
	}
	return &querypb.BeginExecuteBatchResponse{
		Results:       sqltypes.ResultsToProto3(results),
		TransactionId: transactionID,
	}, nil
}
Exemple #20
0
// BeginExecute is part of the queryservice.QueryServer interface
func (q *query) BeginExecute(ctx context.Context, request *querypb.BeginExecuteRequest) (response *querypb.BeginExecuteResponse, err error) {
	defer q.server.HandlePanic(&err)
	ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx),
		request.EffectiveCallerId,
		request.ImmediateCallerId,
	)
	bv, err := querytypes.Proto3ToBindVariables(request.Query.BindVariables)
	if err != nil {
		return nil, vterrors.ToGRPCError(err)
	}

	result, transactionID, err := q.server.BeginExecute(ctx, request.Target, request.Query.Sql, bv)
	if err != nil {
		// if we have a valid transactionID, return the error in-band
		if transactionID != 0 {
			return &querypb.BeginExecuteResponse{
				Error:         vterrors.VtRPCErrorFromVtError(err),
				TransactionId: transactionID,
			}, nil
		}
		return nil, vterrors.ToGRPCError(err)
	}
	return &querypb.BeginExecuteResponse{
		Result:        sqltypes.ResultToProto3(result),
		TransactionId: transactionID,
	}, nil
}
Exemple #21
0
// ExecuteKeyspaceIds is the RPC version of vtgateservice.VTGateService method
func (vtg *VTGateP3) ExecuteKeyspaceIds(ctx context.Context, request *pb.ExecuteKeyspaceIdsRequest, response *pb.ExecuteKeyspaceIdsResponse) (err error) {
	defer vtg.server.HandlePanic(&err)
	ctx, cancel := context.WithDeadline(ctx, time.Now().Add(*rpcTimeout))
	defer cancel()
	ctx = callerid.NewContext(ctx,
		request.CallerId,
		callerid.NewImmediateCallerID("gorpc client"))
	reply := &proto.QueryResult{}
	vtgErr := vtg.server.ExecuteKeyspaceIds(ctx,
		string(request.Query.Sql),
		tproto.Proto3ToBindVariables(request.Query.BindVariables),
		request.Keyspace,
		request.KeyspaceIds,
		request.TabletType,
		proto.ProtoToSession(request.Session),
		request.NotInTransaction,
		reply)
	response.Error = vtgate.VtGateErrorToVtRPCError(vtgErr, reply.Error)
	response.Result = mproto.QueryResultToProto3(reply.Result)
	response.Session = proto.SessionToProto(reply.Session)
	if *vtgate.RPCErrorOnlyInReply {
		return nil
	}
	return vtgErr
}
Exemple #22
0
// StreamExecute2 should not be used by anything other than tests.
// It will eventually replace Rollback, but it breaks compatibility with older clients.
// Once all clients are upgraded, it can be replaced.
func (sq *SqlQuery) StreamExecute2(ctx context.Context, req *proto.StreamExecuteRequest, sendReply func(reply interface{}) error) (err error) {
	defer sq.server.HandlePanic(&err)
	if req == nil || req.Query == nil {
		return nil
	}
	ctx = callerid.NewContext(ctx,
		callerid.GoRPCEffectiveCallerID(req.EffectiveCallerID),
		callerid.GoRPCImmediateCallerID(req.ImmediateCallerID),
	)
	tErr := sq.server.StreamExecute(callinfo.RPCWrapCallInfo(ctx), proto.TargetToProto3(req.Target), req.Query, func(reply *mproto.QueryResult) error {
		return sendReply(reply)
	})
	if tErr == nil {
		return nil
	}
	if *tabletserver.RPCErrorOnlyInReply {
		// If there was an app error, send a QueryResult back with it.
		qr := new(mproto.QueryResult)
		tabletserver.AddTabletErrorToQueryResult(tErr, 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 tErr
}
Exemple #23
0
// ExecuteKeyspaceIds is the RPC version of vtgateservice.VTGateService method
func (vtg *VTGate) ExecuteKeyspaceIds(ctx context.Context, request *pb.ExecuteKeyspaceIdsRequest) (response *pb.ExecuteKeyspaceIdsResponse, err error) {
	defer vtg.server.HandlePanic(&err)
	ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx),
		request.CallerId,
		callerid.NewImmediateCallerID("grpc client"))
	reply := new(proto.QueryResult)
	executeErr := vtg.server.ExecuteKeyspaceIds(ctx,
		string(request.Query.Sql),
		tproto.Proto3ToBindVariables(request.Query.BindVariables),
		request.Keyspace,
		key.ProtoToKeyspaceIds(request.KeyspaceIds),
		request.TabletType,
		proto.ProtoToSession(request.Session),
		request.NotInTransaction,
		reply)
	response = &pb.ExecuteKeyspaceIdsResponse{
		Error: vtgate.VtGateErrorToVtRPCError(executeErr, reply.Error),
	}
	if executeErr == nil {
		response.Result = mproto.QueryResultToProto3(reply.Result)
		response.Session = proto.SessionToProto(reply.Session)
		return response, nil
	}
	if *vtgate.RPCErrorOnlyInReply {
		return response, nil
	}
	return nil, executeErr
}
Exemple #24
0
func testStreamExecute2(t *testing.T, conn tabletconn.TabletConn) {
	ctx := context.Background()
	ctx = callerid.NewContext(ctx, testCallerID, testVTGateCallerID)
	stream, errFunc, err := conn.StreamExecute2(ctx, streamExecuteQuery, streamExecuteBindVars, streamExecuteTransactionID)
	if err != nil {
		t.Fatalf("StreamExecute2 failed: %v", err)
	}
	qr, ok := <-stream
	if !ok {
		t.Fatalf("StreamExecute2 failed: cannot read result1")
	}
	if len(qr.Rows) == 0 {
		qr.Rows = nil
	}
	if !reflect.DeepEqual(*qr, streamExecuteQueryResult1) {
		t.Errorf("Unexpected result1 from StreamExecute2: got %v wanted %v", qr, streamExecuteQueryResult1)
	}
	qr, ok = <-stream
	if !ok {
		t.Fatalf("StreamExecute2 failed: cannot read result2")
	}
	if len(qr.Fields) == 0 {
		qr.Fields = nil
	}
	if !reflect.DeepEqual(*qr, streamExecuteQueryResult2) {
		t.Errorf("Unexpected result2 from StreamExecute2: got %v wanted %v", qr, streamExecuteQueryResult2)
	}
	qr, ok = <-stream
	if ok {
		t.Fatalf("StreamExecute2 channel wasn't closed")
	}
	if err := errFunc(); err != nil {
		t.Fatalf("StreamExecute2 errFunc failed: %v", err)
	}
}
Exemple #25
0
// ExecuteBatchKeyspaceIds is the RPC version of
// vtgateservice.VTGateService method
func (vtg *VTGate) ExecuteBatchKeyspaceIds(ctx context.Context, request *pb.ExecuteBatchKeyspaceIdsRequest) (response *pb.ExecuteBatchKeyspaceIdsResponse, err error) {
	defer vtg.server.HandlePanic(&err)
	ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx),
		request.CallerId,
		callerid.NewImmediateCallerID("grpc client"))
	reply := new(proto.QueryResultList)
	bq, err := proto.ProtoToBoundKeyspaceIdQueries(request.Queries)
	if err != nil {
		return nil, vterrors.ToGRPCError(err)
	}
	executeErr := vtg.server.ExecuteBatchKeyspaceIds(ctx,
		bq,
		request.TabletType,
		request.AsTransaction,
		request.Session,
		reply)
	response = &pb.ExecuteBatchKeyspaceIdsResponse{
		Error: vtgate.RPCErrorToVtRPCError(reply.Err),
	}
	if executeErr != nil {
		return nil, vterrors.ToGRPCError(executeErr)
	}
	response.Results = tproto.QueryResultListToProto3(reply.List)
	response.Session = reply.Session
	return response, nil
}
Exemple #26
0
func testRollback2(t *testing.T, conn tabletconn.TabletConn) {
	ctx := context.Background()
	ctx = callerid.NewContext(ctx, testCallerID, testVTGateCallerID)
	err := conn.Rollback2(ctx, rollbackTransactionID)
	if err != nil {
		t.Fatalf("Rollback2 failed: %v", err)
	}
}
Exemple #27
0
func testCommit(t *testing.T, conn tabletconn.TabletConn) {
	ctx := context.Background()
	ctx = callerid.NewContext(ctx, testCallerID, testVTGateCallerID)
	err := conn.Commit(ctx, commitTransactionID)
	if err != nil {
		t.Fatalf("Commit failed: %v", err)
	}
}
Exemple #28
0
func testRollback(t *testing.T, conn tabletconn.TabletConn, f *FakeQueryService) {
	t.Log("testRollback")
	ctx := context.Background()
	ctx = callerid.NewContext(ctx, TestCallerID, TestVTGateCallerID)
	err := conn.Rollback(ctx, TestTarget, RollbackTransactionID)
	if err != nil {
		t.Fatalf("Rollback failed: %v", err)
	}
}
func TestQueryExecutorTableAclDryRun(t *testing.T) {
	aclName := fmt.Sprintf("simpleacl-test-%d", rand.Int63())
	tableacl.Register(aclName, &simpleacl.Factory{})
	tableacl.SetDefaultACL(aclName)
	db := setUpQueryExecutorTest()
	query := "select * from test_table limit 1000"
	want := &mproto.QueryResult{
		Fields:       getTestTableFields(),
		RowsAffected: 0,
		Rows:         [][]sqltypes.Value{},
	}
	db.AddQuery(query, want)
	db.AddQuery("select * from test_table where 1 != 1", &mproto.QueryResult{
		Fields: getTestTableFields(),
	})

	username := "******"
	callerID := &querypb.VTGateCallerID{
		Username: username,
	}
	ctx := callerid.NewContext(context.Background(), nil, callerID)

	config := &tableaclpb.Config{
		TableGroups: []*tableaclpb.TableGroupSpec{{
			Name:                 "group02",
			TableNamesOrPrefixes: []string{"test_table"},
			Readers:              []string{"u1"},
		}},
	}

	if err := tableacl.InitFromProto(config); err != nil {
		t.Fatalf("unable to load tableacl config, error: %v", err)
	}

	tableACLStatsKey := strings.Join([]string{
		"test_table",
		"group02",
		planbuilder.PLAN_PASS_SELECT.String(),
		username,
	}, ".")
	// enable Config.StrictTableAcl
	sqlQuery := newTestSQLQuery(ctx, enableRowCache|enableSchemaOverrides|enableStrict|enableStrictTableAcl)
	sqlQuery.qe.enableTableAclDryRun = true
	qre := newTestQueryExecutor(ctx, sqlQuery, query, 0)
	defer sqlQuery.disallowQueries()
	checkPlanID(t, planbuilder.PLAN_PASS_SELECT, qre.plan.PlanId)
	beforeCount := sqlQuery.qe.tableaclPseudoDenied.Counters.Counts()[tableACLStatsKey]
	// query should fail because current user do not have read permissions
	_, err := qre.Execute()
	if err != nil {
		t.Fatalf("qre.Execute() = %v, want: nil", err)
	}
	afterCount := sqlQuery.qe.tableaclPseudoDenied.Counters.Counts()[tableACLStatsKey]
	if afterCount-beforeCount != 1 {
		t.Fatalf("table acl pseudo denied count should increase by one. got: %d, want: %d", afterCount, beforeCount+1)
	}
}
Exemple #30
0
// 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, func(value *proto.QueryResult) error {
		return sendReply(value)
	})
}