On Tue, 20 Dec 2022 at 04:27, Corey Huinker <corey.huin...@gmail.com> wrote:
>
>
> Attached is my work in progress to implement the changes to the CAST() 
> function as proposed by Vik Fearing.
>
> This work builds upon the Error-safe User Functions work currently ongoing.
>
> The proposed changes are as follows:
>
> CAST(expr AS typename)
>     continues to behave as before.
>
> CAST(expr AS typename ERROR ON ERROR)
>     has the identical behavior as the unadorned CAST() above.
>
> CAST(expr AS typename NULL ON ERROR)
>     will use error-safe functions to do the cast of expr, and will return 
> NULL if the cast fails.
>
> CAST(expr AS typename DEFAULT expr2 ON ERROR)
>     will use error-safe functions to do the cast of expr, and will return 
> expr2 if the cast fails.
>
> There is an additional FORMAT parameter that I have not yet implemented, my 
> understanding is that it is largely intended for DATE/TIME field conversions, 
> but others are certainly possible.
> CAST(expr AS typename FORMAT fmt DEFAULT expr2 ON ERROR)
>
> What is currently working:
> - Any scalar expression that can be evaluated at parse time. These tests from 
> cast.sql all currently work:
>
> VALUES (CAST('error' AS integer));
> VALUES (CAST('error' AS integer ERROR ON ERROR));
> VALUES (CAST('error' AS integer NULL ON ERROR));
> VALUES (CAST('error' AS integer DEFAULT 42 ON ERROR));
>
> SELECT CAST('{123,abc,456}' AS integer[] DEFAULT '{-789}' ON ERROR) as 
> array_test1;
>
> - Scalar values evaluated at runtime.
>
> CREATE TEMPORARY TABLE t(t text);
> INSERT INTO t VALUES ('a'), ('1'), ('b'), (2);
> SELECT CAST(t.t AS integer DEFAULT -1 ON ERROR) AS foo FROM t;
>  foo
> -----
>   -1
>    1
>   -1
>    2
> (4 rows)
>
>
> Along the way, I made a few design decisions, each of which is up for debate:
>
> First, I created OidInputFunctionCallSafe, which is to OidInputFunctionCall 
> what InputFunctionCallSafe is to InputFunctionCall. Given that the only place 
> I ended up using it was stringTypeDatumSafe(), it may be possible to just 
> move that code inside stringTypeDatumSafe.
>
> Next, I had a need for FuncExpr, CoerceViaIO, and ArrayCoerce to all report 
> if their expr argument failed, and if not, just past the evaluation of expr2. 
> Rather than duplicate this logic in several places, I chose instead to modify 
> CoalesceExpr to allow for an error-test mode in addition to its default 
> null-test mode, and then to provide this altered node with two expressions, 
> the first being the error-safe typecast of expr and the second being the 
> non-error-safe typecast of expr2.
>
> I still don't have array-to-array casts working, as the changed I would 
> likely need to make to ArrayCoerce get somewhat invasive, so this seemed like 
> a good time to post my work so far and solicit some feedback beyond what I've 
> already been getting from Jeff Davis and Michael Paquier.
>
> I've sidestepped domains as well for the time being as well as avoiding JIT 
> issues entirely.
>
> No documentation is currently prepared. All but one of the regression test 
> queries work, the one that is currently failing is:
>
> SELECT CAST('{234,def,567}'::text[] AS integer[] DEFAULT '{-1011}' ON ERROR) 
> as array_test2;
>
> Other quirks:
> - an unaliased CAST ON DEFAULT will return the column name of "coalesce", 
> which internally is true, but obviously would be quite confusing to a user.
>
> As a side observation, I noticed that the optimizer already tries to resolve 
> expressions based on constants and to collapse expression trees where 
> possible, which makes me wonder if the work done to do the same in 
> transformTypeCast/ and coerce_to_target_type and coerce_type isn't also 
> wasted.

CFBot shows some compilation errors as in [1], please post an updated
version for the same:
[02:53:44.829] time make -s -j${BUILD_JOBS} world-bin
[02:55:41.164] llvmjit_expr.c: In function ‘llvm_compile_expr’:
[02:55:41.164] llvmjit_expr.c:928:6: error: ‘v_resnull’ undeclared
(first use in this function); did you mean ‘v_resnullp’?
[02:55:41.164] 928 | v_resnull = LLVMBuildLoad(b, v_reserrorp, "");
[02:55:41.164] | ^~~~~~~~~
[02:55:41.164] | v_resnullp
[02:55:41.164] llvmjit_expr.c:928:6: note: each undeclared identifier
is reported only once for each function it appears in
[02:55:41.164] llvmjit_expr.c:928:35: error: ‘v_reserrorp’ undeclared
(first use in this function); did you mean ‘v_reserror’?
[02:55:41.164] 928 | v_resnull = LLVMBuildLoad(b, v_reserrorp, "");
[02:55:41.164] | ^~~~~~~~~~~
[02:55:41.164] | v_reserror
[02:55:41.165] make[2]: *** [<builtin>: llvmjit_expr.o] Error 1
[02:55:41.165] make[2]: *** Waiting for unfinished jobs....
[02:55:45.495] make[1]: *** [Makefile:42: all-backend/jit/llvm-recurse] Error 2
[02:55:45.495] make: *** [GNUmakefile:21: world-bin-src-recurse] Error 2

[1] - https://cirrus-ci.com/task/6687753371385856?logs=gcc_warning#L448

Regards,
Vignesh


Reply via email to