Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 28 additions & 26 deletions src/dialect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -756,17 +756,17 @@ pub trait Dialect: Debug + Any {
};
}

let token = parser.peek_token();
let token = parser.peek_token_ref();
debug!("get_next_precedence_full() {token:?}");
match token.token {
match &token.token {
Token::Word(w) if w.keyword == Keyword::OR => Ok(p!(Or)),
Token::Word(w) if w.keyword == Keyword::AND => Ok(p!(And)),
Token::Word(w) if w.keyword == Keyword::XOR => Ok(p!(Xor)),

Token::Word(w) if w.keyword == Keyword::AT => {
match (
parser.peek_nth_token(1).token,
parser.peek_nth_token(2).token,
&parser.peek_nth_token_ref(1).token,
&parser.peek_nth_token_ref(2).token,
) {
(Token::Word(w), Token::Word(w2))
if w.keyword == Keyword::TIME && w2.keyword == Keyword::ZONE =>
Expand All @@ -777,28 +777,30 @@ pub trait Dialect: Debug + Any {
}
}

Token::Word(w) if w.keyword == Keyword::NOT => match parser.peek_nth_token(1).token {
// The precedence of NOT varies depending on keyword that
// follows it. If it is followed by IN, BETWEEN, or LIKE,
// it takes on the precedence of those tokens. Otherwise, it
// is not an infix operator, and therefore has zero
// precedence.
Token::Word(w) if w.keyword == Keyword::IN => Ok(p!(Between)),
Token::Word(w) if w.keyword == Keyword::BETWEEN => Ok(p!(Between)),
Token::Word(w) if w.keyword == Keyword::LIKE => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::MATCH => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::MEMBER => Ok(p!(Like)),
Token::Word(w)
if w.keyword == Keyword::NULL && !parser.in_column_definition_state() =>
{
Ok(p!(Is))
Token::Word(w) if w.keyword == Keyword::NOT => {
match &parser.peek_nth_token_ref(1).token {
// The precedence of NOT varies depending on keyword that
// follows it. If it is followed by IN, BETWEEN, or LIKE,
// it takes on the precedence of those tokens. Otherwise, it
// is not an infix operator, and therefore has zero
// precedence.
Token::Word(w) if w.keyword == Keyword::IN => Ok(p!(Between)),
Token::Word(w) if w.keyword == Keyword::BETWEEN => Ok(p!(Between)),
Token::Word(w) if w.keyword == Keyword::LIKE => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::MATCH => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(p!(Like)),
Token::Word(w) if w.keyword == Keyword::MEMBER => Ok(p!(Like)),
Token::Word(w)
if w.keyword == Keyword::NULL && !parser.in_column_definition_state() =>
{
Ok(p!(Is))
}
_ => Ok(self.prec_unknown()),
}
_ => Ok(self.prec_unknown()),
},
}
Token::Word(w) if w.keyword == Keyword::NOTNULL && self.supports_notnull_operator() => {
Ok(p!(Is))
}
Expand Down Expand Up @@ -861,7 +863,7 @@ pub trait Dialect: Debug + Any {
Token::DoubleColon | Token::ExclamationMark | Token::LBracket | Token::CaretAt => {
Ok(p!(DoubleColon))
}
Token::Colon => match parser.peek_nth_token(1).token {
Token::Colon => match &parser.peek_nth_token_ref(1).token {
// When colon is followed by a string or a number, it's usually in MAP syntax.
Token::SingleQuotedString(_) | Token::Number(_, _) => Ok(self.prec_unknown()),
// In other cases, it's used in semi-structured data traversal like in variant or JSON
Expand Down
6 changes: 3 additions & 3 deletions src/dialect/mssql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl Dialect for MsSqlDialect {
.is_some()
|| matches!(p.peek_token_ref().token, Token::SemiColon | Token::EOF)
{
p.expected("statement", p.peek_token())
p.expected_ref("statement", p.peek_token_ref())
} else {
Ok(())
}
Expand Down Expand Up @@ -189,8 +189,8 @@ impl Dialect for MsSqlDialect {
}

fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
let token = parser.peek_token();
match token.token {
let token = parser.peek_token_ref();
match &token.token {
// lowest prec to prevent it from turning into a binary op
Token::Colon => Some(Ok(self.prec_unknown())),
_ => None,
Expand Down
2 changes: 1 addition & 1 deletion src/dialect/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ fn parse_lock_tables_type(parser: &mut Parser) -> Result<LockTableType, ParserEr
} else if parser.parse_keywords(&[Keyword::LOW_PRIORITY, Keyword::WRITE]) {
Ok(LockTableType::Write { low_priority: true })
} else {
parser.expected("an lock type in LOCK TABLES", parser.peek_token())
parser.expected_ref("an lock type in LOCK TABLES", parser.peek_token_ref())
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/dialect/oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ impl Dialect for OracleDialect {
}

fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
let t = parser.peek_token();
let t = parser.peek_token_ref();
debug!("get_next_precedence() {t:?}");

match t.token {
match &t.token {
Token::StringConcat => Some(Ok(self.prec_value(Precedence::PlusMinus))),
_ => None,
}
Expand Down
4 changes: 2 additions & 2 deletions src/dialect/postgresql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@ impl Dialect for PostgreSqlDialect {
}

fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
let token = parser.peek_token();
let token = parser.peek_token_ref();
debug!("get_next_precedence() {token:?}");

// we only return some custom value here when the behaviour (not merely the numeric value) differs
// from the default implementation
match token.token {
match &token.token {
Token::Word(w)
if w.keyword == Keyword::COLLATE && !parser.in_column_definition_state() =>
{
Expand Down
40 changes: 23 additions & 17 deletions src/dialect/snowflake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ impl Dialect for SnowflakeDialect {
let set = match parser.parse_one_of_keywords(&[Keyword::SET, Keyword::UNSET]) {
Some(Keyword::SET) => true,
Some(Keyword::UNSET) => false,
_ => return Some(parser.expected("SET or UNSET", parser.peek_token())),
_ => return Some(parser.expected_ref("SET or UNSET", parser.peek_token_ref())),
};
return Some(parse_alter_session(parser, set));
}
Expand Down Expand Up @@ -417,9 +417,9 @@ impl Dialect for SnowflakeDialect {
}

fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
let token = parser.peek_token();
let token = parser.peek_token_ref();
// Snowflake supports the `:` cast operator unlike other dialects
match token.token {
match &token.token {
Token::Colon => Some(Ok(self.prec_value(Precedence::DoubleColon))),
_ => None,
}
Expand Down Expand Up @@ -715,9 +715,9 @@ fn parse_alter_dynamic_table(parser: &mut Parser) -> Result<Statement, ParserErr
} else if parser.parse_keyword(Keyword::RESUME) {
AlterTableOperation::Resume
} else {
return parser.expected(
return parser.expected_ref(
"REFRESH, SUSPEND, or RESUME after ALTER DYNAMIC TABLE",
parser.peek_token(),
parser.peek_token_ref(),
);
};

Expand Down Expand Up @@ -757,7 +757,10 @@ fn parse_alter_external_table(parser: &mut Parser) -> Result<Statement, ParserEr
};
AlterTableOperation::Refresh { subpath }
} else {
return parser.expected("REFRESH after ALTER EXTERNAL TABLE", parser.peek_token());
return parser.expected_ref(
"REFRESH after ALTER EXTERNAL TABLE",
parser.peek_token_ref(),
);
};

let end_token = if parser.peek_token_ref().token == Token::SemiColon {
Expand Down Expand Up @@ -1242,7 +1245,7 @@ pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result<Ident, ParserE
Token::Minus => ident.push('-'),
Token::Number(n, _) => ident.push_str(n),
Token::Word(w) => ident.push_str(&w.to_string()),
_ => return parser.expected("stage name identifier", parser.peek_token()),
_ => return parser.expected_ref("stage name identifier", parser.peek_token_ref()),
}
}
Ok(Ident::new(ident))
Expand Down Expand Up @@ -1273,7 +1276,7 @@ pub fn parse_snowflake_stage_name(parser: &mut Parser) -> Result<ObjectName, Par
/// Parses a `COPY INTO` statement. Snowflake has two variants, `COPY INTO <table>`
/// and `COPY INTO <location>` which have different syntax.
pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
let kind = match parser.peek_token().token {
let kind = match &parser.peek_token_ref().token {
// Indicates an internal stage
Token::AtSign => CopyIntoSnowflakeKind::Location,
// Indicates an external stage, i.e. s3://, gcs:// or azure://
Expand Down Expand Up @@ -1346,7 +1349,7 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
from_stage_alias = if parser.parse_keyword(Keyword::AS) {
Some(match parser.next_token().token {
Token::Word(w) => Ok(Ident::new(w.value)),
_ => parser.expected("stage alias", parser.peek_token()),
_ => parser.expected_ref("stage alias", parser.peek_token_ref()),
}?)
} else {
None
Expand Down Expand Up @@ -1404,7 +1407,10 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
// In `COPY INTO <location>` the copy options do not have a shared key
// like in `COPY INTO <table>`
Token::Word(key) => copy_options.push(parser.parse_key_value_option(&key)?),
_ => return parser.expected("another copy option, ; or EOF'", parser.peek_token()),
_ => {
return parser
.expected_ref("another copy option, ; or EOF'", parser.peek_token_ref())
}
}
}
}
Expand Down Expand Up @@ -1499,7 +1505,7 @@ fn parse_select_item_for_data_load(
// parse element
element = Some(Ident::new(match parser.next_token().token {
Token::Word(w) => Ok(w.value),
_ => parser.expected("file_col_num", parser.peek_token()),
_ => parser.expected_ref("file_col_num", parser.peek_token_ref()),
}?));
}
_ => {
Expand All @@ -1512,7 +1518,7 @@ fn parse_select_item_for_data_load(
if parser.parse_keyword(Keyword::AS) {
item_as = Some(match parser.next_token().token {
Token::Word(w) => Ok(Ident::new(w.value)),
_ => parser.expected("column item alias", parser.peek_token()),
_ => parser.expected_ref("column item alias", parser.peek_token_ref()),
}?);
}

Expand Down Expand Up @@ -1540,7 +1546,7 @@ fn parse_stage_params(parser: &mut Parser) -> Result<StageParamsObject, ParserEr
parser.expect_token(&Token::Eq)?;
url = Some(match parser.next_token().token {
Token::SingleQuotedString(word) => Ok(word),
_ => parser.expected("a URL statement", parser.peek_token()),
_ => parser.expected_ref("a URL statement", parser.peek_token_ref()),
}?)
}

Expand All @@ -1555,7 +1561,7 @@ fn parse_stage_params(parser: &mut Parser) -> Result<StageParamsObject, ParserEr
parser.expect_token(&Token::Eq)?;
endpoint = Some(match parser.next_token().token {
Token::SingleQuotedString(word) => Ok(word),
_ => parser.expected("an endpoint statement", parser.peek_token()),
_ => parser.expected_ref("an endpoint statement", parser.peek_token_ref()),
}?)
}

Expand Down Expand Up @@ -1795,7 +1801,7 @@ fn parse_multi_table_insert_into_clauses(
into_clauses.push(parse_multi_table_insert_into_clause(parser)?);
}
if into_clauses.is_empty() {
return parser.expected("INTO clause in multi-table INSERT", parser.peek_token());
return parser.expected_ref("INTO clause in multi-table INSERT", parser.peek_token_ref());
}
Ok(into_clauses)
}
Expand Down Expand Up @@ -1874,9 +1880,9 @@ fn parse_multi_table_insert_when_clauses(
}

if when_clauses.is_empty() {
return parser.expected(
return parser.expected_ref(
"at least one WHEN clause in conditional multi-table INSERT",
parser.peek_token(),
parser.peek_token_ref(),
);
}

Expand Down
20 changes: 10 additions & 10 deletions src/parser/alter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,9 @@ impl Parser<'_> {
} else if self.parse_keyword(Keyword::AUTHORIZATIONS) {
None
} else {
return self.expected(
return self.expected_ref(
"REMOVE DELEGATED AUTHORIZATION OF ROLE | REMOVE DELEGATED AUTHORIZATIONS",
self.peek_token(),
self.peek_token_ref(),
);
};
self.expect_keywords(&[Keyword::FROM, Keyword::SECURITY, Keyword::INTEGRATION])?;
Expand Down Expand Up @@ -340,7 +340,7 @@ impl Parser<'_> {
} else if self.parse_keyword(Keyword::DUO) {
Ok(MfaMethodKind::Duo)
} else {
self.expected("PASSKEY, TOTP or DUO", self.peek_token())
self.expected_ref("PASSKEY, TOTP or DUO", self.peek_token_ref())
}
}

Expand All @@ -358,10 +358,10 @@ impl Parser<'_> {
let role_name = self.parse_identifier()?;
AlterRoleOperation::RenameRole { role_name }
} else {
return self.expected("= after WITH NAME ", self.peek_token());
return self.expected_ref("= after WITH NAME ", self.peek_token_ref());
}
} else {
return self.expected("'ADD' or 'DROP' or 'WITH NAME'", self.peek_token());
return self.expected_ref("'ADD' or 'DROP' or 'WITH NAME'", self.peek_token_ref());
};

Ok(Statement::AlterRole {
Expand All @@ -385,7 +385,7 @@ impl Parser<'_> {
let role_name = self.parse_identifier()?;
AlterRoleOperation::RenameRole { role_name }
} else {
return self.expected("TO after RENAME", self.peek_token());
return self.expected_ref("TO after RENAME", self.peek_token_ref());
}
// SET
} else if self.parse_keyword(Keyword::SET) {
Expand All @@ -412,10 +412,10 @@ impl Parser<'_> {
in_database,
}
} else {
self.expected("config value", self.peek_token())?
self.expected_ref("config value", self.peek_token_ref())?
}
} else {
self.expected("'TO' or '=' or 'FROM CURRENT'", self.peek_token())?
self.expected_ref("'TO' or '=' or 'FROM CURRENT'", self.peek_token_ref())?
}
// RESET
} else if self.parse_keyword(Keyword::RESET) {
Expand All @@ -442,7 +442,7 @@ impl Parser<'_> {
}
// check option
if options.is_empty() {
return self.expected("option", self.peek_token())?;
return self.expected_ref("option", self.peek_token_ref())?;
}

AlterRoleOperation::WithOptions { options }
Expand Down Expand Up @@ -504,7 +504,7 @@ impl Parser<'_> {
self.expect_keyword_is(Keyword::UNTIL)?;
RoleOption::ValidUntil(Expr::Value(self.parse_value()?))
}
_ => self.expected("option", self.peek_token())?,
_ => self.expected_ref("option", self.peek_token_ref())?,
};

Ok(option)
Expand Down
Loading
Loading