Skip to content

fix(spp_cel_domain): handle relational fields and SQL JOINs in CEL#41

Open
jeremi wants to merge 1 commit into19.0from
feat/cel-domain-fixes
Open

fix(spp_cel_domain): handle relational fields and SQL JOINs in CEL#41
jeremi wants to merge 1 commit into19.0from
feat/cel-domain-fixes

Conversation

@jeremi
Copy link
Member

@jeremi jeremi commented Feb 17, 2026

Summary

  • Handle one2many/many2many fields as bare CEL predicates instead of erroring
  • Use query.select() for SQL with JOINs instead of raw field access, fixing incorrect query generation
  • Add tests for relational predicate handling

Origin

Cherry-picked from openspp-modules-v2 branch claude/global-alliance-policy-basket.

Test plan

  • Existing CEL domain tests pass
  • New relational predicate tests pass
  • CEL expressions using x2many fields evaluate correctly

- Handle one2many/many2many fields as bare CEL predicates
- Use query.select() for SQL with JOINs instead of raw field access
- Add tests for relational predicate handling
@gemini-code-assist
Copy link

Summary of Changes

Hello @jeremi, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the Common Expression Language (CEL) domain functionality by improving its ability to handle relational fields and generate accurate SQL queries. It allows 'one2many' and 'many2many' fields to be used intuitively as bare predicates, simplifying complex expressions. The changes also ensure that SQL queries involving related fields are correctly constructed with necessary JOINs, preventing data retrieval issues. Furthermore, the cache invalidation mechanism for CEL variables has been made more robust, guaranteeing that changes to variables are immediately reflected across all CEL components.

Highlights

  • Relational Field Predicates: Enabled 'one2many' and 'many2many' fields to be used as bare predicates in CEL expressions, interpreting them as checks for the presence of related records.
  • Improved SQL Generation: Switched to 'query.select()' for SQL generation in CEL domain conversions, ensuring correct handling of SQL JOINs for related field lookups and preventing incorrect query generation.
  • Centralized Cache Invalidation: Consolidated CEL cache invalidation logic to clear all relevant caches (resolver, translation, profile) in a coordinated manner when CEL variables are modified or deleted.
  • Comprehensive Testing: Introduced new dedicated tests for relational predicate handling and expanded existing tests to cover various scenarios of CEL variable cache invalidation.
Changelog
  • spp_cel_domain/models/cel_executor.py
    • Updated SQL generation for domain conversion to use 'query.select()' for better JOIN handling.
    • Adjusted a 'round()' function call for coverage calculation formatting.
  • spp_cel_domain/models/cel_sql_builder.py
    • Refactored 'select_ids_from_domain' to streamline SQL generation and incorporate 'query.select()' for relational field support.
  • spp_cel_domain/models/cel_translator.py
    • Modified '_flatten_attr' to support 'one2many' and 'many2many' fields as bare predicates, treating them as "not empty" checks.
  • spp_cel_domain/models/cel_variable.py
    • Revised '_invalidate_resolver_cache' to call a centralized 'cel_service.invalidate_caches()' method, ensuring all CEL caches are cleared.
  • spp_cel_domain/tests/init.py
    • Added 'test_cel_relational_predicate' to the test suite.
  • spp_cel_domain/tests/test_cel_relational_predicate.py
    • Introduced new tests for 'one2many' and 'many2many' fields as bare CEL predicates, verifying compilation and correct domain generation.
  • spp_cel_domain/tests/test_cel_variable.py
    • Added a new test class 'TestCELVariableCacheInvalidation' with multiple tests covering variable creation, modification, deletion, and their impact on various CEL caches.
Activity
  • No specific activity (comments, reviews, progress updates) has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces important fixes and features, including correctly handling SQL generation for domains with related fields using query.select() in cel_executor.py and cel_sql_builder.py, enabling the use of relational fields (one2many, many2many) as bare predicates in CEL expressions via cel_translator.py, and enhancing cache invalidation in cel_variable.py. A security audit confirmed no vulnerabilities, highlighting the use of Odoo's SQL objects and SQL.identifier to prevent SQL injection, and robust security measures in the CEL parser against sandbox escape or denial-of-service attacks. The new tests are comprehensive, though one could be made more specific.

Comment on lines +77 to +82
found = False
for leaf in domain:
if isinstance(leaf, tuple) and leaf[0] == "program_membership_ids" and leaf[1] == "!=":
found = True
break
self.assertTrue(found, f"Expected '!= False' domain for one2many, got: {domain}")

Choose a reason for hiding this comment

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

medium

The current test assertion is a bit weak as it only checks for the presence of the != operator but not the full domain leaf ('program_membership_ids', '!=', False). This could lead to a false positive if the generated domain was, for example, ('program_membership_ids', '!=', True).

To make the test more robust and specific, I suggest checking for the exact expected tuple within the domain. This can be done more concisely using any().

        expected_leaf = ("program_membership_ids", "!=", False)
        # The domain can be complex due to base_domains, so we check if any leaf matches.
        found = any(leaf == expected_leaf for leaf in domain if isinstance(leaf, tuple))
        self.assertTrue(found, f"Expected '{expected_leaf}' to be in domain, but got: {domain}")

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.

1 participant