Skip to content

Commit 861cfcd

Browse files
committed
improve object name parts
1 parent ef072be commit 861cfcd

17 files changed

+446
-400
lines changed

src/ast/helpers/stmt_create_table.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use crate::parser::ParserError;
4242
/// ```rust
4343
/// use sqlparser::ast::helpers::stmt_create_table::CreateTableBuilder;
4444
/// use sqlparser::ast::{ColumnDef, DataType, Ident, ObjectName};
45-
/// let builder = CreateTableBuilder::new(ObjectName(vec![Ident::new("table_name")]))
45+
/// let builder = CreateTableBuilder::new(ObjectName::from(vec![Ident::new("table_name")]))
4646
/// .if_not_exists(true)
4747
/// .columns(vec![ColumnDef {
4848
/// name: Ident::new("c1"),
@@ -602,7 +602,7 @@ mod tests {
602602

603603
#[test]
604604
pub fn test_from_valid_statement() {
605-
let builder = CreateTableBuilder::new(ObjectName(vec![Ident::new("table_name")]));
605+
let builder = CreateTableBuilder::new(ObjectName::from(vec![Ident::new("table_name")]));
606606

607607
let stmt = builder.clone().build();
608608

src/ast/mod.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,10 @@ impl Ident {
237237
span,
238238
}
239239
}
240+
241+
pub fn to_object_name_part(&self) -> ObjectNamePart {
242+
ObjectNamePart::Identifier(self.clone())
243+
}
240244
}
241245

242246
impl From<&str> for Ident {
@@ -267,14 +271,36 @@ impl fmt::Display for Ident {
267271
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
268272
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
269273
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
270-
pub struct ObjectName(pub Vec<Ident>);
274+
pub struct ObjectName(pub Vec<ObjectNamePart>);
275+
276+
impl From<Vec<Ident>> for ObjectName {
277+
fn from(idents: Vec<Ident>) -> Self {
278+
ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
279+
}
280+
}
271281

272282
impl fmt::Display for ObjectName {
273283
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
274284
write!(f, "{}", display_separated(&self.0, "."))
275285
}
276286
}
277287

288+
/// A single part of an ObjectName
289+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
290+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
291+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
292+
pub enum ObjectNamePart {
293+
Identifier(Ident),
294+
}
295+
296+
impl fmt::Display for ObjectNamePart {
297+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
298+
match self {
299+
ObjectNamePart::Identifier(ident) => write!(f, "{}", ident),
300+
}
301+
}
302+
}
303+
278304
/// Represents an Array Expression, either
279305
/// `ARRAY[..]`, or `[..]`
280306
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]

