mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-04 14:28:22 +00:00
Support UPDATE ... FROM ( subquery )
in some dialects (#694)
* Apply UPDATE SET FROM statement for some dialects * Add GenericDialect to support * Test SnowflakeDialect Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
0d91662c88
commit
4b1dc1abf7
3 changed files with 94 additions and 82 deletions
|
@ -5254,7 +5254,9 @@ impl<'a> Parser<'a> {
|
||||||
let table = self.parse_table_and_joins()?;
|
let table = self.parse_table_and_joins()?;
|
||||||
self.expect_keyword(Keyword::SET)?;
|
self.expect_keyword(Keyword::SET)?;
|
||||||
let assignments = self.parse_comma_separated(Parser::parse_assignment)?;
|
let assignments = self.parse_comma_separated(Parser::parse_assignment)?;
|
||||||
let from = if self.parse_keyword(Keyword::FROM) && dialect_of!(self is PostgreSqlDialect) {
|
let from = if self.parse_keyword(Keyword::FROM)
|
||||||
|
&& dialect_of!(self is GenericDialect | PostgreSqlDialect | BigQueryDialect | SnowflakeDialect | RedshiftSqlDialect | MsSqlDialect)
|
||||||
|
{
|
||||||
Some(self.parse_table_and_joins()?)
|
Some(self.parse_table_and_joins()?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -24,7 +24,7 @@ use sqlparser::ast::SelectItem::UnnamedExpr;
|
||||||
use sqlparser::ast::*;
|
use sqlparser::ast::*;
|
||||||
use sqlparser::dialect::{
|
use sqlparser::dialect::{
|
||||||
AnsiDialect, BigQueryDialect, ClickHouseDialect, GenericDialect, HiveDialect, MsSqlDialect,
|
AnsiDialect, BigQueryDialect, ClickHouseDialect, GenericDialect, HiveDialect, MsSqlDialect,
|
||||||
MySqlDialect, PostgreSqlDialect, SQLiteDialect, SnowflakeDialect,
|
MySqlDialect, PostgreSqlDialect, RedshiftSqlDialect, SQLiteDialect, SnowflakeDialect,
|
||||||
};
|
};
|
||||||
use sqlparser::keywords::ALL_KEYWORDS;
|
use sqlparser::keywords::ALL_KEYWORDS;
|
||||||
use sqlparser::parser::{Parser, ParserError};
|
use sqlparser::parser::{Parser, ParserError};
|
||||||
|
@ -186,6 +186,96 @@ fn parse_update() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_update_set_from() {
|
||||||
|
let sql = "UPDATE t1 SET name = t2.name FROM (SELECT name, id FROM t1 GROUP BY id) AS t2 WHERE t1.id = t2.id";
|
||||||
|
let dialects = TestedDialects {
|
||||||
|
dialects: vec![
|
||||||
|
Box::new(GenericDialect {}),
|
||||||
|
Box::new(PostgreSqlDialect {}),
|
||||||
|
Box::new(BigQueryDialect {}),
|
||||||
|
Box::new(SnowflakeDialect {}),
|
||||||
|
Box::new(RedshiftSqlDialect {}),
|
||||||
|
Box::new(MsSqlDialect {}),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
let stmt = dialects.verified_stmt(sql);
|
||||||
|
assert_eq!(
|
||||||
|
stmt,
|
||||||
|
Statement::Update {
|
||||||
|
table: TableWithJoins {
|
||||||
|
relation: TableFactor::Table {
|
||||||
|
name: ObjectName(vec![Ident::new("t1")]),
|
||||||
|
alias: None,
|
||||||
|
args: None,
|
||||||
|
with_hints: vec![],
|
||||||
|
},
|
||||||
|
joins: vec![],
|
||||||
|
},
|
||||||
|
assignments: vec![Assignment {
|
||||||
|
id: vec![Ident::new("name")],
|
||||||
|
value: Expr::CompoundIdentifier(vec![Ident::new("t2"), Ident::new("name")])
|
||||||
|
}],
|
||||||
|
from: Some(TableWithJoins {
|
||||||
|
relation: TableFactor::Derived {
|
||||||
|
lateral: false,
|
||||||
|
subquery: Box::new(Query {
|
||||||
|
with: None,
|
||||||
|
body: Box::new(SetExpr::Select(Box::new(Select {
|
||||||
|
distinct: false,
|
||||||
|
top: None,
|
||||||
|
projection: vec![
|
||||||
|
SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name"))),
|
||||||
|
SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("id"))),
|
||||||
|
],
|
||||||
|
into: None,
|
||||||
|
from: vec![TableWithJoins {
|
||||||
|
relation: TableFactor::Table {
|
||||||
|
name: ObjectName(vec![Ident::new("t1")]),
|
||||||
|
alias: None,
|
||||||
|
args: None,
|
||||||
|
with_hints: vec![],
|
||||||
|
},
|
||||||
|
joins: vec![],
|
||||||
|
}],
|
||||||
|
lateral_views: vec![],
|
||||||
|
selection: None,
|
||||||
|
group_by: vec![Expr::Identifier(Ident::new("id"))],
|
||||||
|
cluster_by: vec![],
|
||||||
|
distribute_by: vec![],
|
||||||
|
sort_by: vec![],
|
||||||
|
having: None,
|
||||||
|
qualify: None
|
||||||
|
}))),
|
||||||
|
order_by: vec![],
|
||||||
|
limit: None,
|
||||||
|
offset: None,
|
||||||
|
fetch: None,
|
||||||
|
lock: None,
|
||||||
|
}),
|
||||||
|
alias: Some(TableAlias {
|
||||||
|
name: Ident::new("t2"),
|
||||||
|
columns: vec![],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
joins: vec![],
|
||||||
|
}),
|
||||||
|
selection: Some(Expr::BinaryOp {
|
||||||
|
left: Box::new(Expr::CompoundIdentifier(vec![
|
||||||
|
Ident::new("t1"),
|
||||||
|
Ident::new("id")
|
||||||
|
])),
|
||||||
|
op: BinaryOperator::Eq,
|
||||||
|
right: Box::new(Expr::CompoundIdentifier(vec![
|
||||||
|
Ident::new("t2"),
|
||||||
|
Ident::new("id")
|
||||||
|
])),
|
||||||
|
}),
|
||||||
|
returning: None,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_update_with_table_alias() {
|
fn parse_update_with_table_alias() {
|
||||||
let sql = "UPDATE users AS u SET u.username = 'new_user' WHERE u.username = 'old_user'";
|
let sql = "UPDATE users AS u SET u.username = 'new_user' WHERE u.username = 'old_user'";
|
||||||
|
|
|
@ -489,86 +489,6 @@ PHP ₱ USD $
|
||||||
//assert_eq!(sql, ast.to_string());
|
//assert_eq!(sql, ast.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parse_update_set_from() {
|
|
||||||
let sql = "UPDATE t1 SET name = t2.name FROM (SELECT name, id FROM t1 GROUP BY id) AS t2 WHERE t1.id = t2.id";
|
|
||||||
let stmt = pg().verified_stmt(sql);
|
|
||||||
assert_eq!(
|
|
||||||
stmt,
|
|
||||||
Statement::Update {
|
|
||||||
table: TableWithJoins {
|
|
||||||
relation: TableFactor::Table {
|
|
||||||
name: ObjectName(vec![Ident::new("t1")]),
|
|
||||||
alias: None,
|
|
||||||
args: None,
|
|
||||||
with_hints: vec![],
|
|
||||||
},
|
|
||||||
joins: vec![],
|
|
||||||
},
|
|
||||||
assignments: vec![Assignment {
|
|
||||||
id: vec![Ident::new("name")],
|
|
||||||
value: Expr::CompoundIdentifier(vec![Ident::new("t2"), Ident::new("name")])
|
|
||||||
}],
|
|
||||||
from: Some(TableWithJoins {
|
|
||||||
relation: TableFactor::Derived {
|
|
||||||
lateral: false,
|
|
||||||
subquery: Box::new(Query {
|
|
||||||
with: None,
|
|
||||||
body: Box::new(SetExpr::Select(Box::new(Select {
|
|
||||||
distinct: false,
|
|
||||||
top: None,
|
|
||||||
projection: vec![
|
|
||||||
SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name"))),
|
|
||||||
SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("id"))),
|
|
||||||
],
|
|
||||||
into: None,
|
|
||||||
from: vec![TableWithJoins {
|
|
||||||
relation: TableFactor::Table {
|
|
||||||
name: ObjectName(vec![Ident::new("t1")]),
|
|
||||||
alias: None,
|
|
||||||
args: None,
|
|
||||||
with_hints: vec![],
|
|
||||||
},
|
|
||||||
joins: vec![],
|
|
||||||
}],
|
|
||||||
lateral_views: vec![],
|
|
||||||
selection: None,
|
|
||||||
group_by: vec![Expr::Identifier(Ident::new("id"))],
|
|
||||||
cluster_by: vec![],
|
|
||||||
distribute_by: vec![],
|
|
||||||
sort_by: vec![],
|
|
||||||
having: None,
|
|
||||||
qualify: None
|
|
||||||
}))),
|
|
||||||
order_by: vec![],
|
|
||||||
limit: None,
|
|
||||||
offset: None,
|
|
||||||
fetch: None,
|
|
||||||
lock: None,
|
|
||||||
}),
|
|
||||||
alias: Some(TableAlias {
|
|
||||||
name: Ident::new("t2"),
|
|
||||||
columns: vec![],
|
|
||||||
})
|
|
||||||
},
|
|
||||||
joins: vec![],
|
|
||||||
}),
|
|
||||||
selection: Some(Expr::BinaryOp {
|
|
||||||
left: Box::new(Expr::CompoundIdentifier(vec![
|
|
||||||
Ident::new("t1"),
|
|
||||||
Ident::new("id")
|
|
||||||
])),
|
|
||||||
op: BinaryOperator::Eq,
|
|
||||||
right: Box::new(Expr::CompoundIdentifier(vec![
|
|
||||||
Ident::new("t2"),
|
|
||||||
Ident::new("id")
|
|
||||||
])),
|
|
||||||
}),
|
|
||||||
returning: None,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_copy_from() {
|
fn test_copy_from() {
|
||||||
let stmt = pg().verified_stmt("COPY users FROM 'data.csv'");
|
let stmt = pg().verified_stmt("COPY users FROM 'data.csv'");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue