// 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 }
// 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 }
// 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 }
// 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 }
// ExecuteBatch is part of tabletconn.TabletConn // We need to copy the bind variables as tablet server will change them. func (itc *internalTabletConn) ExecuteBatch(ctx context.Context, queries []tproto.BoundQuery, asTransaction bool, transactionID int64) (*tproto.QueryResultList, error) { q := make([]tproto.BoundQuery, len(queries)) for i, query := range queries { bv, err := tproto.BindVariablesToProto3(query.BindVariables) if err != nil { return nil, err } bindVars, err := tproto.Proto3ToBindVariables(bv) if err != nil { return nil, err } q[i].Sql = query.Sql q[i].BindVariables = bindVars } reply := &tproto.QueryResultList{} if err := itc.tablet.qsc.QueryService().ExecuteBatch(ctx, &querypb.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, &tproto.QueryList{ Queries: q, AsTransaction: asTransaction, TransactionId: transactionID, }, reply); err != nil { return nil, tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(err)) } return reply, nil }
// StreamExecute is part of tabletconn.TabletConn // We need to copy the bind variables as tablet server will change them. func (itc *internalTabletConn) StreamExecute(ctx context.Context, query string, bindVars map[string]interface{}, transactionID int64) (<-chan *mproto.QueryResult, tabletconn.ErrFunc, error) { bindVars = tproto.Proto3ToBindVariables(tproto.BindVariablesToProto3(bindVars)) result := make(chan *mproto.QueryResult, 10) var finalErr error go func() { finalErr = itc.tablet.qsc.QueryService().StreamExecute(ctx, &pbq.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, &tproto.Query{ Sql: query, BindVariables: bindVars, TransactionId: transactionID, }, func(reply *mproto.QueryResult) error { result <- reply return nil }) // the client will only access finalErr after the // channel is closed, and then it's already set. close(result) }() return result, func() error { return tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(finalErr)) }, nil }
// StreamExecute is part of tabletconn.TabletConn // We need to copy the bind variables as tablet server will change them. func (itc *internalTabletConn) StreamExecute(ctx context.Context, query string, bindVars map[string]interface{}, transactionID int64) (<-chan *sqltypes.Result, tabletconn.ErrFunc, error) { bv, err := querytypes.BindVariablesToProto3(bindVars) if err != nil { return nil, nil, err } bindVars, err = querytypes.Proto3ToBindVariables(bv) if err != nil { return nil, nil, err } result := make(chan *sqltypes.Result, 10) var finalErr error go func() { finalErr = itc.tablet.qsc.QueryService().StreamExecute(ctx, &querypb.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, query, bindVars, 0, func(reply *sqltypes.Result) error { // We need to deep-copy the reply before returning, // because the underlying buffers are reused. result <- reply.Copy() return nil }) // the client will only access finalErr after the // channel is closed, and then it's already set. close(result) }() return result, func() error { return tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(finalErr)) }, nil }
// StreamHealth is part of tabletconn.TabletConn func (itc *internalTabletConn) StreamHealth(ctx context.Context) (tabletconn.StreamHealthReader, error) { result := make(chan *querypb.StreamHealthResponse, 10) id, err := itc.tablet.qsc.QueryService().StreamHealthRegister(result) if err != nil { return nil, err } var finalErr error go func() { select { case <-ctx.Done(): } // We populate finalErr before closing the channel. // The consumer first waits on the channel closure, // then read finalErr finalErr = itc.tablet.qsc.QueryService().StreamHealthUnregister(id) finalErr = tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(finalErr)) close(result) }() return &streamHealthReader{ c: result, err: &finalErr, }, nil }
// SplitQueryV2 is part of tabletconn.TabletConn // TODO(erez): Rename to SplitQuery once the migration to SplitQuery V2 is done. func (itc *internalTabletConn) SplitQueryV2( ctx context.Context, query querytypes.BoundQuery, splitColumns []string, splitCount int64, numRowsPerQueryPart int64, algorithm querypb.SplitQueryRequest_Algorithm) ([]querytypes.QuerySplit, error) { splits, err := itc.tablet.qsc.QueryService().SplitQueryV2( ctx, &querypb.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, query.Sql, query.BindVariables, splitColumns, splitCount, numRowsPerQueryPart, algorithm) if err != nil { return nil, tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(err)) } return splits, nil }
// Rollback is part of tabletconn.TabletConn func (itc *internalTabletConn) Rollback(ctx context.Context, transactionID int64) error { err := itc.tablet.qsc.QueryService().Rollback(ctx, &querypb.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, 0, transactionID) return tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(err)) }
// ExecuteBatch is part of the queryservice.QueryServer interface func (q *query) ExecuteBatch(ctx context.Context, request *querypb.ExecuteBatchRequest) (response *querypb.ExecuteBatchResponse, 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, tabletserver.ToGRPCError(err) } results, err := q.server.ExecuteBatch(ctx, request.Target, bql, request.SessionId, request.AsTransaction, request.TransactionId) if err != nil { return nil, tabletserver.ToGRPCError(err) } return &querypb.ExecuteBatchResponse{ Results: sqltypes.ResultsToProto3(results), }, nil }
// Execute is part of the queryservice.QueryServer interface func (q *query) Execute(ctx context.Context, request *querypb.ExecuteRequest) (response *querypb.ExecuteResponse, 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, tabletserver.ToGRPCError(err) } result, err := q.server.Execute(ctx, request.Target, request.Query.Sql, bv, request.SessionId, request.TransactionId) if err != nil { return nil, tabletserver.ToGRPCError(err) } return &querypb.ExecuteResponse{ Result: sqltypes.ResultToProto3(result), }, nil }
// Commit is part of tabletconn.TabletConn func (itc *internalTabletConn) Commit(ctx context.Context, transactionID int64) error { err := itc.tablet.qsc.QueryService().Commit(ctx, &pbq.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, &tproto.Session{ TransactionId: transactionID, }) return tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(err)) }
// StreamExecute is part of the queryservice.QueryServer interface func (q *query) StreamExecute(request *querypb.StreamExecuteRequest, stream queryservicepb.Query_StreamExecuteServer) (err error) { defer q.server.HandlePanic(&err) ctx := callerid.NewContext(callinfo.GRPCCallInfo(stream.Context()), request.EffectiveCallerId, request.ImmediateCallerId, ) bv, err := querytypes.Proto3ToBindVariables(request.Query.BindVariables) if err != nil { return tabletserver.ToGRPCError(err) } if err := q.server.StreamExecute(ctx, request.Target, request.Query.Sql, bv, request.SessionId, func(reply *sqltypes.Result) error { return stream.Send(&querypb.StreamExecuteResponse{ Result: sqltypes.ResultToProto3(reply), }) }); err != nil { return tabletserver.ToGRPCError(err) } return nil }
// Begin is part of tabletconn.TabletConn func (itc *internalTabletConn) Begin(ctx context.Context) (int64, error) { transactionID, err := itc.tablet.qsc.QueryService().Begin(ctx, &querypb.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, 0) if err != nil { return 0, tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(err)) } return transactionID, nil }
// Begin is part of tabletconn.TabletConn func (itc *internalTabletConn) Begin(ctx context.Context) (transactionID int64, err error) { result := &tproto.TransactionInfo{} if err := itc.tablet.qsc.QueryService().Begin(ctx, &pbq.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, &tproto.Session{}, result); err != nil { return 0, tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(err)) } return result.TransactionId, nil }
// Commit is part of the queryservice.QueryServer interface func (q *query) Commit(ctx context.Context, request *querypb.CommitRequest) (response *querypb.CommitResponse, err error) { defer q.server.HandlePanic(&err) ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx), request.EffectiveCallerId, request.ImmediateCallerId, ) if err := q.server.Commit(ctx, request.Target, request.SessionId, request.TransactionId); err != nil { return nil, tabletserver.ToGRPCError(err) } return &querypb.CommitResponse{}, nil }
// 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, tabletserver.ToGRPCError(err) } splits, err := q.server.SplitQuery(ctx, request.Target, bq.Sql, bq.BindVariables, request.SplitColumn, request.SplitCount, request.SessionId) if err != nil { return nil, tabletserver.ToGRPCError(err) } qs, err := querytypes.QuerySplitsToProto3(splits) if err != nil { return nil, tabletserver.ToGRPCError(err) } return &querypb.SplitQueryResponse{Queries: qs}, nil }
// GetSessionId is part of the queryservice.QueryServer interface func (q *query) GetSessionId(ctx context.Context, request *querypb.GetSessionIdRequest) (response *querypb.GetSessionIdResponse, err error) { defer q.server.HandlePanic(&err) sessionID, err := q.server.GetSessionId(request.Keyspace, request.Shard) if err != nil { return nil, tabletserver.ToGRPCError(err) } return &querypb.GetSessionIdResponse{ SessionId: sessionID, }, nil }
// Rollback is part of the queryservice.QueryServer interface func (q *query) Rollback(ctx context.Context, request *pb.RollbackRequest) (response *pb.RollbackResponse, err error) { defer q.server.HandlePanic(&err) ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx), request.EffectiveCallerId, request.ImmediateCallerId, ) if err := q.server.Rollback(ctx, request.Target, &proto.Session{ SessionId: request.SessionId, TransactionId: request.TransactionId, }); err != nil { return nil, tabletserver.ToGRPCError(err) } return &pb.RollbackResponse{}, nil }
// SplitQuery is part of tabletconn.TabletConn func (itc *internalTabletConn) SplitQuery(ctx context.Context, query tproto.BoundQuery, splitColumn string, splitCount int) ([]tproto.QuerySplit, error) { reply := &tproto.SplitQueryResult{} if err := itc.tablet.qsc.QueryService().SplitQuery(ctx, &pbq.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, &tproto.SplitQueryRequest{ Query: query, SplitColumn: splitColumn, SplitCount: splitCount, }, reply); err != nil { return nil, tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(err)) } return reply.Queries, nil }
// GetSessionId is part of the queryservice.QueryServer interface func (q *query) GetSessionId(ctx context.Context, request *pb.GetSessionIdRequest) (response *pb.GetSessionIdResponse, err error) { defer q.server.HandlePanic(&err) sessionInfo := new(proto.SessionInfo) if err := q.server.GetSessionId(&proto.SessionParams{ Keyspace: request.Keyspace, Shard: request.Shard, }, sessionInfo); err != nil { return nil, tabletserver.ToGRPCError(err) } return &pb.GetSessionIdResponse{ SessionId: sessionInfo.SessionId, }, nil }
// Execute is part of tabletconn.TabletConn // We need to copy the bind variables as tablet server will change them. func (itc *internalTabletConn) Execute(ctx context.Context, query string, bindVars map[string]interface{}, transactionID int64) (*mproto.QueryResult, error) { bindVars = tproto.Proto3ToBindVariables(tproto.BindVariablesToProto3(bindVars)) reply := &mproto.QueryResult{} if err := itc.tablet.qsc.QueryService().Execute(ctx, &pbq.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, &tproto.Query{ Sql: query, BindVariables: bindVars, TransactionId: transactionID, }, reply); err != nil { return nil, tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(err)) } return reply, nil }
// Begin is part of the queryservice.QueryServer interface func (q *query) Begin(ctx context.Context, request *querypb.BeginRequest) (response *querypb.BeginResponse, err error) { defer q.server.HandlePanic(&err) ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx), request.EffectiveCallerId, request.ImmediateCallerId, ) txInfo := new(proto.TransactionInfo) if err := q.server.Begin(ctx, request.Target, &proto.Session{ SessionId: request.SessionId, }, txInfo); err != nil { return nil, tabletserver.ToGRPCError(err) } return &querypb.BeginResponse{ TransactionId: txInfo.TransactionId, }, nil }
// Execute is part of tabletconn.TabletConn // We need to copy the bind variables as tablet server will change them. func (itc *internalTabletConn) Execute(ctx context.Context, query string, bindVars map[string]interface{}, transactionID int64) (*sqltypes.Result, error) { bv, err := querytypes.BindVariablesToProto3(bindVars) if err != nil { return nil, err } bindVars, err = querytypes.Proto3ToBindVariables(bv) if err != nil { return nil, err } reply, err := itc.tablet.qsc.QueryService().Execute(ctx, &querypb.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, query, bindVars, 0, transactionID) if err != nil { return nil, tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(err)) } return reply, nil }
// StreamHealth is part of tabletconn.TabletConn func (itc *internalTabletConn) StreamHealth(ctx context.Context) (<-chan *querypb.StreamHealthResponse, tabletconn.ErrFunc, error) { result := make(chan *querypb.StreamHealthResponse, 10) id, err := itc.tablet.qsc.QueryService().StreamHealthRegister(result) if err != nil { return nil, nil, err } var finalErr error go func() { select { case <-ctx.Done(): } finalErr = itc.tablet.qsc.QueryService().StreamHealthUnregister(id) close(result) }() return result, func() error { return tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(finalErr)) }, nil }
// ExecuteBatch is part of tabletconn.TabletConn // We need to copy the bind variables as tablet server will change them. func (itc *internalTabletConn) ExecuteBatch(ctx context.Context, queries []querytypes.BoundQuery, asTransaction bool, transactionID int64) ([]sqltypes.Result, error) { q := make([]querytypes.BoundQuery, len(queries)) for i, query := range queries { bv, err := querytypes.BindVariablesToProto3(query.BindVariables) if err != nil { return nil, err } bindVars, err := querytypes.Proto3ToBindVariables(bv) if err != nil { return nil, err } q[i].Sql = query.Sql q[i].BindVariables = bindVars } results, err := itc.tablet.qsc.QueryService().ExecuteBatch(ctx, &querypb.Target{ Keyspace: itc.tablet.keyspace, Shard: itc.tablet.shard, TabletType: itc.tablet.tabletType, }, q, 0, asTransaction, transactionID) if err != nil { return nil, tabletconn.TabletErrorFromGRPC(tabletserver.ToGRPCError(err)) } return results, nil }