Skip to content

Conversation

@visz11
Copy link

@visz11 visz11 commented Oct 16, 2025

User description

  • Have you signed the contributor license agreement?
  • Have you followed the contributor guidelines?
  • If submitting code, have you built your formula locally prior to submission with gradle check?
  • If submitting code, is your pull request against main? Unless there is a good reason otherwise, we prefer pull requests against main and will backport as needed.
  • If submitting code, have you checked that your submission is for an OS and architecture that we support?
  • If you are submitting this code for a class then read our policy for that.

CodeAnt-AI Description

Translate PromQL proper-prefix/suffix label selectors into explicit starts-with + not-equal filters

What Changed

  • PromQL label regexes that use ".+" to mean "proper" prefix or suffix are now recognized and converted into two checks: a starts-with (or ends-with) test plus a not-equal exclusion of the exact literal. For example, pod=~"host-.+" becomes "starts with 'host-'" AND "not equals 'host-'", so the exact label "host-" is excluded.
  • Patterns using ".*" continue to map to simple starts-with/ends-with checks (no not-equal). Complex or mixed patterns still fall back to regex matching.
  • The pattern extractor now classifies proper-prefix and proper-suffix fragments so queries with alternations like "prod-.+|.+-dev" produce the correct matching behavior. Tests were added/updated to assert that planner output contains explicit Filter expressions (StartsWith, NotEquals, In, RegexMatch) when appropriate.

Impact

✅ More accurate label matches for queries like pod=~"host-.+"
✅ Fewer full-regex evaluations for common patterns like prefix.* or .*suffix
✅ Planner emits explicit starts-with + not-equal filters for proper-prefix/suffix patterns

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@codeant-ai
Copy link

codeant-ai bot commented Oct 16, 2025

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@gemini-code-assist
Copy link

Summary of Changes

Hello @visz11, 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 refines the PromQL query translation within ESQL by introducing more granular pattern fragment types for prefixes and suffixes. Previously, patterns like prefix.* and prefix.+ might have been treated similarly. With this change, prefix.+ is now recognized as a "proper prefix" (meaning it starts with prefix but is not exactly prefix), and similarly for suffixes. This allows for more accurate and semantically correct translation of complex PromQL label selectors into underlying ESQL filter conditions, ensuring that queries behave as expected when dealing with non-exact prefix/suffix matches.

Highlights

  • Enhanced Pattern Matching Types: Introduced PROPER_PREFIX and PROPER_SUFFIX types in AutomatonUtils.PatternFragment.Type to distinguish patterns like prefix.+ from prefix.*.
  • Improved PromQL Translation: Modified TranslatePromqlToTimeSeriesAggregate to correctly translate these new proper prefix/suffix patterns into ESQL expressions using AND conditions with NotEquals and StartsWith/EndsWith.
  • Expanded Test Coverage: Added new unit tests in AutomatonUtilsTests and PromqlLogicalPlanOptimizerTests to validate the accurate classification and translation of proper prefix and suffix patterns.
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.

@visz11
Copy link
Author

visz11 commented Oct 16, 2025

/refacto-visz

@coderabbitai
Copy link

coderabbitai bot commented Oct 16, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch clone-promql-proper-prefix

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codeant-ai codeant-ai bot added the size:M This PR changes 30-99 lines, ignoring generated files label Oct 16, 2025
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 correctly implements support for PromQL's proper prefix (.+) and proper suffix (.+-) regex patterns by translating them into STARTS_WITH/ENDS_WITH combined with a NOT_EQUALS check. The changes are logical, and new tests have been added to verify the behavior. My review includes a minor suggestion to reorder conditions in the generated AND expressions for a potential performance optimization.

