Skip to content

Commit 0aaa561

Browse files
committed
Merge branch 'main' into feat/alter_schema
2 parents 31c63ec + 97a5b61 commit 0aaa561

9 files changed

Lines changed: 379 additions & 5 deletions

File tree

src/ast/ddl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub enum AlterTableOperation {
149149
},
150150
/// `ATTACH PART|PARTITION <partition_expr>`
151151
/// Note: this is a ClickHouse-specific operation, please refer to
152-
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/pakrtition#attach-partitionpart)
152+
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#attach-partitionpart)
153153
AttachPartition {
154154
// PART is not a short form of PARTITION, it's a separate keyword
155155
// which represents a physical file on disk and partition is a logical entity.

src/ast/mod.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,7 @@ pub enum Expr {
11441144
///
11451145
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
11461146
/// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1147-
/// [DuckDb](https://duckdb.org/docs/sql/functions/lambda.html)
1147+
/// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
11481148
Lambda(LambdaFunction),
11491149
/// Checks membership of a value in a JSON array
11501150
MemberOf(MemberOf),
@@ -4366,6 +4366,15 @@ pub enum Statement {
43664366
///
43674367
/// See [ReturnStatement]
43684368
Return(ReturnStatement),
4369+
/// Export data statement
4370+
///
4371+
/// Example:
4372+
/// ```sql
4373+
/// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4374+
/// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4375+
/// ```
4376+
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4377+
ExportData(ExportData),
43694378
/// ```sql
43704379
/// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
43714380
/// ```
@@ -6209,6 +6218,7 @@ impl fmt::Display for Statement {
62096218
Statement::Return(r) => write!(f, "{r}"),
62106219
Statement::List(command) => write!(f, "LIST {command}"),
62116220
Statement::Remove(command) => write!(f, "REMOVE {command}"),
6221+
Statement::ExportData(e) => write!(f, "{e}"),
62126222
Statement::CreateUser(s) => write!(f, "{s}"),
62136223
Statement::AlterSchema {
62146224
name, operations, ..
@@ -6791,6 +6801,7 @@ pub enum ActionCreateObjectType {
67916801
OrganiationListing,
67926802
ReplicationGroup,
67936803
Role,
6804+
Schema,
67946805
Share,
67956806
User,
67966807
Warehouse,
@@ -6812,6 +6823,7 @@ impl fmt::Display for ActionCreateObjectType {
68126823
ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
68136824
ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
68146825
ActionCreateObjectType::Role => write!(f, "ROLE"),
6826+
ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
68156827
ActionCreateObjectType::Share => write!(f, "SHARE"),
68166828
ActionCreateObjectType::User => write!(f, "USER"),
68176829
ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
@@ -7049,6 +7061,8 @@ pub enum GrantObjects {
70497061
AllMaterializedViewsInSchema { schemas: Vec<ObjectName> },
70507062
/// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
70517063
AllExternalTablesInSchema { schemas: Vec<ObjectName> },
7064+
/// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7065+
AllFunctionsInSchema { schemas: Vec<ObjectName> },
70527066
/// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
70537067
FutureSchemasInDatabase { databases: Vec<ObjectName> },
70547068
/// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
@@ -7169,6 +7183,13 @@ impl fmt::Display for GrantObjects {
71697183
display_comma_separated(schemas)
71707184
)
71717185
}
7186+
GrantObjects::AllFunctionsInSchema { schemas } => {
7187+
write!(
7188+
f,
7189+
"ALL FUNCTIONS IN SCHEMA {}",
7190+
display_comma_separated(schemas)
7191+
)
7192+
}
71727193
GrantObjects::FutureSchemasInDatabase { databases } => {
71737194
write!(
71747195
f,
@@ -7844,6 +7865,7 @@ pub enum ObjectType {
78447865
Stage,
78457866
Type,
78467867
User,
7868+
Stream,
78477869
}
78487870

78497871
impl fmt::Display for ObjectType {
@@ -7860,6 +7882,7 @@ impl fmt::Display for ObjectType {
78607882
ObjectType::Stage => "STAGE",
78617883
ObjectType::Type => "TYPE",
78627884
ObjectType::User => "USER",
7885+
ObjectType::Stream => "STREAM",
78637886
})
78647887
}
78657888
}
@@ -10151,6 +10174,34 @@ impl fmt::Display for MemberOf {
1015110174
}
1015210175
}
1015310176

10177+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10178+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10179+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10180+
pub struct ExportData {
10181+
pub options: Vec<SqlOption>,
10182+
pub query: Box<Query>,
10183+
pub connection: Option<ObjectName>,
10184+
}
10185+
10186+
impl fmt::Display for ExportData {
10187+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10188+
if let Some(connection) = &self.connection {
10189+
write!(
10190+
f,
10191+
"EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
10192+
display_comma_separated(&self.options),
10193+
self.query
10194+
)
10195+
} else {
10196+
write!(
10197+
f,
10198+
"EXPORT DATA OPTIONS({}) AS {}",
10199+
display_comma_separated(&self.options),
10200+
self.query
10201+
)
10202+
}
10203+
}
10204+
}
1015410205
/// Creates a user
1015510206
///
1015610207
/// Syntax:

src/ast/spans.rs

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

18-
use crate::ast::{query::SelectItemQualifiedWildcardKind, AlterSchemaOperation, ColumnOptions};
18+
use crate::ast::{
19+
query::SelectItemQualifiedWildcardKind, AlterSchemaOperation, ColumnOptions, ExportData,
20+
};
1921
use core::iter;
2022

2123
use crate::tokenizer::Span;
@@ -531,6 +533,17 @@ impl Spanned for Statement {
531533
Statement::Print { .. } => Span::empty(),
532534
Statement::Return { .. } => Span::empty(),
533535
Statement::List(..) | Statement::Remove(..) => Span::empty(),
536+
Statement::ExportData(ExportData {
537+
options,
538+
query,
539+
connection,
540+
}) => union_spans(
541+
options
542+
.iter()
543+
.map(|i| i.span())
544+
.chain(core::iter::once(query.span()))
545+
.chain(connection.iter().map(|i| i.span())),
546+
),
534547
Statement::CreateUser(..) => Span::empty(),
535548
Statement::AlterSchema {
536549
name, operations, ..

src/dialect/bigquery.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::ast::Statement;
1919
use crate::dialect::Dialect;
2020
use crate::keywords::Keyword;
2121
use crate::parser::{Parser, ParserError};
22+
use crate::tokenizer::Token;
2223

2324
/// These keywords are disallowed as column identifiers. Such that
2425
/// `SELECT 5 AS <col> FROM T` is rejected by BigQuery.
@@ -47,6 +48,13 @@ pub struct BigQueryDialect;
4748
impl Dialect for BigQueryDialect {
4849
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
4950
if parser.parse_keyword(Keyword::BEGIN) {
51+
if parser.peek_keyword(Keyword::TRANSACTION)
52+
|| parser.peek_token_ref().token == Token::SemiColon
53+
|| parser.peek_token_ref().token == Token::EOF
54+
{
55+
parser.prev_token();
56+
return None;
57+
}
5058
return Some(parser.parse_begin_exception_end());
5159
}
5260

src/dialect/duckdb.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl Dialect for DuckDbDialect {
6565
true
6666
}
6767

68-
/// See <https://duckdb.org/docs/sql/functions/lambda.html>
68+
/// See <https://duckdb.org/docs/stable/sql/functions/lambda>
6969
fn supports_lambda_functions(&self) -> bool {
7070
true
7171
}

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,7 @@ define_keywords!(
870870
STORAGE_SERIALIZATION_POLICY,
871871
STORED,
872872
STRAIGHT_JOIN,
873+
STREAM,
873874
STRICT,
874875
STRING,
875876
STRUCT,

src/parser/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,10 @@ impl<'a> Parser<'a> {
645645
Keyword::COMMENT if self.dialect.supports_comment_on() => self.parse_comment(),
646646
Keyword::PRINT => self.parse_print(),
647647
Keyword::RETURN => self.parse_return(),
648+
Keyword::EXPORT => {
649+
self.prev_token();
650+
self.parse_export_data()
651+
}
648652
_ => self.expected("an SQL statement", next_token),
649653
},
650654
Token::LParen => {
@@ -6325,6 +6329,8 @@ impl<'a> Parser<'a> {
63256329
ObjectType::Type
63266330
} else if self.parse_keyword(Keyword::USER) {
63276331
ObjectType::User
6332+
} else if self.parse_keyword(Keyword::STREAM) {
6333+
ObjectType::Stream
63286334
} else if self.parse_keyword(Keyword::FUNCTION) {
63296335
return self.parse_drop_function();
63306336
} else if self.parse_keyword(Keyword::POLICY) {
@@ -14144,6 +14150,15 @@ impl<'a> Parser<'a> {
1414414150
Some(GrantObjects::AllMaterializedViewsInSchema {
1414514151
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
1414614152
})
14153+
} else if self.parse_keywords(&[
14154+
Keyword::ALL,
14155+
Keyword::FUNCTIONS,
14156+
Keyword::IN,
14157+
Keyword::SCHEMA,
14158+
]) {
14159+
Some(GrantObjects::AllFunctionsInSchema {
14160+
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
14161+
})
1414714162
} else if self.parse_keywords(&[
1414814163
Keyword::FUTURE,
1414914164
Keyword::SCHEMAS,
@@ -14450,6 +14465,8 @@ impl<'a> Parser<'a> {
1445014465
Some(ActionCreateObjectType::Integration)
1445114466
} else if self.parse_keyword(Keyword::ROLE) {
1445214467
Some(ActionCreateObjectType::Role)
14468+
} else if self.parse_keyword(Keyword::SCHEMA) {
14469+
Some(ActionCreateObjectType::Schema)
1445314470
} else if self.parse_keyword(Keyword::SHARE) {
1445414471
Some(ActionCreateObjectType::Share)
1445514472
} else if self.parse_keyword(Keyword::USER) {
@@ -16546,6 +16563,30 @@ impl<'a> Parser<'a> {
1654616563
}
1654716564
}
1654816565

16566+
/// /// Parse a `EXPORT DATA` statement.
16567+
///
16568+
/// See [Statement::ExportData]
16569+
fn parse_export_data(&mut self) -> Result<Statement, ParserError> {
16570+
self.expect_keywords(&[Keyword::EXPORT, Keyword::DATA])?;
16571+
16572+
let connection = if self.parse_keywords(&[Keyword::WITH, Keyword::CONNECTION]) {
16573+
Some(self.parse_object_name(false)?)
16574+
} else {
16575+
None
16576+
};
16577+
self.expect_keyword(Keyword::OPTIONS)?;
16578+
self.expect_token(&Token::LParen)?;
16579+
let options = self.parse_comma_separated(|p| p.parse_sql_option())?;
16580+
self.expect_token(&Token::RParen)?;
16581+
self.expect_keyword(Keyword::AS)?;
16582+
let query = self.parse_query()?;
16583+
Ok(Statement::ExportData(ExportData {
16584+
options,
16585+
query,
16586+
connection,
16587+
}))
16588+
}
16589+
1654916590
/// Consume the parser and return its underlying token buffer
1655016591
pub fn into_tokens(self) -> Vec<TokenWithSpan> {
1655116592
self.tokens

0 commit comments

Comments
 (0)