mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-10-15 08:19:08 +00:00
Add support for BigQuery table and view options (#1061)
This commit is contained in:
parent
c7d2903c6d
commit
3a6d3ecba2
8 changed files with 465 additions and 54 deletions
|
@ -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};
|
||||
|
@ -3463,8 +3463,12 @@ impl<'a> Parser<'a> {
|
|||
// Many dialects support `OR ALTER` right after `CREATE`, but we don't (yet).
|
||||
// ANSI SQL and Postgres support RECURSIVE here, but we don't support it either.
|
||||
let name = self.parse_object_name()?;
|
||||
let columns = self.parse_parenthesized_column_list(Optional, false)?;
|
||||
let columns = self.parse_view_columns()?;
|
||||
let mut options = CreateTableOptions::None;
|
||||
let with_options = self.parse_options(Keyword::WITH)?;
|
||||
if !with_options.is_empty() {
|
||||
options = CreateTableOptions::With(with_options);
|
||||
}
|
||||
|
||||
let cluster_by = if self.parse_keyword(Keyword::CLUSTER) {
|
||||
self.expect_keyword(Keyword::BY)?;
|
||||
|
@ -3473,6 +3477,17 @@ impl<'a> Parser<'a> {
|
|||
vec![]
|
||||
};
|
||||
|
||||
if dialect_of!(self is BigQueryDialect | GenericDialect) {
|
||||
if let Token::Word(word) = self.peek_token().token {
|
||||
if word.keyword == Keyword::OPTIONS {
|
||||
let opts = self.parse_options(Keyword::OPTIONS)?;
|
||||
if !opts.is_empty() {
|
||||
options = CreateTableOptions::Options(opts);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
self.expect_keyword(Keyword::AS)?;
|
||||
let query = Box::new(self.parse_query()?);
|
||||
// Optional `WITH [ CASCADED | LOCAL ] CHECK OPTION` is widely supported here.
|
||||
|
@ -3491,7 +3506,7 @@ impl<'a> Parser<'a> {
|
|||
query,
|
||||
materialized,
|
||||
or_replace,
|
||||
with_options,
|
||||
options,
|
||||
cluster_by,
|
||||
with_no_schema_binding,
|
||||
if_not_exists,
|
||||
|
@ -4177,6 +4192,12 @@ impl<'a> Parser<'a> {
|
|||
None
|
||||
};
|
||||
|
||||
let big_query_config = if dialect_of!(self is BigQueryDialect | GenericDialect) {
|
||||
self.parse_optional_big_query_create_table_config()?
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
// Parse optional `AS ( query )`
|
||||
let query = if self.parse_keyword(Keyword::AS) {
|
||||
Some(Box::new(self.parse_query()?))
|
||||
|
@ -4260,10 +4281,42 @@ impl<'a> Parser<'a> {
|
|||
.collation(collation)
|
||||
.on_commit(on_commit)
|
||||
.on_cluster(on_cluster)
|
||||
.partition_by(big_query_config.partition_by)
|
||||
.cluster_by(big_query_config.cluster_by)
|
||||
.options(big_query_config.options)
|
||||
.strict(strict)
|
||||
.build())
|
||||
}
|
||||
|
||||
/// Parse configuration like partitioning, clustering information during big-query table creation.
|
||||
/// <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<BigQueryTableConfiguration, ParserError> {
|
||||
let mut partition_by = None;
|
||||
if self.parse_keywords(&[Keyword::PARTITION, Keyword::BY]) {
|
||||
partition_by = Some(Box::new(self.parse_expr()?));
|
||||
};
|
||||
|
||||
let mut cluster_by = None;
|
||||
if self.parse_keywords(&[Keyword::CLUSTER, Keyword::BY]) {
|
||||
cluster_by = Some(self.parse_comma_separated(Parser::parse_identifier)?);
|
||||
};
|
||||
|
||||
let mut options = None;
|
||||
if let Token::Word(word) = self.peek_token().token {
|
||||
if word.keyword == Keyword::OPTIONS {
|
||||
options = Some(self.parse_options(Keyword::OPTIONS)?);
|
||||
}
|
||||
};
|
||||
|
||||
Ok(BigQueryTableConfiguration {
|
||||
partition_by,
|
||||
cluster_by,
|
||||
options,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_optional_procedure_parameters(
|
||||
&mut self,
|
||||
) -> Result<Option<Vec<ProcedureParam>>, ParserError> {
|
||||
|
@ -4453,6 +4506,13 @@ impl<'a> Parser<'a> {
|
|||
Ok(Some(ColumnOption::OnUpdate(expr)))
|
||||
} else if self.parse_keyword(Keyword::GENERATED) {
|
||||
self.parse_optional_column_option_generated()
|
||||
} else if dialect_of!(self is BigQueryDialect | GenericDialect)
|
||||
&& self.parse_keyword(Keyword::OPTIONS)
|
||||
{
|
||||
self.prev_token();
|
||||
Ok(Some(ColumnOption::Options(
|
||||
self.parse_options(Keyword::OPTIONS)?,
|
||||
)))
|
||||
} else if self.parse_keyword(Keyword::AS)
|
||||
&& dialect_of!(self is MySqlDialect | SQLiteDialect | DuckDbDialect | GenericDialect)
|
||||
{
|
||||
|
@ -4731,7 +4791,7 @@ impl<'a> Parser<'a> {
|
|||
pub fn parse_sql_option(&mut self) -> Result<SqlOption, ParserError> {
|
||||
let name = self.parse_identifier()?;
|
||||
self.expect_token(&Token::Eq)?;
|
||||
let value = self.parse_value()?;
|
||||
let value = self.parse_expr()?;
|
||||
Ok(SqlOption { name, value })
|
||||
}
|
||||
|
||||
|
@ -5952,6 +6012,36 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parses a parenthesized, comma-separated list of column definitions within a view.
|
||||
fn parse_view_columns(&mut self) -> Result<Vec<ViewColumnDef>, ParserError> {
|
||||
if self.consume_token(&Token::LParen) {
|
||||
if self.peek_token().token == Token::RParen {
|
||||
self.next_token();
|
||||
Ok(vec![])
|
||||
} else {
|
||||
let cols = self.parse_comma_separated(Parser::parse_view_column)?;
|
||||
self.expect_token(&Token::RParen)?;
|
||||
Ok(cols)
|
||||
}
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a column definition within a view.
|
||||
fn parse_view_column(&mut self) -> Result<ViewColumnDef, ParserError> {
|
||||
let name = self.parse_identifier()?;
|
||||
let options = if dialect_of!(self is BigQueryDialect | GenericDialect)
|
||||
&& self.parse_keyword(Keyword::OPTIONS)
|
||||
{
|
||||
self.prev_token();
|
||||
Some(self.parse_options(Keyword::OPTIONS)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(ViewColumnDef { name, options })
|
||||
}
|
||||
|
||||
/// Parse a parenthesized comma-separated list of unqualified, possibly quoted identifiers
|
||||
pub fn parse_parenthesized_column_list(
|
||||
&mut self,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue