Skip to content

Commit

Permalink
Inline table options, add coment to ViewColumnDef
Browse files Browse the repository at this point in the history
  • Loading branch information
iffyio committed Jan 19, 2024
1 parent a894a74 commit 87642c8
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 89 deletions.
19 changes: 16 additions & 3 deletions src/ast/ddl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,20 @@ impl fmt::Display for ColumnDef {
}
}

/// Column definition for a view.
/// Column definition specified in a `CREATE VIEW` statement.
///
/// Syntax
/// ```markdown
/// <name> [OPTIONS(option, ...)]
///
/// option: <name> = <value>
/// ```
///
/// Examples:
/// ```sql
/// name
/// age OPTIONS(description = "age column", tag = "prod")
/// ```
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
Expand Down Expand Up @@ -741,7 +754,7 @@ pub enum ColumnOption {
/// ```
/// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#view_column_option_list
/// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_option_list
SqlOptions(Vec<SqlOption>),
Options(Vec<SqlOption>),
}

impl fmt::Display for ColumnOption {
Expand Down Expand Up @@ -820,7 +833,7 @@ impl fmt::Display for ColumnOption {
Ok(())
}
}
SqlOptions(options) => {
Options(options) => {
write!(f, "OPTIONS({})", display_comma_separated(options))
}
}
Expand Down
46 changes: 37 additions & 9 deletions src/ast/helpers/stmt_create_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use serde::{Deserialize, Serialize};
use sqlparser_derive::{Visit, VisitMut};

use crate::ast::{
ColumnDef, CreateTableConfiguration, FileFormat, HiveDistributionStyle, HiveFormat, Ident,
ObjectName, OnCommit, Query, SqlOption, Statement, TableConstraint,
ColumnDef, Expr, FileFormat, HiveDistributionStyle, HiveFormat, Ident, ObjectName, OnCommit,
Query, SqlOption, Statement, TableConstraint,
};
use crate::parser::ParserError;

Expand Down Expand Up @@ -72,7 +72,9 @@ pub struct CreateTableBuilder {
pub on_commit: Option<OnCommit>,
pub on_cluster: Option<String>,
pub order_by: Option<Vec<Ident>>,
pub table_config: Option<Box<CreateTableConfiguration>>,
pub partition_by: Option<Box<Expr>>,
pub cluster_by: Option<Vec<Ident>>,
pub options: Option<Vec<SqlOption>>,
pub strict: bool,
}

Expand Down Expand Up @@ -106,7 +108,9 @@ impl CreateTableBuilder {
on_commit: None,
on_cluster: None,
order_by: None,
table_config: None,
partition_by: None,
cluster_by: None,
options: None,
strict: false,
}
}
Expand Down Expand Up @@ -238,8 +242,18 @@ impl CreateTableBuilder {
self
}

