revise FilterToSQLQuery function

This commit is contained in:
arberkatellari
2025-10-24 17:02:10 +02:00
committed by Dan Christian Bogos
parent c9115da4b7
commit 082c412159
2 changed files with 167 additions and 19 deletions

View File

@@ -876,6 +876,11 @@ func (fltr *FilterRule) FilterToSQLQuery() (conditions []string) {
var restOfItems string // Excluding ~*req, hold the rest of the items past the first one. If only 1 item in all element, holds that item. e.g. "Charges[0].RatingID" out of ~*req.cost_details.Charges[0].RatingID or "answer_time" out of ~*req.answer_time
not := strings.HasPrefix(fltr.Type, utils.MetaNot)
elementItems := fltr.ElementItems()[1:] // exclude first item: ~*req
for i := range elementItems { // encapsulate with "" strings starting with *
if strings.HasPrefix(elementItems[i], utils.Meta) {
elementItems[i] = "\"" + elementItems[i] + "\""
}
}
if len(elementItems) > 1 {
firstItem = elementItems[0]
restOfItems = strings.Join(elementItems[1:], utils.NestingSep)
@@ -892,7 +897,11 @@ func (fltr *FilterRule) FilterToSQLQuery() (conditions []string) {
conditions = append(conditions, fmt.Sprintf("%s IS NULL", restOfItems))
return
}
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') IS NULL", firstItem, restOfItems))
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') IS NULL", firstItem, restOfItems)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
conditions = append(conditions, queryPart)
return
}
// existing means Column IS NOT NULL
@@ -900,21 +909,33 @@ func (fltr *FilterRule) FilterToSQLQuery() (conditions []string) {
conditions = append(conditions, fmt.Sprintf("%s IS NOT NULL", restOfItems))
return
}
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') IS NOT NULL", firstItem, restOfItems))
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') IS NOT NULL", firstItem, restOfItems)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
conditions = append(conditions, queryPart)
case utils.MetaEmpty, utils.MetaNotEmpty:
if not {
if firstItem == utils.EmptyString {
conditions = append(conditions, fmt.Sprintf("%s != ''", restOfItems))
return
}
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') != ''", firstItem, restOfItems))
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') != ''", firstItem, restOfItems)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
conditions = append(conditions, queryPart)
return
}
if firstItem == utils.EmptyString {
conditions = append(conditions, fmt.Sprintf("%s == ''", restOfItems))
return
}
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') == ''", firstItem, restOfItems))
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') == ''", firstItem, restOfItems)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
conditions = append(conditions, queryPart)
}
return
}
@@ -934,14 +955,22 @@ func (fltr *FilterRule) FilterToSQLQuery() (conditions []string) {
conditions = append(conditions, fmt.Sprintf("%s != '%s'", restOfItems, value))
continue
}
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') != '%s'",
firstItem, restOfItems, value))
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') != '%s'",
firstItem, restOfItems, value)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
conditions = append(conditions, queryPart)
continue
}
if firstItem == utils.EmptyString {
singleCond = fmt.Sprintf("%s = '%s'", restOfItems, value)
} else {
singleCond = fmt.Sprintf("JSON_VALUE(%s, '$.%s') = '%s'", firstItem, restOfItems, value)
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') = '%s'", firstItem, restOfItems, value)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
singleCond = queryPart
}
case utils.MetaLessThan, utils.MetaLessOrEqual, utils.MetaGreaterThan, utils.MetaGreaterOrEqual:
parsedValAny := utils.StringToInterface(value)
@@ -950,25 +979,41 @@ func (fltr *FilterRule) FilterToSQLQuery() (conditions []string) {
if firstItem == utils.EmptyString {
singleCond = fmt.Sprintf("%s >= '%v'", restOfItems, parsedValAny)
} else {
singleCond = fmt.Sprintf("JSON_VALUE(%s, '$.%s') >= '%v'", firstItem, restOfItems, parsedValAny)
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') >= '%v'", firstItem, restOfItems, parsedValAny)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
singleCond = queryPart
}
case utils.MetaGreaterThan:
if firstItem == utils.EmptyString {
singleCond = fmt.Sprintf("%s > '%v'", restOfItems, parsedValAny)
} else {
singleCond = fmt.Sprintf("JSON_VALUE(%s, '$.%s') > '%v'", firstItem, restOfItems, parsedValAny)
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') > '%v'", firstItem, restOfItems, parsedValAny)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
singleCond = queryPart
}
case utils.MetaLessOrEqual:
if firstItem == utils.EmptyString {
singleCond = fmt.Sprintf("%s <= '%v'", restOfItems, parsedValAny)
} else {
singleCond = fmt.Sprintf("JSON_VALUE(%s, '$.%s') <= '%v'", firstItem, restOfItems, parsedValAny)
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') <= '%v'", firstItem, restOfItems, parsedValAny)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
singleCond = queryPart
}
case utils.MetaLessThan:
if firstItem == utils.EmptyString {
singleCond = fmt.Sprintf("%s < '%v'", restOfItems, parsedValAny)
} else {
singleCond = fmt.Sprintf("JSON_VALUE(%s, '$.%s') < '%v'", firstItem, restOfItems, parsedValAny)
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') < '%v'", firstItem, restOfItems, parsedValAny)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
singleCond = queryPart
}
}
case utils.MetaPrefix, utils.MetaNotPrefix:
@@ -977,13 +1022,21 @@ func (fltr *FilterRule) FilterToSQLQuery() (conditions []string) {
conditions = append(conditions, fmt.Sprintf("%s NOT LIKE '%s%%'", restOfItems, value))
continue
}
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') NOT LIKE '%s%%'", firstItem, restOfItems, value))
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') NOT LIKE '%s%%'", firstItem, restOfItems, value)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
conditions = append(conditions, queryPart)
continue
}
if firstItem == utils.EmptyString {
singleCond = fmt.Sprintf("%s LIKE '%s%%'", restOfItems, value)
} else {
singleCond = fmt.Sprintf("JSON_VALUE(%s, '$.%s') LIKE '%s%%'", firstItem, restOfItems, value)
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') LIKE '%s%%'", firstItem, restOfItems, value)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
singleCond = queryPart
}
case utils.MetaSuffix, utils.MetaNotSuffix:
if not {
@@ -991,13 +1044,21 @@ func (fltr *FilterRule) FilterToSQLQuery() (conditions []string) {
conditions = append(conditions, fmt.Sprintf("%s NOT LIKE '%%%s'", restOfItems, value))
continue
}
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') NOT LIKE '%%%s'", firstItem, restOfItems, value))
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') NOT LIKE '%%%s'", firstItem, restOfItems, value)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
conditions = append(conditions, queryPart)
continue
}
if firstItem == utils.EmptyString {
singleCond = fmt.Sprintf("%s LIKE '%%%s'", restOfItems, value)
} else {
singleCond = fmt.Sprintf("JSON_VALUE(%s, '$.%s') LIKE '%%%s'", firstItem, restOfItems, value)
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') LIKE '%%%s'", firstItem, restOfItems, value)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
singleCond = queryPart
}
case utils.MetaRegex, utils.MetaNotRegex:
if not {
@@ -1005,13 +1066,21 @@ func (fltr *FilterRule) FilterToSQLQuery() (conditions []string) {
conditions = append(conditions, fmt.Sprintf("%s NOT REGEXP '%s'", restOfItems, value))
continue
}
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') NOT REGEXP '%s'", firstItem, restOfItems, value))
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') NOT REGEXP '%s'", firstItem, restOfItems, value)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
conditions = append(conditions, queryPart)
continue
}
if firstItem == utils.EmptyString {
singleCond = fmt.Sprintf("%s REGEXP '%s'", restOfItems, value)
} else {
singleCond = fmt.Sprintf("JSON_VALUE(%s, '$.%s') REGEXP '%s'", firstItem, restOfItems, value)
queryPart := fmt.Sprintf("JSON_VALUE(%s, '$.%s') REGEXP '%s'", firstItem, restOfItems, value)
if strings.HasPrefix(restOfItems, `"*`) {
queryPart = fmt.Sprintf("JSON_UNQUOTE(%s)", queryPart)
}
singleCond = queryPart
}
}
conditions = append(conditions, singleCond)

