Skip to content

Conversation

@xsahil03x
Copy link
Member

@xsahil03x xsahil03x commented Oct 23, 2025

Submit a pull request

Fixes: FLU-304
Ios PR: GetStream/stream-core-swift#2
Android PR: GetStream/stream-core-android#14

Description of the pull request

This PR introduces a significant enhancement to the Filter API by adding client-side matching capabilities with the matches() method. It also refactors the filter implementation for improved type safety and clarity.

New Features

  • Client-Side Filtering (matches() method): A matches(T other) method has been added to the Filter class. This allows filters to be evaluated locally against model instances, enabling client-side data filtering before it's rendered. The matching logic emulates PostgreSQL semantics for consistency with backend behavior:
    • Equal: Deep equality (order-sensitive for lists, order-insensitive for maps).
    • Contains: Subset matching (order-independent for lists).
    • In: Membership testing.
    • Comparison Operators (<, >, <=, >=): Type-safe comparison for numbers, strings, and dates.
    • Query: Case-insensitive substring matching.
    • AutoComplete: Case-insensitive word prefix matching.
    • Exists: Checks for non-null values.
    • PathExists: Validates the existence of nested paths in maps.
  • FilterField with Value Getter: FilterField now requires a value getter function Object? Function(T). This links the remote field name to a type-safe function that extracts the value from a model, which is essential for the new matches() functionality.

Refactoring and Improvements

  • Simplified Filter Classes: The filter operator classes have been renamed for simplicity and clarity (e.g., EqualOperator is now Equal, AndOperator is And).
  • Enhanced Type Safety: The generic signature of Filter is now Filter<T extends Object>, where T is the model type, strengthening the connection between filters and the data they operate on.
  • Utility Functions: New utility files (filter_operation_utils.dart, comparable_field.dart) have been added to support deep equality checks, subset containment, and safe comparisons, centralizing complex logic.
  • Sorting Robustness: The Sort comparator now safely handles comparisons between incompatible types, preventing potential runtime errors by treating them as equal.

Testing

  • The filter_test.dart file has been completely rewritten with an extensive suite of tests for the new matches() method, covering all operators, edge cases, type mismatches, and real-world scenarios to ensure correctness and reliability.

This commit introduces a significant enhancement to the `Filter` API by adding client-side matching capabilities with the `matches()` method. It also refactors the filter implementation for improved type safety and clarity.

### New Features

-   **Client-Side Filtering (`matches()` method)**: A `matches(T other)` method has been added to the `Filter` class. This allows filters to be evaluated locally against model instances, enabling client-side data filtering before it's rendered. The matching logic emulates PostgreSQL semantics for consistency with backend behavior:
    -   `Equal`: Deep equality (order-sensitive for lists, order-insensitive for maps).
    -   `Contains`: Subset matching (order-independent for lists).
    -   `In`: Membership testing.
    -   `Comparison Operators` (`<`, `>`, `<=`, `>=`): Type-safe comparison for numbers, strings, and dates.
    -   `Query`: Case-insensitive substring matching.
    -   `AutoComplete`: Case-insensitive word prefix matching.
    -   `Exists`: Checks for non-null values.
    -   `PathExists`: Validates the existence of nested paths in maps.
-   **`FilterField` with Value Getter**: `FilterField` now requires a value getter function `Object? Function(T)`. This links the remote field name to a type-safe function that extracts the value from a model, which is essential for the new `matches()` functionality.

### Refactoring and Improvements

-   **Simplified Filter Classes**: The filter operator classes have been renamed for simplicity and clarity (e.g., `EqualOperator` is now `Equal`, `AndOperator` is `And`).
-   **Enhanced Type Safety**: The generic signature of `Filter` is now `Filter<T extends Object>`, where `T` is the model type, strengthening the connection between filters and the data they operate on.
-   **Utility Functions**: New utility files (`filter_operation_utils.dart`, `comparable_field.dart`) have been added to support deep equality checks, subset containment, and safe comparisons, centralizing complex logic.
-   **Sorting Robustness**: The `Sort` comparator now safely handles comparisons between incompatible types, preventing potential runtime errors by treating them as equal.

### Testing

-   The `filter_test.dart` file has been completely rewritten with an extensive suite of tests for the new `matches()` method, covering all operators, edge cases, type mismatches, and real-world scenarios to ensure correctness and reliability.
@xsahil03x xsahil03x requested a review from a team as a code owner October 23, 2025 12:03
@codecov
Copy link

codecov bot commented Oct 23, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 26.56%. Comparing base (9559620) to head (4325b80).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #16      +/-   ##
==========================================
+ Coverage   18.01%   26.56%   +8.54%     
==========================================
  Files          47       49       +2     
  Lines         877      960      +83     
==========================================
+ Hits          158      255      +97     
+ Misses        719      705      -14     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

This commit refactors `FilterField` and `SortField` to improve their structure and consistency.

- Replaced the `extension type` implementation of `FilterField` with a standard `class`. This change simplifies the code and improves clarity, as seen in the updated `TestFilterField` and documentation examples.
- Removed the factory constructor from `SortField` in favor of a direct generative constructor, making its initialization more straightforward.
This commit changes the behavior of filter operations to align with PostgreSQL's three-valued logic when handling `NULL` values. Previously, `NULL == NULL` evaluated to `true`; now, any comparison involving `NULL` will evaluate to `false`.

**Key Changes:**
- **Equality (`==`)**: `Filter.equal` now returns `false` if either the field's value or the comparison value is `null`. This affects how models with `null` fields are matched.
- **Comparisons (`>`, `>=`, `<`, `<=`)**: All comparison operators now consistently return `false` when a `null` value is involved, mimicking standard database behavior where `NULL` is not greater than, less than, or equal to any other value (including `NULL`).
- **Tests**: Updated and expanded tests to verify the new `NULL` handling semantics across all relevant filter operators.
@xsahil03x xsahil03x merged commit d9c2407 into main Oct 28, 2025
11 checks passed
@xsahil03x xsahil03x deleted the feat/local-filtering branch October 28, 2025 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants