func (self *Coordinator) RunQueryWithContext(user common.User, database string, queryString string, p engine.Processor, requestContext *api.RequestContext) (err error) { log.Info("Start Query: db: %s, u: %s, q: %s", database, user.GetName(), queryString) runningQuery := NewRunningQuery(user.GetName(), database, queryString, time.Now(), requestContext.RemoteAddr()) self.monitor.StartQuery(runningQuery) defer func() { self.monitor.EndQuery(runningQuery) }() defer func(t time.Time) { log.Debug("End Query: db: %s, u: %s, q: %s, t: %s", database, user.GetName(), queryString, time.Now().Sub(t)) }(time.Now()) // don't let a panic pass beyond RunQuery defer common.RecoverFunc(database, queryString, nil) q, err := parser.ParseQuery(queryString) if err != nil { return err } for _, query := range q { err := self.runSingleQuery(user, database, query, p) if err != nil { return err } } return nil }
func (self *CoordinatorSuite) TestShouldQuerySequentially(c *C) { end := time.Now().Truncate(24 * time.Hour) start := end.Add(-7 * 24 * time.Hour) shard := cluster.NewShard(1, start, end, "", "", nil) shards := []*cluster.ShardData{shard} coordinator := NewCoordinator(&configuration.Configuration{ ClusterMaxResponseBufferSize: 1000, }, nil, nil) queries := map[string]bool{ "list series": false, "select count(foo) from /.*bar.*/ group by time(1d)": true, "select count(foo) from bar": true, "select foo from bar": true, "select count(foo) from bar group by baz": true, "select count(foo) from bar group by time(1d)": false, "select count(foo) from bar group by time(3d)": true, } for query, result := range queries { fmt.Printf("Testing %s\n", query) parsedQuery, err := parser.ParseQuery(query) c.Assert(err, IsNil) c.Assert(parsedQuery, HasLen, 1) querySpec := parser.NewQuerySpec(nil, "", parsedQuery[0]) c.Assert(coordinator.shouldQuerySequentially(shards, querySpec), Equals, result) } }
func (self *ProtobufRequestHandler) handleQuery(request *protocol.Request, conn net.Conn) { // the query should always parse correctly since it was parsed at the originating server. queries, err := parser.ParseQuery(*request.Query) if err != nil || len(queries) < 1 { log.Error("Error parsing query: ", err) errorMsg := fmt.Sprintf("Cannot find user %s", *request.UserName) response := &protocol.Response{ Type: protocol.Response_ERROR.Enum(), ErrorMessage: &errorMsg, RequestId: request.Id, } self.WriteResponse(conn, response) return } query := queries[0] var user common.User if *request.IsDbUser { user = self.clusterConfig.GetDbUser(*request.Database, *request.UserName) } else { user = self.clusterConfig.GetClusterAdmin(*request.UserName) } if user == nil { errorMsg := fmt.Sprintf("Cannot find user %s", *request.UserName) response := &protocol.Response{ Type: protocol.Response_ERROR.Enum(), ErrorMessage: &errorMsg, RequestId: request.Id, } self.WriteResponse(conn, response) return } shard := self.clusterConfig.GetLocalShardById(*request.ShardId) querySpec := parser.NewQuerySpec(user, *request.Database, query) responseChan := make(chan *protocol.Response) if querySpec.IsDestructiveQuery() { go shard.HandleDestructiveQuery(querySpec, request, responseChan, true) } else { go shard.Query(querySpec, responseChan) } for { response := <-responseChan response.RequestId = request.Id self.WriteResponse(conn, response) switch rt := response.GetType(); rt { case protocol.Response_END_STREAM, protocol.Response_ERROR: return case protocol.Response_QUERY: continue default: panic(fmt.Errorf("Unexpected response type: %s", rt)) } } }
func (self *HttpServer) configureDatabase(w libhttp.ResponseWriter, r *libhttp.Request) { self.tryAsClusterAdmin(w, r, func(u User) (int, interface{}) { databaseConfig := &DatabaseConfig{} decoder := json.NewDecoder(r.Body) err := decoder.Decode(databaseConfig) if err != nil { return libhttp.StatusInternalServerError, err.Error() } database := r.URL.Query().Get(":db") // validate before creating anything for _, queryString := range databaseConfig.ContinuousQueries { q, err := parser.ParseQuery(queryString) if err != nil { return libhttp.StatusBadRequest, err.Error() } for _, query := range q { if !query.IsContinuousQuery() { return libhttp.StatusBadRequest, fmt.Errorf("This query isn't a continuous query. Use 'into'. %s", query.GetQueryString()) } } } // validate shard spaces for _, space := range databaseConfig.Spaces { err := space.Validate(self.clusterConfig, false) if err != nil { return libhttp.StatusBadRequest, err.Error() } } err = self.coordinator.CreateDatabase(u, database) if err != nil { return libhttp.StatusBadRequest, err.Error() } for _, space := range databaseConfig.Spaces { space.Database = database err = self.raftServer.CreateShardSpace(space) if err != nil { return libhttp.StatusInternalServerError, err.Error() } } for _, queryString := range databaseConfig.ContinuousQueries { err := self.coordinator.RunQuery(u, database, queryString, cluster.NilProcessor{}) if err != nil { return libhttp.StatusInternalServerError, err.Error() } } return libhttp.StatusCreated, nil }) }