func handleStdinMode() { unqlParser := tuql.NewTuqlParser(*debugTokens, *debugGrammar, *crashHard) naivePlanner := naiveplanner.NewNaivePlanner() naiveOptimizer := naiveoptimizer.NewNaiveOptimizer() nullOptimizer := nulloptimizer.NewNullOptimizer() reader := bufio.NewReader(os.Stdin) for { line, err := reader.ReadString('\n') if err != nil { break } if line == "" { continue } query, err := unqlParser.Parse(line) if err != nil { log.Printf("%v", err) } else { if *debugGrammar { log.Printf("Query is: %#v", query) } if query.WasParsedSuccessfully() { // check to make sure the query is semantically valid err := query.Validate() if err != nil { log.Printf("%v", err) } else { plans := naivePlanner.Plan(*query) if plans != nil { var plan planner.Plan if *disableOptimizer { plan = nullOptimizer.Optimize(plans) } else { plan = naiveOptimizer.Optimize(plans) } if query.IsExplainOnly { result := plan.Explain() if err != nil { log.Printf("Error: %v", err) } else { FormatChannelOutput(result, os.Stdout) } } else { result := plan.Run() if err != nil { log.Printf("Error: %v", err) } else { FormatChannelOutput(result, os.Stdout) } } } } } } } }
func (np *NaivePlanner) Plan(query parser.Select) []planner.Plan { result := planner.Plan{} var last_in_pipeline planner.PlanPipelineComponent // from for _, datasource := range query.From { // look up the data source ds := datasources.NewDataSourceWithName(datasource.Def) if ds == nil { log.Printf("No such datasource exists") return nil } ds.SetName(datasource.Def) ds.SetAs(datasource.As) // handle any overs var lastthis planner.PlanPipelineComponent lastthis = ds for _, v := range datasource.Overs { over := planner.NewOttoOver() over.SetPath(v.Path) over.SetAs(v.As) over.SetSource(lastthis) lastthis = over } if last_in_pipeline != nil { joiner := planner.NewOttoCartesianProductJoiner() joiner.SetLeftSource(last_in_pipeline) joiner.SetRightSource(lastthis) last_in_pipeline = joiner } else { last_in_pipeline = lastthis } } // where if query.Where != nil { ottoFilter := planner.NewOttoFilter() ottoFilter.SetSource(last_in_pipeline) ottoFilter.SetFilter(query.Where) last_in_pipeline = ottoFilter } if query.IsAggregateQuery { // in an aggregate query we sometimes need to collect stats // on fields that we're not aggregating on // the full list will be the symbols from the SELECT clause // invalid entries should have been detected earlier // (columns not in the group by clause and not inside an aggregate function) stat_fields := make([]string, 0) if query.Sel != nil { stat_fields = query.Sel.SymbolsReferenced() } // group by if query.Groupby != nil { ottoGrouper := planner.NewOttoGrouper() ottoGrouper.SetGroupByWithStatsFields(query.Groupby, stat_fields) ottoGrouper.SetSource(last_in_pipeline) last_in_pipeline = ottoGrouper } else { // easy to overlook, but if they use aggregate functions // this is aggregate query, even though they didnt explicitly // have a group by clause, we should apply a default group by // clause that groups everything ottoGrouper := planner.NewOttoGrouper() ottoGrouper.SetGroupByWithStatsFields(parser.ExpressionList{parser.NewBoolLiteral(true)}, stat_fields) ottoGrouper.SetSource(last_in_pipeline) last_in_pipeline = ottoGrouper } // having if query.Having != nil { ottoFilter := planner.NewOttoFilter() ottoFilter.SetSource(last_in_pipeline) ottoFilter.SetFilter(query.Having) last_in_pipeline = ottoFilter } } // order by if query.Orderby != nil { ottoOrderer := planner.NewOttoOrderer() ottoOrderer.SetSource(last_in_pipeline) ottoOrderer.SetOrderBy(query.Orderby) last_in_pipeline = ottoOrderer } // offset if query.Offset != nil { offset := planner.NewOttoOffsetter() offset.SetOffset(query.Offset) offset.SetSource(last_in_pipeline) last_in_pipeline = offset } // limit if query.Limit != nil { limit := planner.NewOttoLimitter() limit.SetLimit(query.Limit) limit.SetSource(last_in_pipeline) last_in_pipeline = limit } // select if query.Sel != nil { ottoSelecter := planner.NewOttoSelecter() ottoSelecter.SetSource(last_in_pipeline) ottoSelecter.SetSelect(query.Sel) result.Root = ottoSelecter } else { defaultSelecter := planner.NewDefaultSelecter() defaultSelecter.SetSource(last_in_pipeline) result.Root = defaultSelecter } return []planner.Plan{result} }
func handleInteractiveMode() { unqlParser := tuql.NewTuqlParser(*debugTokens, *debugGrammar, *crashHard) naivePlanner := naiveplanner.NewNaivePlanner() naiveOptimizer := naiveoptimizer.NewNaiveOptimizer() nullOptimizer := nulloptimizer.NewNullOptimizer() currentUser, err := user.Current() if err != nil { log.Printf("Unable to determine home directory, history file disabled") } var liner = liner.NewLiner() defer liner.Close() LoadHistory(liner, currentUser) go signalCatcher(liner) for { line, err := liner.Prompt("tuq> ") if err != nil { break } if line == "" { continue } UpdateHistory(liner, currentUser, line) query, err := unqlParser.Parse(line) if err != nil { log.Printf("%v", err) } else { if *debugGrammar { log.Printf("Query is: %#v", query) } if query.WasParsedSuccessfully() { // check to make sure the query is semantically valid err := query.Validate() if err != nil { log.Printf("%v", err) } else { plans := naivePlanner.Plan(*query) if plans != nil { var plan planner.Plan if *disableOptimizer { plan = nullOptimizer.Optimize(plans) } else { plan = naiveOptimizer.Optimize(plans) } if query.IsExplainOnly { result := plan.Explain() if err != nil { log.Printf("Error: %v", err) } else { FormatChannelOutput(result, os.Stdout) } } else { result := plan.Run() if err != nil { log.Printf("Error: %v", err) } else { FormatChannelOutput(result, os.Stdout) } } } } } } } }
func doPost(w http.ResponseWriter, req *http.Request) { d := json.NewDecoder(req.Body) request := map[string]interface{}{} err := d.Decode(&request) if err != nil { w.WriteHeader(500) fmt.Fprintf(w, "Error parsing request JSON: %v", err) return } line, ok := request["query"].(string) if !ok { w.WriteHeader(500) fmt.Fprintf(w, "Error reading query string: %v", err) return } unqlParser := tuql.NewTuqlParser(false, false, *crashHard) naiveOptimizer := naiveoptimizer.NewNaiveOptimizer() nullOptimizer := nulloptimizer.NewNullOptimizer() query, err := unqlParser.Parse(line) if err != nil { w.WriteHeader(500) fmt.Fprintf(w, "Error parsing query string: %v", err) return } else { if query.WasParsedSuccessfully() { // check to make sure the query is semantically valid err := query.Validate() if err != nil { w.WriteHeader(500) fmt.Fprintf(w, "Error validating query string: %v", err) return } else { naivePlanner := naiveplanner.NewNaivePlanner() plans := naivePlanner.Plan(*query) if plans != nil { var plan planner.Plan if *disableOptimizer { plan = nullOptimizer.Optimize(plans) } else { plan = naiveOptimizer.Optimize(plans) } if query.IsExplainOnly { result := plan.Explain() if err != nil { w.WriteHeader(500) fmt.Fprintf(w, "Error explaining query string: %v", err) return } else { FormatChannelOutput(result, w) } } else { result := plan.Run() if err != nil { w.WriteHeader(500) fmt.Fprintf(w, "Error running query string: %v", err) return } else { FormatChannelOutput(result, w) } } } } } else { w.WriteHeader(500) fmt.Fprintf(w, "Error parsing query string: %v", err) return } } }