Skip to content

Commit

Permalink
Support empty tags for all WHERE equality operations
Browse files Browse the repository at this point in the history
A missing tag on a point was sometimes treated as `""` and sometimes
treated as a separate `null` entity. This change modifies the equality
operations to always treat a missing tag as an empty string.

Empty tags are *not* indexed and do not have the same performance as a
tag that exists.

Fixes #3773.
  • Loading branch information
jsternberg committed Apr 11, 2016
1 parent ca534bf commit 5bdd61b
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- [#6223](https://github.com/influxdata/influxdb/issues/6223): Failure to start/run on Windows. Thanks @mvadu
- [#6229](https://github.com/influxdata/influxdb/issues/6229): Fixed aggregate queries with no GROUP BY to include the end time.
- [#6283](https://github.com/influxdata/influxdb/pull/6283): Fix GROUP BY tag to produce consistent results when a series has no tags.
- [#3773](https://github.com/influxdata/influxdb/issues/3773): Support empty tags for all WHERE equality operations.

## v0.12.0 [2016-04-05]
### Release Notes
Expand Down
71 changes: 49 additions & 22 deletions tsdb/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -763,13 +763,8 @@ func (m *Measurement) idsForExpr(n *influxql.BinaryExpr) (SeriesIDs, influxql.Ex
return m.seriesIDs, n, nil
}

tagVals, ok := m.seriesByTagKeyValue[name.Val]
if name.Val != "_name" && !ok {
if n.Op == influxql.NEQ || n.Op == influxql.NEQREGEX {
return m.seriesIDs, &influxql.BooleanLiteral{Val: true}, nil
}
return nil, nil, nil
}
// Retrieve list of series with this tag key.
tagVals := m.seriesByTagKeyValue[name.Val]

// if we're looking for series with a specific tag value
if str, ok := value.(*influxql.StringLiteral); ok {
Expand All @@ -784,10 +779,23 @@ func (m *Measurement) idsForExpr(n *influxql.BinaryExpr) (SeriesIDs, influxql.Ex
}

if n.Op == influxql.EQ {
// return series that have a tag of specific value.
ids = tagVals[str.Val]
if str.Val != "" {
// return series that have a tag of specific value.
ids = tagVals[str.Val]
} else {
ids = m.seriesIDs
for k := range tagVals {
ids = ids.Reject(tagVals[k])
}
}
} else if n.Op == influxql.NEQ {
ids = m.seriesIDs.Reject(tagVals[str.Val])
if str.Val != "" {
ids = m.seriesIDs.Reject(tagVals[str.Val])
} else {
for k := range tagVals {
ids = ids.Union(tagVals[k])
}
}
}
return ids, &influxql.BooleanLiteral{Val: true}, nil
}
Expand All @@ -805,19 +813,38 @@ func (m *Measurement) idsForExpr(n *influxql.BinaryExpr) (SeriesIDs, influxql.Ex
return nil, &influxql.BooleanLiteral{Val: true}, nil
}

// The operation is a NEQREGEX, code must start by assuming all match, even
// series without any tags.
if n.Op == influxql.NEQREGEX {
ids = m.seriesIDs
}
// Check if we match the empty string to see if we should include series
// that are missing the tag.
empty := re.Val.MatchString("")

for k := range tagVals {
match := re.Val.MatchString(k)

if match && n.Op == influxql.EQREGEX {
ids = ids.Union(tagVals[k])
} else if match && n.Op == influxql.NEQREGEX {
ids = ids.Reject(tagVals[k])
// Gather the series that match the regex. If we should include the empty string,
// start with the list of all series and reject series that don't match our condition.
// If we should not include the empty string, include series that match our condition.
if empty && n.Op == influxql.EQREGEX {
ids = m.seriesIDs
for k := range tagVals {
if !re.Val.MatchString(k) {
ids = ids.Reject(tagVals[k])
}
}
} else if empty && n.Op == influxql.NEQREGEX {
for k := range tagVals {
if !re.Val.MatchString(k) {
ids = ids.Union(tagVals[k])
}
}
} else if !empty && n.Op == influxql.EQREGEX {
for k := range tagVals {
if re.Val.MatchString(k) {
ids = ids.Union(tagVals[k])
}
}
} else if !empty && n.Op == influxql.NEQREGEX {
ids = m.seriesIDs
for k := range tagVals {
if re.Val.MatchString(k) {
ids = ids.Reject(tagVals[k])
}
}
}
return ids, &influxql.BooleanLiteral{Val: true}, nil
Expand Down

0 comments on commit 5bdd61b

Please sign in to comment.