Re: CAST(... ON DEFAULT) - WIP build on top of Error-Safe User Functions

From: jian he <jian(dot)universality(at)gmail(dot)com>
To: Peter Eisentraut <peter(at)eisentraut(dot)org>
Cc: Corey Huinker <corey(dot)huinker(at)gmail(dot)com>, Amul Sul <sulamul(at)gmail(dot)com>, Kirill Reshke <reshkekirill(at)gmail(dot)com>, Vik Fearing <vik(at)postgresfriends(dot)org>, Isaac Morland <isaac(dot)morland(at)gmail(dot)com>, pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: CAST(... ON DEFAULT) - WIP build on top of Error-Safe User Functions
Date: 2026-03-28 00:37:07
Message-ID: CACJufxHGox47X4zNtVeNw7H=SZ7ATAAD5SEYpvxa2o5mPV0XCA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Thu, Mar 26, 2026 at 4:59 PM jian he <jian(dot)universality(at)gmail(dot)com> wrote:
>
> Currently, when a valid ErrorSaveContext is passed to state->escontext
> (ExprState->escontext),
> ExecInitExprRec is designed to compile the entire expression tree
> using soft errors.
> Consider the following example:
> create table t1(a text, b text, c int, d int8);
> create domain d2 as text check (value <> 'a');
> insert into t1(a, d) values('a', 2147483648);
> select cast (cast(d as int) as text default null on conversion
> error) from t1; -- queryA
> select cast (cast(a as d2) as text default null on conversion
> error) from t1; -- queryB
> select cast (cast(a as int) as text default null on conversion
> error) from t1; -- queryC
>

In ATExecAddColumn, we have:

exprState = ExecPrepareExprWithContext(defval, estate, (Node *) &escontext);

The entire defval expression tree (including all the potential FuncExpr node
subexpression) must be marked as error-safe (all the
FuncExpr->errorsafe must be set to true).
If they aren't, ExecPrepareExprWithContext won't work.
In that scarenio, we need a walker function to set FuncExpr->errorsafe
to true for the above defval, overall feels very ugly.

Therefore, the previous approach (v24) of simply adding an errorsafe boolean to
FuncExpr will not work.
IMHO, it is not feasible to mark only part of an expression tree as error-safe.
Because of this, we should try to make queryA, queryB, queryC return NULL.

However, some inconsistency remains, for example:
SELECT CAST (CAST('a' AS int) AS text DEFAULT NULL ON CONVERSION
ERROR) FROM tcast1; -- error
SELECT CAST (CAST('a'::text AS int) AS text DEFAULT NULL ON CONVERSION
ERROR) FROM tcast1; -- ok

V24: There is a segfault because of eval_const_expressions_mutator,
T_ArrayCoerceExpr handling,
You can invoke it via:
select cast (cast('{a}'::text[] as int[]) as text[] default null on
conversion error) from t2;

In V24, there were no nested type cast regress tests, now I have added some.

I removed the errorsafe boolean from FuncExpr. As mentioned previously, it is
difficult to make ExecInitExprRec compile expression partically eror safe.

refactoring on transformArrayExpr, transformTypeCast, ExecInitSafeTypeCastExpr.

--
jian
https://www.enterprisedb.com/

Attachment Content-Type Size
v25-0008-error-safe-for-casting-money-data-type.patch text/x-patch 3.7 KB
v25-0009-CAST-expr-AS-newtype-DEFAULT-expr-ON-CONVERSION-ERROR.patch text/x-patch 139.4 KB
v25-0006-error-safe-for-casting-geometry-data-type.patch text/x-patch 12.5 KB
v25-0002-error-safe-for-casting-jsonb-to-other-types-per-pg_cast.patch text/x-patch 6.4 KB
v25-0007-error-safe-for-casting-circle-to-polygon.patch text/x-patch 5.2 KB
v25-0001-error-safe-for-casting-text-to-other-types-per-pg_cast.patch text/x-patch 9.7 KB
v25-0003-extended-function-for-float-overflow-underflow-zero_divide.patch text/x-patch 2.3 KB
v25-0005-refactor-point_dt.patch text/x-patch 8.7 KB
v25-0004-introduce-float8-safe-function.patch text/x-patch 3.9 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Michael Paquier 2026-03-28 01:42:09 Re: Refactor query normalization into core query jumbling
Previous Message Peter Geoghegan 2026-03-28 00:35:24 Re: index prefetching