View File

@@ -3324,6 +3324,15 @@ func TestFilterToSQLQueryValidations(t *testing.T) {
},
expected: []string{"JSON_VALUE(data, '$.name') LIKE 'prefix%'"},
},
{
name: "Prefix LIKE with * column with JSON_VALUE",
fltrRule: FilterRule{
Type: utils.MetaPrefix,
Element: "~*req.data.*name",
Values: []string{"prefix"},
},
expected: []string{`JSON_UNQUOTE(JSON_VALUE(data, '$."*name"') LIKE 'prefix%')`},
},
{
name: "Suffix NOT LIKE with empty beforeSep",
fltrRule: FilterRule{
@@ -3342,6 +3351,15 @@ func TestFilterToSQLQueryValidations(t *testing.T) {
},
expected: []string{"JSON_VALUE(data, '$.name') LIKE '%suffix'"},
},
{
name: "Suffix LIKE with * column with JSON_VALUE",
fltrRule: FilterRule{
Type: utils.MetaSuffix,
Element: "~*req.data.*name",
Values: []string{"suffix"},
},
expected: []string{`JSON_UNQUOTE(JSON_VALUE(data, '$."*name"') LIKE '%suffix')`},
},
{
name: "Regex NOT REGEXP with empty beforeSep",
fltrRule: FilterRule{
@@ -3360,7 +3378,15 @@ func TestFilterToSQLQueryValidations(t *testing.T) {
},
expected: []string{"JSON_VALUE(data, '$.pattern') REGEXP '[0-9]+'"},
},
{
name: "Regex REGEXP with * column with JSON_VALUE",
fltrRule: FilterRule{
Type: utils.MetaRegex,
Element: "~*req.data.*pattern",
Values: []string{"[0-9]+"},
},
expected: []string{`JSON_UNQUOTE(JSON_VALUE(data, '$."*pattern"') REGEXP '[0-9]+')`},
},
{
name: "Not equal with empty beforeSep",
fltrRule: FilterRule{
@@ -3379,6 +3405,15 @@ func TestFilterToSQLQueryValidations(t *testing.T) {
},
expected: []string{"JSON_VALUE(data, '$.status') = 'active'"},
},
{
name: "Equal condition with * column with JSON_VALUE",
fltrRule: FilterRule{
Type: utils.MetaString,
Element: "~*req.data.*status",
Values: []string{"active"},
},
expected: []string{`JSON_UNQUOTE(JSON_VALUE(data, '$."*status"') = 'active')`},
},
{
name: "Greater than condition with JSON_VALUE",
fltrRule: FilterRule{
@@ -3388,6 +3423,15 @@ func TestFilterToSQLQueryValidations(t *testing.T) {
},
expected: []string{"JSON_VALUE(data, '$.score') > '50'"},
},
{
name: "Greater than condition with * column with JSON_VALUE",
fltrRule: FilterRule{
Type: utils.MetaGreaterThan,
Element: "~*req.data.*score",
Values: []string{"50"},
},
expected: []string{`JSON_UNQUOTE(JSON_VALUE(data, '$."*score"') > '50')`},
},
{
name: "Less than or equal condition with JSON_VALUE",
fltrRule: FilterRule{
@@ -3397,6 +3441,15 @@ func TestFilterToSQLQueryValidations(t *testing.T) {
},
expected: []string{"JSON_VALUE(data, '$.score') <= '30'"},
},
{
name: "Less than or equal condition with * column with JSON_VALUE",
fltrRule: FilterRule{
Type: utils.MetaLessOrEqual,
Element: "~*req.data.*score",
Values: []string{"30"},
},
expected: []string{`JSON_UNQUOTE(JSON_VALUE(data, '$."*score"') <= '30')`},
},
{
name: "Less than condition with JSON_VALUE",
fltrRule: FilterRule{
@@ -3406,7 +3459,15 @@ func TestFilterToSQLQueryValidations(t *testing.T) {
},
expected: []string{"JSON_VALUE(data, '$.score') < '20'"},
},
{
name: "Less than condition with * column with JSON_VALUE",
fltrRule: FilterRule{
Type: utils.MetaLessThan,
Element: "~*req.data.*score",
Values: []string{"20"},
},
expected: []string{`JSON_UNQUOTE(JSON_VALUE(data, '$."*score"') < '20')`},
},
{
name: "MetaExists with no values",
fltrRule: FilterRule{
@@ -3425,6 +3486,15 @@ func TestFilterToSQLQueryValidations(t *testing.T) {
},
expected: []string{"JSON_VALUE(json_field, '$.key') IS NULL"},
},
{
name: "MetaNotExists with *column with no values",
fltrRule: FilterRule{
Type: utils.MetaNotExists,
Element: "~*req.json_field.*key",
Values: nil,
},
expected: []string{`JSON_UNQUOTE(JSON_VALUE(json_field, '$."*key"') IS NULL)`},
},
{
name: "MetaString with values",
fltrRule: FilterRule{
@@ -3443,6 +3513,15 @@ func TestFilterToSQLQueryValidations(t *testing.T) {
},
expected: []string{"JSON_VALUE(json_field, '$.key') NOT LIKE 'prefix1%'"},
},
{
name: "MetaPrefix with *column name NOT condition",
fltrRule: FilterRule{
Type: utils.MetaNotPrefix,
Element: "~*req.json_field.*key",
Values: []string{"prefix1"},
},
expected: []string{`JSON_UNQUOTE(JSON_VALUE(json_field, '$."*key"') NOT LIKE 'prefix1%')`},
},
{
name: "MetaRegex with multiple values",
fltrRule: FilterRule{