From a55015487d9e04c57723b16945d826c173220126 Mon Sep 17 00:00:00 2001 From: Muhammad Luthfi Fahlevi Date: Wed, 21 Aug 2024 17:25:08 +0700 Subject: [PATCH] feat: add condition when the complex query result is time and refactor codes --- pkg/queryexpr/query_expr.go | 5 +++++ pkg/queryexpr/sql_expr.go | 23 ++++++++++++++++------- pkg/queryexpr/sql_expr_test.go | 8 ++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/pkg/queryexpr/query_expr.go b/pkg/queryexpr/query_expr.go index 80c90454..879c061a 100644 --- a/pkg/queryexpr/query_expr.go +++ b/pkg/queryexpr/query_expr.go @@ -3,6 +3,7 @@ package queryexpr import ( "fmt" "strings" + "time" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" @@ -89,5 +90,9 @@ func GetQueryExprResult(fn string) (any, error) { return nil, fmt.Errorf("failed to evaluate function '%s': %w", fn, err) } + if t, ok := result.(time.Time); ok { + return t.Format(time.RFC3339), nil + } + return result, nil } diff --git a/pkg/queryexpr/sql_expr.go b/pkg/queryexpr/sql_expr.go index d48966c2..20a27826 100644 --- a/pkg/queryexpr/sql_expr.go +++ b/pkg/queryexpr/sql_expr.go @@ -71,11 +71,9 @@ func (s SQLExpr) convertToSQL(node ast.Node, stringBuilder *strings.Builder) err return err } case *ast.BuiltinNode, *ast.ConditionalNode: - result, err := GetQueryExprResult(n.String()) - if err != nil { + if err := s.getQueryExprResult(n.String(), stringBuilder); err != nil { return err } - fmt.Fprintf(stringBuilder, "%v", result) default: return s.unsupportedQueryError(n) } @@ -85,12 +83,10 @@ func (s SQLExpr) convertToSQL(node ast.Node, stringBuilder *strings.Builder) err func (s SQLExpr) binaryNodeToSQLQuery(n *ast.BinaryNode, stringBuilder *strings.Builder) error { operator := s.operatorToSQL(n) - if operator == "" { // most likely the node is operation - result, err := GetQueryExprResult(n.String()) - if err != nil { + if operator == "" { // most likely the node is an operation + if err := s.getQueryExprResult(n.String(), stringBuilder); err != nil { return err } - fmt.Fprintf(stringBuilder, "%v", result) } else { stringBuilder.WriteString("(") if err := s.convertToSQL(n.Left, stringBuilder); err != nil { @@ -109,6 +105,19 @@ func (s SQLExpr) binaryNodeToSQLQuery(n *ast.BinaryNode, stringBuilder *strings. return nil } +func (SQLExpr) getQueryExprResult(fn string, stringBuilder *strings.Builder) error { + result, err := GetQueryExprResult(fn) + if err != nil { + return err + } + if str, ok := result.(string); ok { + result = fmt.Sprintf("'%s'", str) + } + + fmt.Fprintf(stringBuilder, "%v", result) + return nil +} + func (s SQLExpr) arrayNodeToSQLQuery(n *ast.ArrayNode, stringBuilder *strings.Builder) error { stringBuilder.WriteString("(") for i := range n.Nodes { diff --git a/pkg/queryexpr/sql_expr_test.go b/pkg/queryexpr/sql_expr_test.go index 3c2a9ac0..96cee837 100644 --- a/pkg/queryexpr/sql_expr_test.go +++ b/pkg/queryexpr/sql_expr_test.go @@ -1,7 +1,9 @@ package queryexpr_test import ( + "fmt" "testing" + "time" "github.com/goto/compass/pkg/queryexpr" ) @@ -66,6 +68,12 @@ func TestSQLExpr_ToQuery(t *testing.T) { want: `((bool_identifier = false) AND (name != 'John'))`, wantErr: false, }, + { + name: "complex query expression that can directly produce a value regarding time", + expr: queryexpr.SQLExpr(`refreshed_at <= (now() - duration('1h'))`), + want: fmt.Sprintf("(refreshed_at <= '%s')", time.Now().Add(-1*time.Hour).Format(time.RFC3339)), + wantErr: false, + }, { name: "complex query expression that can NOT directly produce a value", expr: queryexpr.SQLExpr(`service in filter(assets, .Service startsWith "T")`),