File tree Expand file tree Collapse file tree 3 files changed +48
-1
lines changed
Expand file tree Collapse file tree 3 files changed +48
-1
lines changed Original file line number Diff line number Diff 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
Original file line number Diff line number Diff 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}
Original file line number Diff line number Diff 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+ }
You can’t perform that action at this time.
0 commit comments