Skip to content

Commit 63d7153

Browse files
Merge unique-unique-constraint into future-main
2 parents 362234e + a359663 commit 63d7153

File tree

7 files changed

+151
-57
lines changed

7 files changed

+151
-57
lines changed

src/ast/ddl.rs

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ use sqlparser_derive::{Visit, VisitMut};
3131
use crate::ast::helpers::attached_token::AttachedToken;
3232
use crate::ast::table_constraints::TableConstraint;
3333
use crate::ast::value::escape_single_quote_string;
34-
use crate::ast::{CreateViewParams, FunctionDesc, HiveSetLocation};
3534
use crate::ast::{
36-
display_comma_separated, display_separated, table_constraints::ForeignKeyConstraint, ArgMode,
37-
CommentDef, ConditionalStatements, CreateFunctionBody, CreateFunctionUsing,
35+
display_comma_separated, display_separated,
36+
table_constraints::{ForeignKeyConstraint, PrimaryKeyConstraint, UniqueConstraint},
37+
ArgMode, CommentDef, ConditionalStatements, CreateFunctionBody, CreateFunctionUsing,
3838
CreateTableLikeKind, CreateTableOptions, DataType, Expr, FileFormat, FunctionBehavior,
3939
FunctionCalledOnNull, FunctionDeterminismSpecifier, FunctionParallel, HiveDistributionStyle,
4040
HiveFormat, HiveIOFormat, HiveRowFormat, Ident, InitializeKind, MySQLColumnPosition,
@@ -43,6 +43,7 @@ use crate::ast::{
4343
StorageSerializationPolicy, TableVersion, Tag, TriggerEvent, TriggerExecBody, TriggerObject,
4444
TriggerPeriod, TriggerReferencing, Value, ValueWithSpan, WrappedCollection,
4545
};
46+
use crate::ast::{CreateViewParams, FunctionDesc, HiveSetLocation};
4647
use crate::display_utils::{DisplayCommaSeparated, Indent, NewLine, SpaceOrNewline};
4748
use crate::keywords::Keyword;
4849
use crate::tokenizer::{Span, Token};
@@ -56,6 +57,22 @@ pub struct IndexColumn {
5657
pub operator_class: Option<Ident>,
5758
}
5859

60+
impl From<Ident> for IndexColumn {
61+
fn from(c: Ident) -> Self {
62+
Self {
63+
column: OrderByExpr::from(c),
64+
operator_class: None,
65+
}
66+
}
67+
}
68+
69+
impl<'a> From<&'a str> for IndexColumn {
70+
fn from(c: &'a str) -> Self {
71+
let ident = Ident::new(c);
72+
ident.into()
73+
}
74+
}
75+
5976
impl fmt::Display for IndexColumn {
6077
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6178
write!(f, "{}", self.column)?;
@@ -1555,12 +1572,10 @@ pub enum ColumnOption {
15551572
///
15561573
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/create/table#default_values)
15571574
Alias(Expr),
1558-
1559-
/// `{ PRIMARY KEY | UNIQUE } [<constraint_characteristics>]`
1560-
Unique {
1561-
is_primary: bool,
1562-
characteristics: Option<ConstraintCharacteristics>,
1563-
},
1575+
/// `PRIMARY KEY [<constraint_characteristics>]`
1576+
PrimaryKey(PrimaryKeyConstraint),
1577+
/// `UNIQUE [<constraint_characteristics>]`
1578+
Unique(UniqueConstraint),
15641579
/// A referential integrity constraint (`REFERENCES <foreign_table> (<referred_columns>)
15651580
/// [ MATCH { FULL | PARTIAL | SIMPLE } ]
15661581
/// { [ON DELETE <referential_action>] [ON UPDATE <referential_action>] |
@@ -1644,6 +1659,17 @@ impl From<ForeignKeyConstraint> for ColumnOption {
16441659
ColumnOption::ForeignKey(fk)
16451660
}
16461661
}
1662+
impl From<UniqueConstraint> for ColumnOption {
1663+
fn from(c: UniqueConstraint) -> Self {
1664+
ColumnOption::Unique(c)
1665+
}
1666+
}
1667+
1668+
impl From<PrimaryKeyConstraint> for ColumnOption {
1669+
fn from(c: PrimaryKeyConstraint) -> Self {
1670+
ColumnOption::PrimaryKey(c)
1671+
}
1672+
}
16471673

16481674
impl fmt::Display for ColumnOption {
16491675
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -1661,12 +1687,16 @@ impl fmt::Display for ColumnOption {
16611687
}
16621688
}
16631689
Alias(expr) => write!(f, "ALIAS {expr}"),
1664-
Unique {
1665-
is_primary,
1666-
characteristics,
1667-
} => {
1668-
write!(f, "{}", if *is_primary { "PRIMARY KEY" } else { "UNIQUE" })?;
1669-
if let Some(characteristics) = characteristics {
1690+
PrimaryKey(constraint) => {
1691+
write!(f, "PRIMARY KEY")?;
1692+
if let Some(characteristics) = &constraint.characteristics {
1693+
write!(f, " {characteristics}")?;
1694+
}
1695+
Ok(())
1696+
}
1697+
Unique(constraint) => {
1698+
write!(f, "UNIQUE")?;
1699+
if let Some(characteristics) = &constraint.characteristics {
16701700
write!(f, " {characteristics}")?;
16711701
}
16721702
Ok(())

src/ast/query.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2506,6 +2506,16 @@ pub struct OrderByExpr {
25062506
pub with_fill: Option<WithFill>,
25072507
}
25082508

2509+
impl From<Ident> for OrderByExpr {
2510+
fn from(ident: Ident) -> Self {
2511+
OrderByExpr {
2512+
expr: Expr::Identifier(ident),
2513+
options: OrderByOptions::default(),
2514+
with_fill: None,
2515+
}
2516+
}
2517+
}
2518+
25092519
impl fmt::Display for OrderByExpr {
25102520
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25112521
write!(f, "{}{}", self.expr, self.options)?;
@@ -2574,7 +2584,7 @@ impl fmt::Display for InterpolateExpr {
25742584
}
25752585
}
25762586

2577-
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2587+
#[derive(Default, Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
25782588
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25792589
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
25802590
pub struct OrderByOptions {

src/ast/spans.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,8 @@ impl Spanned for RaiseStatementValue {
728728
/// - [ColumnOption::Null]
729729
/// - [ColumnOption::NotNull]
730730
/// - [ColumnOption::Comment]
731-
/// - [ColumnOption::Unique]¨
731+
/// - [ColumnOption::PrimaryKey]
732+
/// - [ColumnOption::Unique]
732733
/// - [ColumnOption::DialectSpecific]
733734
/// - [ColumnOption::Generated]
734735
impl Spanned for ColumnOption {
@@ -740,7 +741,8 @@ impl Spanned for ColumnOption {
740741
ColumnOption::Materialized(expr) => expr.span(),
741742
ColumnOption::Ephemeral(expr) => expr.as_ref().map_or(Span::empty(), |e| e.span()),
742743
ColumnOption::Alias(expr) => expr.span(),
743-
ColumnOption::Unique { .. } => Span::empty(),
744+
ColumnOption::PrimaryKey(constraint) => constraint.span(),
745+
ColumnOption::Unique(constraint) => constraint.span(),
744746
ColumnOption::ForeignKey(constraint) => constraint.span(),
745747
ColumnOption::Check(expr) => expr.span(),
746748
ColumnOption::DialectSpecific(_) => Span::empty(),

src/parser/mod.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8058,16 +8058,32 @@ impl<'a> Parser<'a> {
80588058
}
80598059
} else if self.parse_keywords(&[Keyword::PRIMARY, Keyword::KEY]) {
80608060
let characteristics = self.parse_constraint_characteristics()?;
8061-
Ok(Some(ColumnOption::Unique {
8062-
is_primary: true,
8063-
characteristics,
8064-
}))
8061+
Ok(Some(
8062+
PrimaryKeyConstraint {
8063+
name: None,
8064+
index_name: None,
8065+
index_type: None,
8066+
columns: vec![column_ident.clone().into()],
8067+
index_options: vec![],
8068+
characteristics,
8069+
}
8070+
.into(),
8071+
))
80658072
} else if self.parse_keyword(Keyword::UNIQUE) {
80668073
let characteristics = self.parse_constraint_characteristics()?;
8067-
Ok(Some(ColumnOption::Unique {
8068-
is_primary: false,
8069-
characteristics,
8070-
}))
8074+
Ok(Some(
8075+
UniqueConstraint {
8076+
name: None,
8077+
index_name: None,
8078+
index_type_display: KeyOrIndexDisplay::None,
8079+
index_type: None,
8080+
columns: vec![column_ident.clone().into()],
8081+
index_options: vec![],
8082+
characteristics,
8083+
nulls_distinct: NullsDistinctOption::None,
8084+
}
8085+
.into(),
8086+
))
80718087
} else if self.parse_keyword(Keyword::REFERENCES) {
80728088
let foreign_table = self.parse_object_name(false)?;
80738089
// PostgreSQL allows omitting the column list and

tests/sqlparser_common.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3763,21 +3763,31 @@ fn parse_create_table() {
37633763
},
37643764
ColumnOptionDef {
37653765
name: Some("pkey".into()),
3766-
option: ColumnOption::Unique {
3767-
is_primary: true,
3768-
characteristics: None
3769-
},
3766+
option: ColumnOption::PrimaryKey(PrimaryKeyConstraint {
3767+
name: None,
3768+
index_name: None,
3769+
index_type: None,
3770+
columns: vec!["constrained".into()],
3771+
index_options: vec![],
3772+
characteristics: None,
3773+
}),
37703774
},
37713775
ColumnOptionDef {
37723776
name: None,
37733777
option: ColumnOption::NotNull,
37743778
},
37753779
ColumnOptionDef {
37763780
name: None,
3777-
option: ColumnOption::Unique {
3778-
is_primary: false,
3779-
characteristics: None
3780-
},
3781+
option: ColumnOption::Unique(UniqueConstraint {
3782+
name: None,
3783+
index_name: None,
3784+
index_type_display: KeyOrIndexDisplay::None,
3785+
index_type: None,
3786+
columns: vec!["constrained".into()],
3787+
index_options: vec![],
3788+
characteristics: None,
3789+
nulls_distinct: NullsDistinctOption::None,
3790+
}),
37813791
},
37823792
ColumnOptionDef {
37833793
name: None,
@@ -4102,10 +4112,16 @@ fn parse_create_table_column_constraint_characteristics() {
41024112
data_type: DataType::Int(None),
41034113
options: vec![ColumnOptionDef {
41044114
name: None,
4105-
option: ColumnOption::Unique {
4106-
is_primary: false,
4107-
characteristics: expected_value
4108-
}
4115+
option: ColumnOption::Unique(UniqueConstraint {
4116+
name: None,
4117+
index_name: None,
4118+
index_type_display: KeyOrIndexDisplay::None,
4119+
index_type: None,
4120+
columns: vec!["a".into()],
4121+
index_options: vec![],
4122+
characteristics: expected_value,
4123+
nulls_distinct: NullsDistinctOption::None,
4124+
})
41094125
}]
41104126
}],
41114127
"{message}"

tests/sqlparser_mysql.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -638,10 +638,14 @@ fn parse_create_table_auto_increment() {
638638
options: vec![
639639
ColumnOptionDef {
640640
name: None,
641-
option: ColumnOption::Unique {
642-
is_primary: true,
643-
characteristics: None
644-
},
641+
option: ColumnOption::PrimaryKey(PrimaryKeyConstraint {
642+
name: None,
643+
index_name: None,
644+
index_type: None,
645+
columns: vec!["bar".into()],
646+
index_options: vec![],
647+
characteristics: None,
648+
}),
645649
},
646650
ColumnOptionDef {
647651
name: None,
@@ -743,10 +747,14 @@ fn parse_create_table_primary_and_unique_key() {
743747
options: vec![
744748
ColumnOptionDef {
745749
name: None,
746-
option: ColumnOption::Unique {
747-
is_primary: true,
748-
characteristics: None
749-
},
750+
option: ColumnOption::PrimaryKey(PrimaryKeyConstraint {
751+
name: None,
752+
index_name: None,
753+
index_type: None,
754+
columns: vec!["id".into()],
755+
index_options: vec![],
756+
characteristics: None,
757+
}),
750758
},
751759
ColumnOptionDef {
752760
name: None,
@@ -1382,10 +1390,14 @@ fn parse_quote_identifiers() {
13821390
data_type: DataType::Int(None),
13831391
options: vec![ColumnOptionDef {
13841392
name: None,
1385-
option: ColumnOption::Unique {
1386-
is_primary: true,
1387-
characteristics: None
1388-
},
1393+
option: ColumnOption::PrimaryKey(PrimaryKeyConstraint {
1394+
name: None,
1395+
index_name: None,
1396+
index_type: None,
1397+
columns: vec![Ident::with_quote('`', "BEGIN").into()],
1398+
index_options: vec![],
1399+
characteristics: None,
1400+
}),
13891401
}],
13901402
}],
13911403
columns

tests/sqlparser_sqlite.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,14 @@ fn parse_create_table_auto_increment() {
217217
options: vec![
218218
ColumnOptionDef {
219219
name: None,
220-
option: ColumnOption::Unique {
221-
is_primary: true,
222-
characteristics: None
223-
},
220+
option: ColumnOption::PrimaryKey(PrimaryKeyConstraint {
221+
name: None,
222+
index_name: None,
223+
index_type: None,
224+
columns: vec!["bar".into()],
225+
index_options: vec![],
226+
characteristics: None,
227+
}),
224228
},
225229
ColumnOptionDef {
226230
name: None,
@@ -245,10 +249,14 @@ fn parse_create_table_primary_key_asc_desc() {
245249
options: vec![
246250
ColumnOptionDef {
247251
name: None,
248-
option: ColumnOption::Unique {
249-
is_primary: true,
252+
option: ColumnOption::PrimaryKey(PrimaryKeyConstraint {
253+
name: None,
254+
index_name: None,
255+
index_type: None,
256+
columns: vec!["bar".into()],
257+
index_options: vec![],
250258
characteristics: None,
251-
},
259+
}),
252260
},
253261
ColumnOptionDef {
254262
name: None,

0 commit comments

Comments
 (0)