Skip to content

Commit ba00077

Browse files
committed
feat: ColumnOptions enum
1 parent 888201b commit ba00077

8 files changed

Lines changed: 103 additions & 96 deletions

File tree

src/ast/ddl.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,8 +1421,24 @@ impl fmt::Display for ColumnDef {
14211421
pub struct ViewColumnDef {
14221422
pub name: Ident,
14231423
pub data_type: Option<DataType>,
1424-
pub options: Option<Vec<ColumnOption>>,
1425-
pub options_comma_separated: bool,
1424+
pub options: Option<ColumnOptions>,
1425+
}
1426+
1427+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1428+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1429+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1430+
pub enum ColumnOptions {
1431+
CommaSeparated(Vec<ColumnOption>),
1432+
SpaceSeparated(Vec<ColumnOption>),
1433+
}
1434+
1435+
impl ColumnOptions {
1436+
pub fn as_slice(&self) -> &[ColumnOption] {
1437+
match self {
1438+
ColumnOptions::CommaSeparated(options) => options.as_slice(),
1439+
ColumnOptions::SpaceSeparated(options) => options.as_slice(),
1440+
}
1441+
}
14261442
}
14271443

14281444
impl fmt::Display for ViewColumnDef {
@@ -1432,10 +1448,10 @@ impl fmt::Display for ViewColumnDef {
14321448
write!(f, " {}", data_type)?;
14331449
}
14341450
if let Some(options) = self.options.as_ref() {
1435-
if self.options_comma_separated {
1451+
if matches!(options, ColumnOptions::CommaSeparated(_)) {
14361452
write!(f, " {}", display_comma_separated(options.as_slice()))?;
14371453
} else {
1438-
write!(f, " {}", display_separated(options.as_slice(), " "))?;
1454+
write!(f, " {}", display_separated(options.as_slice(), " "))?
14391455
}
14401456
}
14411457
Ok(())

src/ast/mod.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,14 @@ pub use self::ddl::{
6060
AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
6161
AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterType, AlterTypeAddValue,
6262
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
63-
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnPolicy, ColumnPolicyProperty,
64-
ConstraintCharacteristics, CreateConnector, CreateDomain, CreateFunction, Deduplicate,
65-
DeferrableInitial, DropBehavior, GeneratedAs, GeneratedExpressionMode, IdentityParameters,
66-
IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder,
67-
IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition,
68-
ProcedureParam, ReferentialAction, ReplicaIdentity, TableConstraint, TagsColumnOption,
69-
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef,
63+
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
64+
ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain, CreateFunction,
65+
Deduplicate, DeferrableInitial, DropBehavior, GeneratedAs, GeneratedExpressionMode,
66+
IdentityParameters, IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind,
67+
IdentityPropertyOrder, IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner,
68+
Partition, ProcedureParam, ReferentialAction, ReplicaIdentity, TableConstraint,
69+
TagsColumnOption, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation,
70+
ViewColumnDef,
7071
};
7172
pub use self::dml::{CreateIndex, CreateTable, Delete, IndexColumn, Insert};
7273
pub use self::operator::{BinaryOperator, UnaryOperator};

src/ast/spans.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -982,12 +982,14 @@ impl Spanned for ViewColumnDef {
982982
name,
983983
data_type: _, // todo, DataType
984984
options,
985-
options_comma_separated: _,
986985
} = self;
987986

988987
union_spans(
989-
core::iter::once(name.span)
990-
.chain(options.iter().flat_map(|i| i.iter().map(|k| k.span()))),
988+
core::iter::once(name.span).chain(
989+
options
990+
.iter()
991+
.flat_map(|i| i.as_slice().iter().map(|k| k.span())),
992+
),
991993
)
992994
}
993995
}
@@ -1049,7 +1051,9 @@ impl Spanned for CreateTableOptions {
10491051
match self {
10501052
CreateTableOptions::None => Span::empty(),
10511053
CreateTableOptions::With(vec) => union_spans(vec.iter().map(|i| i.span())),
1052-
CreateTableOptions::Options(vec) => union_spans(vec.iter().map(|i| i.span())),
1054+
CreateTableOptions::Options(vec) => {
1055+
union_spans(vec.as_slice().iter().map(|i| i.span()))
1056+
}
10531057
CreateTableOptions::Plain(vec) => union_spans(vec.iter().map(|i| i.span())),
10541058
CreateTableOptions::TableProperties(vec) => union_spans(vec.iter().map(|i| i.span())),
10551059
}

src/parser/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10580,11 +10580,10 @@ impl<'a> Parser<'a> {
1058010580
name,
1058110581
data_type,
1058210582
options,
10583-
options_comma_separated: !dialect_of!(self is SnowflakeDialect),
1058410583
})
1058510584
}
1058610585

