Skip to content

Fix backtick stripping in Cypher map literal keys#3322

Merged
robfrank merged 1 commit intoArcadeData:mainfrom
ExtReMLapin:claude/fix-cypher-backticks-ZP7Ub
Feb 4, 2026
Merged

Fix backtick stripping in Cypher map literal keys#3322
robfrank merged 1 commit intoArcadeData:mainfrom
ExtReMLapin:claude/fix-cypher-backticks-ZP7Ub

Conversation

@ExtReMLapin
Copy link
Contributor

What does this PR do?

This PR fixes an issue where backticks in map literal keys were not being properly stripped during Cypher query parsing. The stripBackticks method in CypherASTBuilder is now made static and called when parsing map literals in CypherExpressionBuilder, ensuring that backticked keys (e.g., `@rid`) are correctly converted to their unquoted form (e.g., @rid).

Motivation

When using map literals in Cypher queries with backticked keys (commonly needed for special characters like @), the backticks were being retained in the resulting map keys. This caused queries like:

RETURN {`@rid`: ID(c), text: c.text} AS chunks

to produce maps with keys like `@rid` instead of @rid, breaking downstream code that expected the unquoted key names.

Related issues

This fix addresses the handling of backticked identifiers in map literals, which is part of the Cypher specification for escaping reserved words and special characters.

Additional Notes

  • The stripBackticks method is now static to allow reuse across different builder classes
  • Two locations in CypherExpressionBuilder now call this method: parseMapLiteralExpression and parseMapProperties
  • Comprehensive test coverage added with three test cases covering:
    • Single backticked keys in map literals
    • Multiple backticked keys in the same map
    • Escaped backticks within key names ( ` ``)

Checklist

  • I have run the build using mvn clean package command
  • My unit tests cover both failure and success scenarios

https://claude.ai/code/session_01ATpxvdUh9HNtuBW7x9NmLT

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ExtReMLapin, 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 resolves an issue in the Cypher parser where map literal keys enclosed in backticks were not being properly unquoted. This fix ensures that keys like `@rid` are correctly processed as @rid, aligning with the Cypher specification and preventing unexpected behavior in applications consuming these query results.

Highlights

  • Method Visibility and Reusability: The stripBackticks method in CypherASTBuilder has been made static to allow its reuse across different builder classes, improving code modularity.
  • Cypher Map Literal Key Parsing: The CypherExpressionBuilder now correctly strips backticks from map literal keys by calling the CypherASTBuilder.stripBackticks method within both parseMapLiteralExpression and parseMapProperties.
  • Comprehensive Test Coverage: New unit tests have been added in CypherMapBackticksTest.java to validate the correct stripping of backticks from map literal keys, covering scenarios with single backticked keys, multiple backticked keys, and escaped backticks within key names.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • engine/src/main/java/com/arcadedb/query/opencypher/parser/CypherASTBuilder.java
    • Changed the stripBackticks method from private to static to enable broader accessibility.
  • engine/src/main/java/com/arcadedb/query/opencypher/parser/CypherExpressionBuilder.java
    • Modified parseMapLiteralExpression to apply CypherASTBuilder.stripBackticks to map keys, ensuring backticks are removed.
    • Modified parseMapProperties to apply CypherASTBuilder.stripBackticks to map keys, ensuring backticks are removed.
  • engine/src/test/java/com/arcadedb/query/opencypher/CypherMapBackticksTest.java
    • Added a new test file to validate the correct stripping of backticks from map literal keys.
    • Included test cases for single backticked keys, multiple backticked keys, and escaped backticks (e.g., -> ` ``).
Activity
  • The author, ExtReMLapin, has confirmed that the build has been run using mvn clean package.
  • Unit tests covering both failure and success scenarios have been implemented and verified by the author.
  • Development of this feature appears to have involved AI assistance, as indicated by a Claude AI session link in the PR description.
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
Contributor

@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 addresses an issue with backticked keys in Cypher map literals by introducing and applying the stripBackticks utility method. The change to make stripBackticks static is a good design choice for reusability, and the new tests provide solid coverage for the fixed scenarios. However, the fix appears to be partial, as similar logic is needed in other parts of the parser to ensure consistent handling of backticked keys across all map-like constructs. I've added a specific comment detailing the missed locations.

@mergify
Copy link
Contributor

mergify bot commented Feb 4, 2026

🧪 CI Insights

Here's what we observed from your CI run for 42b9260.

🟢 All jobs passed!

But CI Insights is watching 👀

@ExtReMLapin
Copy link
Contributor Author

Claude wrote all of this.

Fixes #3321

@ExtReMLapin ExtReMLapin force-pushed the claude/fix-cypher-backticks-ZP7Ub branch 2 times, most recently from 5e4d1d3 to 1c64267 Compare February 4, 2026 09:05
Fixed an issue where backticks in map literal keys and property names
were being included instead of being properly stripped. Applied the fix
consistently across all map-related and property access parsing contexts.

