fix: handle empty variable list in PrepareWhereClause (#9126)

This commit is contained in:
Niladri Adhikary
2025-11-20 22:33:34 +05:30
committed by GitHub
parent 48590c03e2
commit 096e38ee91
2 changed files with 83 additions and 0 deletions

View File

@@ -437,6 +437,10 @@ func (v *filterExpressionVisitor) VisitComparison(ctx *grammar.ComparisonContext
}
switch varValues := varItem.Value.(type) {
case []any:
if len(varValues) == 0 {
v.errors = append(v.errors, fmt.Sprintf("malformed request payload: variable `%s` used in expression has an empty list value", strings.TrimPrefix(var_, "$")))
return ""
}
values = varValues
case any:
values = []any{varValues}
@@ -516,6 +520,10 @@ func (v *filterExpressionVisitor) VisitComparison(ctx *grammar.ComparisonContext
if ok {
switch varValues := varItem.Value.(type) {
case []any:
if len(varValues) == 0 {
v.errors = append(v.errors, fmt.Sprintf("malformed request payload: variable `%s` used in expression has an empty list value", strings.TrimPrefix(var_, "$")))
return ""
}
value = varValues[0]
case any:
value = varValues

View File

@@ -0,0 +1,75 @@
package querybuilder
import (
"strings"
"testing"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
)
// testFieldKey returns a mock TelemetryFieldKey for the given name
func testFieldKey(name string) *telemetrytypes.TelemetryFieldKey {
return &telemetrytypes.TelemetryFieldKey{
Name: name,
Signal: telemetrytypes.SignalLogs,
FieldContext: telemetrytypes.FieldContextAttribute,
FieldDataType: telemetrytypes.FieldDataTypeString,
}
}
// TestPrepareWhereClause_EmptyVariableList ensures PrepareWhereClause errors when a variable has an empty list value
func TestPrepareWhereClause_EmptyVariableList(t *testing.T) {
tests := []struct {
name string
expr string
variables map[string]qbtypes.VariableItem
expectError bool
wantInError string
}{
{
name: "Empty []any for equality",
expr: "service = $service",
variables: map[string]qbtypes.VariableItem{
"service": {Value: []any{}},
},
expectError: true,
wantInError: "Found 1 errors while parsing the search expression",
},
{
name: "Empty []any for IN clause",
expr: "service IN $service",
variables: map[string]qbtypes.VariableItem{
"service": {Value: []any{}},
},
expectError: true,
wantInError: "Found 1 errors while parsing the search expression",
},
}
keys := map[string][]*telemetrytypes.TelemetryFieldKey{
"service": {testFieldKey("service")},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
opts := FilterExprVisitorOpts{
FieldKeys: keys,
Variables: tt.variables,
}
_, err := PrepareWhereClause(tt.expr, opts, 0, 0)
if tt.expectError {
if err == nil {
t.Fatalf("expected error, got nil")
}
if tt.wantInError != "" && !strings.Contains(err.Error(), tt.wantInError) {
t.Fatalf("expected error to contain %q, got %q", tt.wantInError, err.Error())
}
} else if err != nil {
t.Fatalf("unexpected error: %v", err)
}
})
}
}