summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2025-10-22 09:55:17 +0900
committerMichael Paquier <michael@paquier.xyz>2025-10-22 09:55:17 +0900
commit2b75c38b707a070922231de667a0bd08ee71b268 (patch)
tree554bcd6bd9ccca62674da2bb711441888d20917e
parent2470ca435c452fe4def9dcc4a831b5101691d541 (diff)
Add error_on_null(), checking if the input is the null value
This polymorphic function produces an error if the input value is detected as being the null value; otherwise it returns the input value unchanged. This function can for example become handy in SQL function bodies, to enforce that exactly one row was returned. Author: Joel Jacobson <joel@compiler.org> Reviewed-by: Vik Fearing <vik@postgresfriends.org> Reviewed-by: Michael Paquier <michael@paquier.xyz> Discussion: https://postgr.es/m/ece8c6d1-2ab1-45d5-ba12-8dec96fc8886@app.fastmail.com Discussion: https://postgr.es/m/de94808d-ed58-4536-9e28-e79b09a534c7@app.fastmail.com
-rw-r--r--doc/src/sgml/func/func-comparison.sgml22
-rw-r--r--src/backend/utils/adt/misc.c14
-rw-r--r--src/include/catalog/pg_proc.dat3
-rw-r--r--src/test/regress/expected/misc_functions.out31
-rw-r--r--src/test/regress/sql/misc_functions.sql11
5 files changed, 81 insertions, 0 deletions
diff --git a/doc/src/sgml/func/func-comparison.sgml b/doc/src/sgml/func/func-comparison.sgml
index c1205983f8b..ecb1d89463a 100644
--- a/doc/src/sgml/func/func-comparison.sgml
+++ b/doc/src/sgml/func/func-comparison.sgml
@@ -602,6 +602,28 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in
<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>
+ <primary>error_on_null</primary>
+ </indexterm>
+ <function>error_on_null</function> ( <type>anyelement</type> )
+ <returnvalue>anyelement</returnvalue>
+ </para>
+ <para>
+ Checks if the input is the null value, generating an error if so;
+ otherwise, returns the input.
+ </para>
+ <para>
+ <literal>error_on_null(42)</literal>
+ <returnvalue>42</returnvalue>
+ </para>
+ <para>
+ <literal>error_on_null(row(null,null))</literal>
+ <returnvalue>(,)</returnvalue>
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="func_table_entry"><para role="func_signature">
+ <indexterm>
<primary>num_nonnulls</primary>
</indexterm>
<function>num_nonnulls</function> ( <literal>VARIADIC</literal> <type>"any"</type> )
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 7cb7716e58b..fa1cb675027 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -186,6 +186,20 @@ pg_num_nonnulls(PG_FUNCTION_ARGS)
PG_RETURN_INT32(nargs - nulls);
}
+/*
+ * error_on_null()
+ * Check if the input is the NULL value
+ */
+Datum
+pg_error_on_null(PG_FUNCTION_ARGS)
+{
+ if (PG_ARGISNULL(0))
+ ereport(ERROR,
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ errmsg("null value not allowed")));
+
+ PG_RETURN_DATUM(PG_GETARG_DATUM(0));
+}
/*
* current_database()
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b51d2b17379..eecb43ec6f0 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12543,6 +12543,9 @@
{ oid => '6292', descr => 'aggregate transition function',
proname => 'any_value_transfn', prorettype => 'anyelement',
proargtypes => 'anyelement anyelement', prosrc => 'any_value_transfn' },
+{ oid => '8488', descr => 'check if input is the null value',
+ proname => 'error_on_null', proisstrict => 'f', prorettype => 'anyelement',
+ proargtypes => 'anyelement', prosrc => 'pg_error_on_null' },
{ oid => '6321', descr => 'list of available WAL summary files',
proname => 'pg_available_wal_summaries', prorows => '100', proretset => 't',
diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out
index 36164a99c83..e76e28b95ce 100644
--- a/src/test/regress/expected/misc_functions.out
+++ b/src/test/regress/expected/misc_functions.out
@@ -178,6 +178,37 @@ LINE 1: SELECT num_nulls();
^
DETAIL: No function of that name accepts the given number of arguments.
--
+-- error_on_null()
+--
+SELECT error_on_null(1);
+ error_on_null
+---------------
+ 1
+(1 row)
+
+SELECT error_on_null(NULL::int);
+ERROR: null value not allowed
+SELECT error_on_null(NULL::int[]);
+ERROR: null value not allowed
+SELECT error_on_null('{1,2,NULL,3}'::int[]);
+ error_on_null
+---------------
+ {1,2,NULL,3}
+(1 row)
+
+SELECT error_on_null(ROW(1,NULL::int));
+ error_on_null
+---------------
+ (1,)
+(1 row)
+
+SELECT error_on_null(ROW(NULL,NULL));
+ error_on_null
+---------------
+ (,)
+(1 row)
+
+--
-- canonicalize_path()
--
CREATE FUNCTION test_canonicalize_path(text)
diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql
index 23792c4132a..220472d5ad1 100644
--- a/src/test/regress/sql/misc_functions.sql
+++ b/src/test/regress/sql/misc_functions.sql
@@ -78,6 +78,17 @@ SELECT num_nonnulls();
SELECT num_nulls();
--
+-- error_on_null()
+--
+
+SELECT error_on_null(1);
+SELECT error_on_null(NULL::int);
+SELECT error_on_null(NULL::int[]);
+SELECT error_on_null('{1,2,NULL,3}'::int[]);
+SELECT error_on_null(ROW(1,NULL::int));
+SELECT error_on_null(ROW(NULL,NULL));
+
+--
-- canonicalize_path()
--