Open benber86 opened 6 years ago
Another option would be to add support for nested struct in queries as mentioned in #166
I tried with a basic patch on MatchValue
to add parsing of period-separated nested query strings:
func GetNestedValue(v *reflect.Value, fields []string) (interface{}, error) {
nestedV := *v
for _, element := range fields {
nestedField := nestedV.FieldByName(element)
if !nestedField.IsValid() {
return nil, ErrUnknownField
}
nestedV = nestedField
}
return nestedV.Interface(), nil
}
func (r fieldMatcherDelegate) MatchValue(v *reflect.Value) (bool, error) {
if !strings.Contains(r.Field, ".") {
field := v.FieldByName(r.Field)
if !field.IsValid() {
return false, ErrUnknownField
}
return r.MatchField(field.Interface())
} else {
nestedValue, err := GetNestedValue(v, strings.Split(r.Field, "."))
if err != nil {
return false, err
}
return r.MatchField(nestedValue)
}
}
which works but is a bit less practical for queries on NullTime
as one would have to be careful to have both a comparison on the Time
field and a check on the Valid
field when creating the query.
What about adding an interface that custom types would have to implement? Ex:
type Comparable interface {
// Returns a number negative, null or positive if lower, equal or greater than the other.
Compare(other interface{}) (int, error)
}
And it could be used that way
type NullTime pq.NullTime
func (n *NullTime) Compare(other interface{}) (int, error) {
o, ok := other.(*pq.NullTime)
if !ok {
return 0, errors.New(...)
}
// compare and return
...
}
Ok, so the only thing needed in compare
would be to check that the interface is implemented with a type assertion and then run the comparison ?:
o, ok := b.(Comparable)
if ok && ak == bk {
result, err := o.Compare(a)
if err != nil {
return false
}
return constant.Compare(constant.MakeInt64(0), tok, constant.MakeInt64(int64(result)))
}
Storm currently offers the possibility to compare
time.Time
value, which works great. Unfortunately this does not work for nullable Time types (types that can represent atime.Time
that may be Null), such as go-sql-driver's or pq'sNullTime
, null'snull.Time
or similar, since thetime.Time
value is nested.Since all of these follow the same format:
it would be possible to add support for it in
compare
:provided that you deem the addition useful enough and don't mind adding support for custom types.