Skip to content

Commit 5916475

Browse files
committed
Add support for additional ConstraintCharacteristics::Deferrable, ConstraintCharacteristics::Initially, ConstraintCharacteristics::Deferred,
1 parent 6a89a5c commit 5916475

File tree

9 files changed

+254
-63
lines changed

9 files changed

+254
-63
lines changed

.config/nextest.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[profile.dev]

.run/nextest [sqlparser-rs].run.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
<component name="ProjectRunConfigurationManager">
22
<configuration default="false" name="nextest [sqlparser-rs]" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
3+
<option name="buildProfile" value="Dev" />
34
<option name="command" value="nextest run --no-fail-fast" />
45
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
6+
<envs />
57
<option name="emulateTerminal" value="false" />
68
<option name="channel" value="DEFAULT" />
79
<option name="requiredFeatures" value="true" />
810
<option name="allFeatures" value="false" />
911
<option name="withSudo" value="false" />
1012
<option name="buildTarget" value="REMOTE" />
1113
<option name="backtrace" value="SHORT" />
12-
<envs />
1314
<option name="isRedirectInput" value="false" />
1415
<option name="redirectInputPath" value="" />
1516
<method v="2">

src/ast/ddl.rs

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ pub enum TableConstraint {
298298
columns: Vec<WithSpan<Ident>>,
299299
/// Whether this is a `PRIMARY KEY` or just a `UNIQUE` constraint
300300
is_primary: bool,
301-
constraint_properties: Vec<ConstraintProperty>,
301+
characteristics: Vec<ConstraintCharacteristics>,
302302
},
303303
/// A referential integrity constraint (`[ CONSTRAINT <name> ] FOREIGN KEY (<columns>)
304304
/// REFERENCES <foreign_table> (<referred_columns>)
@@ -312,7 +312,7 @@ pub enum TableConstraint {
312312
referred_columns: Vec<WithSpan<Ident>>,
313313
on_delete: Option<ReferentialAction>,
314314
on_update: Option<ReferentialAction>,
315-
constraint_properties: Vec<ConstraintProperty>,
315+
characteristics: Vec<ConstraintCharacteristics>,
316316
},
317317
/// `[ CONSTRAINT <name> ] CHECK (<expr>)`
318318
Check {
@@ -375,7 +375,7 @@ impl fmt::Display for TableConstraint {
375375
name,
376376
columns,
377377
is_primary,
378-
constraint_properties,
378+
characteristics,
379379
} => {
380380
write!(
381381
f,
@@ -384,8 +384,8 @@ impl fmt::Display for TableConstraint {
384384
if *is_primary { "PRIMARY KEY" } else { "UNIQUE" },
385385
display_comma_separated(columns),
386386
)?;
387-
if !constraint_properties.is_empty() {
388-
write!(f, " {}", display_separated(constraint_properties, " "))?;
387+
if !characteristics.is_empty() {
388+
write!(f, " {}", display_separated(characteristics, " "))?;
389389
}
390390
Ok(())
391391
}
@@ -396,7 +396,7 @@ impl fmt::Display for TableConstraint {
396396
referred_columns,
397397
on_delete,
398398
on_update,
399-
constraint_properties,
399+
characteristics,
400400
} => {
401401
write!(
402402
f,
@@ -412,8 +412,8 @@ impl fmt::Display for TableConstraint {
412412
if let Some(action) = on_update {
413413
write!(f, " ON UPDATE {action}")?;
414414
}
415-
if !constraint_properties.is_empty() {
416-
write!(f, " {}", display_separated(constraint_properties, " "))?;
415+
if !characteristics.is_empty() {
416+
write!(f, " {}", display_separated(characteristics, " "))?;
417417
}
418418
Ok(())
419419
}
@@ -663,6 +663,7 @@ pub enum ColumnOption {
663663
/// `{ PRIMARY KEY | UNIQUE }`
664664
Unique {
665665
is_primary: bool,
666+
characteristics: Vec<ConstraintCharacteristics>,
666667
},
667668
/// A referential integrity constraint (`[FOREIGN KEY REFERENCES
668669
/// <foreign_table> (<referred_columns>)
@@ -674,6 +675,7 @@ pub enum ColumnOption {
674675
referred_columns: Vec<WithSpan<Ident>>,
675676
on_delete: Option<ReferentialAction>,
676677
on_update: Option<ReferentialAction>,
678+
characteristics: Vec<ConstraintCharacteristics>,
677679
},
678680
/// `CHECK (<expr>)`
679681
Check(Expr),
@@ -700,14 +702,22 @@ impl fmt::Display for ColumnOption {
700702
Null => write!(f, "NULL"),
701703
NotNull => write!(f, "NOT NULL"),
702704
Default(expr) => write!(f, "DEFAULT {expr}"),
703-
Unique { is_primary } => {
704-
write!(f, "{}", if *is_primary { "PRIMARY KEY" } else { "UNIQUE" })
705+
Unique {
706+
is_primary,
707+
characteristics,
708+
} => {
709+
write!(f, "{}", if *is_primary { "PRIMARY KEY" } else { "UNIQUE" })?;
710+
if !characteristics.is_empty() {
711+
write!(f, " {}", display_separated(characteristics, " "))?;
712+
}
713+
Ok(())
705714
}
706715
ForeignKey {
707716
foreign_table,
708717
referred_columns,
709718
on_delete,
710719
on_update,
720+
characteristics,
711721
} => {
712722
write!(f, "REFERENCES {foreign_table}")?;
713723
if !referred_columns.is_empty() {
@@ -719,6 +729,9 @@ impl fmt::Display for ColumnOption {
719729
if let Some(action) = on_update {
720730
write!(f, " ON UPDATE {action}")?;
721731
}
732+
if !characteristics.is_empty() {
733+
write!(f, " {}", display_separated(characteristics, " "))?;
734+
}
722735
Ok(())
723736
}
724737
Check(expr) => write!(f, "CHECK ({expr})"),
@@ -826,22 +839,32 @@ impl fmt::Display for ReferentialAction {
826839
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
827840
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
828841
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
829-
pub enum ConstraintProperty {
842+
pub enum ConstraintCharacteristics {
830843
Validate,
831844
NoValidate,
832845
Rely,
833846
NoRely,
834847
NotEnforced,
848+
NotDeferrable,
849+
Deferrable,
850+
Initially,
851+
Deferred,
852+
Immediate,
835853
}
836854

837-
impl fmt::Display for ConstraintProperty {
855+
impl fmt::Display for ConstraintCharacteristics {
838856
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
839857
f.write_str(match self {
840-
ConstraintProperty::Validate => "VALIDATE",
841-
ConstraintProperty::NoValidate => "NOVALIDATE",
842-
ConstraintProperty::Rely => "RELY",
843-
ConstraintProperty::NoRely => "NORELY",
844-
ConstraintProperty::NotEnforced => "NOT ENFORCED",
858+
ConstraintCharacteristics::Validate => "VALIDATE",
859+
ConstraintCharacteristics::NoValidate => "NOVALIDATE",
860+
ConstraintCharacteristics::Rely => "RELY",
861+
ConstraintCharacteristics::NoRely => "NORELY",
862+
ConstraintCharacteristics::NotEnforced => "NOT ENFORCED",
863+
ConstraintCharacteristics::NotDeferrable => "NOT DEFERRABLE",
864+
ConstraintCharacteristics::Deferrable => "DEFERRABLE",
865+
ConstraintCharacteristics::Initially => "INITIALLY",
866+
ConstraintCharacteristics::Deferred => "DEFERRED",
867+
ConstraintCharacteristics::Immediate => "IMMEDIATE",
845868
})
846869
}
847870
}

src/ast/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ pub use self::data_type::{
3434
pub use self::dcl::{AlterRoleOperation, ResetConfig, RoleOption, SetConfigValue};
3535
pub use self::ddl::{
3636
AlterColumnOperation, AlterIndexOperation, AlterTableOperation, ColumnDef, ColumnLocation,
37-
ColumnOption, ColumnOptionDef, ConstraintProperty, GeneratedAs, IndexType, KeyOrIndexDisplay,
38-
ProcedureParam, ReferentialAction, TableConstraint, UserDefinedTypeCompositeAttributeDef,
39-
UserDefinedTypeRepresentation,
37+
ColumnOption, ColumnOptionDef, ConstraintCharacteristics, GeneratedAs, IndexType,
38+
KeyOrIndexDisplay, ProcedureParam, ReferentialAction, TableConstraint,
39+
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation,
4040
};
4141
pub use self::operator::{BinaryOperator, UnaryOperator};
4242
pub use self::query::{
@@ -4427,6 +4427,7 @@ pub enum HiveDistributionStyle {
44274427
PARTITIONED {
44284428
columns: Vec<ColumnDef>,
44294429
},
4430+
#[allow(non_camel_case_types)]
44304431
PARTITIONED_NAMES {
44314432
columns: Vec<WithSpan<Ident>>,
44324433
},

src/keywords.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ define_keywords!(
211211
DECIMAL,
212212
DECLARE,
213213
DEFAULT,
214+
DEFERRABLE,
215+
DEFERRED,
214216
DELETE,
215217
DELIMITED,
216218
DELIMITER,
@@ -327,13 +329,15 @@ define_keywords!(
327329
IF,
328330
IGNORE,
329331
ILIKE,
332+
IMMEDIATE,
330333
IMMUTABLE,
331334
IN,
332335
INCLUDE,
333336
INCREMENT,
334337
INDEX,
335338
INDICATOR,
336339
INHERIT,
340+
INITIALLY,
337341
INNER,
338342
INOUT,
339343
INPUTFORMAT,

src/parser/mod.rs

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4575,9 +4575,17 @@ impl<'a> Parser<'a> {
45754575
} else if self.parse_keyword(Keyword::DEFAULT) {
45764576
Ok(Some(ColumnOption::Default(self.parse_expr()?)))
45774577
} else if self.parse_keywords(&[Keyword::PRIMARY, Keyword::KEY]) {
4578-
Ok(Some(ColumnOption::Unique { is_primary: true }))
4578+
let characteristics = self.parse_constraint_characteristics()?;
4579+
Ok(Some(ColumnOption::Unique {
4580+
is_primary: true,
4581+
characteristics,
4582+
}))
45794583
} else if self.parse_keyword(Keyword::UNIQUE) {
4580-
Ok(Some(ColumnOption::Unique { is_primary: false }))
4584+
let characteristics = self.parse_constraint_characteristics()?;
4585+
Ok(Some(ColumnOption::Unique {
4586+
is_primary: false,
4587+
characteristics,
4588+
}))
45814589
} else if self.parse_keyword(Keyword::REFERENCES) {
45824590
let foreign_table = self.parse_object_name(false)?;
45834591
// PostgreSQL allows omitting the column list and
@@ -4596,11 +4604,13 @@ impl<'a> Parser<'a> {
45964604
break;
45974605
}
45984606
}
4607+
let characteristics = self.parse_constraint_characteristics()?;
45994608
Ok(Some(ColumnOption::ForeignKey {
46004609
foreign_table,
46014610
referred_columns,
46024611
on_delete,
46034612
on_update,
4613+
characteristics,
46044614
}))
46054615
} else if self.parse_keyword(Keyword::CHECK) {
46064616
self.expect_token(&Token::LParen)?;
@@ -4699,33 +4709,36 @@ impl<'a> Parser<'a> {
46994709
}
47004710
}
47014711

4702-
pub fn parse_constraint_properties(&mut self) -> Result<Vec<ConstraintProperty>, ParserError> {
4703-
let mut constraint_properties = Vec::new();
4704-
if dialect_of!(self is SnowflakeDialect) {
4705-
loop {
4706-
if self.parse_keyword(Keyword::RELY) {
4707-
constraint_properties.push(ConstraintProperty::Rely);
4708-
} else if self.parse_keyword(Keyword::NORELY) {
4709-
constraint_properties.push(ConstraintProperty::NoRely);
4710-
} else if self.parse_keyword(Keyword::VALIDATE) {
4711-
constraint_properties.push(ConstraintProperty::Validate);
4712-
} else if self.parse_keyword(Keyword::NOVALIDATE) {
4713-
constraint_properties.push(ConstraintProperty::NoValidate);
4714-
} else {
4715-
break;
4716-
}
4717-
}
4718-
}
4719-
if dialect_of!(self is BigQueryDialect) {
4720-
loop {
4721-
if self.parse_keywords(&[Keyword::NOT, Keyword::ENFORCED]) {
4722-
constraint_properties.push(ConstraintProperty::NotEnforced)
4723-
} else {
4724-
break;
4725-
}
4712+
pub fn parse_constraint_characteristics(
4713+
&mut self,
4714+
) -> Result<Vec<ConstraintCharacteristics>, ParserError> {
4715+
let mut characteristics = Vec::new();
4716+
loop {
4717+
if self.parse_keyword(Keyword::RELY) {
4718+
characteristics.push(ConstraintCharacteristics::Rely);
4719+
} else if self.parse_keyword(Keyword::NORELY) {
4720+
characteristics.push(ConstraintCharacteristics::NoRely);
4721+
} else if self.parse_keyword(Keyword::VALIDATE) {
4722+
characteristics.push(ConstraintCharacteristics::Validate);
4723+
} else if self.parse_keyword(Keyword::NOVALIDATE) {
4724+
characteristics.push(ConstraintCharacteristics::NoValidate);
4725+
} else if self.parse_keywords(&[Keyword::NOT, Keyword::ENFORCED]) {
4726+
characteristics.push(ConstraintCharacteristics::NotEnforced)
4727+
} else if self.parse_keywords(&[Keyword::NOT, Keyword::DEFERRABLE]) {
4728+
characteristics.push(ConstraintCharacteristics::NotDeferrable)
4729+
} else if self.parse_keyword(Keyword::DEFERRABLE) {
4730+
characteristics.push(ConstraintCharacteristics::Deferrable);
4731+
} else if self.parse_keyword(Keyword::INITIALLY) {
4732+
characteristics.push(ConstraintCharacteristics::Initially);
4733+
} else if self.parse_keyword(Keyword::DEFERRED) {
4734+
characteristics.push(ConstraintCharacteristics::Deferred);
4735+
} else if self.parse_keyword(Keyword::IMMEDIATE) {
4736+
characteristics.push(ConstraintCharacteristics::Immediate);
4737+
} else {
4738+
break;
47264739
}
47274740
}
4728-
Ok(constraint_properties)
4741+
Ok(characteristics)
47294742
}
47304743

47314744
pub fn parse_optional_table_constraint(
@@ -4752,12 +4765,12 @@ impl<'a> Parser<'a> {
47524765
.or(name);
47534766

47544767
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
4755-
let constraint_properties = self.parse_constraint_properties()?;
4768+
let constraint_properties = self.parse_constraint_characteristics()?;
47564769
Ok(Some(TableConstraint::Unique {
47574770
name,
47584771
columns,
47594772
is_primary,
4760-
constraint_properties,
4773+
characteristics: constraint_properties,
47614774
}))
47624775
}
47634776
Token::Word(w) if w.keyword == Keyword::FOREIGN => {
@@ -4779,15 +4792,15 @@ impl<'a> Parser<'a> {
47794792
break;
47804793
}
47814794
}
4782-
let constraint_properties = self.parse_constraint_properties()?;
4795+
let constraint_properties = self.parse_constraint_characteristics()?;
47834796
Ok(Some(TableConstraint::ForeignKey {
47844797
name,
47854798
columns,
47864799
foreign_table,
47874800
referred_columns,
47884801
on_delete,
47894802
on_update,
4790-
constraint_properties,
4803+
characteristics: constraint_properties,
47914804
}))
47924805
}
47934806
Token::Word(w) if w.keyword == Keyword::CHECK => {

0 commit comments

Comments
 (0)