Fix the time range when an exact timestamp is selected

There is a lot of confusion in the code if the range is [start, end) or
[start, end]. This is not made easier because it is acts one way in some
areas and in another way in some other areas, but it is usually [start,
end]. The `time = ?` syntax assumed that it was [start, end) and added
an extra nanosecond to the end time to accomodate for that, but the
range was actually [start, end] and that caused it to include one extra
nanosecond when it shouldn't have.

This change fixes it so exactly one timestamp is selected when `time = ?`
is used.
pull/8098/head
Jonathan A. Sternberg 2017-03-06 11:12:48 -06:00
parent bf523c0513
commit 33981277bc
4 changed files with 59 additions and 4 deletions

View File

@ -23,6 +23,7 @@
- [#8155](https://github.com/influxdata/influxdb/pull/8155): Simplify admin user check. - [#8155](https://github.com/influxdata/influxdb/pull/8155): Simplify admin user check.
- [#8118](https://github.com/influxdata/influxdb/issues/8118): Significantly improve DROP DATABASE speed. - [#8118](https://github.com/influxdata/influxdb/issues/8118): Significantly improve DROP DATABASE speed.
- [#8181](https://github.com/influxdata/influxdb/issues/8181): Return an error when an invalid duration literal is parsed. - [#8181](https://github.com/influxdata/influxdb/issues/8181): Return an error when an invalid duration literal is parsed.
- [#8093](https://github.com/influxdata/influxdb/issues/8093): Fix the time range when an exact timestamp is selected.
## v1.2.2 [2017-03-14] ## v1.2.2 [2017-03-14]

View File

@ -3957,8 +3957,8 @@ func TimeRange(expr Expr) (min, max time.Time, err error) {
if min.IsZero() || value.After(min) { if min.IsZero() || value.After(min) {
min = value min = value
} }
if max.IsZero() || value.Add(1*time.Nanosecond).Before(max) { if max.IsZero() || value.Before(max) {
max = value.Add(1 * time.Nanosecond) max = value
} }
} }
} }

View File

@ -879,7 +879,7 @@ func TestTimeRange(t *testing.T) {
{expr: `time < 10`, min: `0001-01-01T00:00:00Z`, max: `1970-01-01T00:00:00.000000009Z`}, {expr: `time < 10`, min: `0001-01-01T00:00:00Z`, max: `1970-01-01T00:00:00.000000009Z`},
// Equality // Equality
{expr: `time = '2000-01-01 00:00:00'`, min: `2000-01-01T00:00:00Z`, max: `2000-01-01T00:00:00.000000001Z`}, {expr: `time = '2000-01-01 00:00:00'`, min: `2000-01-01T00:00:00Z`, max: `2000-01-01T00:00:00Z`},
// Multiple time expressions. // Multiple time expressions.
{expr: `time >= '2000-01-01 00:00:00' AND time < '2000-01-02 00:00:00'`, min: `2000-01-01T00:00:00Z`, max: `2000-01-01T23:59:59.999999999Z`}, {expr: `time >= '2000-01-01 00:00:00' AND time < '2000-01-02 00:00:00'`, min: `2000-01-01T00:00:00Z`, max: `2000-01-01T23:59:59.999999999Z`},
@ -888,7 +888,7 @@ func TestTimeRange(t *testing.T) {
{expr: `time >= '2000-01-01 00:00:00' AND time <= '1999-01-01 00:00:00'`, min: `2000-01-01T00:00:00Z`, max: `1999-01-01T00:00:00Z`}, {expr: `time >= '2000-01-01 00:00:00' AND time <= '1999-01-01 00:00:00'`, min: `2000-01-01T00:00:00Z`, max: `1999-01-01T00:00:00Z`},
// Absolute time // Absolute time
{expr: `time = 1388534400s`, min: `2014-01-01T00:00:00Z`, max: `2014-01-01T00:00:00.000000001Z`}, {expr: `time = 1388534400s`, min: `2014-01-01T00:00:00Z`, max: `2014-01-01T00:00:00Z`},
// Non-comparative expressions. // Non-comparative expressions.
{expr: `time`, min: `0001-01-01T00:00:00Z`, max: `0001-01-01T00:00:00Z`}, {expr: `time`, min: `0001-01-01T00:00:00Z`, max: `0001-01-01T00:00:00Z`},

View File

@ -4356,6 +4356,60 @@ func TestServer_Query_AggregateSelectors(t *testing.T) {
} }
} }
func TestServer_Query_ExactTimeRange(t *testing.T) {
t.Parallel()
s := OpenServer(NewConfig())
defer s.Close()
if err := s.CreateDatabaseAndRetentionPolicy("db0", newRetentionPolicySpec("rp0", 1, 0), true); err != nil {
t.Fatal(err)
}
writes := []string{
fmt.Sprintf(`cpu value=1 %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:00.000000000Z").UnixNano()),
fmt.Sprintf(`cpu value=2 %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:00.000000001Z").UnixNano()),
fmt.Sprintf(`cpu value=3 %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:00.000000002Z").UnixNano()),
}
test := NewTest("db0", "rp0")
test.writes = Writes{
&Write{data: strings.Join(writes, "\n")},
}
test.addQueries([]*Query{
&Query{
name: "query point at exactly one time - rfc3339nano",
params: url.Values{"db": []string{"db0"}},
command: `SELECT * FROM cpu WHERE time = '2000-01-01T00:00:00.000000001Z'`,
exp: `{"results":[{"statement_id":0,"series":[{"name":"cpu","columns":["time","value"],"values":[["2000-01-01T00:00:00.000000001Z",2]]}]}]}`,
},
&Query{
name: "query point at exactly one time - timestamp",
params: url.Values{"db": []string{"db0"}},
command: `SELECT * FROM cpu WHERE time = 946684800000000001`,
exp: `{"results":[{"statement_id":0,"series":[{"name":"cpu","columns":["time","value"],"values":[["2000-01-01T00:00:00.000000001Z",2]]}]}]}`,
},
}...)
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_Selectors(t *testing.T) { func TestServer_Query_Selectors(t *testing.T) {
t.Parallel() t.Parallel()
s := OpenServer(NewConfig()) s := OpenServer(NewConfig())