[#1939] removed redundant COALESCE normalizations
This commit is contained in:
+22
-2
@@ -107,9 +107,15 @@ func buildExpr(
|
||||
|
||||
switch op {
|
||||
case fexpr.SignEq, fexpr.SignAnyEq:
|
||||
expr = dbx.NewExp(fmt.Sprintf("COALESCE(%s, '') = COALESCE(%s, '')", left.Identifier, right.Identifier), mergeParams(left.Params, right.Params))
|
||||
expr = dbx.NewExp(
|
||||
fmt.Sprintf("%s = %s", normalizeNullIdentifier(left), normalizeNullIdentifier(right)),
|
||||
mergeParams(left.Params, right.Params),
|
||||
)
|
||||
case fexpr.SignNeq, fexpr.SignAnyNeq:
|
||||
expr = dbx.NewExp(fmt.Sprintf("COALESCE(%s, '') != COALESCE(%s, '')", left.Identifier, right.Identifier), mergeParams(left.Params, right.Params))
|
||||
expr = dbx.NewExp(
|
||||
fmt.Sprintf("%s != %s", normalizeNullIdentifier(left), normalizeNullIdentifier(right)),
|
||||
mergeParams(left.Params, right.Params),
|
||||
)
|
||||
case fexpr.SignLike, fexpr.SignAnyLike:
|
||||
// the right side is a column and therefor wrap it with "%" for contains like behavior
|
||||
if len(right.Params) == 0 {
|
||||
@@ -232,6 +238,20 @@ func resolveToken(token fexpr.Token, fieldResolver FieldResolver) (*ResolverResu
|
||||
return nil, errors.New("unresolvable token type")
|
||||
}
|
||||
|
||||
func normalizeNullIdentifier(result *ResolverResult) string {
|
||||
lower := strings.ToLower(result.Identifier)
|
||||
|
||||
if lower == "null" {
|
||||
return "''"
|
||||
}
|
||||
|
||||
if strings.Contains(lower, "json_extract(") || strings.Contains(lower, "json_array_length(") {
|
||||
return fmt.Sprintf("COALESCE(%s, '')", result.Identifier)
|
||||
}
|
||||
|
||||
return result.Identifier
|
||||
}
|
||||
|
||||
func isAnyMatchOp(op fexpr.SignOp) bool {
|
||||
switch op {
|
||||
case
|
||||
|
||||
+21
-13
@@ -40,7 +40,8 @@ func TestFilterDataBuildExpr(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"simple expression",
|
||||
"test1 > 1", false,
|
||||
"test1 > 1",
|
||||
false,
|
||||
"^" +
|
||||
regexp.QuoteMeta("[[test1]] > {:") +
|
||||
".+" +
|
||||
@@ -49,14 +50,16 @@ func TestFilterDataBuildExpr(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"like with 2 columns",
|
||||
"test1 ~ test2", false,
|
||||
"test1 ~ test2",
|
||||
false,
|
||||
"^" +
|
||||
regexp.QuoteMeta("[[test1]] LIKE ('%' || [[test2]] || '%') ESCAPE '\\'") +
|
||||
"$",
|
||||
},
|
||||
{
|
||||
"like with right column operand",
|
||||
"'lorem' ~ test1", false,
|
||||
"'lorem' ~ test1",
|
||||
false,
|
||||
"^" +
|
||||
regexp.QuoteMeta("{:") +
|
||||
".+" +
|
||||
@@ -65,7 +68,8 @@ func TestFilterDataBuildExpr(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"like with left column operand and text as right operand",
|
||||
"test1 ~ 'lorem'", false,
|
||||
"test1 ~ 'lorem'",
|
||||
false,
|
||||
"^" +
|
||||
regexp.QuoteMeta("[[test1]] LIKE {:") +
|
||||
".+" +
|
||||
@@ -74,14 +78,16 @@ func TestFilterDataBuildExpr(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"not like with 2 columns",
|
||||
"test1 !~ test2", false,
|
||||
"test1 !~ test2",
|
||||
false,
|
||||
"^" +
|
||||
regexp.QuoteMeta("[[test1]] NOT LIKE ('%' || [[test2]] || '%') ESCAPE '\\'") +
|
||||
"$",
|
||||
},
|
||||
{
|
||||
"not like with right column operand",
|
||||
"'lorem' !~ test1", false,
|
||||
"'lorem' !~ test1",
|
||||
false,
|
||||
"^" +
|
||||
regexp.QuoteMeta("{:") +
|
||||
".+" +
|
||||
@@ -90,7 +96,8 @@ func TestFilterDataBuildExpr(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"like with left column operand and text as right operand",
|
||||
"test1 !~ 'lorem'", false,
|
||||
"test1 !~ 'lorem'",
|
||||
false,
|
||||
"^" +
|
||||
regexp.QuoteMeta("[[test1]] NOT LIKE {:") +
|
||||
".+" +
|
||||
@@ -99,7 +106,8 @@ func TestFilterDataBuildExpr(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"current datetime constant",
|
||||
"test1 > @now", false,
|
||||
"test1 > @now",
|
||||
false,
|
||||
"^" +
|
||||
regexp.QuoteMeta("[[test1]] > {:") +
|
||||
".+" +
|
||||
@@ -113,25 +121,25 @@ func TestFilterDataBuildExpr(t *testing.T) {
|
||||
"^" +
|
||||
regexp.QuoteMeta("(([[test1]] > {:") +
|
||||
".+" +
|
||||
regexp.QuoteMeta("} OR COALESCE([[test2]], '') != COALESCE({:") +
|
||||
regexp.QuoteMeta("} OR [[test2]] != {:") +
|
||||
".+" +
|
||||
regexp.QuoteMeta("}, '')) AND [[test3]] LIKE {:") +
|
||||
regexp.QuoteMeta("}) AND [[test3]] LIKE {:") +
|
||||
".+" +
|
||||
regexp.QuoteMeta("} ESCAPE '\\' AND COALESCE([[test4.sub]], '') = COALESCE(NULL, ''))") +
|
||||
regexp.QuoteMeta("} ESCAPE '\\' AND [[test4.sub]] = '')") +
|
||||
"$",
|
||||
},
|
||||
{
|
||||
"combination of special literals (null, true, false)",
|
||||
"test1=true && test2 != false && test3 = null || test4.sub != null",
|
||||
false,
|
||||
"^" + regexp.QuoteMeta("(COALESCE([[test1]], '') = COALESCE(1, '') AND COALESCE([[test2]], '') != COALESCE(0, '') AND COALESCE([[test3]], '') = COALESCE(NULL, '') OR COALESCE([[test4.sub]], '') != COALESCE(NULL, ''))") + "$",
|
||||
"^" + regexp.QuoteMeta("([[test1]] = 1 AND [[test2]] != 0 AND [[test3]] = '' OR [[test4.sub]] != '')") + "$",
|
||||
},
|
||||
{
|
||||
"all operators",
|
||||
"(test1 = test2 || test2 != test3) && (test2 ~ 'example' || test2 !~ '%%abc') && 'switch1%%' ~ test1 && 'switch2' !~ test2 && test3 > 1 && test3 >= 0 && test3 <= 4 && 2 < 5",
|
||||
false,
|
||||
"^" +
|
||||
regexp.QuoteMeta("((COALESCE([[test1]], '') = COALESCE([[test2]], '') OR COALESCE([[test2]], '') != COALESCE([[test3]], '')) AND ([[test2]] LIKE {:") +
|
||||
regexp.QuoteMeta("(([[test1]] = [[test2]] OR [[test2]] != [[test3]]) AND ([[test2]] LIKE {:") +
|
||||
".+" +
|
||||
regexp.QuoteMeta("} ESCAPE '\\' OR [[test2]] NOT LIKE {:") +
|
||||
".+" +
|
||||
|
||||
@@ -274,8 +274,8 @@ func TestProviderExecNonEmptyQuery(t *testing.T) {
|
||||
false,
|
||||
`{"page":1,"perPage":` + fmt.Sprint(MaxPerPage) + `,"totalItems":1,"totalPages":1,"items":[{"test1":2,"test2":"test2.2","test3":""}]}`,
|
||||
[]string{
|
||||
"SELECT COUNT(DISTINCT [[test.id]]) FROM `test` WHERE ((NOT (`test1` IS NULL)) AND (COALESCE(test2, '') != COALESCE(null, ''))) AND (test1 >= 2)",
|
||||
"SELECT * FROM `test` WHERE ((NOT (`test1` IS NULL)) AND (COALESCE(test2, '') != COALESCE(null, ''))) AND (test1 >= 2) ORDER BY `test1` ASC, `test2` DESC LIMIT 500",
|
||||
"SELECT COUNT(DISTINCT [[test.id]]) FROM `test` WHERE ((NOT (`test1` IS NULL)) AND (test2 != '')) AND (test1 >= 2)",
|
||||
"SELECT * FROM `test` WHERE ((NOT (`test1` IS NULL)) AND (test2 != '')) AND (test1 >= 2) ORDER BY `test1` ASC, `test2` DESC LIMIT 500",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -287,8 +287,8 @@ func TestProviderExecNonEmptyQuery(t *testing.T) {
|
||||
false,
|
||||
`{"page":1,"perPage":10,"totalItems":0,"totalPages":0,"items":[]}`,
|
||||
[]string{
|
||||
"SELECT COUNT(DISTINCT [[test.id]]) FROM `test` WHERE (NOT (`test1` IS NULL)) AND (COALESCE(test3, '') != COALESCE('', ''))",
|
||||
"SELECT * FROM `test` WHERE (NOT (`test1` IS NULL)) AND (COALESCE(test3, '') != COALESCE('', '')) ORDER BY `test1` ASC, `test3` ASC LIMIT 10",
|
||||
"SELECT COUNT(DISTINCT [[test.id]]) FROM `test` WHERE (NOT (`test1` IS NULL)) AND (test3 != '')",
|
||||
"SELECT * FROM `test` WHERE (NOT (`test1` IS NULL)) AND (test3 != '') ORDER BY `test1` ASC, `test3` ASC LIMIT 10",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user