Skip to content

Commit af73c9c

Browse files
MazterQyoumcheshkov
authored andcommitted
feat: Add PostgreSQL array subquery constructor
Can drop this after rebase on commit 31ba001 "Support PostgreSQL array subquery constructor (apache#566)", first released in 0.21.0
1 parent 9c3d6a2 commit af73c9c

File tree

4 files changed

+81
-1
lines changed

4 files changed

+81
-1
lines changed

src/ast/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@ pub enum Expr {
401401
},
402402
/// An array expression e.g. `ARRAY[1, 2]`
403403
Array(Array),
404+
/// An array subquery constructor, e.g. `array(SELECT 1 UNION SELECT 2)`
405+
ArraySubquery(Box<Query>),
404406
}
405407

406408
impl fmt::Display for Expr {
@@ -576,6 +578,7 @@ impl fmt::Display for Expr {
576578
}
577579
Expr::Exists(s) => write!(f, "EXISTS ({})", s),
578580
Expr::Subquery(s) => write!(f, "({})", s),
581+
Expr::ArraySubquery(s) => write!(f, "ARRAY({})", s),
579582
Expr::ListAgg(listagg) => write!(f, "{}", listagg),
580583
Expr::GroupingSets(sets) => {
581584
write!(f, "GROUPING SETS (")?;

src/parser.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,13 @@ impl<'a> Parser<'a> {
453453
self.expect_token(&Token::LBracket)?;
454454
self.parse_array_expr(true)
455455
}
456+
Keyword::ARRAY
457+
if dialect_of!(self is PostgreSqlDialect | GenericDialect)
458+
&& self.peek_token() == Token::LParen =>
459+
{
460+
self.expect_token(&Token::LParen)?;
461+
self.parse_array_subquery()
462+
}
456463
Keyword::NOT => Ok(Expr::UnaryOp {
457464
op: UnaryOperator::Not,
458465
expr: Box::new(self.parse_subexpr(Self::UNARY_NOT_PREC)?),
@@ -911,6 +918,13 @@ impl<'a> Parser<'a> {
911918
}
912919
}
913920

921+
/// Parses an array subquery `ARRAY(SELECT 1 UNION SELECT 2)`
922+
pub fn parse_array_subquery(&mut self) -> Result<Expr, ParserError> {
923+
let subquery = self.parse_query()?;
924+
self.expect_token(&Token::RParen)?;
925+
Ok(Expr::ArraySubquery(Box::new(subquery)))
926+
}
927+
914928
/// Parse a SQL LISTAGG expression, e.g. `LISTAGG(...) WITHIN GROUP (ORDER BY ...)`.
915929
pub fn parse_listagg_expr(&mut self) -> Result<Expr, ParserError> {
916930
self.expect_token(&Token::LParen)?;

tests/sqlparser_common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2439,7 +2439,7 @@ fn parse_bad_constraint() {
24392439

24402440
#[test]
24412441
fn parse_scalar_function_in_projection() {
2442-
let names = vec!["sqrt", "array", "foo"];
2442+
let names = vec!["sqrt", "foo"];
24432443

24442444
for function_name in names {
24452445
// like SELECT sqrt(id) FROM foo

tests/sqlparser_postgres.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,69 @@ fn parse_array_index_expr() {
12411241
);
12421242
}
12431243

1244+
#[test]
1245+
fn parse_array_subquery_expr() {
1246+
let sql = "SELECT ARRAY(SELECT 1 UNION SELECT 2)";
1247+
let select = pg().verified_only_select(sql);
1248+
assert_eq!(
1249+
&Expr::ArraySubquery(Box::new(Query {
1250+
with: None,
1251+
body: SetExpr::SetOperation {
1252+
op: SetOperator::Union,
1253+
all: false,
1254+
left: Box::new(SetExpr::Select(Box::new(Select {
1255+
distinct: false,
1256+
top: None,
1257+
projection: vec![SelectItem::UnnamedExpr(Expr::Value(Value::Number(
1258+
#[cfg(not(feature = "bigdecimal"))]
1259+
"1".to_string(),
1260+
#[cfg(feature = "bigdecimal")]
1261+
"1".parse().unwrap(),
1262+
false,
1263+
)))],
1264+
into: None,
1265+
from: vec![],
1266+
lateral_views: vec![],
1267+
selection: None,
1268+
group_by: vec![],
1269+
cluster_by: vec![],
1270+
distribute_by: vec![],
1271+
sort_by: vec![],
1272+
having: None,
1273+
qualify: None,
1274+
}))),
1275+
right: Box::new(SetExpr::Select(Box::new(Select {
1276+
distinct: false,
1277+
top: None,
1278+
projection: vec![SelectItem::UnnamedExpr(Expr::Value(Value::Number(
1279+
#[cfg(not(feature = "bigdecimal"))]
1280+
"2".to_string(),
1281+
#[cfg(feature = "bigdecimal")]
1282+
"2".parse().unwrap(),
1283+
false,
1284+
)))],
1285+
into: None,
1286+
from: vec![],
1287+
lateral_views: vec![],
1288+
selection: None,
1289+
group_by: vec![],
1290+
cluster_by: vec![],
1291+
distribute_by: vec![],
1292+
sort_by: vec![],
1293+
having: None,
1294+
qualify: None,
1295+
}))),
1296+
},
1297+
order_by: vec![],
1298+
limit: None,
1299+
offset: None,
1300+
fetch: None,
1301+
lock: None,
1302+
})),
1303+
expr_from_projection(only(&select.projection)),
1304+
);
1305+
}
1306+
12441307
#[test]
12451308
fn test_transaction_statement() {
12461309
let statement = pg().verified_stmt("SET TRANSACTION SNAPSHOT '000003A1-1'");

0 commit comments

Comments
 (0)