Skip to content

Commit 3aa41f3

Browse files
committed
Code review feedback
1 parent a8a8b81 commit 3aa41f3

File tree

6 files changed

+45
-28
lines changed

6 files changed

+45
-28
lines changed

src/ast/helpers/stmt_create_table.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -383,14 +383,24 @@ impl CreateTableBuilder {
383383
self
384384
}
385385

386-
/// Returns true if information on the structure of the table
387-
/// to be created was provided to the builder. If not, the
388-
/// statement is invalid.
389-
pub(crate) fn has_schema_info(&self) -> bool {
390-
!self.columns.is_empty()
391-
|| self.query.is_some()
392-
|| self.like.is_some()
393-
|| self.clone.is_some()
386+
/// Returns true if the statement has exactly one source of info on the schema of the new table.
387+
/// This is Snowflake-specific, some dialects allow more than one source.
388+
pub(crate) fn validate_schema_info(&self) -> bool {
389+
let mut sources = 0;
390+
if !self.columns.is_empty() {
391+
sources += 1;
392+
}
393+
if self.query.is_some() {
394+
sources += 1;
395+
}
396+
if self.like.is_some() {
397+
sources += 1;
398+
}
399+
if self.clone.is_some() {
400+
sources += 1;
401+
}
402+
403+
sources == 1
394404
}
395405

396406
pub fn build(self) -> Statement {

src/dialect/bigquery.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,8 @@ impl Dialect for BigQueryDialect {
144144
fn supports_pipe_operator(&self) -> bool {
145145
true
146146
}
147+
148+
fn supports_create_table_multi_schema_info_sources(&self) -> bool {
149+
true
150+
}
147151
}

src/dialect/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,13 @@ pub trait Dialect: Debug + Any {
590590
false
591591
}
592592

593+
/// Returne true if the dialect supports specifying multiple options
594+
/// in a `CREATE TABLE` statement for the structure of the new table. For example:
595+
/// `CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a`
596+
fn supports_create_table_multi_schema_info_sources(&self) -> bool {
597+
false
598+
}
599+
593600
/// Dialect-specific infix parser override
594601
///
595602
/// This method is called to parse the next infix expression.

src/dialect/snowflake.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ pub fn parse_create_table(
688688
builder = builder.columns(columns).constraints(constraints);
689689
}
690690
Token::EOF => {
691-
if !builder.has_schema_info() {
691+
if !builder.validate_schema_info() {
692692
return Err(ParserError::ParserError(
693693
"unexpected end of input".to_string(),
694694
));
@@ -697,7 +697,7 @@ pub fn parse_create_table(
697697
break;
698698
}
699699
Token::SemiColon => {
700-
if !builder.has_schema_info() {
700+
if !builder.validate_schema_info() {
701701
return Err(ParserError::ParserError(
702702
"unexpected end of input".to_string(),
703703
));

tests/sqlparser_common.rs

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4346,8 +4346,9 @@ fn parse_create_table_as() {
43464346
// BigQuery allows specifying table schema in CTAS
43474347
// ANSI SQL and PostgreSQL let you only specify the list of columns
43484348
// (without data types) in a CTAS, but we have yet to support that.
4349+
let dialects = all_dialects_where(|d| d.supports_create_table_multi_schema_info_sources());
43494350
let sql = "CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a";
4350-
match verified_stmt(sql) {
4351+
match dialects.verified_stmt(sql) {
43514352
Statement::CreateTable(CreateTable { columns, query, .. }) => {
43524353
assert_eq!(columns.len(), 2);
43534354
assert_eq!(columns[0].to_string(), "a INT".to_string());
@@ -4452,20 +4453,6 @@ fn parse_create_or_replace_table() {
44524453
}
44534454
_ => unreachable!(),
44544455
}
4455-
4456-
let sql = "CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a";
4457-
match verified_stmt(sql) {
4458-
Statement::CreateTable(CreateTable { columns, query, .. }) => {
4459-
assert_eq!(columns.len(), 2);
4460-
assert_eq!(columns[0].to_string(), "a INT".to_string());
4461-
assert_eq!(columns[1].to_string(), "b INT".to_string());
4462-
assert_eq!(
4463-
query,
4464-
Some(Box::new(verified_query("SELECT 1 AS b, 2 AS a")))
4465-
);
4466-
}
4467-
_ => unreachable!(),
4468-
}
44694456
}
44704457

44714458
#[test]

tests/sqlparser_snowflake.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,15 +1020,24 @@ fn test_snowflake_create_table_trailing_options() {
10201020
}
10211021

10221022
#[test]
1023-
fn test_snowflake_create_table_has_schema_info() {
1024-
// The parser validates there's information on the schema of the new
1025-
// table, such as a list of columns or a source table\query to copy it from.
1023+
fn test_snowflake_create_table_valid_schema_info() {
1024+
// Validate there's exactly one source of information on the schema of the new table
10261025
assert_eq!(
10271026
snowflake()
10281027
.parse_sql_statements("CREATE TABLE dst")
10291028
.is_err(),
10301029
true
10311030
);
1031+
assert_eq!(
1032+
snowflake().parse_sql_statements("CREATE OR REPLACE TEMP TABLE dst LIKE src AS (SELECT * FROM CUSTOMERS) ON COMMIT PRESERVE ROWS").is_err(),
1033+
true
1034+
);
1035+
assert_eq!(
1036+
snowflake()
1037+
.parse_sql_statements("CREATE OR REPLACE TEMP TABLE dst CLONE customers LIKE customer2")
1038+
.is_err(),
1039+
true
1040+
);
10321041
}
10331042

10341043
#[test]

0 commit comments

Comments
 (0)