3
0

Fix SQLite date formatting

* Add missing mappings,
* add validation for supported substitutions.
This commit is contained in:
Tomaž Jerman 2022-03-21 12:28:53 +01:00 committed by Denis Arh
parent 0534096ad2
commit c64a98e36c
2 changed files with 49 additions and 2 deletions

View File

@ -2,6 +2,7 @@ package sqlite3
import (
"fmt"
"regexp"
"strings"
"github.com/cortezaproject/corteza-server/pkg/ql"
@ -103,6 +104,19 @@ var (
return
},
}
supportedSubstitutions = map[string]bool{
"d": true,
"H": true,
"j": true,
"m": true,
"M": true,
"S": true,
"w": true,
"W": true,
"Y": true,
"%": true,
}
)
func sqlASTFormatter(n *qlng.ASTNode) rdbms.HandlerSig {
@ -123,7 +137,15 @@ func sqlFunctionHandler(f ql.Function) (ql.ASTNode, error) {
if len(f.Arguments) != 2 {
return nil, fmt.Errorf("expecting exactly two arguments for DATE_FORMAT function")
}
return ql.MakeFormattedNode("STRFTIME('%s', %s)", f.Arguments[0], f.Arguments[1]), nil
format := f.Arguments[1]
col := f.Arguments[0]
err := supportedDateFormatParams(format)
if err != nil {
return nil, err
}
return ql.MakeReplacedFormattedNode("STRFTIME(%s, %s)", translateDateFormatParams, format, col), nil
case "DATE":
// need to convert back to datetime so it can be converted to time.Time
return ql.MakeFormattedNode("STRFTIME('%%Y-%%m-%%dT00:00:00Z', %s)", f.Arguments...), nil
@ -133,3 +155,28 @@ func sqlFunctionHandler(f ql.Function) (ql.ASTNode, error) {
return f, nil
}
func supportedDateFormatParams(fmtNode ql.ASTNode) error {
format := translateDateFormatParams(fmtNode.String())
r := regexp.MustCompile(`%(?P<sub>.)`)
for _, m := range r.FindAllStringSubmatch(format, -1) {
if len(m) == 0 {
continue
}
if _, ok := supportedSubstitutions[m[1]]; !ok {
return fmt.Errorf("format substitution not supported: %%%s", m[1])
}
}
return nil
}
func translateDateFormatParams(format string) string {
return strings.NewReplacer(
`%i`, `%M`,
`%U`, `%W`,
).Replace(format)
}

View File

@ -1606,7 +1606,7 @@ func testComposeRecords(t *testing.T, s store.ComposeRecords) {
req.NoError(err)
req.Len(report, 3)
report, err = s.ComposeRecordReport(ctx, mod, "MAX(num1)", "DATE_FORMAT(dt1, '%y; %j @ %H %i %p')", "")
report, err = s.ComposeRecordReport(ctx, mod, "MAX(num1)", "DATE_FORMAT(dt1, '%Y; %j @ %H %i')", "")
req.NoError(err)
req.Len(report, 3)
})