// ExecuteKeyRanges executes a non-streaming query based on the specified keyranges. func (vtg *VTGate) ExecuteKeyRanges(context interface{}, query *proto.KeyRangeQuery, reply *proto.QueryResult) error { shards, err := mapKeyRangesToShards( vtg.scatterConn.toposerv, vtg.scatterConn.cell, query.Keyspace, query.TabletType, query.KeyRanges) if err != nil { return err } qr, err := vtg.scatterConn.Execute( context, query.Sql, query.BindVariables, query.Keyspace, shards, query.TabletType, NewSafeSession(query.Session)) if err == nil { proto.PopulateQueryResult(qr, reply) } else { reply.Error = err.Error() log.Errorf("ExecuteKeyRange: %v, query: %+v", err, query) } reply.Session = query.Session return nil }
// ExecuteEntityIds excutes a non-streaming query based on given KeyspaceId map. func (vtg *VTGate) ExecuteEntityIds(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, entityColumnName string, entityKeyspaceIDs []*pbg.ExecuteEntityIdsRequest_EntityId, tabletType pb.TabletType, session *proto.Session, notInTransaction bool, reply *proto.QueryResult) error { startTime := time.Now() statsKey := []string{"ExecuteEntityIds", keyspace, strings.ToLower(tabletType.String())} defer vtg.timings.Record(statsKey, startTime) x := vtg.inFlight.Add(1) defer vtg.inFlight.Add(-1) if 0 < vtg.maxInFlight && vtg.maxInFlight < x { return errTooManyInFlight } qr, err := vtg.resolver.ExecuteEntityIds(ctx, sql, bindVariables, keyspace, entityColumnName, entityKeyspaceIDs, tabletType, session, notInTransaction) if err == nil { reply.Result = qr vtg.rowsReturned.Add(statsKey, int64(len(qr.Rows))) } else { query := map[string]interface{}{ "Sql": sql, "BindVariables": bindVariables, "Keyspace": keyspace, "EntityColumnName": entityColumnName, "EntityKeyspaceIDs": entityKeyspaceIDs, "TabletType": strings.ToLower(tabletType.String()), "Session": session, "NotInTransaction": notInTransaction, } reply.Error = handleExecuteError(err, statsKey, query, vtg.logExecuteEntityIds).Error() reply.Err = rpcErrFromVtGateError(err) } reply.Session = session return nil }
// ExecuteEntityIds excutes a non-streaming query based on given KeyspaceId map. func (vtg *VTGate) ExecuteEntityIds(context context.Context, query *proto.EntityIdsQuery, reply *proto.QueryResult) (err error) { defer handlePanic(&err) startTime := time.Now() statsKey := []string{"ExecuteEntityIds", query.Keyspace, string(query.TabletType)} defer vtg.timings.Record(statsKey, startTime) x := vtg.inFlight.Add(1) defer vtg.inFlight.Add(-1) if 0 < vtg.maxInFlight && vtg.maxInFlight < x { return ErrTooManyInFlight } qr, err := vtg.resolver.ExecuteEntityIds(context, query) if err == nil { reply.Result = qr } else { reply.Error = err.Error() if strings.Contains(reply.Error, errDupKey) { infoErrors.Add("DupKey", 1) } else { normalErrors.Add(statsKey, 1) vtg.logExecuteEntityIds.Errorf("%v, query: %+v", err, query) } } reply.Session = query.Session return nil }
// Execute executes a non-streaming query by routing based on the values in the query. func (vtg *VTGate) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType pb.TabletType, session *proto.Session, notInTransaction bool, reply *proto.QueryResult) error { startTime := time.Now() statsKey := []string{"Execute", "Any", strings.ToLower(tabletType.String())} defer vtg.timings.Record(statsKey, startTime) x := vtg.inFlight.Add(1) defer vtg.inFlight.Add(-1) if 0 < vtg.maxInFlight && vtg.maxInFlight < x { return errTooManyInFlight } qr, err := vtg.router.Execute(ctx, sql, bindVariables, tabletType, session, notInTransaction) if err == nil { reply.Result = qr vtg.rowsReturned.Add(statsKey, int64(len(qr.Rows))) } else { query := map[string]interface{}{ "Sql": sql, "BindVariables": bindVariables, "TabletType": strings.ToLower(tabletType.String()), "Session": session, "NotInTransaction": notInTransaction, } reply.Error = handleExecuteError(err, statsKey, query, vtg.logExecute) } reply.Session = session return nil }
// ExecuteKeyRanges executes a non-streaming query based on the specified keyranges. func (vtg *VTGate) ExecuteKeyRanges(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, keyRanges []*pb.KeyRange, tabletType pb.TabletType, session *proto.Session, notInTransaction bool, reply *proto.QueryResult) error { startTime := time.Now() statsKey := []string{"ExecuteKeyRanges", keyspace, strings.ToLower(tabletType.String())} defer vtg.timings.Record(statsKey, startTime) x := vtg.inFlight.Add(1) defer vtg.inFlight.Add(-1) if 0 < vtg.maxInFlight && vtg.maxInFlight < x { return errTooManyInFlight } sql = sqlannotation.AddFilteredReplicationUnfriendlyIfDML(sql) qr, err := vtg.resolver.ExecuteKeyRanges(ctx, sql, bindVariables, keyspace, keyRanges, tabletType, session, notInTransaction) if err == nil { reply.Result = qr vtg.rowsReturned.Add(statsKey, int64(len(qr.Rows))) } else { query := map[string]interface{}{ "Sql": sql, "BindVariables": bindVariables, "Keyspace": keyspace, "KeyRanges": keyRanges, "TabletType": strings.ToLower(tabletType.String()), "Session": session, "NotInTransaction": notInTransaction, } reply.Error = handleExecuteError(err, statsKey, query, vtg.logExecuteKeyRanges).Error() reply.Err = vterrors.RPCErrFromVtError(err) } reply.Session = session return nil }
// ExecuteShard executes a non-streaming query on the specified shards. func (vtg *VTGate) ExecuteShard(ctx context.Context, query *proto.QueryShard, reply *proto.QueryResult) error { startTime := time.Now() statsKey := []string{"ExecuteShard", query.Keyspace, string(query.TabletType)} defer vtg.timings.Record(statsKey, startTime) x := vtg.inFlight.Add(1) defer vtg.inFlight.Add(-1) if 0 < vtg.maxInFlight && vtg.maxInFlight < x { return errTooManyInFlight } qr, err := vtg.resolver.Execute( ctx, query.Sql, query.BindVariables, query.Keyspace, query.TabletType, query.Session, func(keyspace string) (string, []string, error) { return query.Keyspace, query.Shards, nil }, query.NotInTransaction, ) if err == nil { reply.Result = qr vtg.rowsReturned.Add(statsKey, int64(len(qr.Rows))) } else { reply.Error = handleExecuteError(err, statsKey, query, vtg.logExecuteShard) } reply.Session = query.Session return nil }
// ExecuteEntityIds excutes a non-streaming query based on given KeyspaceId map. func (vtg *VTGate) ExecuteEntityIds(context interface{}, query *proto.EntityIdsQuery, reply *proto.QueryResult) error { shardMap, err := mapEntityIdsToShards( vtg.scatterConn.toposerv, vtg.scatterConn.cell, query.Keyspace, query.EntityKeyspaceIdMap, query.TabletType) if err != nil { return err } shards, sqls, bindVars := buildEntityIds(shardMap, query.Sql, query.EntityColumnName, query.BindVariables) qr, err := vtg.scatterConn.ExecuteEntityIds( context, shards, sqls, bindVars, query.Keyspace, query.TabletType, NewSafeSession(query.Session)) if err == nil { proto.PopulateQueryResult(qr, reply) } else { reply.Error = err.Error() log.Errorf("ExecuteEntityIds: %v, query: %+v", err, query) } reply.Session = query.Session return nil }
// ExecuteShard executes a non-streaming query on the specified shards. func (vtg *VTGate) ExecuteShard(context interface{}, query *proto.QueryShard, reply *proto.QueryResult) error { startTime := time.Now() statsKey := []string{"ExecuteShard", query.Keyspace, string(query.TabletType)} defer vtg.timings.Record(statsKey, startTime) qr, err := vtg.resolver.Execute( context, query.Sql, query.BindVariables, query.Keyspace, query.TabletType, query.Session, func(keyspace string) (string, []string, error) { return query.Keyspace, query.Shards, nil }, ) if err == nil { proto.PopulateQueryResult(qr, reply) } else { reply.Error = err.Error() vtg.errors.Add(statsKey, 1) // FIXME(alainjobart): throttle this log entry log.Errorf("ExecuteShard: %v, query: %+v", err, query) } reply.Session = query.Session return nil }
// ExecuteShard executes a non-streaming query on the specified shards. func (vtg *VTGate) ExecuteShard(context context.Context, query *proto.QueryShard, reply *proto.QueryResult) error { startTime := time.Now() statsKey := []string{"ExecuteShard", query.Keyspace, string(query.TabletType)} defer vtg.timings.Record(statsKey, startTime) qr, err := vtg.resolver.Execute( context, query.Sql, query.BindVariables, query.Keyspace, query.TabletType, query.Session, func(keyspace string) (string, []string, error) { return query.Keyspace, query.Shards, nil }, ) if err == nil { reply.Result = qr } else { reply.Error = err.Error() if strings.Contains(reply.Error, errDupKey) { vtg.infoErrors.Add("DupKey", 1) } else { vtg.errors.Add(statsKey, 1) vtg.logExecuteShard.Errorf("%v, query: %+v", err, query) } } reply.Session = query.Session return nil }
// ExecuteEntityIds excutes a non-streaming query based on given KeyspaceId map. func (vtg *VTGate) ExecuteEntityIds(context interface{}, query *proto.EntityIdsQuery, reply *proto.QueryResult) error { qr, err := vtg.resolver.ExecuteEntityIds(context, query) if err == nil { proto.PopulateQueryResult(qr, reply) } else { reply.Error = err.Error() log.Errorf("ExecuteEntityIds: %v, query: %+v", err, query) } reply.Session = query.Session return nil }
// requestToPartialError fills reply for a partial error if requested. // It returns true if a partial error was requested, false otherwise. // This partial error should only be returned by Execute* calls. func requestToPartialError(request string, session *vtgatepb.Session, reply *proto.QueryResult) bool { if !strings.HasPrefix(request, PartialErrorPrefix) { return false } request = strings.TrimPrefix(request, PartialErrorPrefix) parts := strings.Split(request, "/") rpcErr := vterrors.RPCErrFromVtError(trimmedRequestToError(parts[0])) reply.Err = rpcErr reply.Session = session if len(parts) > 1 && parts[1] == "close transaction" { reply.Session.InTransaction = false } return true }
func (c *echoClient) Execute(ctx context.Context, sql string, bindVariables map[string]interface{}, tabletType pb.TabletType, session *proto.Session, notInTransaction bool, reply *proto.QueryResult) error { if strings.HasPrefix(sql, EchoPrefix) { reply.Result = echoQueryResult(map[string]interface{}{ "callerId": callerid.EffectiveCallerIDFromContext(ctx), "query": sql, "bindVars": bindVariables, "tabletType": tabletType, "session": session, "notInTransaction": notInTransaction, }) reply.Session = session return nil } return c.fallbackClient.Execute(ctx, sql, bindVariables, tabletType, session, notInTransaction, reply) }
// ExecuteKeyspaceIds executes a non-streaming query based on the specified keyspace ids. func (vtg *VTGate) ExecuteKeyspaceIds(context interface{}, query *proto.KeyspaceIdQuery, reply *proto.QueryResult) error { startTime := time.Now() statsKey := []string{"ExecuteKeyspaceIds", query.Keyspace, string(query.TabletType)} defer vtg.timings.Record(statsKey, startTime) qr, err := vtg.resolver.ExecuteKeyspaceIds(context, query) if err == nil { proto.PopulateQueryResult(qr, reply) } else { reply.Error = err.Error() vtg.errors.Add(statsKey, 1) vtg.logExecuteKeyspaceIds.Errorf("%v, query: %+v", err, query) } reply.Session = query.Session return nil }
// ExecuteShard executes a non-streaming query on the specified shards. func (vtg *VTGate) ExecuteShard(context *rpcproto.Context, query *proto.QueryShard, reply *proto.QueryResult) error { qr, err := vtg.scatterConn.Execute( query.Sql, query.BindVariables, query.Keyspace, query.Shards, query.TabletType, NewSafeSession(query.Session)) if err == nil { proto.PopulateQueryResult(qr, reply) } else { reply.Error = err.Error() log.Errorf("ExecuteShard: %v, query: %#v", err, query) } reply.Session = query.Session return nil }
// ExecuteEntityIds excutes a non-streaming query based on given KeyspaceId map. func (vtg *VTGate) ExecuteEntityIds(context interface{}, query *proto.EntityIdsQuery, reply *proto.QueryResult) error { startTime := time.Now() statsKey := []string{"ExecuteEntityIds", query.Keyspace, string(query.TabletType)} defer vtg.timings.Record(statsKey, startTime) qr, err := vtg.resolver.ExecuteEntityIds(context, query) if err == nil { proto.PopulateQueryResult(qr, reply) } else { reply.Error = err.Error() vtg.errors.Add(statsKey, 1) // FIXME(alainjobart): throttle this log entry log.Errorf("ExecuteEntityIds: %v, query: %+v", err, query) } reply.Session = query.Session return nil }
func (c *echoClient) ExecuteEntityIds(ctx context.Context, sql string, bindVariables map[string]interface{}, keyspace string, entityColumnName string, entityKeyspaceIDs []*pbg.ExecuteEntityIdsRequest_EntityId, tabletType pb.TabletType, session *pbg.Session, notInTransaction bool, reply *proto.QueryResult) error { if strings.HasPrefix(sql, EchoPrefix) { reply.Result = echoQueryResult(map[string]interface{}{ "callerId": callerid.EffectiveCallerIDFromContext(ctx), "query": sql, "bindVars": bindVariables, "keyspace": keyspace, "entityColumnName": entityColumnName, "entityIds": entityKeyspaceIDs, "tabletType": tabletType, "session": session, "notInTransaction": notInTransaction, }) reply.Session = session return nil } return c.fallbackClient.ExecuteEntityIds(ctx, sql, bindVariables, keyspace, entityColumnName, entityKeyspaceIDs, tabletType, session, notInTransaction, reply) }
// Execute is the RPC version of vtgateservice.VTGateService method func (vtg *VTGate) Execute(ctx context.Context, request *proto.Query, 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")) sessionFromRPC(request.Session) vtgErr := vtg.server.Execute(ctx, request.Sql, request.BindVariables, request.TabletType, request.Session, request.NotInTransaction, reply) reply.Session = sessionToRPC(reply.Session) vtgate.AddVtGateError(vtgErr, &reply.Err) return nil }
// ExecuteEntityIds excutes a non-streaming query based on given KeyspaceId map. func (vtg *VTGate) ExecuteEntityIds(context context.Context, query *proto.EntityIdsQuery, reply *proto.QueryResult) error { startTime := time.Now() statsKey := []string{"ExecuteEntityIds", query.Keyspace, string(query.TabletType)} defer vtg.timings.Record(statsKey, startTime) qr, err := vtg.resolver.ExecuteEntityIds(context, query) if err == nil { reply.Result = qr } else { reply.Error = err.Error() if strings.Contains(reply.Error, errDupKey) { vtg.infoErrors.Add("DupKey", 1) } else { vtg.errors.Add(statsKey, 1) vtg.logExecuteEntityIds.Errorf("%v, query: %+v", err, query) } } reply.Session = query.Session return nil }
// ExecuteShard executes a non-streaming query on the specified shards. func (vtg *VTGate) ExecuteShard(context interface{}, query *proto.QueryShard, reply *proto.QueryResult) error { qr, err := vtg.resolver.Execute( context, query.Sql, query.BindVariables, query.Keyspace, query.TabletType, query.Session, func(keyspace string) ([]string, error) { return query.Shards, nil }, ) if err == nil { proto.PopulateQueryResult(qr, reply) } else { reply.Error = err.Error() log.Errorf("ExecuteShard: %v, query: %+v", err, query) } reply.Session = query.Session return nil }
// ExecuteEntityIds excutes a non-streaming query based on given KeyspaceId map. func (vtg *VTGate) ExecuteEntityIds(ctx context.Context, query *proto.EntityIdsQuery, reply *proto.QueryResult) error { startTime := time.Now() statsKey := []string{"ExecuteEntityIds", query.Keyspace, string(query.TabletType)} defer vtg.timings.Record(statsKey, startTime) x := vtg.inFlight.Add(1) defer vtg.inFlight.Add(-1) if 0 < vtg.maxInFlight && vtg.maxInFlight < x { return errTooManyInFlight } qr, err := vtg.resolver.ExecuteEntityIds(ctx, query) if err == nil { reply.Result = qr vtg.rowsReturned.Add(statsKey, int64(len(qr.Rows))) } else { reply.Error = handleExecuteError(err, statsKey, query, vtg.logExecuteEntityIds) } reply.Session = query.Session return nil }