Skip to content

Commit 99b7705

Browse files
Merge branch 'apache:main' into main
2 parents 7e6d09b + 355a3bf commit 99b7705

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

src/parser/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,15 @@ impl<'a> Parser<'a> {
12681268
Token::Mul => {
12691269
return Ok(Expr::Wildcard(AttachedToken(next_token)));
12701270
}
1271+
// Handle parenthesized wildcard: (*)
1272+
Token::LParen => {
1273+
let [maybe_mul, maybe_rparen] = self.peek_tokens_ref();
1274+
if maybe_mul.token == Token::Mul && maybe_rparen.token == Token::RParen {
1275+
let mul_token = self.next_token(); // consume Mul
1276+
self.next_token(); // consume RParen
1277+
return Ok(Expr::Wildcard(AttachedToken(mul_token)));
1278+
}
1279+
}
12711280
_ => (),
12721281
};
12731282

src/tokenizer.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1717,7 +1717,7 @@ impl<'a> Tokenizer<'a> {
17171717
}
17181718
}
17191719
Some('#') => self.consume_and_return(chars, Token::QuestionMarkSharp),
1720-
_ => self.consume_and_return(chars, Token::Question),
1720+
_ => Ok(Some(Token::Question)),
17211721
}
17221722
}
17231723
'?' => {
@@ -4147,4 +4147,23 @@ mod tests {
41474147
panic!("Tokenizer should have failed on {sql}, but it succeeded with {tokens:?}");
41484148
}
41494149
}
4150+
4151+
#[test]
4152+
fn tokenize_question_mark() {
4153+
let dialect = PostgreSqlDialect {};
4154+
let sql = "SELECT x ? y";
4155+
let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
4156+
compare(
4157+
tokens,
4158+
vec![
4159+
Token::make_keyword("SELECT"),
4160+
Token::Whitespace(Whitespace::Space),
4161+
Token::make_word("x", None),
4162+
Token::Whitespace(Whitespace::Space),
4163+
Token::Question,
4164+
Token::Whitespace(Whitespace::Space),
4165+
Token::make_word("y", None),
4166+
],
4167+
)
4168+
}
41504169
}

tests/sqlparser_common.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17953,3 +17953,22 @@ fn test_parse_set_session_authorization() {
1795317953
}))
1795417954
);
1795517955
}
17956+
17957+
#[test]
17958+
fn parse_select_parenthesized_wildcard() {
17959+
// Test SELECT DISTINCT(*) which uses a parenthesized wildcard
17960+
// The parentheses are syntactic sugar and get normalized to just *
17961+
let sql = "SELECT DISTINCT (*) FROM table1";
17962+
let canonical = "SELECT DISTINCT * FROM table1";
17963+
let select = all_dialects().verified_only_select_with_canonical(sql, canonical);
17964+
assert_eq!(select.distinct, Some(Distinct::Distinct));
17965+
assert_eq!(select.projection.len(), 1);
17966+
assert!(matches!(select.projection[0], SelectItem::Wildcard(_)));
17967+
17968+
// Also test without spaces: SELECT DISTINCT(*)
17969+
let sql_no_spaces = "SELECT DISTINCT(*) FROM table1";
17970+
let select2 = all_dialects().verified_only_select_with_canonical(sql_no_spaces, canonical);
17971+
assert_eq!(select2.distinct, Some(Distinct::Distinct));
17972+
assert_eq!(select2.projection.len(), 1);
17973+
assert!(matches!(select2.projection[0], SelectItem::Wildcard(_)));
17974+
}

0 commit comments

Comments
 (0)