fix #88. Support datetime strings

pull/113/merge
John Shahid 2013-12-03 17:09:57 -05:00
parent e2ff2d7a40
commit 78e7643567
3 changed files with 82 additions and 2 deletions

View File

@ -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

View File

@ -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)

View File

@ -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()