Skip to content

Feature: add TRY_CONVERT extension - #51

Open
Alena0704 wants to merge 1 commit into
REL_2_STABLEfrom
try_convert-REL_2_STABLE
Open

Feature: add TRY_CONVERT extension#51
Alena0704 wants to merge 1 commit into
REL_2_STABLEfrom
try_convert-REL_2_STABLE

Conversation

@Alena0704

@Alena0704 Alena0704 commented Jul 30, 2026

Copy link
Copy Markdown

Feature: add TRY_CONVERT extension

TRY_CONVERT(source_value, default_value) casts source_value to the type of default_value and returns default_value whenever the cast fails, which is the behaviour of TRY_CAST in SQL Server. Without it a single malformed value makes the whole query fail, and the plpgsql workarounds that catch the error per row are several times slower.

TRY_CONVERT('42'::text, NULL::int2)   -- returns 42::int2
TRY_CONVERT('42d'::text, NULL::int2)  -- returns NULL::int2
TRY_CONVERT('42d'::text, 1234::int2)  -- returns 1234::int2

The conversion to use is resolved the same way the parser resolves an explicit cast in coerce_type(): a pg_cast entry, an I/O conversion or a binary-compatible relabel, followed by the length coercion of the target type. Casts between array types and casts to domain types are not supported and are reported as query errors, the same as a cast that does not exist at all; only a failure caused by the converted data is turned into the default value.

The cast itself runs inside a PG_TRY() block, since the datatype input functions of Cloudberry cannot yet report a conversion failure without throwing.

The extension is marked trusted, so the owner of a database can install it without being a superuser.

Co-authored-by: Vladimir Rachkin vova@kpnn.ru
See: PR#901 apache#901

TRY_CONVERT(source_value, default_value) casts source_value to the type
of default_value and returns default_value whenever the cast fails,
which is the behaviour of TRY_CAST in SQL Server.  Without it a single
malformed value makes the whole query fail, and the plpgsql workarounds
that catch the error per row are several times slower.

    TRY_CONVERT('42'::text, NULL::int2)   -- returns 42::int2
    TRY_CONVERT('42d'::text, NULL::int2)  -- returns NULL::int2
    TRY_CONVERT('42d'::text, 1234::int2)  -- returns 1234::int2

The conversion to use is resolved the same way the parser resolves an
explicit cast in coerce_type(): a pg_cast entry, an I/O conversion or a
binary-compatible relabel, followed by the length coercion of the
target type.  Casts between array types and casts to domain types are
not supported and are reported as query errors, the same as a cast that
does not exist at all; only a failure caused by the converted data is
turned into the default value.

The cast itself runs inside a PG_TRY() block, since the datatype input
functions of Cloudberry cannot yet report a conversion failure without
throwing.

The extension is marked trusted, so the owner of a database can install
it without being a superuser.

Co-authored-by: Vladimir Rachkin <vova@kpnn.ru>
See: PR#901 <apache#901>
(cherry picked from commit 420a628)

@leborchuk leborchuk left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants