[CALCITE-6254] Support table function calls in FROM clause without TABLE() wrapper
diff --git a/core/src/main/codegen/templates/Parser.jj b/core/src/main/codegen/templates/Parser.jj
index 90497ac..fa7c018 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -2200,12 +2200,20 @@
{
(
LOOKAHEAD(2)
- tableName = CompoundTableIdentifier()
- ( tableRef = TableHints(tableName) | { tableRef = tableName; } )
- [ tableRef = ExtendTable(tableRef) ]
- tableRef = Over(tableRef)
- [ tableRef = Snapshot(tableRef) ]
- [ tableRef = MatchRecognize(tableRef) ]
+ tableName = CompoundTableIdentifier() { s = span(); }
+ (
+ // Table call syntax like FROM a.b() instead of FROM TABLE(a.b())
+ // Three tokens needed to disambiguate EXTEND syntax from CALCITE-493.
+ // Example: "FROM EventLog(lastGCTime TIME)".
+ LOOKAHEAD(3)
+ tableRef = ImplicitTableFunctionCallArgs(tableName)
+ |
+ ( tableRef = TableHints(tableName) | { tableRef = tableName; } )
+ [ tableRef = ExtendTable(tableRef) ]
+ tableRef = Over(tableRef)
+ [ tableRef = Snapshot(tableRef) ]
+ [ tableRef = MatchRecognize(tableRef) ]
+ )
|
LOOKAHEAD(2)
[ <LATERAL> { lateral = true; } ]
@@ -2395,6 +2403,38 @@
}
}
+SqlNode ImplicitTableFunctionCallArgs(SqlIdentifier name) :
+{
+ final List<SqlNode> tableFuncArgs = new ArrayList<SqlNode>();
+ final SqlNode call;
+ final Span s;
+}
+{
+ // Table call syntax like FROM a.b() instead of FROM TABLE(a.b())
+ // We've already parsed the name, so we don't use NamedRoutineCall.
+ { s = span(); }
+ <LPAREN>
+ [
+ AddArg0(tableFuncArgs, ExprContext.ACCEPT_CURSOR)
+ (
+ <COMMA> {
+ // a comma-list can't appear where only a query is expected
+ checkNonQueryExpression(ExprContext.ACCEPT_CURSOR);
+ }
+ AddArg(tableFuncArgs, ExprContext.ACCEPT_CURSOR)
+ )*
+ ]
+ <RPAREN>
+ {
+ final SqlParserPos pos = s.end(this);
+ call = createCall(name, pos,
+ SqlFunctionCategory.USER_DEFINED_TABLE_FUNCTION, null,
+ tableFuncArgs);
+ return SqlStdOperatorTable.COLLECTION_TABLE.createCall(pos,
+ call);
+ }
+}
+
SqlNode TableFunctionCall() :
{
final Span s;
diff --git a/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java b/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java
index 32b7bb2..a8ed3e6 100644
--- a/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java
+++ b/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java
@@ -3416,10 +3416,9 @@
.ok(expected);
}
- /** Even in SQL Server conformance mode, we do not yet support
- * 'function(args)' as an abbreviation for 'table(function(args)'. */
+ /** We now support 'function(args)' as an abbreviation for 'table(function(args)'. */
@Test void testOuterApplyFunctionFails() {
- final String sql = "select * from dept outer apply ramp(deptno^)^)";
+ final String sql = "select * from dept outer apply ramp(deptno)^)^";
sql(sql)
.withConformance(SqlConformanceEnum.SQL_SERVER_2008)
.fails("(?s).*Encountered \"\\)\" at .*");
@@ -4592,13 +4591,20 @@
sql(sql).ok(expected);
}
- @Test void testTableFunction() {
+ @Test void testTableFunctionWithTableWrapper() {
final String sql = "select * from table(score(table orders))";
final String expected = "SELECT *\n"
+ "FROM TABLE(`SCORE`((TABLE `ORDERS`)))";
sql(sql).ok(expected);
}
+ @Test void testTableFunctionWithoutTableWrapper() {
+ final String sql = "select * from score(table orders)";
+ final String expected = "SELECT *\n"
+ + "FROM TABLE(`SCORE`((TABLE `ORDERS`)))";
+ sql(sql).ok(expected);
+ }
+
@Test void testTableFunctionWithPartitionKey() {
// test one partition key for input table
final String sql = "select * from table(topn(table orders partition by productid, 3))";