wip
parent
f6b19711f1
commit
8ea3c47747
|
@ -2322,6 +2322,65 @@ func TestServer_Query_Wildcards(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestServer_Query_WildcardExpansion(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := OpenServer(NewConfig(), "")
|
||||
defer s.Close()
|
||||
|
||||
if err := s.CreateDatabaseAndRetentionPolicy("db0", newRetentionPolicyInfo("rp0", 1, 0)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.MetaStore.SetDefaultRetentionPolicy("db0", "rp0"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
writes := []string{
|
||||
fmt.Sprintf(`wildcard,region=us-east,host=A value=10,cpu=80 %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:00Z").UnixNano()),
|
||||
fmt.Sprintf(`wildcard,region=us-east,host=B value=20,cpu=90 %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:10Z").UnixNano()),
|
||||
fmt.Sprintf(`wildcard,region=us-west,host=B value=30,cpu=70 %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:20Z").UnixNano()),
|
||||
fmt.Sprintf(`wildcard,region=us-east,host=A value=40,cpu=60 %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:30Z").UnixNano()),
|
||||
|
||||
fmt.Sprintf(`dupnames,region=us-east,day=1 value=10,day=3i %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:00Z").UnixNano()),
|
||||
fmt.Sprintf(`dupnames,region=us-east,day=2 value=20,day=2i %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:10Z").UnixNano()),
|
||||
fmt.Sprintf(`dupnames,region=us-west,day=3 value=30,day=1i %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:20Z").UnixNano()),
|
||||
}
|
||||
|
||||
test := NewTest("db0", "rp0")
|
||||
test.write = strings.Join(writes, "\n")
|
||||
|
||||
test.addQueries([]*Query{
|
||||
&Query{
|
||||
name: "wildcard",
|
||||
params: url.Values{"db": []string{"db0"}},
|
||||
command: `SELECT * FROM wildcard`,
|
||||
exp: `{"results":[{"series":[{"name":"wildcard","columns":["time","cpu","host","region","value"],"values":[["2000-01-01T00:00:00Z",80,"A","us-east",10],["2000-01-01T00:00:10Z",90,"B","us-east",20],["2000-01-01T00:00:20Z",70,"B","us-west",30]]}]}]}`,
|
||||
},
|
||||
//&Query{
|
||||
//name: "duplicate tag and field name",
|
||||
//params: url.Values{"db": []string{"db0"}},
|
||||
//command: `SELECT * FROM dupnames`,
|
||||
//exp: `{}`,
|
||||
//},
|
||||
}...)
|
||||
|
||||
for i, query := range test.queries {
|
||||
if i == 0 {
|
||||
if err := test.init(s); err != nil {
|
||||
t.Fatalf("test init failed: %s", err)
|
||||
}
|
||||
}
|
||||
if query.skip {
|
||||
t.Logf("SKIP:: %s", query.name)
|
||||
continue
|
||||
}
|
||||
if err := query.Execute(s); err != nil {
|
||||
t.Error(query.Error(err))
|
||||
} else if !query.success() {
|
||||
t.Error(query.failureMessage())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_Query_AcrossShardsAndFields(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := OpenServer(NewConfig(), "")
|
||||
|
|
|
@ -953,6 +953,31 @@ func (s *SelectStatement) HasWildcard() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// HasFieldWildcard returns whether or not the select statement has at least 1 wildcard in the fields
|
||||
func (s *SelectStatement) HasFieldWildcard() bool {
|
||||
for _, f := range s.Fields {
|
||||
_, ok := f.Expr.(*Wildcard)
|
||||
if ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// HasDimensionWildcard returns whether or not the select statement has
|
||||
// at least 1 wildcard in the dimensions aka `GROUP BY`
|
||||
func (s *SelectStatement) HasDimensionWildcard() bool {
|
||||
for _, d := range s.Dimensions {
|
||||
_, ok := d.Expr.(*Wildcard)
|
||||
if ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// hasTimeDimensions returns whether or not the select statement has at least 1
|
||||
// where condition with time as the condition
|
||||
func (s *SelectStatement) hasTimeDimensions(node Node) bool {
|
||||
|
@ -1344,6 +1369,17 @@ func (s *SelectStatement) NamesInSelect() []string {
|
|||
return a
|
||||
}
|
||||
|
||||
// NamesInDimension returns the field and tag names (idents) in the group by
|
||||
func (s *SelectStatement) NamesInDimension() []string {
|
||||
var a []string
|
||||
|
||||
for _, d := range s.Dimensions {
|
||||
a = append(a, walkNames(d.Expr)...)
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// walkNames will walk the Expr and return the database fields
|
||||
func walkNames(exp Expr) []string {
|
||||
switch expr := exp.(type) {
|
||||
|
|
|
@ -188,6 +188,7 @@ func (e *Executor) executeRaw(out chan *influxql.Row) {
|
|||
for {
|
||||
if m.bufferedChunk == nil {
|
||||
m.bufferedChunk, err = m.NextChunk()
|
||||
//spew.Dump(m.bufferedChunk)
|
||||
if err != nil {
|
||||
out <- &influxql.Row{Err: err}
|
||||
return
|
||||
|
|
|
@ -443,6 +443,8 @@ func (lm *LocalMapper) rewriteSelectStatement(stmt *influxql.SelectStatement) (*
|
|||
|
||||
// expandWildcards returns a new SelectStatement with wildcards in the fields
|
||||
// and/or GROUP BY expanded with actual field names.
|
||||
// Tags and Measurements are included in the select if a `SELECT *` is issued
|
||||
// There is no longer an explicit `GROUP BY *` when tags are used in the `SELECT` clause
|
||||
func (lm *LocalMapper) expandWildcards(stmt *influxql.SelectStatement) (*influxql.SelectStatement, error) {
|
||||
// If there are no wildcards in the statement, return it as-is.
|
||||
if !stmt.HasWildcard() {
|
||||
|
@ -471,13 +473,27 @@ func (lm *LocalMapper) expandWildcards(stmt *influxql.SelectStatement) (*influxq
|
|||
fieldSet[name] = struct{}{}
|
||||
fields = append(fields, &influxql.Field{Expr: &influxql.VarRef{Val: name}})
|
||||
}
|
||||
// Get the dimensions for this measurement.
|
||||
for _, t := range mm.TagKeys() {
|
||||
if _, ok := dimensionSet[t]; ok {
|
||||
continue
|
||||
|
||||
// Add tags to fields if a wildcard was provided.
|
||||
if stmt.HasFieldWildcard() {
|
||||
for _, t := range mm.TagKeys() {
|
||||
if _, ok := fieldSet[t]; ok {
|
||||
continue
|
||||
}
|
||||
fieldSet[t] = struct{}{}
|
||||
fields = append(fields, &influxql.Field{Expr: &influxql.VarRef{Val: t}})
|
||||
}
|
||||
}
|
||||
|
||||
// Get the dimensions for this measurement.
|
||||
if stmt.HasDimensionWildcard() {
|
||||
for _, t := range mm.TagKeys() {
|
||||
if _, ok := dimensionSet[t]; ok {
|
||||
continue
|
||||
}
|
||||
dimensionSet[t] = struct{}{}
|
||||
dimensions = append(dimensions, &influxql.Dimension{Expr: &influxql.VarRef{Val: t}})
|
||||
}
|
||||
dimensionSet[t] = struct{}{}
|
||||
dimensions = append(dimensions, &influxql.Dimension{Expr: &influxql.VarRef{Val: t}})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -789,9 +805,15 @@ func createTagSetsAndFields(m *Measurement, stmt *influxql.SelectStatement) (*ta
|
|||
}
|
||||
if m.HasTagKey(n) {
|
||||
sts.add(n)
|
||||
}
|
||||
}
|
||||
|
||||
for _, n := range stmt.NamesInDimension() {
|
||||
if m.HasTagKey(n) {
|
||||
tagKeys = append(tagKeys, n)
|
||||
}
|
||||
}
|
||||
|
||||
for _, n := range stmt.NamesInWhere() {
|
||||
if n == "time" {
|
||||
continue
|
||||
|
|
Loading…
Reference in New Issue