Parse a restricted `SELECT` statement (no CTEs / `UNION` / `ORDER BY`), assuming the initial `SELECT` was already consumed
(&mut self)
| 7811 | /// Parse a restricted `SELECT` statement (no CTEs / `UNION` / `ORDER BY`), |
| 7812 | /// assuming the initial `SELECT` was already consumed |
| 7813 | fn parse_select(&mut self) -> Result<Select<Raw>, ParserError> { |
| 7814 | let all = self.parse_keyword(ALL); |
| 7815 | let distinct = self.parse_keyword(DISTINCT); |
| 7816 | if all && distinct { |
| 7817 | return parser_err!( |
| 7818 | self, |
| 7819 | self.peek_prev_pos(), |
| 7820 | "Cannot specify both ALL and DISTINCT in SELECT" |
| 7821 | ); |
| 7822 | } |
| 7823 | let distinct = if distinct && self.parse_keyword(ON) { |
| 7824 | self.expect_token(&Token::LParen)?; |
| 7825 | let exprs = self.parse_comma_separated(Parser::parse_expr)?; |
| 7826 | self.expect_token(&Token::RParen)?; |
| 7827 | Some(Distinct::On(exprs)) |
| 7828 | } else if distinct { |
| 7829 | Some(Distinct::EntireRow) |
| 7830 | } else { |
| 7831 | None |
| 7832 | }; |
| 7833 | |
| 7834 | let projection = match self.peek_token() { |
| 7835 | // An empty target list is permissible to match PostgreSQL, which |
| 7836 | // permits these for symmetry with zero column tables. We need |
| 7837 | // to sniff out `AS` here specially to support `SELECT AS OF ...`. |
| 7838 | Some(Token::Keyword(kw)) if kw.is_always_reserved() || kw == AS => vec![], |
| 7839 | Some(Token::Semicolon) | Some(Token::RParen) | None => vec![], |
| 7840 | _ => { |
| 7841 | let mut projection = vec![]; |
| 7842 | loop { |
| 7843 | projection.push(self.parse_select_item()?); |
| 7844 | if !self.consume_token(&Token::Comma) { |
| 7845 | break; |
| 7846 | } |
| 7847 | if self.peek_keyword(FROM) { |
| 7848 | return parser_err!( |
| 7849 | self, |
| 7850 | self.peek_prev_pos(), |
| 7851 | "invalid trailing comma in SELECT list", |
| 7852 | ); |
| 7853 | } |
| 7854 | } |
| 7855 | projection |
| 7856 | } |
| 7857 | }; |
| 7858 | |
| 7859 | // Note that for keywords to be properly handled here, they need to be |
| 7860 | // added to `RESERVED_FOR_COLUMN_ALIAS` / `RESERVED_FOR_TABLE_ALIAS`, |
| 7861 | // otherwise they may be parsed as an alias as part of the `projection` |
| 7862 | // or `from`. |
| 7863 | |
| 7864 | let from = if self.parse_keyword(FROM) { |
| 7865 | self.parse_comma_separated(Parser::parse_table_and_joins)? |
| 7866 | } else { |
| 7867 | vec![] |
| 7868 | }; |
| 7869 | |
| 7870 | let selection = if self.parse_keyword(WHERE) { |
no test coverage detected