Skip to content

Commit 61431b0

Browse files
authored
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
1 parent a246d5d commit 61431b0

File tree

3 files changed

+59
-9
lines changed

3 files changed

+59
-9
lines changed

src/ast/query.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ pub enum TableFactor {
235235
subquery: Box<Query>,
236236
alias: Option<TableAlias>,
237237
},
238+
/// `TABLE(<expr>)[ AS <alias> ]`
239+
TableFunction {
240+
expr: Expr,
241+
alias: Option<TableAlias>,
242+
},
238243
/// Represents a parenthesized table factor. The SQL spec only allows a
239244
/// join expression (`(foo <JOIN> bar [ <JOIN> baz ... ])`) to be nested,
240245
/// possibly several times, but the parser also accepts the non-standard
@@ -278,6 +283,13 @@ impl fmt::Display for TableFactor {
278283
}
279284
Ok(())
280285
}
286+
TableFactor::TableFunction { expr, alias } => {
287+
write!(f, "TABLE({})", expr)?;
288+
if let Some(alias) = alias {
289+
write!(f, " AS {}", alias)?;
290+
}
291+
Ok(())
292+
}
281293
TableFactor::NestedJoin(table_reference) => write!(f, "({})", table_reference),
282294
}
283295
}

src/parser.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,10 +2066,15 @@ impl Parser {
20662066
if !self.consume_token(&Token::LParen) {
20672067
self.expected("subquery after LATERAL", self.peek_token())?;
20682068
}
2069-
return self.parse_derived_table_factor(Lateral);
2070-
}
2071-
2072-
if self.consume_token(&Token::LParen) {
2069+
self.parse_derived_table_factor(Lateral)
2070+
} else if self.parse_keyword(Keyword::TABLE) {
2071+
// parse table function (SELECT * FROM TABLE (<expr>) [ AS <alias> ])
2072+
self.expect_token(&Token::LParen)?;
2073+
let expr = self.parse_expr()?;
2074+
self.expect_token(&Token::RParen)?;
2075+
let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?;
2076+
Ok(TableFactor::TableFunction { expr, alias })
2077+
} else if self.consume_token(&Token::LParen) {
20732078
// A left paren introduces either a derived table (i.e., a subquery)
20742079
// or a nested join. It's nearly impossible to determine ahead of
20752080
// time which it is... so we just try to parse both.

tests/sqlparser_common.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,8 +1158,8 @@ fn parse_create_table_with_multiple_on_delete_fails() {
11581158

11591159
#[test]
11601160
fn parse_assert() {
1161-
let sql = "ASSERT (SELECT COUNT(*) FROM table) > 0";
1162-
let ast = one_statement_parses_to(sql, "ASSERT (SELECT COUNT(*) FROM table) > 0");
1161+
let sql = "ASSERT (SELECT COUNT(*) FROM my_table) > 0";
1162+
let ast = one_statement_parses_to(sql, "ASSERT (SELECT COUNT(*) FROM my_table) > 0");
11631163
match ast {
11641164
Statement::Assert {
11651165
condition: _condition,
@@ -1173,18 +1173,18 @@ fn parse_assert() {
11731173

11741174
#[test]
11751175
fn parse_assert_message() {
1176-
let sql = "ASSERT (SELECT COUNT(*) FROM table) > 0 AS 'No rows in table'";
1176+
let sql = "ASSERT (SELECT COUNT(*) FROM my_table) > 0 AS 'No rows in my_table'";
11771177
let ast = one_statement_parses_to(
11781178
sql,
1179-
"ASSERT (SELECT COUNT(*) FROM table) > 0 AS 'No rows in table'",
1179+
"ASSERT (SELECT COUNT(*) FROM my_table) > 0 AS 'No rows in my_table'",
11801180
);
11811181
match ast {
11821182
Statement::Assert {
11831183
condition: _condition,
11841184
message: Some(message),
11851185
} => {
11861186
match message {
1187-
Expr::Value(Value::SingleQuotedString(s)) => assert_eq!(s, "No rows in table"),
1187+
Expr::Value(Value::SingleQuotedString(s)) => assert_eq!(s, "No rows in my_table"),
11881188
_ => unreachable!(),
11891189
};
11901190
}
@@ -1864,6 +1864,39 @@ fn parse_simple_math_expr_minus() {
18641864
verified_only_select(sql);
18651865
}
18661866

1867+
#[test]
1868+
fn parse_table_function() {
1869+
let select = verified_only_select("SELECT * FROM TABLE(FUN('1')) AS a");
1870+
1871+
match only(select.from).relation {
1872+
TableFactor::TableFunction { expr, alias } => {
1873+
let expected_expr = Expr::Function(Function {
1874+
name: ObjectName(vec![Ident::new("FUN")]),
1875+
args: vec![FunctionArg::Unnamed(Expr::Value(
1876+
Value::SingleQuotedString("1".to_owned()),
1877+
))],
1878+
over: None,
1879+
distinct: false,
1880+
});
1881+
assert_eq!(expr, expected_expr);
1882+
assert_eq!(alias, table_alias("a"))
1883+
}
1884+
_ => panic!("Expecting TableFactor::TableFunction"),
1885+
}
1886+
1887+
let res = parse_sql_statements("SELECT * FROM TABLE '1' AS a");
1888+
assert_eq!(
1889+
ParserError::ParserError("Expected (, found: \'1\'".to_string()),
1890+
res.unwrap_err()
1891+
);
1892+
1893+
let res = parse_sql_statements("SELECT * FROM TABLE (FUN(a) AS a");
1894+
assert_eq!(
1895+
ParserError::ParserError("Expected ), found: AS".to_string()),
1896+
res.unwrap_err()
1897+
);
1898+
}
1899+
18671900
#[test]
18681901
fn parse_delimited_identifiers() {
18691902
// check that quoted identifiers in any position remain quoted after serialization

0 commit comments

Comments
 (0)