use log::debug;
use super::ast::*;
use super::dialect::keywords;
use super::dialect::Dialect;
use super::tokenizer::*;
use std::error::Error;
use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub enum ParserError {
TokenizerError(String),
ParserError(String),
}
macro_rules! parser_err {
($MSG:expr) => {
Err(ParserError::ParserError($MSG.to_string()))
};
}
#[derive(PartialEq)]
pub enum IsOptional {
Optional,
Mandatory,
}
use IsOptional::*;
pub enum IsLateral {
Lateral,
NotLateral,
}
use IsLateral::*;
impl From<TokenizerError> for ParserError {
fn from(e: TokenizerError) -> Self {
ParserError::TokenizerError(format!("{:?}", e))
}
}
impl fmt::Display for ParserError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"sql parser error: {}",
match self {
ParserError::TokenizerError(s) => s,
ParserError::ParserError(s) => s,
}
)
}
}
impl Error for ParserError {}
pub struct Parser {
tokens: Vec<Token>,
index: usize,
}
impl Parser {
pub fn new(tokens: Vec<Token>) -> Self {
Parser { tokens, index: 0 }
}
pub fn parse_sql(dialect: &dyn Dialect, sql: String) -> Result<Vec<Statement>, ParserError> {
let mut tokenizer = Tokenizer::new(dialect, &sql);
let tokens = tokenizer.tokenize()?;
let mut parser = Parser::new(tokens);
let mut stmts = Vec::new();
let mut expecting_statement_delimiter = false;
debug!("Parsing sql '{}'...", sql);
loop {
while parser.consume_token(&Token::SemiColon) {
expecting_statement_delimiter = false;
}
if parser.peek_token().is_none() {
break;
} else if expecting_statement_delimiter {
return parser.expected("end of statement", parser.peek_token());
}
let statement = parser.parse_statement()?;
stmts.push(statement);
expecting_statement_delimiter = true;
}
Ok(stmts)
}
pub fn parse_statement(&mut self) -> Result<Statement, ParserError> {
match self.next_token() {
Some(t) => match t {
Token::Word(ref w) if w.keyword != "" => match w.keyword.as_ref() {
"SELECT" | "WITH" | "VALUES" => {
self.prev_token();
Ok(Statement::Query(Box::new(self.parse_query()?)))
}
"CREATE" => Ok(self.parse_create()?),
"DROP" => Ok(self.parse_drop()?),
"DELETE" => Ok(self.parse_delete()?),
"INSERT" => Ok(self.parse_insert()?),
"UPDATE" => Ok(self.parse_update()?),
"ALTER" => Ok(self.parse_alter()?),
"COPY" => Ok(self.parse_copy()?),
"SET" => Ok(self.parse_set()?),
"SHOW" => Ok(self.parse_show()?),
"START" => Ok(self.parse_start_transaction()?),
"BEGIN" => Ok(self.parse_begin()?),
"COMMIT" => Ok(self.parse_commit()?),
"ROLLBACK" => Ok(self.parse_rollback()?),
_ => parser_err!(format!(
"Unexpected keyword {:?} at the beginning of a statement",
w.to_string()
)),
},
Token::LParen => {
self.prev_token();
Ok(Statement::Query(Box::new(self.parse_query()?)))
}
unexpected => self.expected(
"a keyword at the beginning of a statement",
Some(unexpected),
),
},
None => self.expected("SQL statement", None),
}
}
pub fn parse_expr(&mut self) -> Result<Expr, ParserError> {
self.parse_subexpr(0)
}
pub fn parse_subexpr(&mut self, precedence: u8) -> Result<Expr, ParserError> {
debug!("parsing expr");
let mut expr = self.parse_prefix()?;
debug!("prefix: {:?}", expr);
loop {
let next_precedence = self.get_next_precedence()?;
debug!("next precedence: {:?}", next_precedence);
if precedence >= next_precedence {
break;
}
expr = self.parse_infix(expr, next_precedence)?;
}
Ok(expr)
}
pub fn parse_prefix(&mut self) -> Result<Expr, ParserError> {
let tok = self
.next_token()
.ok_or_else(|| ParserError::ParserError("Unexpected EOF".to_string()))?;
let expr = match tok {
Token::Word(w) => match w.keyword.as_ref() {
"TRUE" | "FALSE" | "NULL" => {
self.prev_token();
Ok(Expr::Value(self.parse_value()?))
}
"CASE" => self.parse_case_expr(),
"CAST" => self.parse_cast_expr(),
"DATE" => Ok(Expr::Value(Value::Date(self.parse_literal_string()?))),
"EXISTS" => self.parse_exists_expr(),
"EXTRACT" => self.parse_extract_expr(),
"INTERVAL" => self.parse_literal_interval(),
"NOT" => Ok(Expr::UnaryOp {
op: UnaryOperator::Not,
expr: Box::new(self.parse_subexpr(Self::UNARY_NOT_PREC)?),
}),
"TIME" => Ok(Expr::Value(Value::Time(self.parse_literal_string()?))),
"TIMESTAMP" => Ok(Expr::Value(Value::Timestamp(self.parse_literal_string()?))),
_ => match self.peek_token() {
Some(Token::LParen) | Some(Token::Period) => {
let mut id_parts: Vec<Ident> = vec![w.to_ident()];
let mut ends_with_wildcard = false;
while self.consume_token(&Token::Period) {
match self.next_token() {
Some(Token::Word(w)) => id_parts.push(w.to_ident()),
Some(Token::Mult) => {
ends_with_wildcard = true;
break;
}
unexpected => {
return self
.expected("an identifier or a '*' after '.'", unexpected);
}
}
}
if ends_with_wildcard {
Ok(Expr::QualifiedWildcard(id_parts))
} else if self.consume_token(&Token::LParen) {
self.prev_token();
self.parse_function(ObjectName(id_parts))
} else {
Ok(Expr::CompoundIdentifier(id_parts))
}
}
_ => Ok(Expr::Identifier(w.to_ident())),
},
},
Token::Mult => Ok(Expr::Wildcard),
tok @ Token::Minus | tok @ Token::Plus => {
let op = if tok == Token::Plus {
UnaryOperator::Plus
} else {
UnaryOperator::Minus
};
Ok(Expr::UnaryOp {
op,
expr: Box::new(self.parse_subexpr(Self::PLUS_MINUS_PREC)?),
})
}
Token::Number(_)
| Token::SingleQuotedString(_)
| Token::NationalStringLiteral(_)
| Token::HexStringLiteral(_) => {
self.prev_token();
Ok(Expr::Value(self.parse_value()?))
}
Token::LParen => {
let expr = if self.parse_keyword("SELECT") || self.parse_keyword("WITH") {
self.prev_token();
Expr::Subquery(Box::new(self.parse_query()?))
} else {
Expr::Nested(Box::new(self.parse_expr()?))
};
self.expect_token(&Token::RParen)?;
Ok(expr)
}
unexpected => self.expected("an expression", Some(unexpected)),
}?;
if self.parse_keyword("COLLATE") {
Ok(Expr::Collate {
expr: Box::new(expr),
collation: self.parse_object_name()?,
})
} else {
Ok(expr)
}
}
pub fn parse_function(&mut self, name: ObjectName) -> Result<Expr, ParserError> {
self.expect_token(&Token::LParen)?;
let all = self.parse_keyword("ALL");
let distinct = self.parse_keyword("DISTINCT");
if all && distinct {
return parser_err!(format!(
"Cannot specify both ALL and DISTINCT in function: {}",
name.to_string(),
));
}
let args = self.parse_optional_args()?;
let over = if self.parse_keyword("OVER") {
self.expect_token(&Token::LParen)?;
let partition_by = if self.parse_keywords(vec!["PARTITION", "BY"]) {
self.parse_comma_separated(Parser::parse_expr)?
} else {
vec![]
};
let order_by = if self.parse_keywords(vec!["ORDER", "BY"]) {
self.parse_comma_separated(Parser::parse_order_by_expr)?
} else {
vec![]
};
let window_frame = if !self.consume_token(&Token::RParen) {
let window_frame = self.parse_window_frame()?;
self.expect_token(&Token::RParen)?;
Some(window_frame)
} else {
None
};
Some(WindowSpec {
partition_by,
order_by,
window_frame,
})
} else {
None
};
Ok(Expr::Function(Function {
name,
args,
over,
distinct,
}))
}
pub fn parse_window_frame(&mut self) -> Result<WindowFrame, ParserError> {
let units = match self.next_token() {
Some(Token::Word(w)) => w.keyword.parse::<WindowFrameUnits>()?,
unexpected => return self.expected("ROWS, RANGE, GROUPS", unexpected),
};
let (start_bound, end_bound) = if self.parse_keyword("BETWEEN") {
let start_bound = self.parse_window_frame_bound()?;
self.expect_keyword("AND")?;
let end_bound = Some(self.parse_window_frame_bound()?);
(start_bound, end_bound)
} else {
(self.parse_window_frame_bound()?, None)
};
Ok(WindowFrame {
units,
start_bound,
end_bound,
})
}
pub fn parse_window_frame_bound(&mut self) -> Result<WindowFrameBound, ParserError> {
if self.parse_keywords(vec!["CURRENT", "ROW"]) {
Ok(WindowFrameBound::CurrentRow)
} else {
let rows = if self.parse_keyword("UNBOUNDED") {
None
} else {
Some(self.parse_literal_uint()?)
};
if self.parse_keyword("PRECEDING") {
Ok(WindowFrameBound::Preceding(rows))
} else if self.parse_keyword("FOLLOWING") {
Ok(WindowFrameBound::Following(rows))
} else {
self.expected("PRECEDING or FOLLOWING", self.peek_token())
}
}
}
pub fn parse_case_expr(&mut self) -> Result<Expr, ParserError> {
let mut operand = None;
if !self.parse_keyword("WHEN") {
operand = Some(Box::new(self.parse_expr()?));
self.expect_keyword("WHEN")?;
}
let mut conditions = vec![];
let mut results = vec![];
loop {
conditions.push(self.parse_expr()?);
self.expect_keyword("THEN")?;
results.push(self.parse_expr()?);
if !self.parse_keyword("WHEN") {
break;
}
}
let else_result = if self.parse_keyword("ELSE") {
Some(Box::new(self.parse_expr()?))
} else {
None
};
self.expect_keyword("END")?;
Ok(Expr::Case {
operand,
conditions,
results,
else_result,
})
}
pub fn parse_cast_expr(&mut self) -> Result<Expr, ParserError> {
self.expect_token(&Token::LParen)?;
let expr = self.parse_expr()?;
self.expect_keyword("AS")?;
let data_type = self.parse_data_type()?;
self.expect_token(&Token::RParen)?;
Ok(Expr::Cast {
expr: Box::new(expr),
data_type,
})
}
pub fn parse_exists_expr(&mut self) -> Result<Expr, ParserError> {
self.expect_token(&Token::LParen)?;
let exists_node = Expr::Exists(Box::new(self.parse_query()?));
self.expect_token(&Token::RParen)?;
Ok(exists_node)
}
pub fn parse_extract_expr(&mut self) -> Result<Expr, ParserError> {
self.expect_token(&Token::LParen)?;
let field = self.parse_date_time_field()?;
self.expect_keyword("FROM")?;
let expr = self.parse_expr()?;
self.expect_token(&Token::RParen)?;
Ok(Expr::Extract {
field,
expr: Box::new(expr),
})
}
pub fn parse_date_time_field(&mut self) -> Result<DateTimeField, ParserError> {
let tok = self.next_token();
if let Some(Token::Word(ref k)) = tok {
match k.keyword.as_ref() {
"YEAR" => Ok(DateTimeField::Year),
"MONTH" => Ok(DateTimeField::Month),
"DAY" => Ok(DateTimeField::Day),
"HOUR" => Ok(DateTimeField::Hour),
"MINUTE" => Ok(DateTimeField::Minute),
"SECOND" => Ok(DateTimeField::Second),
_ => self.expected("date/time field", tok)?,
}
} else {
self.expected("date/time field", tok)?
}
}
pub fn parse_literal_interval(&mut self) -> Result<Expr, ParserError> {
let value = self.parse_literal_string()?;
let leading_field = self.parse_date_time_field()?;
let (leading_precision, last_field, fsec_precision) =
if leading_field == DateTimeField::Second {
let last_field = None;
let (leading_precision, fsec_precision) = self.parse_optional_precision_scale()?;
(leading_precision, last_field, fsec_precision)
} else {
let leading_precision = self.parse_optional_precision()?;
if self.parse_keyword("TO") {
let last_field = Some(self.parse_date_time_field()?);
let fsec_precision = if last_field == Some(DateTimeField::Second) {
self.parse_optional_precision()?
} else {
None
};
(leading_precision, last_field, fsec_precision)
} else {
(leading_precision, None, None)
}
};
Ok(Expr::Value(Value::Interval {
value,
leading_field,
leading_precision,
last_field,
fractional_seconds_precision: fsec_precision,
}))
}
pub fn parse_infix(&mut self, expr: Expr, precedence: u8) -> Result<Expr, ParserError> {
debug!("parsing infix");
let tok = self.next_token().unwrap();
let regular_binary_operator = match tok {
Token::Eq => Some(BinaryOperator::Eq),
Token::Neq => Some(BinaryOperator::NotEq),
Token::Gt => Some(BinaryOperator::Gt),
Token::GtEq => Some(BinaryOperator::GtEq),
Token::Lt => Some(BinaryOperator::Lt),
Token::LtEq => Some(BinaryOperator::LtEq),
Token::Plus => Some(BinaryOperator::Plus),
Token::Minus => Some(BinaryOperator::Minus),
Token::Mult => Some(BinaryOperator::Multiply),
Token::Mod => Some(BinaryOperator::Modulus),
Token::Div => Some(BinaryOperator::Divide),
Token::Word(ref k) => match k.keyword.as_ref() {
"AND" => Some(BinaryOperator::And),
"OR" => Some(BinaryOperator::Or),
"LIKE" => Some(BinaryOperator::Like),
"NOT" => {
if self.parse_keyword("LIKE") {
Some(BinaryOperator::NotLike)
} else {
None
}
}
_ => None,
},
_ => None,
};
if let Some(op) = regular_binary_operator {
Ok(Expr::BinaryOp {
left: Box::new(expr),
op,
right: Box::new(self.parse_subexpr(precedence)?),
})
} else if let Token::Word(ref k) = tok {
match k.keyword.as_ref() {
"IS" => {
if self.parse_keyword("NULL") {
Ok(Expr::IsNull(Box::new(expr)))
} else if self.parse_keywords(vec!["NOT", "NULL"]) {
Ok(Expr::IsNotNull(Box::new(expr)))
} else {
self.expected("NULL or NOT NULL after IS", self.peek_token())
}
}
"NOT" | "IN" | "BETWEEN" => {
self.prev_token();
let negated = self.parse_keyword("NOT");
if self.parse_keyword("IN") {
self.parse_in(expr, negated)
} else if self.parse_keyword("BETWEEN") {
self.parse_between(expr, negated)
} else {
self.expected("IN or BETWEEN after NOT", self.peek_token())
}
}
_ => panic!("No infix parser for token {:?}", tok),
}
} else if Token::DoubleColon == tok {
self.parse_pg_cast(expr)
} else {
panic!("No infix parser for token {:?}", tok)
}
}
pub fn parse_in(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
self.expect_token(&Token::LParen)?;
let in_op = if self.parse_keyword("SELECT") || self.parse_keyword("WITH") {
self.prev_token();
Expr::InSubquery {
expr: Box::new(expr),
subquery: Box::new(self.parse_query()?),
negated,
}
} else {
Expr::InList {
expr: Box::new(expr),
list: self.parse_comma_separated(Parser::parse_expr)?,
negated,
}
};
self.expect_token(&Token::RParen)?;
Ok(in_op)
}
pub fn parse_between(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
let low = self.parse_subexpr(Self::BETWEEN_PREC)?;
self.expect_keyword("AND")?;
let high = self.parse_subexpr(Self::BETWEEN_PREC)?;
Ok(Expr::Between {
expr: Box::new(expr),
negated,
low: Box::new(low),
high: Box::new(high),
})
}
pub fn parse_pg_cast(&mut self, expr: Expr) -> Result<Expr, ParserError> {
Ok(Expr::Cast {
expr: Box::new(expr),
data_type: self.parse_data_type()?,
})
}
const UNARY_NOT_PREC: u8 = 15;
const BETWEEN_PREC: u8 = 20;
const PLUS_MINUS_PREC: u8 = 30;
pub fn get_next_precedence(&self) -> Result<u8, ParserError> {
if let Some(token) = self.peek_token() {
debug!("get_next_precedence() {:?}", token);
match &token {
Token::Word(k) if k.keyword == "OR" => Ok(5),
Token::Word(k) if k.keyword == "AND" => Ok(10),
Token::Word(k) if k.keyword == "NOT" => match &self.peek_nth_token(1) {
Some(Token::Word(k)) if k.keyword == "IN" => Ok(Self::BETWEEN_PREC),
Some(Token::Word(k)) if k.keyword == "BETWEEN" => Ok(Self::BETWEEN_PREC),
Some(Token::Word(k)) if k.keyword == "LIKE" => Ok(Self::BETWEEN_PREC),
_ => Ok(0),
},
Token::Word(k) if k.keyword == "IS" => Ok(17),
Token::Word(k) if k.keyword == "IN" => Ok(Self::BETWEEN_PREC),
Token::Word(k) if k.keyword == "BETWEEN" => Ok(Self::BETWEEN_PREC),
Token::Word(k) if k.keyword == "LIKE" => Ok(Self::BETWEEN_PREC),
Token::Eq | Token::Lt | Token::LtEq | Token::Neq | Token::Gt | Token::GtEq => {
Ok(20)
}
Token::Plus | Token::Minus => Ok(Self::PLUS_MINUS_PREC),
Token::Mult | Token::Div | Token::Mod => Ok(40),
Token::DoubleColon => Ok(50),
_ => Ok(0),
}
} else {
Ok(0)
}
}
pub fn peek_token(&self) -> Option<Token> {
self.peek_nth_token(0)
}
pub fn peek_nth_token(&self, mut n: usize) -> Option<Token> {
let mut index = self.index;
loop {
index += 1;
match self.tokens.get(index - 1) {
Some(Token::Whitespace(_)) => continue,
non_whitespace => {
if n == 0 {
return non_whitespace.cloned();
}
n -= 1;
}
}
}
}
pub fn next_token(&mut self) -> Option<Token> {
loop {
self.index += 1;
match self.tokens.get(self.index - 1) {
Some(Token::Whitespace(_)) => continue,
token => return token.cloned(),
}
}
}
pub fn next_token_no_skip(&mut self) -> Option<&Token> {
self.index += 1;
self.tokens.get(self.index - 1)
}
pub fn prev_token(&mut self) {
loop {
assert!(self.index > 0);
self.index -= 1;
if let Some(Token::Whitespace(_)) = self.tokens.get(self.index) {
continue;
}
return;
}
}
fn expected<T>(&self, expected: &str, found: Option<Token>) -> Result<T, ParserError> {
parser_err!(format!(
"Expected {}, found: {}",
expected,
found.map_or_else(|| "EOF".to_string(), |t| format!("{}", t))
))
}
#[must_use]
pub fn parse_keyword(&mut self, expected: &'static str) -> bool {
assert!(keywords::ALL_KEYWORDS.contains(&expected));
match self.peek_token() {
Some(Token::Word(ref k)) if expected.eq_ignore_ascii_case(&k.keyword) => {
self.next_token();
true
}
_ => false,
}
}
#[must_use]
pub fn parse_keywords(&mut self, keywords: Vec<&'static str>) -> bool {
let index = self.index;
for keyword in keywords {
if !self.parse_keyword(&keyword) {
self.index = index;
return false;
}
}
true
}
#[must_use]
pub fn parse_one_of_keywords(&mut self, keywords: &[&'static str]) -> Option<&'static str> {
for keyword in keywords {
assert!(
keywords::ALL_KEYWORDS.contains(keyword),
"{} is not contained in keyword list",
keyword
);
}
match self.peek_token() {
Some(Token::Word(ref k)) => keywords
.iter()
.find(|keyword| keyword.eq_ignore_ascii_case(&k.keyword))
.map(|keyword| {
self.next_token();
*keyword
}),
_ => None,
}
}
#[must_use]
pub fn expect_one_of_keywords(
&mut self,
keywords: &[&'static str],
) -> Result<&'static str, ParserError> {
if let Some(keyword) = self.parse_one_of_keywords(keywords) {
Ok(keyword)
} else {
self.expected(
&format!("one of {}", keywords.join(" or ")),
self.peek_token(),
)
}
}
pub fn expect_keyword(&mut self, expected: &'static str) -> Result<(), ParserError> {
if self.parse_keyword(expected) {
Ok(())
} else {
self.expected(expected, self.peek_token())
}
}
pub fn expect_keywords(&mut self, expected: &[&'static str]) -> Result<(), ParserError> {
for kw in expected {
self.expect_keyword(kw)?;
}
Ok(())
}
#[must_use]
pub fn consume_token(&mut self, expected: &Token) -> bool {
match &self.peek_token() {
Some(t) if *t == *expected => {
self.next_token();
true
}
_ => false,
}
}
pub fn expect_token(&mut self, expected: &Token) -> Result<(), ParserError> {
if self.consume_token(expected) {
Ok(())
} else {
self.expected(&expected.to_string(), self.peek_token())
}
}
pub fn parse_comma_separated<T, F>(&mut self, mut f: F) -> Result<Vec<T>, ParserError>
where
F: FnMut(&mut Parser) -> Result<T, ParserError>,
{
let mut values = vec![];
loop {
values.push(f(self)?);
if !self.consume_token(&Token::Comma) {
break;
}
}
Ok(values)
}
pub fn parse_create(&mut self) -> Result<Statement, ParserError> {
if self.parse_keyword("TABLE") {
self.parse_create_table()
} else if self.parse_keyword("MATERIALIZED") || self.parse_keyword("VIEW") {
self.prev_token();
self.parse_create_view()
} else if self.parse_keyword("EXTERNAL") {
self.parse_create_external_table()
} else {
self.expected("TABLE or VIEW after CREATE", self.peek_token())
}
}
pub fn parse_create_external_table(&mut self) -> Result<Statement, ParserError> {
self.expect_keyword("TABLE")?;
let table_name = self.parse_object_name()?;
let (columns, constraints) = self.parse_columns()?;
self.expect_keywords(&["STORED", "AS"])?;
let file_format = self.parse_identifier()?.value.parse::<FileFormat>()?;
self.expect_keyword("LOCATION")?;
let location = self.parse_literal_string()?;
Ok(Statement::CreateTable {
name: table_name,
if_not_exists: false,
columns,
constraints,
with_options: vec![],
external: true,
file_format: Some(file_format),
location: Some(location),
})
}
pub fn parse_create_view(&mut self) -> Result<Statement, ParserError> {
let materialized = self.parse_keyword("MATERIALIZED");
self.expect_keyword("VIEW")?;
let name = self.parse_object_name()?;
let columns = self.parse_parenthesized_column_list(Optional)?;
let with_options = self.parse_with_options()?;
self.expect_keyword("AS")?;
let query = Box::new(self.parse_query()?);
Ok(Statement::CreateView {
name,
columns,
query,
materialized,
with_options,
})
}
pub fn parse_drop(&mut self) -> Result<Statement, ParserError> {
let object_type = if self.parse_keyword("TABLE") {
ObjectType::Table
} else if self.parse_keyword("VIEW") {
ObjectType::View
} else {
return self.expected("TABLE or VIEW after DROP", self.peek_token());
};
let if_exists = self.parse_keywords(vec!["IF", "EXISTS"]);
let names = self.parse_comma_separated(Parser::parse_object_name)?;
let cascade = self.parse_keyword("CASCADE");
let restrict = self.parse_keyword("RESTRICT");
if cascade && restrict {
return parser_err!("Cannot specify both CASCADE and RESTRICT in DROP");
}
Ok(Statement::Drop {
object_type,
if_exists,
names,
cascade,
})
}
pub fn parse_create_table(&mut self) -> Result<Statement, ParserError> {
let if_not_exists = self.parse_keywords(vec!["IF", "NOT", "EXISTS"]);
let table_name = self.parse_object_name()?;
let (columns, constraints) = self.parse_columns()?;
let with_options = self.parse_with_options()?;
Ok(Statement::CreateTable {
name: table_name,
if_not_exists,
columns,
constraints,
with_options,
external: false,
file_format: None,
location: None,
})
}
fn parse_column_def(&mut self) -> Result<ColumnDef, ParserError> {
if let Some(Token::Word(column_name)) = self.peek_token() {
self.next_token();
let data_type = self.parse_data_type()?;
let collation = if self.parse_keyword("COLLATE") {
Some(self.parse_object_name()?)
} else {
None
};
let mut options = vec![];
loop {
match self.peek_token() {
None | Some(Token::Comma) | Some(Token::RParen) => break,
_ => options.push(self.parse_column_option_def()?),
}
}
Ok(ColumnDef {
name: column_name.to_ident(),
data_type,
collation,
options,
})
} else {
self.expected("column name", self.peek_token())
}
}
fn parse_columns(&mut self) -> Result<(Vec<ColumnDef>, Vec<TableConstraint>), ParserError> {
let mut columns = vec![];
let mut constraints = vec![];
if !self.consume_token(&Token::LParen) || self.consume_token(&Token::RParen) {
return Ok((columns, constraints));
}
loop {
if let Some(constraint) = self.parse_optional_table_constraint()? {
constraints.push(constraint);
} else if let Some(Token::Word(_column_name)) = self.peek_token() {
columns.push(self.parse_column_def()?);
} else {
return self.expected("column name or constraint definition", self.peek_token());
}
let comma = self.consume_token(&Token::Comma);
if self.consume_token(&Token::RParen) {
break;
} else if !comma {
return self.expected("',' or ')' after column definition", self.peek_token());
}
}
Ok((columns, constraints))
}
pub fn parse_column_option_def(&mut self) -> Result<ColumnOptionDef, ParserError> {
let name = if self.parse_keyword("CONSTRAINT") {
Some(self.parse_identifier()?)
} else {
None
};
let option = if self.parse_keywords(vec!["NOT", "NULL"]) {
ColumnOption::NotNull
} else if self.parse_keyword("NULL") {
ColumnOption::Null
} else if self.parse_keyword("DEFAULT") {
ColumnOption::Default(self.parse_expr()?)
} else if self.parse_keywords(vec!["PRIMARY", "KEY"]) {
ColumnOption::Unique { is_primary: true }
} else if self.parse_keyword("UNIQUE") {
ColumnOption::Unique { is_primary: false }
} else if self.parse_keyword("REFERENCES") {
let foreign_table = self.parse_object_name()?;
let referred_columns = self.parse_parenthesized_column_list(Mandatory)?;
ColumnOption::ForeignKey {
foreign_table,
referred_columns,
}
} else if self.parse_keyword("CHECK") {
self.expect_token(&Token::LParen)?;
let expr = self.parse_expr()?;
self.expect_token(&Token::RParen)?;
ColumnOption::Check(expr)
} else {
return self.expected("column option", self.peek_token());
};
Ok(ColumnOptionDef { name, option })
}
pub fn parse_optional_table_constraint(
&mut self,
) -> Result<Option<TableConstraint>, ParserError> {
let name = if self.parse_keyword("CONSTRAINT") {
Some(self.parse_identifier()?)
} else {
None
};
match self.next_token() {
Some(Token::Word(ref k)) if k.keyword == "PRIMARY" || k.keyword == "UNIQUE" => {
let is_primary = k.keyword == "PRIMARY";
if is_primary {
self.expect_keyword("KEY")?;
}
let columns = self.parse_parenthesized_column_list(Mandatory)?;
Ok(Some(TableConstraint::Unique {
name,
columns,
is_primary,
}))
}
Some(Token::Word(ref k)) if k.keyword == "FOREIGN" => {
self.expect_keyword("KEY")?;
let columns = self.parse_parenthesized_column_list(Mandatory)?;
self.expect_keyword("REFERENCES")?;
let foreign_table = self.parse_object_name()?;
let referred_columns = self.parse_parenthesized_column_list(Mandatory)?;
Ok(Some(TableConstraint::ForeignKey {
name,
columns,
foreign_table,
referred_columns,
}))
}
Some(Token::Word(ref k)) if k.keyword == "CHECK" => {
self.expect_token(&Token::LParen)?;
let expr = Box::new(self.parse_expr()?);
self.expect_token(&Token::RParen)?;
Ok(Some(TableConstraint::Check { name, expr }))
}
unexpected => {
if name.is_some() {
self.expected("PRIMARY, UNIQUE, FOREIGN, or CHECK", unexpected)
} else {
self.prev_token();
Ok(None)
}
}
}
}
pub fn parse_with_options(&mut self) -> Result<Vec<SqlOption>, ParserError> {
if self.parse_keyword("WITH") {
self.expect_token(&Token::LParen)?;
let options = self.parse_comma_separated(Parser::parse_sql_option)?;
self.expect_token(&Token::RParen)?;
Ok(options)
} else {
Ok(vec![])
}
}
pub fn parse_sql_option(&mut self) -> Result<SqlOption, ParserError> {
let name = self.parse_identifier()?;
self.expect_token(&Token::Eq)?;
let value = self.parse_value()?;
Ok(SqlOption { name, value })
}
pub fn parse_alter(&mut self) -> Result<Statement, ParserError> {
self.expect_keyword("TABLE")?;
let _ = self.parse_keyword("ONLY");
let table_name = self.parse_object_name()?;
let operation = if self.parse_keyword("ADD") {
if self.parse_keyword("COLUMN") {
AlterTableOperation::AddColumn(self.parse_column_def()?)
} else if let Some(constraint) = self.parse_optional_table_constraint()? {
AlterTableOperation::AddConstraint(constraint)
} else {
return self.expected(
"a column or a constraint in ALTER TABLE .. ADD",
self.peek_token(),
);
}
} else if self.parse_keyword("DROP") {
if self.parse_keyword("COLUMN") {
let if_exists = if self.parse_keywords(vec!["IF", "EXISTS"]) {
true
} else {
false
};
let column = self.parse_identifier()?;
let cascade = if self.parse_keyword("CASCADE") {
true
} else {
false
};
AlterTableOperation::DropColumn {
column,
if_exists,
cascade,
}
} else {
return self.expected("a column in ALTER TABLE .. DROP", self.peek_token());
}
} else {
return self.expected("ADD or DROP after ALTER TABLE", self.peek_token());
};
Ok(Statement::AlterTable {
name: table_name,
operation,
})
}
pub fn parse_copy(&mut self) -> Result<Statement, ParserError> {
let table_name = self.parse_object_name()?;
let columns = self.parse_parenthesized_column_list(Optional)?;
self.expect_keywords(&["FROM", "STDIN"])?;
self.expect_token(&Token::SemiColon)?;
let values = self.parse_tsv()?;
Ok(Statement::Copy {
table_name,
columns,
values,
})
}
fn parse_tsv(&mut self) -> Result<Vec<Option<String>>, ParserError> {
let values = self.parse_tab_value()?;
Ok(values)
}
fn parse_tab_value(&mut self) -> Result<Vec<Option<String>>, ParserError> {
let mut values = vec![];
let mut content = String::from("");
while let Some(t) = self.next_token_no_skip() {
match t {
Token::Whitespace(Whitespace::Tab) => {
values.push(Some(content.to_string()));
content.clear();
}
Token::Whitespace(Whitespace::Newline) => {
values.push(Some(content.to_string()));
content.clear();
}
Token::Backslash => {
if self.consume_token(&Token::Period) {
return Ok(values);
}
if let Some(token) = self.next_token() {
if let Token::Word(Word { value: v, .. }) = token {
if v == "N" {
values.push(None);
}
}
} else {
continue;
}
}
_ => {
content.push_str(&t.to_string());
}
}
}
Ok(values)
}
fn parse_value(&mut self) -> Result<Value, ParserError> {
match self.next_token() {
Some(t) => match t {
Token::Word(k) => match k.keyword.as_ref() {
"TRUE" => Ok(Value::Boolean(true)),
"FALSE" => Ok(Value::Boolean(false)),
"NULL" => Ok(Value::Null),
_ => {
return parser_err!(format!("No value parser for keyword {}", k.keyword));
}
},
Token::Number(ref n) => match n.parse() {
Ok(n) => Ok(Value::Number(n)),
Err(e) => parser_err!(format!("Could not parse '{}' as number: {}", n, e)),
},
Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())),
Token::NationalStringLiteral(ref s) => {
Ok(Value::NationalStringLiteral(s.to_string()))
}
Token::HexStringLiteral(ref s) => Ok(Value::HexStringLiteral(s.to_string())),
_ => parser_err!(format!("Unsupported value: {:?}", t)),
},
None => parser_err!("Expecting a value, but found EOF"),
}
}
pub fn parse_number_value(&mut self) -> Result<Value, ParserError> {
match self.parse_value()? {
v @ Value::Number(_) => Ok(v),
_ => {
self.prev_token();
self.expected("literal number", self.peek_token())
}
}
}
pub fn parse_literal_uint(&mut self) -> Result<u64, ParserError> {
match self.next_token() {
Some(Token::Number(s)) => s.parse::<u64>().map_err(|e| {
ParserError::ParserError(format!("Could not parse '{}' as u64: {}", s, e))
}),
other => self.expected("literal int", other),
}
}
pub fn parse_literal_string(&mut self) -> Result<String, ParserError> {
match self.next_token() {
Some(Token::SingleQuotedString(ref s)) => Ok(s.clone()),
other => self.expected("literal string", other),
}
}
pub fn parse_data_type(&mut self) -> Result<DataType, ParserError> {
match self.next_token() {
Some(Token::Word(k)) => match k.keyword.as_ref() {
"BOOLEAN" => Ok(DataType::Boolean),
"FLOAT" => Ok(DataType::Float(self.parse_optional_precision()?)),
"REAL" => Ok(DataType::Real),
"DOUBLE" => {
let _ = self.parse_keyword("PRECISION");
Ok(DataType::Double)
}
"SMALLINT" => Ok(DataType::SmallInt),
"INT" | "INTEGER" => Ok(DataType::Int),
"BIGINT" => Ok(DataType::BigInt),
"VARCHAR" => Ok(DataType::Varchar(self.parse_optional_precision()?)),
"CHAR" | "CHARACTER" => {
if self.parse_keyword("VARYING") {
Ok(DataType::Varchar(self.parse_optional_precision()?))
} else {
Ok(DataType::Char(self.parse_optional_precision()?))
}
}
"UUID" => Ok(DataType::Uuid),
"DATE" => Ok(DataType::Date),
"TIMESTAMP" => {
if self.parse_keyword("WITH") || self.parse_keyword("WITHOUT") {
self.expect_keywords(&["TIME", "ZONE"])?;
}
Ok(DataType::Timestamp)
}
"TIME" => {
if self.parse_keyword("WITH") || self.parse_keyword("WITHOUT") {
self.expect_keywords(&["TIME", "ZONE"])?;
}
Ok(DataType::Time)
}
"INTERVAL" => Ok(DataType::Interval),
"REGCLASS" => Ok(DataType::Regclass),
"TEXT" => {
if self.consume_token(&Token::LBracket) {
self.expect_token(&Token::RBracket)?;
Ok(DataType::Array(Box::new(DataType::Text)))
} else {
Ok(DataType::Text)
}
}
"BYTEA" => Ok(DataType::Bytea),
"NUMERIC" | "DECIMAL" | "DEC" => {
let (precision, scale) = self.parse_optional_precision_scale()?;
Ok(DataType::Decimal(precision, scale))
}
_ => {
self.prev_token();
let type_name = self.parse_object_name()?;
Ok(DataType::Custom(type_name))
}
},
other => self.expected("a data type name", other),
}
}
pub fn parse_optional_alias(
&mut self,
reserved_kwds: &[&str],
) -> Result<Option<Ident>, ParserError> {
let after_as = self.parse_keyword("AS");
match self.next_token() {
Some(Token::Word(ref w))
if after_as || !reserved_kwds.contains(&w.keyword.as_str()) =>
{
Ok(Some(w.to_ident()))
}
Some(Token::SingleQuotedString(ref s)) => Ok(Some(Ident::with_quote('\'', s.clone()))),
not_an_ident => {
if after_as {
return self.expected("an identifier after AS", not_an_ident);
}
self.prev_token();
Ok(None)
}
}
}
pub fn parse_optional_table_alias(
&mut self,
reserved_kwds: &[&str],
) -> Result<Option<TableAlias>, ParserError> {
match self.parse_optional_alias(reserved_kwds)? {
Some(name) => {
let columns = self.parse_parenthesized_column_list(Optional)?;
Ok(Some(TableAlias { name, columns }))
}
None => Ok(None),
}
}
pub fn parse_object_name(&mut self) -> Result<ObjectName, ParserError> {
let mut idents = vec![];
loop {
idents.push(self.parse_identifier()?);
if !self.consume_token(&Token::Period) {
break;
}
}
Ok(ObjectName(idents))
}
pub fn parse_identifier(&mut self) -> Result<Ident, ParserError> {
match self.next_token() {
Some(Token::Word(w)) => Ok(w.to_ident()),
unexpected => self.expected("identifier", unexpected),
}
}
pub fn parse_parenthesized_column_list(
&mut self,
optional: IsOptional,
) -> Result<Vec<Ident>, ParserError> {
if self.consume_token(&Token::LParen) {
let cols = self.parse_comma_separated(Parser::parse_identifier)?;
self.expect_token(&Token::RParen)?;
Ok(cols)
} else if optional == Optional {
Ok(vec![])
} else {
self.expected("a list of columns in parentheses", self.peek_token())
}
}
pub fn parse_optional_precision(&mut self) -> Result<Option<u64>, ParserError> {
if self.consume_token(&Token::LParen) {
let n = self.parse_literal_uint()?;
self.expect_token(&Token::RParen)?;
Ok(Some(n))
} else {
Ok(None)
}
}
pub fn parse_optional_precision_scale(
&mut self,
) -> Result<(Option<u64>, Option<u64>), ParserError> {
if self.consume_token(&Token::LParen) {
let n = self.parse_literal_uint()?;
let scale = if self.consume_token(&Token::Comma) {
Some(self.parse_literal_uint()?)
} else {
None
};
self.expect_token(&Token::RParen)?;
Ok((Some(n), scale))
} else {
Ok((None, None))
}
}
pub fn parse_delete(&mut self) -> Result<Statement, ParserError> {
self.expect_keyword("FROM")?;
let table_name = self.parse_object_name()?;
let selection = if self.parse_keyword("WHERE") {
Some(self.parse_expr()?)
} else {
None
};
Ok(Statement::Delete {
table_name,
selection,
})
}
pub fn parse_query(&mut self) -> Result<Query, ParserError> {
let ctes = if self.parse_keyword("WITH") {
self.parse_comma_separated(Parser::parse_cte)?
} else {
vec![]
};
let body = self.parse_query_body(0)?;
let order_by = if self.parse_keywords(vec!["ORDER", "BY"]) {
self.parse_comma_separated(Parser::parse_order_by_expr)?
} else {
vec![]
};
let limit = if self.parse_keyword("LIMIT") {
self.parse_limit()?
} else {
None
};
let offset = if self.parse_keyword("OFFSET") {
Some(self.parse_offset()?)
} else {
None
};
let fetch = if self.parse_keyword("FETCH") {
Some(self.parse_fetch()?)
} else {
None
};
Ok(Query {
ctes,
body,
limit,
order_by,
offset,
fetch,
})
}
fn parse_cte(&mut self) -> Result<Cte, ParserError> {
let alias = TableAlias {
name: self.parse_identifier()?,
columns: self.parse_parenthesized_column_list(Optional)?,
};
self.expect_keyword("AS")?;
self.expect_token(&Token::LParen)?;
let query = self.parse_query()?;
self.expect_token(&Token::RParen)?;
Ok(Cte { alias, query })
}
fn parse_query_body(&mut self, precedence: u8) -> Result<SetExpr, ParserError> {
let mut expr = if self.parse_keyword("SELECT") {
SetExpr::Select(Box::new(self.parse_select()?))
} else if self.consume_token(&Token::LParen) {
let subquery = self.parse_query()?;
self.expect_token(&Token::RParen)?;
SetExpr::Query(Box::new(subquery))
} else if self.parse_keyword("VALUES") {
SetExpr::Values(self.parse_values()?)
} else {
return self.expected(
"SELECT, VALUES, or a subquery in the query body",
self.peek_token(),
);
};
loop {
let next_token = self.peek_token();
let op = self.parse_set_operator(&next_token);
let next_precedence = match op {
Some(SetOperator::Union) | Some(SetOperator::Except) => 10,
Some(SetOperator::Intersect) => 20,
None => break,
};
if precedence >= next_precedence {
break;
}
self.next_token();
expr = SetExpr::SetOperation {
left: Box::new(expr),
op: op.unwrap(),
all: self.parse_keyword("ALL"),
right: Box::new(self.parse_query_body(next_precedence)?),
};
}
Ok(expr)
}
fn parse_set_operator(&mut self, token: &Option<Token>) -> Option<SetOperator> {
match token {
Some(Token::Word(w)) if w.keyword == "UNION" => Some(SetOperator::Union),
Some(Token::Word(w)) if w.keyword == "EXCEPT" => Some(SetOperator::Except),
Some(Token::Word(w)) if w.keyword == "INTERSECT" => Some(SetOperator::Intersect),
_ => None,
}
}
pub fn parse_select(&mut self) -> Result<Select, ParserError> {
let all = self.parse_keyword("ALL");
let distinct = self.parse_keyword("DISTINCT");
if all && distinct {
return parser_err!("Cannot specify both ALL and DISTINCT in SELECT");
}
let projection = self.parse_comma_separated(Parser::parse_select_item)?;
let from = if self.parse_keyword("FROM") {
self.parse_comma_separated(Parser::parse_table_and_joins)?
} else {
vec![]
};
let selection = if self.parse_keyword("WHERE") {
Some(self.parse_expr()?)
} else {
None
};
let group_by = if self.parse_keywords(vec!["GROUP", "BY"]) {
self.parse_comma_separated(Parser::parse_expr)?
} else {
vec![]
};
let having = if self.parse_keyword("HAVING") {
Some(self.parse_expr()?)
} else {
None
};
Ok(Select {
distinct,
projection,
from,
selection,
group_by,
having,
})
}
pub fn parse_set(&mut self) -> Result<Statement, ParserError> {
let modifier = self.parse_one_of_keywords(&["SESSION", "LOCAL"]);
let variable = self.parse_identifier()?;
if self.consume_token(&Token::Eq) || self.parse_keyword("TO") {
let token = self.peek_token();
let value = match (self.parse_value(), token) {
(Ok(value), _) => SetVariableValue::Literal(value),
(Err(_), Some(Token::Word(ident))) => SetVariableValue::Ident(ident.to_ident()),
(Err(_), other) => self.expected("variable value", other)?,
};
Ok(Statement::SetVariable {
local: modifier == Some("LOCAL"),
variable,
value,
})
} else if variable.value == "TRANSACTION" && modifier.is_none() {
Ok(Statement::SetTransaction {
modes: self.parse_transaction_modes()?,
})
} else {
self.expected("equals sign or TO", self.peek_token())
}
}
pub fn parse_show(&mut self) -> Result<Statement, ParserError> {
if self
.parse_one_of_keywords(&["EXTENDED", "FULL", "COLUMNS", "FIELDS"])
.is_some()
{
self.prev_token();
self.parse_show_columns()
} else {
Ok(Statement::ShowVariable {
variable: self.parse_identifier()?,
})
}
}
fn parse_show_columns(&mut self) -> Result<Statement, ParserError> {
let extended = self.parse_keyword("EXTENDED");
let full = self.parse_keyword("FULL");
self.expect_one_of_keywords(&["COLUMNS", "FIELDS"])?;
self.expect_one_of_keywords(&["FROM", "IN"])?;
let table_name = self.parse_object_name()?;
let filter = self.parse_show_statement_filter()?;
Ok(Statement::ShowColumns {
extended,
full,
table_name,
filter,
})
}
fn parse_show_statement_filter(&mut self) -> Result<Option<ShowStatementFilter>, ParserError> {
if self.parse_keyword("LIKE") {
Ok(Some(ShowStatementFilter::Like(
self.parse_literal_string()?,
)))
} else if self.parse_keyword("WHERE") {
Ok(Some(ShowStatementFilter::Where(self.parse_expr()?)))
} else {
Ok(None)
}
}
pub fn parse_table_and_joins(&mut self) -> Result<TableWithJoins, ParserError> {
let relation = self.parse_table_factor()?;
let mut joins = vec![];
loop {
let join = if self.parse_keyword("CROSS") {
let join_operator = if self.parse_keyword("JOIN") {
JoinOperator::CrossJoin
} else if self.parse_keyword("APPLY") {
JoinOperator::CrossApply
} else {
return self.expected("JOIN or APPLY after CROSS", self.peek_token());
};
Join {
relation: self.parse_table_factor()?,
join_operator,
}
} else if self.parse_keyword("OUTER") {
self.expect_keyword("APPLY")?;
Join {
relation: self.parse_table_factor()?,
join_operator: JoinOperator::OuterApply,
}
} else {
let natural = self.parse_keyword("NATURAL");
let peek_keyword = if let Some(Token::Word(kw)) = self.peek_token() {
kw.keyword
} else {
String::default()
};
let join_operator_type = match peek_keyword.as_ref() {
"INNER" | "JOIN" => {
let _ = self.parse_keyword("INNER");
self.expect_keyword("JOIN")?;
JoinOperator::Inner
}
kw @ "LEFT" | kw @ "RIGHT" | kw @ "FULL" => {
let _ = self.next_token();
let _ = self.parse_keyword("OUTER");
self.expect_keyword("JOIN")?;
match kw {
"LEFT" => JoinOperator::LeftOuter,
"RIGHT" => JoinOperator::RightOuter,
"FULL" => JoinOperator::FullOuter,
_ => unreachable!(),
}
}
"OUTER" => return self.expected("LEFT, RIGHT, or FULL", self.peek_token()),
_ if natural => {
return self.expected("a join type after NATURAL", self.peek_token());
}
_ => break,
};
let relation = self.parse_table_factor()?;
let join_constraint = self.parse_join_constraint(natural)?;
Join {
relation,
join_operator: join_operator_type(join_constraint),
}
};
joins.push(join);
}
Ok(TableWithJoins { relation, joins })
}
pub fn parse_table_factor(&mut self) -> Result<TableFactor, ParserError> {
if self.parse_keyword("LATERAL") {
if !self.consume_token(&Token::LParen) {
self.expected("subquery after LATERAL", self.peek_token())?;
}
return self.parse_derived_table_factor(Lateral);
}
if self.consume_token(&Token::LParen) {
let index = self.index;
match self.parse_derived_table_factor(NotLateral) {
Ok(table_factor) => Ok(table_factor),
Err(_) => {
self.index = index;
let table_and_joins = self.parse_table_and_joins()?;
match table_and_joins.relation {
TableFactor::NestedJoin { .. } => (),
_ => {
if table_and_joins.joins.is_empty() {
self.expected("joined table", self.peek_token())?
}
}
}
self.expect_token(&Token::RParen)?;
Ok(TableFactor::NestedJoin(Box::new(table_and_joins)))
}
}
} else {
let name = self.parse_object_name()?;
let args = if self.consume_token(&Token::LParen) {
self.parse_optional_args()?
} else {
vec![]
};
let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?;
let mut with_hints = vec![];
if self.parse_keyword("WITH") {
if self.consume_token(&Token::LParen) {
with_hints = self.parse_comma_separated(Parser::parse_expr)?;
self.expect_token(&Token::RParen)?;
} else {
self.prev_token();
}
};
Ok(TableFactor::Table {
name,
alias,
args,
with_hints,
})
}
}
pub fn parse_derived_table_factor(
&mut self,
lateral: IsLateral,
) -> Result<TableFactor, ParserError> {
let subquery = Box::new(self.parse_query()?);
self.expect_token(&Token::RParen)?;
let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?;
Ok(TableFactor::Derived {
lateral: match lateral {
Lateral => true,
NotLateral => false,
},
subquery,
alias,
})
}
fn parse_join_constraint(&mut self, natural: bool) -> Result<JoinConstraint, ParserError> {
if natural {
Ok(JoinConstraint::Natural)
} else if self.parse_keyword("ON") {
let constraint = self.parse_expr()?;
Ok(JoinConstraint::On(constraint))
} else if self.parse_keyword("USING") {
let columns = self.parse_parenthesized_column_list(Mandatory)?;
Ok(JoinConstraint::Using(columns))
} else {
self.expected("ON, or USING after JOIN", self.peek_token())
}
}
pub fn parse_insert(&mut self) -> Result<Statement, ParserError> {
self.expect_keyword("INTO")?;
let table_name = self.parse_object_name()?;
let columns = self.parse_parenthesized_column_list(Optional)?;
let source = Box::new(self.parse_query()?);
Ok(Statement::Insert {
table_name,
columns,
source,
})
}
pub fn parse_update(&mut self) -> Result<Statement, ParserError> {
let table_name = self.parse_object_name()?;
self.expect_keyword("SET")?;
let assignments = self.parse_comma_separated(Parser::parse_assignment)?;
let selection = if self.parse_keyword("WHERE") {
Some(self.parse_expr()?)
} else {
None
};
Ok(Statement::Update {
table_name,
assignments,
selection,
})
}
pub fn parse_assignment(&mut self) -> Result<Assignment, ParserError> {
let id = self.parse_identifier()?;
self.expect_token(&Token::Eq)?;
let value = self.parse_expr()?;
Ok(Assignment { id, value })
}
pub fn parse_optional_args(&mut self) -> Result<Vec<Expr>, ParserError> {
if self.consume_token(&Token::RParen) {
Ok(vec![])
} else {
let args = self.parse_comma_separated(Parser::parse_expr)?;
self.expect_token(&Token::RParen)?;
Ok(args)
}
}
pub fn parse_select_item(&mut self) -> Result<SelectItem, ParserError> {
let expr = self.parse_expr()?;
if let Expr::Wildcard = expr {
Ok(SelectItem::Wildcard)
} else if let Expr::QualifiedWildcard(prefix) = expr {
Ok(SelectItem::QualifiedWildcard(ObjectName(prefix)))
} else {
if let Some(alias) = self.parse_optional_alias(keywords::RESERVED_FOR_COLUMN_ALIAS)? {
Ok(SelectItem::ExprWithAlias { expr, alias })
} else {
Ok(SelectItem::UnnamedExpr(expr))
}
}
}
pub fn parse_order_by_expr(&mut self) -> Result<OrderByExpr, ParserError> {
let expr = self.parse_expr()?;
let asc = if self.parse_keyword("ASC") {
Some(true)
} else if self.parse_keyword("DESC") {
Some(false)
} else {
None
};
Ok(OrderByExpr { expr, asc })
}
pub fn parse_limit(&mut self) -> Result<Option<Expr>, ParserError> {
if self.parse_keyword("ALL") {
Ok(None)
} else {
Ok(Some(Expr::Value(self.parse_number_value()?)))
}
}
pub fn parse_offset(&mut self) -> Result<Expr, ParserError> {
let value = Expr::Value(self.parse_number_value()?);
self.expect_one_of_keywords(&["ROW", "ROWS"])?;
Ok(value)
}
pub fn parse_fetch(&mut self) -> Result<Fetch, ParserError> {
self.expect_one_of_keywords(&["FIRST", "NEXT"])?;
let (quantity, percent) = if self.parse_one_of_keywords(&["ROW", "ROWS"]).is_some() {
(None, false)
} else {
let quantity = Expr::Value(self.parse_value()?);
let percent = self.parse_keyword("PERCENT");
self.expect_one_of_keywords(&["ROW", "ROWS"])?;
(Some(quantity), percent)
};
let with_ties = if self.parse_keyword("ONLY") {
false
} else if self.parse_keywords(vec!["WITH", "TIES"]) {
true
} else {
return self.expected("one of ONLY or WITH TIES", self.peek_token());
};
Ok(Fetch {
with_ties,
percent,
quantity,
})
}
pub fn parse_values(&mut self) -> Result<Values, ParserError> {
let values = self.parse_comma_separated(|parser| {
parser.expect_token(&Token::LParen)?;
let exprs = parser.parse_comma_separated(Parser::parse_expr)?;
parser.expect_token(&Token::RParen)?;
Ok(exprs)
})?;
Ok(Values(values))
}
pub fn parse_start_transaction(&mut self) -> Result<Statement, ParserError> {
self.expect_keyword("TRANSACTION")?;
Ok(Statement::StartTransaction {
modes: self.parse_transaction_modes()?,
})
}
pub fn parse_begin(&mut self) -> Result<Statement, ParserError> {
let _ = self.parse_one_of_keywords(&["TRANSACTION", "WORK"]);
Ok(Statement::StartTransaction {
modes: self.parse_transaction_modes()?,
})
}
pub fn parse_transaction_modes(&mut self) -> Result<Vec<TransactionMode>, ParserError> {
let mut modes = vec![];
let mut required = false;
loop {
let mode = if self.parse_keywords(vec!["ISOLATION", "LEVEL"]) {
let iso_level = if self.parse_keywords(vec!["READ", "UNCOMMITTED"]) {
TransactionIsolationLevel::ReadUncommitted
} else if self.parse_keywords(vec!["READ", "COMMITTED"]) {
TransactionIsolationLevel::ReadCommitted
} else if self.parse_keywords(vec!["REPEATABLE", "READ"]) {
TransactionIsolationLevel::RepeatableRead
} else if self.parse_keyword("SERIALIZABLE") {
TransactionIsolationLevel::Serializable
} else {
self.expected("isolation level", self.peek_token())?
};
TransactionMode::IsolationLevel(iso_level)
} else if self.parse_keywords(vec!["READ", "ONLY"]) {
TransactionMode::AccessMode(TransactionAccessMode::ReadOnly)
} else if self.parse_keywords(vec!["READ", "WRITE"]) {
TransactionMode::AccessMode(TransactionAccessMode::ReadWrite)
} else if required {
self.expected("transaction mode", self.peek_token())?
} else {
break;
};
modes.push(mode);
required = self.consume_token(&Token::Comma);
}
Ok(modes)
}
pub fn parse_commit(&mut self) -> Result<Statement, ParserError> {
Ok(Statement::Commit {
chain: self.parse_commit_rollback_chain()?,
})
}
pub fn parse_rollback(&mut self) -> Result<Statement, ParserError> {
Ok(Statement::Rollback {
chain: self.parse_commit_rollback_chain()?,
})
}
pub fn parse_commit_rollback_chain(&mut self) -> Result<bool, ParserError> {
let _ = self.parse_one_of_keywords(&["TRANSACTION", "WORK"]);
if self.parse_keyword("AND") {
let chain = !self.parse_keyword("NO");
self.expect_keyword("CHAIN")?;
Ok(chain)
} else {
Ok(false)
}
}
}
impl Word {
pub fn to_ident(&self) -> Ident {
Ident {
value: self.value.clone(),
quote_style: self.quote_style,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::all_dialects;
#[test]
fn test_prev_index() {
let sql = "SELECT version";
all_dialects().run_parser_method(sql, |parser| {
assert_eq!(parser.peek_token(), Some(Token::make_keyword("SELECT")));
assert_eq!(parser.next_token(), Some(Token::make_keyword("SELECT")));
parser.prev_token();
assert_eq!(parser.next_token(), Some(Token::make_keyword("SELECT")));
assert_eq!(parser.next_token(), Some(Token::make_word("version", None)));
parser.prev_token();
assert_eq!(parser.peek_token(), Some(Token::make_word("version", None)));
assert_eq!(parser.next_token(), Some(Token::make_word("version", None)));
assert_eq!(parser.peek_token(), None);
parser.prev_token();
assert_eq!(parser.next_token(), Some(Token::make_word("version", None)));
assert_eq!(parser.next_token(), None);
assert_eq!(parser.next_token(), None);
parser.prev_token();
});
}
}