From 8fec6a90bee80b13e0c71eebeeeb6f609854cce5 Mon Sep 17 00:00:00 2001 From: LucaCappelletti94 Date: Sun, 27 Apr 2025 18:25:16 +0200 Subject: [PATCH 1/5] Added support for CREATE DOMAIN and its test suite --- src/ast/mod.rs | 38 +++++++++++++ src/ast/spans.rs | 1 + src/keywords.rs | 1 + src/parser/mod.rs | 43 +++++++++++++++ tests/sqlparser_postgres.rs | 105 ++++++++++++++++++++++++++++++++++++ 5 files changed, 188 insertions(+) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 45924579b..fcb34a5c8 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3968,6 +3968,25 @@ pub enum Statement { owned_by: Option, }, /// ```sql + /// CREATE DOMAIN name [ AS ] data_type + /// [ COLLATE collation ] + /// [ DEFAULT expression ] + /// [ domain_constraint [ ... ] ] + /// + /// where domain_constraint is: + /// + /// [ CONSTRAINT constraint_name ] + /// { NOT NULL | NULL | CHECK (expression) } + /// ``` + /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createdomain.html) + CreateDomain { + name: ObjectName, + data_type: DataType, + collation: Option, + default: Option, + constraints: Vec, + }, + /// ```sql /// CREATE TYPE /// ``` CreateType { @@ -4513,6 +4532,25 @@ impl fmt::Display for Statement { Ok(()) } Statement::CreateFunction(create_function) => create_function.fmt(f), + Statement::CreateDomain { + name, + data_type, + collation, + default, + constraints, + } => { + write!(f, "CREATE DOMAIN {name} AS {data_type}")?; + if let Some(collation) = collation { + write!(f, " COLLATE {collation}")?; + } + if let Some(default) = default { + write!(f, " DEFAULT {default}")?; + } + if !constraints.is_empty() { + write!(f, " {}", display_separated(constraints, " "))?; + } + Ok(()) + } Statement::CreateTrigger { or_replace, is_constraint, diff --git a/src/ast/spans.rs b/src/ast/spans.rs index 93de5fff2..95245be84 100644 --- a/src/ast/spans.rs +++ b/src/ast/spans.rs @@ -479,6 +479,7 @@ impl Spanned for Statement { Statement::CreateSchema { .. } => Span::empty(), Statement::CreateDatabase { .. } => Span::empty(), Statement::CreateFunction { .. } => Span::empty(), + Statement::CreateDomain { .. } => Span::empty(), Statement::CreateTrigger { .. } => Span::empty(), Statement::DropTrigger { .. } => Span::empty(), Statement::CreateProcedure { .. } => Span::empty(), diff --git a/src/keywords.rs b/src/keywords.rs index 4eaad7ed2..a872911b3 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -286,6 +286,7 @@ define_keywords!( DISTRIBUTE, DIV, DO, + DOMAIN, DOUBLE, DOW, DOY, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 0546548af..3a57ee7ab 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -4555,6 +4555,8 @@ impl<'a> Parser<'a> { self.parse_create_external_table(or_replace) } else if self.parse_keyword(Keyword::FUNCTION) { self.parse_create_function(or_alter, or_replace, temporary) + } else if self.parse_keyword(Keyword::DOMAIN) { + self.parse_create_domain() } else if self.parse_keyword(Keyword::TRIGGER) { self.parse_create_trigger(or_replace, false) } else if self.parse_keywords(&[Keyword::CONSTRAINT, Keyword::TRIGGER]) { @@ -5894,6 +5896,47 @@ impl<'a> Parser<'a> { Ok(owner) } + /// ```sql + /// CREATE DOMAIN name [ AS ] data_type + /// [ COLLATE collation ] + /// [ DEFAULT expression ] + /// [ domain_constraint [ ... ] ] + /// + /// where domain_constraint is: + /// + /// [ CONSTRAINT constraint_name ] + /// { NOT NULL | NULL | CHECK (expression) } + /// ``` + /// + /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createdomain.html) + pub fn parse_create_domain(&mut self) -> Result { + let name = self.parse_object_name(false)?; + self.expect_keyword_is(Keyword::AS)?; + let data_type = self.parse_data_type()?; + let collation = if self.parse_keyword(Keyword::COLLATE) { + Some(self.parse_identifier()?) + } else { + None + }; + let default = if self.parse_keyword(Keyword::DEFAULT) { + Some(self.parse_expr()?) + } else { + None + }; + let mut constraints = Vec::new(); + while let Some(constraint) = self.parse_optional_table_constraint()? { + constraints.push(constraint); + } + + Ok(Statement::CreateDomain { + name, + data_type, + collation, + default, + constraints, + }) + } + /// ```sql /// CREATE POLICY name ON table_name [ AS { PERMISSIVE | RESTRICTIVE } ] /// [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ] diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 27fc7fa17..fab18e94f 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -5080,6 +5080,111 @@ fn test_escaped_string_literal() { } } +#[test] +fn parse_create_domain() { + let sql1 = "CREATE DOMAIN my_domain AS INTEGER CHECK (VALUE > 0)"; + let expected = Statement::CreateDomain { + name: ObjectName::from(vec![Ident::new("my_domain")]), + data_type: DataType::Integer(None), + collation: None, + default: None, + constraints: vec![TableConstraint::Check { + name: None, + expr: Box::new(Expr::BinaryOp { + left: Box::new(Expr::Identifier(Ident::new("VALUE"))), + op: BinaryOperator::Gt, + right: Box::new(Expr::Value(Value::Number("0".to_string(), false).into())), + }), + }], + }; + + assert_eq!(pg().verified_stmt(sql1), expected); +} + +#[test] +fn parse_create_domain_with_collation() { + let sql2 = "CREATE DOMAIN my_domain AS INTEGER COLLATE \"en_US\" CHECK (VALUE > 0)"; + let expected = Statement::CreateDomain { + name: ObjectName::from(vec![Ident::new("my_domain")]), + data_type: DataType::Integer(None), + collation: Some(Ident::with_quote('"', "en_US")), + default: None, + constraints: vec![TableConstraint::Check { + name: None, + expr: Box::new(Expr::BinaryOp { + left: Box::new(Expr::Identifier(Ident::new("VALUE"))), + op: BinaryOperator::Gt, + right: Box::new(Expr::Value(Value::Number("0".to_string(), false).into())), + }), + }], + }; + + assert_eq!(pg().verified_stmt(sql2), expected); +} + +#[test] +fn parse_create_domain_with_default() { + let sql3 = "CREATE DOMAIN my_domain AS INTEGER DEFAULT 1 CHECK (VALUE > 0)"; + let expected = Statement::CreateDomain { + name: ObjectName::from(vec![Ident::new("my_domain")]), + data_type: DataType::Integer(None), + collation: None, + default: Some(Expr::Value(Value::Number("1".to_string(), false).into())), + constraints: vec![TableConstraint::Check { + name: None, + expr: Box::new(Expr::BinaryOp { + left: Box::new(Expr::Identifier(Ident::new("VALUE"))), + op: BinaryOperator::Gt, + right: Box::new(Expr::Value(Value::Number("0".to_string(), false).into())), + }), + }], + }; + + assert_eq!(pg().verified_stmt(sql3), expected); +} + +#[test] +fn parse_create_domain_with_default_and_collation() { + let sql4 = "CREATE DOMAIN my_domain AS INTEGER COLLATE \"en_US\" DEFAULT 1 CHECK (VALUE > 0)"; + let expected = Statement::CreateDomain { + name: ObjectName::from(vec![Ident::new("my_domain")]), + data_type: DataType::Integer(None), + collation: Some(Ident::with_quote('"', "en_US")), + default: Some(Expr::Value(Value::Number("1".to_string(), false).into())), + constraints: vec![TableConstraint::Check { + name: None, + expr: Box::new(Expr::BinaryOp { + left: Box::new(Expr::Identifier(Ident::new("VALUE"))), + op: BinaryOperator::Gt, + right: Box::new(Expr::Value(Value::Number("0".to_string(), false).into())), + }), + }], + }; + + assert_eq!(pg().verified_stmt(sql4), expected); +} + +#[test] +fn parse_create_domain_with_named_constraint() { + let sql5 = "CREATE DOMAIN my_domain AS INTEGER CONSTRAINT my_constraint CHECK (VALUE > 0)"; + let expected = Statement::CreateDomain { + name: ObjectName::from(vec![Ident::new("my_domain")]), + data_type: DataType::Integer(None), + collation: None, + default: None, + constraints: vec![TableConstraint::Check { + name: Some(Ident::new("my_constraint")), + expr: Box::new(Expr::BinaryOp { + left: Box::new(Expr::Identifier(Ident::new("VALUE"))), + op: BinaryOperator::Gt, + right: Box::new(Expr::Value(Value::Number("0".to_string(), false).into())), + }), + }], + }; + + assert_eq!(pg().verified_stmt(sql5), expected); +} + #[test] fn parse_create_simple_before_insert_trigger() { let sql = "CREATE TRIGGER check_insert BEFORE INSERT ON accounts FOR EACH ROW EXECUTE FUNCTION check_account_insert"; From 2bd50b1b7f19cadf34488e2a3ed3c16d83ff3a39 Mon Sep 17 00:00:00 2001 From: LucaCappelletti94 Date: Sun, 27 Apr 2025 18:32:09 +0200 Subject: [PATCH 2/5] Replaced number creation with `test_utils::number` to support feature big number --- tests/sqlparser_postgres.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index fab18e94f..25614b056 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -5093,7 +5093,7 @@ fn parse_create_domain() { expr: Box::new(Expr::BinaryOp { left: Box::new(Expr::Identifier(Ident::new("VALUE"))), op: BinaryOperator::Gt, - right: Box::new(Expr::Value(Value::Number("0".to_string(), false).into())), + right: Box::new(Expr::Value(test_utils::number("0").into())), }), }], }; @@ -5114,7 +5114,7 @@ fn parse_create_domain_with_collation() { expr: Box::new(Expr::BinaryOp { left: Box::new(Expr::Identifier(Ident::new("VALUE"))), op: BinaryOperator::Gt, - right: Box::new(Expr::Value(Value::Number("0".to_string(), false).into())), + right: Box::new(Expr::Value(test_utils::number("0").into())), }), }], }; @@ -5129,13 +5129,13 @@ fn parse_create_domain_with_default() { name: ObjectName::from(vec![Ident::new("my_domain")]), data_type: DataType::Integer(None), collation: None, - default: Some(Expr::Value(Value::Number("1".to_string(), false).into())), + default: Some(Expr::Value(test_utils::number("1").into())), constraints: vec![TableConstraint::Check { name: None, expr: Box::new(Expr::BinaryOp { left: Box::new(Expr::Identifier(Ident::new("VALUE"))), op: BinaryOperator::Gt, - right: Box::new(Expr::Value(Value::Number("0".to_string(), false).into())), + right: Box::new(Expr::Value(test_utils::number("0").into())), }), }], }; @@ -5150,13 +5150,13 @@ fn parse_create_domain_with_default_and_collation() { name: ObjectName::from(vec![Ident::new("my_domain")]), data_type: DataType::Integer(None), collation: Some(Ident::with_quote('"', "en_US")), - default: Some(Expr::Value(Value::Number("1".to_string(), false).into())), + default: Some(Expr::Value(test_utils::number("1").into())), constraints: vec![TableConstraint::Check { name: None, expr: Box::new(Expr::BinaryOp { left: Box::new(Expr::Identifier(Ident::new("VALUE"))), op: BinaryOperator::Gt, - right: Box::new(Expr::Value(Value::Number("0".to_string(), false).into())), + right: Box::new(Expr::Value(test_utils::number("0").into())), }), }], }; @@ -5177,7 +5177,7 @@ fn parse_create_domain_with_named_constraint() { expr: Box::new(Expr::BinaryOp { left: Box::new(Expr::Identifier(Ident::new("VALUE"))), op: BinaryOperator::Gt, - right: Box::new(Expr::Value(Value::Number("0".to_string(), false).into())), + right: Box::new(Expr::Value(test_utils::number("0").into())), }), }], }; From dfc180b7f76c9b9dce46d9355ba4eaf4282ad830 Mon Sep 17 00:00:00 2001 From: LucaCappelletti94 Date: Wed, 30 Apr 2025 09:54:52 +0200 Subject: [PATCH 3/5] Refactored introducing struct CreateDomain --- src/ast/ddl.rs | 44 +++++++++++++++++++++++++++++++++++++ src/ast/mod.rs | 28 ++--------------------- src/parser/mod.rs | 4 ++-- tests/sqlparser_postgres.rs | 20 ++++++++--------- 4 files changed, 58 insertions(+), 38 deletions(-) diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index c1c113b32..bd1a485f5 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -2153,6 +2153,50 @@ impl fmt::Display for ClusteredBy { } } +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// ```sql +/// CREATE DOMAIN name [ AS ] data_type +/// [ COLLATE collation ] +/// [ DEFAULT expression ] +/// [ domain_constraint [ ... ] ] +/// +/// where domain_constraint is: +/// +/// [ CONSTRAINT constraint_name ] +/// { NOT NULL | NULL | CHECK (expression) } +/// ``` +/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createdomain.html) +pub struct CreateDomain { + /// The name of the domain to be created. + name: ObjectName, + /// The data type of the domain. + data_type: DataType, + /// The collation of the domain. + collation: Option, + /// The default value of the domain. + default: Option, + /// The constraints of the domain. + constraints: Vec, +} + +impl fmt::Display for CreateDomain { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "CREATE DOMAIN {name} AS {data_type}")?; + if let Some(collation) = collation { + write!(f, " COLLATE {collation}")?; + } + if let Some(default) = default { + write!(f, " DEFAULT {default}")?; + } + if !constraints.is_empty() { + write!(f, " {}", display_separated(constraints, " "))?; + } + Ok(()) + } +} + #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] diff --git a/src/ast/mod.rs b/src/ast/mod.rs index fcb34a5c8..576fda497 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3979,13 +3979,7 @@ pub enum Statement { /// { NOT NULL | NULL | CHECK (expression) } /// ``` /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createdomain.html) - CreateDomain { - name: ObjectName, - data_type: DataType, - collation: Option, - default: Option, - constraints: Vec, - }, + CreateDomain(CreateDomain), /// ```sql /// CREATE TYPE /// ``` @@ -4532,25 +4526,7 @@ impl fmt::Display for Statement { Ok(()) } Statement::CreateFunction(create_function) => create_function.fmt(f), - Statement::CreateDomain { - name, - data_type, - collation, - default, - constraints, - } => { - write!(f, "CREATE DOMAIN {name} AS {data_type}")?; - if let Some(collation) = collation { - write!(f, " COLLATE {collation}")?; - } - if let Some(default) = default { - write!(f, " DEFAULT {default}")?; - } - if !constraints.is_empty() { - write!(f, " {}", display_separated(constraints, " "))?; - } - Ok(()) - } + Statement::CreateDomain(create_domain) => create_domain.fmt(f), Statement::CreateTrigger { or_replace, is_constraint, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 3a57ee7ab..44c86231a 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -5928,13 +5928,13 @@ impl<'a> Parser<'a> { constraints.push(constraint); } - Ok(Statement::CreateDomain { + Ok(Statement::CreateDomain(CreateDomain { name, data_type, collation, default, constraints, - }) + })) } /// ```sql diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 25614b056..304acb955 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -5083,7 +5083,7 @@ fn test_escaped_string_literal() { #[test] fn parse_create_domain() { let sql1 = "CREATE DOMAIN my_domain AS INTEGER CHECK (VALUE > 0)"; - let expected = Statement::CreateDomain { + let expected = Statement::CreateDomain(CreateDomain { name: ObjectName::from(vec![Ident::new("my_domain")]), data_type: DataType::Integer(None), collation: None, @@ -5096,7 +5096,7 @@ fn parse_create_domain() { right: Box::new(Expr::Value(test_utils::number("0").into())), }), }], - }; + }); assert_eq!(pg().verified_stmt(sql1), expected); } @@ -5104,7 +5104,7 @@ fn parse_create_domain() { #[test] fn parse_create_domain_with_collation() { let sql2 = "CREATE DOMAIN my_domain AS INTEGER COLLATE \"en_US\" CHECK (VALUE > 0)"; - let expected = Statement::CreateDomain { + let expected = Statement::CreateDomain(CreateDomain { name: ObjectName::from(vec![Ident::new("my_domain")]), data_type: DataType::Integer(None), collation: Some(Ident::with_quote('"', "en_US")), @@ -5117,7 +5117,7 @@ fn parse_create_domain_with_collation() { right: Box::new(Expr::Value(test_utils::number("0").into())), }), }], - }; + }); assert_eq!(pg().verified_stmt(sql2), expected); } @@ -5125,7 +5125,7 @@ fn parse_create_domain_with_collation() { #[test] fn parse_create_domain_with_default() { let sql3 = "CREATE DOMAIN my_domain AS INTEGER DEFAULT 1 CHECK (VALUE > 0)"; - let expected = Statement::CreateDomain { + let expected = Statement::CreateDomain(CreateDomain { name: ObjectName::from(vec![Ident::new("my_domain")]), data_type: DataType::Integer(None), collation: None, @@ -5138,7 +5138,7 @@ fn parse_create_domain_with_default() { right: Box::new(Expr::Value(test_utils::number("0").into())), }), }], - }; + }); assert_eq!(pg().verified_stmt(sql3), expected); } @@ -5146,7 +5146,7 @@ fn parse_create_domain_with_default() { #[test] fn parse_create_domain_with_default_and_collation() { let sql4 = "CREATE DOMAIN my_domain AS INTEGER COLLATE \"en_US\" DEFAULT 1 CHECK (VALUE > 0)"; - let expected = Statement::CreateDomain { + let expected = Statement::CreateDomain(CreateDomain { name: ObjectName::from(vec![Ident::new("my_domain")]), data_type: DataType::Integer(None), collation: Some(Ident::with_quote('"', "en_US")), @@ -5159,7 +5159,7 @@ fn parse_create_domain_with_default_and_collation() { right: Box::new(Expr::Value(test_utils::number("0").into())), }), }], - }; + }); assert_eq!(pg().verified_stmt(sql4), expected); } @@ -5167,7 +5167,7 @@ fn parse_create_domain_with_default_and_collation() { #[test] fn parse_create_domain_with_named_constraint() { let sql5 = "CREATE DOMAIN my_domain AS INTEGER CONSTRAINT my_constraint CHECK (VALUE > 0)"; - let expected = Statement::CreateDomain { + let expected = Statement::CreateDomain(CreateDomain { name: ObjectName::from(vec![Ident::new("my_domain")]), data_type: DataType::Integer(None), collation: None, @@ -5180,7 +5180,7 @@ fn parse_create_domain_with_named_constraint() { right: Box::new(Expr::Value(test_utils::number("0").into())), }), }], - }; + }); assert_eq!(pg().verified_stmt(sql5), expected); } From d4868ba1316419ef3dc79942eaf1eaf662be359c Mon Sep 17 00:00:00 2001 From: LucaCappelletti94 Date: Wed, 30 Apr 2025 10:01:41 +0200 Subject: [PATCH 4/5] Finished implementation of CreateDomain --- src/ast/ddl.rs | 25 +++++++++++++++---------- src/ast/mod.rs | 12 ++++++------ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index bd1a485f5..a457a0655 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -2170,28 +2170,33 @@ impl fmt::Display for ClusteredBy { /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createdomain.html) pub struct CreateDomain { /// The name of the domain to be created. - name: ObjectName, + pub name: ObjectName, /// The data type of the domain. - data_type: DataType, + pub data_type: DataType, /// The collation of the domain. - collation: Option, + pub collation: Option, /// The default value of the domain. - default: Option, + pub default: Option, /// The constraints of the domain. - constraints: Vec, + pub constraints: Vec, } impl fmt::Display for CreateDomain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "CREATE DOMAIN {name} AS {data_type}")?; - if let Some(collation) = collation { + write!( + f, + "CREATE DOMAIN {name} AS {data_type}", + name = self.name, + data_type = self.data_type + )?; + if let Some(collation) = &self.collation { write!(f, " COLLATE {collation}")?; } - if let Some(default) = default { + if let Some(default) = &self.default { write!(f, " DEFAULT {default}")?; } - if !constraints.is_empty() { - write!(f, " {}", display_separated(constraints, " "))?; + if !self.constraints.is_empty() { + write!(f, " {}", display_separated(&self.constraints, " "))?; } Ok(()) } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 576fda497..2e7b488d5 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -55,12 +55,12 @@ pub use self::ddl::{ AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnPolicy, ColumnPolicyProperty, - ConstraintCharacteristics, CreateConnector, CreateFunction, Deduplicate, DeferrableInitial, - DropBehavior, GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty, - IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexOption, - IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition, ProcedureParam, - ReferentialAction, TableConstraint, TagsColumnOption, UserDefinedTypeCompositeAttributeDef, - UserDefinedTypeRepresentation, ViewColumnDef, + ConstraintCharacteristics, CreateConnector, CreateDomain, CreateFunction, Deduplicate, + DeferrableInitial, DropBehavior, GeneratedAs, GeneratedExpressionMode, IdentityParameters, + IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, + IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition, + ProcedureParam, ReferentialAction, TableConstraint, TagsColumnOption, + UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef, }; pub use self::dml::{CreateIndex, CreateTable, Delete, IndexColumn, Insert}; pub use self::operator::{BinaryOperator, UnaryOperator}; From b82f111a27bb4b5f460d9e0512d774ca23228264 Mon Sep 17 00:00:00 2001 From: LucaCappelletti94 Date: Sat, 3 May 2025 17:56:59 +0200 Subject: [PATCH 5/5] Refactored requests from PR --- src/ast/mod.rs | 13 +------------ src/parser/mod.rs | 16 ++-------------- tests/sqlparser_postgres.rs | 12 ------------ 3 files changed, 3 insertions(+), 38 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 2e7b488d5..5a7e0edf7 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3967,18 +3967,7 @@ pub enum Statement { sequence_options: Vec, owned_by: Option, }, - /// ```sql - /// CREATE DOMAIN name [ AS ] data_type - /// [ COLLATE collation ] - /// [ DEFAULT expression ] - /// [ domain_constraint [ ... ] ] - /// - /// where domain_constraint is: - /// - /// [ CONSTRAINT constraint_name ] - /// { NOT NULL | NULL | CHECK (expression) } - /// ``` - /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createdomain.html) + /// A `CREATE DOMAIN` statement. CreateDomain(CreateDomain), /// ```sql /// CREATE TYPE diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 44c86231a..b6a79ae6d 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -5896,20 +5896,8 @@ impl<'a> Parser<'a> { Ok(owner) } - /// ```sql - /// CREATE DOMAIN name [ AS ] data_type - /// [ COLLATE collation ] - /// [ DEFAULT expression ] - /// [ domain_constraint [ ... ] ] - /// - /// where domain_constraint is: - /// - /// [ CONSTRAINT constraint_name ] - /// { NOT NULL | NULL | CHECK (expression) } - /// ``` - /// - /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createdomain.html) - pub fn parse_create_domain(&mut self) -> Result { + /// Parses a [Statement::CreateDomain] statement. + fn parse_create_domain(&mut self) -> Result { let name = self.parse_object_name(false)?; self.expect_keyword_is(Keyword::AS)?; let data_type = self.parse_data_type()?; diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 304acb955..910e358da 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -5099,10 +5099,7 @@ fn parse_create_domain() { }); assert_eq!(pg().verified_stmt(sql1), expected); -} -#[test] -fn parse_create_domain_with_collation() { let sql2 = "CREATE DOMAIN my_domain AS INTEGER COLLATE \"en_US\" CHECK (VALUE > 0)"; let expected = Statement::CreateDomain(CreateDomain { name: ObjectName::from(vec![Ident::new("my_domain")]), @@ -5120,10 +5117,7 @@ fn parse_create_domain_with_collation() { }); assert_eq!(pg().verified_stmt(sql2), expected); -} -#[test] -fn parse_create_domain_with_default() { let sql3 = "CREATE DOMAIN my_domain AS INTEGER DEFAULT 1 CHECK (VALUE > 0)"; let expected = Statement::CreateDomain(CreateDomain { name: ObjectName::from(vec![Ident::new("my_domain")]), @@ -5141,10 +5135,7 @@ fn parse_create_domain_with_default() { }); assert_eq!(pg().verified_stmt(sql3), expected); -} -#[test] -fn parse_create_domain_with_default_and_collation() { let sql4 = "CREATE DOMAIN my_domain AS INTEGER COLLATE \"en_US\" DEFAULT 1 CHECK (VALUE > 0)"; let expected = Statement::CreateDomain(CreateDomain { name: ObjectName::from(vec![Ident::new("my_domain")]), @@ -5162,10 +5153,7 @@ fn parse_create_domain_with_default_and_collation() { }); assert_eq!(pg().verified_stmt(sql4), expected); -} -#[test] -fn parse_create_domain_with_named_constraint() { let sql5 = "CREATE DOMAIN my_domain AS INTEGER CONSTRAINT my_constraint CHECK (VALUE > 0)"; let expected = Statement::CreateDomain(CreateDomain { name: ObjectName::from(vec![Ident::new("my_domain")]),