Skip to content

Refactoring of QueryMatchFilter and provide greater support for JSONPath spec #79

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Mar 22, 2025

Conversation

lucasnetau
Copy link
Contributor

@lucasnetau lucasnetau commented Mar 20, 2025

🔀 Pull Request

What does this PR do?

Refactoring of QueryMatchFilter and provide greater support for JSONPath spec

Queries now passing:

Test Plan

PHPUnit test all passing with additional tests from the RFC added (specifically around Null). Addition QueryTest now passing. No significant change in memory or time to run tests.

Before

Time: 00:00.226, Memory: 6.00 MB
OK (320 tests, 596 assertions)

After

Time: 00:00.207, Memory: 6.00 MB
OK (329 tests, 610 assertions)

Related PRs and Issues

This started out for me requiring logical AND filter and support for negation, and ended up with me refactoring the QueryMatchFilter to simplify the code while also making stricter in terms of comparisons per the RFC and not rely on PHP semantics for comparisons.

I've kept the commit history to show the development path, can squash if required or split into multiple PRs if preferred.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Released version 0.10.0 with a detailed changelog entry highlighting multiple fixes related to query/selector filter expressions.
  • Refactor

    • Upgraded filtering functionality to support more flexible and robust handling of complex query conditions.
  • Bug Fixes

    • Addressed various issues with query/selector filter expressions, including negation, equality checks, and comparisons.
  • Chores

    • Updated the package version and streamlined internal workflows for improved release reliability.
    • Enhanced error handling in tests and updated test cases for better coverage of edge cases.
    • Modified test workflows to improve error handling during test execution.

@SoftCreatR
Copy link
Owner

Lgtm. I wonder, if this resolves some of the open issues.

@SoftCreatR SoftCreatR added the good first issue Good for newcomers label Mar 21, 2025
Signed-off-by: Sascha Greuel <github@1-2.dev>
Copy link

coderabbitai bot commented Mar 21, 2025

Walkthrough

The updates introduce a new release version 0.10.0 by adding an entry in the changelog and bumping the package version in composer.json. The query filtering logic in the core filter class has been refactored to support enhanced regex patterns, negation handling, and modular comparison methods. Multiple test files have been updated to adjust error handling, method signatures, and test data, while the GitHub Actions workflow now alters the error handling logic during test execution.

Changes

File(s) Change Summary
CHANGELOG.md, composer.json Added a new version 0.10.0 entry in the changelog with a placeholder and updated the package version from 0.9.1 to 0.10.0.
src/Filters/QueryMatchFilter.php Refactored filtering logic to support advanced regex patterns for negation and logical operations; added new methods (isNumber, compareEquals, compareLessThan) and enabled strict types.
tests/QueryTest.php, tests/Traits/TestDataTrait.php, tests/data/baselineFailedQueries.txt,
tests/JSONPathArrayAccessTest.php
Enhanced tests with refined URL construction, consolidated error handling, updated test data sets (including new and removed cases), and adjusted method signatures and defaults.
.github/workflows/Test.yml Updated the test execution command to include a multi-line script for improved error handling.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant QMF as QueryMatchFilter
    participant RE as Regex Engine
    participant CE as Comparison Methods

    C->>QMF: Call filter(query)
    QMF->>RE: Match negation & logical expressions
    RE-->>QMF: Return regex match results
    QMF->>QMF: Iterate through query parts
    QMF->>CE: Invoke compareEquals / compareLessThan
    CE-->>QMF: Return comparison result
    QMF-->>C: Return final filtering outcome
Loading

Assessment against linked issues

