Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
7phs committed Oct 14, 2024
1 parent 96ec5b1 commit 01dc886
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 127 deletions.
155 changes: 102 additions & 53 deletions src/ast/ddl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1096,7 +1096,7 @@ impl fmt::Display for ColumnOptionDef {
}
}

/// Identity is a column option for defining an identity or autoincrement column in a creating table statement.
/// Identity is a column option for defining an identity or autoincrement column in a `CREATE TABLE` statement.
/// Syntax
/// ```sql
/// { IDENTITY | AUTOINCREMENT } [ (seed , increment) | START num INCREMENT num ] [ ORDER | NOORDER ]
Expand All @@ -1106,17 +1106,53 @@ impl fmt::Display for ColumnOptionDef {
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum Identity {
pub enum IdentityPropertyKind {
/// An identity property declared via the `AUTOINCREMENT` key word
/// Example:
/// ```sql
/// AUTOINCREMENT(100, 1) NOORDER
/// AUTOINCREMENT START 100 INCREMENT 1 ORDER
/// ```
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
Autoincrement(IdentityProperty),
/// An identity property declared via the `IDENTITY` key word
/// Example, [MS SQL Server] or [Snowflake]:
/// ```sql
/// IDENTITY(100, 1)
/// ```
/// [Snowflake]
/// ```sql
/// IDENTITY(100, 1) ORDER
/// IDENTITY START 100 INCREMENT 1 NOORDER
/// ```
/// [MS SQL Server]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
Identity(IdentityProperty),
}

impl fmt::Display for IdentityPropertyKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (command, property) = match self {
IdentityPropertyKind::Identity(property) => ("IDENTITY", property),
IdentityPropertyKind::Autoincrement(property) => ("AUTOINCREMENT", property),
};
write!(f, "{command}")?;
if let Some(parameters) = &property.parameters {
write!(f, "{parameters}")?;
}
if let Some(order) = &property.order {
write!(f, "{order}")?;
}
Ok(())
}
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct IdentityProperty {
pub parameters: Option<IdentityFormat>,
pub order: Option<IdentityOrder>,
pub parameters: Option<IdentityPropertyFormatKind>,
pub order: Option<IdentityPropertyOrder>,
}

/// A format of parameters of identity column.
Expand All @@ -1136,11 +1172,40 @@ pub struct IdentityProperty {
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum IdentityFormat {
pub enum IdentityPropertyFormatKind {
/// A parameters of identity column declared like parameters of function call
/// Example:
/// ```sql
/// (100, 1)
/// ```
/// [MS SQL Server]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
FunctionCall(IdentityParameters),
/// A parameters of identity column declared with keywords `START` and `INCREMENT`
/// Example:
/// ```sql
/// START 100 INCREMENT 1
/// ```
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
StartAndIncrement(IdentityParameters),
}

impl fmt::Display for IdentityPropertyFormatKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
IdentityPropertyFormatKind::FunctionCall(parameters) => {
write!(f, "({}, {})", parameters.seed, parameters.increment)
}
IdentityPropertyFormatKind::StartAndIncrement(parameters) => {
write!(
f,
" START {} INCREMENT {}",
parameters.seed, parameters.increment
)
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
Expand All @@ -1149,53 +1214,25 @@ pub struct IdentityParameters {
pub increment: Expr,
}

/// The identity column option specifies how values are generated for the auto-incremented column, either in increasing or decreasing order.
/// Syntax
/// ```sql
/// ORDER | NOORDER
/// ```
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum IdentityOrder {
pub enum IdentityPropertyOrder {
Order,
NoOrder,
}

impl fmt::Display for Identity {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (command, property) = match self {
Identity::Identity(property) => ("IDENTITY", property),
Identity::Autoincrement(property) => ("AUTOINCREMENT", property),
};
write!(f, "{command}")?;
if let Some(parameters) = &property.parameters {
write!(f, "{parameters}")?;
}
if let Some(order) = &property.order {
write!(f, "{order}")?;
}
Ok(())
}
}

impl fmt::Display for IdentityFormat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
IdentityFormat::FunctionCall(parameters) => {
write!(f, "({}, {})", parameters.seed, parameters.increment)
}
IdentityFormat::StartAndIncrement(parameters) => {
write!(
f,
" START {} INCREMENT {}",
parameters.seed, parameters.increment
)
}
}
}
}

impl fmt::Display for IdentityOrder {
impl fmt::Display for IdentityPropertyOrder {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
IdentityOrder::Order => write!(f, " ORDER"),
IdentityOrder::NoOrder => write!(f, " NOORDER"),
IdentityPropertyOrder::Order => write!(f, " ORDER"),
IdentityPropertyOrder::NoOrder => write!(f, " NOORDER"),
}
}
}
Expand All @@ -1215,15 +1252,6 @@ pub enum ColumnPolicy {
ProjectionPolicy(ColumnPolicyProperty),
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct ColumnPolicyProperty {
pub with: bool,
pub policy_name: Ident,
pub using_columns: Option<Vec<Ident>>,
}

impl fmt::Display for ColumnPolicy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (command, property) = match self {
Expand All @@ -1241,6 +1269,21 @@ impl fmt::Display for ColumnPolicy {
}
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct ColumnPolicyProperty {
/// This flag indicates that the column policy option is declared using the `WITH` prefix.
/// Example
/// ```sql
/// WITH PROJECTION POLICY sample_policy
/// ```
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
pub with: bool,
pub policy_name: Ident,
pub using_columns: Option<Vec<Ident>>,
}

/// Tags option of column
/// Syntax
/// ```sql
Expand All @@ -1251,6 +1294,12 @@ impl fmt::Display for ColumnPolicy {
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct TagsColumnOption {
/// This flag indicates that the tags option is declared using the `WITH` prefix.
/// Example:
/// ```sql
/// WITH TAG (A = 'Tag A')
/// ```
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
pub with: bool,
pub tags: Vec<Tag>,
}
Expand Down Expand Up @@ -1342,7 +1391,7 @@ pub enum ColumnOption {
/// ```
/// [MS SQL Server]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
Identity(Identity),
Identity(IdentityPropertyKind),
/// SQLite specific: ON CONFLICT option on column definition
/// <https://www.sqlite.org/lang_conflict.html>
OnConflict(Keyword),
Expand Down
8 changes: 4 additions & 4 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ pub use self::ddl::{
AlterColumnOperation, AlterIndexOperation, AlterPolicyOperation, AlterTableOperation,
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnPolicy, ColumnPolicyProperty,
ConstraintCharacteristics, Deduplicate, DeferrableInitial, GeneratedAs,
GeneratedExpressionMode, Identity, IdentityFormat, IdentityOrder, IdentityParameters,
IdentityProperty, IndexOption, IndexType, KeyOrIndexDisplay, Owner, Partition, ProcedureParam,
ReferentialAction, TableConstraint, TagsColumnOption, UserDefinedTypeCompositeAttributeDef,
UserDefinedTypeRepresentation, ViewColumnDef,
GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
IdentityPropertyKind, IdentityPropertyOrder, IndexOption, IndexType, KeyOrIndexDisplay, Owner,
Partition, ProcedureParam, ReferentialAction, TableConstraint, TagsColumnOption,
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef,
};
pub use self::dml::{CreateIndex, CreateTable, Delete, Insert};
pub use self::operator::{BinaryOperator, UnaryOperator};
Expand Down
51 changes: 33 additions & 18 deletions src/dialect/snowflake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ use crate::ast::helpers::stmt_data_loading::{
StageParamsObject,
};
use crate::ast::{
ColumnOption, ColumnPolicy, ColumnPolicyProperty, Ident, Identity, IdentityFormat,
IdentityOrder, IdentityParameters, IdentityProperty, ObjectName, RowAccessPolicy, Statement,
WrappedCollection,
ColumnOption, ColumnPolicy, ColumnPolicyProperty, Ident, IdentityParameters, IdentityProperty,
IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, ObjectName,
RowAccessPolicy, Statement, TagsColumnOption, WrappedCollection,
};
use crate::dialect::{Dialect, Precedence};
use crate::keywords::Keyword;
Expand Down Expand Up @@ -162,13 +162,14 @@ impl Dialect for SnowflakeDialect {
if parser.parse_keyword(Keyword::IDENTITY) {
Some(
parse_identity_property(parser)
.map(|p| Some(ColumnOption::Identity(Identity::Identity(p)))),
.map(|p| Some(ColumnOption::Identity(IdentityPropertyKind::Identity(p)))),
)
} else if parser.parse_keyword(Keyword::AUTOINCREMENT) {
Some(
parse_identity_property(parser)
.map(|p| Some(ColumnOption::Identity(Identity::Autoincrement(p)))),
)
Some(parse_identity_property(parser).map(|p| {
Some(ColumnOption::Identity(IdentityPropertyKind::Autoincrement(
p,
)))
}))
} else if parser.parse_keywords(&[Keyword::MASKING, Keyword::POLICY]) {
Some(
parse_column_policy_property(parser, with)
Expand All @@ -179,6 +180,8 @@ impl Dialect for SnowflakeDialect {
parse_column_policy_property(parser, with)
.map(|p| Some(ColumnOption::Policy(ColumnPolicy::ProjectionPolicy(p)))),
)
} else if parser.parse_keywords(&[Keyword::TAG]) {
Some(parse_column_tags(parser, with).map(|p| Some(ColumnOption::Tags(p))))
} else {
// needs to revert initial state of parser if dialect finds any matching
if with {
Expand Down Expand Up @@ -821,25 +824,23 @@ fn parse_identity_property(parser: &mut Parser) -> Result<IdentityProperty, Pars
let increment = parser.parse_number()?;
parser.expect_token(&Token::RParen)?;

Some(IdentityFormat::FunctionCall(IdentityParameters {
seed,
increment,
}))
Some(IdentityPropertyFormatKind::FunctionCall(
IdentityParameters { seed, increment },
))
} else if parser.parse_keyword(Keyword::START) {
let seed = parser.parse_number()?;
parser.expect_keyword(Keyword::INCREMENT)?;
let increment = parser.parse_number()?;

Some(IdentityFormat::StartAndIncrement(IdentityParameters {
seed,
increment,
}))
Some(IdentityPropertyFormatKind::StartAndIncrement(
IdentityParameters { seed, increment },
))
} else {
None
};
let order = match parser.parse_one_of_keywords(&[Keyword::ORDER, Keyword::NOORDER]) {
Some(Keyword::ORDER) => Some(IdentityOrder::Order),
Some(Keyword::NOORDER) => Some(IdentityOrder::NoOrder),
Some(Keyword::ORDER) => Some(IdentityPropertyOrder::Order),
Some(Keyword::NOORDER) => Some(IdentityPropertyOrder::NoOrder),
_ => None,
};
Ok(IdentityProperty { parameters, order })
Expand Down Expand Up @@ -871,3 +872,17 @@ fn parse_column_policy_property(
using_columns,
})
}

/// Parsing tags list of column
/// Syntax:
/// ```sql
/// ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] )
/// ```
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
fn parse_column_tags(parser: &mut Parser, with: bool) -> Result<TagsColumnOption, ParserError> {
parser.expect_token(&Token::LParen)?;
let tags = parser.parse_comma_separated(Parser::parse_tag)?;
parser.expect_token(&Token::RParen)?;

Ok(TagsColumnOption { with, tags })
}
28 changes: 7 additions & 21 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6104,8 +6104,6 @@ impl<'a> Parser<'a> {
return option;
}

let with = self.parse_keyword(Keyword::WITH);

if self.parse_keywords(&[Keyword::CHARACTER, Keyword::SET]) {
Ok(Some(ColumnOption::CharacterSet(
self.parse_object_name(false)?,
Expand Down Expand Up @@ -6239,19 +6237,18 @@ impl<'a> Parser<'a> {
let increment = self.parse_number()?;
self.expect_token(&Token::RParen)?;

Some(IdentityFormat::FunctionCall(IdentityParameters {
seed,
increment,
}))
Some(IdentityPropertyFormatKind::FunctionCall(
IdentityParameters { seed, increment },
))
} else {
None
};
Ok(Some(ColumnOption::Identity(Identity::Identity(
IdentityProperty {
Ok(Some(ColumnOption::Identity(
IdentityPropertyKind::Identity(IdentityProperty {
parameters,
order: None,
},
))))
}),
)))
} else if dialect_of!(self is SQLiteDialect | GenericDialect)
&& self.parse_keywords(&[Keyword::ON, Keyword::CONFLICT])
{
Expand All @@ -6265,18 +6262,7 @@ impl<'a> Parser<'a> {
Keyword::REPLACE,
])?,
)))
} else if self.parse_keywords(&[Keyword::TAG])
&& dialect_of!(self is SnowflakeDialect | GenericDialect)
{
self.expect_token(&Token::LParen)?;
let tags = self.parse_comma_separated(Self::parse_tag)?;
self.expect_token(&Token::RParen)?;

Ok(Some(ColumnOption::Tags(TagsColumnOption { with, tags })))
} else {
if with {
self.prev_token();
}
Ok(None)
}
}
Expand Down
Loading

0 comments on commit 01dc886

Please sign in to comment.