mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-04 06:18:17 +00:00
add support for postgres composite types (#466)
* add support for postgres composite types Signed-off-by: password <rbalajis25@gmail.com> * fix composite test for bigdecimal feature Signed-off-by: password <rbalajis25@gmail.com>
This commit is contained in:
parent
6b2fc8102f
commit
ed86c6d53d
3 changed files with 81 additions and 1 deletions
|
@ -231,6 +231,11 @@ pub enum Expr {
|
|||
operator: JsonOperator,
|
||||
right: Box<Expr>,
|
||||
},
|
||||
/// CompositeAccess (postgres) eg: SELECT (information_schema._pg_expandarray(array['i','i'])).n
|
||||
CompositeAccess {
|
||||
expr: Box<Expr>,
|
||||
key: Ident,
|
||||
},
|
||||
/// `IS NULL` operator
|
||||
IsNull(Box<Expr>),
|
||||
/// `IS NOT NULL` operator
|
||||
|
@ -565,6 +570,9 @@ impl fmt::Display for Expr {
|
|||
} => {
|
||||
write!(f, "{} {} {}", left, operator, right)
|
||||
}
|
||||
Expr::CompositeAccess { expr, key } => {
|
||||
write!(f, "{}.{}", expr, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -518,7 +518,18 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
};
|
||||
self.expect_token(&Token::RParen)?;
|
||||
Ok(expr)
|
||||
if !self.consume_token(&Token::Period) {
|
||||
return Ok(expr);
|
||||
}
|
||||
let tok = self.next_token();
|
||||
let key = match tok {
|
||||
Token::Word(word) => word.to_ident(),
|
||||
_ => return parser_err!(format!("Expected identifier, found: {}", tok)),
|
||||
};
|
||||
Ok(Expr::CompositeAccess {
|
||||
expr: Box::new(expr),
|
||||
key,
|
||||
})
|
||||
}
|
||||
Token::Placeholder(_) => {
|
||||
self.prev_token();
|
||||
|
|
|
@ -1334,6 +1334,67 @@ fn test_json() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_composite_value() {
|
||||
let sql = "SELECT (on_hand.item).name FROM on_hand WHERE (on_hand.item).price > 9";
|
||||
let select = pg().verified_only_select(sql);
|
||||
assert_eq!(
|
||||
SelectItem::UnnamedExpr(Expr::CompositeAccess {
|
||||
key: Ident::new("name"),
|
||||
expr: Box::new(Expr::Nested(Box::new(Expr::CompoundIdentifier(vec![
|
||||
Ident::new("on_hand"),
|
||||
Ident::new("item")
|
||||
]))))
|
||||
}),
|
||||
select.projection[0]
|
||||
);
|
||||
|
||||
#[cfg(feature = "bigdecimal")]
|
||||
let num: Expr = Expr::Value(Value::Number(bigdecimal::BigDecimal::from(9), false));
|
||||
#[cfg(not(feature = "bigdecimal"))]
|
||||
let num: Expr = Expr::Value(Value::Number("9".to_string(), false));
|
||||
assert_eq!(
|
||||
select.selection,
|
||||
Some(Expr::BinaryOp {
|
||||
left: Box::new(Expr::CompositeAccess {
|
||||
key: Ident::new("price"),
|
||||
expr: Box::new(Expr::Nested(Box::new(Expr::CompoundIdentifier(vec![
|
||||
Ident::new("on_hand"),
|
||||
Ident::new("item")
|
||||
]))))
|
||||
}),
|
||||
op: BinaryOperator::Gt,
|
||||
right: Box::new(num)
|
||||
})
|
||||
);
|
||||
|
||||
let sql = "SELECT (information_schema._pg_expandarray(ARRAY['i', 'i'])).n";
|
||||
let select = pg().verified_only_select(sql);
|
||||
assert_eq!(
|
||||
SelectItem::UnnamedExpr(Expr::CompositeAccess {
|
||||
key: Ident::new("n"),
|
||||
expr: Box::new(Expr::Nested(Box::new(Expr::Function(Function {
|
||||
name: ObjectName(vec![
|
||||
Ident::new("information_schema"),
|
||||
Ident::new("_pg_expandarray")
|
||||
]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Array(
|
||||
Array {
|
||||
elem: vec![
|
||||
Expr::Value(Value::SingleQuotedString("i".to_string())),
|
||||
Expr::Value(Value::SingleQuotedString("i".to_string())),
|
||||
],
|
||||
named: true
|
||||
}
|
||||
)))],
|
||||
over: None,
|
||||
distinct: false,
|
||||
}))))
|
||||
}),
|
||||
select.projection[0]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_comments() {
|
||||
match pg().verified_stmt("COMMENT ON COLUMN tab.name IS 'comment'") {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue