func NewPercentileAggregator(_ *parser.SelectQuery, value *parser.Value, defaultValue *parser.Value) (Aggregator, error) { if len(value.Elems) != 2 { return nil, common.NewQueryError(common.WrongNumberOfArguments, "function percentile() requires exactly two arguments") } if value.Elems[0].Type == parser.ValueWildcard { return nil, common.NewQueryError(common.WrongNumberOfArguments, "wildcard cannot be used with percentile") } percentile, err := strconv.ParseFloat(value.Elems[1].Name, 64) if err != nil || percentile <= 0 || percentile >= 100 { return nil, common.NewQueryError(common.InvalidArgument, "function percentile() requires a numeric second argument between 0 and 100") } wrappedDefaultValue, err := wrapDefaultValue(defaultValue) if err != nil { return nil, err } functionName := "percentile" if value.Alias != "" { functionName = value.Alias } return &PercentileAggregator{ AbstractAggregator: AbstractAggregator{ value: value.Elems[0], }, functionName: functionName, percentile: percentile, defaultValue: wrappedDefaultValue, }, nil }
func NewTopOrBottomAggregator(name string, v *parser.Value, isTop bool, defaultValue *parser.Value) (Aggregator, error) { if len(v.Elems) != 2 { return nil, common.NewQueryError(common.WrongNumberOfArguments, fmt.Sprintf("function %s() requires at exactly 2 arguments", name)) } if v.Elems[1].Type != parser.ValueInt { return nil, common.NewQueryError(common.InvalidArgument, fmt.Sprintf("function %s() second parameter expect int", name)) } wrappedDefaultValue, err := wrapDefaultValue(defaultValue) if err != nil { return nil, err } limit, err := strconv.ParseInt(v.Elems[1].Name, 10, 64) if err != nil { return nil, err } if limit < 1 { return nil, common.NewQueryError(common.InvalidArgument, fmt.Sprintf("function %s() second parameter must be > 0", name)) } return &TopOrBottomAggregator{ AbstractAggregator: AbstractAggregator{ value: v.Elems[0], }, name: name, isTop: isTop, defaultValue: wrappedDefaultValue, alias: v.Alias, limit: limit}, nil }
func NewCountAggregator(q *parser.SelectQuery, v *parser.Value, defaultValue *parser.Value) (Aggregator, error) { if len(v.Elems) != 1 { return nil, common.NewQueryError(common.WrongNumberOfArguments, "function count() requires exactly one argument") } if v.Elems[0].Type == parser.ValueWildcard { return nil, common.NewQueryError(common.InvalidArgument, "function count() doesn't work with wildcards") } wrappedDefaultValue, err := wrapDefaultValue(defaultValue) if err != nil { return nil, err } if v.Elems[0].Type != parser.ValueSimpleName { innerName := strings.ToLower(v.Elems[0].Name) init := registeredAggregators[innerName] if init == nil { return nil, common.NewQueryError(common.InvalidArgument, fmt.Sprintf("Unknown function %s", innerName)) } inner, err := init(q, v.Elems[0], defaultValue) if err != nil { return nil, err } return NewCompositeAggregator(&CountAggregator{AbstractAggregator{}, wrappedDefaultValue, v.Alias}, inner) } return &CountAggregator{AbstractAggregator{}, wrappedDefaultValue, v.Alias}, nil }
func NewAggregatorEngine(query *parser.SelectQuery, next Processor) (*AggregatorEngine, error) { ae := &AggregatorEngine{ next: next, seriesStates: make(map[string]*SeriesState), ascending: query.Ascending, } var err error ae.duration, ae.irregularInterval, err = query.GetGroupByClause().GetGroupByTime() if err != nil { return nil, err } ae.aggregators = []Aggregator{} for _, value := range query.GetColumnNames() { if !value.IsFunctionCall() { continue } lowerCaseName := strings.ToLower(value.Name) initializer := registeredAggregators[lowerCaseName] if initializer == nil { return nil, common.NewQueryError(common.InvalidArgument, fmt.Sprintf("Unknown function %s", value.Name)) } aggregator, err := initializer(query, value, query.GetGroupByClause().FillValue) if err != nil { return nil, common.NewQueryError(common.InvalidArgument, fmt.Sprintf("%s", err)) } ae.aggregators = append(ae.aggregators, aggregator) } for _, elem := range query.GetGroupByClause().Elems { if elem.IsFunctionCall() { continue } ae.elems = append(ae.elems, elem) } ae.isFillQuery = query.GetGroupByClause().FillWithZero // This is a special case for issue #426. If the start time is // specified and there's a group by clause and fill with zero, then // we need to fill the entire range from start time to end time if query.IsStartTimeSpecified() && ae.duration != nil && ae.isFillQuery { ae.startTimeSpecified = true ae.startTime = query.GetStartTime().Truncate(*ae.duration).UnixNano() / 1000 ae.endTime = query.GetEndTime().Truncate(*ae.duration).UnixNano() / 1000 } ae.initializeFields() return ae, nil }
// Process responses from the given channel. Returns true if // processing should stop for other channels. False otherwise. func (p *MergeChannelProcessor) processChannel(channel <-chan *protocol.Response) bool { for response := range channel { log4go.Debug("%s received %s", p, response) switch rt := response.GetType(); rt { // all these types end the stream case protocol.Response_HEARTBEAT, protocol.Response_END_STREAM: p.e <- nil return false case protocol.Response_ERROR: err := common.NewQueryError(common.InvalidArgument, response.GetErrorMessage()) p.e <- err return false case protocol.Response_QUERY: for _, s := range response.MultiSeries { log4go.Debug("Yielding to %s: %s", p.next.Name(), s) _, err := p.next.Yield(s) if err != nil { p.e <- err return true } } default: panic(fmt.Errorf("Unknown response type: %s", rt)) } } panic(errors.New("Reached end of method")) }
func NewMedianAggregator(_ *parser.SelectQuery, value *parser.Value, defaultValue *parser.Value) (Aggregator, error) { if len(value.Elems) != 1 { return nil, common.NewQueryError(common.WrongNumberOfArguments, "function median() requires exactly one argument") } wrappedDefaultValue, err := wrapDefaultValue(defaultValue) if err != nil { return nil, err } functionName := "median" if value.Alias != "" { functionName = value.Alias } aggregator := &PercentileAggregator{ AbstractAggregator: AbstractAggregator{ value: value.Elems[0], }, functionName: functionName, percentile: 50.0, defaultValue: wrappedDefaultValue, alias: value.Alias, } return aggregator, nil }
func NewModeAggregator(_ *parser.SelectQuery, value *parser.Value, defaultValue *parser.Value) (Aggregator, error) { if len(value.Elems) < 1 { return nil, common.NewQueryError(common.WrongNumberOfArguments, "function mode() requires at least one argument") } // TODO: Mode can in fact take two argument, the second specifies // the "size", but it's not clear if size is set to 2 whether to // return at least 2 elements, or return the most common values and // the second most common values. The difference will be apparent if // the data set is multimodel and there are two most common // values. In the first case, the two most common values will be // returned, but in the second case the two most common values and // the second most common values will be returned if len(value.Elems) > 1 { return nil, common.NewQueryError(common.WrongNumberOfArguments, "function mode() takes at most one arguments") } size := 1 if len(value.Elems) == 2 { switch value.Elems[1].Type { case parser.ValueInt: var err error size, err = strconv.Atoi(value.Elems[1].Name) if err != nil { return nil, common.NewQueryError(common.InvalidArgument, "Cannot parse %s into an int", value.Elems[1].Name) } default: return nil, common.NewQueryError(common.InvalidArgument, "Cannot parse %s into a int", value.Elems[1].Name) } } wrappedDefaultValue, err := wrapDefaultValue(defaultValue) if err != nil { return nil, err } return &ModeAggregator{ AbstractAggregator: AbstractAggregator{ value: value.Elems[0], }, defaultValue: wrappedDefaultValue, alias: value.Alias, size: size, }, nil }
func HashPassword(password string) ([]byte, error) { if length := len(password); length < 4 || length > 56 { return nil, common.NewQueryError(common.InvalidArgument, "Password must be more than 4 and less than 56 characters") } // The second arg is the cost of the hashing, higher is slower but makes it harder // to brute force, since it will be really slow and impractical return bcrypt.GenerateFromPassword([]byte(password), 10) }
func NewStandardDeviationAggregator(q *parser.SelectQuery, v *parser.Value, defaultValue *parser.Value) (Aggregator, error) { if len(v.Elems) != 1 { return nil, common.NewQueryError(common.WrongNumberOfArguments, "function stddev() requires exactly one argument") } if v.Elems[0].Type == parser.ValueWildcard { return nil, common.NewQueryError(common.InvalidArgument, "function stddev() doesn't work with wildcards") } value, err := wrapDefaultValue(defaultValue) if err != nil { return nil, err } return &StandardDeviationAggregator{ AbstractAggregator: AbstractAggregator{ value: v.Elems[0], }, defaultValue: value, alias: v.Alias, }, nil }
func NewMeanAggregator(_ *parser.SelectQuery, value *parser.Value, defaultValue *parser.Value) (Aggregator, error) { if len(value.Elems) != 1 { return nil, common.NewQueryError(common.WrongNumberOfArguments, "function mean() requires exactly one argument") } wrappedDefaultValue, err := wrapDefaultValue(defaultValue) if err != nil { return nil, err } return &MeanAggregator{ AbstractAggregator: AbstractAggregator{ value: value.Elems[0], }, defaultValue: wrappedDefaultValue, alias: value.Alias, }, nil }
func NewFirstOrLastAggregator(name string, v *parser.Value, isFirst bool, defaultValue *parser.Value) (Aggregator, error) { if len(v.Elems) != 1 { return nil, common.NewQueryError(common.WrongNumberOfArguments, fmt.Sprintf("function %s() requires exactly one argument", name)) } wrappedDefaultValue, err := wrapDefaultValue(defaultValue) if err != nil { return nil, err } if v.Alias != "" { name = v.Alias } return &FirstOrLastAggregator{ AbstractAggregator: AbstractAggregator{ value: v.Elems[0], }, name: name, isFirst: isFirst, defaultValue: wrappedDefaultValue, }, nil }
func NewCumulativeArithmeticAggregator(name string, value *parser.Value, initialValue float64, defaultValue *parser.Value, operation Operation) (Aggregator, error) { if len(value.Elems) != 1 { return nil, common.NewQueryError(common.WrongNumberOfArguments, "function max() requires only one argument") } wrappedDefaultValue, err := wrapDefaultValue(defaultValue) if err != nil { return nil, err } if value.Alias != "" { name = value.Alias } return &CumulativeArithmeticAggregator{ AbstractAggregator: AbstractAggregator{ value: value.Elems[0], }, name: name, operation: operation, initialValue: initialValue, defaultValue: wrappedDefaultValue, }, nil }
func NewHistogramAggregator(q *parser.SelectQuery, v *parser.Value, defaultValue *parser.Value) (Aggregator, error) { if len(v.Elems) < 1 { return nil, common.NewQueryError(common.WrongNumberOfArguments, "function histogram() requires at least one arguments") } if len(v.Elems) > 4 { return nil, common.NewQueryError(common.WrongNumberOfArguments, "function histogram() takes at most four arguments") } if v.Elems[0].Type == parser.ValueWildcard { return nil, common.NewQueryError(common.InvalidArgument, "function histogram() doesn't work with wildcards") } bucketSize := 1.0 bucketStart := 0.0 explicitBucketStart := false bucketStop := 0.0 bucketStopIdx := -1 if len(v.Elems) > 1 { switch v.Elems[1].Type { case parser.ValueInt, parser.ValueFloat: var err error bucketSize, err = strconv.ParseFloat(v.Elems[1].Name, 64) if err != nil { return nil, common.NewQueryError(common.InvalidArgument, "Cannot parse %s into a float", v.Elems[1].Name) } default: return nil, common.NewQueryError(common.InvalidArgument, "Cannot parse %s into a float", v.Elems[1].Name) } if len(v.Elems) > 2 { switch v.Elems[2].Type { case parser.ValueInt, parser.ValueFloat: var err error bucketStart, err = strconv.ParseFloat(v.Elems[2].Name, 64) explicitBucketStart = true if err != nil { return nil, common.NewQueryError(common.InvalidArgument, "Cannot parse %s into a float", v.Elems[2].Name) } default: return nil, common.NewQueryError(common.InvalidArgument, "Cannot parse %s into a float", v.Elems[2].Name) } if len(v.Elems) == 4 { switch v.Elems[3].Type { case parser.ValueInt, parser.ValueFloat: var err error bucketStop, err = strconv.ParseFloat(v.Elems[3].Name, 64) bucketStopIdx = int(math.Floor((bucketStop - bucketStart) / bucketSize)) if err != nil { return nil, common.NewQueryError(common.InvalidArgument, "Cannot parse %s into a float", v.Elems[3].Name) } default: return nil, common.NewQueryError(common.InvalidArgument, "Cannot parse %s into a float", v.Elems[3].Name) } } } } columnNames := []string{"bucket_start", "count"} if v.Alias != "" { columnNames[0] = fmt.Sprintf("%s_bucket_start", v.Alias) columnNames[1] = fmt.Sprintf("%s_count", v.Alias) } return &HistogramAggregator{ AbstractAggregator: AbstractAggregator{ value: v.Elems[0], }, bucketSize: bucketSize, bucketStart: bucketStart, explicitBucketStart: explicitBucketStart, bucketStopIdx: bucketStopIdx, columnNames: columnNames, }, nil }