10587-
fn parse_view_column_options(&mut self) -> Result<Option<Vec<ColumnOption>>, ParserError> {
10586+
fn parse_view_column_options(&mut self) -> Result<Option<ColumnOptions>, ParserError> {
1058810587
let mut options = Vec::new();
1058910588
loop {
1059010589
let option = self.parse_optional_column_option()?;
@@ -10594,7 +10593,14 @@ impl<'a> Parser<'a> {
1059410593
break;
1059510594
}
1059610595
}
10597-
Ok(options.is_empty().not().then_some(options))
10596+
Ok(options
10597+
.is_empty()
10598+
.not()
10599+
.then_some(if dialect_of!(self is SnowflakeDialect) {
10600+
ColumnOptions::SpaceSeparated(options)
10601+
} else {
10602+
ColumnOptions::CommaSeparated(options)
10603+
}))
1059810604
}
1059910605

1060010606
/// Parses a parenthesized comma-separated list of unqualified, possibly quoted identifiers.

tests/sqlparser_bigquery.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -348,20 +348,20 @@ fn parse_create_view_with_options() {
348348
name: Ident::new("name"),
349349
data_type: None,
350350
options: None,
351-
options_comma_separated: true,
352351
},
353352
ViewColumnDef {
354353
name: Ident::new("age"),
355354
data_type: None,
356-
options: Some(vec![ColumnOption::Options(vec![SqlOption::KeyValue {
357-
key: Ident::new("description"),
358-
value: Expr::Value(
359-
Value::DoubleQuotedString("field age".to_string()).with_span(
360-
Span::new(Location::new(1, 42), Location::new(1, 52))
361-
)
362-
),
363-
}])]),
364-
options_comma_separated: true,
355+
options: Some(ColumnOptions::CommaSeparated(vec![ColumnOption::Options(
356+
vec![SqlOption::KeyValue {
357+
key: Ident::new("description"),
358+
value: Expr::Value(
359+
Value::DoubleQuotedString("field age".to_string()).with_span(
360+
Span::new(Location::new(1, 42), Location::new(1, 52))
361+
)
362+
),
363+
}]
364+
)])),
365365
},
366366
],
367367
columns

tests/sqlparser_clickhouse.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,6 @@ fn parse_create_view_with_fields_data_types() {
915915
vec![]
916916
)),
917917
options: None,
918-
options_comma_separated: true,
919918
},
920919
ViewColumnDef {
921920
name: "f".into(),
@@ -928,7 +927,6 @@ fn parse_create_view_with_fields_data_types() {
928927
vec![]
929928
)),
930929
options: None,
931-
options_comma_separated: true,
932930
},
933931
]
934932
);

tests/sqlparser_common.rs

