Skip to content

Commit

Permalink
fix: issues with like and ilike fixed in v4 qb (#6018)
Browse files Browse the repository at this point in the history
  • Loading branch information
nityanandagohain committed Sep 19, 2024
1 parent 2f7d208 commit 8eb2cf1
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 16 deletions.
16 changes: 9 additions & 7 deletions pkg/query-service/app/logs/v4/query_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,21 +146,23 @@ func buildAttributeFilter(item v3.FilterItem) (string, error) {

return fmt.Sprintf(logsOp, keyName, fmtVal), nil
case v3.FilterOperatorContains, v3.FilterOperatorNotContains:
// we also want to treat %, _ as literals for contains
val := utils.QuoteEscapedStringForContains(fmt.Sprintf("%s", item.Value))
// for body the contains is case insensitive
if keyName == BODY {
return fmt.Sprintf("lower(%s) %s lower('%%%s%%')", keyName, logsOp, val), nil
} else {
return fmt.Sprintf("%s %s '%%%s%%'", keyName, logsOp, val), nil
}
default:
// for use lower for like and ilike
if op == v3.FilterOperatorLike || op == v3.FilterOperatorNotLike {
if keyName == BODY {
keyName = fmt.Sprintf("lower(%s)", keyName)
fmtVal = fmt.Sprintf("lower(%s)", fmtVal)
}
case v3.FilterOperatorLike, v3.FilterOperatorNotLike:
// for body use lower for like and ilike
val := utils.QuoteEscapedString(fmt.Sprintf("%s", item.Value))
if keyName == BODY {
return fmt.Sprintf("lower(%s) %s lower('%s')", keyName, logsOp, val), nil
} else {
return fmt.Sprintf("%s %s '%s'", keyName, logsOp, val), nil
}
default:
return fmt.Sprintf("%s %s %s", keyName, logsOp, fmtVal), nil
}
} else {
Expand Down
4 changes: 2 additions & 2 deletions pkg/query-service/app/logs/v4/query_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,10 +277,10 @@ func Test_buildAttributeFilter(t *testing.T) {
Type: v3.AttributeKeyTypeResource,
},
Operator: v3.FilterOperatorLike,
Value: "test",
Value: "test%",
},
},
want: "resources_string['service.name'] LIKE 'test'",
want: "resources_string['service.name'] LIKE 'test%'",
},
{
name: "build attribute filter like-body",
Expand Down
17 changes: 14 additions & 3 deletions pkg/query-service/app/logs/v4/resource_query_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ func buildResourceFilter(logsOp string, key string, op v3.FilterOperator, value
return fmt.Sprintf(logsOp, searchKey, chFmtVal)
case v3.FilterOperatorContains, v3.FilterOperatorNotContains:
// this is required as clickhouseFormattedValue add's quotes to the string
// we also want to treat %, _ as literals for contains
escapedStringValue := utils.QuoteEscapedStringForContains(fmt.Sprintf("%s", value))
return fmt.Sprintf("%s %s '%%%s%%'", searchKey, logsOp, escapedStringValue)
case v3.FilterOperatorLike, v3.FilterOperatorNotLike:
// this is required as clickhouseFormattedValue add's quotes to the string
escapedStringValue := utils.QuoteEscapedString(fmt.Sprintf("%s", value))
return fmt.Sprintf("%s %s '%s'", searchKey, logsOp, escapedStringValue)
default:
return fmt.Sprintf("%s %s %s", searchKey, logsOp, chFmtVal)
}
Expand Down Expand Up @@ -74,13 +79,19 @@ func buildIndexFilterForInOperator(key string, op v3.FilterOperator, value inter
// example:= x like '%john%' = labels like '%x%john%'
func buildResourceIndexFilter(key string, op v3.FilterOperator, value interface{}) string {
// not using clickhouseFormattedValue as we don't wan't the quotes
formattedValueEscaped := utils.QuoteEscapedStringForContains(fmt.Sprintf("%s", value))
strVal := fmt.Sprintf("%s", value)
formattedValueEscapedForContains := utils.QuoteEscapedStringForContains(strVal)
formattedValueEscaped := utils.QuoteEscapedString(strVal)

// add index filters
switch op {
case v3.FilterOperatorContains, v3.FilterOperatorEqual, v3.FilterOperatorLike:
case v3.FilterOperatorContains:
return fmt.Sprintf("labels like '%%%s%%%s%%'", key, formattedValueEscapedForContains)
case v3.FilterOperatorNotContains:
return fmt.Sprintf("labels not like '%%%s%%%s%%'", key, formattedValueEscapedForContains)
case v3.FilterOperatorLike, v3.FilterOperatorEqual:
return fmt.Sprintf("labels like '%%%s%%%s%%'", key, formattedValueEscaped)
case v3.FilterOperatorNotContains, v3.FilterOperatorNotEqual, v3.FilterOperatorNotLike:
case v3.FilterOperatorNotLike, v3.FilterOperatorNotEqual:
return fmt.Sprintf("labels not like '%%%s%%%s%%'", key, formattedValueEscaped)
case v3.FilterOperatorNotRegex:
return fmt.Sprintf("labels not like '%%%s%%'", key)
Expand Down
27 changes: 23 additions & 4 deletions pkg/query-service/app/logs/v4/resource_query_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ func Test_buildResourceFilter(t *testing.T) {
logsOp: "=",
key: "service.name",
op: v3.FilterOperatorEqual,
value: "Application",
value: "Application%",
},
want: `simpleJSONExtractString(labels, 'service.name') = 'Application'`,
want: `simpleJSONExtractString(labels, 'service.name') = 'Application%'`,
},
{
name: "test value with quotes",
Expand All @@ -75,6 +75,16 @@ func Test_buildResourceFilter(t *testing.T) {
},
want: `simpleJSONExtractString(labels, 'service.name') = 'Application\'s'`,
},
{
name: "test like",
args: args{
logsOp: "LIKE",
key: "service.name",
op: v3.FilterOperatorLike,
value: "Application%_",
},
want: `simpleJSONExtractString(labels, 'service.name') LIKE 'Application%_'`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -119,9 +129,9 @@ func Test_buildIndexFilterForInOperator(t *testing.T) {
args: args{
key: "service.name",
op: v3.FilterOperatorIn,
value: "application",
value: "application%",
},
want: `(labels like '%"service.name":"application"%')`,
want: `(labels like '%"service.name":"application\%"%')`,
},
{
name: "test nin string",
Expand Down Expand Up @@ -180,6 +190,15 @@ func Test_buildResourceIndexFilter(t *testing.T) {
},
want: `labels not like '%service.name%application\%\_test%'`,
},
{
name: "test like with % and _",
args: args{
key: "service.name",
op: v3.FilterOperatorLike,
value: "application%_test",
},
want: `labels like '%service.name%application%_test%'`,
},
{
name: "test not regex",
args: args{
Expand Down

0 comments on commit 8eb2cf1

Please sign in to comment.