func (b *Backend) sort(info *db.ModelInfo, items *reflector.SliceReflector, field Expression, asc bool) apperror.Error { fieldName := "" if id, ok := field.(*IdentifierExpr); ok { fieldName = id.Identifier() } else if id, ok := field.(*ColFieldIdentifierExpr); ok { if id.Collection() != info.Collection() { return apperror.New("unsupported_sort", fmt.Sprint("The memory backend does not support sorting with joined collections")) } fieldName = id.Field() } else { return apperror.New("unsupported_sort", fmt.Sprintf("The memory backend does not support sorting with custom field expressions")) } attr := info.FindAttribute(fieldName) if attr == nil { return apperror.New("invalid_sort", fmt.Sprintf("Invalid sort for inexistant field %v", fieldName)) } if err := items.SortByField(attr.Name(), asc); err != nil { return apperror.Wrap(err, "sort_error") } return nil }
func (b *Backend) filterItem(info *db.ModelInfo, item *reflector.Reflector, filter Expression) (bool, apperror.Error) { switch f := filter.(type) { case *AndExpr: // Check each filter. for _, e := range f.Expressions() { flag, err := b.filterItem(info, item, e) if err != nil { return false, err } else if !flag { // One filter does not match, so return false. return false, nil } } // All filters matched, we can return true. return true, nil case *OrExpr: // Check each filter. for _, e := range f.Expressions() { flag, err := b.filterItem(info, item, e) if err != nil { return false, err } else if flag { // One match is enough, so return true. return true, nil } } // No filters matched, so return false. return false, nil case *NotExpr: // Reverse nested filter. flag, err := b.filterItem(info, item, f.Not()) if err != nil { return false, err } else { return !flag, nil } case FilterExpression: field := f.Field() fieldName := "" if id, ok := field.(*IdentifierExpr); ok { fieldName = id.Identifier() } else if id, ok := field.(*ColFieldIdentifierExpr); ok { if id.Collection() != info.Collection() { return false, apperror.New("unsupported_filter", fmt.Sprint("The memory backend does not support filtering with joined collections")) } fieldName = id.Field() } else { return false, apperror.New("unsupported_filter", fmt.Sprintf("The memory backend does not support filtering with custom field expressions")) } attr := info.FindAttribute(fieldName) if attr == nil { return false, apperror.New("invalid_filter", fmt.Sprintf("Invalid filter for inexistant field %v", fieldName)) } operator := f.Operator() var clauseValue interface{} if valExpr, ok := f.Clause().(*ValueExpr); ok { clauseValue = valExpr.Value() } else { return false, apperror.New("unsupported_filter_clause", fmt.Sprintf("The memory backend does not support filtering with custom clause expressions")) } if info.StructName() != "" { b.Logger().Infof("filtering item with %v %v %v", fieldName, operator, clauseValue) s, err := item.Struct() if err != nil { return false, apperror.Wrap(err, "invalid_model_error") } flag, err := s.Field(attr.Name()).CompareTo(clauseValue, operator) if err != nil { return false, apperror.Wrap(err, "compare_error") } return flag, nil } else { // Assume a map. if !item.IsMap() { return false, apperror.New("filter_invalid_model", "Could not filter because model value is neither struct nor map.") } flag, err := reflector.R(item.Value().MapIndex(reflect.ValueOf(attr.BackendName()))).CompareTo(clauseValue, operator) if err != nil { return false, apperror.Wrap(err, "compare_error") } return flag, nil } default: b.Logger().Panicf("Unhandled filter expression: %v", reflect.TypeOf(filter)) } return false, nil }