Lines changed: 43 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7960,64 +7960,52 @@ fn parse_create_view_with_options() {
79607960
#[test]
79617961
fn parse_create_view_with_columns() {
79627962
let sql = "CREATE VIEW v (has, cols) AS SELECT 1, 2";
7963-
fn assert_stmt_as_expected(stmt: Statement, options_comma_separated: bool) {
7964-
match stmt {
7965-
Statement::CreateView {
7966-
or_alter,
7967-
name,
7963+
// TODO: why does this fail for ClickHouseDialect? (#1449)
7964+
// match all_dialects().verified_stmt(sql) {
7965+
match all_dialects_where(|d| !d.is::<ClickHouseDialect>()).verified_stmt(sql) {
7966+
Statement::CreateView {
7967+
or_alter,
7968+
name,
7969+
columns,
7970+
or_replace,
7971+
options,
7972+
query,
7973+
materialized,
7974+
cluster_by,
7975+
comment,
7976+
with_no_schema_binding: late_binding,
7977+
if_not_exists,
7978+
temporary,
7979+
to,
7980+
params,
7981+
} => {
7982+
assert_eq!(or_alter, false);
7983+
assert_eq!("v", name.to_string());
7984+
assert_eq!(
79687985
columns,
7969-
or_replace,
7970-
options,
7971-
query,
7972-
materialized,
7973-
cluster_by,
7974-
comment,
7975-
with_no_schema_binding: late_binding,
7976-
if_not_exists,
7977-
temporary,
7978-
to,
7979-
params,
7980-
} => {
7981-
assert_eq!(or_alter, false);
7982-
assert_eq!("v", name.to_string());
7983-
assert_eq!(
7984-
columns,
7985-
vec![Ident::new("has"), Ident::new("cols"),]
7986-
.into_iter()
7987-
.map(|name| ViewColumnDef {
7988-
name,
7989-
data_type: None,
7990-
options: None,
7991-
options_comma_separated,
7992-
})
7993-
.collect::<Vec<_>>()
7994-
);
7995-
assert_eq!(options, CreateTableOptions::None);
7996-
assert_eq!("SELECT 1, 2", query.to_string());
7997-
assert!(!materialized);
7998-
assert!(!or_replace);
7999-
assert_eq!(cluster_by, vec![]);
8000-
assert!(comment.is_none());
8001-
assert!(!late_binding);
8002-
assert!(!if_not_exists);
8003-
assert!(!temporary);
8004-
assert!(to.is_none());
8005-
assert!(params.is_none());
8006-
}
8007-
_ => unreachable!(),
7986+
vec![Ident::new("has"), Ident::new("cols"),]
7987+
.into_iter()
7988+
.map(|name| ViewColumnDef {
7989+
name,
7990+
data_type: None,
7991+
options: None,
7992+
})
7993+
.collect::<Vec<_>>()
7994+
);
7995+
assert_eq!(options, CreateTableOptions::None);
7996+
assert_eq!("SELECT 1, 2", query.to_string());
7997+
assert!(!materialized);
7998+
assert!(!or_replace);
7999+
assert_eq!(cluster_by, vec![]);
8000+
assert!(comment.is_none());
8001+
assert!(!late_binding);
8002+
assert!(!if_not_exists);
8003+
assert!(!temporary);
8004+
assert!(to.is_none());
8005+
assert!(params.is_none());
80088006
}
8007+
_ => unreachable!(),
80098008
}
8010-
// TODO: why does this fail for ClickHouseDialect? (#1449)
8011-
// match all_dialects().verified_stmt(sql) {
8012-
assert_stmt_as_expected(
8013-
all_dialects_where(|d| !d.is::<ClickHouseDialect>() && !d.is::<SnowflakeDialect>())
8014-
.verified_stmt(sql),
8015-
true,
8016-
);
8017-
assert_stmt_as_expected(
8018-
all_dialects_where(|d| d.is::<SnowflakeDialect>()).verified_stmt(sql),
8019-
false,
8020-
);
80218009
}
80228010

80238011
#[test]

tests/sqlparser_snowflake.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3142,14 +3142,14 @@ fn parse_view_column_descriptions() {
31423142
ViewColumnDef {
31433143
name: Ident::new("a"),
31443144
data_type: None,
3145-
options: Some(vec![ColumnOption::Comment("Comment".to_string())]),
3146-
options_comma_separated: false,
3145+
options: Some(ColumnOptions::SpaceSeparated(vec![ColumnOption::Comment(
3146+
"Comment".to_string()
3147+
)])),
31473148
},
31483149
ViewColumnDef {
31493150
name: Ident::new("b"),
31503151
data_type: None,
31513152
options: None,
3152-
options_comma_separated: false,
31533153
}
31543154
]
31553155
);
@@ -4087,13 +4087,7 @@ fn parse_connect_by_root_operator() {
40874087

40884088
#[test]
40894089
fn test_snowflake_create_view_with_tag() {
4090-
let create_view_with_tag = r#"CREATE VIEW X (COL WITH TAG (pii='email')) AS SELECT * FROM Y"#;
4091-
snowflake().verified_stmt(create_view_with_tag);
4092-
}
4093-
4094-
#[test]
4095-
fn test_snowflake_create_view_with_tag_and_comment() {
4096-
let create_view_with_tag_and_comment =
4090+
let create_view_with_tag =
40974091
r#"CREATE VIEW X (COL WITH TAG (pii='email') COMMENT 'foobar') AS SELECT * FROM Y"#;
4098-
snowflake().verified_stmt(create_view_with_tag_and_comment);
4092+
snowflake().verified_stmt(create_view_with_tag);
40994093
}

0 commit comments

Comments
 (0)