fix #88. Support datetime strings
parent
e2ff2d7a40
commit
78e7643567
|
@ -145,6 +145,7 @@
|
|||
## Features
|
||||
|
||||
- [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
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
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) {
|
||||
q, err := ParseQuery("select value from cpu.idle where value > exp() * 2 and value < exp() * 3;")
|
||||
c.Assert(err, IsNil)
|
||||
|
|
|
@ -2,6 +2,7 @@ package parser
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -166,6 +167,41 @@ func (self *Query) GetEndTime() time.Time {
|
|||
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
|
||||
func parseTime(expr *Expression) (int64, error) {
|
||||
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)
|
||||
}
|
||||
|
||||
if value.Type == ValueString {
|
||||
t, err := parseTimeString(value.Name)
|
||||
return t.UnixNano(), err
|
||||
}
|
||||
|
||||
name := value.Name
|
||||
|
||||
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 {
|
||||
switch value.Type {
|
||||
case ValueDuration, ValueFloat, ValueInt:
|
||||
case ValueDuration, ValueFloat, ValueInt, ValueString:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
@ -365,7 +406,7 @@ func getTime(condition *WhereCondition, isParsingStartTime bool) (*WhereConditio
|
|||
if err != nil {
|
||||
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()
|
||||
|
|
Loading…
Reference in New Issue