Re: CAST(... ON DEFAULT) - WIP build on top of Error-Safe User Functions
jian he <jian.universality@gmail.com>
From: jian he <jian.universality@gmail.com>
To: Corey Huinker <corey.huinker@gmail.com>
Cc: Vik Fearing <vik@postgresfriends.org>,
Isaac Morland <isaac.morland@gmail.com>, pgsql-hackers@lists.postgresql.org
Date: 2025-11-04T06:02:14Z
Lists: pgsql-hackers
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Make cast functions to type money error safe
- b36b95640487 19 (unreleased) landed
-
Make cast function from circle to polygon error safe
- 26f9012beecf 19 (unreleased) landed
-
Make geometry cast functions error safe
- 45cdaf3665be 19 (unreleased) landed
-
Make cast functions from jsonb error safe
- 10e4d8aaf46f 19 (unreleased) landed
-
Make many cast functions error safe
- e2f289e5b9b8 19 (unreleased) landed
-
Add SQL/JSON query functions
- 6185c9737cf4 17.0 cited
-
Add soft error handling to some expression nodes
- aaaf9449ec6b 17.0 cited
Attachments
- v9-0017-error-safe-for-casting-jsonb-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0017
- v9-0016-error-safe-for-casting-timestamp-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0016
- v9-0019-CAST-expr-AS-newtype-DEFAULT-ON-ERROR.patch (text/x-patch) patch v9-0019
- v9-0015-error-safe-for-casting-timestamptz-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0015
- v9-0018-error-safe-for-casting-geometry-data-type.patch (text/x-patch) patch v9-0018
- v9-0014-error-safe-for-casting-interval-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0014
- v9-0012-error-safe-for-casting-float8-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0012
- v9-0013-error-safe-for-casting-date-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0013
- v9-0011-error-safe-for-casting-float4-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0011
- v9-0010-error-safe-for-casting-numeric-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0010
- v9-0009-error-safe-for-casting-bigint-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0009
- v9-0008-error-safe-for-casting-integer-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0008
- v9-0005-error-safe-for-casting-character-varying-to-other-types-per-pg_ca.patch (text/x-patch) patch v9-0005
- v9-0007-error-safe-for-casting-macaddr8-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0007
- v9-0006-error-safe-for-casting-inet-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0006
- v9-0004-error-safe-for-casting-text-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0004
- v9-0002-error-safe-for-casting-bit-varbit-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0002
- v9-0003-error-safe-for-casting-character-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0003
- v9-0001-error-safe-for-casting-bytea-to-other-types-per-pg_cast.patch (text/x-patch) patch v9-0001
On Tue, Oct 14, 2025 at 10:00 AM jian he <jian.universality@gmail.com> wrote:
> Please check the attached v8.
>
hi.
please see the attached V9 patchset.
v9-0001 to v9-0018: refactor pg_cast.castfunc entries, make it error safe.
v9-0019: CAST(... AS ... DEFAULT def_expr ON CONVERSION ERROR)
select pc.castsource::regtype,pc.casttarget::regtype,
castfunc::regproc, pp.prosrc
from pg_cast pc join pg_proc pp on pp.oid = pc.castfunc
join pg_type pt on pt.oid = castsource
join pg_type pt1 on pt1.oid = casttarget
and pc.castfunc > 0 and pt.typnamespace = 'pg_catalog'::regnamespace
and pt1.typnamespace = 'pg_catalog'::regnamespace and not pc.casterrorsafe;
castsource | casttarget | castfunc | prosrc
------------+------------+----------------------+--------------
circle | polygon | pg_catalog.polygon |
bigint | money | pg_catalog.money | int8_cash
integer | money | pg_catalog.money | int4_cash
numeric | money | pg_catalog.money | numeric_cash
money | numeric | pg_catalog."numeric" | cash_numeric
(5 rows)
The above result shows type casts using functions which cannot be error safe.
Money type related casts still can not be error safe.
Cast from circle to polygon cannot be error safe because the associated cast
function (pg_cast.castfunc) is written in SQL
(see src/backend/catalog/system_functions.sql LINE 112).
It appears impossible to make SQL language functions error safe, because
fmgr_sql ignores fcinfo->context.
eval_const_expressions cannot be error safe, so we need to handle
source_expr as an UNKNOWN constant in an error safe beforehand.
For example, we need handle ('1' AS DATE) in an error safe way
for
SELECT CAST('1' AS date DEFAULT '2011-01-01' ON ERROR);
Since we must handle the source_expr when it is an UNKNOWN constant in an
error safe way, we can apply the same handling when source_expr is a
Const whose type is not UNKNOWN.
For example:
SELECT CAST('[(1,2),(3,4)]'::path AS polygon DEFAULT NULL ON CONVERSION ERROR);
If source_expr is a Const and the cast expression is a FuncExpr, we can be
certain that all arguments (FuncExpr->args) are also Const; see the function
chain coerce_to_target_type → coerce_type → build_coercion_expression.
We don’t need to worry about deparsing the expression because struct
SafeTypeCastExpr includes source_expr, cast_expr, and default_expr. Even if
cast_expr is NULL, we can still use source_expr to reconstruct the original CAST
expression.
so I introduced:
evaluate_expr_safe: error safe version of evaluate_expr
CoerceUnknownConstSafe: tests whether an UNKNOWN Const can be coerced to the
target type.