Objective Addressed Explanation
Filter Expression With Boolean And Operator (#42) The changes do not resolve the issues related to the Boolean AND operator as expected results still differ.
Filter Expression With Boolean Or Operator (#43) The changes do not resolve the issues related to the Boolean OR operator as expected results still differ.
Filter Expression With Equals (#45) The changes do not resolve the issues related to equality checks as expected results still differ.
Filter Expression With Equals False (#46) The changes do not resolve the issues related to equality checks with false as expected results still differ.
Filter Expression With Equals Null (#47) The changes do not resolve the issues related to equality checks with null as expected results still differ.

Poem

I'm a bunny with a byte-sized cheer,
Hopping through changes crisp and clear.
New regex hops and comparisons align,
Tests and versions in a joyful line.
Carrots and code in a magical spree,
Leaping forward—oh, how happy me! 🥕
CodeRabbit Inc. sends a hoppy decree!


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (7)
CHANGELOG.md (2)

3-5: CHANGELOG entry placeholder added properly

The new version entry has been added with a TBA placeholder, which is appropriate for tracking the upcoming changes. This will need to be updated with actual details before the final release.

Consider adding specific details about the QueryMatchFilter refactoring and JSONPath spec support mentioned in the PR objectives.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

3-3: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)


3-3: Minor: Inconsistent heading level

Static analysis flagged that heading levels should only increment by one level at a time. The file starts with # Changelog (h1) and then jumps to ### 0.10.0 (h3) without an h2 in between.

However, this follows the established pattern in the rest of the file, so it's just a note for consistency with markdown best practices rather than something that needs to be changed.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

3-3: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

src/Filters/QueryMatchFilter.php (4)

42-49: Negation logic introduction.
Your approach to detect and strip negation before further processing is sound. However, consider edge cases in which logicalexpr might be empty or malformed to avoid unexpected results.


52-69: Complex expression grouping.
Using string replacement with %groupX% placeholders effectively breaks down nested filtering logic. However, grouping can become costly for deeply nested or repeated expressions. Consider caching sub-results or reducing string replacements if performance becomes an issue.


71-84: More specific exceptions might help debugging.
Throwing a RuntimeException is functional but consider a custom FilterQueryException or similar to better separate malformed filter errors from generic runtime issues.


186-217: Consider stricter comparisons.
While the partial type check is helpful ($type_a === $type_b), using == can still allow implicit type juggling. Consider fully strict checks (===) if alignment with RFC semantics permits.

tests/data/baselineFailedQueries.txt (1)

21-28: Explicitly marking null-handling queries as XFAIL.
Marking these queries shows you’re intentionally acknowledging partial or unimplemented support for null semantics. Consider referencing an issue or roadmap if a fix is planned.

Do you want help opening an issue to track these known failures?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 272173a and e2ad48b.

📒 Files selected for processing (6)
  • CHANGELOG.md (1 hunks)
  • composer.json (1 hunks)
  • src/Filters/QueryMatchFilter.php (1 hunks)
  • tests/QueryTest.php (6 hunks)
  • tests/Traits/TestDataTrait.php (2 hunks)
  • tests/data/baselineFailedQueries.txt (2 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
tests/QueryTest.php (1)
src/JSONPathException.php (1) (1)
  • JSONPathException (13-16)
🪛 markdownlint-cli2 (0.17.2)
CHANGELOG.md

3-3: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🔇 Additional comments (15)
composer.json (1)

5-5: Version bump from 0.9.1 to 0.10.0 looks good

The version increment from 0.9.1 to 0.10.0 aligns with the refactoring work described in the PR objectives. Following semantic versioning, this minor version bump appropriately signals new functionality while maintaining backward compatibility.

tests/Traits/TestDataTrait.php (2)

21-21: Updated PHPDoc to reflect proper exception type

The @throws annotation has been correctly updated to reflect that the method now throws a RuntimeException instead of a JsonException.


31-35: Improved JSON error handling with try-catch

The error handling has been enhanced by:

  1. Using JSON_THROW_ON_ERROR flag to make json_decode throw exceptions on error
  2. Catching the specific JsonException and converting it to a more informative RuntimeException
  3. Including the original exception message in the new exception for better debugging

This is a more robust approach to error handling compared to the previous implementation.

tests/QueryTest.php (6)

51-55: Enhanced URL reference for RFC-based tests

The code now constructs a URL to the RFC specification document for test IDs that start with 'rfc_', which improves traceability to the standard. This change aligns with the PR objective of providing better support for the JSONPath specification.


77-81: Added handling for unexpectedly passing tests

This new code checks if a test that is expected to fail (listed in self::$baselineFailedQueries) unexpectedly passes, and throws an appropriate exception. This is valuable for keeping the test suite accurate and ensuring that known failures are properly tracked. When these tests eventually pass due to implementation improvements, the base failure list should be updated.


105-111: Consolidated exception handling

The exception handling for JSONPathException and RuntimeException has been consolidated into a single catch block, which simplifies the code without losing any functionality. The error message now includes more context, making debugging easier.


1311-1311: Fixed missing closing quote in test data

The formatting of the expected result for the filter expression with not equals test has been fixed to properly close a quoted string.


1479-1479: Updated test expectation for script expression

The expected result for the script expression test has been changed from an unknown value to ["fifth"], which appears to be the correct expected value based on the test description.


1560-1613: Added new RFC compliance tests for null value semantics

Nine new test cases have been added to verify the implementation's handling of null values in JSONPath expressions, including:

  • Null object values
  • Null used as an array
  • Null used as an object
  • Null in array values
  • Null existence checking
  • Null comparisons

Some tests are marked as expected failures (XFAIL), indicating areas where the current implementation doesn't fully comply with the RFC. This is a significant improvement in test coverage and will guide future development of the JSONPath implementation.

These tests are directly related to the PR objective of improving JSONPath spec compliance. They will help ensure that the implementation correctly handles null values as specified in the RFC.

src/Filters/QueryMatchFilter.php (4)

9-10: Great use of strict typing.
Enabling strict_types=1 helps catch type-related bugs early and ensures more predictable behavior across the codebase.


16-21: Improved exception-based error handling.
Introducing JsonException and JSON_THROW_ON_ERROR ensures transparent and consistent error handling for JSON operations.


25-27: Well-defined negation patterns.
Defining separate constants for wrapped vs. unwrapped negation clarifies the regex approach and improves maintainability.


170-177: Verify negation on null results.
If $comparisonResult is null (e.g., when a prior check doesn’t set it), applying !null yields true. Confirm that $comparisonResult is guaranteed to be a boolean here or handle the null case explicitly.

tests/data/baselineFailedQueries.txt (2)

1-4: New test items for bracket/dot notation and union checks.
Adding these baseline entries helps ensure a comprehensive test suite covering common notation edge cases and tautological filters.


31-31: Confirm expected behavior for “union_with_slice_and_number.”
This line is flagged as changed but the difference isn’t obvious. Double-check whether it’s truly modified in content or if it merely reflects a reformat.

Comment on lines +151 to +159
$comparisonResult = null;

if ($notNothing) {
$comparisonResult = match ($operator) {
null => AccessHelper::keyExists($node, $key, $this->magicIsAllowed) || (!$key),
"=", "==" => $this->compareEquals($selectedNode, $comparisonValue),
"!=", "!==", "<>" => !$this->compareEquals($selectedNode, $comparisonValue),
'=~' => @\preg_match($comparisonValue, $selectedNode),
'<' => $this->compareLessThan($selectedNode, $comparisonValue),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential risk with error-suppressed regex.
Using @\preg_match($comparisonValue, $selectedNode) may hide warnings or errors from invalid user-supplied patterns. This can raise security and debugging concerns. Consider removing error suppression or validating patterns ahead of time.

@SoftCreatR SoftCreatR force-pushed the james-dev branch 2 times, most recently from d761568 to b67f7aa Compare March 21, 2025 07:43
@codecov-commenter
Copy link

codecov-commenter commented Mar 21, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.86%. Comparing base (fc12dee) to head (9aab673).
Report is 8 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main      #79      +/-   ##
============================================
+ Coverage     89.36%   89.86%   +0.49%     
- Complexity      202      223      +21     
============================================
  Files            11       11              
  Lines           395      444      +49     
============================================
+ Hits            353      399      +46     
- Misses           42       45       +3     

☔ 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.

@lucasnetau
Copy link
Contributor Author

Lgtm. I wonder, if this resolves some of the open issues.

It does. I'll go through tomorrow and mark the ones it closes.

@SoftCreatR
Copy link
Owner

Lgtm. I wonder, if this resolves some of the open issues.

It does. I'll go through tomorrow and mark the ones it closes.

Excellent. Your pull request is slated for release as v0.10.0. I've already added a placeholder for these updates in the changelog. Please update the changelog with any additional details you deem necessary. Once that's done, I'll publish the new release as soon as possible. Thank you for your hard work :)

@lucasnetau
Copy link
Contributor Author

Fixed issues have been marked for closing. I'll now update the Changelog.

@lucasnetau
Copy link
Contributor Author

CHANGELOG updated.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
CHANGELOG.md (1)

3-3: Adjust Heading Level for Consistency

The version header "### 0.10.0" on line 3 should increment by only one level from the top-level heading. Since "# Changelog" is an h1, consider updating "### 0.10.0" to "## 0.10.0" to conform with proper Markdown heading hierarchy.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

3-3: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d4fe01 and 9aab673.

📒 Files selected for processing (1)
  • CHANGELOG.md (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
CHANGELOG.md

3-3: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🔇 Additional comments (1)
CHANGELOG.md (1)

4-24: Comprehensive Changelog Entry for v0.10.0

The new changelog entry clearly details all the fixes and enhancements (e.g., various filter expression adjustments, test corrections, and the addition of JSONPath-related NULL tests) in line with the PR objectives. The bullet points are well-organized and descriptive.

@SoftCreatR
Copy link
Owner

Awesome, thank you =)

@SoftCreatR SoftCreatR merged commit 6c39dbd into SoftCreatR:main Mar 22, 2025
6 checks passed
@lucasnetau lucasnetau deleted the james-dev branch March 22, 2025 00:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment