Improve filters validation

This commit is contained in:
arberkatellari
2025-06-30 17:03:22 +02:00
committed by Dan Christian Bogos
parent d7254ff73c
commit 73667f343f
4 changed files with 253 additions and 22 deletions

View File

@@ -823,6 +823,12 @@ func CheckFilter(fltr *Filter) (err error) {
return fmt.Errorf("%s for filter <%v>", err, fltr) //encapsulated error
}
for _, val := range rls.Values {
if rls.Type == utils.MetaEmpty || rls.Type == utils.MetaNotEmpty ||
rls.Type == utils.MetaExists || rls.Type == utils.MetaNotExists &&
val != utils.EmptyString {
return fmt.Errorf("value of filter <%s> is not empty <%s>",
fltr.ID, val)
}
if err = valFunc(val); err != nil {
return fmt.Errorf("%s for filter <%v>", err, fltr) //encapsulated error
}
@@ -881,19 +887,20 @@ func (fltr *FilterRule) FilterToSQLQuery() (conditions []string) {
if len(fltr.Values) == 0 {
switch fltr.Type {
case utils.MetaExists, utils.MetaNotExists:
if not {
if not { // not existing means Column IS NULL
if firstItem == utils.EmptyString {
conditions = append(conditions, fmt.Sprintf("%s IS NOT NULL", restOfItems))
conditions = append(conditions, fmt.Sprintf("%s IS NULL", restOfItems))
return
}
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') IS NOT NULL", firstItem, restOfItems))
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') IS NULL", firstItem, restOfItems))
return
}
// existing means Column IS NOT NULL
if firstItem == utils.EmptyString {
conditions = append(conditions, fmt.Sprintf("%s IS NULL", restOfItems))
conditions = append(conditions, fmt.Sprintf("%s IS NOT NULL", restOfItems))
return
}
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') IS NULL", firstItem, restOfItems))
conditions = append(conditions, fmt.Sprintf("JSON_VALUE(%s, '$.%s') IS NOT NULL", firstItem, restOfItems))
case utils.MetaEmpty, utils.MetaNotEmpty:
if not {
if firstItem == utils.EmptyString {
@@ -938,25 +945,26 @@ func (fltr *FilterRule) FilterToSQLQuery() (conditions []string) {
}
case utils.MetaLessThan, utils.MetaLessOrEqual, utils.MetaGreaterThan, utils.MetaGreaterOrEqual:
parsedValAny := utils.StringToInterface(value)
if fltr.Type == utils.MetaGreaterOrEqual {
switch fltr.Type {
case utils.MetaGreaterOrEqual:
if firstItem == utils.EmptyString {
singleCond = fmt.Sprintf("%s >= '%v'", restOfItems, parsedValAny)
} else {
singleCond = fmt.Sprintf("JSON_VALUE(%s, '$.%s') >= '%v'", firstItem, restOfItems, parsedValAny)
}
} else if fltr.Type == utils.MetaGreaterThan {
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)
}
} else if fltr.Type == utils.MetaLessOrEqual {
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)
}
} else if fltr.Type == utils.MetaLessThan {
case utils.MetaLessThan:
if firstItem == utils.EmptyString {
singleCond = fmt.Sprintf("%s < '%v'", restOfItems, parsedValAny)
} else {

View File

@@ -2446,6 +2446,24 @@ func TestCheckFilterErr(t *testing.T) {
}
}
func TestCheckFilterNotEmptyErr(t *testing.T) {
fltr := &Filter{
Tenant: "cgrates.org",
ID: "TestFilter",
Rules: []*FilterRule{
{
Type: utils.MetaNotEmpty,
Element: "~*req.Account",
Values: []string{"''"},
},
},
}
expErr := `value of filter <TestFilter> is not empty <''>`
if err := CheckFilter(fltr); err == nil || err.Error() != expErr {
t.Error(err)
}
}
func TestFilterPassRegexErr(t *testing.T) {
cd := &CallDescriptor{
Category: "callx",
@@ -3169,13 +3187,13 @@ func TestFilterToSQLQuery(t *testing.T) {
}{
{"MetaEqual with values", FilterRule{Type: utils.MetaEqual, Element: "~*req.cost_details.Charges[0].RatingID", Values: []string{"RatingID2"}}, []string{"JSON_VALUE(cost_details, '$.Charges[0].RatingID') = 'RatingID2'"}},
{"MetaExists with no values", FilterRule{Type: utils.MetaExists, Element: "~*req.answer_time", Values: nil}, []string{"answer_time IS NULL"}},
{"MetaExists with no values", FilterRule{Type: utils.MetaExists, Element: "~*req.answer_time", Values: nil}, []string{"answer_time IS NOT NULL"}},
{"MetaExists with JSON field", FilterRule{Type: utils.MetaExists, Element: "~*req.cost_details.Charges[0].RatingID", Values: nil}, []string{"JSON_VALUE(cost_details, '$.Charges[0].RatingID') IS NULL"}},
{"MetaExists with JSON field", FilterRule{Type: utils.MetaExists, Element: "~*req.cost_details.Charges[0].RatingID", Values: nil}, []string{"JSON_VALUE(cost_details, '$.Charges[0].RatingID') IS NOT NULL"}},
{"MetaNotExists with no values", FilterRule{Type: utils.MetaNotExists, Element: "~*req.answer_time", Values: nil}, []string{"answer_time IS NOT NULL"}},
{"MetaNotExists with no values", FilterRule{Type: utils.MetaNotExists, Element: "~*req.answer_time", Values: nil}, []string{"answer_time IS NULL"}},
{"MetaNotExists with JSON field", FilterRule{Type: utils.MetaNotExists, Element: "~*req.cost_details.Charges[0].RatingID", Values: nil}, []string{"JSON_VALUE(cost_details, '$.Charges[0].RatingID') IS NOT NULL"}},
{"MetaNotExists with JSON field", FilterRule{Type: utils.MetaNotExists, Element: "~*req.cost_details.Charges[0].RatingID", Values: nil}, []string{"JSON_VALUE(cost_details, '$.Charges[0].RatingID') IS NULL"}},
{"MetaString with values", FilterRule{Type: utils.MetaString, Element: "~*req.answer_time", Values: []string{"value1", "value2"}}, []string{"answer_time = 'value1'", "answer_time = 'value2'"}},
@@ -3396,7 +3414,7 @@ func TestFilterToSQLQueryValidations(t *testing.T) {
Element: "~*req.column1",
Values: nil,
},
expected: []string{"column1 IS NULL"},
expected: []string{"column1 IS NOT NULL"},
},
{
name: "MetaNotExists with no values",
@@ -3405,7 +3423,7 @@ func TestFilterToSQLQueryValidations(t *testing.T) {
Element: "~*req.json_field.key",
Values: nil,
},
expected: []string{"JSON_VALUE(json_field, '$.key') IS NOT NULL"},
expected: []string{"JSON_VALUE(json_field, '$.key') IS NULL"},
},
{
name: "MetaString with values",