Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ var allowedComparisonOperators = map[string]struct{}{
sqlparser.NotInStr: {},
sqlparser.StartsWithStr: {},
sqlparser.NotStartsWithStr: {},
sqlparser.ContainsStr: {},
sqlparser.NotContainsStr: {},
}

func NewQueryConverter(
Expand Down
12 changes: 12 additions & 0 deletions common/persistence/visibility/store/query/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,18 @@ func (c *comparisonExprConverter) Convert(expr sqlparser.Expr) (elastic.Query, e
return nil, NewConverterError("right-hand side of '%v' must be a string", comparisonExpr.Operator)
}
query = elastic.NewBoolQuery().MustNot(elastic.NewPrefixQuery(colName, v))
case sqlparser.ContainsStr:
v, ok := colValues[0].(string)
if !ok {
return nil, NewConverterError("right-hand side of '%v' must be a string", comparisonExpr.Operator)
}
query = elastic.NewWildcardQuery(colName, "*"+v+"*")
case sqlparser.NotContainsStr:
v, ok := colValues[0].(string)
if !ok {
return nil, NewConverterError("right-hand side of '%v' must be a string", comparisonExpr.Operator)
}
query = elastic.NewBoolQuery().MustNot(elastic.NewWildcardQuery(colName, "*"+v+"*"))
}

return query, nil
Expand Down
32 changes: 32 additions & 0 deletions common/persistence/visibility/store/sql/query_converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ var (
sqlparser.NotInStr,
sqlparser.StartsWithStr,
sqlparser.NotStartsWithStr,
sqlparser.ContainsStr,
sqlparser.NotContainsStr,
}

supportedKeyworkListOperators = []string{
Expand Down Expand Up @@ -395,6 +397,23 @@ func (c *QueryConverter) convertComparisonExpr(exprRef *sqlparser.Expr) error {
}
expr.Escape = defaultLikeEscapeExpr
valueExpr.Val = escapeLikeValueForPrefixSearch(valueExpr.Val, defaultLikeEscapeChar)
case sqlparser.ContainsStr, sqlparser.NotContainsStr:
valueExpr, ok := expr.Right.(*unsafeSQLString)
if !ok {
return query.NewConverterError(
"%s: right-hand side of '%s' must be a literal string (got: %v)",
query.InvalidExpressionErrMessage,
expr.Operator,
sqlparser.String(expr.Right),
)
}
if expr.Operator == sqlparser.ContainsStr {
expr.Operator = sqlparser.LikeStr
} else {
expr.Operator = sqlparser.NotLikeStr
}
expr.Escape = defaultLikeEscapeExpr
valueExpr.Val = escapeLikeValueForSubstringSearch(valueExpr.Val, defaultLikeEscapeChar)
}

return nil
Expand Down Expand Up @@ -662,6 +681,19 @@ func escapeLikeValueForPrefixSearch(in string, escape byte) string {
return sb.String()
}

func escapeLikeValueForSubstringSearch(in string, escape byte) string {
sb := strings.Builder{}
sb.WriteByte('%')
for _, c := range in {
if c == '%' || c == '_' || c == rune(escape) {
sb.WriteByte(escape)
}
sb.WriteRune(c)
}
sb.WriteByte('%')
return sb.String()
}

func isSupportedOperator(supportedOperators []string, operator string) bool {
for _, op := range supportedOperators {
if operator == op {
Expand Down
38 changes: 38 additions & 0 deletions common/persistence/visibility/store/sql/query_converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,44 @@ func (s *queryConverterSuite) TestConvertComparisonExpr() {
sqlparser.NotStartsWithStr,
),
},
{
name: "contains expression",
input: "AliasForKeyword01 contains 'substring'",
output: `Keyword01 like '%substring%' escape '!'`,
err: nil,
},
{
name: "not contains expression",
input: "AliasForKeyword01 not contains 'substring'",
output: `Keyword01 not like '%substring%' escape '!'`,
err: nil,
},
{
name: "contains expression with special chars",
input: "AliasForKeyword01 contains 'foo_bar%'",
output: `Keyword01 like '%foo!_bar!%%' escape '!'`,
err: nil,
},
{
name: "contains expression error",
input: "AliasForKeyword01 contains 123",
output: "",
err: query.NewConverterError(
"%s: right-hand side of '%s' must be a literal string (got: 123)",
query.InvalidExpressionErrMessage,
sqlparser.ContainsStr,
),
},
{
name: "not contains expression error",
input: "AliasForKeyword01 not contains 123",
output: "",
err: query.NewConverterError(
"%s: right-hand side of '%s' must be a literal string (got: 123)",
query.InvalidExpressionErrMessage,
sqlparser.NotContainsStr,
),
},
{
name: "like expression",
input: "AliasForKeyword01 like 'foo%'",
Expand Down