Dynamic ConditionBuilder

Viewed 228

My problem is pretty simple, I would like to dynamically create filters to use it in my query input. I must precise that the tf variable can't change.

So here is what I did :

totalFilter := expression.ConditionBuilder{}
filter := expression.Name("status").Equal(expression.Value("0"))
filter2 := expression.Name("foo").Equal(expression.Value("bar"))
filter3 := expression.Name("yes").Equal(expression.Value("no"))
tf := []expression.ConditionBuilder{filter, filter2, filter3}
for _, v := range tf {
    totalFilter = totalFilter.And(v)
}
expr := expression.NewBuilder().WithFilter(totalFilter)
builder, err := expr.Build()
if err != nil {
    log.Println(err)
    return err
}

But the probleme is that totalFilter is an empty struct so it's mode variable is equal to 0 and then it raise an alert because mode 0 is unsetCond.

The only workaround that I found is to do this :

for i, v := range tf {
    if i == 0 {
        totalFilter = v
    } else {
        totalFilter.And(v)
    }
}

But I was wondering if there is another solution.

1 Answers

You could abstract away the treatment of the first expression.ConditionBuilder in a custom variadic function taking at least one expression.ConditionBuilder parameter:

func And(first expression.ConditionBuilder, rest ...expression.ConditionBuilder) expression.ConditionBuilder {
    result := first
    for _, cb := range rest {
        result = result.And(cb)
    }
    return result
}

Then, in main:

filter := expression.Name("status").Equal(expression.Value("0"))
filter2 := expression.Name("foo").Equal(expression.Value("bar"))
filter3 := expression.Name("yes").Equal(expression.Value("no"))
totalFilter := And(filter, filter2, filter3)
expr := expression.NewBuilder().WithFilter(totalFilter)
builder, err := expr.Build()
// etc.

Note that a similar function, also named And, is exported by the expression package, but it takes at least two (not just one) expression.ConditionBuilder parameters. That's unfortunate...

Related