Allow format QL nodes to properly format their arguents
This commit is contained in:
parent
3a1d62d2a1
commit
d700d76c39
@ -2,8 +2,9 @@ package ql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Masterminds/squirrel"
|
||||
"strings"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
)
|
||||
|
||||
// SelectStatement represents a SQL SELECT statement.
|
||||
@ -15,6 +16,8 @@ type (
|
||||
Validate() error
|
||||
}
|
||||
|
||||
replacer func(string) string
|
||||
|
||||
ASTSet []ASTNode // Stream of comma delimited nodes
|
||||
ASTNodes []ASTNode // Stream of space delimited nodes
|
||||
|
||||
@ -63,6 +66,7 @@ type (
|
||||
NodeF struct {
|
||||
Expr string
|
||||
Arguments []ASTNode
|
||||
replacer replacer
|
||||
}
|
||||
)
|
||||
|
||||
@ -219,6 +223,11 @@ func (nn Columns) Strings() (out []string) {
|
||||
return
|
||||
}
|
||||
|
||||
// MakeReplacedFormattedNode also accepts the replacer to apply to the arguments
|
||||
func MakeReplacedFormattedNode(expr string, r replacer, nn ...ASTNode) *NodeF {
|
||||
return &NodeF{Expr: expr, Arguments: nn, replacer: r}
|
||||
}
|
||||
|
||||
func MakeFormattedNode(expr string, nn ...ASTNode) *NodeF {
|
||||
return &NodeF{Expr: expr, Arguments: nn}
|
||||
}
|
||||
|
||||
@ -127,7 +127,18 @@ func (n NodeF) ToSql() (string, []interface{}, error) {
|
||||
adtArgs []interface{}
|
||||
)
|
||||
|
||||
for _, s := range n.Arguments {
|
||||
for i, s := range n.Arguments {
|
||||
// When provided, apply the replacer over the arguments of the node.
|
||||
// We can skip any node other then LString as thats the only one we can apply it to (currently)
|
||||
if n.replacer != nil {
|
||||
if c, ok := s.(LString); ok {
|
||||
c.Value = n.replacer(c.Value)
|
||||
// Updating the originals as we're dealing with values
|
||||
n.Arguments[i] = c
|
||||
s = c
|
||||
}
|
||||
}
|
||||
|
||||
if fa, aa, err := s.ToSql(); err != nil {
|
||||
return "", nil, err
|
||||
} else {
|
||||
|
||||
@ -42,7 +42,7 @@ func sqlFunctionHandler(f ql.Function) (ql.ASTNode, error) {
|
||||
case "QUARTER", "YEAR":
|
||||
return ql.MakeFormattedNode(fmt.Sprintf("EXTRACT(%s FROM %%s::date)", f.Name), f.Arguments...), nil
|
||||
case "DATE_FORMAT":
|
||||
return ql.MakeFormattedNode("TO_CHAR(%s, %s)", f.Arguments...), nil
|
||||
return ql.MakeReplacedFormattedNode("TO_CHAR(%s, %s)", translateDateFormatParams, f.Arguments...), nil
|
||||
case "DATE":
|
||||
return ql.MakeFormattedNode("%s::DATE", f.Arguments...), nil
|
||||
case "DATE_ADD", "DATE_SUB", "STD":
|
||||
|
||||
@ -1567,35 +1567,48 @@ func testComposeRecords(t *testing.T, s store.ComposeRecords) {
|
||||
report []map[string]interface{}
|
||||
)
|
||||
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "MAX(num1)", "QUARTER(dt1)", "")
|
||||
req.NoError(err)
|
||||
req.Len(report, 3)
|
||||
t.Run("base", func(t *testing.T) {
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "MAX(num1)", "QUARTER(dt1)", "")
|
||||
req.NoError(err)
|
||||
req.Len(report, 3)
|
||||
|
||||
// @todo find a way to compare the results
|
||||
// @todo find a way to compare the results
|
||||
|
||||
//expected := []map[string]interface{}{
|
||||
// {"count": 3, "dimension_0": 1, "metric_0": 3},
|
||||
// {"count": 2, "dimension_0": 2, "metric_0": 5},
|
||||
// {"count": 1, "dimension_0": nil, "metric_0": nil},
|
||||
//}
|
||||
//
|
||||
//req.True(
|
||||
// reflect.DeepEqual(report, expected),
|
||||
// "report does not match expected results:\n%#v\n%#v", report, expected)
|
||||
//expected := []map[string]interface{}{
|
||||
// {"count": 3, "dimension_0": 1, "metric_0": 3},
|
||||
// {"count": 2, "dimension_0": 2, "metric_0": 5},
|
||||
// {"count": 1, "dimension_0": nil, "metric_0": nil},
|
||||
//}
|
||||
//
|
||||
//req.True(
|
||||
// reflect.DeepEqual(report, expected),
|
||||
// "report does not match expected results:\n%#v\n%#v", report, expected)
|
||||
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "COUNT(num1)", "YEAR(dt1)", "")
|
||||
req.NoError(err)
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "COUNT(num1)", "YEAR(dt1)", "")
|
||||
req.NoError(err)
|
||||
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "SUM(num1)", "DATE(dt1)", "")
|
||||
req.NoError(err)
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "SUM(num1)", "DATE(dt1)", "")
|
||||
req.NoError(err)
|
||||
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "MIN(num1)", "DATE(NOW())", "")
|
||||
req.NoError(err)
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "MIN(num1)", "DATE(NOW())", "")
|
||||
req.NoError(err)
|
||||
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "AVG(num1)", "DATE(NOW())", "")
|
||||
req.NoError(err)
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "AVG(num1)", "DATE(NOW())", "")
|
||||
req.NoError(err)
|
||||
|
||||
// Note that not all functions are compatible across all backends
|
||||
})
|
||||
|
||||
t.Run("date formatting", func(t *testing.T) {
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "MAX(num1)", "DATE_FORMAT(dt1, '%Y-%m-01')", "")
|
||||
req.NoError(err)
|
||||
req.Len(report, 3)
|
||||
|
||||
report, err = s.ComposeRecordReport(ctx, mod, "MAX(num1)", "DATE_FORMAT(dt1, '%y; %j @ %H %i %p')", "")
|
||||
req.NoError(err)
|
||||
req.Len(report, 3)
|
||||
})
|
||||
|
||||
// Note that not all functions are compatible across all backends
|
||||
})
|
||||
|
||||
t.Run("partial value update", func(t *testing.T) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user