Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for quantified comparison predicates (ALL/ANY/SOME) #1459

Merged
merged 6 commits into from
Oct 9, 2024

Conversation

yoavcloud
Copy link
Contributor

Allows comparisons against subquery results: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#_8_9_quantified_comparison_predicate

For example:

SELECT 42 >= SOME (SELECT 41 UNION ALL SELECT 42 UNION ALL SELECT 43); -- true

Comment on lines 2639 to 2642
let right = if self.is_query_ahead() {
// We have a subquery ahead (SELECT\WITH ...) need to rewind and
// use the parenthesis for parsing the subquery as an expression.
self.prev_token(); // SELECT
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make sense to call the self.prev_token() as part of the is_query_ahead() logic? Currently with the split it feels a bit disconnected that the method is abstracted but the caller here still has to know the details and manually rewind the token stream which seems like an arbitrary split of responsibility? So that if it works the same then the caller can only rely on the flag returned without knowing the details of how the check is done

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, good idea, implemented in the new commit.

// use the parenthesis for parsing the subquery as an expression.
self.prev_token(); // SELECT
self.prev_token(); // LParen
self.parse_subexpr(precedence)?
Copy link
Contributor

Choose a reason for hiding this comment

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

would it make sense to call self.try_parse_expr_sub_query() here already? it seems like it could let us avoid most of the if block here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried to make that work in the new commit, but since we need to rewind the LParen first it got a bit messy

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah right that makes sense!

@@ -12141,6 +12144,12 @@ impl<'a> Parser<'a> {
pub fn into_tokens(self) -> Vec<TokenWithLocation> {
self.tokens
}

/// Checks if the next keyword indicates a query, i.e. SELECT or WITH
pub fn is_query_ahead(&mut self) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
pub fn is_query_ahead(&mut self) -> bool {
fn peek_sub_query(&mut self) -> bool {

also the function was made public, assuming that was unintentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in new commit

@@ -12141,6 +12144,12 @@ impl<'a> Parser<'a> {
pub fn into_tokens(self) -> Vec<TokenWithLocation> {
self.tokens
}

/// Checks if the next keyword indicates a query, i.e. SELECT or WITH
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Checks if the next keyword indicates a query, i.e. SELECT or WITH
/// Returns true if the next keyword indicates a sub query, i.e. SELECT or WITH

src/ast/mod.rs Outdated
@@ -650,6 +650,8 @@ pub enum Expr {
left: Box<Expr>,
compare_op: BinaryOperator,
right: Box<Expr>,
// ANY and SOME are synonymous
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any one of the supported dialects supporting the SOME variant?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah cool! Can we include the link in the comment here as well? It could help later on in case someone comes across this and wonders the same

@yoavcloud yoavcloud requested a review from iffyio October 8, 2024 09:04
Copy link
Contributor

@iffyio iffyio left a comment

Choose a reason for hiding this comment

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

Thanks @yoavcloud! Left a couple minor comment regarding doc links, other than that I think this looks good

src/ast/mod.rs Outdated
@@ -650,6 +650,8 @@ pub enum Expr {
left: Box<Expr>,
compare_op: BinaryOperator,
right: Box<Expr>,
// ANY and SOME are synonymous
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah cool! Can we include the link in the comment here as well? It could help later on in case someone comes across this and wonders the same

src/ast/mod.rs Outdated
@@ -646,12 +646,16 @@ pub enum Expr {
regexp: bool,
},
/// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
/// https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#_8_9_quantified_comparison_predicate
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm thinking we can link to snowflake instead? Since that's a supported dialect that has the subquery functionality. The current link doesnt seem to refer to any specific dialect so it could add confusion later on when trying to figure what features in the parser to maintain

// use the parenthesis for parsing the subquery as an expression.
self.prev_token(); // SELECT
self.prev_token(); // LParen
self.parse_subexpr(precedence)?
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah right that makes sense!

@yoavcloud
Copy link
Contributor Author

Pushed doc changes as recommended.

@yoavcloud yoavcloud requested a review from iffyio October 8, 2024 16:40
Copy link
Contributor

@iffyio iffyio left a comment

Choose a reason for hiding this comment

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

LGTM! cc @alamb

Copy link
Contributor

@alamb alamb left a comment

Choose a reason for hiding this comment

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

🚀 -- thanks @iffyio and @yoavcloud

@coveralls
Copy link

coveralls commented Oct 9, 2024

Pull Request Test Coverage Report for Build 11261716771

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 34 of 40 (85.0%) changed or added relevant lines in 3 files are covered.
  • 1099 unchanged lines in 9 files lost coverage.
  • Overall coverage increased (+0.007%) to 89.315%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/parser/mod.rs 19 21 90.48%
src/ast/mod.rs 10 14 71.43%
Files with Coverage Reduction New Missed Lines %
tests/sqlparser_snowflake.rs 1 98.01%
src/dialect/sqlite.rs 1 80.0%
src/dialect/generic.rs 1 62.22%
tests/sqlparser_sqlite.rs 5 98.23%
src/dialect/mod.rs 12 67.51%
src/ast/ddl.rs 67 86.74%
src/parser/mod.rs 264 93.38%
src/ast/mod.rs 306 82.4%
tests/sqlparser_common.rs 442 89.57%
Totals Coverage Status
Change from base Build 11186281805: 0.007%
Covered Lines: 30143
Relevant Lines: 33749

💛 - Coveralls

@yoavcloud
Copy link
Contributor Author

@alamb can you please trigger the workflow again? Fixed an issue with the URLs in the docs

@alamb alamb merged commit a4fa9e0 into apache:main Oct 9, 2024
10 checks passed
@alamb
Copy link
Contributor

alamb commented Oct 9, 2024

Thanks again @yoavcloud

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.

4 participants