mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-31 19:27:21 +00:00
Support TABLE functions in FROM (#253)
Support `TABLE(...)` syntax in `FROM`, for example: select * from TABLE(SOME_FUNCTION(some_arg)) The ANSI spec allows routine invocations (and some other kinds of expressions we don't currently support) inside TABLE: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#PTF-derived-table https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#table-function-derived-table
This commit is contained in:
parent
a246d5da9a
commit
61431b087d
3 changed files with 59 additions and 9 deletions
|
@ -235,6 +235,11 @@ pub enum TableFactor {
|
|||
subquery: Box<Query>,
|
||||
alias: Option<TableAlias>,
|
||||
},
|
||||
/// `TABLE(<expr>)[ AS <alias> ]`
|
||||
TableFunction {
|
||||
expr: Expr,
|
||||
alias: Option<TableAlias>,
|
||||
},
|
||||
/// Represents a parenthesized table factor. The SQL spec only allows a
|
||||
/// join expression (`(foo <JOIN> bar [ <JOIN> baz ... ])`) to be nested,
|
||||
/// possibly several times, but the parser also accepts the non-standard
|
||||
|
@ -278,6 +283,13 @@ impl fmt::Display for TableFactor {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
TableFactor::TableFunction { expr, alias } => {
|
||||
write!(f, "TABLE({})", expr)?;
|
||||
if let Some(alias) = alias {
|
||||
write!(f, " AS {}", alias)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
TableFactor::NestedJoin(table_reference) => write!(f, "({})", table_reference),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2066,10 +2066,15 @@ impl Parser {
|
|||
if !self.consume_token(&Token::LParen) {
|
||||
self.expected("subquery after LATERAL", self.peek_token())?;
|
||||
}
|
||||
return self.parse_derived_table_factor(Lateral);
|
||||
}
|
||||
|
||||
if self.consume_token(&Token::LParen) {
|
||||
self.parse_derived_table_factor(Lateral)
|
||||
} else if self.parse_keyword(Keyword::TABLE) {
|
||||
// parse table function (SELECT * FROM TABLE (<expr>) [ AS <alias> ])
|
||||
self.expect_token(&Token::LParen)?;
|
||||
let expr = self.parse_expr()?;
|
||||
self.expect_token(&Token::RParen)?;
|
||||
let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?;
|
||||
Ok(TableFactor::TableFunction { expr, alias })
|
||||
} else if self.consume_token(&Token::LParen) {
|
||||
// A left paren introduces either a derived table (i.e., a subquery)
|
||||
// or a nested join. It's nearly impossible to determine ahead of
|
||||
// time which it is... so we just try to parse both.
|
||||
|
|
|
@ -1158,8 +1158,8 @@ fn parse_create_table_with_multiple_on_delete_fails() {
|
|||
|
||||
#[test]
|
||||
fn parse_assert() {
|
||||
let sql = "ASSERT (SELECT COUNT(*) FROM table) > 0";
|
||||
let ast = one_statement_parses_to(sql, "ASSERT (SELECT COUNT(*) FROM table) > 0");
|
||||
let sql = "ASSERT (SELECT COUNT(*) FROM my_table) > 0";
|
||||
let ast = one_statement_parses_to(sql, "ASSERT (SELECT COUNT(*) FROM my_table) > 0");
|
||||
match ast {
|
||||
Statement::Assert {
|
||||
condition: _condition,
|
||||
|
@ -1173,10 +1173,10 @@ fn parse_assert() {
|
|||
|
||||
#[test]
|
||||
fn parse_assert_message() {
|
||||
let sql = "ASSERT (SELECT COUNT(*) FROM table) > 0 AS 'No rows in table'";
|
||||
let sql = "ASSERT (SELECT COUNT(*) FROM my_table) > 0 AS 'No rows in my_table'";
|
||||
let ast = one_statement_parses_to(
|
||||
sql,
|
||||
"ASSERT (SELECT COUNT(*) FROM table) > 0 AS 'No rows in table'",
|
||||
"ASSERT (SELECT COUNT(*) FROM my_table) > 0 AS 'No rows in my_table'",
|
||||
);
|
||||
match ast {
|
||||
Statement::Assert {
|
||||
|
@ -1184,7 +1184,7 @@ fn parse_assert_message() {
|
|||
message: Some(message),
|
||||
} => {
|
||||
match message {
|
||||
Expr::Value(Value::SingleQuotedString(s)) => assert_eq!(s, "No rows in table"),
|
||||
Expr::Value(Value::SingleQuotedString(s)) => assert_eq!(s, "No rows in my_table"),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
@ -1864,6 +1864,39 @@ fn parse_simple_math_expr_minus() {
|
|||
verified_only_select(sql);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_table_function() {
|
||||
let select = verified_only_select("SELECT * FROM TABLE(FUN('1')) AS a");
|
||||
|
||||
match only(select.from).relation {
|
||||
TableFactor::TableFunction { expr, alias } => {
|
||||
let expected_expr = Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("FUN")]),
|
||||
args: vec![FunctionArg::Unnamed(Expr::Value(
|
||||
Value::SingleQuotedString("1".to_owned()),
|
||||
))],
|
||||
over: None,
|
||||
distinct: false,
|
||||
});
|
||||
assert_eq!(expr, expected_expr);
|
||||
assert_eq!(alias, table_alias("a"))
|
||||
}
|
||||
_ => panic!("Expecting TableFactor::TableFunction"),
|
||||
}
|
||||
|
||||
let res = parse_sql_statements("SELECT * FROM TABLE '1' AS a");
|
||||
assert_eq!(
|
||||
ParserError::ParserError("Expected (, found: \'1\'".to_string()),
|
||||
res.unwrap_err()
|
||||
);
|
||||
|
||||
let res = parse_sql_statements("SELECT * FROM TABLE (FUN(a) AS a");
|
||||
assert_eq!(
|
||||
ParserError::ParserError("Expected ), found: AS".to_string()),
|
||||
res.unwrap_err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_delimited_identifiers() {
|
||||
// check that quoted identifiers in any position remain quoted after serialization
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue