From 17d1aade52808132645b563659430614e1ffb440 Mon Sep 17 00:00:00 2001 From: Fabian Hueske Date: Thu, 7 May 2026 16:54:18 +0200 Subject: [PATCH 1/2] [FLINK-39780][table] Make TABLE keyword optional in LATERAL context Extend the SQL parser accept the implicit table-function-call form (e.g. "FROM t, LATERAL fn(args)") in addition to the explicit "LATERAL TABLE(fn(args))" form. Mirrors FLINK-36824, which made the TABLE wrapper optional outside LATERAL. Add tests in FlinkSqlParserImplTest and overwrites methods in Calcite's SqlParserTest that need adjustments. --- .../src/main/codegen/templates/Parser.jj | 10 ++ .../sql/parser/FlinkSqlParserImplTest.java | 144 ++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/flink-table/flink-sql-parser/src/main/codegen/templates/Parser.jj b/flink-table/flink-sql-parser/src/main/codegen/templates/Parser.jj index 1f0ae3d455cd8..8d66364d37374 100644 --- a/flink-table/flink-sql-parser/src/main/codegen/templates/Parser.jj +++ b/flink-table/flink-sql-parser/src/main/codegen/templates/Parser.jj @@ -2236,6 +2236,16 @@ SqlNode TableRef3(ExprContext exprContext, boolean lateral) : { tableRef = unnestOp.createCall(s.end(this), (List) args); } + | + // LATERAL with implicit table function call syntax, + // e.g. "FROM t, LATERAL fn(...)" instead of "FROM t, LATERAL TABLE(fn(...))". + // The non-LATERAL implicit form is handled by the CompoundTableIdentifier + // branch above. + LOOKAHEAD(2) + { lateral = true; } + tableName = CompoundTableIdentifier() + tableRef = ImplicitTableFunctionCallArgs(tableName) + tableRef = addLateral(tableRef, lateral) | [ { lateral = true; } ] tableRef = TableFunctionCall() diff --git a/flink-table/flink-sql-parser/src/test/java/org/apache/flink/sql/parser/FlinkSqlParserImplTest.java b/flink-table/flink-sql-parser/src/test/java/org/apache/flink/sql/parser/FlinkSqlParserImplTest.java index 1d1e7d639fa00..492482bb0ba51 100644 --- a/flink-table/flink-sql-parser/src/test/java/org/apache/flink/sql/parser/FlinkSqlParserImplTest.java +++ b/flink-table/flink-sql-parser/src/test/java/org/apache/flink/sql/parser/FlinkSqlParserImplTest.java @@ -4018,6 +4018,150 @@ void testOuterApplyFunctionFails() { .fails("(?s).*Encountered \"\\)\" at .*"); } + /** + * Overrides the parent {@link org.apache.calcite.sql.parser.SqlParserTest#testLateral()} + * because Flink makes the {@code TABLE} keyword optional inside {@code LATERAL}. With this + * change, {@code LATERAL } is the start of an implicit table-function call; the + * parser expects an argument list next, so the error position shifts. + */ + @Test + void testLateral() { + // This is the only test case that differs from Calcite's SqlParserTest.testLateral(). + // LATERAL is now interpreted as an implicit table function + // call; the error moves to where the argument list (LPAREN) is missing. + sql("select * from lateral em^p^").fails("(?s)Encountered \"\" at .*"); + + // All other test cases are identical to Calcite's SqlParserTest.testLateral(). + // LATERAL TABLE still fails at the identifier (no LPAREN). + sql("select * from lateral table ^emp^ as e").fails("(?s)Encountered \"emp\" at .*"); + sql("select * from lateral table ^scott^.emp").fails("(?s)Encountered \"scott\" at .*"); + + final String expected = "SELECT *\n" + "FROM LATERAL TABLE(`RAMP`(1))"; + + // Good: LATERAL TABLE function(arg, arg) + sql("select * from lateral table(ramp(1))").ok(expected); + sql("select * from lateral table(ramp(1)) as t").ok(expected + " AS `T`"); + sql("select * from lateral table(ramp(1)) as t(x)").ok(expected + " AS `T` (`X`)"); + // Bad: Parentheses make it look like a sub-query + sql("select * from lateral (^table (ramp(1))^)").fails("Expected query or join"); + + // Good: LATERAL (subQuery) + final String expected2 = "SELECT *\n" + "FROM LATERAL (SELECT *\n" + "FROM `EMP`)"; + sql("select * from lateral (select * from emp)").ok(expected2); + sql("select * from lateral (select * from emp) as t").ok(expected2 + " AS `T`"); + sql("select * from lateral (select * from emp) as t(x)").ok(expected2 + " AS `T` (`X`)"); + } + + /** + * Overrides the parent {@link org.apache.calcite.sql.parser.SqlParserTest#testTemporalTable()} + * for the same reason as {@link #testLateral()}: with the implicit table-function call form, + * {@code LATERAL products_temporal} now parses successfully and the error shifts to the next + * unexpected token ({@code for}). + */ + @Test + void testTemporalTable() { + // This test case is identical to Calcite's SqlParserTest.testTemporalTable(). + final String sql0 = + "select stream * from orders, products\n" + + "for system_time as of TIMESTAMP '2011-01-02 00:00:00'"; + final String expected0 = + "SELECT STREAM *\n" + + "FROM `ORDERS`,\n" + + "`PRODUCTS` FOR SYSTEM_TIME AS OF TIMESTAMP '2011-01-02 00:00:00'"; + sql(sql0).ok(expected0); + + // This is the only test case that differs from Calcite's SqlParserTest.testTemporalTable(). + // Cannot use explicit LATERAL keyword. Error now points to "for" + // (the token after the implicit-table-function-call name). + final String sql1 = + "select stream * from orders, LATERAL products_temporal\n" + + "^for^ system_time as of TIMESTAMP '2011-01-02 00:00:00'"; + sql(sql1).fails("(?s)Encountered \"for\" at line .*"); + + // All following test cases are identical to Calcite's SqlParserTest.testTemporalTable(). + // Inner join with a specific timestamp + final String sql2 = + "select stream * from orders join products_temporal\n" + + "for system_time as of timestamp '2011-01-02 00:00:00'\n" + + "on orders.productid = products_temporal.productid"; + final String expected2 = + "SELECT STREAM *\n" + + "FROM `ORDERS`\n" + + "INNER JOIN `PRODUCTS_TEMPORAL` " + + "FOR SYSTEM_TIME AS OF TIMESTAMP '2011-01-02 00:00:00' " + + "ON (`ORDERS`.`PRODUCTID` = `PRODUCTS_TEMPORAL`.`PRODUCTID`)"; + sql(sql2).ok(expected2); + + // Left join with a timestamp field + final String sql3 = + "select stream * from orders left join products_temporal\n" + + "for system_time as of orders.rowtime " + + "on orders.productid = products_temporal.productid"; + final String expected3 = + "SELECT STREAM *\n" + + "FROM `ORDERS`\n" + + "LEFT JOIN `PRODUCTS_TEMPORAL` " + + "FOR SYSTEM_TIME AS OF `ORDERS`.`ROWTIME` " + + "ON (`ORDERS`.`PRODUCTID` = `PRODUCTS_TEMPORAL`.`PRODUCTID`)"; + sql(sql3).ok(expected3); + + // Left join with a timestamp expression + final String sql4 = + "select stream * from orders left join products_temporal\n" + + "for system_time as of orders.rowtime - INTERVAL '3' DAY " + + "on orders.productid = products_temporal.productid"; + final String expected4 = + "SELECT STREAM *\n" + + "FROM `ORDERS`\n" + + "LEFT JOIN `PRODUCTS_TEMPORAL` " + + "FOR SYSTEM_TIME AS OF (`ORDERS`.`ROWTIME` - INTERVAL '3' DAY) " + + "ON (`ORDERS`.`PRODUCTID` = `PRODUCTS_TEMPORAL`.`PRODUCTID`)"; + sql(sql4).ok(expected4); + } + + @Test + void testLateralImplicitTableFunction() { + // LATERAL allows the implicit table-function-call form (no outer + // TABLE(...) wrapper). The non-LATERAL form was already backported + // in FLINK-36824. + sql("select * from t, lateral ramp(t.x)") + .ok("SELECT *\n" + "FROM `T`,\n" + "LATERAL TABLE(`RAMP`(`T`.`X`))"); + + // Backward-compatible: explicit TABLE wrapper still works. + sql("select * from t, lateral table(ramp(t.x))") + .ok("SELECT *\n" + "FROM `T`,\n" + "LATERAL TABLE(`RAMP`(`T`.`X`))"); + + // CROSS JOIN form. + sql("select * from t cross join lateral ramp(t.x) on true") + .ok( + "SELECT *\n" + + "FROM `T`\n" + + "CROSS JOIN LATERAL TABLE(`RAMP`(`T`.`X`)) ON TRUE"); + + // LEFT JOIN form with ON condition. + sql("select * from t left join lateral ramp(t.x) on t.a = 1") + .ok( + "SELECT *\n" + + "FROM `T`\n" + + "LEFT JOIN LATERAL TABLE(`RAMP`(`T`.`X`)) ON (`T`.`A` = 1)"); + + // Named arguments and TABLE-typed arg passed to the function. + sql("select * from t, lateral snapshot(" + + "input => table s, " + + "load_completed_condition => 'on_time')") + .ok( + "SELECT *\n" + + "FROM `T`,\n" + + "LATERAL TABLE(`SNAPSHOT`(" + + "`INPUT` => (TABLE `S`), " + + "`LOAD_COMPLETED_CONDITION` => 'on_time'))"); + + // LATERAL fn(...) as the very first FROM entry (no preceding table). The function call + // doesn't reference any outer column but the LATERAL keyword is still permitted by the + // grammar. + sql("select * from lateral ramp(3)").ok("SELECT *\n" + "FROM LATERAL TABLE(`RAMP`(3))"); + } + @Test void testVariantType() { sql("CREATE TABLE t (\n" + "v variant" + "\n)") From f71f7a8e2eca1d79b9d5236c8c0a1f4527b4cce8 Mon Sep 17 00:00:00 2001 From: Fabian Hueske Date: Fri, 29 May 2026 10:20:04 +0200 Subject: [PATCH 2/2] [FLINK-39780][docs] Adjust documentation to implicit LATERAL table function calls --- .../temporal_table_function.md | 2 +- docs/content.zh/docs/dev/table/functions/udfs.md | 16 ++++++++-------- .../docs/sql/reference/queries/joins.md | 8 ++++---- .../docs/sql/reference/queries/overview.md | 3 ++- .../docs/sql/reference/queries/vector-search.md | 16 ++++++++-------- .../temporal_table_function.md | 2 +- docs/content/docs/dev/table/functions/udfs.md | 16 ++++++++-------- docs/content/docs/sql/reference/queries/joins.md | 8 ++++---- .../docs/sql/reference/queries/overview.md | 3 ++- .../docs/sql/reference/queries/vector-search.md | 16 ++++++++-------- 10 files changed, 46 insertions(+), 44 deletions(-) diff --git a/docs/content.zh/docs/concepts/sql-table-concepts/temporal_table_function.md b/docs/content.zh/docs/concepts/sql-table-concepts/temporal_table_function.md index c0ef280ff06ac..c4d3c405280d5 100644 --- a/docs/content.zh/docs/concepts/sql-table-concepts/temporal_table_function.md +++ b/docs/content.zh/docs/concepts/sql-table-concepts/temporal_table_function.md @@ -112,7 +112,7 @@ SELECT SUM(amount * rate) AS amount FROM orders, - LATERAL TABLE (rates(order_time)) + LATERAL rates(order_time) WHERE rates.currency = orders.currency ``` diff --git a/docs/content.zh/docs/dev/table/functions/udfs.md b/docs/content.zh/docs/dev/table/functions/udfs.md index bd4771fba2dae..55ec0b03e7176 100644 --- a/docs/content.zh/docs/dev/table/functions/udfs.md +++ b/docs/content.zh/docs/dev/table/functions/udfs.md @@ -1088,7 +1088,7 @@ env.sqlQuery("SELECT GetBeverageName(beverageId) FROM Beverages"); 在 Table API 中,表值函数是通过 `.joinLateral(...)` 或者 `.leftOuterJoinLateral(...)` 来使用的。`joinLateral` 算子会把外表(算子左侧的表)的每一行跟跟表值函数返回的所有行(位于算子右侧)进行 (cross)join。`leftOuterJoinLateral` 算子也是把外表(算子左侧的表)的每一行跟表值函数返回的所有行(位于算子右侧)进行(cross)join,并且如果表值函数返回 0 行也会保留外表的这一行。 -在 SQL 里面用 `JOIN` 或者 以 `ON TRUE` 为条件的 `LEFT JOIN` 来配合 `LATERAL TABLE()` 的使用。 +在 SQL 里面用 `JOIN` 或者 以 `ON TRUE` 为条件的 `LEFT JOIN` 来配合 `LATERAL (...)` 的使用(等价的写法为 `LATERAL TABLE((...))`)。 下面的例子展示了如何实现一个分隔函数并在查询里调用它,详情可参考[开发指南](#开发指南): @@ -1147,17 +1147,17 @@ env // 在 SQL 里调用注册好的函数 env.sqlQuery( "SELECT myField, word, length " + - "FROM MyTable, LATERAL TABLE(SplitFunction(myField))"); + "FROM MyTable, LATERAL SplitFunction(myField)"); env.sqlQuery( "SELECT myField, word, length " + "FROM MyTable " + - "LEFT JOIN LATERAL TABLE(SplitFunction(myField)) ON TRUE"); + "LEFT JOIN LATERAL SplitFunction(myField) ON TRUE"); // 在 SQL 里重命名函数字段 env.sqlQuery( "SELECT myField, newWord, newLength " + "FROM MyTable " + - "LEFT JOIN LATERAL TABLE(SplitFunction(myField)) AS T(newWord, newLength) ON TRUE"); + "LEFT JOIN LATERAL SplitFunction(myField) AS T(newWord, newLength) ON TRUE"); ``` {{< /tab >}} @@ -1212,17 +1212,17 @@ env // 在 SQL 里调用注册好的函数 env.sqlQuery( "SELECT myField, word, length " + - "FROM MyTable, LATERAL TABLE(SplitFunction(myField))"); + "FROM MyTable, LATERAL SplitFunction(myField)"); env.sqlQuery( "SELECT myField, word, length " + "FROM MyTable " + - "LEFT JOIN LATERAL TABLE(SplitFunction(myField)) ON TRUE") + "LEFT JOIN LATERAL SplitFunction(myField) ON TRUE") // 在 SQL 里重命名函数字段 env.sqlQuery( "SELECT myField, newWord, newLength " + "FROM MyTable " + - "LEFT JOIN LATERAL TABLE(SplitFunction(myField)) AS T(newWord, newLength) ON TRUE") + "LEFT JOIN LATERAL SplitFunction(myField) AS T(newWord, newLength) ON TRUE") ``` {{< /tab >}} @@ -1312,7 +1312,7 @@ env.from("MyTable") .select($("*")) // call registered function in SQL -env.sqlQuery("SELECT * FROM MyTable, LATERAL TABLE(BackgroundFunction(myField))"); +env.sqlQuery("SELECT * FROM MyTable, LATERAL BackgroundFunction(myField)"); ``` diff --git a/docs/content.zh/docs/sql/reference/queries/joins.md b/docs/content.zh/docs/sql/reference/queries/joins.md index a1e1db2caab8b..27ce6c55cf726 100644 --- a/docs/content.zh/docs/sql/reference/queries/joins.md +++ b/docs/content.zh/docs/sql/reference/queries/joins.md @@ -259,7 +259,7 @@ SELECT o_amount, r_rate FROM Orders, - LATERAL TABLE (Rates(o_proctime)) + LATERAL Rates(o_proctime) WHERE r_currency = o_currency ``` @@ -285,7 +285,7 @@ SELECT o_amount, r_rate FROM Orders, - LATERAL TABLE (Rates(o_proctime)) + LATERAL Rates(o_proctime) WHERE r_currency = o_currency ``` @@ -348,7 +348,7 @@ Table Function ```sql SELECT order_id, res FROM Orders, -LATERAL TABLE(table_func(order_id)) t(res) +LATERAL table_func(order_id) t(res) ``` ### LEFT OUTER JOIN @@ -358,7 +358,7 @@ LATERAL TABLE(table_func(order_id)) t(res) ```sql SELECT order_id, res FROM Orders -LEFT OUTER JOIN LATERAL TABLE(table_func(order_id)) t(res) +LEFT OUTER JOIN LATERAL table_func(order_id) t(res) ON TRUE ``` diff --git a/docs/content.zh/docs/sql/reference/queries/overview.md b/docs/content.zh/docs/sql/reference/queries/overview.md index 7373700ab52c8..18aba399c61f7 100644 --- a/docs/content.zh/docs/sql/reference/queries/overview.md +++ b/docs/content.zh/docs/sql/reference/queries/overview.md @@ -316,7 +316,8 @@ tableReference: tablePrimary: [ TABLE ] tablePath [ dynamicTableOptions ] [systemTimePeriod] [[AS] correlationName] - | LATERAL TABLE '(' functionName '(' expression [, expression ]* ')' ')' + | [ LATERAL ] functionName '(' expression [, expression ]* ')' + | [ LATERAL ] TABLE '(' functionName '(' expression [, expression ]* ')' ')' | [ LATERAL ] '(' query ')' | UNNEST '(' expression ')' diff --git a/docs/content.zh/docs/sql/reference/queries/vector-search.md b/docs/content.zh/docs/sql/reference/queries/vector-search.md index 415004cd5dcc2..978568932b9df 100644 --- a/docs/content.zh/docs/sql/reference/queries/vector-search.md +++ b/docs/content.zh/docs/sql/reference/queries/vector-search.md @@ -35,13 +35,13 @@ Flink SQL 提供了 `VECTOR_SEARCH` 表值函数 (TVF) 来在 SQL 查询中执 ### 语法 ```sql -SELECT * FROM input_table, LATERAL TABLE(VECTOR_SEARCH( +SELECT * FROM input_table, LATERAL VECTOR_SEARCH( TABLE vector_table, input_table.vector_column, DESCRIPTOR(index_column), top_k, [CONFIG => MAP['key', 'value']] - )) + ) ``` ### 参数 @@ -64,32 +64,32 @@ SELECT * FROM input_table, LATERAL TABLE(VECTOR_SEARCH( ```sql -- 基本用法 SELECT * FROM -input_table, LATERAL TABLE(VECTOR_SEARCH( +input_table, LATERAL VECTOR_SEARCH( TABLE vector_table, input_table.vector_column, DESCRIPTOR(index_column), 10 -)); +); -- 带配置选项 SELECT * FROM -input_table, LATERAL TABLE(VECTOR_SEARCH( +input_table, LATERAL VECTOR_SEARCH( TABLE vector_table, input_table.vector_column, DESCRIPTOR(index_column), 10, MAP['async', 'true', 'timeout', '100s'] -)); +); -- 使用命名参数 SELECT * FROM -input_table, LATERAL TABLE(VECTOR_SEARCH( +input_table, LATERAL VECTOR_SEARCH( SEARCH_TABLE => TABLE vector_table, COLUMN_TO_QUERY => input_table.vector_column, COLUMN_TO_SEARCH => DESCRIPTOR(index_column), TOP_K => 10, CONFIG => MAP['async', 'true', 'timeout', '100s'] -)); +); -- 使用常量值搜索 SELECT * FROM TABLE(VECTOR_SEARCH( diff --git a/docs/content/docs/concepts/sql-table-concepts/temporal_table_function.md b/docs/content/docs/concepts/sql-table-concepts/temporal_table_function.md index 90ae717f988cf..1f87a57512f0e 100644 --- a/docs/content/docs/concepts/sql-table-concepts/temporal_table_function.md +++ b/docs/content/docs/concepts/sql-table-concepts/temporal_table_function.md @@ -112,7 +112,7 @@ SELECT SUM(amount * rate) AS amount FROM orders, - LATERAL TABLE (rates(order_time)) + LATERAL rates(order_time) WHERE rates.currency = orders.currency ``` diff --git a/docs/content/docs/dev/table/functions/udfs.md b/docs/content/docs/dev/table/functions/udfs.md index 9441a28e1581b..1ca87ea99fb30 100644 --- a/docs/content/docs/dev/table/functions/udfs.md +++ b/docs/content/docs/dev/table/functions/udfs.md @@ -1130,7 +1130,7 @@ In order to define a table function, one has to extend the base class `TableFunc In the Table API, a table function is used with `.joinLateral(...)` or `.leftOuterJoinLateral(...)`. The `joinLateral` operator (cross) joins each row from the outer table (table on the left of the operator) with all rows produced by the table-valued function (which is on the right side of the operator). The `leftOuterJoinLateral` operator joins each row from the outer table (table on the left of the operator) with all rows produced by the table-valued function (which is on the right side of the operator) and preserves outer rows for which the table function returns an empty table. -In SQL, use `LATERAL TABLE()` with `JOIN` or `LEFT JOIN` with an `ON TRUE` join condition. +In SQL, use `LATERAL (...)` (or the equivalent `LATERAL TABLE((...))`) with `JOIN` or `LEFT JOIN` with an `ON TRUE` join condition. The following example shows how to define your own split function and call it in a query. See the [Implementation Guide](#implementation-guide) for more details. @@ -1189,17 +1189,17 @@ env // call registered function in SQL env.sqlQuery( "SELECT myField, word, length " + - "FROM MyTable, LATERAL TABLE(SplitFunction(myField))"); + "FROM MyTable, LATERAL SplitFunction(myField)"); env.sqlQuery( "SELECT myField, word, length " + "FROM MyTable " + - "LEFT JOIN LATERAL TABLE(SplitFunction(myField)) ON TRUE"); + "LEFT JOIN LATERAL SplitFunction(myField) ON TRUE"); // rename fields of the function in SQL env.sqlQuery( "SELECT myField, newWord, newLength " + "FROM MyTable " + - "LEFT JOIN LATERAL TABLE(SplitFunction(myField)) AS T(newWord, newLength) ON TRUE"); + "LEFT JOIN LATERAL SplitFunction(myField) AS T(newWord, newLength) ON TRUE"); ``` {{< /tab >}} @@ -1254,17 +1254,17 @@ env // call registered function in SQL env.sqlQuery( "SELECT myField, word, length " + - "FROM MyTable, LATERAL TABLE(SplitFunction(myField))") + "FROM MyTable, LATERAL SplitFunction(myField)") env.sqlQuery( "SELECT myField, word, length " + "FROM MyTable " + - "LEFT JOIN LATERAL TABLE(SplitFunction(myField)) ON TRUE") + "LEFT JOIN LATERAL SplitFunction(myField) ON TRUE") // rename fields of the function in SQL env.sqlQuery( "SELECT myField, newWord, newLength " + "FROM MyTable " + - "LEFT JOIN LATERAL TABLE(SplitFunction(myField)) AS T(newWord, newLength) ON TRUE") + "LEFT JOIN LATERAL SplitFunction(myField) AS T(newWord, newLength) ON TRUE") ``` {{< /tab >}} @@ -1354,7 +1354,7 @@ env.from("MyTable") .select($("*")) // call registered function in SQL -env.sqlQuery("SELECT * FROM MyTable, LATERAL TABLE(BackgroundFunction(myField))"); +env.sqlQuery("SELECT * FROM MyTable, LATERAL BackgroundFunction(myField)"); ``` diff --git a/docs/content/docs/sql/reference/queries/joins.md b/docs/content/docs/sql/reference/queries/joins.md index d000a46b822ce..8626c57f6e1e7 100644 --- a/docs/content/docs/sql/reference/queries/joins.md +++ b/docs/content/docs/sql/reference/queries/joins.md @@ -264,7 +264,7 @@ SELECT o_amount, r_rate FROM Orders, - LATERAL TABLE (Rates(o_proctime)) + LATERAL Rates(o_proctime) WHERE r_currency = o_currency ``` @@ -290,7 +290,7 @@ SELECT o_amount, r_rate FROM Orders, - LATERAL TABLE (Rates(o_proctime)) + LATERAL Rates(o_proctime) WHERE r_currency = o_currency ``` @@ -435,7 +435,7 @@ The row of the left (outer) table is dropped, if its table function call returns ```sql SELECT order_id, res FROM Orders, -LATERAL TABLE(table_func(order_id)) t(res) +LATERAL table_func(order_id) t(res) ``` ### LEFT OUTER JOIN @@ -445,7 +445,7 @@ If a table function call returns an empty result, the corresponding outer row is ```sql SELECT order_id, res FROM Orders -LEFT OUTER JOIN LATERAL TABLE(table_func(order_id)) t(res) +LEFT OUTER JOIN LATERAL table_func(order_id) t(res) ON TRUE ``` diff --git a/docs/content/docs/sql/reference/queries/overview.md b/docs/content/docs/sql/reference/queries/overview.md index 1b607d9681528..e5346941eabb4 100644 --- a/docs/content/docs/sql/reference/queries/overview.md +++ b/docs/content/docs/sql/reference/queries/overview.md @@ -316,7 +316,8 @@ tableReference: tablePrimary: [ TABLE ] tablePath [ dynamicTableOptions ] [systemTimePeriod] [[AS] correlationName] - | LATERAL TABLE '(' functionName '(' expression [, expression ]* ')' ')' + | [ LATERAL ] functionName '(' expression [, expression ]* ')' + | [ LATERAL ] TABLE '(' functionName '(' expression [, expression ]* ')' ')' | [ LATERAL ] '(' query ')' | UNNEST '(' expression ')' diff --git a/docs/content/docs/sql/reference/queries/vector-search.md b/docs/content/docs/sql/reference/queries/vector-search.md index 1ffac76125a6e..4f800ac356fea 100644 --- a/docs/content/docs/sql/reference/queries/vector-search.md +++ b/docs/content/docs/sql/reference/queries/vector-search.md @@ -37,13 +37,13 @@ The `VECTOR_SEARCH` uses a processing-time attribute to correlate rows to the la ```sql SELECT * -FROM input_table, LATERAL TABLE(VECTOR_SEARCH( +FROM input_table, LATERAL VECTOR_SEARCH( TABLE vector_table, input_table.vector_column, DESCRIPTOR(index_column), top_k, [CONFIG => MAP['key', 'value']] - )) + ) ``` ### Parameters @@ -66,32 +66,32 @@ The following configuration options can be specified in the config map: ```sql -- Basic usage SELECT * FROM -input_table, LATERAL TABLE(VECTOR_SEARCH( +input_table, LATERAL VECTOR_SEARCH( TABLE vector_table, input_table.vector_column, DESCRIPTOR(index_column), 10 -)); +); -- With configuration options SELECT * FROM -input_table, LATERAL TABLE(VECTOR_SEARCH( +input_table, LATERAL VECTOR_SEARCH( TABLE vector_table, input_table.vector_column, DESCRIPTOR(index_column), 10, MAP['async', 'true', 'timeout', '100s'] -)); +); -- Using named parameters SELECT * FROM -input_table, LATERAL TABLE(VECTOR_SEARCH( +input_table, LATERAL VECTOR_SEARCH( SEARCH_TABLE => TABLE vector_table, COLUMN_TO_QUERY => input_table.vector_column, COLUMN_TO_SEARCH => DESCRIPTOR(index_column), TOP_K => 10, CONFIG => MAP['async', 'true', 'timeout', '100s'] -)); +); -- Searching with contant value SELECT *