From f469097e8bb7280ec76f9ed4ce36c2eb6a05560a Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Thu, 11 Dec 2014 09:58:33 -0700 Subject: [PATCH] Add ability to fold without now(). --- influxql/ast.go | 8 ++++---- influxql/ast_test.go | 18 ++++++++++-------- influxql/parser_test.go | 9 +++++++++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/influxql/ast.go b/influxql/ast.go index 592210f767..eb7cbe0e68 100644 --- a/influxql/ast.go +++ b/influxql/ast.go @@ -577,12 +577,12 @@ func (e *Wildcard) String() string { return "*" } // Fold performs constant folding on an expression. // The function, "now()", is expanded into the current time during folding. -func Fold(expr Expr, now time.Time) Expr { +func Fold(expr Expr, now *time.Time) Expr { switch expr := expr.(type) { case *Call: // Replace "now()" with current time. - if strings.ToLower(expr.Name) == "now" { - return &TimeLiteral{Val: now} + if strings.ToLower(expr.Name) == "now" && now != nil { + return &TimeLiteral{Val: *now} } // Fold call arguments. @@ -610,7 +610,7 @@ func Fold(expr Expr, now time.Time) Expr { } // foldBinaryExpr performs constant folding if the binary expression has two literals. -func foldBinaryExpr(expr *BinaryExpr, now time.Time) Expr { +func foldBinaryExpr(expr *BinaryExpr, now *time.Time) Expr { // Fold both sides of binary expression first. expr.LHS = Fold(expr.LHS, now) expr.RHS = Fold(expr.RHS, now) diff --git a/influxql/ast_test.go b/influxql/ast_test.go index d9eadfd338..aa67945f3f 100644 --- a/influxql/ast_test.go +++ b/influxql/ast_test.go @@ -141,15 +141,9 @@ func TestFold(t *testing.T) { // String literals. {`"foo" + 'bar'`, `"foobar"`}, } { - // Parse incoming expression. - expr, err := influxql.NewParser(strings.NewReader(tt.in)).ParseExpr() - if err != nil { - t.Errorf("%d. %s: parse error: %s", i, tt.in, err) - continue - } - // Fold expression. - expr = influxql.Fold(expr, mustParseTime("2000-01-01T00:00:00Z")) + now := mustParseTime("2000-01-01T00:00:00Z") + expr := influxql.Fold(MustParseExpr(tt.in), &now) // Compare with expected output. if out := expr.String(); tt.out != out { @@ -158,3 +152,11 @@ func TestFold(t *testing.T) { } } } + +// Ensure an a "now()" call is not folded when now is not passed in. +func TestFold_WithoutNow(t *testing.T) { + expr := influxql.Fold(MustParseExpr(`now()`), nil) + if s := expr.String(); s != `now()` { + t.Fatalf("unexpected expr: %s", s) + } +} diff --git a/influxql/parser_test.go b/influxql/parser_test.go index 01796d8563..eb58d4136a 100644 --- a/influxql/parser_test.go +++ b/influxql/parser_test.go @@ -451,6 +451,15 @@ func MustParseSelectStatement(s string) *influxql.SelectStatement { return stmt.(*influxql.SelectStatement) } +// MustParseExpr parses an expression. Panic on error. +func MustParseExpr(s string) influxql.Expr { + expr, err := influxql.NewParser(strings.NewReader(s)).ParseExpr() + if err != nil { + panic(err.Error()) + } + return expr +} + // errstring converts an error to its string representation. func errstring(err error) string { if err != nil {