fix #88. Support datetime strings
parent
e2ff2d7a40
commit
78e7643567
|
@ -145,6 +145,7 @@
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- [Issue #92](https://github.com/influxdb/influxdb/issues/92). Change '==' to '=' and '!=' to '<>'
|
- [Issue #92](https://github.com/influxdb/influxdb/issues/92). Change '==' to '=' and '!=' to '<>'
|
||||||
|
- [Issue #88](https://github.com/influxdb/influxdb/issues/88). Support datetime strings
|
||||||
|
|
||||||
## Bugfixes
|
## Bugfixes
|
||||||
|
|
||||||
|
|
|
@ -209,6 +209,44 @@ func (self *QueryParserSuite) TestParseSelectWithTimeCondition(c *C) {
|
||||||
c.Assert(q.GetStartTime().Round(time.Minute), Equals, time.Now().Add(-24*time.Hour).Round(time.Minute))
|
c.Assert(q.GetStartTime().Round(time.Minute), Equals, time.Now().Add(-24*time.Hour).Round(time.Minute))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *QueryParserSuite) TestParseSelectWithPartialTimeString(c *C) {
|
||||||
|
for actual, expected := range map[string]string{
|
||||||
|
"2013-08-15": "2013-08-15 00:00:00",
|
||||||
|
"2013-08-15 7": "2013-08-15 07:00:00",
|
||||||
|
"2013-08-15 7:04": "2013-08-15 07:04:00",
|
||||||
|
"2013-08-15 15": "2013-08-15 15:00:00",
|
||||||
|
"2013-08-15 15:14": "2013-08-15 15:14:00",
|
||||||
|
"2013-08-15 15:14:26": "2013-08-15 15:14:26",
|
||||||
|
} {
|
||||||
|
t, err := time.Parse("2006-01-02 15:04:05", expected)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
q, err := ParseQuery(fmt.Sprintf("select value, time from t where time > '%s';", actual))
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
// note: the time condition will be removed
|
||||||
|
c.Assert(q.GetWhereCondition(), IsNil)
|
||||||
|
|
||||||
|
startTime := q.GetStartTime()
|
||||||
|
c.Assert(startTime, Equals, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *QueryParserSuite) TestParseSelectWithTimeString(c *C) {
|
||||||
|
t, err := time.Parse("2006-01-02 15:04:05", "2013-08-12 23:32:01.232")
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
q, err := ParseQuery("select value, time from t where time > '2013-08-12 23:32:01.232';")
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
// note: the time condition will be removed
|
||||||
|
c.Assert(q.GetWhereCondition(), IsNil)
|
||||||
|
|
||||||
|
startTime := q.GetStartTime()
|
||||||
|
c.Assert(startTime, Equals, t)
|
||||||
|
|
||||||
|
milliseconds := startTime.Sub(startTime.Round(time.Second)).Nanoseconds() / 1000000
|
||||||
|
c.Assert(milliseconds, Equals, int64(232))
|
||||||
|
}
|
||||||
|
|
||||||
func (self *QueryParserSuite) TestParseSelectWithAnd(c *C) {
|
func (self *QueryParserSuite) TestParseSelectWithAnd(c *C) {
|
||||||
q, err := ParseQuery("select value from cpu.idle where value > exp() * 2 and value < exp() * 3;")
|
q, err := ParseQuery("select value from cpu.idle where value > exp() * 2 and value < exp() * 3;")
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -166,6 +167,41 @@ func (self *Query) GetEndTime() time.Time {
|
||||||
return self.endTime
|
return self.endTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse time that matches the following format:
|
||||||
|
// 2006-01-02 [15[:04[:05[.000]]]]
|
||||||
|
// notice, hour, minute and seconds are optional
|
||||||
|
var time_regex *regexp.Regexp
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var err error
|
||||||
|
time_regex, err = regexp.Compile(
|
||||||
|
"^([0-9]{4}|[0-9]{2})-[0-9]{1,2}-[0-9]{1,2}( [0-9]{1,2}(:[0-9]{1,2}(:[0-9]{1,2}?(\\.[0-9]+)?)?)?)?$")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseTimeString(t string) (time.Time, error) {
|
||||||
|
submatches := time_regex.FindStringSubmatch(t)
|
||||||
|
if len(submatches) == 0 {
|
||||||
|
return ZERO_TIME, fmt.Errorf("%s isn't a valid time string", t)
|
||||||
|
}
|
||||||
|
|
||||||
|
if submatches[5] != "" || submatches[4] != "" {
|
||||||
|
return time.Parse("2006-01-02 15:04:05", t)
|
||||||
|
}
|
||||||
|
|
||||||
|
if submatches[3] != "" {
|
||||||
|
return time.Parse("2006-01-02 15:04", t)
|
||||||
|
}
|
||||||
|
|
||||||
|
if submatches[2] != "" {
|
||||||
|
return time.Parse("2006-01-02 15", t)
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Parse("2006-01-02", t)
|
||||||
|
}
|
||||||
|
|
||||||
// parse time expressions, e.g. now() - 1d
|
// parse time expressions, e.g. now() - 1d
|
||||||
func parseTime(expr *Expression) (int64, error) {
|
func parseTime(expr *Expression) (int64, error) {
|
||||||
if value, ok := expr.GetLeftValue(); ok {
|
if value, ok := expr.GetLeftValue(); ok {
|
||||||
|
@ -177,6 +213,11 @@ func parseTime(expr *Expression) (int64, error) {
|
||||||
return 0, fmt.Errorf("Invalid use of function %s", value.Name)
|
return 0, fmt.Errorf("Invalid use of function %s", value.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if value.Type == ValueString {
|
||||||
|
t, err := parseTimeString(value.Name)
|
||||||
|
return t.UnixNano(), err
|
||||||
|
}
|
||||||
|
|
||||||
name := value.Name
|
name := value.Name
|
||||||
|
|
||||||
parsedFloat, err := strconv.ParseFloat(name[:len(name)-1], 64)
|
parsedFloat, err := strconv.ParseFloat(name[:len(name)-1], 64)
|
||||||
|
@ -297,7 +338,7 @@ func getReferencedColumnsFromCondition(condition *WhereCondition, mapping map[st
|
||||||
|
|
||||||
func isNumericValue(value *Value) bool {
|
func isNumericValue(value *Value) bool {
|
||||||
switch value.Type {
|
switch value.Type {
|
||||||
case ValueDuration, ValueFloat, ValueInt:
|
case ValueDuration, ValueFloat, ValueInt, ValueString:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
@ -365,7 +406,7 @@ func getTime(condition *WhereCondition, isParsingStartTime bool) (*WhereConditio
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ZERO_TIME, err
|
return nil, ZERO_TIME, err
|
||||||
}
|
}
|
||||||
return nil, time.Unix(nanoseconds/int64(time.Second), nanoseconds%int64(time.Second)), nil
|
return nil, time.Unix(nanoseconds/int64(time.Second), nanoseconds%int64(time.Second)).UTC(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
leftCondition, _ := condition.GetLeftWhereCondition()
|
leftCondition, _ := condition.GetLeftWhereCondition()
|
||||||
|
|
Loading…
Reference in New Issue