예제 #1
0
파일: stdin.go 프로젝트: mschoch/tuq
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)
							}
						}

					}
				}

			}
		}
	}

}
예제 #2
0
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}

}
예제 #3
0
파일: interactive.go 프로젝트: mschoch/tuq
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)
							}
						}
					}
				}

			}
		}
	}

}
예제 #4
0
파일: http.go 프로젝트: mschoch/tuq
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
		}
	}
}