commit
2409047bb3
|
@ -44,6 +44,14 @@ func init() {
|
|||
registeredAggregators["last"] = NewLastAggregator
|
||||
}
|
||||
|
||||
// used in testing to get a list of all aggregators
|
||||
func GetRegisteredAggregators() (names []string) {
|
||||
for n, _ := range registeredAggregators {
|
||||
names = append(names, n)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type AbstractAggregator struct {
|
||||
Aggregator
|
||||
value *parser.Value
|
||||
|
@ -103,6 +111,7 @@ type StandardDeviationAggregator struct {
|
|||
AbstractAggregator
|
||||
running map[string]map[interface{}]*StandardDeviationRunning
|
||||
defaultValue *protocol.FieldValue
|
||||
alias string
|
||||
}
|
||||
|
||||
func (self *StandardDeviationAggregator) AggregatePoint(series string, group interface{}, p *protocol.Point) error {
|
||||
|
@ -140,6 +149,10 @@ func (self *StandardDeviationAggregator) AggregatePoint(series string, group int
|
|||
}
|
||||
|
||||
func (self *StandardDeviationAggregator) ColumnNames() []string {
|
||||
if self.alias != "" {
|
||||
return []string{self.alias}
|
||||
}
|
||||
|
||||
return []string{"stddev"}
|
||||
}
|
||||
|
||||
|
@ -196,6 +209,7 @@ func NewStandardDeviationAggregator(q *parser.SelectQuery, v *parser.Value, defa
|
|||
},
|
||||
running: make(map[string]map[interface{}]*StandardDeviationRunning),
|
||||
defaultValue: value,
|
||||
alias: v.Alias,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -208,6 +222,7 @@ type DerivativeAggregator struct {
|
|||
firstValues map[string]map[interface{}]*protocol.Point
|
||||
lastValues map[string]map[interface{}]*protocol.Point
|
||||
defaultValue *protocol.FieldValue
|
||||
alias string
|
||||
}
|
||||
|
||||
func (self *DerivativeAggregator) AggregatePoint(series string, group interface{}, p *protocol.Point) error {
|
||||
|
@ -253,6 +268,9 @@ func (self *DerivativeAggregator) AggregatePoint(series string, group interface{
|
|||
}
|
||||
|
||||
func (self *DerivativeAggregator) ColumnNames() []string {
|
||||
if self.alias != "" {
|
||||
return []string{self.alias}
|
||||
}
|
||||
return []string{"derivative"}
|
||||
}
|
||||
|
||||
|
@ -299,6 +317,7 @@ func NewDerivativeAggregator(q *parser.SelectQuery, v *parser.Value, defaultValu
|
|||
firstValues: make(map[string]map[interface{}]*protocol.Point),
|
||||
lastValues: make(map[string]map[interface{}]*protocol.Point),
|
||||
defaultValue: wrappedDefaultValue,
|
||||
alias: v.Alias,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -308,8 +327,9 @@ func NewDerivativeAggregator(q *parser.SelectQuery, v *parser.Value, defaultValu
|
|||
|
||||
type HistogramAggregator struct {
|
||||
AbstractAggregator
|
||||
bucketSize float64
|
||||
histograms map[string]map[interface{}]map[int]int
|
||||
bucketSize float64
|
||||
histograms map[string]map[interface{}]map[int]int
|
||||
columnNames []string
|
||||
}
|
||||
|
||||
func (self *HistogramAggregator) AggregatePoint(series string, group interface{}, p *protocol.Point) error {
|
||||
|
@ -344,7 +364,7 @@ func (self *HistogramAggregator) AggregatePoint(series string, group interface{}
|
|||
}
|
||||
|
||||
func (self *HistogramAggregator) ColumnNames() []string {
|
||||
return []string{"bucket_start", "count"}
|
||||
return self.columnNames
|
||||
}
|
||||
|
||||
func (self *HistogramAggregator) GetValues(series string, group interface{}) [][]*protocol.FieldValue {
|
||||
|
@ -391,12 +411,19 @@ func NewHistogramAggregator(q *parser.SelectQuery, v *parser.Value, defaultValue
|
|||
}
|
||||
}
|
||||
|
||||
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,
|
||||
histograms: make(map[string]map[interface{}]map[int]int),
|
||||
bucketSize: bucketSize,
|
||||
histograms: make(map[string]map[interface{}]map[int]int),
|
||||
columnNames: columnNames,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -407,6 +434,7 @@ func NewHistogramAggregator(q *parser.SelectQuery, v *parser.Value, defaultValue
|
|||
type CountAggregator struct {
|
||||
defaultValue *protocol.FieldValue
|
||||
counts map[string]map[interface{}]int32
|
||||
alias string
|
||||
}
|
||||
|
||||
func (self *CountAggregator) AggregatePoint(series string, group interface{}, p *protocol.Point) error {
|
||||
|
@ -420,6 +448,9 @@ func (self *CountAggregator) AggregatePoint(series string, group interface{}, p
|
|||
}
|
||||
|
||||
func (self *CountAggregator) ColumnNames() []string {
|
||||
if self.alias != "" {
|
||||
return []string{self.alias}
|
||||
}
|
||||
return []string{"count"}
|
||||
}
|
||||
|
||||
|
@ -464,10 +495,10 @@ func NewCountAggregator(q *parser.SelectQuery, v *parser.Value, defaultValue *pa
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewCompositeAggregator(&CountAggregator{wrappedDefaultValue, make(map[string]map[interface{}]int32)}, inner)
|
||||
return NewCompositeAggregator(&CountAggregator{wrappedDefaultValue, make(map[string]map[interface{}]int32), v.Alias}, inner)
|
||||
}
|
||||
|
||||
return &CountAggregator{wrappedDefaultValue, make(map[string]map[interface{}]int32)}, nil
|
||||
return &CountAggregator{wrappedDefaultValue, make(map[string]map[interface{}]int32), v.Alias}, nil
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -537,6 +568,7 @@ type MeanAggregator struct {
|
|||
means map[string]map[interface{}]float64
|
||||
counts map[string]map[interface{}]int
|
||||
defaultValue *protocol.FieldValue
|
||||
alias string
|
||||
}
|
||||
|
||||
func (self *MeanAggregator) AggregatePoint(series string, group interface{}, p *protocol.Point) error {
|
||||
|
@ -574,6 +606,9 @@ func (self *MeanAggregator) AggregatePoint(series string, group interface{}, p *
|
|||
}
|
||||
|
||||
func (self *MeanAggregator) ColumnNames() []string {
|
||||
if self.alias != "" {
|
||||
return []string{self.alias}
|
||||
}
|
||||
return []string{"mean"}
|
||||
}
|
||||
|
||||
|
@ -608,6 +643,7 @@ func NewMeanAggregator(_ *parser.SelectQuery, value *parser.Value, defaultValue
|
|||
means: make(map[string]map[interface{}]float64),
|
||||
counts: make(map[string]map[interface{}]int),
|
||||
defaultValue: wrappedDefaultValue,
|
||||
alias: value.Alias,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -621,15 +657,22 @@ func NewMedianAggregator(_ *parser.SelectQuery, value *parser.Value, defaultValu
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &PercentileAggregator{
|
||||
functionName := "median"
|
||||
if value.Alias != "" {
|
||||
functionName = value.Alias
|
||||
}
|
||||
|
||||
aggregator := &PercentileAggregator{
|
||||
AbstractAggregator: AbstractAggregator{
|
||||
value: value.Elems[0],
|
||||
},
|
||||
functionName: "median",
|
||||
functionName: functionName,
|
||||
percentile: 50.0,
|
||||
float_values: make(map[string]map[interface{}][]float64),
|
||||
defaultValue: wrappedDefaultValue,
|
||||
}, nil
|
||||
alias: value.Alias,
|
||||
}
|
||||
return aggregator, nil
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -642,6 +685,7 @@ type PercentileAggregator struct {
|
|||
percentile float64
|
||||
float_values map[string]map[interface{}][]float64
|
||||
defaultValue *protocol.FieldValue
|
||||
alias string
|
||||
}
|
||||
|
||||
func (self *PercentileAggregator) AggregatePoint(series string, group interface{}, p *protocol.Point) error {
|
||||
|
@ -671,6 +715,9 @@ func (self *PercentileAggregator) AggregatePoint(series string, group interface{
|
|||
}
|
||||
|
||||
func (self *PercentileAggregator) ColumnNames() []string {
|
||||
if self.alias != "" {
|
||||
return []string{self.alias}
|
||||
}
|
||||
return []string{self.functionName}
|
||||
}
|
||||
|
||||
|
@ -708,11 +755,16 @@ func NewPercentileAggregator(_ *parser.SelectQuery, value *parser.Value, default
|
|||
return nil, err
|
||||
}
|
||||
|
||||
functionName := "percentile"
|
||||
if value.Alias != "" {
|
||||
functionName = value.Alias
|
||||
}
|
||||
|
||||
return &PercentileAggregator{
|
||||
AbstractAggregator: AbstractAggregator{
|
||||
value: value.Elems[0],
|
||||
},
|
||||
functionName: "percentile",
|
||||
functionName: functionName,
|
||||
percentile: percentile,
|
||||
float_values: make(map[string]map[interface{}][]float64),
|
||||
defaultValue: wrappedDefaultValue,
|
||||
|
@ -727,6 +779,7 @@ type ModeAggregator struct {
|
|||
AbstractAggregator
|
||||
counts map[string]map[interface{}]map[float64]int
|
||||
defaultValue *protocol.FieldValue
|
||||
alias string
|
||||
}
|
||||
|
||||
func (self *ModeAggregator) AggregatePoint(series string, group interface{}, p *protocol.Point) error {
|
||||
|
@ -764,6 +817,9 @@ func (self *ModeAggregator) AggregatePoint(series string, group interface{}, p *
|
|||
}
|
||||
|
||||
func (self *ModeAggregator) ColumnNames() []string {
|
||||
if self.alias != "" {
|
||||
return []string{self.alias}
|
||||
}
|
||||
return []string{"mode"}
|
||||
}
|
||||
|
||||
|
@ -815,6 +871,7 @@ func NewModeAggregator(_ *parser.SelectQuery, value *parser.Value, defaultValue
|
|||
},
|
||||
counts: make(map[string]map[interface{}]map[float64]int),
|
||||
defaultValue: wrappedDefaultValue,
|
||||
alias: value.Alias,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -826,6 +883,7 @@ type DistinctAggregator struct {
|
|||
AbstractAggregator
|
||||
counts map[string]map[interface{}]map[interface{}]int
|
||||
defaultValue *protocol.FieldValue
|
||||
alias string
|
||||
}
|
||||
|
||||
func (self *DistinctAggregator) AggregatePoint(series string, group interface{}, p *protocol.Point) error {
|
||||
|
@ -867,6 +925,9 @@ func (self *DistinctAggregator) AggregatePoint(series string, group interface{},
|
|||
}
|
||||
|
||||
func (self *DistinctAggregator) ColumnNames() []string {
|
||||
if self.alias != "" {
|
||||
return []string{self.alias}
|
||||
}
|
||||
return []string{"distinct"}
|
||||
}
|
||||
|
||||
|
@ -907,6 +968,7 @@ func NewDistinctAggregator(_ *parser.SelectQuery, value *parser.Value, defaultVa
|
|||
},
|
||||
counts: make(map[string]map[interface{}]map[interface{}]int),
|
||||
defaultValue: wrappedDefaultValue,
|
||||
alias: value.Alias,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -964,6 +1026,10 @@ func NewCumulativeArithmeticAggregator(name string, value *parser.Value, initial
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if value.Alias != "" {
|
||||
name = value.Alias
|
||||
}
|
||||
|
||||
return &CumulativeArithmeticAggregator{
|
||||
AbstractAggregator: AbstractAggregator{
|
||||
value: value.Elems[0],
|
||||
|
@ -1065,6 +1131,10 @@ func NewFirstOrLastAggregator(name string, v *parser.Value, isFirst bool, defaul
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if v.Alias != "" {
|
||||
name = v.Alias
|
||||
}
|
||||
|
||||
return &FirstOrLastAggregator{
|
||||
AbstractAggregator: AbstractAggregator{
|
||||
value: v.Elems[0],
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"checkers"
|
||||
. "common"
|
||||
"encoding/json"
|
||||
"engine"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -626,6 +627,39 @@ func (self *IntegrationSuite) TestCountWithGroupBy(c *C) {
|
|||
c.Assert(data[0].Points[1][1], Equals, 20.0)
|
||||
}
|
||||
|
||||
func (self *IntegrationSuite) TestCountWithAlias(c *C) {
|
||||
for i := 0; i < 5; i++ {
|
||||
err := self.server.WriteData(fmt.Sprintf(`
|
||||
[
|
||||
{
|
||||
"name": "test_aliasing",
|
||||
"columns": ["cpu", "host"],
|
||||
"points": [[%d, "hosta"], [%d, "hostb"]]
|
||||
}
|
||||
]
|
||||
`, 60+i*10, 70+i*10))
|
||||
c.Assert(err, IsNil)
|
||||
}
|
||||
for _, name := range engine.GetRegisteredAggregators() {
|
||||
query := fmt.Sprintf("select %s(cpu) as some_alias from test_aliasing", name)
|
||||
if name == "percentile" {
|
||||
query = "select percentile(cpu, 90) as some_alias from test_aliasing"
|
||||
}
|
||||
fmt.Printf("query: %s\n", query)
|
||||
bs, err := self.server.RunQuery(query, "m")
|
||||
c.Assert(err, IsNil)
|
||||
data := []*SerializedSeries{}
|
||||
err = json.Unmarshal(bs, &data)
|
||||
c.Assert(data, HasLen, 1)
|
||||
c.Assert(data[0].Name, Equals, "test_aliasing")
|
||||
if name == "histogram" {
|
||||
c.Assert(data[0].Columns, DeepEquals, []string{"time", "some_alias_bucket_start", "some_alias_count"})
|
||||
continue
|
||||
}
|
||||
c.Assert(data[0].Columns, DeepEquals, []string{"time", "some_alias"})
|
||||
}
|
||||
}
|
||||
|
||||
// test for issue #30
|
||||
func (self *IntegrationSuite) TestHttpPostWithTime(c *C) {
|
||||
now := time.Now().Add(-10 * 24 * time.Hour)
|
||||
|
|
|
@ -60,6 +60,7 @@ void
|
|||
free_value(value *value)
|
||||
{
|
||||
free(value->name);
|
||||
if (value->alias) free(value->alias);
|
||||
if (value->args) free_value_array(value->args);
|
||||
free(value);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ const (
|
|||
|
||||
type Value struct {
|
||||
Name string
|
||||
Alias string
|
||||
Type ValueType
|
||||
Elems []*Value
|
||||
compiledRegex *regexp.Regexp
|
||||
|
@ -385,6 +386,9 @@ func GetValue(value *C.value) (*Value, error) {
|
|||
v.compiledRegex, err = regexp.Compile(v.Name)
|
||||
}
|
||||
}
|
||||
if value.alias != nil {
|
||||
v.Alias = C.GoString(value.alias)
|
||||
}
|
||||
return v, err
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ var _ = Suite(&QueryParserSuite{})
|
|||
|
||||
func ToValueArray(strings ...string) (values []*Value) {
|
||||
for _, str := range strings {
|
||||
values = append(values, &Value{str, ValueSimpleName, nil, nil})
|
||||
values = append(values, &Value{str, "", ValueSimpleName, nil, nil})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -463,18 +463,18 @@ func (self *QueryParserSuite) TestParseSelectWithAnd(c *C) {
|
|||
rightBoolExpression, ok := w.Right.GetBoolExpression()
|
||||
c.Assert(ok, Equals, true)
|
||||
|
||||
c.Assert(leftBoolExpression.Elems[0], DeepEquals, &Value{"value", ValueSimpleName, nil, nil})
|
||||
c.Assert(leftBoolExpression.Elems[0], DeepEquals, &Value{"value", "", ValueSimpleName, nil, nil})
|
||||
value := leftBoolExpression.Elems[1].Elems[0]
|
||||
c.Assert(value, DeepEquals, &Value{"exp", ValueFunctionCall, nil, nil})
|
||||
c.Assert(value, DeepEquals, &Value{"exp", "", ValueFunctionCall, nil, nil})
|
||||
value = leftBoolExpression.Elems[1].Elems[1]
|
||||
c.Assert(value, DeepEquals, &Value{"2", ValueInt, nil, nil})
|
||||
c.Assert(value, DeepEquals, &Value{"2", "", ValueInt, nil, nil})
|
||||
c.Assert(leftBoolExpression.Name, Equals, ">")
|
||||
|
||||
c.Assert(rightBoolExpression.Elems[0], DeepEquals, &Value{"value", ValueSimpleName, nil, nil})
|
||||
c.Assert(rightBoolExpression.Elems[0], DeepEquals, &Value{"value", "", ValueSimpleName, nil, nil})
|
||||
value = rightBoolExpression.Elems[1].Elems[0]
|
||||
c.Assert(value, DeepEquals, &Value{"exp", ValueFunctionCall, nil, nil})
|
||||
c.Assert(value, DeepEquals, &Value{"exp", "", ValueFunctionCall, nil, nil})
|
||||
value = rightBoolExpression.Elems[1].Elems[1]
|
||||
c.Assert(value, DeepEquals, &Value{"3", ValueInt, nil, nil})
|
||||
c.Assert(value, DeepEquals, &Value{"3", "", ValueInt, nil, nil})
|
||||
c.Assert(rightBoolExpression.Name, Equals, "<")
|
||||
}
|
||||
|
||||
|
@ -568,14 +568,14 @@ func (self *QueryParserSuite) TestParseWhereClausePrecedence(c *C) {
|
|||
leftExpression, ok := condition.GetBoolExpression()
|
||||
c.Assert(ok, Equals, true)
|
||||
c.Assert(leftExpression.Name, Equals, ">")
|
||||
c.Assert(leftExpression.Elems[0], DeepEquals, &Value{"value", ValueSimpleName, nil, nil})
|
||||
c.Assert(leftExpression.Elems[1], DeepEquals, &Value{"90", ValueInt, nil, nil})
|
||||
c.Assert(leftExpression.Elems[0], DeepEquals, &Value{"value", "", ValueSimpleName, nil, nil})
|
||||
c.Assert(leftExpression.Elems[1], DeepEquals, &Value{"90", "", ValueInt, nil, nil})
|
||||
|
||||
rightExpression, ok := leftCondition.Right.GetBoolExpression()
|
||||
c.Assert(ok, Equals, true)
|
||||
c.Assert(rightExpression.Name, Equals, ">")
|
||||
c.Assert(rightExpression.Elems[0], DeepEquals, &Value{"other_value", ValueSimpleName, nil, nil})
|
||||
c.Assert(rightExpression.Elems[1], DeepEquals, &Value{"10.0", ValueFloat, nil, nil})
|
||||
c.Assert(rightExpression.Elems[0], DeepEquals, &Value{"other_value", "", ValueSimpleName, nil, nil})
|
||||
c.Assert(rightExpression.Elems[1], DeepEquals, &Value{"10.0", "", ValueFloat, nil, nil})
|
||||
}
|
||||
|
||||
func (self *QueryParserSuite) TestParseWhereClauseParentheses(c *C) {
|
||||
|
@ -631,11 +631,23 @@ func (self *QueryParserSuite) TestParseFromWithNestedFunctions2(c *C) {
|
|||
c.Assert(q.GetGroupByClause().Elems, HasLen, 1)
|
||||
c.Assert(q.GetGroupByClause().Elems[0], DeepEquals, &Value{
|
||||
Name: "time",
|
||||
Alias: "",
|
||||
Type: ValueFunctionCall,
|
||||
Elems: []*Value{&Value{"15m", ValueDuration, nil, nil}},
|
||||
Elems: []*Value{&Value{"15m", "", ValueDuration, nil, nil}},
|
||||
})
|
||||
}
|
||||
|
||||
func (self *QueryParserSuite) TestParseWithColumnAlias(c *C) {
|
||||
q, err := ParseSelectQuery("select count(email) as email_count from user.events")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(q.GetColumnNames(), HasLen, 1)
|
||||
column := q.GetColumnNames()[0]
|
||||
c.Assert(column.IsFunctionCall(), Equals, true)
|
||||
c.Assert(column.Name, Equals, "count")
|
||||
c.Assert(column.Elems, HasLen, 1)
|
||||
c.Assert(column.Alias, Equals, "email_count")
|
||||
}
|
||||
|
||||
func (self *QueryParserSuite) TestParseSelectWithInvalidRegex(c *C) {
|
||||
_, err := ParseSelectQuery("select email from users.events where email =~ /[/i and time>now()-2d;")
|
||||
c.Assert(err, ErrorMatches, ".*missing closing.*")
|
||||
|
@ -648,7 +660,7 @@ func (self *QueryParserSuite) TestParseSelectWithRegexCondition(c *C) {
|
|||
|
||||
// note: conditions that involve time are removed after the query is parsed
|
||||
regexExpression, _ := w.GetBoolExpression()
|
||||
c.Assert(regexExpression.Elems[0], DeepEquals, &Value{"email", ValueSimpleName, nil, nil})
|
||||
c.Assert(regexExpression.Elems[0], DeepEquals, &Value{"email", "", ValueSimpleName, nil, nil})
|
||||
c.Assert(regexExpression.Name, Equals, "=~")
|
||||
expr := regexExpression.Elems[1]
|
||||
c.Assert(expr.Type, Equals, ValueRegex)
|
||||
|
@ -662,7 +674,7 @@ func (self *QueryParserSuite) TestParseSelectWithComplexArithmeticOperations(c *
|
|||
boolExpression, ok := q.GetWhereCondition().GetBoolExpression()
|
||||
c.Assert(ok, Equals, true)
|
||||
|
||||
c.Assert(boolExpression.Elems[0], DeepEquals, &Value{".30", ValueFloat, nil, nil})
|
||||
c.Assert(boolExpression.Elems[0], DeepEquals, &Value{".30", "", ValueFloat, nil, nil})
|
||||
|
||||
// value * 1 / 3
|
||||
rightExpression := boolExpression.Elems[1]
|
||||
|
@ -727,14 +739,14 @@ func (self *QueryParserSuite) TestParseSinglePointQuery(c *C) {
|
|||
rightBoolExpression, ok := w.Right.GetBoolExpression()
|
||||
c.Assert(ok, Equals, true)
|
||||
|
||||
c.Assert(leftBoolExpression.Elems[0], DeepEquals, &Value{"time", ValueSimpleName, nil, nil})
|
||||
c.Assert(leftBoolExpression.Elems[0], DeepEquals, &Value{"time", "", ValueSimpleName, nil, nil})
|
||||
value := leftBoolExpression.Elems[1]
|
||||
c.Assert(value, DeepEquals, &Value{"999", ValueInt, nil, nil})
|
||||
c.Assert(value, DeepEquals, &Value{"999", "", ValueInt, nil, nil})
|
||||
c.Assert(leftBoolExpression.Name, Equals, "=")
|
||||
|
||||
c.Assert(rightBoolExpression.Elems[0], DeepEquals, &Value{"sequence_number", ValueSimpleName, nil, nil})
|
||||
c.Assert(rightBoolExpression.Elems[0], DeepEquals, &Value{"sequence_number", "", ValueSimpleName, nil, nil})
|
||||
value = rightBoolExpression.Elems[1]
|
||||
c.Assert(value, DeepEquals, &Value{"1", ValueInt, nil, nil})
|
||||
c.Assert(value, DeepEquals, &Value{"1", "", ValueInt, nil, nil})
|
||||
c.Assert(rightBoolExpression.Name, Equals, "=")
|
||||
}
|
||||
|
||||
|
@ -754,7 +766,7 @@ func (self *QueryParserSuite) TestParseContinuousQueryCreation(c *C) {
|
|||
c.Assert(q.IsContinuousQuery(), Equals, true)
|
||||
c.Assert(q.IsValidContinuousQuery(), Equals, true)
|
||||
clause := q.GetIntoClause()
|
||||
c.Assert(clause.Target, DeepEquals, &Value{"bar", ValueSimpleName, nil, nil})
|
||||
c.Assert(clause.Target, DeepEquals, &Value{"bar", "", ValueSimpleName, nil, nil})
|
||||
}
|
||||
|
||||
func (self *QueryParserSuite) TestParseInterpolatedContinuousQueryCreation(c *C) {
|
||||
|
@ -763,28 +775,28 @@ func (self *QueryParserSuite) TestParseInterpolatedContinuousQueryCreation(c *C)
|
|||
c.Assert(err, IsNil)
|
||||
c.Assert(q.IsContinuousQuery(), Equals, true)
|
||||
clause := q.GetIntoClause()
|
||||
c.Assert(clause.Target, DeepEquals, &Value{"bar.[c4]", ValueIntoName, nil, nil})
|
||||
c.Assert(clause.Target, DeepEquals, &Value{"bar.[c4]", "", ValueIntoName, nil, nil})
|
||||
|
||||
query = "select * from foo into [c5].bar.[c4];"
|
||||
q, err = ParseSelectQuery(query)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(q.IsContinuousQuery(), Equals, true)
|
||||
clause = q.GetIntoClause()
|
||||
c.Assert(clause.Target, DeepEquals, &Value{"[c5].bar.[c4]", ValueIntoName, nil, nil})
|
||||
c.Assert(clause.Target, DeepEquals, &Value{"[c5].bar.[c4]", "", ValueIntoName, nil, nil})
|
||||
|
||||
query = "select average(c4), count(c5) from s3 group by time(1h) into [average].[count];"
|
||||
q, err = ParseSelectQuery(query)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(q.IsContinuousQuery(), Equals, true)
|
||||
clause = q.GetIntoClause()
|
||||
c.Assert(clause.Target, DeepEquals, &Value{"[average].[count]", ValueIntoName, nil, nil})
|
||||
c.Assert(clause.Target, DeepEquals, &Value{"[average].[count]", "", ValueIntoName, nil, nil})
|
||||
|
||||
query = "select * from foo into :series_name.foo;"
|
||||
q, err = ParseSelectQuery(query)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(q.IsContinuousQuery(), Equals, true)
|
||||
clause = q.GetIntoClause()
|
||||
c.Assert(clause.Target, DeepEquals, &Value{":series_name.foo", ValueIntoName, nil, nil})
|
||||
c.Assert(clause.Target, DeepEquals, &Value{":series_name.foo", "", ValueIntoName, nil, nil})
|
||||
|
||||
query = "select * from foo into ]bar"
|
||||
q, err = ParseSelectQuery(query)
|
||||
|
|
|
@ -13,12 +13,14 @@ value *create_value(char *name, int type, char is_case_insensitive, value_array
|
|||
v->value_type = type;
|
||||
v->is_case_insensitive = is_case_insensitive;
|
||||
v->args = args;
|
||||
v->alias = NULL;
|
||||
return v;
|
||||
}
|
||||
|
||||
value *create_expression_value(char *operator, size_t size, ...) {
|
||||
value *v = malloc(sizeof(value));
|
||||
v->name = operator;
|
||||
v->alias = NULL;
|
||||
v->value_type = VALUE_EXPRESSION;
|
||||
v->is_case_insensitive = FALSE;
|
||||
v->args = malloc(sizeof(value_array));
|
||||
|
@ -418,20 +420,46 @@ VALUE:
|
|||
}
|
||||
|
|
||||
DURATION_VALUE
|
||||
{
|
||||
$$ = $1;
|
||||
$$->alias = NULL;
|
||||
}
|
||||
|
|
||||
SIMPLE_NAME_VALUE
|
||||
{
|
||||
$$ = $1;
|
||||
$$->alias = NULL;
|
||||
}
|
||||
|
|
||||
WILDCARD
|
||||
{
|
||||
$$ = $1;
|
||||
$$->alias = NULL;
|
||||
}
|
||||
|
|
||||
TABLE_NAME_VALUE
|
||||
{
|
||||
$$ = $1;
|
||||
$$->alias = NULL;
|
||||
}
|
||||
|
|
||||
FUNCTION_CALL
|
||||
{
|
||||
$$ = $1;
|
||||
$$->alias = NULL;
|
||||
}
|
||||
|
|
||||
'(' VALUE ')'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
|
|
||||
FUNCTION_CALL AS SIMPLE_NAME
|
||||
{
|
||||
$$ = $1;
|
||||
$$->alias = $3;
|
||||
}
|
||||
|
|
||||
VALUE '*' VALUE { $$ = create_expression_value(strdup("*"), 2, $1, $3); }
|
||||
|
|
||||
VALUE '/' VALUE { $$ = create_expression_value(strdup("/"), 2, $1, $3); }
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef struct value_t {
|
|||
VALUE_FUNCTION_CALL,
|
||||
VALUE_EXPRESSION
|
||||
} value_type;
|
||||
char *alias;
|
||||
char is_case_insensitive;
|
||||
value_array *args;
|
||||
} value;
|
||||
|
|
|
@ -12,6 +12,10 @@ int main(int argc, char **argv) {
|
|||
q = parse_query("select count(*) from users.events group_by user_email,time(1h) where time >> now()-1d;");
|
||||
close_query(&q);
|
||||
|
||||
// test freeing alias
|
||||
q = parse_query("select count(bar) as the_count from users.events group_by user_email,time(1h);");
|
||||
close_query(&q);
|
||||
|
||||
// test freeing where conditions
|
||||
q = parse_query("select value from t where c == 5 and b == 6;");
|
||||
close_query(&q);
|
||||
|
|
Loading…
Reference in New Issue