From e8c1f0f5ffcdfac56c0780cd80fb774bdeb0cb8b Mon Sep 17 00:00:00 2001 From: Ryan Kuo Date: Tue, 29 Jul 2025 15:05:06 -0400 Subject: [PATCH 1/3] create views with UDFs --- .../known-limitations/udf-limitations.md | 1 - src/current/v25.3/create-view.md | 67 +++++++++++++++++++ src/current/v25.3/user-defined-functions.md | 6 ++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/current/_includes/v25.3/known-limitations/udf-limitations.md b/src/current/_includes/v25.3/known-limitations/udf-limitations.md index 8b2ef66b403..cd749ced7e4 100644 --- a/src/current/_includes/v25.3/known-limitations/udf-limitations.md +++ b/src/current/_includes/v25.3/known-limitations/udf-limitations.md @@ -3,7 +3,6 @@ - A `RECORD`-returning UDF cannot be created without a `RETURN` statement in the root block, which would restrict the wildcard type to a concrete one. [#122945](https://github.com/cockroachdb/cockroach/issues/122945) - User-defined functions are not currently supported in: - Expressions (column, index, constraint) in tables. [#87699](https://github.com/cockroachdb/cockroach/issues/87699) - - Views. [#87699](https://github.com/cockroachdb/cockroach/issues/87699) - User-defined functions cannot call themselves recursively. [#93049](https://github.com/cockroachdb/cockroach/issues/93049) - The `setval` function cannot be resolved when used inside UDF bodies. [#110860](https://github.com/cockroachdb/cockroach/issues/110860) - Casting subqueries to [user-defined types]({% link {{ page.version.version }}/create-type.md %}) in UDFs is not supported. [#108184](https://github.com/cockroachdb/cockroach/issues/108184) \ No newline at end of file diff --git a/src/current/v25.3/create-view.md b/src/current/v25.3/create-view.md index 9bd76c2f8cc..927affb40c0 100644 --- a/src/current/v25.3/create-view.md +++ b/src/current/v25.3/create-view.md @@ -147,6 +147,73 @@ Executing the query is as easy as `SELECT`ing from the view, as you would from a (3 rows) ~~~ +### Create a view that references routines + +{% include_cached new-in.html version="v25.3" %} Views can call both scalar and set-returning [user-defined functions (UDFs)]({% link {{ page.version.version }}/user-defined-functions.md %}) in their `SELECT` statements. + +The following example builds a view over a table and two UDFs. + +Create and populate a table: + +{% include_cached copy-clipboard.html %} +~~~ sql +CREATE TABLE xy (x INT, y INT); +INSERT INTO xy VALUES (1, 2), (3, 4), (5, 6); +~~~ + +Define a scalar and a set-returning UDF: + +{% include_cached copy-clipboard.html %} +~~~ sql +CREATE FUNCTION f_scalar() RETURNS INT LANGUAGE SQL AS $$ + SELECT count(*) FROM xy; + $$; +~~~ + +{% include_cached copy-clipboard.html %} +~~~ sql +CREATE FUNCTION f_setof() RETURNS SETOF xy LANGUAGE SQL AS $$ + SELECT * FROM xy; + $$; +~~~ + +Create a view that references both functions: + +{% include_cached copy-clipboard.html %} +~~~ sql +CREATE VIEW v_xy AS +SELECT x, y, f_scalar() AS total_rows +FROM f_setof(); +~~~ + +Query the view: + +{% include_cached copy-clipboard.html %} +~~~ sql +SELECT * FROM v_xy ORDER BY x; +~~~ + +~~~ + x | y | total_rows +----+---+------------- + 1 | 2 | 3 + 3 | 4 | 3 + 5 | 6 | 3 +(3 rows) +~~~ + +Because the view depends on `f_scalar` and `f_setof`, attempting to rename either function returns an error: + +{% include_cached copy-clipboard.html %} +~~~ sql +ALTER FUNCTION f_scalar RENAME TO f_scalar_renamed; +~~~ + +~~~ +ERROR: cannot rename function "f_scalar" because other functions or views ([movr.public.v_xy]) still depend on it +SQLSTATE: 0A000 +~~~ + ## See also - [Selection Queries]({% link {{ page.version.version }}/selection-queries.md %}) diff --git a/src/current/v25.3/user-defined-functions.md b/src/current/v25.3/user-defined-functions.md index 307bce901d7..33a82e2d7c8 100644 --- a/src/current/v25.3/user-defined-functions.md +++ b/src/current/v25.3/user-defined-functions.md @@ -113,6 +113,12 @@ SELECT add(3,5) as sum; (1 row) ~~~ +### Call a UDF from a view + +You can include UDF calls in a view definition. Each time the view is queried, the function executes. + +Refer to [Create a view that references routines]({% link {{ page.version.version }}/create-view.md %}#create-a-view-that-references-routines). + ### Create a UDF using PL/pgSQL {% include {{ page.version.version }}/sql/udf-plpgsql-example.md %} From 2a4f40012392acb7b7fcf3ef819b76b8eaa8f4bb Mon Sep 17 00:00:00 2001 From: Ryan Kuo Date: Wed, 30 Jul 2025 19:05:05 -0400 Subject: [PATCH 2/3] address reviewer comment --- src/current/v25.3/user-defined-functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/current/v25.3/user-defined-functions.md b/src/current/v25.3/user-defined-functions.md index 33a82e2d7c8..bf60ab767aa 100644 --- a/src/current/v25.3/user-defined-functions.md +++ b/src/current/v25.3/user-defined-functions.md @@ -115,7 +115,7 @@ SELECT add(3,5) as sum; ### Call a UDF from a view -You can include UDF calls in a view definition. Each time the view is queried, the function executes. +You can include UDF calls in a view definition. The function is invoked each time the view is queried. A [materialized view]({% link {{ page.version.version }}/views.md %}#materialized-views) will invoke the function only when the view is created or refreshed. Refer to [Create a view that references routines]({% link {{ page.version.version }}/create-view.md %}#create-a-view-that-references-routines). From 51726a0368852d910fb797b48eb103c2d387e7d3 Mon Sep 17 00:00:00 2001 From: Ryan Kuo Date: Fri, 1 Aug 2025 10:14:09 -0400 Subject: [PATCH 3/3] review edit --- src/current/v25.3/user-defined-functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/current/v25.3/user-defined-functions.md b/src/current/v25.3/user-defined-functions.md index bf60ab767aa..c525ac6a5ea 100644 --- a/src/current/v25.3/user-defined-functions.md +++ b/src/current/v25.3/user-defined-functions.md @@ -115,7 +115,7 @@ SELECT add(3,5) as sum; ### Call a UDF from a view -You can include UDF calls in a view definition. The function is invoked each time the view is queried. A [materialized view]({% link {{ page.version.version }}/views.md %}#materialized-views) will invoke the function only when the view is created or refreshed. +You can include UDF calls in a [view]({% link {{ page.version.version }}/views.md %}) definition. The function is invoked each time the view is queried. A [materialized view]({% link {{ page.version.version }}/views.md %}#materialized-views) will invoke the function only when the view is created or refreshed. Refer to [Create a view that references routines]({% link {{ page.version.version }}/create-view.md %}#create-a-view-that-references-routines).