Skip to content

Allow dialects that use -> as an operator to support LAMBDA syntax - #2458

Open
adriangb wants to merge 5 commits into
apache:mainfrom
adriangb:split-lambda-keyword-syntax
Open

Allow dialects that use -> as an operator to support LAMBDA syntax#2458
adriangb wants to merge 5 commits into
apache:mainfrom
adriangb:split-lambda-keyword-syntax

Conversation

@adriangb

Copy link
Copy Markdown

Motivation

supports_lambda_functions() gates two different spellings of the same feature:

  • the arrow form, x -> x + 1
  • the LAMBDA keyword form, LAMBDA x : x + 1

Because they share one flag, a dialect cannot have one without the other. That
shuts out any dialect that already gives -> a meaning. PostgreSQL is the
obvious case: -> is JSON member access, so turning the flag on silently
reinterprets existing expressions rather than adding a capability.

Concretely, with the flag enabled, a -> 'b' no longer parses as a binary
operator. It parses as a lambda with parameter a and body 'b', because
parse_prefix treats any unreserved word followed by -> as a lambda
parameter. Note ->> is unaffected, so the breakage is partial and easy to
miss.

The LAMBDA keyword form has no such conflict: it does not claim ->.

Change

Adds Dialect::supports_lambda_keyword_syntax(), which gates only the LAMBDA
keyword form, and defaults to supports_lambda_functions().

No existing dialect changes behavior. Dialects that support the arrow form keep
both spellings; dialects that support neither still get neither. A dialect that
uses -> for something else can now override just the new method to get lambdas
without disturbing its operator.

No dialect shipped here opts in; this only makes the capability reachable.

Tests

Two tests in tests/sqlparser_custom_dialect.rs:

  • a dialect enabling only supports_lambda_keyword_syntax parses
    lambda x : x + 1 while -> stays a BinaryOperator::Arrow
  • a dialect enabling only supports_lambda_functions still accepts both
    spellings, pinning the defaulting behavior

Full suite, cargo fmt --check, and cargo clippy --all-targets --all-features
all pass.

Comment thread src/dialect/mod.rs
Comment on lines +558 to +560
fn supports_lambda_keyword_syntax(&self) -> bool {
self.supports_lambda_functions()
}

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.

One could argue for adding fn supports_lambda_arrow_syntax() as well, but I'd hold off until there is a concrete use case for enabling arrow syntax but not lambda syntax.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Arrow-only is already expressible by overriding supports_lambda_keyword_syntax to false, so I believe there is no need.

Comment on lines +127 to +128
#[test]
fn test_lambda_keyword_syntax_on_postgres_derivative() {

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.

I'm split between this (the real regression test I want) and another test using a MyDialect in sqlparser_custom_dialect.rs that enables the two flags. Open to input.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Both seem worth keeping.

Comment thread tests/sqlparser_derive_dialect.rs Outdated
@adriangb

Copy link
Copy Markdown
Author

@LucaCappelletti94 could I ask you to take a look at this change? Thanks!

@LucaCappelletti94 LucaCappelletti94 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Generally ok, just a missing Snowflake syntax test, and the missing documentation to lambda, and the wrong syntax in the example.

panic!("expected `->` to stay a binary operator");
};
assert_eq!(&BinaryOperator::Arrow, op);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I believe we should add a test for the Spark/Snowflake case (they only accept ->):

Suggested change
}
}
#[test]
fn custom_dialect_lambda_arrow_syntax_without_keyword() {
// Arrow lambdas stay on while the `LAMBDA` keyword spelling is off,
// as in engines like Spark and Snowflake.
#[derive(Debug)]
struct MyDialect {}
impl Dialect for MyDialect {
fn is_identifier_start(&self, ch: char) -> bool {
is_identifier_start(ch)
}
fn is_identifier_part(&self, ch: char) -> bool {
is_identifier_part(ch)
}
fn supports_lambda_functions(&self) -> bool {
true
}
fn supports_lambda_keyword_syntax(&self) -> bool {
false
}
}
let dialect = MyDialect {};
let sql = "SELECT transform(xs, x -> x + 1)";
assert_eq!(
sql,
&format!("{}", Parser::parse_sql(&dialect, sql).unwrap()[0])
);
assert!(Parser::parse_sql(&dialect, "SELECT transform(xs, lambda x : x + 1)").is_err());
}

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.

Thanks, added but in sqlparser_custom_dialect.rs

Comment thread src/dialect/mod.rs Outdated
/// lambda functions, for example:
///
/// ```sql
/// SELECT transform(array(1, 2, 3), LAMBDA x : x + 1); -- returns [2,3,4]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I believe transform(array(...), LAMBDA ...) is the wrong spelling, if you meant the DuckDB syntax it would be more like:

Suggested change
/// SELECT transform(array(1, 2, 3), LAMBDA x : x + 1); -- returns [2,3,4]
/// SELECT list_transform([1, 2, 3], lambda x : x + 1); -- returns [2, 3, 4]

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.

Thanks, applied!

Comment thread src/dialect/mod.rs
/// and its derivatives, where `->` is JSON member access. Defaults to
/// [`Self::supports_lambda_functions`], so dialects supporting the `->`
/// spelling accept the `LAMBDA` spelling too unless they say otherwise.
fn supports_lambda_keyword_syntax(&self) -> bool {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
fn supports_lambda_keyword_syntax(&self) -> bool {
///
/// See <https://duckdb.org/docs/stable/sql/functions/lambda>
fn supports_lambda_keyword_syntax(&self) -> bool {

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.

Thanks, applied!

Comment thread src/dialect/mod.rs
Comment on lines +558 to +560
fn supports_lambda_keyword_syntax(&self) -> bool {
self.supports_lambda_functions()
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Arrow-only is already expressible by overriding supports_lambda_keyword_syntax to false, so I believe there is no need.

Comment on lines +127 to +128
#[test]
fn test_lambda_keyword_syntax_on_postgres_derivative() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Both seem worth keeping.

@adriangb
adriangb force-pushed the split-lambda-keyword-syntax branch from 2d11f84 to d994419 Compare August 30, 2026 16:08
adriangb and others added 5 commits August 30, 2026 11:24
Exercises the capability the way a downstream crate would: derive a
dialect from PostgreSqlDialect with `supports_lambda_keyword_syntax`
overridden, then check that `LAMBDA x : x + 1` parses while `->` and
`->>` keep parsing as JSON member access rather than lambda parameters.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Address review feedback: rather than parsing the `LAMBDA` spelling and
the `->` operator as separate statements, parse one expression that uses
both — a lambda whose body is a JSON access — which is the shape a
PostgreSQL derivative actually cares about.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
All three changes are applied review suggestions from Luca Cappelletti.

Co-Authored-By: Luca Cappelletti <7738570+LucaCappelletti94@users.noreply.github.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@adriangb
adriangb force-pushed the split-lambda-keyword-syntax branch from d994419 to 1d89c66 Compare August 30, 2026 16:24
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