[#1939] removed redundant COALESCE normalizations

This commit is contained in:
Gani Georgiev
2023-03-23 19:30:35 +02:00
parent 5cbdbf6c10
commit 67ecebe935
9 changed files with 81 additions and 44 deletions
+22 -2
View File
@@ -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
View File
@@ -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 {:") +
".+" +
+4 -4
View File
@@ -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",
},
},
{