interface conversion: interface {} is nil, not string (1:9)
mbardelmeijer opened this issue · 5 comments
When running the following expression, it returns in the error interface conversion: interface {} is nil, not string (1:9)
We would like to handle this gracefully, as the query
parameter are optional that we're matching on. We prefer not to wrap it in string()
, as our customer may create their own expression, and prefer to have this expression as clean as possible.
Is there any way to combat this, with for instance AllowUndefinedVariables
? Or can expr-lang
be modified to allow contains
queries etc. on possible nil
types?
env := map[string]interface{}{
"query": map[string]interface{}{
"another_query": "test",
},
}
expression := "query.b contains 'test'"
prg, _ := expr.Compile(expression, expr.Env(env))
result, err := expr.Run(prg, env)
fmt.Println(result)
fmt.Println(err)
Output:
interface conversion: interface {} is nil, not string (1:9)
| query.b contains 'test'
I think we should make it possible to compare to nil anything.
I will update == operator to support this.
Actually, the problem is not with ==
, but with contains
.
The ==
already supports this:
func TestExpr_string_nil_equals_string(t *testing.T) {
var str *string = nil
env := map[string]any{
"nilString": str,
}
program, err := expr.Compile(`nilString == "hello, world"`, expr.Env(env))
require.NoError(t, err) // Pass
output, err := expr.Run(program, env)
require.NoError(t, err)
require.Equal(t, false, output) // Pass
}
Here is the test, only first is pasing:
func TestExpr_nil_op_str(t *testing.T) {
// Let's test operators, which do `.(string)` in VM, also check for nil.
var str *string = nil
env := map[string]any{
"nilString": str,
}
tests := []struct{ code string }{
{`nilString == "str"`}, // ok
{`nilString contains "str"`},
{`nilString matches "str"`},
{`nilString startsWith "str"`},
{`nilString endsWith "str"`},
}
for _, tt := range tests {
t.Run(tt.code, func(t *testing.T) {
program, err := expr.Compile(tt.code)
require.NoError(t, err)
output, err := expr.Run(program, env)
require.NoError(t, err)
require.Equal(t, false, output)
})
}
}
Fixed.
Awesome, thanks a lot! 🙏 -- Can confirm the fix works.