From: Nick Crews Date: Wed, 10 May 2023 16:07:46 +0000 (-0800) Subject: fixup: try_cast: v5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9f2a0e5f398ec75ac6a0d5d7f7e9083bd801f768;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git fixup: try_cast: v5 - Tweak docs to be explicit that only MSSQL is currently supported. - Update try_cast() docstring to better follow the conventions of cast() (and just be better in general) - export try_cast from sql/__init__.py --- diff --git a/doc/build/changelog/unreleased_20/9752.rst b/doc/build/changelog/unreleased_20/9752.rst index 0c095fcedc..6e9bb35123 100644 --- a/doc/build/changelog/unreleased_20/9752.rst +++ b/doc/build/changelog/unreleased_20/9752.rst @@ -3,11 +3,13 @@ :tickets: 9752 - Generalized the MSSQL :func:`.try_cast` function to any dialect. + Generalized the MSSQL :func:`.try_cast` function so that other + extension dialects can use it (MSSQL is the only builtin dialect + that currently supports it). + This implements a cast where un-castable values are returned as NULL, instead of raising an error. - Now this function can be taken advantage of by third party dialects - that also support this function, such as + These are a few third party dialects that could implement this: * ``SAFE_CAST`` in Google BigQuery * ``TRY_CAST`` in DuckDB diff --git a/lib/sqlalchemy/sql/__init__.py b/lib/sqlalchemy/sql/__init__.py index 96cffed7d0..c4c8c7d27a 100644 --- a/lib/sqlalchemy/sql/__init__.py +++ b/lib/sqlalchemy/sql/__init__.py @@ -93,6 +93,7 @@ from .expression import tablesample as tablesample from .expression import text as text from .expression import true as true from .expression import True_ as True_ +from .expression import try_cast as try_cast from .expression import tuple_ as tuple_ from .expression import type_coerce as type_coerce from .expression import union as union diff --git a/lib/sqlalchemy/sql/_elements_constructors.py b/lib/sqlalchemy/sql/_elements_constructors.py index 9a52e59e4e..e85d46818f 100644 --- a/lib/sqlalchemy/sql/_elements_constructors.py +++ b/lib/sqlalchemy/sql/_elements_constructors.py @@ -896,6 +896,7 @@ def cast( :func:`.try_cast` - an alternative to CAST that results in NULLs when the cast fails, instead of raising an error. + Only supported by some dialects. :func:`.type_coerce` - an alternative to CAST that coerces the type on the Python side only, which is often sufficient to generate the @@ -907,11 +908,21 @@ def cast( def try_cast(*arg, **kw): - """Create a TRY_CAST expression. + """Produce a ``TRY_CAST`` expression. + + :func:`.try_cast` returns an instance of :class:`.TryCast`. + + The only builtin dialect that supports :class:`.TryCast` is + Microsoft SQL (other third party dialects may support it as well). :class:`.TryCast` is a subclass of SQLAlchemy's :class:`.Cast` - construct, and works in the same way, except that the SQL expression - rendered is "TRY_CAST" rather than "CAST":: + construct, and works in the same way, except in regards to error + handling. If the function encounters an un-castable value + (for instance when trying to convert the string "hi" to an INT) + then normal :class:`.Cast` raises an error. :class:`.TryCast` + instead returns a NULL value. + + E.g.:: from sqlalchemy import select, try_cast, Numeric @@ -919,12 +930,12 @@ def try_cast(*arg, **kw): try_cast(product_table.c.unit_price, Numeric(10, 4)) ) - The above would render with mssql as:: + The above would render with Microsoft SQL as:: SELECT TRY_CAST (product_table.unit_price AS NUMERIC(10, 4)) FROM product_table - .. versionadded:: 2.1.0 + .. versionadded:: 2.0.14 """ return TryCast(*arg, **kw)