getEventListeners()
- {
- return emptySet();
- }
-
/**
* Commit the transaction. Will be called at most once and will not be called if
* {@link #rollback} is called.
diff --git a/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorMetadata.java b/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorMetadata.java
index 4696d8c03ea4..ce45ca7415f0 100644
--- a/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorMetadata.java
+++ b/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorMetadata.java
@@ -116,29 +116,6 @@ default ConnectorTableHandle getTableHandle(
throw new TrinoException(GENERIC_INTERNAL_ERROR, "ConnectorMetadata getTableHandle() is not implemented");
}
- /**
- * Create initial handle for execution of table procedure. The handle will be used through planning process. It will be converted to final
- * handle used for execution via @{link {@link ConnectorMetadata#beginTableExecute}
- *
- * If connector does not support execution with retries, the method should throw:
- *
- * new TrinoException(NOT_SUPPORTED, "This connector does not support query retries")
- *
- * unless {@code retryMode} is set to {@code NO_RETRIES}.
- *
- * @deprecated {Use {@link #getTableHandleForExecute(ConnectorSession, ConnectorAccessControl, ConnectorTableHandle, String, Map, RetryMode)}}
- */
- @Deprecated
- default Optional getTableHandleForExecute(
- ConnectorSession session,
- ConnectorTableHandle tableHandle,
- String procedureName,
- Map executeProperties,
- RetryMode retryMode)
- {
- throw new TrinoException(NOT_SUPPORTED, "This connector does not support table procedures");
- }
-
/**
* Create initial handle for execution of table procedure. The handle will be used through planning process. It will be converted to final
* handle used for execution via @{link {@link ConnectorMetadata#beginTableExecute}
@@ -157,7 +134,7 @@ default Optional getTableHandleForExecute(
Map executeProperties,
RetryMode retryMode)
{
- return getTableHandleForExecute(session, tableHandle, procedureName, executeProperties, retryMode);
+ throw new TrinoException(NOT_SUPPORTED, "This connector does not support table procedures");
}
default Optional getLayoutForTableExecute(ConnectorSession session, ConnectorTableExecuteHandle tableExecuteHandle)
@@ -885,25 +862,13 @@ default Optional getUpdateLayout(ConnectorSession s
return Optional.empty();
}
- /**
- * Do whatever is necessary to start an MERGE query, returning the {@link ConnectorMergeTableHandle}
- * instance that will be passed to the PageSink, and to the {@link #finishMerge} method.
- *
- * @deprecated {Use {@link #beginMerge(ConnectorSession, ConnectorTableHandle, Map, RetryMode)}}
- */
- @Deprecated
- default ConnectorMergeTableHandle beginMerge(ConnectorSession session, ConnectorTableHandle tableHandle, RetryMode retryMode)
- {
- throw new TrinoException(NOT_SUPPORTED, MODIFYING_ROWS_MESSAGE);
- }
-
/**
* Do whatever is necessary to start an MERGE query, returning the {@link ConnectorMergeTableHandle}
* instance that will be passed to the PageSink, and to the {@link #finishMerge} method.
*/
default ConnectorMergeTableHandle beginMerge(ConnectorSession session, ConnectorTableHandle tableHandle, Map> updateCaseColumns, RetryMode retryMode)
{
- return beginMerge(session, tableHandle, retryMode);
+ throw new TrinoException(NOT_SUPPORTED, MODIFYING_ROWS_MESSAGE);
}
/**
diff --git a/core/trino-spi/src/main/java/io/trino/spi/type/SqlDate.java b/core/trino-spi/src/main/java/io/trino/spi/type/SqlDate.java
index d8f092448de3..2ca4cecab692 100644
--- a/core/trino-spi/src/main/java/io/trino/spi/type/SqlDate.java
+++ b/core/trino-spi/src/main/java/io/trino/spi/type/SqlDate.java
@@ -13,8 +13,6 @@
*/
package io.trino.spi.type;
-import com.fasterxml.jackson.annotation.JsonValue;
-
import java.time.LocalDate;
public final class SqlDate
@@ -51,7 +49,6 @@ public boolean equals(Object obj)
return days == other.days;
}
- @JsonValue
@Override
public String toString()
{
diff --git a/core/trino-spi/src/main/java/io/trino/spi/type/SqlDecimal.java b/core/trino-spi/src/main/java/io/trino/spi/type/SqlDecimal.java
index f84341736ad6..d25369fe6782 100644
--- a/core/trino-spi/src/main/java/io/trino/spi/type/SqlDecimal.java
+++ b/core/trino-spi/src/main/java/io/trino/spi/type/SqlDecimal.java
@@ -13,8 +13,6 @@
*/
package io.trino.spi.type;
-import com.fasterxml.jackson.annotation.JsonValue;
-
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
@@ -81,7 +79,6 @@ public int hashCode()
return Objects.hash(unscaledValue, precision, scale);
}
- @JsonValue
@Override
public String toString()
{
diff --git a/core/trino-spi/src/main/java/io/trino/spi/type/SqlTime.java b/core/trino-spi/src/main/java/io/trino/spi/type/SqlTime.java
index a70a50a1875b..44113f652cb0 100644
--- a/core/trino-spi/src/main/java/io/trino/spi/type/SqlTime.java
+++ b/core/trino-spi/src/main/java/io/trino/spi/type/SqlTime.java
@@ -13,8 +13,6 @@
*/
package io.trino.spi.type;
-import com.fasterxml.jackson.annotation.JsonValue;
-
import java.util.Objects;
import static io.trino.spi.type.TimeType.MAX_PRECISION;
@@ -85,7 +83,6 @@ public int hashCode()
return Objects.hash(precision, picos);
}
- @JsonValue
@Override
public String toString()
{
diff --git a/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimeWithTimeZone.java b/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimeWithTimeZone.java
index dc039a09bf4a..c37c18a32b6c 100644
--- a/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimeWithTimeZone.java
+++ b/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimeWithTimeZone.java
@@ -13,8 +13,6 @@
*/
package io.trino.spi.type;
-import com.fasterxml.jackson.annotation.JsonValue;
-
import java.util.Objects;
import static io.trino.spi.type.TimeType.MAX_PRECISION;
@@ -99,7 +97,6 @@ public int hashCode()
return Objects.hash(precision, picos, offsetMinutes);
}
- @JsonValue
@Override
public String toString()
{
diff --git a/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimestamp.java b/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimestamp.java
index bab2fadfda55..1a2b2558adff 100644
--- a/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimestamp.java
+++ b/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimestamp.java
@@ -13,8 +13,6 @@
*/
package io.trino.spi.type;
-import com.fasterxml.jackson.annotation.JsonValue;
-
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Objects;
@@ -149,7 +147,6 @@ public int hashCode()
return Objects.hash(epochMicros, picosOfMicros, precision);
}
- @JsonValue
@Override
public String toString()
{
diff --git a/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimestampWithTimeZone.java b/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimestampWithTimeZone.java
index 7c1b6155f5ce..9eaf8133e80c 100644
--- a/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimestampWithTimeZone.java
+++ b/core/trino-spi/src/main/java/io/trino/spi/type/SqlTimestampWithTimeZone.java
@@ -13,8 +13,6 @@
*/
package io.trino.spi.type;
-import com.fasterxml.jackson.annotation.JsonValue;
-
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
@@ -132,7 +130,6 @@ public SqlTimestampWithTimeZone roundTo(int precision)
return newInstanceWithRounding(precision, epochMillis, picosOfMilli, timeZoneKey);
}
- @JsonValue
@Override
public String toString()
{
diff --git a/core/trino-spi/src/main/java/io/trino/spi/type/SqlVarbinary.java b/core/trino-spi/src/main/java/io/trino/spi/type/SqlVarbinary.java
index 5c54a95fe15f..673c14fc35f6 100644
--- a/core/trino-spi/src/main/java/io/trino/spi/type/SqlVarbinary.java
+++ b/core/trino-spi/src/main/java/io/trino/spi/type/SqlVarbinary.java
@@ -13,9 +13,8 @@
*/
package io.trino.spi.type;
-import com.fasterxml.jackson.annotation.JsonValue;
-
import java.util.Arrays;
+import java.util.Base64;
import java.util.HexFormat;
import static java.lang.Math.min;
@@ -42,7 +41,6 @@ public int compareTo(SqlVarbinary obj)
return Arrays.compare(bytes, obj.bytes);
}
- @JsonValue
public byte[] getBytes()
{
return bytes;
@@ -69,6 +67,11 @@ public boolean equals(Object obj)
@Override
public String toString()
+ {
+ return Base64.getEncoder().encodeToString(bytes);
+ }
+
+ public String toHexString()
{
if (bytes.length == 0) {
return "";
diff --git a/core/trino-spi/src/test/java/io/trino/spi/type/TestSqlVarbinary.java b/core/trino-spi/src/test/java/io/trino/spi/type/TestSqlVarbinary.java
index 54da3087a7b6..8d4bc970035a 100644
--- a/core/trino-spi/src/test/java/io/trino/spi/type/TestSqlVarbinary.java
+++ b/core/trino-spi/src/test/java/io/trino/spi/type/TestSqlVarbinary.java
@@ -15,24 +15,27 @@
import org.junit.jupiter.api.Test;
+import java.util.Base64;
+
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
public class TestSqlVarbinary
{
@Test
- public void testToString()
+ public void testToHexString()
{
for (int lines = 0; lines < 5; lines++) {
for (int lastLineBytes = 0; lastLineBytes < 32; lastLineBytes++) {
byte[] bytes = createBytes(lines, lastLineBytes);
- String expected = simpleToString(bytes);
- assertThat(expected).isEqualTo(new SqlVarbinary(bytes).toString());
+ String expectedHex = simpleToHex(bytes);
+ assertThat(expectedHex).isEqualTo(new SqlVarbinary(bytes).toHexString());
+ assertThat(Base64.getEncoder().encodeToString(bytes)).isEqualTo(new SqlVarbinary(bytes).toString());
}
}
}
- private static String simpleToString(byte[] bytes)
+ private static String simpleToHex(byte[] bytes)
{
StringBuilder builder = new StringBuilder();
diff --git a/core/trino-web-ui/pom.xml b/core/trino-web-ui/pom.xml
index 9f21b8edf7d3..a8ef1e605f99 100644
--- a/core/trino-web-ui/pom.xml
+++ b/core/trino-web-ui/pom.xml
@@ -5,7 +5,7 @@
io.trino
trino-root
- 468-SNAPSHOT
+ 469-SNAPSHOT
../../pom.xml
diff --git a/docs/pom.xml b/docs/pom.xml
index 55aa7e62b4b9..8ad50977d6df 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -5,7 +5,7 @@
io.trino
trino-root
- 468-SNAPSHOT
+ 469-SNAPSHOT
trino-docs
diff --git a/docs/src/main/sphinx/admin/properties-sql-environment.md b/docs/src/main/sphinx/admin/properties-sql-environment.md
index a4092cef9ace..d31ce3f13990 100644
--- a/docs/src/main/sphinx/admin/properties-sql-environment.md
+++ b/docs/src/main/sphinx/admin/properties-sql-environment.md
@@ -31,15 +31,14 @@ client overrides this default.
- **Type:** [](prop-type-string)
-Set the default catalog for [SQL routine](/routines) storage for all clients.
-The connector used in the catalog must support [](sql-routine-management). Any
-usage of a fully qualified name for a routine overrides this default.
+Set the default catalog for [](/udf) storage for all clients. The connector used
+in the catalog must support [](udf-management). Any usage of a fully qualified
+name for a UDF overrides this default.
-The default catalog and schema for SQL routine storage must be configured
-together, and the resulting entry must be set as part of the path. For example,
-the following example section for [](config-properties) uses the `functions`
-schema in the `brain` catalog for routine storage, and adds it as the only entry
-on the path:
+The default catalog and schema for UDF storage must be configured together, and
+the resulting entry must be set as part of the path. For example, the following
+section for [](config-properties) uses the `functions` schema in the `brain`
+catalog for UDF storage, and adds it as the only entry on the path:
```properties
sql.default-function-catalog=brain
@@ -51,9 +50,9 @@ sql.path=brain.default
- **Type:** [](prop-type-string)
-Set the default schema for SQL routine storage for all clients. Must be set to a
-schema name that is valid for the default function catalog. Any usage of a fully
-qualified name for a routine overrides this default.
+Set the default schema for UDF storage for all clients. Must be set to a schema
+name that is valid for the default function catalog. Any usage of a fully
+qualified name for a UDF overrides this default.
## `sql.path`
diff --git a/docs/src/main/sphinx/client.md b/docs/src/main/sphinx/client.md
index 502bf3552520..98837c87f999 100644
--- a/docs/src/main/sphinx/client.md
+++ b/docs/src/main/sphinx/client.md
@@ -15,9 +15,10 @@ following client drivers:
* [trino-go-client](https://github.com/trinodb/trino-go-client)
* [trino-js-client](https://github.com/trinodb/trino-js-client)
* [trino-python-client](https://github.com/trinodb/trino-python-client)
+* [trino-csharp-client](https://github.com/trinodb/trino-csharp-client)
Other communities and vendors provide [other client
-drivers](https://trino.io/ecosystem/client.html).
+drivers](https://trino.io/ecosystem/client-driver#other-client-drivers).
## Client applications
@@ -26,11 +27,12 @@ run queries with Trino. You can inspect the results, perform analytics with
further queries, and create visualizations. Client applications typically use a
client driver.
-The Trino project maintains the [Trino command line interface](/client/cli) as a
-client application.
+The Trino project maintains the [Trino command line interface](/client/cli) and
+the [Trino Grafana Data Source Plugin](https://github.com/trinodb/grafana-trino)
+as a client application.
Other communities and vendors provide [numerous other client
-applications](https://trino.io/ecosystem/client.html)
+applications](https://trino.io/ecosystem/client-application#other-client-applications)
## Client protocol
diff --git a/docs/src/main/sphinx/client/cli.md b/docs/src/main/sphinx/client/cli.md
index 8b7a0ee17613..439d43558d82 100644
--- a/docs/src/main/sphinx/client/cli.md
+++ b/docs/src/main/sphinx/client/cli.md
@@ -181,8 +181,7 @@ mode:
- Do not show query processing progress.
* - `--path`
- Set the default [SQL path](/sql/set-path) for the session. Useful for
- setting a catalog and schema location for [catalog
- routines](routine-catalog).
+ setting a catalog and schema location for [](udf-catalog).
* - `--password`
- Prompts for a password. Use if your Trino server requires password
authentication. You can set the `TRINO_PASSWORD` environment variable with
diff --git a/docs/src/main/sphinx/client/jdbc.md b/docs/src/main/sphinx/client/jdbc.md
index 427f688000f3..bcf7af7a0182 100644
--- a/docs/src/main/sphinx/client/jdbc.md
+++ b/docs/src/main/sphinx/client/jdbc.md
@@ -142,7 +142,7 @@ may not be specified using both methods.
- Client tags for selecting resource groups. Example: `abc,xyz`
* - `path`
- Set the default [SQL path](/sql/set-path) for the session. Useful for
- setting a catalog and schema location for [catalog routines](routine-catalog).
+ setting a catalog and schema location for [](udf-catalog).
* - `traceToken`
- Trace token for correlating requests across systems.
* - `source`
diff --git a/docs/src/main/sphinx/connector/alter-schema-limitation.fragment b/docs/src/main/sphinx/connector/alter-schema-limitation.fragment
index 39065f900324..33100d90c262 100644
--- a/docs/src/main/sphinx/connector/alter-schema-limitation.fragment
+++ b/docs/src/main/sphinx/connector/alter-schema-limitation.fragment
@@ -1,4 +1,4 @@
-### ALTER SCHEMA
+### ALTER SCHEMA limitation
The connector supports renaming a schema with the `ALTER SCHEMA RENAME`
statement. `ALTER SCHEMA SET AUTHORIZATION` is not supported.
diff --git a/docs/src/main/sphinx/connector/alter-table-limitation.fragment b/docs/src/main/sphinx/connector/alter-table-limitation.fragment
index de64a02a9c3b..d3101270ee69 100644
--- a/docs/src/main/sphinx/connector/alter-table-limitation.fragment
+++ b/docs/src/main/sphinx/connector/alter-table-limitation.fragment
@@ -1,4 +1,4 @@
-### ALTER TABLE RENAME TO
+### ALTER TABLE RENAME TO limitation
The connector does not support renaming tables across multiple schemas. For
example, the following statement is supported:
diff --git a/docs/src/main/sphinx/connector/clickhouse.md b/docs/src/main/sphinx/connector/clickhouse.md
index 0da7a863bb28..fc34ac02ee17 100644
--- a/docs/src/main/sphinx/connector/clickhouse.md
+++ b/docs/src/main/sphinx/connector/clickhouse.md
@@ -93,9 +93,6 @@ configured connector to create a catalog named `sales`.
```{include} jdbc-case-insensitive-matching.fragment
```
-```{include} non-transactional-insert.fragment
-```
-
## Querying ClickHouse
The ClickHouse connector provides a schema for every ClickHouse *database*.
@@ -317,18 +314,27 @@ No other types are supported.
(clickhouse-sql-support)=
## SQL support
-The connector provides read and write access to data and metadata in
-a ClickHouse catalog. In addition to the {ref}`globally available
-` and {ref}`read operation `
+The connector provides read and write access to data and metadata in a
+ClickHouse catalog. In addition to the [globally
+available](sql-globally-available) and [read operation](sql-read-operations)
statements, the connector supports the following features:
-- {doc}`/sql/insert`
-- {doc}`/sql/truncate`
-- {ref}`sql-schema-table-management`
+- [](/sql/insert), see also [](clickhouse-insert)
+- [](/sql/truncate)
+- [](sql-schema-table-management), see also:
+ - [](clickhouse-alter-table)
+- [](clickhouse-procedures)
+- [](clickhouse-table-functions)
+
+(clickhouse-insert)=
+```{include} non-transactional-insert.fragment
+```
+(clickhouse-alter-table)=
```{include} alter-schema-limitation.fragment
```
+(clickhouse-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
@@ -336,6 +342,7 @@ statements, the connector supports the following features:
```{include} procedures-execute.fragment
```
+(clickhouse-table-functions)=
### Table functions
The connector provides specific {doc}`table functions ` to
diff --git a/docs/src/main/sphinx/connector/delta-lake.md b/docs/src/main/sphinx/connector/delta-lake.md
index 2e6785c3a40a..0069b9fe65af 100644
--- a/docs/src/main/sphinx/connector/delta-lake.md
+++ b/docs/src/main/sphinx/connector/delta-lake.md
@@ -108,7 +108,7 @@ values. Typical usage does not require you to configure them.
* `GZIP`
The equivalent catalog session property is `compression_codec`.
- - `SNAPPY`
+ - `ZSTD`
* - `delta.max-partitions-per-writer`
- Maximum number of partitions per writer.
- `100`
diff --git a/docs/src/main/sphinx/connector/druid.md b/docs/src/main/sphinx/connector/druid.md
index ab6f4d269a2b..261047c85dcd 100644
--- a/docs/src/main/sphinx/connector/druid.md
+++ b/docs/src/main/sphinx/connector/druid.md
@@ -116,10 +116,15 @@ be an empty string `''`, and so forth.
(druid-sql-support)=
## SQL support
-The connector provides {ref}`globally available ` and
-{ref}`read operation ` statements to access data and
-metadata in the Druid database.
+The connector provides read access to data and metadata in the Druid database.
+In addition to the [globally available](sql-globally-available) and [read
+operation](sql-read-operations) statements, the connector supports the following
+features:
+- [](druid-procedures)
+- [](druid-table-functions)
+
+(druid-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
@@ -127,6 +132,7 @@ metadata in the Druid database.
```{include} procedures-execute.fragment
```
+(druid-table-functions)=
### Table functions
The connector provides specific {doc}`table functions ` to
diff --git a/docs/src/main/sphinx/connector/exasol.md b/docs/src/main/sphinx/connector/exasol.md
index a6b7de26d8c2..23147958a70c 100644
--- a/docs/src/main/sphinx/connector/exasol.md
+++ b/docs/src/main/sphinx/connector/exasol.md
@@ -133,10 +133,15 @@ Exasol does not support longer values.
(exasol-sql-support)=
## SQL support
-The connector provides {ref}`globally available ` and
-{ref}`read operation ` statements to access data and
-metadata in the Exasol database.
+The connector provides read access to data and metadata in Exasol. In addition
+to the [globally available](sql-globally-available) and [read
+operation](sql-read-operations) statements, the connector supports the following
+features:
+- [](exasol-procedures)
+- [](exasol-table-functions)
+
+(exasol-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
@@ -144,6 +149,7 @@ metadata in the Exasol database.
```{include} procedures-execute.fragment
```
+(exasol-table-functions)=
### Table functions
The connector provides specific {doc}`table functions ` to
diff --git a/docs/src/main/sphinx/connector/faker.md b/docs/src/main/sphinx/connector/faker.md
index 793064b7178e..2a3f01cd9c09 100644
--- a/docs/src/main/sphinx/connector/faker.md
+++ b/docs/src/main/sphinx/connector/faker.md
@@ -30,9 +30,9 @@ reading from tables returns random, but deterministic data. As a result,
repeated invocation of a query returns identical data. See [](faker-usage) for
more examples.
-Schemas and tables in a catalog are not persisted, and are stored in the memory
-of the coordinator only. They need to be recreated every time after restarting
-the coordinator.
+Schemas, tables, and views in a catalog are not persisted, and are stored in the
+memory of the coordinator only. They need to be recreated every time after
+restarting the coordinator.
The following table details all general configuration properties:
@@ -102,6 +102,18 @@ The following table details all supported column properties.
sentence from the
[Lorem](https://javadoc.io/doc/net.datafaker/datafaker/latest/net/datafaker/providers/base/Lorem.html)
provider.
+* - `min`
+ - Minimum generated value (inclusive). Cannot be set for character-based type
+ columns.
+* - `max`
+ - Maximum generated value (inclusive). Cannot be set for character-based type
+ columns.
+* - `allowed_values`
+ - List of allowed values. Cannot be set together with the `min`, or `max`
+ properties.
+* - `step`
+ - If set, generate sequential values with this step. For date and time columns
+ set this to a duration. Cannot be set for character-based type columns.
:::
### Character types
@@ -166,7 +178,7 @@ Faker supports the following non-character types:
- `UUID`
You can not use generator expressions for non-character-based columns. To limit
-their data range, specify constraints in the `WHERE` clause - see
+their data range, set the `min` and `max` column properties - see
[](faker-usage).
### Unsupported types
@@ -184,12 +196,11 @@ can be combined, like in the following example:
```sql
CREATE TABLE faker.default.prices (
currency VARCHAR NOT NULL WITH (generator = '#{Currency.code}'),
- price DECIMAL(8,2) NOT NULL
+ price DECIMAL(8,2) NOT NULL WITH (min = '0')
);
SELECT JSON_OBJECT(KEY currency VALUE price) AS complex
FROM faker.default.prices
-WHERE price > 0
LIMIT 3;
```
@@ -238,6 +249,7 @@ To define the schema for generating data, it supports the following features:
- [](/sql/drop-table)
- [](/sql/create-schema)
- [](/sql/drop-schema)
+- [](sql-view-management)
(faker-usage)=
## Usage
@@ -260,40 +272,48 @@ CREATE TABLE generator.default.customer (LIKE production.public.customer EXCLUDI
Insert random data into the original table, by selecting it from the
`generator` catalog. Data generated by the Faker connector for columns of
-non-character types cover the whole range of that data type. Add constraints to
-adjust the data as desired. The following example ensures that date of birth
-and age in years are related and realistic values.
+non-character types cover the whole range of that data type. Set the `min` and
+`max` column properties, to adjust the generated data as desired. The following
+example ensures that date of birth and age in years are related and realistic
+values.
+
+Start with getting the complete definition of
+a table:
+
+```sql
+SHOW CREATE TABLE production.public.customers;
+```
+
+Modify the output of the previous query and add some column properties.
+
+```sql
+CREATE TABLE generator.default.customer (
+ id UUID NOT NULL,
+ name VARCHAR NOT NULL,
+ address VARCHAR NOT NULL,
+ born_at DATE WITH (min = '1900-01-01', max = '2025-01-01'),
+ age_years INTEGER WITH (min = '0', max = '150'),
+ group_id INTEGER WITH (allowed_values = ARRAY['10', '32', '81'])
+);
+```
```sql
INSERT INTO production.public.customers
SELECT *
FROM generator.default.customers
-WHERE
- born_at BETWEEN CURRENT_DATE - INTERVAL '150' YEAR AND CURRENT_DATE
- AND age_years BETWEEN 0 AND 150
LIMIT 100;
```
To generate even more realistic data, choose specific generators by setting the
-`generator` property on columns. Start with getting the complete definition of
-a table:
-
-```sql
-SHOW CREATE TABLE production.public.customers;
-```
-
-Modify the output of the previous query and add some column properties.
+`generator` property on columns.
```sql
CREATE TABLE generator.default.customer (
id UUID NOT NULL,
name VARCHAR NOT NULL WITH (generator = '#{Name.first_name} #{Name.last_name}'),
address VARCHAR NOT NULL WITH (generator = '#{Address.fullAddress}'),
- born_at DATE,
- age_years INTEGER
+ born_at DATE WITH (min = '1900-01-01', max = '2025-01-01'),
+ age_years INTEGER WITH (min = '0', max = '150'),
+ group_id INTEGER WITH (allowed_values = ARRAY['10', '32', '81'])
);
```
-
-## Limitations
-
-* It is not possible to choose the locale used by the Datafaker's generators.
diff --git a/docs/src/main/sphinx/connector/hive.md b/docs/src/main/sphinx/connector/hive.md
index cf58c3a000d0..b642004c06a0 100644
--- a/docs/src/main/sphinx/connector/hive.md
+++ b/docs/src/main/sphinx/connector/hive.md
@@ -403,7 +403,7 @@ configured object storage system and metadata stores:
- {ref}`sql-view-management`; see also
{ref}`Hive-specific view management `
-- [](sql-routine-management)
+- [](udf-management)
- {ref}`sql-security-operations`: see also
{ref}`SQL standard-based authorization for object storage `
diff --git a/docs/src/main/sphinx/connector/iceberg.md b/docs/src/main/sphinx/connector/iceberg.md
index 6ec6cd7bd4e0..42cb12927220 100644
--- a/docs/src/main/sphinx/connector/iceberg.md
+++ b/docs/src/main/sphinx/connector/iceberg.md
@@ -1502,6 +1502,18 @@ CREATE TABLE example.customers.orders (
WITH (sorted_by = ARRAY['order_date'])
```
+You can explicitly configure sort directions or null ordering in the following way:
+
+```
+CREATE TABLE example.customers.orders (
+ order_id BIGINT,
+ order_date DATE,
+ account_number BIGINT,
+ customer VARCHAR,
+ country VARCHAR)
+WITH (sorted_by = ARRAY['order_date DESC NULLS FIRST', 'order_id ASC NULLS LAST'])
+```
+
Sorting can be combined with partitioning on the same column. For example:
```
diff --git a/docs/src/main/sphinx/connector/ignite.md b/docs/src/main/sphinx/connector/ignite.md
index abd43a529bd4..108ebc4a2a7e 100644
--- a/docs/src/main/sphinx/connector/ignite.md
+++ b/docs/src/main/sphinx/connector/ignite.md
@@ -75,9 +75,6 @@ configured connector to create a catalog named `sales`.
```{include} jdbc-case-insensitive-matching.fragment
```
-```{include} non-transactional-insert.fragment
-```
-
## Table properties
Table property usage example:
@@ -173,20 +170,33 @@ Ignite. In addition to the {ref}`globally available
` and {ref}`read operation `
statements, the connector supports the following features:
-- {doc}`/sql/insert`
-- {doc}`/sql/update`
-- {doc}`/sql/delete`
-- {doc}`/sql/create-table`
-- {doc}`/sql/create-table-as`
-- {doc}`/sql/drop-table`
-- {doc}`/sql/alter-table`
+- [](/sql/insert), see also [](ignite-insert)
+- [](/sql/update), see also [](ignite-update)
+- [](/sql/delete)
+- [](/sql/merge), see also [](ignite-merge)
+- [](/sql/create-table)
+- [](/sql/create-table-as)
+- [](/sql/drop-table)
+- [](/sql/alter-table), see also [](ignite-alter-table)
+- [](ignite-procedures)
+
+(ignite-insert)=
+```{include} non-transactional-insert.fragment
+```
+(ignite-update)=
```{include} sql-update-limitation.fragment
```
+(ignite-merge)=
+```{include} non-transactional-merge.fragment
+```
+
+(ignite-alter-table)=
```{include} alter-table-limitation.fragment
```
+(ignite-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
diff --git a/docs/src/main/sphinx/connector/mariadb.md b/docs/src/main/sphinx/connector/mariadb.md
index e07d37cd585d..37d1762cce74 100644
--- a/docs/src/main/sphinx/connector/mariadb.md
+++ b/docs/src/main/sphinx/connector/mariadb.md
@@ -52,9 +52,6 @@ properties files.
```{include} jdbc-case-insensitive-matching.fragment
```
-```{include} non-transactional-insert.fragment
-```
-
(mariadb-fte-support)=
### Fault-tolerant execution support
@@ -283,28 +280,37 @@ Complete list of [MariaDB data types](https://mariadb.com/kb/en/data-types/).
(mariadb-sql-support)=
## SQL support
-The connector provides read access and write access to data and metadata in
-a MariaDB database. In addition to the {ref}`globally available
-` and {ref}`read operation `
+The connector provides read access and write access to data and metadata in a
+MariaDB database. In addition to the [globally
+available](sql-globally-available) and [read operation](sql-read-operations)
statements, the connector supports the following features:
-- {doc}`/sql/insert`
-- {doc}`/sql/update`
-- {doc}`/sql/delete`
-- {doc}`/sql/truncate`
-- {doc}`/sql/create-table`
-- {doc}`/sql/create-table-as`
-- {doc}`/sql/drop-table`
-- {doc}`/sql/alter-table`
-- {doc}`/sql/create-schema`
-- {doc}`/sql/drop-schema`
+- [](/sql/insert), see also [](mariadb-insert)
+- [](/sql/update), see also [](mariadb-update)
+- [](/sql/delete), see also [](mariadb-delete)
+- [](/sql/truncate)
+- [](/sql/create-table)
+- [](/sql/create-table-as)
+- [](/sql/drop-table)
+- [](/sql/alter-table)
+- [](/sql/create-schema)
+- [](/sql/drop-schema)
+- [](mariadb-procedures)
+- [](mariadb-table-functions)
+
+(mariadb-insert)=
+```{include} non-transactional-insert.fragment
+```
+(mariadb-update)=
```{include} sql-update-limitation.fragment
```
+(mariadb-delete)=
```{include} sql-delete-limitation.fragment
```
+(mariadb-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
@@ -312,6 +318,7 @@ statements, the connector supports the following features:
```{include} procedures-execute.fragment
```
+(mariadb-table-functions)=
### Table functions
The connector provides specific {doc}`table functions ` to
diff --git a/docs/src/main/sphinx/connector/memory.md b/docs/src/main/sphinx/connector/memory.md
index 2a7377a1dea7..23bc958abf80 100644
--- a/docs/src/main/sphinx/connector/memory.md
+++ b/docs/src/main/sphinx/connector/memory.md
@@ -69,7 +69,7 @@ statements, the connector supports the following features:
- {doc}`/sql/alter-schema`
- {doc}`/sql/comment`
- [](sql-view-management)
-- [](sql-routine-management)
+- [](udf-management)
### TRUNCATE and DROP TABLE
diff --git a/docs/src/main/sphinx/connector/mysql.md b/docs/src/main/sphinx/connector/mysql.md
index 61d5457d786d..30f5e2bac925 100644
--- a/docs/src/main/sphinx/connector/mysql.md
+++ b/docs/src/main/sphinx/connector/mysql.md
@@ -99,9 +99,6 @@ creates a catalog named `sales` using the configured connector.
```{include} jdbc-case-insensitive-matching.fragment
```
-```{include} non-transactional-insert.fragment
-```
-
(mysql-fte-support)=
### Fault-tolerant execution support
@@ -334,26 +331,35 @@ that catalog name instead of `example` in the above examples.
## SQL support
The connector provides read access and write access to data and metadata in the
-MySQL database. In addition to the {ref}`globally available ` and
-{ref}`read operation ` statements, the connector supports
-the following statements:
-
-- {doc}`/sql/insert`
-- {doc}`/sql/update`
-- {doc}`/sql/delete`
-- {doc}`/sql/truncate`
-- {doc}`/sql/create-table`
-- {doc}`/sql/create-table-as`
-- {doc}`/sql/drop-table`
-- {doc}`/sql/create-schema`
-- {doc}`/sql/drop-schema`
+MySQL database. In addition to the [globally available](sql-globally-available)
+and [read operation](sql-read-operations) statements, the connector supports the
+following features:
+
+- [](/sql/insert), see also [](mysql-insert)
+- [](/sql/update), see also [](mysql-update)
+- [](/sql/delete), see also [](mysql-delete)
+- [](/sql/truncate)
+- [](/sql/create-table)
+- [](/sql/create-table-as)
+- [](/sql/drop-table)
+- [](/sql/create-schema)
+- [](/sql/drop-schema)
+- [](mysql-procedures)
+- [](mysql-table-functions)
+
+(mysql-insert)=
+```{include} non-transactional-insert.fragment
+```
+(mysql-update)=
```{include} sql-update-limitation.fragment
```
+(mysql-delete)=
```{include} sql-delete-limitation.fragment
```
+(mysql-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
@@ -361,6 +367,7 @@ the following statements:
```{include} procedures-execute.fragment
```
+(mysql-table-functions)=
### Table functions
The connector provides specific {doc}`table functions ` to
diff --git a/docs/src/main/sphinx/connector/non-transactional-merge.fragment b/docs/src/main/sphinx/connector/non-transactional-merge.fragment
new file mode 100644
index 000000000000..60e905372a38
--- /dev/null
+++ b/docs/src/main/sphinx/connector/non-transactional-merge.fragment
@@ -0,0 +1,11 @@
+### Non-transactional MERGE
+
+The connector supports adding, updating, and deleting rows using [MERGE
+statements](/sql/merge), if the `merge.non-transactional-merge.enabled` catalog
+property or the corresponding `non_transactional_merge_enabled` catalog session
+property is set to `true`. Merge is only supported for directly modifying target
+tables.
+
+In rare cases, expections occur during the merge operation, potentially
+resulting in a partial update.
+
diff --git a/docs/src/main/sphinx/connector/oracle.md b/docs/src/main/sphinx/connector/oracle.md
index de4cb33b0b3d..238f046bb60a 100644
--- a/docs/src/main/sphinx/connector/oracle.md
+++ b/docs/src/main/sphinx/connector/oracle.md
@@ -98,9 +98,6 @@ you name the property file `sales.properties`, Trino creates a catalog named
```{include} jdbc-case-insensitive-matching.fragment
```
-```{include} non-transactional-insert.fragment
-```
-
(oracle-fte-support)=
### Fault-tolerant execution support
@@ -405,29 +402,39 @@ fails. This is also true for the equivalent `VARCHAR` types.
## SQL support
The connector provides read access and write access to data and metadata in
-Oracle. In addition to the {ref}`globally available `
-and {ref}`read operation ` statements, the connector
-supports the following statements:
-
-- {doc}`/sql/insert`
-- {doc}`/sql/update`
-- {doc}`/sql/delete`
-- {doc}`/sql/truncate`
-- {doc}`/sql/create-table`
-- {doc}`/sql/create-table-as`
-- {doc}`/sql/drop-table`
-- {doc}`/sql/alter-table`
-- {doc}`/sql/comment`
+Oracle. In addition to the [globally available](sql-globally-available) and
+[read operation](sql-read-operations) statements, the connector supports the
+following features:
+
+- [](/sql/insert), see also [](oracle-insert)
+- [](/sql/update), see also [](oracle-update)
+- [](/sql/delete), see also [](oracle-delete)
+- [](/sql/truncate)
+- [](/sql/create-table)
+- [](/sql/create-table-as)
+- [](/sql/drop-table)
+- [](/sql/alter-table), see also [](oracle-alter-table)
+- [](/sql/comment)
+- [](oracle-procedures)
+- [](oracle-table-functions)
+
+(oracle-insert)=
+```{include} non-transactional-insert.fragment
+```
+(oracle-update)=
```{include} sql-update-limitation.fragment
```
+(oracle-delete)=
```{include} sql-delete-limitation.fragment
```
+(oracle-alter-table)=
```{include} alter-table-limitation.fragment
```
+(oracle-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
@@ -435,6 +442,7 @@ supports the following statements:
```{include} procedures-execute.fragment
```
+(oracle-table-functions)=
### Table functions
The connector provides specific {doc}`table functions ` to
diff --git a/docs/src/main/sphinx/connector/phoenix.md b/docs/src/main/sphinx/connector/phoenix.md
index a1116b13234f..7efdbe2e98c1 100644
--- a/docs/src/main/sphinx/connector/phoenix.md
+++ b/docs/src/main/sphinx/connector/phoenix.md
@@ -63,9 +63,6 @@ The following Phoenix-specific configuration properties are available:
```{include} jdbc-case-insensitive-matching.fragment
```
-```{include} non-transactional-insert.fragment
-```
-
## Querying Phoenix tables
The default empty schema in Phoenix maps to a schema named `default` in Trino.
@@ -268,24 +265,35 @@ Use them in the same way as above: in the `WITH` clause of the `CREATE TABLE` st
(phoenix-sql-support)=
## SQL support
-The connector provides read and write access to data and metadata in
-Phoenix. In addition to the {ref}`globally available
-` and {ref}`read operation `
-statements, the connector supports the following features:
-
-- {doc}`/sql/insert`
-- {doc}`/sql/update`
-- {doc}`/sql/delete`
-- {doc}`/sql/merge`
-- {doc}`/sql/create-table`
-- {doc}`/sql/create-table-as`
-- {doc}`/sql/drop-table`
-- {doc}`/sql/create-schema`
-- {doc}`/sql/drop-schema`
+The connector provides read and write access to data and metadata in Phoenix. In
+addition to the [globally available](sql-globally-available) and [read
+operation](sql-read-operations) statements, the connector supports the following
+features:
+
+- [](/sql/insert), see also [](phoenix-insert)
+- [](/sql/update)
+- [](/sql/delete), see also [](phoenix-delete)
+- [](/sql/merge), see also [](phoenix-merge)
+- [](/sql/create-table)
+- [](/sql/create-table-as)
+- [](/sql/drop-table)
+- [](/sql/create-schema)
+- [](/sql/drop-schema)
+- [](phoenix-procedures)
+
+(phoenix-insert)=
+```{include} non-transactional-insert.fragment
+```
+(phoenix-delete)=
```{include} sql-delete-limitation.fragment
```
+(phoenix-merge)=
+```{include} non-transactional-merge.fragment
+```
+
+(phoenix-procedures)=
### Procedures
```{include} procedures-execute.fragment
diff --git a/docs/src/main/sphinx/connector/postgresql.md b/docs/src/main/sphinx/connector/postgresql.md
index 62d3d7789518..30eb90c0ce0d 100644
--- a/docs/src/main/sphinx/connector/postgresql.md
+++ b/docs/src/main/sphinx/connector/postgresql.md
@@ -112,21 +112,6 @@ catalog named `sales` using the configured connector.
```{include} jdbc-case-insensitive-matching.fragment
```
-```{include} non-transactional-insert.fragment
-```
-
-### Non-transactional MERGE
-
-The connector supports adding rows using {doc}`MERGE statements `.
-However, the connector only support merge modifying directly to the target
-table at current, to use merge you need to set the `merge.non-transactional-merge.enabled`
-catalog property or the corresponding `non_transactional_merge_enabled` catalog session property to
-`true`.
-
-Note that with this property enabled, data can be corrupted in rare cases where
-exceptions occur during the merge operation. With transactions disabled, no
-rollback can be performed.
-
(postgresql-fte-support)=
### Fault-tolerant execution support
@@ -360,28 +345,46 @@ that catalog name instead of `example` in the above examples.
## SQL support
The connector provides read access and write access to data and metadata in
-PostgreSQL. In addition to the {ref}`globally available
-` and {ref}`read operation `
-statements, the connector supports the following features:
-
-- {doc}`/sql/insert`
-- {doc}`/sql/update`
-- {doc}`/sql/delete`
-- {doc}`/sql/truncate`
-- {ref}`sql-schema-table-management`
+PostgreSQL. In addition to the [globally available](sql-globally-available) and
+[read operation](sql-read-operations) statements, the connector supports the
+following features:
+
+- [](/sql/insert), see also [](postgresql-insert)
+- [](/sql/update), see also [](postgresql-update)
+- [](/sql/delete), see also [](postgresql-delete)
+- [](/sql/merge), see also [](postgresql-merge)
+- [](/sql/truncate)
+- [](sql-schema-table-management), see also:
+ - [](postgresql-alter-table)
+ - [](postgresql-alter-schema)
+- [](postgresql-procedures)
+- [](postgresql-table-functions)
+
+(postgresql-insert)=
+```{include} non-transactional-insert.fragment
+```
+(postgresql-update)=
```{include} sql-update-limitation.fragment
```
+(postgresql-delete)=
```{include} sql-delete-limitation.fragment
```
+(postgresql-merge)=
+```{include} non-transactional-merge.fragment
+```
+
+(postgresql-alter-table)=
```{include} alter-table-limitation.fragment
```
+(postgresql-alter-schema)=
```{include} alter-schema-limitation.fragment
```
+(postgresql-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
@@ -389,6 +392,7 @@ statements, the connector supports the following features:
```{include} procedures-execute.fragment
```
+(postgresql-table-functions)=
### Table functions
The connector provides specific {doc}`table functions ` to
diff --git a/docs/src/main/sphinx/connector/redshift.md b/docs/src/main/sphinx/connector/redshift.md
index ba21b13134cd..1543834e5911 100644
--- a/docs/src/main/sphinx/connector/redshift.md
+++ b/docs/src/main/sphinx/connector/redshift.md
@@ -64,6 +64,43 @@ documentation](https://docs.aws.amazon.com/redshift/latest/mgmt/jdbc20-configura
```{include} jdbc-authentication.fragment
```
+### UNLOAD configuration
+
+This feature enables using Amazon S3 to efficiently transfer data out of Redshift
+instead of the default single threaded JDBC based implementation.
+The connector automatically triggers the appropriate `UNLOAD` command
+on Redshift to extract the output from Redshift to the configured
+S3 bucket in the form of Parquet files. These Parquet files are read in parallel
+from S3 to improve latency of reading from Redshift tables. The Parquet
+files will be removed when Trino finishes executing the query. It is recommended
+to define a custom life cycle policy on the S3 bucket used for unloading the
+Redshift query results.
+This feature is supported only when the Redshift cluster and the configured S3
+bucket are in the same AWS region.
+
+The following table describes configuration properties for using
+`UNLOAD` command in Redshift connector. `redshift.unload-location` must be set
+to use `UNLOAD`.
+
+:::{list-table} UNLOAD configuration properties
+:widths: 30, 60
+:header-rows: 1
+
+* - Property value
+ - Description
+* - `redshift.unload-location`
+ - A writeable location in Amazon S3, to be used for temporarily unloading
+ Redshift query results.
+* - `redshift.unload-iam-role`
+ - Optional. Fully specified ARN of the IAM Role attached to the Redshift cluster.
+ Provided role will be used in `UNLOAD` command. IAM role must have access to
+ Redshift cluster and write access to S3 bucket. The default IAM role attached to
+ Redshift cluster is used when this property is not configured.
+:::
+
+Additionally, define appropriate [S3 configurations](/object-storage/file-system-s3)
+except `fs.native-s3.enabled`, required to read Parquet files from S3 bucket.
+
### Multiple Redshift databases or clusters
The Redshift connector can only access a single database within
@@ -88,9 +125,6 @@ catalog named `sales` using the configured connector.
```{include} jdbc-case-insensitive-matching.fragment
```
-```{include} non-transactional-insert.fragment
-```
-
(redshift-fte-support)=
## Fault-tolerant execution support
@@ -144,24 +178,37 @@ Redshift. In addition to the {ref}`globally available
` and {ref}`read operation `
statements, the connector supports the following features:
-- {doc}`/sql/insert`
-- {doc}`/sql/update`
-- {doc}`/sql/delete`
-- {doc}`/sql/truncate`
-- {ref}`sql-schema-table-management`
+- [](/sql/insert), see also [](redshift-insert)
+- [](/sql/update), see also [](redshift-update)
+- [](/sql/delete), see also [](redshift-delete)
+- [](/sql/truncate)
+- [](sql-schema-table-management), see also:
+ - [](redshift-alter-table)
+ - [](redshift-alter-schema)
+- [](redshift-procedures)
+- [](redshift-table-functions)
+
+(redshift-insert)=
+```{include} non-transactional-insert.fragment
+```
+(redshift-update)=
```{include} sql-update-limitation.fragment
```
+(redshift-delete)=
```{include} sql-delete-limitation.fragment
```
+(redshift-alter-table)=
```{include} alter-table-limitation.fragment
```
+(redshift-alter-schema)=
```{include} alter-schema-limitation.fragment
```
+(redshift-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
@@ -169,6 +216,7 @@ statements, the connector supports the following features:
```{include} procedures-execute.fragment
```
+(redshift-table-functions)=
### Table functions
The connector provides specific {doc}`table functions ` to
diff --git a/docs/src/main/sphinx/connector/singlestore.md b/docs/src/main/sphinx/connector/singlestore.md
index e30f770e1798..c11467e1e330 100644
--- a/docs/src/main/sphinx/connector/singlestore.md
+++ b/docs/src/main/sphinx/connector/singlestore.md
@@ -85,9 +85,6 @@ will create a catalog named `sales` using the configured connector.
```{include} jdbc-case-insensitive-matching.fragment
```
-```{include} non-transactional-insert.fragment
-```
-
## Querying SingleStore
The SingleStore connector provides a schema for every SingleStore *database*.
@@ -315,26 +312,35 @@ a SingleStore database. In addition to the {ref}`globally available
` and {ref}`read operation `
statements, the connector supports the following features:
-- {doc}`/sql/insert`
-- {doc}`/sql/update`
-- {doc}`/sql/delete`
-- {doc}`/sql/truncate`
-- {doc}`/sql/create-table`
-- {doc}`/sql/create-table-as`
-- {doc}`/sql/drop-table`
-- {doc}`/sql/alter-table`
-- {doc}`/sql/create-schema`
-- {doc}`/sql/drop-schema`
+- [](/sql/insert), see also [](singlestore-insert)
+- [](/sql/update), see also [](singlestore-update)
+- [](/sql/delete), see also [](singlestore-delete)
+- [](/sql/truncate)
+- [](/sql/create-table)
+- [](/sql/create-table-as)
+- [](/sql/alter-table), see also [](singlestore-alter-table)
+- [](/sql/drop-table)
+- [](/sql/create-schema)
+- [](/sql/drop-schema)
+- [](singlestore-procedures)
+
+(singlestore-insert)=
+```{include} non-transactional-insert.fragment
+```
+(singlestore-update)=
```{include} sql-update-limitation.fragment
```
+(singlestore-delete)=
```{include} sql-delete-limitation.fragment
```
+(singlestore-alter-table)=
```{include} alter-table-limitation.fragment
```
+(singlestore-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
diff --git a/docs/src/main/sphinx/connector/snowflake.md b/docs/src/main/sphinx/connector/snowflake.md
index e17ca51a8b47..8d82faa722ce 100644
--- a/docs/src/main/sphinx/connector/snowflake.md
+++ b/docs/src/main/sphinx/connector/snowflake.md
@@ -62,9 +62,6 @@ multiple instances of the Snowflake connector.
```{include} jdbc-case-insensitive-matching.fragment
```
-```{include} non-transactional-insert.fragment
-```
-
% snowflake-type-mapping:
## Type mapping
@@ -233,21 +230,28 @@ No other types are supported.
(snowflake-sql-support)=
## SQL support
-The connector provides read access and write access to data and metadata in
-a Snowflake database. In addition to the {ref}`globally available
-` and {ref}`read operation `
+The connector provides read access and write access to data and metadata in a
+Snowflake database. In addition to the [globally
+available](sql-globally-available) and [read operation](sql-read-operations)
statements, the connector supports the following features:
-- {doc}`/sql/insert`
-- {doc}`/sql/delete`
-- {doc}`/sql/truncate`
-- {doc}`/sql/create-table`
-- {doc}`/sql/create-table-as`
-- {doc}`/sql/drop-table`
-- {doc}`/sql/alter-table`
-- {doc}`/sql/create-schema`
-- {doc}`/sql/drop-schema`
+- [](/sql/insert), see also [](snowflake-insert)
+- [](/sql/delete)
+- [](/sql/truncate)
+- [](/sql/create-table)
+- [](/sql/create-table-as)
+- [](/sql/drop-table)
+- [](/sql/alter-table)
+- [](/sql/create-schema)
+- [](/sql/drop-schema)
+- [](snowflake-procedures)
+- [](snowflake-table-functions)
+
+(snowflake-insert)=
+```{include} non-transactional-insert.fragment
+```
+(snowflake-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
@@ -255,6 +259,7 @@ statements, the connector supports the following features:
```{include} procedures-execute.fragment
```
+(snowflake-table-functions)=
### Table functions
The connector provides specific [table functions](/functions/table) to
diff --git a/docs/src/main/sphinx/connector/sql-delete-limitation.fragment b/docs/src/main/sphinx/connector/sql-delete-limitation.fragment
index 5c3a201ca369..aeb1e9bd9e18 100644
--- a/docs/src/main/sphinx/connector/sql-delete-limitation.fragment
+++ b/docs/src/main/sphinx/connector/sql-delete-limitation.fragment
@@ -1,4 +1,4 @@
-### SQL DELETE
+### DELETE limitation
If a ``WHERE`` clause is specified, the ``DELETE`` operation only works if the
predicate in the clause can be fully pushed down to the data source.
diff --git a/docs/src/main/sphinx/connector/sql-update-limitation.fragment b/docs/src/main/sphinx/connector/sql-update-limitation.fragment
index 6143a8e0762d..0e3ece216322 100644
--- a/docs/src/main/sphinx/connector/sql-update-limitation.fragment
+++ b/docs/src/main/sphinx/connector/sql-update-limitation.fragment
@@ -1,4 +1,4 @@
-### UPDATE
+### UPDATE limitation
Only `UPDATE` statements with constant assignments and predicates are
supported. For example, the following statement is supported because the values
diff --git a/docs/src/main/sphinx/connector/sqlserver.md b/docs/src/main/sphinx/connector/sqlserver.md
index 705083eb3281..469864d9fe9e 100644
--- a/docs/src/main/sphinx/connector/sqlserver.md
+++ b/docs/src/main/sphinx/connector/sqlserver.md
@@ -111,9 +111,6 @@ behavior of the connector and the issues queries to the database.
```{include} jdbc-case-insensitive-matching.fragment
```
-```{include} non-transactional-insert.fragment
-```
-
(sqlserver-fte-support)=
### Fault-tolerant execution support
@@ -325,25 +322,37 @@ For Trino `VARCHAR(n)`:
## SQL support
The connector provides read access and write access to data and metadata in SQL
-Server. In addition to the {ref}`globally available `
-and {ref}`read operation ` statements, the connector
-supports the following features:
+Server. In addition to the [globally available](sql-globally-available) and
+[read operation](sql-read-operations) statements, the connector supports the
+following features:
+
+- [](/sql/insert), see also [](sqlserver-insert)
+- [](/sql/update), see also [](sqlserver-update)
+- [](/sql/delete), see also [](sqlserver-delete)
+- [](/sql/truncate)
+- [](sql-schema-table-management), see also:
+ - [](sqlserver-alter-table)
+- [](sqlserver-procedures)
+- [](sqlserver-table-functions)
-- {doc}`/sql/insert`
-- {doc}`/sql/update`
-- {doc}`/sql/delete`
-- {doc}`/sql/truncate`
-- {ref}`sql-schema-table-management`
+(sqlserver-insert)=
+```{include} non-transactional-insert.fragment
+```
+
+(sqlserver-update)=
```{include} sql-update-limitation.fragment
```
+(sqlserver-delete)=
```{include} sql-delete-limitation.fragment
```
+(sqlserver-alter-table)=
```{include} alter-table-limitation.fragment
```
+(sqlserver-procedures)=
### Procedures
```{include} jdbc-procedures-flush.fragment
@@ -351,6 +360,7 @@ supports the following features:
```{include} procedures-execute.fragment
```
+(sqlserver-table-functions)=
### Table functions
The connector provides specific {doc}`table functions ` to
diff --git a/docs/src/main/sphinx/connector/vertica.md b/docs/src/main/sphinx/connector/vertica.md
index 72960dba32fb..79f2ff079b44 100644
--- a/docs/src/main/sphinx/connector/vertica.md
+++ b/docs/src/main/sphinx/connector/vertica.md
@@ -165,13 +165,16 @@ features:
- [](/sql/create-table)
- [](/sql/create-table-as)
- [](/sql/drop-table)
-- [](/sql/alter-table) excluding `DROP COLUMN`
+- [](/sql/alter-table) excluding `DROP COLUMN`, see also [](vertica-alter-table)
- [](/sql/create-schema)
- [](/sql/drop-schema)
+- [](vertica-table-functions)
+(vertica-alter-table)=
```{include} alter-table-limitation.fragment
```
+(vertica-table-functions)=
## Table functions
The connector provides specific [table functions](/functions/table) to
diff --git a/docs/src/main/sphinx/functions.md b/docs/src/main/sphinx/functions.md
index c445861ecce0..cb931d755667 100644
--- a/docs/src/main/sphinx/functions.md
+++ b/docs/src/main/sphinx/functions.md
@@ -12,7 +12,7 @@ Refer to the following sections for further details:
In addition, Trino supports implementation of [custom
functions](/develop/functions) or [custom table
functions](/develop/table-functions) provided by a plugin, and creation of
-user-defined functions as [SQL routines](/routines).
+[](/udf).
## Functions by name
diff --git a/docs/src/main/sphinx/functions/conditional.md b/docs/src/main/sphinx/functions/conditional.md
index d4086848294a..6aad6280f331 100644
--- a/docs/src/main/sphinx/functions/conditional.md
+++ b/docs/src/main/sphinx/functions/conditional.md
@@ -51,7 +51,7 @@ SELECT a, b,
END
```
-SQL routines can use [`CASE` statements](/routines/case) that use a slightly
+SQL UDFs can use [`CASE` statements](/udf/sql/case) that use a slightly
different syntax from the CASE expressions. Specifically note the requirements
for terminating each clause with a semicolon `;` and the usage of `END CASE`.
@@ -95,9 +95,9 @@ SELECT
FROM tpch.sf1.orders;
```
-SQL routines can use [`IF` statements](/routines/if) that use a slightly
-different syntax from `IF` expressions. Specifically note the requirement
-for terminating each clause with a semicolon `;` and the usage of `END IF`.
+SQL UDFs can use [`IF` statements](/udf/sql/if) that use a slightly different
+syntax from `IF` expressions. Specifically note the requirement for terminating
+each clause with a semicolon `;` and the usage of `END IF`.
(coalesce-function)=
## COALESCE
diff --git a/docs/src/main/sphinx/index.md b/docs/src/main/sphinx/index.md
index 16e8ab72011b..24ea617a83bb 100644
--- a/docs/src/main/sphinx/index.md
+++ b/docs/src/main/sphinx/index.md
@@ -12,9 +12,9 @@ optimizer
connector
object-storage
functions
+udf
language
sql
-routines
develop
glossary
appendix
diff --git a/docs/src/main/sphinx/language/sql-support.md b/docs/src/main/sphinx/language/sql-support.md
index 767db2af93cf..8dc3b693d51d 100644
--- a/docs/src/main/sphinx/language/sql-support.md
+++ b/docs/src/main/sphinx/language/sql-support.md
@@ -118,10 +118,10 @@ connector to connector:
- {doc}`/sql/drop-materialized-view`
- {doc}`/sql/refresh-materialized-view`
-(sql-routine-management)=
-### Routine management
+(udf-management)=
+### User-defined function management
-The following statements are used to manage [catalog routines](routine-catalog):
+The following statements are used to manage [](udf-catalog):
- [](/sql/create-function)
- [](/sql/drop-function)
diff --git a/docs/src/main/sphinx/object-storage/file-system-s3.md b/docs/src/main/sphinx/object-storage/file-system-s3.md
index 926d31cb870d..e18f188cdcc8 100644
--- a/docs/src/main/sphinx/object-storage/file-system-s3.md
+++ b/docs/src/main/sphinx/object-storage/file-system-s3.md
@@ -174,6 +174,9 @@ The security mapping must provide one or more configuration settings:
- `kmsKeyId`: ID of KMS-managed key to be used for client-side encryption.
- `allowedKmsKeyIds`: KMS-managed key IDs that are allowed to be specified as an extra
credential. If list cotains `*`, then any key can be specified via extra credential.
+- `sseCustomerKey`: The customer provided key (SSE-C) for server-side encryption.
+- `allowedSseCustomerKey`: The SSE-C keys that are allowed to be specified as an extra
+ credential. If list cotains `*`, then any key can be specified via extra credential.
- `endpoint`: The S3 storage endpoint server. This optional property can be used
to override S3 endpoints on a per-bucket basis.
- `region`: The S3 region to connect to. This optional property can be used
@@ -262,6 +265,8 @@ Example JSON configuration:
- The name of the *extra credential* used to provide the IAM role.
* - `s3.security-mapping.kms-key-id-credential-name`
- The name of the *extra credential* used to provide the KMS-managed key ID.
+* - `s3.security-mapping.sse-customer-key-credential-name`
+ - The name of the *extra credential* used to provide the server-side encryption with customer-provided keys (SSE-C).
* - `s3.security-mapping.refresh-period`
- How often to refresh the security mapping configuration, specified as a
{ref}`prop-type-duration`. By default, the configuration is not refreshed.
diff --git a/docs/src/main/sphinx/redirects.txt b/docs/src/main/sphinx/redirects.txt
index 361a63fc6989..26e0254da98a 100644
--- a/docs/src/main/sphinx/redirects.txt
+++ b/docs/src/main/sphinx/redirects.txt
@@ -10,3 +10,18 @@ connector/atop.md connector/removed.md
connector/localfile.md connector/removed.md
connector/accumulo.md connector/removed.md
security/apache-ranger-access-control.md security/ranger-access-control.md
+routines.md udf.md
+routines/function.md udf/function.md
+routines/introduction.md udf/introduction.md
+routines/begin.md udf/sql/begin.md
+routines/case.md udf/sql/case.md
+routines/declare.md udf/sql/declare.md
+routines/examples.md udf/sql/examples.md
+routines/if.md udf/sql/if.md
+routines/iterate.md udf/sql/iterate.md
+routines/leave.md udf/sql/leave.md
+routines/loop.md udf/sql/loop.md
+routines/repeat.md udf/sql/repeat.md
+routines/return.md udf/sql/return.md
+routines/set.md udf/sql/set.md
+routines/while.md udf/sql/while.md
diff --git a/docs/src/main/sphinx/release.md b/docs/src/main/sphinx/release.md
index 2d083b797a47..c2bac1c08263 100644
--- a/docs/src/main/sphinx/release.md
+++ b/docs/src/main/sphinx/release.md
@@ -6,6 +6,7 @@
```{toctree}
:maxdepth: 1
+release/release-468
release/release-467
release/release-466
release/release-465
diff --git a/docs/src/main/sphinx/release/release-431.md b/docs/src/main/sphinx/release/release-431.md
index 5a80e2d172fb..068cc79657ba 100644
--- a/docs/src/main/sphinx/release/release-431.md
+++ b/docs/src/main/sphinx/release/release-431.md
@@ -2,7 +2,7 @@
## General
-* Add support for [](/routines). ({issue}`19308`)
+* Add support for [](/udf/sql). ({issue}`19308`)
* Add support for [](/sql/create-function) and [](/sql/drop-function) statements. ({issue}`19308`)
* Add support for the `REPLACE` modifier to the `CREATE TABLE` statement. ({issue}`13180`)
* Disallow a `null` offset for the {func}`lead` and {func}`lag` functions. ({issue}`19003`)
@@ -27,7 +27,7 @@
## Hive connector
-* Add support for [SQL routine management](sql-routine-management). ({issue}`19308`)
+* Add support for [](udf-management). ({issue}`19308`)
* Replace the `hive.metastore-timeout` Hive metastore configuration property
with the `hive.metastore.thrift.client.connect-timeout` and
`hive.metastore.thrift.client.read-timeout` properties. ({issue}`19390`)
@@ -50,7 +50,7 @@
## Memory connector
-* Add support for [SQL routine management](sql-routine-management). ({issue}`19308`)
+* Add support for [](udf-management). ({issue}`19308`)
## SPI
diff --git a/docs/src/main/sphinx/release/release-436.md b/docs/src/main/sphinx/release/release-436.md
index b1a0bab0e7c9..c6abe7357eaf 100644
--- a/docs/src/main/sphinx/release/release-436.md
+++ b/docs/src/main/sphinx/release/release-436.md
@@ -6,7 +6,7 @@
[](jvm-config). ({issue}`20010`)
* Improve performance by not generating redundant predicates. ({issue}`16520`)
* Fix query failure when invoking the `json_table` function. ({issue}`20122`)
-* Fix query hang when a [SQL routine](/routines) dereferences a row field. ({issue}`19997`).
+* Fix query hang when a [](/udf/sql) dereferences a row field. ({issue}`19997`).
* Fix potential incorrect results when using the {func}`ST_Centroid` and
{func}`ST_Buffer` functions for tiny geometries. ({issue}`20237`)
diff --git a/docs/src/main/sphinx/release/release-440.md b/docs/src/main/sphinx/release/release-440.md
index 2a79828a8e5f..5490782be738 100644
--- a/docs/src/main/sphinx/release/release-440.md
+++ b/docs/src/main/sphinx/release/release-440.md
@@ -12,7 +12,7 @@
* Fix query failure when a check constraint is null. ({issue}`20906`)
* Fix query failure for aggregations over `CASE` expressions when the input
evaluation could throw an error. ({issue}`20652`)
-* Fix incorrect behavior of the else clause in a SQL routines with a single
+* Fix incorrect behavior of the else clause in a SQL UDFs with a single
if/end condition. ({issue}`20926`)
* Fix the `ALTER TABLE EXECUTE optimize` queries failing due to exceeding the
open writer limit. ({issue}`20871`)
diff --git a/docs/src/main/sphinx/release/release-446.md b/docs/src/main/sphinx/release/release-446.md
index eadcbe190fea..05f6b0bf0f16 100644
--- a/docs/src/main/sphinx/release/release-446.md
+++ b/docs/src/main/sphinx/release/release-446.md
@@ -10,9 +10,9 @@
statement. ({issue}`21619`)
* Fix `CREATE CATALOG` statements including quotes in catalog names. ({issue}`21399`)
* Fix potential query failure when a column name ends with a `:`. ({issue}`21676`)
-* Fix potential query failure when a [SQL routine](/routines) contains a label
+* Fix potential query failure when a [](/udf/sql) contains a label
reference in a `LEAVE`, `ITERATE`, `REPEAT`, or `WHILE` statement. ({issue}`21682`)
-* Fix query failure when [SQL routines](/routines) use the `NULLIF` or `BETWEEN`
+* Fix query failure when [](/udf/sql) use the `NULLIF` or `BETWEEN`
functions. ({issue}`19820`)
* Fix potential query failure due to worker nodes running out of memory in
concurrent scenarios. ({issue}`21706`)
diff --git a/docs/src/main/sphinx/release/release-447.md b/docs/src/main/sphinx/release/release-447.md
index d9e675f7e6b7..b1aee4fd4d31 100644
--- a/docs/src/main/sphinx/release/release-447.md
+++ b/docs/src/main/sphinx/release/release-447.md
@@ -13,7 +13,7 @@
## CLI
-* Fix incorrect error location markers for SQL routines causing CLI to print
+* Fix incorrect error location markers for SQL UDFs causing the CLI to print
exceptions. ({issue}`21357`)
## Delta Lake connector
diff --git a/docs/src/main/sphinx/release/release-453.md b/docs/src/main/sphinx/release/release-453.md
index ecf70c8eea80..e5c6e63cdf1d 100644
--- a/docs/src/main/sphinx/release/release-453.md
+++ b/docs/src/main/sphinx/release/release-453.md
@@ -70,7 +70,7 @@
`hive.metastore.glue.use-web-identity-token-credentials-provider`
configuration property. ({issue}`15267`)
* Fix failure to read Hive tables migrated to Iceberg with Apache Spark. ({issue}`11338`)
-* Fix failure for `CREATE FUNCTION` with SQL routine storage in Glue when
+* Fix failure for `CREATE FUNCTION` with SQL UDF storage in Glue when
`hive.metastore.glue.catalogid` is set. ({issue}`22717`)
## Hudi connector
diff --git a/docs/src/main/sphinx/release/release-454.md b/docs/src/main/sphinx/release/release-454.md
index 7c66071bd7ec..6aa22f305814 100644
--- a/docs/src/main/sphinx/release/release-454.md
+++ b/docs/src/main/sphinx/release/release-454.md
@@ -23,7 +23,7 @@
## Web UI
-* Add information about which tables and routines have been referenced by a
+* Add information about which tables and UDFs have been referenced by a
query. ({issue}`20843`)
## JDBC driver
diff --git a/docs/src/main/sphinx/release/release-468.md b/docs/src/main/sphinx/release/release-468.md
new file mode 100644
index 000000000000..601d41728fba
--- /dev/null
+++ b/docs/src/main/sphinx/release/release-468.md
@@ -0,0 +1,51 @@
+# Release 468 (17 Dec 2024)
+
+## General
+
+* Add experimental support for [](/udf/python). ({issue}`24378`)
+* Add cluster overview to the [](/admin/preview-web-interface). ({issue}`23600`)
+* Add new node states `DRAINING` and `DRAINED` to make it possible to reactivate
+ a draining worker node. ({issue}`24444 `)
+
+## BigQuery connector
+
+* Improve performance when reading external
+ [BigLake](https://cloud.google.com/bigquery/docs/biglake-intro) tables. ({issue}`21016`)
+
+## Delta Lake connector
+
+* {{breaking}} Reduce coordinator memory usage for the Delta table metadata
+ cache and enable configuration `delta.metadata.cache-max-retained-size` to
+ control memory usage. Remove the configuration property
+ `delta.metadata.cache-size` and increase the default for
+ `delta.metadata.cache-ttl` to `30m`. ({issue}`24432`)
+
+## Hive connector
+
+* Enable mismatched bucket execution optimization by default. This can be
+ disabled with `hive.optimize-mismatched-bucket-count` configuration property
+ and the `optimize_mismatched_bucket_count` session property. ({issue}`23432`)
+* Improve performance by deactivating bucket execution when not useful in query
+ processing. ({issue}`23432`)
+
+## Iceberg connector
+
+* Improve performance when running a join or aggregation on a bucketed table
+ with bucketed execution. This can be deactivated with the
+ `iceberg.bucket-execution` configuration property and the
+ `bucket_execution_enabled` session property. ({issue}`23432`)
+* Deprecate the `iceberg.materialized-views.storage-schema` configuration
+ property. ({issue}`24398`)
+* {{breaking}} Rename the `partitions` column in the `$manifests` metadata table
+ to `partition_summaries`. ({issue}`24103`)
+* Avoid excessive resource usage on coordinator when reading Iceberg system
+ tables. ({issue}`24396`)
+
+## PostgreSQL connector
+
+* Add support for non-transactional [MERGE statements](/sql/merge). ({issue}`23034`)
+
+## SPI
+
+* Add partitioning push down, which a connector can use to activate optional
+ partitioning or choose between multiple partitioning strategies. ({issue}`23432`)
diff --git a/docs/src/main/sphinx/routines.md b/docs/src/main/sphinx/routines.md
deleted file mode 100644
index 541608d529d2..000000000000
--- a/docs/src/main/sphinx/routines.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# SQL routines
-
-A SQL routine is a custom, user-defined function authored by a user of Trino in
-a client and written in the SQL routine language. Routines are scalar functions
-that return a single output value. More details are available in the following
-sections:
-
-```{toctree}
-:maxdepth: 1
-
-Introduction
-Examples
-routines/begin
-routines/case
-routines/declare
-routines/function
-routines/if
-routines/iterate
-routines/leave
-routines/loop
-routines/repeat
-routines/return
-routines/set
-routines/while
-```
diff --git a/docs/src/main/sphinx/routines/begin.md b/docs/src/main/sphinx/routines/begin.md
deleted file mode 100644
index c1ef143fd70a..000000000000
--- a/docs/src/main/sphinx/routines/begin.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# BEGIN
-
-## Synopsis
-
-```text
-BEGIN
- [ DECLARE ... ]
- statements
-END
-```
-
-## Description
-
-Marks the start and end of a block in a [SQL routine](/routines/introduction).
-`BEGIN` can be used wherever a statement can be used to group multiple
-statements together and to declare variables local to the block. A typical use
-case is as first statement within a [](/routines/function). Blocks can also be
-nested.
-
-After the `BEGIN` keyword, you can add variable declarations using
-[](/routines/declare) statements, followed by one or more statements that define
-the main body of the routine, separated by `;`. The following statements can be
-used:
-
-* [](/routines/case)
-* [](/routines/if)
-* [](/routines/iterate)
-* [](/routines/leave)
-* [](/routines/loop)
-* [](/routines/repeat)
-* [](/routines/return)
-* [](/routines/set)
-* [](/routines/while)
-* Nested [](/routines/begin) blocks
-
-## Examples
-
-The following example computes the value `42`:
-
-```sql
-FUNCTION meaning_of_life()
- RETURNS tinyint
- BEGIN
- DECLARE a tinyint DEFAULT 6;
- DECLARE b tinyint DEFAULT 7;
- RETURN a * b;
- END
-```
-
-Further examples of varying complexity that cover usage of the `BEGIN` statement
-in combination with other statements are available in the [SQL routines examples
-documentation](/routines/examples).
-
-## See also
-
-* [](/routines/introduction)
-* [](/routines/function)
diff --git a/docs/src/main/sphinx/routines/function.md b/docs/src/main/sphinx/routines/function.md
deleted file mode 100644
index 21df3a95c392..000000000000
--- a/docs/src/main/sphinx/routines/function.md
+++ /dev/null
@@ -1,102 +0,0 @@
-# FUNCTION
-
-## Synopsis
-
-```text
-FUNCTION name ( [ parameter_name data_type [, ...] ] )
- RETURNS type
- [ LANGUAGE language]
- [ NOT? DETERMINISTIC ]
- [ RETURNS NULL ON NULL INPUT ]
- [ CALLED ON NULL INPUT ]
- [ SECURITY { DEFINER | INVOKER } ]
- [ COMMENT description]
- statements
-```
-
-## Description
-
-Declare a SQL routine.
-
-The `name` of the routine. [Inline routines](routine-inline) can use a simple
-string. [Catalog routines](routine-catalog) must qualify the name of the catalog
-and schema, delimited by `.`, to store the routine or rely on the [default
-catalog and schema for routine storage](/admin/properties-sql-environment).
-
-The list of parameters is a comma-separated list of names `parameter_name` and
-data types `data_type`, see [data type](/language/types). An empty list, specified as
-`()` is also valid.
-
-The `type` value after the `RETURNS` keyword identifies the [data
-type](/language/types) of the routine output.
-
-The optional `LANGUAGE` characteristic identifies the language used for the
-routine definition with `language`. Only `SQL` is supported.
-
-The optional `DETERMINISTIC` or `NOT DETERMINISTIC` characteristic declares that
-the routine is deterministic. This means that repeated routine calls with
-identical input parameters yield the same result. For SQL language routines, a
-routine is non-deterministic if it calls any non-deterministic routines and
-[functions](/functions). By default, routines are assume to have a deterministic
-behavior.
-
-The optional `RETURNS NULL ON NULL INPUT` characteristic declares that the
-routine returns a `NULL` value when any of the input parameters are `NULL`.
-The routine is not invoked with a `NULL` input value.
-
-The `CALLED ON NULL INPUT` characteristic declares that the routine is invoked
-with `NULL` input parameter values.
-
-The `RETURNS NULL ON NULL INPUT` and `CALLED ON NULL INPUT` characteristics are
-mutually exclusive, with `CALLED ON NULL INPUT` as the default.
-
-The security declaration of `SECURITY INVOKER` or `SECURITY DEFINER` is only
-valid for catalog routines. It sets the mode for processing the routine with the
-permissions of the user who calls the routine (`INVOKER`) or the user who
-created the routine (`DEFINER`).
-
-The `COMMENT` characteristic can be used to provide information about the
-function to other users as `description`. The information is accessible with
-[](/sql/show-functions).
-
-The body of the routine can either be a simple single `RETURN` statement with an
-expression, or compound list of `statements` in a `BEGIN` block. Routines must
-contain a `RETURN` statement at the end of the top-level block, even if it's
-unreachable.
-
-## Examples
-
-A simple catalog function:
-
-```sql
-CREATE FUNCTION example.default.meaning_of_life()
- RETURNS BIGINT
- RETURN 42;
-```
-
-And used:
-
-```sql
-SELECT example.default.meaning_of_life(); -- returns 42
-```
-
-Equivalent usage with an inline function:
-
-```sql
-WITH FUNCTION meaning_of_life()
- RETURNS BIGINT
- RETURN 42
-SELECT meaning_of_life();
-```
-
-Further examples of varying complexity that cover usage of the `FUNCTION`
-statement in combination with other statements are available in the [SQL
-routines examples documentation](/routines/examples).
-
-## See also
-
-* [](/routines/introduction)
-* [](/routines/begin)
-* [](/routines/return)
-* [](/sql/create-function)
-
diff --git a/docs/src/main/sphinx/routines/introduction.md b/docs/src/main/sphinx/routines/introduction.md
deleted file mode 100644
index b6fb55d05631..000000000000
--- a/docs/src/main/sphinx/routines/introduction.md
+++ /dev/null
@@ -1,192 +0,0 @@
-# Introduction to SQL routines
-
-A SQL routine is a custom, user-defined function authored by a user of Trino and
-written in the SQL routine language. Routines are scalar functions that return a
-single output value, similar to [built-in functions](/functions).
-
-[Declare the routine](routine-declaration) with a `FUNCTION` definition using
-the supported SQL routine statements. A routine can be declared and used as an
-[inline routine](routine-inline) or declared as a [catalog
-routine](routine-catalog) and used repeatedly.
-
-(routine-inline)=
-## Inline routines
-
-An inline routine declares and uses the routine within a query processing
-context. The routine is declared in a `WITH` block before the query:
-
-```sql
-WITH
- FUNCTION abc(x integer)
- RETURNS integer
- RETURN x * 2
-SELECT abc(21);
-```
-
-Inline routine names must follow SQL identifier naming conventions, and cannot
-contain `.` characters.
-
-The routine declaration is only valid within the context of the query. A
-separate later invocation of the routine is not possible. If this is desired,
-use a [catalog routine](routine-catalog).
-
-Multiple inline routine declarations are comma-separated, and can include
-routines calling each other, as long as a called routine is declared before
-the first invocation.
-
-```sql
-WITH
- FUNCTION abc(x integer)
- RETURNS integer
- RETURN x * 2,
- FUNCTION xyz(x integer)
- RETURNS integer
- RETURN abc(x) + 1
-SELECT xyz(21);
-```
-
-Note that inline routines can mask and override the meaning of a built-in function:
-
-```sql
-WITH
- FUNCTION abs(x integer)
- RETURNS integer
- RETURN x * 2
-SELECT abs(-10); -- -20, not 10!
-```
-
-(routine-catalog)=
-## Catalog routines
-
-You can store a routine in the context of a catalog, if the connector used in
-the catalog supports routine storage. The following connectors support catalog
-routine storage:
-
-* [](/connector/hive)
-* [](/connector/memory)
-
-In this scenario, the following commands can be used:
-
-* [](/sql/create-function) to create and store a routine.
-* [](/sql/drop-function) to remove a routine.
-* [](/sql/show-functions) to display a list of routines in a catalog.
-
-Catalog routines must use a name that combines the catalog name and schema name
-with the routine name, such as `example.default.power` for the `power` routine
-in the `default` schema of the `example` catalog.
-
-Invocation must use the fully qualified name, such as `example.default.power`.
-
-(routine-sql-environment)=
-## SQL environment configuration
-
-Configuration of the `sql.default-function-catalog` and
-`sql.default-function-schema` [](/admin/properties-sql-environment) allows you
-to set the default storage for SQL routines. The catalog and schema must be
-added to the `sql.path` as well. This enables users to call SQL routines and
-perform all [SQL routine management](sql-routine-management) without specifying
-the full path to the routine.
-
-:::{note}
-Use the [](/connector/memory) in a catalog for simple storing and
-testing of your SQL routines.
-:::
-
-(routine-declaration)=
-## Routine declaration
-
-Refer to the documentation for the [](/routines/function) keyword for more
-details about declaring the routine overall. The routine body is composed with
-statements from the following list:
-
-* [](/routines/begin)
-* [](/routines/case)
-* [](/routines/declare)
-* [](/routines/if)
-* [](/routines/iterate)
-* [](/routines/leave)
-* [](/routines/loop)
-* [](/routines/repeat)
-* [](/routines/return)
-* [](/routines/set)
-* [](/routines/while)
-
-Statements can also use [built-in functions and operators](/functions) as well
-as other routines, although recursion is not supported for routines.
-
-Find simple examples in each statement documentation, and refer to the [example
-documentation](/routines/examples) for more complex use cases that combine
-multiple statements.
-
-:::{note}
-User-defined functions can alternatively be written in Java and deployed as a
-plugin. Details are available in the [developer guide](/develop/functions).
-:::
-
-(routine-label)=
-## Labels
-
-Routines can contain labels as markers for a specific block in the declaration
-before the following keywords:
-
-* `CASE`
-* `IF`
-* `LOOP`
-* `REPEAT`
-* `WHILE`
-
-The label is used to name the block to continue processing with the `ITERATE`
-statement or exit the block with the `LEAVE` statement. This flow control is
-supported for nested blocks, allowing to continue or exit an outer block, not
-just the innermost block. For example, the following snippet uses the label
-`top` to name the complete block from `REPEAT` to `END REPEAT`:
-
-```sql
-top: REPEAT
- SET a = a + 1;
- IF a <= 3 THEN
- ITERATE top;
- END IF;
- SET b = b + 1;
- UNTIL a >= 10
-END REPEAT;
-```
-
-Labels can be used with the `ITERATE` and `LEAVE` statements to continue
-processing the block or leave the block. This flow control is also supported for
-nested blocks and labels.
-
-## Recommendations
-
-Processing routines can potentially be resource intensive on the cluster in
-terms of memory and processing. Take the following considerations into account
-when writing and running SQL routines:
-
-* Some checks for the runtime behavior of routines are in place. For example,
- routines that take longer to process than a hardcoded threshold are
- automatically terminated.
-* Avoid creation of arrays in a looping construct. Each iteration creates a
- separate new array with all items and copies the data for each modification,
- leaving the prior array in memory for automated clean up later. Use a [lambda
- expression](/functions/lambda) instead of the loop.
-* Avoid concatenating strings in a looping construct. Each iteration creates a
- separate new string and copying the old string for each modification, leaving
- the prior string in memory for automated clean up later. Use a [lambda
- expression](/functions/lambda) instead of the loop.
-* Most routines should declare the `RETURNS NULL ON NULL INPUT` characteristics
- unless the code has some special handling for null values. You must declare
- this explicitly since `CALLED ON NULL INPUT` is the default characteristic.
-
-## Limitations
-
-The following limitations apply to SQL routines.
-
-* Routines must be declared before they are referenced.
-* Recursion cannot be declared or processed.
-* Mutual recursion can not be declared or processed.
-* Queries cannot be processed in a routine.
-
-Specifically this means that routines can not use `SELECT` queries to retrieve
-data or any other queries to process data within the routine. Instead queries
-can use routines to process data. Routines only work on data provided as input
-values and only provide output data from the `RETURN` statement.
diff --git a/docs/src/main/sphinx/routines/return.md b/docs/src/main/sphinx/routines/return.md
deleted file mode 100644
index cc8bfe483989..000000000000
--- a/docs/src/main/sphinx/routines/return.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# RETURN
-
-## Synopsis
-
-```text
-RETURN expression
-```
-
-## Description
-
-Provide the value from a [SQL routines](/routines/introduction) to the caller.
-The value is the result of evaluating the expression. It can be a static value,
-a declared variable or a more complex expression.
-
-## Examples
-
-The following examples return a static value, the result of an expression, and
-the value of the variable x:
-
-```sql
-RETURN 42;
-RETURN 6 * 7;
-RETURN x;
-```
-
-Further examples of varying complexity that cover usage of the `RETURN`
-statement in combination with other statements are available in the [SQL
-routines examples documentation](/routines/examples).
-
-All routines must contain a `RETURN` statement at the end of the top-level
-block in the `FUNCTION` declaration, even if it's unreachable.
-
-## See also
-
-* [](/routines/introduction)
-* [](/routines/function)
diff --git a/docs/src/main/sphinx/security/file-system-access-control.md b/docs/src/main/sphinx/security/file-system-access-control.md
index 55644dfc12b5..7651f438a33a 100644
--- a/docs/src/main/sphinx/security/file-system-access-control.md
+++ b/docs/src/main/sphinx/security/file-system-access-control.md
@@ -142,11 +142,11 @@ Permissions required for executing functions:
* - `CREATE FUNCTION`
- `all`
- `ownership`
- - Not all connectors support [catalog routines](routine-catalog).
+ - Not all connectors support [](udf-catalog).
* - `DROP FUNCTION`
- `all`
- `ownership`
- - Not all connectors support [catalog routines](routine-catalog).
+ - Not all connectors support [](udf-catalog).
:::
(system-file-auth-visibility)=
diff --git a/docs/src/main/sphinx/sql/create-function.md b/docs/src/main/sphinx/sql/create-function.md
index 513b64557506..b5ace2dde8a0 100644
--- a/docs/src/main/sphinx/sql/create-function.md
+++ b/docs/src/main/sphinx/sql/create-function.md
@@ -4,24 +4,23 @@
```text
CREATE [OR REPLACE] FUNCTION
- routine_definition
+ udf_definition
```
## Description
-Create or replace a [](routine-catalog). The `routine_definition` is composed of
-the usage of [](/routines/function) and nested statements. The name of the
-routine must be fully qualified with catalog and schema location, unless the
-[default SQL routine storage catalog and
-schema](/admin/properties-sql-environment) are configured. The connector used in
-the catalog must support routine storage.
+Create or replace a [](udf-catalog). The `udf_definition` is composed of the
+usage of [](/udf/function) and nested statements. The name of the UDF must be
+fully qualified with catalog and schema location, unless the [default UDF
+storage catalog and schema](/admin/properties-sql-environment) are configured.
+The connector used in the catalog must support UDF storage.
-The optional `OR REPLACE` clause causes the routine to be replaced if it already
+The optional `OR REPLACE` clause causes the UDF to be replaced if it already
exists rather than raising an error.
## Examples
-The following example creates the `meaning_of_life` routine in the `default`
+The following example creates the `meaning_of_life` UDF in the `default`
schema of the `example` catalog:
```sql
@@ -32,7 +31,7 @@ CREATE FUNCTION example.default.meaning_of_life()
END;
```
-If the [default catalog and schema for routine
+If the [default catalog and schema for UDF
storage](/admin/properties-sql-environment) is configured, you can use the
following more compact syntax:
@@ -42,12 +41,12 @@ CREATE FUNCTION meaning_of_life() RETURNS bigint RETURN 42;
Further examples of varying complexity that cover usage of the `FUNCTION`
statement in combination with other statements are available in the [SQL
-routines examples documentation](/routines/examples).
+UDF examples documentation](/udf/sql/examples).
## See also
* [](/sql/drop-function)
* [](/sql/show-create-function)
* [](/sql/show-functions)
-* [](/routines/introduction)
+* [](/udf)
* [](/admin/properties-sql-environment)
diff --git a/docs/src/main/sphinx/sql/drop-function.md b/docs/src/main/sphinx/sql/drop-function.md
index 76235b0f6de9..0183facb80f1 100644
--- a/docs/src/main/sphinx/sql/drop-function.md
+++ b/docs/src/main/sphinx/sql/drop-function.md
@@ -3,38 +3,37 @@
## Synopsis
```text
-DROP FUNCTION [ IF EXISTS ] routine_name ( [ [ parameter_name ] data_type [, ...] ] )
+DROP FUNCTION [ IF EXISTS ] udf_name ( [ [ parameter_name ] data_type [, ...] ] )
```
## Description
-Removes a [](routine-catalog). The value of `routine_name`
-must be fully qualified with catalog and schema location of the routine, unless
-the [default SQL routine storage catalog and
-schema](/admin/properties-sql-environment) are configured.
+Removes a [catalog UDF](udf-catalog). The value of `udf_name` must be fully
+qualified with catalog and schema location of the UDF, unless the [default UDF storage catalog and schema](/admin/properties-sql-environment) are
+configured.
-The `data_type`s must be included for routines that use parameters to ensure the
-routine with the correct name and parameter signature is removed.
+The `data_type`s must be included for UDFs that use parameters to ensure the UDF
+with the correct name and parameter signature is removed.
The optional `IF EXISTS` clause causes the error to be suppressed if
the function does not exist.
## Examples
-The following example removes the `meaning_of_life` routine in the `default`
-schema of the `example` catalog:
+The following example removes the `meaning_of_life` UDF in the `default` schema
+of the `example` catalog:
```sql
DROP FUNCTION example.default.meaning_of_life();
```
-If the routine uses a input parameter, the type must be added:
+If the UDF uses a input parameter, the type must be added:
```sql
DROP FUNCTION multiply_by_two(bigint);
```
-If the [default catalog and schema for routine
+If the [default catalog and schema for UDF
storage](/admin/properties-sql-environment) is configured, you can use the
following more compact syntax:
@@ -47,5 +46,5 @@ DROP FUNCTION meaning_of_life();
* [](/sql/create-function)
* [](/sql/show-create-function)
* [](/sql/show-functions)
-* [](/routines/introduction)
+* [](/udf)
* [](/admin/properties-sql-environment)
diff --git a/docs/src/main/sphinx/sql/select.md b/docs/src/main/sphinx/sql/select.md
index 5d6b93b6ed23..82938f816871 100644
--- a/docs/src/main/sphinx/sql/select.md
+++ b/docs/src/main/sphinx/sql/select.md
@@ -3,7 +3,7 @@
## Synopsis
```text
-[ WITH FUNCTION sql_routines ]
+[ WITH FUNCTION udf ]
[ WITH [ RECURSIVE ] with_query [, ...] ]
SELECT [ ALL | DISTINCT ] select_expression [, ...]
[ FROM from_item [, ...] ]
@@ -70,10 +70,10 @@ Retrieve rows from zero or more tables.
## WITH FUNCTION clause
-The `WITH FUNCTION` clause allows you to define a list of inline SQL routines
-that are available for use in the rest of the query.
+The `WITH FUNCTION` clause allows you to define a list of [](udf-inline) that
+are available for use in the rest of the query.
-The following example declares and uses two inline routines:
+The following example declares and uses two inline UDFs:
```sql
WITH
@@ -87,8 +87,8 @@ SELECT hello('Finn') || ' and ' || bye('Joe');
-- Hello Finn! and Bye Joe!
```
-Find further information about routines in general, inline routines, all
-supported statements, and examples in [](/routines).
+Find further information about UDFs in general, inline UDFs, all supported
+statements, and examples in [](/udf).
## WITH clause
diff --git a/docs/src/main/sphinx/sql/show-create-function.md b/docs/src/main/sphinx/sql/show-create-function.md
index 1015726b6de1..bac15c00b448 100644
--- a/docs/src/main/sphinx/sql/show-create-function.md
+++ b/docs/src/main/sphinx/sql/show-create-function.md
@@ -23,5 +23,5 @@ SHOW CREATE FUNCTION example.default.meaning_of_life;
* [](/sql/create-function)
* [](/sql/drop-function)
* [](/sql/show-functions)
-* [](/routines/introduction)
+* [](/udf)
* [](/admin/properties-sql-environment)
diff --git a/docs/src/main/sphinx/sql/show-functions.md b/docs/src/main/sphinx/sql/show-functions.md
index 9d9fe0067591..41136258bda7 100644
--- a/docs/src/main/sphinx/sql/show-functions.md
+++ b/docs/src/main/sphinx/sql/show-functions.md
@@ -10,7 +10,7 @@ SHOW FUNCTIONS [ FROM schema ] [ LIKE pattern ]
List functions in `schema` or all functions in the current session path. This
can include built-in functions, [functions from a custom
-plugin](/develop/functions), and [SQL routines](/routines).
+plugin](/develop/functions), and [](/udf).
For each function returned, the following information is displayed:
@@ -30,8 +30,8 @@ filter the results to the desired subset.
## Examples
-List all SQL routines and plugin functions in the `default` schema of the
-`example` catalog:
+List all UDFs and plugin functions in the `default` schema of the `example`
+catalog:
```sql
SHOW FUNCTIONS FROM example.default;
@@ -62,7 +62,7 @@ Example output:
## See also
* [](/functions)
-* [](/routines)
+* [](/udf)
* [](/develop/functions)
* [](/sql/create-function)
* [](/sql/drop-function)
diff --git a/docs/src/main/sphinx/udf.md b/docs/src/main/sphinx/udf.md
new file mode 100644
index 000000000000..4e8c54a61420
--- /dev/null
+++ b/docs/src/main/sphinx/udf.md
@@ -0,0 +1,17 @@
+# User-defined functions
+
+A user-defined function (UDF) is a custom function authored by a user of Trino
+in a client application. UDFs are scalar functions that return a single output
+value, similar to [built-in functions](/functions).
+
+More details are available in the following sections:
+
+```{toctree}
+:titlesonly: true
+:maxdepth: 1
+
+udf/introduction
+udf/function
+udf/sql
+udf/python
+```
diff --git a/docs/src/main/sphinx/udf/function.md b/docs/src/main/sphinx/udf/function.md
new file mode 100644
index 000000000000..f5564ab574af
--- /dev/null
+++ b/docs/src/main/sphinx/udf/function.md
@@ -0,0 +1,113 @@
+# FUNCTION
+
+## Synopsis
+
+```text
+FUNCTION name ( [ parameter_name data_type [, ...] ] )
+ RETURNS type
+ [ LANGUAGE language]
+ [ NOT? DETERMINISTIC ]
+ [ RETURNS NULL ON NULL INPUT ]
+ [ CALLED ON NULL INPUT ]
+ [ SECURITY { DEFINER | INVOKER } ]
+ [ COMMENT description]
+ [ WITH ( property_name = expression [, ...] ) ]
+ { statements | AS definition }
+```
+
+## Description
+
+Declare a [user-defined function](/udf).
+
+The `name` of the UDF. [](udf-inline) can use a simple string. [](udf-catalog)
+must qualify the name of the catalog and schema, delimited by `.`, to store the
+UDF or rely on the [default catalog and schema for UDF
+storage](/admin/properties-sql-environment).
+
+The list of parameters is a comma-separated list of names `parameter_name` and
+data types `data_type`, see [data type](/language/types). An empty list, specified as
+`()` is also valid.
+
+The `type` value after the `RETURNS` keyword identifies the [data
+type](/language/types) of the UDF output.
+
+The optional `LANGUAGE` characteristic identifies the language used for the UDF
+definition with `language`. The `SQL` and `PYTHON` languages are supported by
+default. Additional languages may be supported via a language engine plugin.
+If not specified, the default language is `SQL`.
+
+The optional `DETERMINISTIC` or `NOT DETERMINISTIC` characteristic declares that
+the UDF is deterministic. This means that repeated UDF calls with identical
+input parameters yield the same result. A UDF is non-deterministic if it calls
+any non-deterministic UDFs and [functions](/functions). By default, UDFs are
+assumed to have a deterministic behavior.
+
+The optional `RETURNS NULL ON NULL INPUT` characteristic declares that the UDF
+returns a `NULL` value when any of the input parameters are `NULL`. The UDF is
+not invoked with a `NULL` input value.
+
+The `CALLED ON NULL INPUT` characteristic declares that the UDF is invoked with
+`NULL` input parameter values.
+
+The `RETURNS NULL ON NULL INPUT` and `CALLED ON NULL INPUT` characteristics are
+mutually exclusive, with `CALLED ON NULL INPUT` as the default.
+
+The security declaration of `SECURITY INVOKER` or `SECURITY DEFINER` is only
+valid for catalog UDFs. It sets the mode for processing the UDF with the
+permissions of the user who calls the UDF (`INVOKER`) or the user who created
+the UDF (`DEFINER`).
+
+The `COMMENT` characteristic can be used to provide information about the
+function to other users as `description`. The information is accessible with
+[](/sql/show-functions).
+
+The optional `WITH` clause can be used to specify properties for the function.
+The available properties vary based on the function language. For
+[](/udf/python), the `handler` property specifies the name of the Python
+function to invoke.
+
+For SQL UDFs the body of the UDF can either be a simple single `RETURN`
+statement with an expression, or compound list of `statements` in a `BEGIN`
+block. UDF must contain a `RETURN` statement at the end of the top-level block,
+even if it's unreachable.
+
+For UDFs in other languages, the `definition` is enclosed in a `$$`-quoted
+string.
+
+## Examples
+
+A simple catalog function:
+
+```sql
+CREATE FUNCTION example.default.meaning_of_life()
+ RETURNS BIGINT
+ RETURN 42;
+```
+
+And used:
+
+```sql
+SELECT example.default.meaning_of_life(); -- returns 42
+```
+
+Equivalent usage with an inline function:
+
+```sql
+WITH FUNCTION meaning_of_life()
+ RETURNS BIGINT
+ RETURN 42
+SELECT meaning_of_life();
+```
+
+Further examples of varying complexity that cover usage of the `FUNCTION`
+statement in combination with other statements are available in the [SQL UDF
+documentation](/udf/sql/examples) and the [Python UDF
+documentation](/udf/python).
+
+## See also
+
+* [](/udf)
+* [](/udf/sql)
+* [](/udf/python)
+* [](/sql/create-function)
+
diff --git a/docs/src/main/sphinx/udf/introduction.md b/docs/src/main/sphinx/udf/introduction.md
new file mode 100644
index 000000000000..da479dc491f1
--- /dev/null
+++ b/docs/src/main/sphinx/udf/introduction.md
@@ -0,0 +1,127 @@
+# Introduction to UDFs
+
+A user-defined function (UDF) is a custom function authored by a user of Trino
+in a client application. UDFs are scalar functions that return a single output
+value, similar to [built-in functions](/functions).
+
+:::{note}
+Custom functions can alternatively be written in Java and deployed as a
+plugin. Details are available in the [developer guide](/develop/functions).
+:::
+
+(udf-declaration)=
+## UDF declaration
+
+Declare the UDF with the SQL [](/udf/function) keyword and the supported
+statements for [](/udf/sql) or [](/udf/python).
+
+A UDF can be declared as an [inline UDF](udf-inline) to be used in the current
+query, or declared as a [catalog UDF](udf-catalog) to be used in any future
+query.
+
+(udf-inline)=
+## Inline user-defined functions
+
+An inline user-defined function (inline UDF) declares and uses the UDF within a
+query processing context. The UDF is declared in a `WITH` block before the
+query:
+
+```sql
+WITH
+ FUNCTION doubleup(x integer)
+ RETURNS integer
+ RETURN x * 2
+SELECT doubleup(21);
+-- 42
+```
+
+Inline UDF names must follow SQL identifier naming conventions, and cannot
+contain `.` characters.
+
+The UDF declaration is only valid within the context of the query. A separate
+later invocation of the UDF is not possible. If this is desired, use a [catalog
+UDF](udf-catalog).
+
+Multiple inline UDF declarations are comma-separated, and can include UDFs
+calling each other, as long as a called UDF is declared before the first
+invocation.
+
+```sql
+WITH
+ FUNCTION doubleup(x integer)
+ RETURNS integer
+ RETURN x * 2,
+ FUNCTION doubleupplusone(x integer)
+ RETURNS integer
+ RETURN doubleup(x) + 1
+SELECT doubleupplusone(21);
+-- 43
+```
+
+Note that inline UDFs can mask and override the meaning of a built-in function:
+
+```sql
+WITH
+ FUNCTION abs(x integer)
+ RETURNS integer
+ RETURN x * 2
+SELECT abs(-10); -- -20, not 10!
+```
+
+(udf-catalog)=
+## Catalog user-defined functions
+
+You can store a UDF in the context of a catalog, if the connector used in the
+catalog supports UDF storage. The following connectors support catalog UDF
+storage:
+
+* [](/connector/hive)
+* [](/connector/memory)
+
+In this scenario, the following commands can be used:
+
+* [](/sql/create-function) to create and store a UDF.
+* [](/sql/drop-function) to remove a UDF.
+* [](/sql/show-functions) to display a list of UDFs in a catalog.
+
+Catalog UDFs must use a name that combines the catalog name and schema name with
+the UDF name, such as `example.default.power` for the `power` UDF in the
+`default` schema of the `example` catalog.
+
+Invocation must use the fully qualified name, such as `example.default.power`.
+
+(udf-sql-environment)=
+## SQL environment configuration for UDFs
+
+Configuration of the `sql.default-function-catalog` and
+`sql.default-function-schema` [](/admin/properties-sql-environment) allows you
+to set the default storage for UDFs. The catalog and schema must be added to the
+`sql.path` as well. This enables users to call UDFs and perform all
+[](udf-management) without specifying the full path to the UDF.
+
+:::{note}
+Use the [](/connector/memory) in a catalog for simple storing and
+testing of your UDFs.
+:::
+
+## Recommendations
+
+Processing UDFs can potentially be resource intensive on the cluster in
+terms of memory and processing. Take the following considerations into account
+when writing and running UDFs:
+
+* Some checks for the runtime behavior of queries, and therefore UDF processing,
+ are in place. For example, if a query takes longer to process than a hardcoded
+ threshold, processing is automatically terminated.
+* Avoid creation of arrays in a looping construct. Each iteration creates a
+ separate new array with all items and copies the data for each modification,
+ leaving the prior array in memory for automated clean up later. Use a [lambda
+ expression](/functions/lambda) instead of the loop.
+* Avoid concatenating strings in a looping construct. Each iteration creates a
+ separate new string and copying the old string for each modification, leaving
+ the prior string in memory for automated clean up later. Use a [lambda
+ expression](/functions/lambda) instead of the loop.
+* Most UDFs should declare the `RETURNS NULL ON NULL INPUT` characteristics
+ unless the code has some special handling for null values. You must declare
+ this explicitly since `CALLED ON NULL INPUT` is the default characteristic.
+
diff --git a/docs/src/main/sphinx/udf/python.md b/docs/src/main/sphinx/udf/python.md
new file mode 100644
index 000000000000..56900550c137
--- /dev/null
+++ b/docs/src/main/sphinx/udf/python.md
@@ -0,0 +1,182 @@
+# Python user-defined functions
+
+A Python user-defined function is a [user-defined function](/udf) that uses the
+[Python programming language and statements](python-udf-lang) for the definition
+of the function.
+
+:::{warning}
+Python user-defined functions are an experimental feature.
+:::
+
+## Python UDF declaration
+
+Declare a Python UDF as [inline](udf-inline) or [catalog UDF](udf-catalog) with
+the following steps:
+
+* Use the [](/udf/function) keyword to declare the UDF name and parameters.
+* Add the `RETURNS` declaration to specify the data type of the result.
+* Set the `LANGUAGE` to `PYTHON`.
+* Declare the name of the Python function to call with the `handler` property in
+ the `WITH` block.
+* Use `$$` to enclose the Python code after the `AS` keyword.
+* Add the function from the handler property and ensure it returns the declared
+ data type.
+* Expand your Python code section to implement the function using the available
+ [Python language](python-udf-lang).
+
+The following snippet shows pseudo-code:
+
+```text
+FUNCTION python_udf_name(input_parameter data_type)
+ RETURNS result_data_type
+ LANGUAGE PYTHON
+ WITH (handler = 'python_function')
+ AS $$
+ ...
+ def python_function(input):
+ return ...
+ ...
+ $$
+```
+
+A minimal example declares the UDF `doubleup` that returns the input integer
+value `x` multiplied by two. The example shows declaration as [](udf-inline) and
+invocation with the value `21` to yield the result `42`.
+
+Set the language to `PYTHON` to override the default `SQL` for [](/udf/sql).
+The Python code is enclosed with ``$$` and must use valid formatting.
+
+```text
+WITH
+ FUNCTION doubleup(x integer)
+ RETURNS integer
+ LANGUAGE PYTHON
+ WITH (handler = 'twice')
+ AS $$
+ def twice(a):
+ return a * 2
+ $$
+SELECT doubleup(21);
+-- 42
+```
+
+The same UDF can also be declared as [](udf-catalog).
+
+Refer to the [](/udf/python/examples) for more complex use cases and examples.
+
+```{toctree}
+:titlesonly: true
+:hidden:
+
+/udf/python/examples
+```
+
+(python-udf-lang)=
+## Python language details
+
+The Trino Python UDF integrations uses Python 3.13.0 in a sandboxed environment.
+Python code runs within a WebAssembly (WASM) runtime within the Java virtual
+machine running Trino.
+
+Python language rules including indents must be observed.
+
+Python UDFs therefore only have access to the Python language and core libraries
+included in the sandboxed runtime. Access to external resources with network or
+file system operations is not supported. Usage of other Python libraries as well
+as command line tools or package managers is not supported.
+
+The following libraries are explicitly removed from the runtime and therefore
+not available within a Python UDF:
+
+* `bdb`
+* `concurrent`
+* `curses`
+* `ensurepip`
+* `doctest`
+* `idlelib`
+* `multiprocessing`
+* `pdb`
+* `pydoc`
+* `socketserver`
+* `sqlite3`
+* `ssl`
+* `subprocess`
+* `tkinter`
+* `turtle`
+* `unittest`
+* `venv`
+* `webbrowser`
+* `wsgiref`
+* `xmlrpc`
+
+## Type mapping
+
+The following table shows supported Trino types and their corresponding Python
+types for input and output values of a Python UDF:
+
+:::{list-table}
+:widths: 40, 60
+:header-rows: 1
+
+* - Trino type
+ - Python type
+* - `ROW`
+ - `tuple`
+* - `ARRAY`
+ - `list`
+* - `MAP`
+ - `dict`
+* - `BOOLEAN`
+ - `bool`
+* - `TINYINT`
+ - `int`
+* - `SMALLINT`
+ - `int`
+* - `INTEGER`
+ - `int`
+* - `BIGINT`
+ - `int`
+* - `REAL`
+ - `float`
+* - `DOUBLE`
+ - `float`
+* - `DECIMAL`
+ - `decimal.Decimal`
+* - `VARCHAR`
+ - `str`
+* - `VARBINARY`
+ - `bytes`
+* - `DATE`
+ - `datetime.date`
+* - `TIME`
+ - `datetime.time`
+* - `TIME WITH TIME ZONE`
+ - `datetime.time` with `datetime.tzinfo`
+* - `TIMESTAMP`
+ - `datetime.datetime`
+* - `TIMESTAMP WITH TIME ZONE`
+ - `datetime.datetime` with `datetime.tzinfo`
+* - `INTERVAL YEAR TO MONTH`
+ - `int` as the number of months
+* - `INTERVAL DAY TO SECOND`
+ - `datetime.timedelta`
+* - `JSON`
+ - `str`
+* - `UUID`
+ - `uuid.UUID`
+* - `IPADDRESS`
+ - `ipaddress.IPv4Address` or `ipaddress.IPv6Address`
+
+:::
+
+### Time and timestamp
+
+Python `datetime` and `time` objects only support microsecond precision.
+Trino argument values with greater precision are rounded when converted to
+Python values, and Python return values are rounded if the Trino return type
+has less than microsecond precision.
+
+### Timestamp with time zone
+
+Only fixed offset time zones are supported. Timestamps with political time zones
+have the zone converted to the zone's offset for the timestamp's instant.
diff --git a/docs/src/main/sphinx/udf/python/examples.md b/docs/src/main/sphinx/udf/python/examples.md
new file mode 100644
index 000000000000..19b28729b86c
--- /dev/null
+++ b/docs/src/main/sphinx/udf/python/examples.md
@@ -0,0 +1,157 @@
+# Example Python UDFs
+
+After learning about [](/udf/python), the following sections show examples
+of valid Python UDFs.
+
+The UDFs are suitable as [](udf-inline) or [](udf-catalog),
+after adjusting the name and the example invocations.
+
+## Inline and catalog Python UDFs
+
+The following section shows the differences in usage with inline and catalog
+UDFs with a simple Python UDF example. The same pattern applies to all other
+following sections.
+
+A very simple Python UDF that returns the static int value `42` without
+requiring any input:
+
+```text
+FUNCTION answer()
+LANGUAGE PYTHON
+RETURNS int
+WITH (handler='theanswer')
+AS $$
+def theanswer():
+ return 42
+$$
+```
+
+A full example of this UDF as inline UDF and usage in a string concatenation
+with a cast:
+
+```text
+WITH
+ FUNCTION answer()
+ RETURNS int
+ LANGUAGE PYTHON
+ WITH (handler='theanswer')
+ AS $$
+ def theanswer():
+ return 42
+ $$
+SELECT 'The answer is ' || CAST(answer() as varchar);
+-- The answer is 42
+```
+
+Provided the catalog `example` supports UDF storage in the `default` schema, you
+can use the following:
+
+```text
+CREATE FUNCTION example.default.answer()
+ RETURNS int
+ LANGUAGE PYTHON
+ WITH (handler='theanswer')
+ AS $$
+ def theanswer():
+ return 42
+ $$;
+```
+
+With the UDF stored in the catalog, you can run the UDF multiple times without
+repeated definition:
+
+```sql
+SELECT example.default.answer() + 1; -- 43
+SELECT 'The answer is ' || CAST(example.default.answer() as varchar); -- The answer is 42
+```
+
+Alternatively, you can configure the SQL PATH in the [](config-properties) to a
+catalog and schema that support UDF storage:
+
+```properties
+sql.default-function-catalog=example
+sql.default-function-schema=default
+sql.path=example.default
+```
+
+Now you can manage UDFs without the full path:
+
+```text
+CREATE FUNCTION answer()
+ RETURNS int
+ LANGUAGE PYTHON
+ WITH (handler='theanswer')
+ AS $$
+ def theanswer():
+ return 42
+ $$;
+```
+
+UDF invocation works without the full path:
+
+```sql
+SELECT answer() + 5; -- 47
+```
+
+## XOR
+
+The following example implements a `xor` function for a logical Exclusive OR
+operation on two boolean input parameters and tests it with two invocations:
+
+```text
+WITH FUNCTION xor(a boolean, b boolean)
+RETURNS boolean
+LANGUAGE PYTHON
+WITH (handler = 'bool_xor')
+AS $$
+import operator
+def bool_xor(a, b):
+ return operator.xor(a, b)
+$$
+SELECT xor(true, false), xor(false, true);
+```
+
+Result of the query:
+
+```
+ true | true
+```
+
+## reverse_words
+
+The following example uses a more elaborate Python script to reverse the
+characters in each word of the input string `s` of type `varchar` and tests the
+function.
+
+```text
+WITH FUNCTION reverse_words(s varchar)
+RETURNS varchar
+LANGUAGE PYTHON
+WITH (handler = 'reverse_words')
+AS $$
+import re
+
+def reverse(s):
+ str = ""
+ for i in s:
+ str = i + str
+ return str
+
+pattern = re.compile(r"\w+[.,'!?\"]\w*")
+
+def process_word(word):
+ # Reverse only words without non-letter signs
+ return word if pattern.match(word) else reverse(word)
+
+def reverse_words(payload):
+ text_words = payload.split(' ')
+ return ' '.join([process_word(w) for w in text_words])
+$$
+SELECT reverse_words('Civic, level, dna racecar era semordnilap');
+```
+
+Result of the query:
+
+```
+Civic, level, and racecar are palindromes
+```
\ No newline at end of file
diff --git a/docs/src/main/sphinx/udf/sql.md b/docs/src/main/sphinx/udf/sql.md
new file mode 100644
index 000000000000..df70207075b4
--- /dev/null
+++ b/docs/src/main/sphinx/udf/sql.md
@@ -0,0 +1,107 @@
+# SQL user-defined functions
+
+A SQL user-defined function, also known as SQL routine, is a [user-defined
+function](/udf) that uses the SQL routine language and statements for the
+definition of the function.
+
+## SQL UDF declaration
+
+Declare a SQL UDF using the [](/udf/function) keyword and the following
+statements can be used in addition to [built-in functions and
+operators](/functions) and other UDFs:
+
+* [](/udf/sql/begin)
+* [](/udf/sql/case)
+* [](/udf/sql/declare)
+* [](/udf/sql/if)
+* [](/udf/sql/iterate)
+* [](/udf/sql/leave)
+* [](/udf/sql/loop)
+* [](/udf/sql/repeat)
+* [](/udf/sql/return)
+* [](/udf/sql/set)
+* [](/udf/sql/while)
+
+```{toctree}
+:titlesonly: true
+:hidden:
+
+sql/examples
+sql/begin
+sql/case
+sql/declare
+sql/if
+sql/iterate
+sql/leave
+sql/loop
+sql/repeat
+sql/return
+sql/set
+sql/while
+```
+
+A minimal example declares the UDF `doubleup` that returns the input integer
+value `x` multiplied by two. The example shows declaration as [](udf-inline) and
+invocation with the value 21 to yield the result 42:
+
+```sql
+WITH
+ FUNCTION doubleup(x integer)
+ RETURNS integer
+ RETURN x * 2
+SELECT doubleup(21);
+-- 42
+```
+
+The same UDF can also be declared as [](udf-catalog).
+
+Find simple examples in each statement documentation, and refer to the
+[](/udf/sql/examples) for more complex use cases that combine multiple
+statements.
+
+(udf-sql-label)=
+## Labels
+
+SQL UDFs can contain labels as markers for a specific block in the declaration
+before the following keywords:
+
+* `CASE`
+* `IF`
+* `LOOP`
+* `REPEAT`
+* `WHILE`
+
+The label is used to name the block to continue processing with the `ITERATE`
+statement or exit the block with the `LEAVE` statement. This flow control is
+supported for nested blocks, allowing to continue or exit an outer block, not
+just the innermost block. For example, the following snippet uses the label
+`top` to name the complete block from `REPEAT` to `END REPEAT`:
+
+```sql
+top: REPEAT
+ SET a = a + 1;
+ IF a <= 3 THEN
+ ITERATE top;
+ END IF;
+ SET b = b + 1;
+ UNTIL a >= 10
+END REPEAT;
+```
+
+Labels can be used with the `ITERATE` and `LEAVE` statements to continue
+processing the block or leave the block. This flow control is also supported for
+nested blocks and labels.
+
+## Limitations
+
+The following limitations apply to SQL UDFs.
+
+* UDFs must be declared before they are referenced.
+* Recursion cannot be declared or processed.
+* Mutual recursion can not be declared or processed.
+* Queries cannot be processed in a UDF.
+
+Specifically this means that UDFs can not use `SELECT` queries to retrieve
+data or any other queries to process data within the UDF. Instead queries can
+use UDFs to process data. UDFs only work on data provided as input values and
+only provide output data from the `RETURN` statement.
\ No newline at end of file
diff --git a/docs/src/main/sphinx/udf/sql/begin.md b/docs/src/main/sphinx/udf/sql/begin.md
new file mode 100644
index 000000000000..7e850383193e
--- /dev/null
+++ b/docs/src/main/sphinx/udf/sql/begin.md
@@ -0,0 +1,56 @@
+# BEGIN
+
+## Synopsis
+
+```text
+BEGIN
+ [ DECLARE ... ]
+ statements
+END
+```
+
+## Description
+
+Marks the start and end of a block in a [](/udf/sql). `BEGIN` can be used
+wherever a statement can be used to group multiple statements together and to
+declare variables local to the block. A typical use case is as first statement
+within a [](/udf/function). Blocks can also be nested.
+
+After the `BEGIN` keyword, you can add variable declarations using
+[](/udf/sql/declare) statements, followed by one or more statements that define
+the main body of the SQL UDF, separated by `;`. The following statements can be
+used:
+
+* [](/udf/sql/case)
+* [](/udf/sql/if)
+* [](/udf/sql/iterate)
+* [](/udf/sql/leave)
+* [](/udf/sql/loop)
+* [](/udf/sql/repeat)
+* [](/udf/sql/return)
+* [](/udf/sql/set)
+* [](/udf/sql/while)
+* Nested [](/udf/sql/begin) blocks
+
+## Examples
+
+The following example computes the value `42`:
+
+```sql
+FUNCTION meaning_of_life()
+ RETURNS tinyint
+ BEGIN
+ DECLARE a tinyint DEFAULT 6;
+ DECLARE b tinyint DEFAULT 7;
+ RETURN a * b;
+ END
+```
+
+Further examples of varying complexity that cover usage of the `BEGIN` statement
+in combination with other statements are available in the [](/udf/sql/examples).
+
+## See also
+
+* [](/udf)
+* [](/udf/sql)
+* [](/udf/function)
diff --git a/docs/src/main/sphinx/routines/case.md b/docs/src/main/sphinx/udf/sql/case.md
similarity index 86%
rename from docs/src/main/sphinx/routines/case.md
rename to docs/src/main/sphinx/udf/sql/case.md
index f7264d08b096..146699360299 100644
--- a/docs/src/main/sphinx/routines/case.md
+++ b/docs/src/main/sphinx/udf/sql/case.md
@@ -25,7 +25,7 @@ END
## Description
The `CASE` statement is an optional construct to allow conditional processing
-in [SQL routines](/routines/introduction).
+in [](/udf/sql).
The `WHEN` clauses are evaluated sequentially, stopping after the first match,
and therefore the order of the statements is significant. The statements of the
@@ -54,10 +54,9 @@ FUNCTION simple_case(a bigint)
```
Further examples of varying complexity that cover usage of the `CASE` statement
-in combination with other statements are available in the [SQL routines examples
-documentation](/routines/examples).
+in combination with other statements are available in the [](/udf/sql/examples).
## See also
-* [](/routines/introduction)
+* [](/udf/sql)
* [Conditional expressions using `CASE`](case-expression)
diff --git a/docs/src/main/sphinx/routines/declare.md b/docs/src/main/sphinx/udf/sql/declare.md
similarity index 80%
rename from docs/src/main/sphinx/routines/declare.md
rename to docs/src/main/sphinx/udf/sql/declare.md
index 2238ca2de0c0..518b6b4552dd 100644
--- a/docs/src/main/sphinx/routines/declare.md
+++ b/docs/src/main/sphinx/udf/sql/declare.md
@@ -8,8 +8,8 @@ DECLARE identifier [, ...] type [ DEFAULT expression ]
## Description
-Use the `DECLARE` statement directly after the [](/routines/begin) keyword in
-[](/routines) to define one or more variables with an `identifier` as name. Each
+Use the `DECLARE` statement directly after the [](/udf/sql/begin) keyword in
+[](/udf/sql) to define one or more variables with an `identifier` as name. Each
statement must specify the [data type](/language/types) of the variable with
`type`. It can optionally include a default, initial value defined by an
`expression`. The default value is `NULL` if not specified.
@@ -43,10 +43,10 @@ DECLARE start_time timestamp(3) with time zone DEFAULT now();
```
Further examples of varying complexity that cover usage of the `DECLARE`
-statement in combination with other statements are available in the [SQL
-routines examples documentation](/routines/examples).
+statement in combination with other statements are available in the
+[](/udf/sql/examples).
## See also
-* [](/routines/introduction)
+* [](/udf/sql)
* [](/language/types)
diff --git a/docs/src/main/sphinx/routines/examples.md b/docs/src/main/sphinx/udf/sql/examples.md
similarity index 85%
rename from docs/src/main/sphinx/routines/examples.md
rename to docs/src/main/sphinx/udf/sql/examples.md
index 40667856e53f..2ffd63a45fab 100644
--- a/docs/src/main/sphinx/routines/examples.md
+++ b/docs/src/main/sphinx/udf/sql/examples.md
@@ -1,24 +1,27 @@
-# Example SQL routines
+# Example SQL UDFs
-
-After learning about [SQL routines from the
-introduction](/routines/introduction), the following sections show numerous
-examples of valid SQL routines. The routines are suitable as [inline
-routines](routine-inline) or [catalog routines](routine-catalog), after
-adjusting the name and the example invocations.
+After learning about [](/udf/sql), the following sections show numerous examples
+of valid SQL UDFs. The UDFs are suitable as [](udf-inline) or [](udf-catalog),
+after adjusting the name and the example invocations.
The examples combine numerous supported statements. Refer to the specific
statement documentation for further details:
-* [](/routines/function) for general SQL routine declaration
-* [](/routines/begin) and [](/routines/declare) for routine blocks
-* [](/routines/set) for assigning values to variables
-* [](/routines/return) for returning routine results
-* [](/routines/case) and [](/routines/if) for conditional flows
-* [](/routines/loop), [](/routines/repeat), and [](/routines/while) for looping constructs
-* [](/routines/iterate) and [](/routines/leave) for flow control
+* [](/udf/function) for general UDF declaration
+* [](/udf/sql/begin) and [](/udf/sql/declare) for SQL UDF blocks
+* [](/udf/sql/set) for assigning values to variables
+* [](/udf/sql/return) for returning results
+* [](/udf/sql/case) and [](/udf/sql/if) for conditional flows
+* [](/udf/sql/loop), [](/udf/sql/repeat), and [](/udf/sql/while) for looping constructs
+* [](/udf/sql/iterate) and [](/udf/sql/leave) for flow control
+
+## Inline and catalog UDFs
-A very simple routine that returns a static value without requiring any input:
+The following section shows the differences in usage with inline and catalog
+UDFs with a simple SQL UDF example. The same pattern applies to all other
+following sections.
+
+A very simple SQL UDF that returns a static value without requiring any input:
```sql
FUNCTION answer()
@@ -26,10 +29,8 @@ RETURNS BIGINT
RETURN 42
```
-## Inline and catalog routines
-
-A full example of this routine as inline routine and usage in a string
-concatenation with a cast:
+A full example of this UDF as inline UDF and usage in a string concatenation
+with a cast:
```sql
WITH
@@ -40,33 +41,33 @@ SELECT 'The answer is ' || CAST(answer() as varchar);
-- The answer is 42
```
-Provided the catalog `example` supports routine storage in the `default` schema,
-you can use the following:
+Provided the catalog `example` supports UDF storage in the `default` schema, you
+can use the following:
```sql
-USE example.default;
CREATE FUNCTION example.default.answer()
RETURNS BIGINT
RETURN 42;
```
-With the routine stored in the catalog, you can run the routine multiple times
-without repeated definition:
+With the UDF stored in the catalog, you can run the UDF multiple times without
+repeated definition:
```sql
SELECT example.default.answer() + 1; -- 43
-SELECT 'The answer is' || CAST(example.default.answer() as varchar); -- The answer is 42
+SELECT 'The answer is ' || CAST(example.default.answer() as varchar); -- The answer is 42
```
-Alternatively, you can configure the SQL environment in the
-[](config-properties) to a catalog and schema that support SQL routine storage:
+Alternatively, you can configure the SQL PATH in the [](config-properties) to a
+catalog and schema that support UDF storage:
```properties
sql.default-function-catalog=example
sql.default-function-schema=default
+sql.path=example.default
```
-Now you can manage SQL routines without the full path:
+Now you can manage UDFs without the full path:
```sql
CREATE FUNCTION answer()
@@ -74,7 +75,7 @@ CREATE FUNCTION answer()
RETURN 42;
```
-SQL routine invocation works without the full path:
+UDF invocation works without the full path:
```sql
SELECT answer() + 5; -- 47
@@ -82,7 +83,7 @@ SELECT answer() + 5; -- 47
## Declaration examples
-The result of calling the routine `answer()` is always identical, so you can
+The result of calling the UDF `answer()` is always identical, so you can
declare it as deterministic, and add some other information:
```sql
@@ -94,10 +95,10 @@ COMMENT 'Provide the answer to the question about life, the universe, and everyt
RETURN 42
```
-The comment and other information about the routine is visible in the output of
+The comment and other information about the UDF is visible in the output of
[](/sql/show-functions).
-A simple routine that returns a greeting back to the input string `fullname`
+A simple UDF that returns a greeting back to the input string `fullname`
concatenating two strings and the input value:
```sql
@@ -112,7 +113,7 @@ Following is an example invocation:
SELECT hello('Jane Doe'); -- Hello, Jane Doe!
```
-A first example routine, that uses multiple statements in a `BEGIN` block. It
+A first example UDF, that uses multiple statements in a `BEGIN` block. It
calculates the result of a multiplication of the input integer with `99`. The
`bigint` data type is used for all variables and values. The value of integer
`99` is cast to `bigint` in the default value assignment for the variable `x`:
@@ -134,7 +135,7 @@ SELECT times_ninety_nine(CAST(2 as bigint)); -- 198
## Conditional flows
-A first example of conditional flow control in a routine using the `CASE`
+A first example of conditional flow control in a SQL UDF using the `CASE`
statement. The simple `bigint` input value is compared to a number of values:
```sql
@@ -165,7 +166,7 @@ SELECT simple_case(100); -- other (from else clause)
SELECT simple_case(null); -- null .. but really??
```
-A second example of a routine with a `CASE` statement, this time with two
+A second example of a SQL UDF with a `CASE` statement, this time with two
parameters, showcasing the importance of the order of the conditions:
```sql
@@ -200,15 +201,15 @@ SELECT simple_case(null,null); -- null .. but really??
## Fibonacci example
-This routine calculates the `n`-th value in the Fibonacci series, in which each
-number is the sum of the two preceding ones. The two initial values are set
-to `1` as the defaults for `a` and `b`. The routine uses an `IF` statement
-condition to return `1` for all input values of `2` or less. The `WHILE` block
-then starts to calculate each number in the series, starting with `a=1` and
-`b=1` and iterates until it reaches the `n`-th position. In each iteration is
-sets `a` and `b` for the preceding to values, so it can calculate the sum, and
-finally return it. Note that processing the routine takes longer and longer with
-higher `n` values, and the result is deterministic:
+This SQL UDF calculates the `n`-th value in the Fibonacci series, in which each
+number is the sum of the two preceding ones. The two initial values are set to
+`1` as the defaults for `a` and `b`. The UDF uses an `IF` statement condition to
+return `1` for all input values of `2` or less. The `WHILE` block then starts to
+calculate each number in the series, starting with `a=1` and `b=1` and iterates
+until it reaches the `n`-th position. In each iteration it sets `a` and `b` for
+the preceding to values, so it can calculate the sum, and finally return it.
+Note that processing the UDF takes longer and longer with higher `n` values, and
+the result is deterministic:
```sql
FUNCTION fib(n bigint)
@@ -246,13 +247,13 @@ SELECT fib(8); -- 21
## Labels and loops
-This routine uses the `top` label to name the `WHILE` block, and then controls
+This SQL UDF uses the `top` label to name the `WHILE` block, and then controls
the flow with conditional statements, `ITERATE`, and `LEAVE`. For the values of
`a=1` and `a=2` in the first two iterations of the loop the `ITERATE` call moves
the flow up to `top` before `b` is ever increased. Then `b` is increased for the
values `a=3`, `a=4`, `a=5`, `a=6`, and `a=7`, resulting in `b=5`. The `LEAVE`
call then causes the exit of the block before a is increased further to `10` and
-therefore the result of the routine is `5`:
+therefore the result of the UDF is `5`:
```sql
FUNCTION labels()
@@ -273,9 +274,9 @@ BEGIN
END
```
-This routine implements calculating the `n` to the power of `p` by repeated
+This SQL UDF implements calculating the `n` to the power of `p` by repeated
multiplication and keeping track of the number of multiplications performed.
-Note that this routine does not return the correct `0` for `p=0` since the `top`
+Note that this SQL UDF does not return the correct `0` for `p=0` since the `top`
block is merely escaped and the value of `n` is returned. The same incorrect
behavior happens for negative values of `p`:
@@ -305,7 +306,7 @@ SELECT power(3, 0); -- 3, which is wrong
SELECT power(3, -2); -- 3, which is wrong
```
-This routine returns `7` as a result of the increase of `b` in the loop from
+This SQL UDF returns `7` as a result of the increase of `b` in the loop from
`a=3` to `a=10`:
```sql
@@ -326,7 +327,7 @@ BEGIN
END
```
-This routine returns `2` and shows that labels can be repeated and label usage
+This SQL UDF returns `2` and shows that labels can be repeated and label usage
within a block refers to the label of that block:
```sql
@@ -346,10 +347,10 @@ BEGIN
END
```
-## Routines and built-in functions
+## SQL UDFs and built-in functions
-This routine show that multiple data types and built-in functions like
-`length()` and `cardinality()` can be used in a routine. The two nested `BEGIN`
+This SQL UDF shows that multiple data types and built-in functions like
+`length()` and `cardinality()` can be used in a UDF. The two nested `BEGIN`
blocks also show how variable names are local within these blocks `x`, but the
global `r` from the top-level block can be accessed in the nested blocks:
@@ -372,13 +373,13 @@ END
## Optional parameter example
-Routines can invoke other routines and other functions. The full signature of a
-routine is composed of the routine name and parameters, and determines the exact
-routine to use. You can declare multiple routines with the same name, but with a
-different number of arguments or different argument types. One example use case
-is to implement an optional parameter.
+UDFs can invoke other UDFs and other functions. The full signature of a UDF is
+composed of the UDF name and parameters, and determines the exact UDF to use.
+You can declare multiple UDFs with the same name, but with a different number of
+arguments or different argument types. One example use case is to implement an
+optional parameter.
-The following routine truncates a string to the specified length including three
+The following SQL UDF truncates a string to the specified length including three
dots at the end of the output:
```sql
@@ -401,8 +402,8 @@ SELECT dots('A short string',15);
-- A short string
```
-If you want to provide a routine with the same name, but without the parameter
-for length, you can create another routine that invokes the preceding routine:
+If you want to provide a UDF with the same name, but without the parameter
+for length, you can create another UDF that invokes the preceding UDF:
```sql
FUNCTION dots(input varchar)
@@ -410,7 +411,7 @@ RETURNS varchar
RETURN dots(input, 15);
```
-You can now use both routines. When the length parameter is omitted, the default
+You can now use both UDFs. When the length parameter is omitted, the default
value from the second declaration is used.
```sql
@@ -424,18 +425,18 @@ SELECT dots('A long string that will be shortened',20);
## Date string parsing example
-This example routine parses a date string of type `VARCHAR` into `TIMESTAMP WITH
+This example SQL UDF parses a date string of type `VARCHAR` into `TIMESTAMP WITH
TIME ZONE`. Date strings are commonly represented by ISO 8601 standard, such as
`2023-12-01`, `2023-12-01T23`. Date strings are also often represented in the
`YYYYmmdd` and `YYYYmmddHH` format, such as `20230101` and `2023010123`. Hive
tables can use this format to represent day and hourly partitions, for example
`/day=20230101`, `/hour=2023010123`.
-This routine parses date strings in a best-effort fashion and can be used as a
+This UDF parses date strings in a best-effort fashion and can be used as a
replacement for date string manipulation functions such as `date`, `date_parse`,
`from_iso8601_date`, and `from_iso8601_timestamp`.
-Note that the routine defaults the time value to `00:00:00.000` and the time
+Note that the UDF defaults the time value to `00:00:00.000` and the time
zone to the session time zone:
```sql
@@ -475,7 +476,7 @@ SELECT human_readable_seconds(134823);
-- 1 day, 13 hours, 27 minutes, 3 seconds
```
-The example routine `hrd` formats a number of days into a human readable text
+The example SQL UDF `hrd` formats a number of days into a human readable text
that provides the approximate number of years and months:
```sql
@@ -523,16 +524,16 @@ SELECT hrd(1100); -- About 3 years
SELECT hrd(5000); -- About 13 years and 8 months
```
-Improvements of the routine could include the following modifications:
+Improvements of the SQL UDF could include the following modifications:
* Take into account that one month equals 30.4375 days.
* Take into account that one year equals 365.25 days.
* Add weeks to the output.
-* Expand to cover decades, centuries, and millenia.
+* Expand to cover decades, centuries, and millennia.
## Truncating long strings
-This example routine `strtrunc` truncates strings longer than 60 characters,
+This example SQL UDF `strtrunc` truncates strings longer than 60 characters,
leaving the first 30 and the last 25 characters, and cutting out extra
characters in the middle:
@@ -550,10 +551,10 @@ The preceding declaration is very compact and consists of only one complex
statement with a [`CASE` expression](case-expression) and multiple function
calls. It can therefore define the complete logic in the `RETURN` clause.
-The following statement shows the same capability within the routine itself.
+The following statement shows the same capability within the SQL UDF itself.
Note the duplicate `RETURN` inside and outside the `CASE` statement and the
-required `END CASE;`. The second `RETURN` statement is required, because a
-routine must end with a `RETURN` statement. As a result the `ELSE` clause can be
+required `END CASE;`. The second `RETURN` statement is required, because a SQL
+UDF must end with a `RETURN` statement. As a result the `ELSE` clause can be
omitted:
```sql
@@ -601,8 +602,8 @@ FROM data
ORDER BY data.value;
```
-The preceding query produces the following output with all variants of the
-routine:
+The preceding query produces the following output with all variants of the SQL
+UDF:
```
value | truncated
@@ -623,7 +624,7 @@ A possible improvement is to introduce parameters for the total length.
## Formatting bytes
Trino includes a built-in `format_number()` function. However, it is using units
-that do not work well with bytes. The following `format_data_size` routine can
+that do not work well with bytes. The following `format_data_size` SQL UDF can
format large values of bytes into a human readable string:
```sql
@@ -745,7 +746,7 @@ The preceding query produces the following output:
Trino already has a built-in `bar()` [color function](/functions/color), but it
is using ANSI escape codes to output colors, and thus is only usable for
-displaying results in a terminal. The following example shows a similar routine
+displaying results in a terminal. The following example shows a similar SQL UDF
that only uses ASCII characters:
```sql
@@ -818,7 +819,7 @@ The preceding query produces the following output:
3.1 | 0.0416 | ▋
```
-It is also possible to draw more compacted charts. Following is a routine
+It is also possible to draw more compacted charts. Following is a SQL UDF
drawing vertical bars:
```sql
@@ -898,7 +899,7 @@ Trino already has a built-in [aggregate function](/functions/aggregate) called
values. It returns a map with values as keys and number of occurrences as
values. Maps are not ordered, so when displayed, the entries can change places
on subsequent runs of the same query, and readers must still compare all
-frequencies to find the one most frequent value. The following is a routine that
+frequencies to find the one most frequent value. The following is a SQL UDF that
returns ordered results as a string:
```sql
diff --git a/docs/src/main/sphinx/routines/if.md b/docs/src/main/sphinx/udf/sql/if.md
similarity index 56%
rename from docs/src/main/sphinx/routines/if.md
rename to docs/src/main/sphinx/udf/sql/if.md
index 264beec66b52..626b5a2512a9 100644
--- a/docs/src/main/sphinx/routines/if.md
+++ b/docs/src/main/sphinx/udf/sql/if.md
@@ -14,11 +14,11 @@ END IF
## Description
The `IF THEN` statement is an optional construct to allow conditional processing
-in [SQL routines](/routines/introduction). Each `condition` following an `IF`
-or `ELSEIF` must evaluate to a boolean. The result of processing the expression
-must result in a boolean `true` value to process the `statements` in the `THEN`
-block. A result of `false` results in skipping the `THEN` block and moving to
-evaluate the next `ELSEIF` and `ELSE` blocks in order.
+in [](/udf/sql). Each `condition` following an `IF` or `ELSEIF` must evaluate
+to a boolean. The result of processing the expression must result in a boolean
+`true` value to process the `statements` in the `THEN` block. A result of
+`false` results in skipping the `THEN` block and moving to evaluate the next
+`ELSEIF` and `ELSE` blocks in order.
The `ELSEIF` and `ELSE` segments are optional.
@@ -39,10 +39,9 @@ FUNCTION simple_if(a bigint)
```
Further examples of varying complexity that cover usage of the `IF` statement in
-combination with other statements are available in the [SQL routines examples
-documentation](/routines/examples).
+combination with other statements are available in the [](/udf/sql/examples).
## See also
-* [](/routines/introduction)
+* [](/udf/sql)
* [Conditional expressions using `IF`](if-expression)
diff --git a/docs/src/main/sphinx/routines/iterate.md b/docs/src/main/sphinx/udf/sql/iterate.md
similarity index 54%
rename from docs/src/main/sphinx/routines/iterate.md
rename to docs/src/main/sphinx/udf/sql/iterate.md
index 7be395881459..59b67f2710ca 100644
--- a/docs/src/main/sphinx/routines/iterate.md
+++ b/docs/src/main/sphinx/udf/sql/iterate.md
@@ -8,10 +8,10 @@ ITERATE label
## Description
-The `ITERATE` statement allows processing of blocks in [SQL
-routines](/routines/introduction) to move processing back to the start of a
-context block. Contexts are defined by a [`label`](routine-label). If no label
-is found, the functions fails with an error message.
+The `ITERATE` statement allows processing of blocks in [](/udf/sql) to move
+processing back to the start of a context block. Contexts are defined by a
+[`label`](udf-sql-label). If no label is found, the functions fails with an
+error message.
## Examples
@@ -32,10 +32,10 @@ END
```
Further examples of varying complexity that cover usage of the `ITERATE`
-statement in combination with other statements are available in the [SQL
-routines examples documentation](/routines/examples).
+statement in combination with other statements are available in the
+[](/udf/sql/examples).
## See also
-* [](/routines/introduction)
-* [](/routines/leave)
+* [](/udf/sql)
+* [](/udf/sql/leave)
diff --git a/docs/src/main/sphinx/routines/leave.md b/docs/src/main/sphinx/udf/sql/leave.md
similarity index 62%
rename from docs/src/main/sphinx/routines/leave.md
rename to docs/src/main/sphinx/udf/sql/leave.md
index 196855509921..7697a3fc3fa7 100644
--- a/docs/src/main/sphinx/routines/leave.md
+++ b/docs/src/main/sphinx/udf/sql/leave.md
@@ -8,10 +8,9 @@ LEAVE label
## Description
-The `LEAVE` statement allows processing of blocks in [SQL
-routines](/routines/introduction) to move out of a specified context. Contexts
-are defined by a [`label`](routine-label). If no label is found, the functions
-fails with an error message.
+The `LEAVE` statement allows processing of blocks in [](/udf/sql) to move out of
+a specified context. Contexts are defined by a [`label`](udf-sql-label). If no
+label is found, the functions fails with an error message.
## Examples
@@ -37,10 +36,9 @@ END
```
Further examples of varying complexity that cover usage of the `LEAVE` statement
-in combination with other statements are available in the [SQL routines examples
-documentation](/routines/examples).
+in combination with other statements are available in the [](/udf/sql/examples).
## See also
-* [](/routines/introduction)
-* [](/routines/iterate)
+* [](/udf/sql)
+* [](/udf/sql/iterate)
diff --git a/docs/src/main/sphinx/routines/loop.md b/docs/src/main/sphinx/udf/sql/loop.md
similarity index 80%
rename from docs/src/main/sphinx/routines/loop.md
rename to docs/src/main/sphinx/udf/sql/loop.md
index d38918a456bf..339cea3b50b4 100644
--- a/docs/src/main/sphinx/routines/loop.md
+++ b/docs/src/main/sphinx/udf/sql/loop.md
@@ -10,8 +10,7 @@ END LOOP
## Description
-The `LOOP` statement is an optional construct in [SQL
-routines](/routines/introduction) to allow processing of a block of statements
+The `LOOP` statement is an optional construct in [](/udf/sql) to allow processing of a block of statements
repeatedly.
The block of `statements` is processed until an explicit use of `LEAVE` causes
@@ -20,7 +19,7 @@ of processing from the beginning starts. `LEAVE` statements are typically
wrapped in an `IF` statement that declares a condition to stop the loop.
The optional `label` before the `LOOP` keyword can be used to [name the
-block](routine-label).
+block](udf-sql-label).
## Examples
@@ -55,10 +54,10 @@ SELECT to_one_hundred(12, 3); -- 30
```
Further examples of varying complexity that cover usage of the `LOOP` statement
-in combination with other statements are available in the [SQL routines examples
-documentation](/routines/examples).
+in combination with other statements are available in the [SQL UDF examples
+documentation](/udf/sql/examples).
## See also
-* [](/routines/introduction)
-* [](/routines/leave)
+* [](/udf/sql)
+* [](/udf/sql/leave)
diff --git a/docs/src/main/sphinx/routines/repeat.md b/docs/src/main/sphinx/udf/sql/repeat.md
similarity index 71%
rename from docs/src/main/sphinx/routines/repeat.md
rename to docs/src/main/sphinx/udf/sql/repeat.md
index 5d750554c172..d75eebfec5ca 100644
--- a/docs/src/main/sphinx/routines/repeat.md
+++ b/docs/src/main/sphinx/udf/sql/repeat.md
@@ -11,10 +11,9 @@ END REPEAT
## Description
-The `REPEAT UNTIL` statement is an optional construct in [SQL
-routines](/routines/introduction) to allow processing of a block of statements
-as long as a condition is met. The condition is validated as a last step of each
-iteration.
+The `REPEAT UNTIL` statement is an optional construct in [](/udf/sql) to allow
+processing of a block of statements as long as a condition is met. The condition
+is validated as a last step of each iteration.
The block of statements is processed at least once. After the first, and every
subsequent processing the expression `condidtion` is validated. If the result is
@@ -22,7 +21,7 @@ subsequent processing the expression `condidtion` is validated. If the result is
the function. If the result is `false`, the statements are processed again.
The optional `label` before the `REPEAT` keyword can be used to [name the
-block](routine-label).
+block](udf-sql-label).
Note that a `WHILE` statement is very similar, with the difference that for
`REPEAT` the statements are processed at least once, and for `WHILE` blocks the
@@ -30,7 +29,7 @@ statements might not be processed at all.
## Examples
-The following routine shows a routine with a `REPEAT` statement that runs until
+The following SQL UDF shows a UDF with a `REPEAT` statement that runs until
the value of `a` is greater or equal to `10`.
```sql
@@ -46,7 +45,7 @@ FUNCTION test_repeat(a bigint)
```
Since `a` is also the input value and it is increased before the check the
-routine always returns `10` for input values of `9` or less, and the input value
+UDF always returns `10` for input values of `9` or less, and the input value
+ 1 for all higher values.
Following are a couple of example invocations with result and explanation:
@@ -60,11 +59,11 @@ SELECT test_repeat(12); -- 13
```
Further examples of varying complexity that cover usage of the `REPEAT`
-statement in combination with other statements are available in the [SQL
-routines examples documentation](/routines/examples).
+statement in combination with other statements are available in the
+[](/udf/sql/examples).
## See also
-* [](/routines/introduction)
-* [](/routines/loop)
-* [](/routines/while)
+* [](/udf/sql)
+* [](/udf/sql/loop)
+* [](/udf/sql/while)
diff --git a/docs/src/main/sphinx/udf/sql/return.md b/docs/src/main/sphinx/udf/sql/return.md
new file mode 100644
index 000000000000..2044b17466b0
--- /dev/null
+++ b/docs/src/main/sphinx/udf/sql/return.md
@@ -0,0 +1,36 @@
+# RETURN
+
+## Synopsis
+
+```text
+RETURN expression
+```
+
+## Description
+
+Provide the value from a [](/udf/sql) to the caller. The value is the result of
+evaluating the expression. It can be a static value, a declared variable or a
+more complex expression.
+
+## Examples
+
+The following examples return a static value, the result of an expression, and
+the value of the variable x:
+
+```sql
+RETURN 42;
+RETURN 6 * 7;
+RETURN x;
+```
+
+Further examples of varying complexity that cover usage of the `RETURN`
+statement in combination with other statements are available in the
+[](/udf/sql/examples).
+
+All SQL UDFs must contain a `RETURN` statement at the end of the top-level block
+in the `FUNCTION` declaration, even if it's unreachable.
+
+## See also
+
+* [](/udf/sql)
+* [](/udf/function)
diff --git a/docs/src/main/sphinx/routines/set.md b/docs/src/main/sphinx/udf/sql/set.md
similarity index 63%
rename from docs/src/main/sphinx/routines/set.md
rename to docs/src/main/sphinx/udf/sql/set.md
index d9c24414e049..971ac5772e59 100644
--- a/docs/src/main/sphinx/routines/set.md
+++ b/docs/src/main/sphinx/udf/sql/set.md
@@ -8,9 +8,9 @@ SET identifier = expression
## Description
-Use the `SET` statement in [SQL routines](/routines/introduction) to assign a
-value to a variable, referenced by comma-separated `identifier`s. The
-value is determined by evaluating the `expression` after the `=` sign.
+Use the `SET` statement in [](/udf/sql) to assign a value to a variable,
+referenced by comma-separated `identifier`s. The value is determined by
+evaluating the `expression` after the `=` sign.
Before the assignment the variable must be defined with a `DECLARE` statement.
The data type of the variable must be identical to the data type of evaluating
@@ -34,10 +34,9 @@ FUNCTION one()
```
Further examples of varying complexity that cover usage of the `SET` statement
-in combination with other statements are available in the [SQL routines examples
-documentation](/routines/examples).
+in combination with other statements are available in the [](/udf/sql/examples).
## See also
-* [](/routines/introduction)
-* [](/routines/declare)
+* [](/udf/sql)
+* [](/udf/sql/declare)
diff --git a/docs/src/main/sphinx/routines/while.md b/docs/src/main/sphinx/udf/sql/while.md
similarity index 66%
rename from docs/src/main/sphinx/routines/while.md
rename to docs/src/main/sphinx/udf/sql/while.md
index 6e252482d4b8..74f4b143659e 100644
--- a/docs/src/main/sphinx/routines/while.md
+++ b/docs/src/main/sphinx/udf/sql/while.md
@@ -10,10 +10,9 @@ END WHILE
## Description
-The `WHILE` statement is an optional construct in [SQL
-routines](/routines/introduction) to allow processing of a block of statements
-as long as a condition is met. The condition is validated as a first step of
-each iteration.
+The `WHILE` statement is an optional construct in [](/udf/sql) to allow
+processing of a block of statements as long as a condition is met. The condition
+is validated as a first step of each iteration.
The expression that defines the `condition` is evaluated at least once. If the
result is `true`, processing moves to `DO`, through following `statements` and
@@ -21,7 +20,7 @@ back to `WHILE` and the `condition`. If the result is `false`, processing moves
to `END WHILE` and continues with the next statement in the function.
The optional `label` before the `WHILE` keyword can be used to [name the
-block](routine-label).
+block](udf-sql-label).
Note that a `WHILE` statement is very similar, with the difference that for
`REPEAT` the statements are processed at least once, and for `WHILE` blocks the
@@ -37,11 +36,10 @@ END WHILE;
```
Further examples of varying complexity that cover usage of the `WHILE` statement
-in combination with other statements are available in the [SQL routines examples
-documentation](/routines/examples).
+in combination with other statements are available in the [](/udf/sql/examples).
## See also
-* [](/routines/introduction)
-* [](/routines/loop)
-* [](/routines/repeat)
+* [](/udf/sql)
+* [](/udf/sql/loop)
+* [](/udf/sql/repeat)
diff --git a/lib/trino-array/pom.xml b/lib/trino-array/pom.xml
index 9cd91d5fa696..770af98fada8 100644
--- a/lib/trino-array/pom.xml
+++ b/lib/trino-array/pom.xml
@@ -5,7 +5,7 @@
io.trino
trino-root
- 468-SNAPSHOT
+ 469-SNAPSHOT
../../pom.xml
diff --git a/lib/trino-cache/pom.xml b/lib/trino-cache/pom.xml
index 0ae4a50d484e..49d3b1c68de9 100644
--- a/lib/trino-cache/pom.xml
+++ b/lib/trino-cache/pom.xml
@@ -5,7 +5,7 @@
io.trino
trino-root
- 468-SNAPSHOT
+ 469-SNAPSHOT
../../pom.xml
diff --git a/lib/trino-filesystem-alluxio/pom.xml b/lib/trino-filesystem-alluxio/pom.xml
index db27a0db7c9e..7adc50ffd260 100644
--- a/lib/trino-filesystem-alluxio/pom.xml
+++ b/lib/trino-filesystem-alluxio/pom.xml
@@ -5,7 +5,7 @@
io.trino
trino-root
- 468-SNAPSHOT
+ 469-SNAPSHOT
../../pom.xml
diff --git a/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioFileIterator.java b/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioFileIterator.java
index e67a51f16e90..d20bc4cc2aff 100644
--- a/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioFileIterator.java
+++ b/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioFileIterator.java
@@ -24,19 +24,18 @@
import java.util.List;
import java.util.Optional;
-import static io.trino.filesystem.alluxio.AlluxioUtils.convertToLocation;
import static java.util.Objects.requireNonNull;
public class AlluxioFileIterator
implements FileIterator
{
private final Iterator files;
- private final String mountRoot;
+ private final String basePath;
- public AlluxioFileIterator(List files, String mountRoot)
+ public AlluxioFileIterator(List files, String basePath)
{
this.files = requireNonNull(files.iterator(), "files is null");
- this.mountRoot = requireNonNull(mountRoot, "mountRoot is null");
+ this.basePath = requireNonNull(basePath, "basePath is null");
}
@Override
@@ -54,7 +53,8 @@ public FileEntry next()
return null;
}
URIStatus fileStatus = files.next();
- Location location = convertToLocation(fileStatus.getPath(), mountRoot);
+ String filePath = fileStatus.getPath();
+ Location location = Location.of(basePath + filePath);
return new FileEntry(
location,
fileStatus.getLength(),
diff --git a/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioFileSystem.java b/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioFileSystem.java
index b6a949ee44d6..94654da3f1b2 100644
--- a/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioFileSystem.java
+++ b/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioFileSystem.java
@@ -38,6 +38,7 @@
import java.util.stream.Collectors;
import static io.trino.filesystem.alluxio.AlluxioUtils.convertToAlluxioURI;
+import static io.trino.filesystem.alluxio.AlluxioUtils.getAlluxioBase;
import static java.util.Objects.requireNonNull;
import static java.util.UUID.randomUUID;
@@ -189,20 +190,20 @@ public FileIterator listFiles(Location location)
try {
URIStatus status = alluxioClient.getStatus(convertToAlluxioURI(location, mountRoot));
if (status == null) {
- new AlluxioFileIterator(Collections.emptyList(), mountRoot);
+ new AlluxioFileIterator(Collections.emptyList(), getAlluxioBase(location.toString()));
}
if (!status.isFolder()) {
throw new IOException("Location is not a directory: %s".formatted(location));
}
}
catch (NotFoundRuntimeException | AlluxioException e) {
- return new AlluxioFileIterator(Collections.emptyList(), mountRoot);
+ return new AlluxioFileIterator(Collections.emptyList(), getAlluxioBase(location.toString()));
}
try {
List filesStatus = alluxioClient.listStatus(convertToAlluxioURI(location, mountRoot),
ListStatusPOptions.newBuilder().setRecursive(true).build());
- return new AlluxioFileIterator(filesStatus.stream().filter(status -> !status.isFolder() & status.isCompleted()).toList(), mountRoot);
+ return new AlluxioFileIterator(filesStatus.stream().filter(status -> !status.isFolder() & status.isCompleted()).toList(), getAlluxioBase(location.toString()));
}
catch (AlluxioException e) {
throw new IOException("Error listFiles %s".formatted(location), e);
diff --git a/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioUtils.java b/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioUtils.java
index 49ece36a8b93..ac95c970dd36 100644
--- a/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioUtils.java
+++ b/lib/trino-filesystem-alluxio/src/main/java/io/trino/filesystem/alluxio/AlluxioUtils.java
@@ -50,6 +50,16 @@ public static Location convertToLocation(String path, String mountRoot)
return Location.of(schema + mountRootWithSlash + path);
}
+ public static String getAlluxioBase(String path)
+ {
+ requireNonNull(path, "path is null");
+ if (!path.startsWith("alluxio://")) {
+ throw new IllegalArgumentException("path is not an alluxio://");
+ }
+ int index = path.indexOf('/', "alluxio://".length());
+ return path.substring(0, index);
+ }
+
public static String simplifyPath(String path)
{
// Use a deque to store the path components
diff --git a/lib/trino-filesystem-alluxio/src/test/java/io/trino/filesystem/alluxio/TestAlluxioFileIterator.java b/lib/trino-filesystem-alluxio/src/test/java/io/trino/filesystem/alluxio/TestAlluxioFileIterator.java
new file mode 100644
index 000000000000..6ae971673887
--- /dev/null
+++ b/lib/trino-filesystem-alluxio/src/test/java/io/trino/filesystem/alluxio/TestAlluxioFileIterator.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.trino.filesystem.alluxio;
+
+import alluxio.client.file.URIStatus;
+import alluxio.wire.FileInfo;
+import io.trino.filesystem.FileEntry;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+final class TestAlluxioFileIterator
+{
+ private final String fileName = "000000_0";
+ private final String filePath = "/s3a/tables/sales/000000_0";
+ private final String ufsFilePath = "s3a://test-bucket/tables/sales/000000_0";
+
+ @Test
+ void testNext()
+ throws IOException
+ {
+ String alluxioBasePath = "alluxio://master:19998";
+ FileInfo fileInfo = new FileInfo();
+ fileInfo.setName(fileName);
+ fileInfo.setPath(filePath);
+ fileInfo.setUfsPath(ufsFilePath);
+ URIStatus fileStatus = new URIStatus(fileInfo);
+ AlluxioFileIterator iterator = new AlluxioFileIterator(
+ List.of(fileStatus),
+ alluxioBasePath);
+ FileEntry fileEntry = iterator.next();
+ assertThat(fileEntry.location().toString())
+ .isEqualTo(alluxioBasePath + filePath);
+
+ alluxioBasePath = "alluxio:/";
+ fileInfo = new FileInfo();
+ fileInfo.setName(fileName);
+ fileInfo.setPath(filePath);
+ fileInfo.setUfsPath(ufsFilePath);
+ fileStatus = new URIStatus(fileInfo);
+ iterator = new AlluxioFileIterator(
+ List.of(fileStatus),
+ alluxioBasePath);
+ fileEntry = iterator.next();
+ assertThat(fileEntry.location().toString())
+ .isEqualTo(alluxioBasePath + filePath);
+ }
+}
diff --git a/lib/trino-filesystem-azure/pom.xml b/lib/trino-filesystem-azure/pom.xml
index 8fad433ce06f..e67100cd4db4 100644
--- a/lib/trino-filesystem-azure/pom.xml
+++ b/lib/trino-filesystem-azure/pom.xml
@@ -5,7 +5,7 @@
io.trino
trino-root
- 468-SNAPSHOT
+ 469-SNAPSHOT
../../pom.xml
@@ -178,6 +178,12 @@
test