Changes:
- Made CypherASTBuilder.stripBackticks() static and package-private
  to allow access from CypherExpressionBuilder
- Updated CypherExpressionBuilder.parseMapLiteralExpression() to strip
  backticks from map keys (RETURN clause map literals)
- Updated CypherExpressionBuilder.parseMapProperties() to strip
  backticks from map keys (pattern properties)
- Updated CypherASTBuilder.visitMap() to strip backticks from map keys
  (CREATE/MERGE clause map literals)
- Updated CypherExpressionBuilder.parseMapProjection() to strip
  backticks from both explicit keys and property names (map projections)
- Updated CypherExpressionBuilder.parseExpression2WithPostfix() to strip
  backticks from property names in property access expressions
- Updated CypherExpressionBuilder.parseExpressionText() to strip
  backticks from property names in text-based parsing
- Added comprehensive test cases in CypherMapBackticksTest to verify:
  - Single backticked key in RETURN (e.g., `@rid`)
  - Multiple backticked keys in RETURN
  - Escaped backticks within keys (e.g., `key``with``backticks`)
  - Backticked keys in CREATE clause
  - Backticked keys in map projections
  - Property access with backticked names (e.g., n.`@id`)

Example queries that now work correctly:
- RETURN: collect({`@rid`: ID(c), text: c.text})
- CREATE: CREATE (n {`@special`: 'value'})
- Map projection: n{.name, `@id`: n.id}
- Property access: RETURN n.`@special`

Before: keys/properties were stored/accessed as "`@rid`" (with backticks)
After: keys/properties are stored/accessed as "@Rid" (without backticks)

https://claude.ai/code/session_01ATpxvdUh9HNtuBW7x9NmLT
@ExtReMLapin ExtReMLapin force-pushed the claude/fix-cypher-backticks-ZP7Ub branch from 1c64267 to 42b9260 Compare February 4, 2026 09:13
@ExtReMLapin
Copy link
Contributor Author

mvn test -Dtest="com.arcadedb.query.opencypher.**.*"

[INFO] ArcadeDB ........................................... SUCCESS [ 0.038 s]
[INFO] ArcadeDB Engine .................................... SUCCESS [ 13.498 s]

@robfrank robfrank added this to the 26.2.1 milestone Feb 4, 2026
@codecov
Copy link

codecov bot commented Feb 4, 2026

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 56.58%. Comparing base (0ffaf5b) to head (42b9260).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...ery/opencypher/parser/CypherExpressionBuilder.java 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3322      +/-   ##
==========================================
- Coverage   56.61%   56.58%   -0.03%     
==========================================
  Files        1368     1368              
  Lines      100618   100618              
  Branches    20486    20486              
==========================================
- Hits        56961    56934      -27     
- Misses      34538    34545       +7     
- Partials     9119     9139      +20     

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@robfrank robfrank merged commit ada9a89 into ArcadeData:main Feb 4, 2026
15 of 20 checks passed
robfrank pushed a commit that referenced this pull request Feb 17, 2026
…3322)

Fixed an issue where backticks in map literal keys and property names
were being included instead of being properly stripped. Applied the fix
consistently across all map-related and property access parsing contexts.

Changes:
- Made CypherASTBuilder.stripBackticks() static and package-private
  to allow access from CypherExpressionBuilder
- Updated CypherExpressionBuilder.parseMapLiteralExpression() to strip
  backticks from map keys (RETURN clause map literals)
- Updated CypherExpressionBuilder.parseMapProperties() to strip
  backticks from map keys (pattern properties)
- Updated CypherASTBuilder.visitMap() to strip backticks from map keys
  (CREATE/MERGE clause map literals)
- Updated CypherExpressionBuilder.parseMapProjection() to strip
  backticks from both explicit keys and property names (map projections)
- Updated CypherExpressionBuilder.parseExpression2WithPostfix() to strip
  backticks from property names in property access expressions
- Updated CypherExpressionBuilder.parseExpressionText() to strip
  backticks from property names in text-based parsing
- Added comprehensive test cases in CypherMapBackticksTest to verify:
  - Single backticked key in RETURN (e.g., `@rid`)
  - Multiple backticked keys in RETURN
  - Escaped backticks within keys (e.g., `key``with``backticks`)
  - Backticked keys in CREATE clause
  - Backticked keys in map projections
  - Property access with backticked names (e.g., n.`@id`)

Before: keys/properties were stored/accessed as "`@rid`" (with backticks)
After: keys/properties are stored/accessed as "@Rid" (without backticks)

(cherry picked from commit ada9a89)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cypher : `collect({@rid: ID(c), text: c.text})` should return a key with no backtick

3 participants