pub fn table_config(mut self, table_config: Option<Box<CreateTableConfiguration>>) -> Self {
self.table_config = table_config;
pub fn partition_by(mut self, partition_by: Option<Box<Expr>>) -> Self {
self.partition_by = partition_by;
self
}

pub fn cluster_by(mut self, cluster_by: Option<Vec<Ident>>) -> Self {
self.cluster_by = cluster_by;
self
}

pub fn options(mut self, options: Option<Vec<SqlOption>>) -> Self {
self.options = options;
self
}

Expand Down Expand Up @@ -277,7 +291,9 @@ impl CreateTableBuilder {
on_commit: self.on_commit,
on_cluster: self.on_cluster,
order_by: self.order_by,
table_config: self.table_config,
partition_by: self.partition_by,
cluster_by: self.cluster_by,
options: self.options,
strict: self.strict,
}
}
Expand Down Expand Up @@ -318,7 +334,9 @@ impl TryFrom<Statement> for CreateTableBuilder {
on_commit,
on_cluster,
order_by,
table_config: config,
partition_by,
cluster_by,
options,
strict,
} => Ok(Self {
or_replace,
Expand Down Expand Up @@ -348,7 +366,9 @@ impl TryFrom<Statement> for CreateTableBuilder {
on_commit,
on_cluster,
order_by,
table_config: config,
partition_by,
cluster_by,
options,
strict,
}),
_ => Err(ParserError::ParserError(format!(
Expand All @@ -358,6 +378,14 @@ impl TryFrom<Statement> for CreateTableBuilder {
}
}

/// Helper return type when parsing configuration for a BigQuery `CREATE TABLE` statement.
#[derive(Default)]
pub(crate) struct BigQueryTableConfiguration {
pub partition_by: Option<Box<Expr>>,
pub cluster_by: Option<Vec<Ident>>,
pub options: Option<Vec<SqlOption>>,
}

#[cfg(test)]
mod tests {
use crate::ast::helpers::stmt_create_table::CreateTableBuilder;
Expand Down
78 changes: 28 additions & 50 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1632,8 +1632,15 @@ pub enum Statement {
/// than empty (represented as ()), the latter meaning "no sorting".
/// <https://clickhouse.com/docs/en/sql-reference/statements/create/table/>
order_by: Option<Vec<Ident>>,
/// Database specific configuration during table creation.
table_config: Option<Box<CreateTableConfiguration>>,
/// BigQuery: A partition expression for the table.
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#partition_expression>
partition_by: Option<Box<Expr>>,
/// BigQuery: Table clustering column list.
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
cluster_by: Option<Vec<Ident>>,
/// BigQuery: Table options list.
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
options: Option<Vec<SqlOption>>,
/// SQLite "STRICT" clause.
/// if the "STRICT" table-option keyword is added to the end, after the closing ")",
/// then strict typing rules apply to that table.
Expand Down Expand Up @@ -2826,7 +2833,9 @@ impl fmt::Display for Statement {
on_commit,
on_cluster,
order_by,
table_config,
partition_by,
cluster_by,
options,
strict,
} => {
// We want to allow the following options
Expand Down Expand Up @@ -2983,26 +2992,22 @@ impl fmt::Display for Statement {
if let Some(order_by) = order_by {
write!(f, " ORDER BY ({})", display_comma_separated(order_by))?;
}
if let Some(CreateTableConfiguration::BigQuery(big_query_config)) =
table_config.as_ref().map(|c| c.as_ref())
{
if let Some(partition_by) = big_query_config.partition_by.as_ref() {
write!(f, " PARTITION BY {partition_by}")?;
}
if let Some(cluster_by) = big_query_config.cluster_by.as_ref() {
write!(
f,
" CLUSTER BY {}",
display_comma_separated(cluster_by.as_slice())
)?;
}
if let Some(options) = big_query_config.options.as_ref() {
write!(
f,
" OPTIONS({})",
display_comma_separated(options.as_slice())
)?;
}
if let Some(partition_by) = partition_by.as_ref() {
write!(f, " PARTITION BY {partition_by}")?;
}
if let Some(cluster_by) = cluster_by.as_ref() {
write!(
f,
" CLUSTER BY {}",
display_comma_separated(cluster_by.as_slice())
)?;
}
if let Some(options) = options.as_ref() {
write!(
f,
" OPTIONS({})",
display_comma_separated(options.as_slice())
)?;
}
if let Some(query) = query {
write!(f, " AS {query}")?;
Expand Down Expand Up @@ -4550,33 +4555,6 @@ pub struct HiveFormat {
pub location: Option<String>,
}

/// Represents BigQuery specific configuration like partitioning, clustering
/// information during table creation.
///
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_statement>
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct BigQueryCreateTableConfiguration {
/// A partition expression for the table.
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#partition_expression>
pub partition_by: Option<Expr>,
/// Table clustering column list.
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
pub cluster_by: Option<Vec<Ident>>,
/// Table options list.
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
pub options: Option<Vec<SqlOption>>,
}

/// Represents database specific configuration during table creation.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum CreateTableConfiguration {
BigQuery(BigQueryCreateTableConfiguration),
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
Expand Down
32 changes: 14 additions & 18 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use log::debug;
use IsLateral::*;
use IsOptional::*;

use crate::ast::helpers::stmt_create_table::CreateTableBuilder;
use crate::ast::helpers::stmt_create_table::{BigQueryTableConfiguration, CreateTableBuilder};
use crate::ast::*;
use crate::dialect::*;
use crate::keywords::{self, Keyword, ALL_KEYWORDS};
Expand Down Expand Up @@ -4184,10 +4184,10 @@ impl<'a> Parser<'a> {
None
};

let table_config = if dialect_of!(self is BigQueryDialect | GenericDialect) {
let big_query_config = if dialect_of!(self is BigQueryDialect | GenericDialect) {
self.parse_optional_big_query_create_table_config()?
} else {
None
Default::default()
};

// Parse optional `AS ( query )`
Expand Down Expand Up @@ -4273,7 +4273,9 @@ impl<'a> Parser<'a> {
.collation(collation)
.on_commit(on_commit)
.on_cluster(on_cluster)
.table_config(table_config)
.partition_by(big_query_config.partition_by)
.cluster_by(big_query_config.cluster_by)
.options(big_query_config.options)
.strict(strict)
.build())
}
Expand All @@ -4282,10 +4284,10 @@ impl<'a> Parser<'a> {
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_2>
fn parse_optional_big_query_create_table_config(
&mut self,
) -> Result<Option<Box<CreateTableConfiguration>>, ParserError> {
) -> Result<BigQueryTableConfiguration, ParserError> {
let mut partition_by = None;
if self.parse_keywords(&[Keyword::PARTITION, Keyword::BY]) {
partition_by = Some(self.parse_expr()?);
partition_by = Some(Box::new(self.parse_expr()?));
};

let mut cluster_by = None;
Expand All @@ -4300,17 +4302,11 @@ impl<'a> Parser<'a> {
}
};

if partition_by.is_some() || cluster_by.is_some() || options.is_some() {
Ok(Some(Box::new(CreateTableConfiguration::BigQuery(
BigQueryCreateTableConfiguration {
partition_by,
cluster_by,
options,
},
))))
} else {
Ok(None)
}
Ok(BigQueryTableConfiguration {
partition_by,
cluster_by,
options,
})
}

pub fn parse_optional_procedure_parameters(
Expand Down Expand Up @@ -4506,7 +4502,7 @@ impl<'a> Parser<'a> {
&& self.parse_keyword(Keyword::OPTIONS)
{
self.prev_token();
Ok(Some(ColumnOption::SqlOptions(
Ok(Some(ColumnOption::Options(
self.parse_options(Keyword::OPTIONS)?,
)))
} else if self.parse_keyword(Keyword::AS)
Expand Down
20 changes: 11 additions & 9 deletions tests/sqlparser_bigquery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,9 @@ fn parse_create_table_with_options() {
Statement::CreateTable {
name,
columns,
table_config,
partition_by,
cluster_by,
options,
..
} => {
assert_eq!(
Expand All @@ -186,7 +188,7 @@ fn parse_create_table_with_options() {
},
ColumnOptionDef {
name: None,
option: ColumnOption::SqlOptions(vec![SqlOption {
option: ColumnOption::Options(vec![SqlOption {
name: Ident::new("description"),
value: Expr::Value(Value::DoubleQuotedString(
"field x".to_string()
Expand All @@ -201,7 +203,7 @@ fn parse_create_table_with_options() {
collation: None,
options: vec![ColumnOptionDef {
name: None,
option: ColumnOption::SqlOptions(vec![SqlOption {
option: ColumnOption::Options(vec![SqlOption {
name: Ident::new("description"),
value: Expr::Value(Value::DoubleQuotedString(
"field y".to_string()
Expand All @@ -213,10 +215,10 @@ fn parse_create_table_with_options() {
columns
);
assert_eq!(
CreateTableConfiguration::BigQuery(BigQueryCreateTableConfiguration {
partition_by: Some(Expr::Identifier(Ident::new("_PARTITIONDATE"))),
cluster_by: Some(vec![Ident::new("userid"), Ident::new("age"),]),
options: Some(vec![
(
Some(Box::new(Expr::Identifier(Ident::new("_PARTITIONDATE")))),
Some(vec![Ident::new("userid"), Ident::new("age"),]),
Some(vec![
SqlOption {
name: Ident::new("partition_expiration_days"),
value: Expr::Value(number("1")),
Expand All @@ -228,8 +230,8 @@ fn parse_create_table_with_options() {
)),
},
])
}),
*table_config.unwrap(),
),
(partition_by, cluster_by, options)
)
}
_ => unreachable!(),
Expand Down

0 comments on commit 87642c8

Please sign in to comment.