src/dialect/snowflake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ pub fn parse_snowflake_stage_name(parser: &mut Parser) -> Result<ObjectName, Par
651651
break;
652652
}
653653
}
654-
Ok(ObjectName(idents))
654+
Ok(ObjectName::from(idents))
655655
}
656656
_ => {
657657
parser.prev_token();

src/parser/mod.rs

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@ impl<'a> Parser<'a> {
988988
}
989989
Token::Mul => {
990990
return Ok(Expr::QualifiedWildcard(
991-
ObjectName(id_parts),
991+
ObjectName::from(id_parts),
992992
AttachedToken(next_token),
993993
));
994994
}
@@ -1128,7 +1128,7 @@ impl<'a> Parser<'a> {
11281128
if dialect_of!(self is PostgreSqlDialect | GenericDialect) =>
11291129
{
11301130
Ok(Some(Expr::Function(Function {
1131-
name: ObjectName(vec![w.clone().into_ident(w_span)]),
1131+
name: ObjectName::from(vec![w.clone().into_ident(w_span)]),
11321132
uses_odbc_syntax: false,
11331133
parameters: FunctionArguments::None,
11341134
args: FunctionArguments::None,
@@ -1143,7 +1143,7 @@ impl<'a> Parser<'a> {
11431143
| Keyword::CURRENT_DATE
11441144
| Keyword::LOCALTIME
11451145
| Keyword::LOCALTIMESTAMP => {
1146-
Ok(Some(self.parse_time_functions(ObjectName(vec![w.clone().into_ident(w_span)]))?))
1146+
Ok(Some(self.parse_time_functions(ObjectName::from(vec![w.clone().into_ident(w_span)]))?))
11471147
}
11481148
Keyword::CASE => Ok(Some(self.parse_case_expr()?)),
11491149
Keyword::CONVERT => Ok(Some(self.parse_convert_expr(false)?)),
@@ -1187,7 +1187,7 @@ impl<'a> Parser<'a> {
11871187
let query = self.parse_query()?;
11881188
self.expect_token(&Token::RParen)?;
11891189
Ok(Some(Expr::Function(Function {
1190-
name: ObjectName(vec![w.clone().into_ident(w_span)]),
1190+
name: ObjectName::from(vec![w.clone().into_ident(w_span)]),
11911191
uses_odbc_syntax: false,
11921192
parameters: FunctionArguments::None,
11931193
args: FunctionArguments::Subquery(query),
@@ -1232,7 +1232,7 @@ impl<'a> Parser<'a> {
12321232
if let Some(expr) = self.parse_outer_join_expr(&id_parts) {
12331233
Ok(expr)
12341234
} else {
1235-
let mut expr = self.parse_function(ObjectName(id_parts))?;
1235+
let mut expr = self.parse_function(ObjectName::from(id_parts))?;
12361236
// consume all period if it's a method chain
12371237
expr = self.try_parse_method(expr)?;
12381238
let fields = vec![];
@@ -1694,7 +1694,7 @@ impl<'a> Parser<'a> {
16941694
Token::Word(word) => word.into_ident(tok.span),
16951695
_ => return p.expected("identifier", tok),
16961696
};
1697-
let func = match p.parse_function(ObjectName(vec![name]))? {
1697+
let func = match p.parse_function(ObjectName::from(vec![name]))? {
16981698
Expr::Function(func) => func,
16991699
_ => return p.expected("function", p.peek_token()),
17001700
};
@@ -2197,7 +2197,7 @@ impl<'a> Parser<'a> {
21972197
Some(expr) => Ok(expr),
21982198
// Snowflake supports `position` as an ordinary function call
21992199
// without the special `IN` syntax.
2200-
None => self.parse_function(ObjectName(vec![ident])),
2200+
None => self.parse_function(ObjectName::from(vec![ident])),
22012201
}
22022202
}
22032203

@@ -4044,6 +4044,24 @@ impl<'a> Parser<'a> {
40444044
Ok(values)
40454045
}
40464046

4047+
pub fn parse_period_separated<T, F>(&mut self, mut f: F) -> Result<Vec<T>, ParserError>
4048+
where
4049+
F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
4050+
{
4051+
let mut values = vec![];
4052+
loop {
4053+
values.push(f(self)?);
4054+
if !self.consume_token(&Token::Period) {
4055+
break;
4056+
}
4057+
}
4058+
Ok(values)
4059+
}
4060+
4061+
pub fn parse_period_separated_identifiers(&mut self) -> Result<Vec<Ident>, ParserError> {
4062+
self.parse_period_separated(|p| p.parse_identifier(false))
4063+
}
4064+
40474065
/// Parse a keyword-separated list of 1+ items accepted by `F`
40484066
pub fn parse_keyword_separated<T, F>(
40494067
&mut self,
@@ -4757,7 +4775,10 @@ impl<'a> Parser<'a> {
47574775
let mut data_type = self.parse_data_type()?;
47584776
if let DataType::Custom(n, _) = &data_type {
47594777
// the first token is actually a name
4760-
name = Some(n.0[0].clone());
4778+
match n.0[0].clone() {
4779+
ObjectNamePart::Identifier(ident) => name = Some(ident),
4780+
}
4781+
// name = Some(n.0[0].clone());
47614782
data_type = self.parse_data_type()?;
47624783
}
47634784

@@ -9093,7 +9114,7 @@ impl<'a> Parser<'a> {
90939114
.collect()
90949115
}
90959116

9096-
Ok(ObjectName(idents))
9117+
Ok(ObjectName::from(idents))
90979118
}
90989119

90999120
/// Parse identifiers
@@ -10419,14 +10440,14 @@ impl<'a> Parser<'a> {
1041910440
}
1042010441

1042110442
let variables = if self.parse_keywords(&[Keyword::TIME, Keyword::ZONE]) {
10422-
OneOrManyWithParens::One(ObjectName(vec!["TIMEZONE".into()]))
10443+
OneOrManyWithParens::One(ObjectName::from(vec!["TIMEZONE".into()]))
1042310444
} else if self.dialect.supports_parenthesized_set_variables()
1042410445
&& self.consume_token(&Token::LParen)
1042510446
{
1042610447
let variables = OneOrManyWithParens::Many(
1042710448
self.parse_comma_separated(|parser: &mut Parser<'a>| parser.parse_identifier())?
1042810449
.into_iter()
10429-
.map(|ident| ObjectName(vec![ident]))
10450+
.map(|ident| ObjectName::from(vec![ident]))
1043010451
.collect(),
1043110452
);
1043210453
self.expect_token(&Token::RParen)?;
@@ -11762,7 +11783,7 @@ impl<'a> Parser<'a> {
1176211783
Token::Word(w) => Ok(w.value),
1176311784
_ => self.expected("a function identifier", self.peek_token()),
1176411785
}?;
11765-
let expr = self.parse_function(ObjectName(vec![Ident::new(function_name)]))?;
11786+
let expr = self.parse_function(ObjectName::from(vec![Ident::new(function_name)]))?;
1176611787
let alias = if self.parse_keyword(Keyword::AS) {
1176711788
Some(self.parse_identifier()?)
1176811789
} else {
@@ -11811,7 +11832,7 @@ impl<'a> Parser<'a> {
1181111832
self.expect_token(&Token::LParen)?;
1181211833
let aggregate_functions = self.parse_comma_separated(Self::parse_aliased_function_call)?;
1181311834
self.expect_keyword_is(Keyword::FOR)?;
11814-
let value_column = self.parse_object_name(false)?.0;
11835+
let value_column = self.parse_period_separated_identifiers()?;
1181511836
self.expect_keyword_is(Keyword::IN)?;
1181611837

1181711838
self.expect_token(&Token::LParen)?;
@@ -13773,7 +13794,7 @@ impl<'a> Parser<'a> {
1377313794
// [ OWNED BY { table_name.column_name | NONE } ]
1377413795
let owned_by = if self.parse_keywords(&[Keyword::OWNED, Keyword::BY]) {
1377513796
if self.parse_keywords(&[Keyword::NONE]) {
13776-
Some(ObjectName(vec![Ident::new("NONE")]))
13797+
Some(ObjectName::from(vec![Ident::new("NONE")]))
1377713798
} else {
1377813799
Some(self.parse_object_name(false)?)
1377913800
}
@@ -14064,7 +14085,7 @@ impl<'a> Parser<'a> {
1406414085
.parse_one_of_keywords(&[Keyword::FROM, Keyword::IN])
1406514086
.is_some()
1406614087
{
14067-
parent_name.0.insert(0, self.parse_identifier()?);
14088+
parent_name.0.insert(0, self.parse_identifier()?.to_object_name_part());
1406814089
}
1406914090
(None, Some(parent_name))
1407014091
}
@@ -14380,14 +14401,14 @@ mod tests {
1438014401
test_parse_data_type!(
1438114402
dialect,
1438214403
"GEOMETRY",
14383-
DataType::Custom(ObjectName(vec!["GEOMETRY".into()]), vec![])
14404+
DataType::Custom(ObjectName::from(vec!["GEOMETRY".into()]), vec![])
1438414405
);
1438514406

1438614407
test_parse_data_type!(
1438714408
dialect,
1438814409
"GEOMETRY(POINT)",
1438914410
DataType::Custom(
14390-
ObjectName(vec!["GEOMETRY".into()]),
14411+
ObjectName::from(vec!["GEOMETRY".into()]),
1439114412
vec!["POINT".to_string()]
1439214413
)
1439314414
);
@@ -14396,7 +14417,7 @@ mod tests {
1439614417
dialect,
1439714418
"GEOMETRY(POINT, 4326)",
1439814419
DataType::Custom(
14399-
ObjectName(vec!["GEOMETRY".into()]),
14420+
ObjectName::from(vec!["GEOMETRY".into()]),
1440014421
vec!["POINT".to_string(), "4326".to_string()]
1440114422
)
1440214423
);
@@ -14532,7 +14553,7 @@ mod tests {
1453214553
}};
1453314554
}
1453414555

14535-
let dummy_name = ObjectName(vec![Ident::new("dummy_name")]);
14556+
let dummy_name = ObjectName::from(vec![Ident::new("dummy_name")]);
1453614557
let dummy_authorization = Ident::new("dummy_authorization");
1453714558

1453814559
test_parse_schema_name!(

src/test_utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ pub fn table_alias(name: impl Into<String>) -> Option<TableAlias> {
353353

354354
pub fn table(name: impl Into<String>) -> TableFactor {
355355
TableFactor::Table {
356-
name: ObjectName(vec![Ident::new(name.into())]),
356+
name: ObjectName::from(vec![Ident::new(name.into())]),
357357
alias: None,
358358
args: None,
359359
with_hints: vec![],
@@ -381,7 +381,7 @@ pub fn table_from_name(name: ObjectName) -> TableFactor {
381381

382382
pub fn table_with_alias(name: impl Into<String>, alias: impl Into<String>) -> TableFactor {
383383
TableFactor::Table {
384-
name: ObjectName(vec![Ident::new(name)]),
384+
name: ObjectName::from(vec![Ident::new(name)]),
385385
alias: Some(TableAlias {
386386
name: Ident::new(alias),
387387
columns: vec![],
@@ -406,7 +406,7 @@ pub fn join(relation: TableFactor) -> Join {
406406

407407
pub fn call(function: &str, args: impl IntoIterator<Item = Expr>) -> Expr {
408408
Expr::Function(Function {
409-
name: ObjectName(vec![Ident::new(function)]),
409+
name: ObjectName::from(vec![Ident::new(function)]),
410410
uses_odbc_syntax: false,
411411
parameters: FunctionArguments::None,
412412
args: FunctionArguments::List(FunctionArgumentList {

0 commit comments

Comments
 (0)