mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-06-04 11:25:52 +08:00
fix: escape string for contains and ncontains (#5083)
* fix: escape string for contains and ncontains * fix: add changes to json and traces builder --------- Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
This commit is contained in:
parent
749fba67cb
commit
ab444af8e6
@ -144,7 +144,8 @@ func GetJSONFilter(item v3.FilterItem) (string, error) {
|
|||||||
fmtVal := utils.ClickHouseFormattedValue(value)
|
fmtVal := utils.ClickHouseFormattedValue(value)
|
||||||
filter = fmt.Sprintf(logsOp, key, fmtVal)
|
filter = fmt.Sprintf(logsOp, key, fmtVal)
|
||||||
case v3.FilterOperatorContains, v3.FilterOperatorNotContains:
|
case v3.FilterOperatorContains, v3.FilterOperatorNotContains:
|
||||||
filter = fmt.Sprintf("%s %s '%%%s%%'", key, logsOp, item.Value)
|
val := utils.QuoteEscapedString(fmt.Sprintf("%v", item.Value))
|
||||||
|
filter = fmt.Sprintf("%s %s '%%%s%%'", key, logsOp, val)
|
||||||
default:
|
default:
|
||||||
fmtVal := utils.ClickHouseFormattedValue(value)
|
fmtVal := utils.ClickHouseFormattedValue(value)
|
||||||
filter = fmt.Sprintf("%s %s %s", key, logsOp, fmtVal)
|
filter = fmt.Sprintf("%s %s %s", key, logsOp, fmtVal)
|
||||||
|
@ -300,6 +300,19 @@ var testGetJSONFilterData = []struct {
|
|||||||
},
|
},
|
||||||
Filter: "JSON_EXISTS(body, '$.\"message\"') AND JSON_VALUE(body, '$.\"message\"') ILIKE '%a%'",
|
Filter: "JSON_EXISTS(body, '$.\"message\"') AND JSON_VALUE(body, '$.\"message\"') ILIKE '%a%'",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "contains operator with quotes",
|
||||||
|
FilterItem: v3.FilterItem{
|
||||||
|
Key: v3.AttributeKey{
|
||||||
|
Key: "body.message",
|
||||||
|
DataType: "string",
|
||||||
|
IsJSON: true,
|
||||||
|
},
|
||||||
|
Operator: "contains",
|
||||||
|
Value: "hello 'world'",
|
||||||
|
},
|
||||||
|
Filter: "JSON_EXISTS(body, '$.\"message\"') AND JSON_VALUE(body, '$.\"message\"') ILIKE '%hello \\'world\\'%'",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "exists",
|
Name: "exists",
|
||||||
FilterItem: v3.FilterItem{
|
FilterItem: v3.FilterItem{
|
||||||
|
@ -192,7 +192,8 @@ func buildLogsTimeSeriesFilterQuery(fs *v3.FilterSet, groupBy []v3.AttributeKey,
|
|||||||
conditions = append(conditions, fmt.Sprintf(logsOp, columnName, fmtVal))
|
conditions = append(conditions, fmt.Sprintf(logsOp, columnName, fmtVal))
|
||||||
case v3.FilterOperatorContains, v3.FilterOperatorNotContains:
|
case v3.FilterOperatorContains, v3.FilterOperatorNotContains:
|
||||||
columnName := getClickhouseColumnName(item.Key)
|
columnName := getClickhouseColumnName(item.Key)
|
||||||
conditions = append(conditions, fmt.Sprintf("%s %s '%%%s%%'", columnName, logsOp, item.Value))
|
val := utils.QuoteEscapedString(fmt.Sprintf("%v", item.Value))
|
||||||
|
conditions = append(conditions, fmt.Sprintf("%s %s '%%%s%%'", columnName, logsOp, val))
|
||||||
default:
|
default:
|
||||||
columnName := getClickhouseColumnName(item.Key)
|
columnName := getClickhouseColumnName(item.Key)
|
||||||
fmtVal := utils.ClickHouseFormattedValue(value)
|
fmtVal := utils.ClickHouseFormattedValue(value)
|
||||||
|
@ -187,6 +187,13 @@ var timeSeriesFilterQueryData = []struct {
|
|||||||
}},
|
}},
|
||||||
ExpectedFilter: "attributes_string_value[indexOf(attributes_string_key, 'host')] ILIKE '%102.%'",
|
ExpectedFilter: "attributes_string_value[indexOf(attributes_string_key, 'host')] ILIKE '%102.%'",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "Test contains with single quotes",
|
||||||
|
FilterSet: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
||||||
|
{Key: v3.AttributeKey{Key: "message", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}, Value: "hello 'world'", Operator: "contains"},
|
||||||
|
}},
|
||||||
|
ExpectedFilter: "attributes_string_value[indexOf(attributes_string_key, 'message')] ILIKE '%hello \\'world\\'%'",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "Test not contains",
|
Name: "Test not contains",
|
||||||
FilterSet: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
FilterSet: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
||||||
@ -280,7 +287,6 @@ var timeSeriesFilterQueryData = []struct {
|
|||||||
}},
|
}},
|
||||||
ExpectedFilter: "`attribute_int64_status_exists`=false",
|
ExpectedFilter: "`attribute_int64_status_exists`=false",
|
||||||
},
|
},
|
||||||
// add new tests
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildLogsTimeSeriesFilterQuery(t *testing.T) {
|
func TestBuildLogsTimeSeriesFilterQuery(t *testing.T) {
|
||||||
|
@ -174,7 +174,8 @@ func buildTracesFilterQuery(fs *v3.FilterSet, keys map[string]v3.AttributeKey) (
|
|||||||
if operator, ok := tracesOperatorMappingV3[item.Operator]; ok {
|
if operator, ok := tracesOperatorMappingV3[item.Operator]; ok {
|
||||||
switch item.Operator {
|
switch item.Operator {
|
||||||
case v3.FilterOperatorContains, v3.FilterOperatorNotContains:
|
case v3.FilterOperatorContains, v3.FilterOperatorNotContains:
|
||||||
conditions = append(conditions, fmt.Sprintf("%s %s '%%%s%%'", columnName, operator, item.Value))
|
val = utils.QuoteEscapedString(fmt.Sprintf("%v", item.Value))
|
||||||
|
conditions = append(conditions, fmt.Sprintf("%s %s '%%%s%%'", columnName, operator, val))
|
||||||
case v3.FilterOperatorRegex, v3.FilterOperatorNotRegex:
|
case v3.FilterOperatorRegex, v3.FilterOperatorNotRegex:
|
||||||
conditions = append(conditions, fmt.Sprintf(operator, columnName, fmtVal))
|
conditions = append(conditions, fmt.Sprintf(operator, columnName, fmtVal))
|
||||||
case v3.FilterOperatorExists, v3.FilterOperatorNotExists:
|
case v3.FilterOperatorExists, v3.FilterOperatorNotExists:
|
||||||
@ -263,7 +264,7 @@ func buildTracesQuery(start, end, step int64, mq *v3.BuilderQuery, tableName str
|
|||||||
queryTmpl =
|
queryTmpl =
|
||||||
"SELECT now() as ts,"
|
"SELECT now() as ts,"
|
||||||
// step or aggregate interval is whole time period in case of table panel
|
// step or aggregate interval is whole time period in case of table panel
|
||||||
step = (end*getZerosForEpochNano(end) - start*getZerosForEpochNano(start))/1000000000
|
step = (end*getZerosForEpochNano(end) - start*getZerosForEpochNano(start)) / 1000000000
|
||||||
} else if panelType == v3.PanelTypeGraph || panelType == v3.PanelTypeValue {
|
} else if panelType == v3.PanelTypeGraph || panelType == v3.PanelTypeValue {
|
||||||
// Select the aggregate value for interval
|
// Select the aggregate value for interval
|
||||||
queryTmpl =
|
queryTmpl =
|
||||||
|
@ -100,6 +100,13 @@ var buildFilterQueryData = []struct {
|
|||||||
}},
|
}},
|
||||||
ExpectedFilter: " AND stringTagMap['host'] ILIKE '%102.%'",
|
ExpectedFilter: " AND stringTagMap['host'] ILIKE '%102.%'",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "Test contains with quotes",
|
||||||
|
FilterSet: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
||||||
|
{Key: v3.AttributeKey{Key: "message", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}, Value: "Hello 'world'", Operator: "contains"},
|
||||||
|
}},
|
||||||
|
ExpectedFilter: " AND stringTagMap['message'] ILIKE '%Hello \\'world\\'%'",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "Test not contains",
|
Name: "Test not contains",
|
||||||
FilterSet: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
FilterSet: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
||||||
|
@ -143,7 +143,7 @@ func ValidateAndCastValue(v interface{}, dataType v3.AttributeKeyDataType) (inte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func quoteEscapedString(str string) string {
|
func QuoteEscapedString(str string) string {
|
||||||
// https://clickhouse.com/docs/en/sql-reference/syntax#string
|
// https://clickhouse.com/docs/en/sql-reference/syntax#string
|
||||||
str = strings.ReplaceAll(str, `\`, `\\`)
|
str = strings.ReplaceAll(str, `\`, `\\`)
|
||||||
str = strings.ReplaceAll(str, `'`, `\'`)
|
str = strings.ReplaceAll(str, `'`, `\'`)
|
||||||
@ -161,7 +161,7 @@ func ClickHouseFormattedValue(v interface{}) string {
|
|||||||
case float32, float64:
|
case float32, float64:
|
||||||
return fmt.Sprintf("%f", x)
|
return fmt.Sprintf("%f", x)
|
||||||
case string:
|
case string:
|
||||||
return fmt.Sprintf("'%s'", quoteEscapedString(x))
|
return fmt.Sprintf("'%s'", QuoteEscapedString(x))
|
||||||
case bool:
|
case bool:
|
||||||
return fmt.Sprintf("%v", x)
|
return fmt.Sprintf("%v", x)
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ func ClickHouseFormattedValue(v interface{}) string {
|
|||||||
case string:
|
case string:
|
||||||
str := "["
|
str := "["
|
||||||
for idx, sVal := range x {
|
for idx, sVal := range x {
|
||||||
str += fmt.Sprintf("'%s'", quoteEscapedString(sVal.(string)))
|
str += fmt.Sprintf("'%s'", QuoteEscapedString(sVal.(string)))
|
||||||
if idx != len(x)-1 {
|
if idx != len(x)-1 {
|
||||||
str += ","
|
str += ","
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user