Skip to content

Commit 1678c36

Browse files
committed
feat: support export data for bigquery
1 parent 4921846 commit 1678c36

4 files changed

Lines changed: 52 additions & 1 deletion

File tree

src/ast/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4355,6 +4355,15 @@ pub enum Statement {
43554355
///
43564356
/// See [ReturnStatement]
43574357
Return(ReturnStatement),
4358+
4359+
/// Export data statement
4360+
///
4361+
/// Example:
4362+
/// ```sql
4363+
/// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4364+
/// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4365+
/// ```
4366+
ExportData(ExportData),
43584367
}
43594368

43604369
/// ```sql
@@ -6193,6 +6202,7 @@ impl fmt::Display for Statement {
61936202
Statement::Return(r) => write!(f, "{r}"),
61946203
Statement::List(command) => write!(f, "LIST {command}"),
61956204
Statement::Remove(command) => write!(f, "REMOVE {command}"),
6205+
Statement::ExportData(e) => write!(f, "{e}"),
61966206
}
61976207
}
61986208
}
@@ -10125,6 +10135,20 @@ impl fmt::Display for MemberOf {
1012510135
}
1012610136
}
1012710137

10138+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10139+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10140+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10141+
pub struct ExportData {
10142+
pub options: Vec<SqlOption>,
10143+
pub query: Box<Query>,
10144+
}
10145+
10146+
impl fmt::Display for ExportData {
10147+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10148+
write!(f, "EXPORT DATA OPTIONS({}) AS {}", display_comma_separated(&self.options), self.query)
10149+
}
10150+
}
10151+
1012810152
#[cfg(test)]
1012910153
mod tests {
1013010154
use crate::tokenizer::Location;

src/ast/spans.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use crate::ast::{query::SelectItemQualifiedWildcardKind, ColumnOptions};
18+
use crate::ast::{query::SelectItemQualifiedWildcardKind, ColumnOptions, ExportData};
1919
use core::iter;
2020

2121
use crate::tokenizer::Span;
@@ -531,6 +531,9 @@ impl Spanned for Statement {
531531
Statement::Print { .. } => Span::empty(),
532532
Statement::Return { .. } => Span::empty(),
533533
Statement::List(..) | Statement::Remove(..) => Span::empty(),
534+
Statement::ExportData(ExportData { options, query }) => union_spans(
535+
options.iter().map(|i| i.span()).chain(core::iter::once(query.span()))
536+
),
534537
}
535538
}
536539
}

src/parser/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ impl<'a> Parser<'a> {
640640
Keyword::COMMENT if self.dialect.supports_comment_on() => self.parse_comment(),
641641
Keyword::PRINT => self.parse_print(),
642642
Keyword::RETURN => self.parse_return(),
643+
Keyword::EXPORT => self.parse_export(),
643644
_ => self.expected("an SQL statement", next_token),
644645
},
645646
Token::LParen => {
@@ -16472,6 +16473,17 @@ impl<'a> Parser<'a> {
1647216473
}
1647316474
}
1647416475

16476+
fn parse_export(&mut self) -> Result<Statement, ParserError> {
16477+
self.expect_keyword(Keyword::DATA)?;
16478+
self.expect_keyword(Keyword::OPTIONS)?;
16479+
self.expect_token(&Token::LParen)?;
16480+
let options = self.parse_comma_separated(|p| p.parse_sql_option())?;
16481+
self.expect_token(&Token::RParen)?;
16482+
self.expect_keyword(Keyword::AS)?;
16483+
let query = self.parse_query()?;
16484+
Ok(Statement::ExportData(ExportData { options, query }))
16485+
}
16486+
1647516487
/// Consume the parser and return its underlying token buffer
1647616488
pub fn into_tokens(self) -> Vec<TokenWithSpan> {
1647716489
self.tokens

tests/sqlparser_bigquery.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,3 +2566,15 @@ fn test_struct_trailing_and_nested_bracket() {
25662566
)
25672567
);
25682568
}
2569+
2570+
#[test]
2571+
fn test_export() {
2572+
bigquery().verified_stmt(concat!(
2573+
"EXPORT DATA OPTIONS(",
2574+
"uri = 'gs://bucket/folder/*', ",
2575+
"format = 'PARQUET', ",
2576+
"overwrite = true",
2577+
") AS ",
2578+
"SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10",
2579+
));
2580+
}

0 commit comments

Comments
 (0)