Skip to content

Escape single quotes in string literals pushed to Cassandra and Geode#5075

Open
Samin061 wants to merge 2 commits into
apache:mainfrom
Samin061:escape-quotes-cql-oql
Open

Escape single quotes in string literals pushed to Cassandra and Geode#5075
Samin061 wants to merge 2 commits into
apache:mainfrom
Samin061:escape-quotes-cql-oql

Conversation

@Samin061

@Samin061 Samin061 commented Jul 4, 2026

Copy link
Copy Markdown

Jira Link

No Jira filed yet; happy to open one under CALCITE if you'd prefer to track it there.

Changes Proposed

When the Cassandra and Geode adapters push a filter down to the backend, a SQL string literal is wrapped in single quotes to build the CQL/OQL predicate, but embedded single quotes are not escaped. CassandraFilter.translateOp2 and GeodeFilter.quoteCharLiteral emit col = '<value>' verbatim, so a value that itself contains a quote breaks out of the string literal. A legitimate value such as O'Brien produces malformed CQL/OQL, and a runtime-supplied literal can inject additional predicate syntax into the query that reaches session.execute / QueryService.newQuery.

The Geode test for WHERE city = 'a''b' currently makes the OQL parser fail with unexpected token: b, which shows the value leaking out of the literal. Doubling the embedded quote (' -> '') keeps the value inside the literal for both dialects; this is the same escaping the Druid adapter already applies in DruidExpressions.stringLiteral.

Added a Geode test that asserts the generated OQL is ... WHERE city = 'a''b', and a Cassandra test that a quoted filter value executes cleanly.

@xiedeyantu xiedeyantu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the idea is good, but the code is not good.

SqlTypeName typeName = field.getType().getSqlTypeName();
if (typeName != SqlTypeName.CHAR) {
valueString = "'" + valueString + "'";
valueString = "'" + valueString.replace("'", "''") + "'";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If the value is I''m fine, I think replace will return an unexpected results.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

String.replace here is literal, not regex, so it doubles every embedded quote independently. For the value I''m fine (two adjacent quotes) it produces 'I''''m fine', which the CQL/OQL parser reads back as exactly I''m fine, so it round-trips fine. This is the same doubling core already does in SqlDialect.quoteStringLiteral (val.replace(literalEndQuoteString, literalEscapedQuote)). I pushed a Geode test with that exact value to lock it in.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Apologies, I misunderstood the situation. I think this change is good; you can create a Jira ticket and—following the example of other PRs—update the title and adjust the commit message accordingly.

Signed-off-by: bibi samina <sam@bugqore.com>
@Samin061

Samin061 commented Jul 5, 2026

Copy link
Copy Markdown
Author

Replied on the inline thread. The quote doubling mirrors what core does in SqlDialect.quoteStringLiteral, and I added a Geode test using your I''m fine example to show it round-trips. Happy to reshape it further if you have a specific form in mind.

@sonarqubecloud

sonarqubecloud Bot commented Jul 5, 2026

Copy link
Copy Markdown

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.

2 participants