return switch (fragment.type()) {
case EXACT -> new Equals(source, field, value);
case PREFIX -> new StartsWith(source, field, value);
case PROPER_PREFIX -> new And(source, new NotEquals(source, field, value), new StartsWith(source, field, value));

Choose a reason for hiding this comment

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

medium

For a potential performance improvement, it's generally better to place the more selective filter first in an AND condition. StartsWith is likely more selective than NotEquals, which could allow the query engine to short-circuit more effectively.

Suggested change
case PROPER_PREFIX -> new And(source, new NotEquals(source, field, value), new StartsWith(source, field, value));
case PROPER_PREFIX -> new And(source, new StartsWith(source, field, value), new NotEquals(source, field, value));

case PREFIX -> new StartsWith(source, field, value);
case PROPER_PREFIX -> new And(source, new NotEquals(source, field, value), new StartsWith(source, field, value));
case SUFFIX -> new EndsWith(source, field, value);
case PROPER_SUFFIX -> new And(source, new NotEquals(source, field, value), new EndsWith(source, field, value));

Choose a reason for hiding this comment

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

medium

For a potential performance improvement, it's generally better to place the more selective filter first in an AND condition. EndsWith is likely more selective than NotEquals, which could allow the query engine to short-circuit more effectively.

Suggested change
case PROPER_SUFFIX -> new And(source, new NotEquals(source, field, value), new EndsWith(source, field, value));
case PROPER_SUFFIX -> new And(source, new EndsWith(source, field, value), new NotEquals(source, field, value));

@refacto-visz
Copy link

refacto-visz bot commented Oct 16, 2025

Refacto is reviewing this PR. Please wait for the review comments to be posted.

Comment on lines +344 to +346
case PROPER_PREFIX -> new And(source, new NotEquals(source, field, value), new StartsWith(source, field, value));
case SUFFIX -> new EndsWith(source, field, value);
case PROPER_SUFFIX -> new And(source, new NotEquals(source, field, value), new EndsWith(source, field, value));
Copy link

Choose a reason for hiding this comment

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

Suggestion: Use the existing Predicates.combineAnd helper to compose the proper-prefix/proper-suffix condition instead of instantiating the And node directly, keeping combination logic consistent and avoiding a direct dependency on the And implementation. [best practice]

Suggested change
case PROPER_PREFIX -> new And(source, new NotEquals(source, field, value), new StartsWith(source, field, value));
case SUFFIX -> new EndsWith(source, field, value);
case PROPER_SUFFIX -> new And(source, new NotEquals(source, field, value), new EndsWith(source, field, value));
case PROPER_PREFIX -> Predicates.combineAnd(List.of(new NotEquals(source, field, value), new StartsWith(source, field, value)));
case PROPER_SUFFIX -> Predicates.combineAnd(List.of(new NotEquals(source, field, value), new EndsWith(source, field, value)));
Why Change? ⭐

The improved code replaces direct instantiation of the And node with the existing helper Predicates.combineAnd, which is already used elsewhere in the file (e.g., combineAnd(selectorConditions)). Predicates.combineAnd accepts a List, and List.of(...) is valid in the project's Java target (Java 9+ / 11). All referenced classes (NotEquals, StartsWith, EndsWith, Predicates) are present in the current file imports/context. The switch expression still returns an Expression, and Predicates.combineAnd returns an Expression as well, so the types match and the switch remains valid.

Assumptions:

  • Predicates.combineAnd(List) exists and returns an Expression (consistent with other usages in this file).
  • The project uses a Java version that supports List.of.
  • The NotEquals import (already present in the PR) is available.

This change is purely a refactor to use the helper for predicate composition, does not alter semantics, and avoids a direct dependency on the And implementation. No new runtime errors or compilation issues are introduced given the stated assumptions.

@codeant-ai
Copy link

codeant-ai bot commented Oct 16, 2025

CodeAnt AI finished reviewing your PR.

@refacto-visz
Copy link

refacto-visz bot commented Oct 16, 2025

Code Review: PromQL Pattern Matching Logic

👍 Well Done
Pattern Type Extension

Proper prefix/suffix distinction improves pattern matching precision and query optimization effectiveness

Comprehensive Test Coverage

New test methods validate proper prefix and regex pattern behavior with clear assertions

📁 Selected files for review (4)
  • x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/promql/AutomatonUtils.java
  • x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/promql/TranslatePromqlToTimeSeriesAggregate.java
  • x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/PromqlLogicalPlanOptimizerTests.java
  • x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/promql/AutomatonUtilsTests.java
🎯 Custom Instructions
✅ Applied Instructions
Organization Guidelines
  • Keep pull requests small and focused (prefer < 400 lines of code).
  • All CI/CD checks, linting, and unit tests must pass before merge.
  • Use feature flags for new functionality and include a clear rollback plan.
  • Follow the company security checklist:
    • No hard-coded secrets or credentials.
    • Validate all external inputs.
    • Use parameterized queries for DB access.

Scope: All files

📝 Additional Comments
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/promql/TranslatePromqlToTimeSeriesAggregate.java (2)
Complex Conditional Logic

Complex expression construction creates multiple nested objects in single statement. Extract method for creating proper prefix/suffix conditions would improve readability and reduce cognitive complexity.

Standards:

  • Clean-Code-Functions
  • Refactoring-Extract-Method
Complex Condition Optimization

Creating compound And expressions with NotEquals and pattern matching predicates increases query complexity. Each And operation requires evaluation of both conditions, potentially impacting query execution performance. Consider optimizing with single regex patterns for proper prefix/suffix matching.

Standards:

  • ISO-IEC-25010-Performance-Efficiency-Time-Behavior
  • Query-Optimization-Pattern-Compound-Conditions
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/promql/AutomatonUtils.java (1)
Pattern Validation Enhancement

Pattern classification logic uses string prefix checks without validation of the trimmed input format. While not directly exploitable, adding input validation would prevent potential edge cases where malformed patterns could bypass proper classification.

Standards:

  • CWE-20
  • OWASP-A03
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/PromqlLogicalPlanOptimizerTests.java (1)
Test Coverage Enhancement

New test methods validate proper prefix and regex pattern behavior effectively. Consider adding edge case tests for empty patterns and malformed regex to ensure comprehensive coverage of pattern detection logic.

Standards:

  • Clean-Code-Tests
  • Maintainability-Quality-Testing

if (isLiteral(suffix)) {
return new PatternFragment(PatternFragment.Type.SUFFIX, suffix);
return new PatternFragment(
trimmed.startsWith(".*") ? PatternFragment.Type.SUFFIX : PatternFragment.Type.PROPER_SUFFIX,
Copy link

Choose a reason for hiding this comment

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

Incorrect Suffix Pattern Detection Logic

Logic error in suffix pattern detection: condition checks startsWith(".*") but should validate if the suffix equals the entire literal after removing the prefix wildcard. This causes incorrect classification where all suffix patterns are misidentified, resulting in wrong query optimization behavior.

                    suffix.equals(trimmed.substring(2)) ? PatternFragment.Type.SUFFIX : PatternFragment.Type.PROPER_SUFFIX,
Commitable Suggestion
Suggested change
trimmed.startsWith(".*") ? PatternFragment.Type.SUFFIX : PatternFragment.Type.PROPER_SUFFIX,
suffix.equals(trimmed.substring(2)) ? PatternFragment.Type.SUFFIX : PatternFragment.Type.PROPER_SUFFIX,
Standards
  • Algorithm-Correctness-Boolean-Logic
  • Business-Rule-Pattern-Classification

if (isLiteral(prefix)) {
return new PatternFragment(PatternFragment.Type.PREFIX, prefix);
return new PatternFragment(
trimmed.endsWith(".*") ? PatternFragment.Type.PREFIX : PatternFragment.Type.PROPER_PREFIX,
Copy link

Choose a reason for hiding this comment

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

Incorrect Prefix Pattern Detection Logic

Logic error in prefix pattern detection: condition checks endsWith(".*") but should validate if the prefix equals the entire literal after removing the suffix wildcard. This causes incorrect classification where all prefix patterns are misidentified, affecting regex optimization logic.

                    prefix.equals(trimmed.substring(0, trimmed.length() - 2)) ? PatternFragment.Type.PREFIX : PatternFragment.Type.PROPER_PREFIX,
Commitable Suggestion
Suggested change
trimmed.endsWith(".*") ? PatternFragment.Type.PREFIX : PatternFragment.Type.PROPER_PREFIX,
prefix.equals(trimmed.substring(0, trimmed.length() - 2)) ? PatternFragment.Type.PREFIX : PatternFragment.Type.PROPER_PREFIX,
Standards
  • Algorithm-Correctness-Boolean-Logic
  • Business-Rule-Pattern-Classification

if (isLiteral(suffix)) {
return new PatternFragment(PatternFragment.Type.SUFFIX, suffix);
return new PatternFragment(
trimmed.startsWith(".*") ? PatternFragment.Type.SUFFIX : PatternFragment.Type.PROPER_SUFFIX,
Copy link

Choose a reason for hiding this comment

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

Redundant Pattern Validation

Conditional check for trimmed.startsWith(".*") is redundant since the containing if condition already validates this pattern. The ternary operator will always evaluate to SUFFIX type, making PROPER_SUFFIX unreachable and creating unnecessary computational overhead.

Standards
  • ISO-IEC-25010-Performance-Efficiency-Time-Behavior
  • Algorithmic-Complexity-Conditional-Optimization

if (isLiteral(prefix)) {
return new PatternFragment(PatternFragment.Type.PREFIX, prefix);
return new PatternFragment(
trimmed.endsWith(".*") ? PatternFragment.Type.PREFIX : PatternFragment.Type.PROPER_PREFIX,
Copy link

Choose a reason for hiding this comment

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

Redundant Pattern Validation

Conditional check for trimmed.endsWith(".*") is redundant since the containing if condition already validates this pattern. The ternary operator will always evaluate to PREFIX type, making PROPER_PREFIX unreachable and creating unnecessary computational overhead.

Standards
  • ISO-IEC-25010-Performance-Efficiency-Time-Behavior
  • Algorithmic-Complexity-Conditional-Optimization

@refacto-visz
Copy link

refacto-visz bot commented Oct 16, 2025

PR already reviewed at the latest commit: 5609698.
Please try again with new changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants