mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-20 06:00:15 +00:00
into keyword is optional (#473)
Signed-off-by: Maciej Obuchowski <obuchowski.maciej@gmail.com>
This commit is contained in:
parent
8ef5fc8624
commit
835bb2f9ad
3 changed files with 58 additions and 25 deletions
|
@ -770,6 +770,8 @@ pub enum Statement {
|
|||
Insert {
|
||||
/// Only for Sqlite
|
||||
or: Option<SqliteOnConflict>,
|
||||
/// INTO - optional keyword
|
||||
into: bool,
|
||||
/// TABLE
|
||||
table_name: ObjectName,
|
||||
/// COLUMNS
|
||||
|
@ -1043,6 +1045,8 @@ pub enum Statement {
|
|||
Savepoint { name: Ident },
|
||||
// MERGE INTO statement, based on Snowflake. See <https://docs.snowflake.com/en/sql-reference/sql/merge.html>
|
||||
Merge {
|
||||
// optional INTO keyword
|
||||
into: bool,
|
||||
// Specifies the table to merge
|
||||
table: TableFactor,
|
||||
// Specifies the table or subquery to join with the target table
|
||||
|
@ -1188,6 +1192,7 @@ impl fmt::Display for Statement {
|
|||
}
|
||||
Statement::Insert {
|
||||
or,
|
||||
into,
|
||||
table_name,
|
||||
overwrite,
|
||||
partitioned,
|
||||
|
@ -1202,9 +1207,10 @@ impl fmt::Display for Statement {
|
|||
} else {
|
||||
write!(
|
||||
f,
|
||||
"INSERT {act}{tbl} {table_name} ",
|
||||
"INSERT{over}{int}{tbl} {table_name} ",
|
||||
table_name = table_name,
|
||||
act = if *overwrite { "OVERWRITE" } else { "INTO" },
|
||||
over = if *overwrite { " OVERWRITE" } else { "" },
|
||||
int = if *into { " INTO" } else { "" },
|
||||
tbl = if *table { " TABLE" } else { "" }
|
||||
)?;
|
||||
}
|
||||
|
@ -1755,13 +1761,18 @@ impl fmt::Display for Statement {
|
|||
write!(f, "{}", name)
|
||||
}
|
||||
Statement::Merge {
|
||||
into,
|
||||
table,
|
||||
source,
|
||||
alias,
|
||||
on,
|
||||
clauses,
|
||||
} => {
|
||||
write!(f, "MERGE INTO {} USING {} ", table, source)?;
|
||||
write!(
|
||||
f,
|
||||
"MERGE{int} {table} USING {source} ",
|
||||
int = if *into { " INTO" } else { "" }
|
||||
)?;
|
||||
if let Some(a) = alias {
|
||||
write!(f, "as {} ", a)?;
|
||||
};
|
||||
|
|
|
@ -3802,8 +3802,11 @@ impl<'a> Parser<'a> {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let action = self.expect_one_of_keywords(&[Keyword::INTO, Keyword::OVERWRITE])?;
|
||||
let overwrite = action == Keyword::OVERWRITE;
|
||||
|
||||
let action = self.parse_one_of_keywords(&[Keyword::INTO, Keyword::OVERWRITE]);
|
||||
let into = action == Some(Keyword::INTO);
|
||||
let overwrite = action == Some(Keyword::OVERWRITE);
|
||||
|
||||
let local = self.parse_keyword(Keyword::LOCAL);
|
||||
|
||||
if self.parse_keyword(Keyword::DIRECTORY) {
|
||||
|
@ -3854,6 +3857,7 @@ impl<'a> Parser<'a> {
|
|||
Ok(Statement::Insert {
|
||||
or,
|
||||
table_name,
|
||||
into,
|
||||
overwrite,
|
||||
partitioned,
|
||||
columns,
|
||||
|
@ -4266,7 +4270,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
pub fn parse_merge(&mut self) -> Result<Statement, ParserError> {
|
||||
self.expect_keyword(Keyword::INTO)?;
|
||||
let into = self.parse_keyword(Keyword::INTO);
|
||||
|
||||
let table = self.parse_table_factor()?;
|
||||
|
||||
|
@ -4278,6 +4282,7 @@ impl<'a> Parser<'a> {
|
|||
let clauses = self.parse_merge_clauses()?;
|
||||
|
||||
Ok(Statement::Merge {
|
||||
into,
|
||||
table,
|
||||
source: Box::new(source),
|
||||
alias,
|
||||
|
|
|
@ -41,6 +41,9 @@ fn parse_insert_values() {
|
|||
let rows1 = vec![row.clone()];
|
||||
let rows2 = vec![row.clone(), row];
|
||||
|
||||
let sql = "INSERT customer VALUES (1, 2, 3)";
|
||||
check_one(sql, "customer", &[], &rows1);
|
||||
|
||||
let sql = "INSERT INTO customer VALUES (1, 2, 3)";
|
||||
check_one(sql, "customer", &[], &rows1);
|
||||
|
||||
|
@ -91,16 +94,6 @@ fn parse_insert_values() {
|
|||
verified_stmt("INSERT INTO customer WITH foo AS (SELECT 1) SELECT * FROM foo UNION VALUES (1)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_insert_invalid() {
|
||||
let sql = "INSERT public.customer (id, name, active) VALUES (1, 2, 3)";
|
||||
let res = parse_sql_statements(sql);
|
||||
assert_eq!(
|
||||
ParserError::ParserError("Expected one of INTO or OVERWRITE, found: public".to_string()),
|
||||
res.unwrap_err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_insert_sqlite() {
|
||||
let dialect = SQLiteDialect {};
|
||||
|
@ -4357,14 +4350,29 @@ fn test_revoke() {
|
|||
#[test]
|
||||
fn parse_merge() {
|
||||
let sql = "MERGE INTO s.bar AS dest USING (SELECT * FROM s.foo) as stg ON dest.D = stg.D AND dest.E = stg.E WHEN NOT MATCHED THEN INSERT (A, B, C) VALUES (stg.A, stg.B, stg.C) WHEN MATCHED AND dest.A = 'a' THEN UPDATE SET dest.F = stg.F, dest.G = stg.G WHEN MATCHED THEN DELETE";
|
||||
match verified_stmt(sql) {
|
||||
let sql_no_into = "MERGE s.bar AS dest USING (SELECT * FROM s.foo) as stg ON dest.D = stg.D AND dest.E = stg.E WHEN NOT MATCHED THEN INSERT (A, B, C) VALUES (stg.A, stg.B, stg.C) WHEN MATCHED AND dest.A = 'a' THEN UPDATE SET dest.F = stg.F, dest.G = stg.G WHEN MATCHED THEN DELETE";
|
||||
match (verified_stmt(sql), verified_stmt(sql_no_into)) {
|
||||
(
|
||||
Statement::Merge {
|
||||
into,
|
||||
table,
|
||||
source,
|
||||
alias,
|
||||
on,
|
||||
clauses,
|
||||
} => {
|
||||
},
|
||||
Statement::Merge {
|
||||
into: no_into,
|
||||
table: table_no_into,
|
||||
source: source_no_into,
|
||||
alias: alias_no_into,
|
||||
on: on_no_into,
|
||||
clauses: clauses_no_into,
|
||||
},
|
||||
) => {
|
||||
assert!(into);
|
||||
assert!(!no_into);
|
||||
|
||||
assert_eq!(
|
||||
table,
|
||||
TableFactor::Table {
|
||||
|
@ -4377,6 +4385,8 @@ fn parse_merge() {
|
|||
with_hints: vec![]
|
||||
}
|
||||
);
|
||||
assert_eq!(table, table_no_into);
|
||||
|
||||
assert_eq!(
|
||||
source,
|
||||
Box::new(SetExpr::Query(Box::new(Query {
|
||||
|
@ -4411,6 +4421,8 @@ fn parse_merge() {
|
|||
lock: None
|
||||
})))
|
||||
);
|
||||
assert_eq!(source, source_no_into);
|
||||
|
||||
assert_eq!(
|
||||
alias,
|
||||
Some(TableAlias {
|
||||
|
@ -4418,6 +4430,8 @@ fn parse_merge() {
|
|||
columns: vec![]
|
||||
})
|
||||
);
|
||||
assert_eq!(alias, alias_no_into);
|
||||
|
||||
assert_eq!(
|
||||
on,
|
||||
Box::new(Expr::BinaryOp {
|
||||
|
@ -4446,6 +4460,8 @@ fn parse_merge() {
|
|||
})
|
||||
})
|
||||
);
|
||||
assert_eq!(on, on_no_into);
|
||||
|
||||
assert_eq!(
|
||||
clauses,
|
||||
vec![
|
||||
|
@ -4488,7 +4504,8 @@ fn parse_merge() {
|
|||
},
|
||||
MergeClause::MatchedDelete(None)
|
||||
]
|
||||
)
|
||||
);
|
||||
assert_eq!(clauses, clauses_no_into);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue