mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-04 06:18:17 +00:00
Support for unquoted hyphenated identifiers on bigquery (#1109)
This commit is contained in:
parent
498708c463
commit
398a81029e
7 changed files with 298 additions and 175 deletions
|
@ -82,7 +82,7 @@ fn parse_lock_tables(parser: &mut Parser) -> Result<Statement, ParserError> {
|
|||
|
||||
// tbl_name [[AS] alias] lock_type
|
||||
fn parse_lock_table(parser: &mut Parser) -> Result<LockTable, ParserError> {
|
||||
let table = parser.parse_identifier()?;
|
||||
let table = parser.parse_identifier(false)?;
|
||||
let alias =
|
||||
parser.parse_optional_alias(&[Keyword::READ, Keyword::WRITE, Keyword::LOW_PRIORITY])?;
|
||||
let lock_type = parse_lock_tables_type(parser)?;
|
||||
|
|
|
@ -57,11 +57,11 @@ pub fn parse_comment(parser: &mut Parser) -> Result<Statement, ParserError> {
|
|||
|
||||
let (object_type, object_name) = match token.token {
|
||||
Token::Word(w) if w.keyword == Keyword::COLUMN => {
|
||||
let object_name = parser.parse_object_name()?;
|
||||
let object_name = parser.parse_object_name(false)?;
|
||||
(CommentObject::Column, object_name)
|
||||
}
|
||||
Token::Word(w) if w.keyword == Keyword::TABLE => {
|
||||
let object_name = parser.parse_object_name()?;
|
||||
let object_name = parser.parse_object_name(false)?;
|
||||
(CommentObject::Table, object_name)
|
||||
}
|
||||
_ => parser.expected("comment object_type", token)?,
|
||||
|
|
|
@ -91,7 +91,7 @@ pub fn parse_create_stage(
|
|||
) -> Result<Statement, ParserError> {
|
||||
//[ IF NOT EXISTS ]
|
||||
let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
||||
let name = parser.parse_object_name()?;
|
||||
let name = parser.parse_object_name(false)?;
|
||||
let mut directory_table_params = Vec::new();
|
||||
let mut file_format = Vec::new();
|
||||
let mut copy_options = Vec::new();
|
||||
|
@ -181,7 +181,7 @@ pub fn parse_snowflake_stage_name(parser: &mut Parser) -> Result<ObjectName, Par
|
|||
}
|
||||
_ => {
|
||||
parser.prev_token();
|
||||
Ok(parser.parse_object_name()?)
|
||||
Ok(parser.parse_object_name(false)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
|
|||
}
|
||||
_ => {
|
||||
parser.prev_token();
|
||||
from_stage = parser.parse_object_name()?;
|
||||
from_stage = parser.parse_object_name(false)?;
|
||||
stage_params = parse_stage_params(parser)?;
|
||||
|
||||
// as
|
||||
|
|
|
@ -37,17 +37,17 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
fn parse_mssql_alter_role(&mut self) -> Result<Statement, ParserError> {
|
||||
let role_name = self.parse_identifier()?;
|
||||
let role_name = self.parse_identifier(false)?;
|
||||
|
||||
let operation = if self.parse_keywords(&[Keyword::ADD, Keyword::MEMBER]) {
|
||||
let member_name = self.parse_identifier()?;
|
||||
let member_name = self.parse_identifier(false)?;
|
||||
AlterRoleOperation::AddMember { member_name }
|
||||
} else if self.parse_keywords(&[Keyword::DROP, Keyword::MEMBER]) {
|
||||
let member_name = self.parse_identifier()?;
|
||||
let member_name = self.parse_identifier(false)?;
|
||||
AlterRoleOperation::DropMember { member_name }
|
||||
} else if self.parse_keywords(&[Keyword::WITH, Keyword::NAME]) {
|
||||
if self.consume_token(&Token::Eq) {
|
||||
let role_name = self.parse_identifier()?;
|
||||
let role_name = self.parse_identifier(false)?;
|
||||
AlterRoleOperation::RenameRole { role_name }
|
||||
} else {
|
||||
return self.expected("= after WITH NAME ", self.peek_token());
|
||||
|
@ -63,25 +63,25 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
fn parse_pg_alter_role(&mut self) -> Result<Statement, ParserError> {
|
||||
let role_name = self.parse_identifier()?;
|
||||
let role_name = self.parse_identifier(false)?;
|
||||
|
||||
// [ IN DATABASE _`database_name`_ ]
|
||||
let in_database = if self.parse_keywords(&[Keyword::IN, Keyword::DATABASE]) {
|
||||
self.parse_object_name().ok()
|
||||
self.parse_object_name(false).ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let operation = if self.parse_keyword(Keyword::RENAME) {
|
||||
if self.parse_keyword(Keyword::TO) {
|
||||
let role_name = self.parse_identifier()?;
|
||||
let role_name = self.parse_identifier(false)?;
|
||||
AlterRoleOperation::RenameRole { role_name }
|
||||
} else {
|
||||
return self.expected("TO after RENAME", self.peek_token());
|
||||
}
|
||||
// SET
|
||||
} else if self.parse_keyword(Keyword::SET) {
|
||||
let config_name = self.parse_object_name()?;
|
||||
let config_name = self.parse_object_name(false)?;
|
||||
// FROM CURRENT
|
||||
if self.parse_keywords(&[Keyword::FROM, Keyword::CURRENT]) {
|
||||
AlterRoleOperation::Set {
|
||||
|
@ -117,7 +117,7 @@ impl<'a> Parser<'a> {
|
|||
in_database,
|
||||
}
|
||||
} else {
|
||||
let config_name = self.parse_object_name()?;
|
||||
let config_name = self.parse_object_name(false)?;
|
||||
AlterRoleOperation::Reset {
|
||||
config_name: ResetConfig::ConfigName(config_name),
|
||||
in_database,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -878,6 +878,47 @@ fn parse_table_identifiers() {
|
|||
Ident::with_quote('`', "da-sh-es"),
|
||||
],
|
||||
);
|
||||
|
||||
test_table_ident(
|
||||
"foo-bar.baz-123",
|
||||
Some("foo-bar.baz-123"),
|
||||
vec![Ident::new("foo-bar"), Ident::new("baz-123")],
|
||||
);
|
||||
|
||||
test_table_ident_err("foo-`bar`");
|
||||
test_table_ident_err("`foo`-bar");
|
||||
test_table_ident_err("foo-123a");
|
||||
test_table_ident_err("foo - bar");
|
||||
test_table_ident_err("123-bar");
|
||||
test_table_ident_err("bar-");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_hyphenated_table_identifiers() {
|
||||
bigquery().one_statement_parses_to(
|
||||
"select * from foo-bar f join baz-qux b on f.id = b.id",
|
||||
"SELECT * FROM foo-bar AS f JOIN baz-qux AS b ON f.id = b.id",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
bigquery()
|
||||
.verified_only_select_with_canonical(
|
||||
"SELECT foo-bar.x FROM t",
|
||||
"SELECT foo - bar.x FROM t"
|
||||
)
|
||||
.projection[0],
|
||||
SelectItem::UnnamedExpr(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier(Ident::new("foo"))),
|
||||
op: BinaryOperator::Minus,
|
||||
right: Box::new(Expr::CompoundIdentifier(vec![
|
||||
Ident::new("bar"),
|
||||
Ident::new("x")
|
||||
]))
|
||||
})
|
||||
);
|
||||
|
||||
let error_sql = "select foo-bar.* from foo-bar";
|
||||
assert!(bigquery().parse_sql_statements(error_sql).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -507,14 +507,15 @@ fn parse_select_with_table_alias() {
|
|||
|
||||
#[test]
|
||||
fn parse_invalid_table_name() {
|
||||
let ast = all_dialects()
|
||||
.run_parser_method("db.public..customer", |parser| parser.parse_object_name());
|
||||
let ast = all_dialects().run_parser_method("db.public..customer", |parser| {
|
||||
parser.parse_object_name(false)
|
||||
});
|
||||
assert!(ast.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_no_table_name() {
|
||||
let ast = all_dialects().run_parser_method("", |parser| parser.parse_object_name());
|
||||
let ast = all_dialects().run_parser_method("", |parser| parser.parse_object_name(false));
|
||||
assert!(ast.is_err());
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue